diff options
Diffstat (limited to 'thirdparty')
96 files changed, 18245 insertions, 1713 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md index ea2a996812..9da3d857a6 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -40,6 +40,17 @@ File extracted from a recent Fedora install: as it's generated on the user's system.) +## cvtt + +- Upstream: https://github.com/elasota/cvtt +- Version: 1.0.0-beta4 +- License: MIT + +Files extracted from upstream source: + +- all .cpp, .h, and .txt files in ConvectionKernels/ + + ## enet - Upstream: http://enet.bespin.org @@ -117,7 +128,7 @@ Files extracted from upstream source: ## glad - Upstream: https://github.com/Dav1dde/glad -- Version: 0.1.20a0 +- Version: 0.1.25 - License: MIT The files we package are automatically generated. @@ -152,7 +163,7 @@ Files extracted from upstream source: ## libpng - Upstream: http://libpng.org/pub/png/libpng.html -- Version: 1.6.34 +- Version: 1.6.35 - License: libpng/zlib Files extracted from upstream source: @@ -161,6 +172,7 @@ Files extracted from upstream source: `example.c` and `pngtest.c` - the arm/ folder - `scripts/pnglibconf.h.prebuilt` as `pnglibconf.h` +- `LICENSE` ## libsimplewebm @@ -262,14 +274,12 @@ Godot build configurations, check them out when updating. ## mbedtls - Upstream: https://tls.mbed.org/ -- Version: 2.8.0 +- Version: 2.12.0 - License: Apache 2.0 -File extracted from upstream release tarball `mbedtls-2.8.0-apache.tgz`: +File extracted from upstream release tarball `mbedtls-2.12.0-apache.tgz`: - All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/` - All `*.c` from `library/` to `thirdparty/mbedtls/library/` -- In file `thirdparty/mbedtls/library/net_sockets.c` mbedTLS overrides the `_WIN32_WINNT` define. - Be sure to check the Godot addition to only redfine it when undefined or `< 0x0501` (PRed upstream). - Applied the patch in `thirdparty/mbedtls/1453.diff` (PR 1453). Soon to be merged upstream. Check it out at next update. diff --git a/thirdparty/b2d_convexdecomp/b2Glue.h b/thirdparty/b2d_convexdecomp/b2Glue.h index 425486356e..10c2f62361 100644 --- a/thirdparty/b2d_convexdecomp/b2Glue.h +++ b/thirdparty/b2d_convexdecomp/b2Glue.h @@ -19,7 +19,7 @@ #ifndef B2GLUE_H #define B2GLUE_H -#include "math_2d.h" +#include "vector2.h" #include <limits.h> namespace b2ConvexDecomp { diff --git a/thirdparty/cvtt/ConvectionKernels.cpp b/thirdparty/cvtt/ConvectionKernels.cpp new file mode 100644 index 0000000000..6661d8120d --- /dev/null +++ b/thirdparty/cvtt/ConvectionKernels.cpp @@ -0,0 +1,7576 @@ +/* +Convection Texture Tools +Copyright (c) 2018 Eric Lasota + +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. + +------------------------------------------------------------------------------------- + +Portions based on DirectX Texture Library (DirectXTex) + +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the MIT License. + +http://go.microsoft.com/fwlink/?LinkId=248926 +*/ +#include "ConvectionKernels.h" +#include "ConvectionKernels_BC7_SingleColor.h" + +#if (defined(_M_IX86_FP) && _M_IX86_FP >= 2) || defined(_M_X64) || defined(__SSE2__) +#define CVTT_USE_SSE2 +#endif + +#ifdef CVTT_USE_SSE2 +#include <emmintrin.h> +#endif + +#include <float.h> +#include <assert.h> +#include <string.h> +#include <algorithm> +#include <math.h> + +#define UNREFERENCED_PARAMETER(n) ((void)n) + +namespace cvtt +{ +#ifdef CVTT_USE_SSE2 + // SSE2 version + struct ParallelMath + { + typedef uint16_t ScalarUInt16; + typedef int16_t ScalarSInt16; + + template<unsigned int TRoundingMode> + struct RoundForScope + { + unsigned int m_oldCSR; + + RoundForScope() + { + m_oldCSR = _mm_getcsr(); + _mm_setcsr((m_oldCSR & ~_MM_ROUND_MASK) | (TRoundingMode)); + } + + ~RoundForScope() + { + _mm_setcsr(m_oldCSR); + } + }; + + struct RoundTowardZeroForScope : RoundForScope<_MM_ROUND_TOWARD_ZERO> + { + }; + + struct RoundTowardNearestForScope : RoundForScope<_MM_ROUND_NEAREST> + { + }; + + struct RoundUpForScope : RoundForScope<_MM_ROUND_UP> + { + }; + + struct RoundDownForScope : RoundForScope<_MM_ROUND_DOWN> + { + }; + + static const int ParallelSize = 8; + + enum Int16Subtype + { + IntSubtype_Signed, + IntSubtype_UnsignedFull, + IntSubtype_UnsignedTruncated, + IntSubtype_Abstract, + }; + + template<int TSubtype> + struct VInt16 + { + __m128i m_value; + + inline VInt16 operator+(int16_t other) const + { + VInt16 result; + result.m_value = _mm_add_epi16(m_value, _mm_set1_epi16(static_cast<int16_t>(other))); + return result; + } + + inline VInt16 operator+(const VInt16 &other) const + { + VInt16 result; + result.m_value = _mm_add_epi16(m_value, other.m_value); + return result; + } + + inline VInt16 operator|(const VInt16 &other) const + { + VInt16 result; + result.m_value = _mm_or_si128(m_value, other.m_value); + return result; + } + + inline VInt16 operator&(const VInt16 &other) const + { + VInt16 result; + result.m_value = _mm_and_si128(m_value, other.m_value); + return result; + } + + inline VInt16 operator-(const VInt16 &other) const + { + VInt16 result; + result.m_value = _mm_sub_epi16(m_value, other.m_value); + return result; + } + + inline VInt16 operator<<(int bits) const + { + VInt16 result; + result.m_value = _mm_slli_epi16(m_value, bits); + return result; + } + }; + + typedef VInt16<IntSubtype_Signed> SInt16; + typedef VInt16<IntSubtype_UnsignedFull> UInt16; + typedef VInt16<IntSubtype_UnsignedTruncated> UInt15; + typedef VInt16<IntSubtype_Abstract> AInt16; + + template<int TSubtype> + struct VInt32 + { + __m128i m_values[2]; + + inline VInt32 operator+(const VInt32& other) const + { + VInt32 result; + result.m_values[0] = _mm_add_epi32(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_add_epi32(m_values[1], other.m_values[1]); + return result; + } + + inline VInt32 operator-(const VInt32& other) const + { + VInt32 result; + result.m_values[0] = _mm_sub_epi32(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_sub_epi32(m_values[1], other.m_values[1]); + return result; + } + + inline VInt32 operator<<(const int other) const + { + VInt32 result; + result.m_values[0] = _mm_slli_epi32(m_values[0], other); + result.m_values[1] = _mm_slli_epi32(m_values[1], other); + return result; + } + }; + + typedef VInt32<IntSubtype_Signed> SInt32; + typedef VInt32<IntSubtype_UnsignedTruncated> UInt31; + typedef VInt32<IntSubtype_UnsignedFull> UInt32; + typedef VInt32<IntSubtype_Abstract> AInt32; + + template<class TTargetType> + struct LosslessCast + { +#ifdef CVTT_PERMIT_ALIASING + template<int TSrcSubtype> + static const TTargetType& Cast(const VInt32<TSrcSubtype> &src) + { + return reinterpret_cast<VInt32<TSubtype>&>(src); + } + + template<int TSrcSubtype> + static const TTargetType& Cast(const VInt16<TSrcSubtype> &src) + { + return reinterpret_cast<VInt16<TSubtype>&>(src); + } +#else + template<int TSrcSubtype> + static TTargetType Cast(const VInt32<TSrcSubtype> &src) + { + TTargetType result; + result.m_values[0] = src.m_values[0]; + result.m_values[1] = src.m_values[1]; + return result; + } + + template<int TSrcSubtype> + static TTargetType Cast(const VInt16<TSrcSubtype> &src) + { + TTargetType result; + result.m_value = src.m_value; + return result; + } +#endif + }; + + struct Int64 + { + __m128i m_values[4]; + }; + + struct Float + { + __m128 m_values[2]; + + inline Float operator+(const Float& other) const + { + Float result; + result.m_values[0] = _mm_add_ps(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_add_ps(m_values[1], other.m_values[1]); + return result; + } + + inline Float operator+(float other) const + { + Float result; + result.m_values[0] = _mm_add_ps(m_values[0], _mm_set1_ps(other)); + result.m_values[1] = _mm_add_ps(m_values[1], _mm_set1_ps(other)); + return result; + } + + inline Float operator-(const Float& other) const + { + Float result; + result.m_values[0] = _mm_sub_ps(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_sub_ps(m_values[1], other.m_values[1]); + return result; + } + + inline Float operator-() const + { + Float result; + result.m_values[0] = _mm_sub_ps(_mm_setzero_ps(), m_values[0]); + result.m_values[1] = _mm_sub_ps(_mm_setzero_ps(), m_values[1]); + return result; + } + + inline Float operator*(const Float& other) const + { + Float result; + result.m_values[0] = _mm_mul_ps(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_mul_ps(m_values[1], other.m_values[1]); + return result; + } + + inline Float operator*(float other) const + { + Float result; + result.m_values[0] = _mm_mul_ps(m_values[0], _mm_set1_ps(other)); + result.m_values[1] = _mm_mul_ps(m_values[1], _mm_set1_ps(other)); + return result; + } + + inline Float operator/(const Float& other) const + { + Float result; + result.m_values[0] = _mm_div_ps(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_div_ps(m_values[1], other.m_values[1]); + return result; + } + + inline Float operator/(float other) const + { + Float result; + result.m_values[0] = _mm_div_ps(m_values[0], _mm_set1_ps(other)); + result.m_values[1] = _mm_div_ps(m_values[1], _mm_set1_ps(other)); + return result; + } + }; + + struct Int16CompFlag + { + __m128i m_value; + + inline Int16CompFlag operator&(const Int16CompFlag& other) const + { + Int16CompFlag result; + result.m_value = _mm_and_si128(m_value, other.m_value); + return result; + } + + inline Int16CompFlag operator|(const Int16CompFlag& other) const + { + Int16CompFlag result; + result.m_value = _mm_or_si128(m_value, other.m_value); + return result; + } + }; + + struct FloatCompFlag + { + __m128 m_values[2]; + }; + + template<int TSubtype> + static VInt16<TSubtype> AbstractAdd(const VInt16<TSubtype> &a, const VInt16<TSubtype> &b) + { + VInt16<TSubtype> result; + result.m_value = _mm_add_epi16(a.m_value, b.m_value); + return result; + } + + template<int TSubtype> + static VInt16<TSubtype> AbstractSubtract(const VInt16<TSubtype> &a, const VInt16<TSubtype> &b) + { + VInt16<TSubtype> result; + result.m_value = _mm_sub_epi16(a.m_value, b.m_value); + return result; + } + + static Float Select(FloatCompFlag flag, Float a, Float b) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_or_ps(_mm_and_ps(flag.m_values[i], a.m_values[i]), _mm_andnot_ps(flag.m_values[i], b.m_values[i])); + return result; + } + + template<int TSubtype> + static VInt16<TSubtype> Select(Int16CompFlag flag, const VInt16<TSubtype> &a, const VInt16<TSubtype> &b) + { + VInt16<TSubtype> result; + result.m_value = _mm_or_si128(_mm_and_si128(flag.m_value, a.m_value), _mm_andnot_si128(flag.m_value, b.m_value)); + return result; + } + + template<int TSubtype> + static VInt16<TSubtype> SelectOrZero(Int16CompFlag flag, const VInt16<TSubtype> &a) + { + VInt16<TSubtype> result; + result.m_value = _mm_and_si128(flag.m_value, a.m_value); + return result; + } + + template<int TSubtype> + static void ConditionalSet(VInt16<TSubtype>& dest, Int16CompFlag flag, const VInt16<TSubtype> src) + { + dest.m_value = _mm_or_si128(_mm_andnot_si128(flag.m_value, dest.m_value), _mm_and_si128(flag.m_value, src.m_value)); + } + + static SInt16 ConditionalNegate(const Int16CompFlag &flag, const SInt16& v) + { + SInt16 result; + result.m_value = _mm_add_epi16(_mm_xor_si128(flag.m_value, v.m_value), _mm_srli_epi16(flag.m_value, 15)); + return result; + } + + template<int TSubtype> + static void NotConditionalSet(VInt16<TSubtype>& dest, Int16CompFlag flag, const VInt16<TSubtype> src) + { + dest.m_value = _mm_or_si128(_mm_and_si128(flag.m_value, dest.m_value), _mm_andnot_si128(flag.m_value, src.m_value)); + } + + static void ConditionalSet(Float& dest, FloatCompFlag flag, const Float src) + { + for (int i = 0; i < 2; i++) + dest.m_values[i] = _mm_or_ps(_mm_andnot_ps(flag.m_values[i], dest.m_values[i]), _mm_and_ps(flag.m_values[i], src.m_values[i])); + } + + static void NotConditionalSet(Float& dest, FloatCompFlag flag, const Float src) + { + for (int i = 0; i < 2; i++) + dest.m_values[i] = _mm_or_ps(_mm_and_ps(flag.m_values[i], dest.m_values[i]), _mm_andnot_ps(flag.m_values[i], src.m_values[i])); + } + + static void MakeSafeDenominator(Float& v) + { + ConditionalSet(v, Equal(v, MakeFloatZero()), MakeFloat(1.0f)); + } + + static SInt16 TruncateToPrecisionSigned(const SInt16 &v, int precision) + { + int lostBits = 16 - precision; + if (lostBits == 0) + return v; + + SInt16 result; + result.m_value = _mm_srai_epi16(_mm_slli_epi16(v.m_value, lostBits), lostBits); + return result; + } + + static UInt16 TruncateToPrecisionUnsigned(const UInt16 &v, int precision) + { + int lostBits = 16 - precision; + if (lostBits == 0) + return v; + + UInt16 result; + result.m_value = _mm_srli_epi16(_mm_slli_epi16(v.m_value, lostBits), lostBits); + return result; + } + + static UInt16 Min(const UInt16 &a, const UInt16 &b) + { + __m128i bitFlip = _mm_set1_epi16(-32768); + + UInt16 result; + result.m_value = _mm_xor_si128(_mm_min_epi16(_mm_xor_si128(a.m_value, bitFlip), _mm_xor_si128(b.m_value, bitFlip)), bitFlip); + return result; + } + + static SInt16 Min(const SInt16 &a, const SInt16 &b) + { + SInt16 result; + result.m_value = _mm_min_epi16(a.m_value, b.m_value); + return result; + } + + static UInt15 Min(const UInt15 &a, const UInt15 &b) + { + UInt15 result; + result.m_value = _mm_min_epi16(a.m_value, b.m_value); + return result; + } + + static Float Min(Float a, Float b) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_min_ps(a.m_values[i], b.m_values[i]); + return result; + } + + static UInt16 Max(const UInt16 &a, const UInt16 &b) + { + __m128i bitFlip = _mm_set1_epi16(-32768); + + UInt16 result; + result.m_value = _mm_xor_si128(_mm_max_epi16(_mm_xor_si128(a.m_value, bitFlip), _mm_xor_si128(b.m_value, bitFlip)), bitFlip); + return result; + } + + static SInt16 Max(const SInt16 &a, const SInt16 &b) + { + SInt16 result; + result.m_value = _mm_max_epi16(a.m_value, b.m_value); + return result; + } + + static UInt15 Max(const UInt15 &a, const UInt15 &b) + { + UInt15 result; + result.m_value = _mm_max_epi16(a.m_value, b.m_value); + return result; + } + + static Float Max(Float a, Float b) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_max_ps(a.m_values[i], b.m_values[i]); + return result; + } + + static Float Clamp(Float v, float min, float max) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_max_ps(_mm_min_ps(v.m_values[i], _mm_set1_ps(max)), _mm_set1_ps(min)); + return result; + } + + static Float Reciprocal(Float v) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_rcp_ps(v.m_values[i]); + return result; + } + + static void ConvertLDRInputs(const PixelBlockU8* inputBlocks, int pxOffset, int channel, UInt15& chOut) + { + int16_t values[8]; + for (int i = 0; i < 8; i++) + values[i] = inputBlocks[i].m_pixels[pxOffset][channel]; + + chOut.m_value = _mm_set_epi16(values[7], values[6], values[5], values[4], values[3], values[2], values[1], values[0]); + } + + static void ConvertHDRInputs(const PixelBlockF16* inputBlocks, int pxOffset, int channel, SInt16& chOut) + { + int16_t values[8]; + for (int i = 0; i < 8; i++) + values[i] = inputBlocks[i].m_pixels[pxOffset][channel]; + + chOut.m_value = _mm_set_epi16(values[7], values[6], values[5], values[4], values[3], values[2], values[1], values[0]); + } + + static Float MakeFloat(float v) + { + Float f; + f.m_values[0] = f.m_values[1] = _mm_set1_ps(v); + return f; + } + + static Float MakeFloatZero() + { + Float f; + f.m_values[0] = f.m_values[1] = _mm_setzero_ps(); + return f; + } + + static UInt16 MakeUInt16(uint16_t v) + { + UInt16 result; + result.m_value = _mm_set1_epi16(static_cast<short>(v)); + return result; + } + + static SInt16 MakeSInt16(int16_t v) + { + SInt16 result; + result.m_value = _mm_set1_epi16(static_cast<short>(v)); + return result; + } + + static AInt16 MakeAInt16(int16_t v) + { + AInt16 result; + result.m_value = _mm_set1_epi16(static_cast<short>(v)); + return result; + } + + static UInt15 MakeUInt15(uint16_t v) + { + UInt15 result; + result.m_value = _mm_set1_epi16(static_cast<short>(v)); + return result; + } + + static SInt32 MakeSInt32(int32_t v) + { + SInt32 result; + result.m_values[0] = _mm_set1_epi32(v); + result.m_values[1] = _mm_set1_epi32(v); + return result; + } + + static UInt31 MakeUInt31(uint32_t v) + { + UInt31 result; + result.m_values[0] = _mm_set1_epi32(v); + result.m_values[1] = _mm_set1_epi32(v); + return result; + } + + static uint16_t Extract(const UInt16 &v, int offset) + { + return reinterpret_cast<const uint16_t*>(&v.m_value)[offset]; + } + + static int16_t Extract(const SInt16 &v, int offset) + { + return reinterpret_cast<const int16_t*>(&v.m_value)[offset]; + } + + static uint16_t Extract(const UInt15 &v, int offset) + { + return reinterpret_cast<const uint16_t*>(&v.m_value)[offset]; + } + + static int16_t Extract(const AInt16 &v, int offset) + { + return reinterpret_cast<const int16_t*>(&v.m_value)[offset]; + } + + static void PutUInt16(UInt16 &dest, int offset, uint16_t v) + { + reinterpret_cast<uint16_t*>(&dest)[offset] = v; + } + + static void PutUInt15(UInt15 &dest, int offset, uint16_t v) + { + reinterpret_cast<uint16_t*>(&dest)[offset] = v; + } + + static void PutSInt16(SInt16 &dest, int offset, int16_t v) + { + reinterpret_cast<int16_t*>(&dest)[offset] = v; + } + + static float ExtractFloat(const Float& v, int offset) + { + return reinterpret_cast<const float*>(&v)[offset]; + } + + static void PutFloat(Float &dest, int offset, float v) + { + reinterpret_cast<float*>(&dest)[offset] = v; + } + + static Int16CompFlag Less(const SInt16 &a, const SInt16 &b) + { + Int16CompFlag result; + result.m_value = _mm_cmplt_epi16(a.m_value, b.m_value); + return result; + } + + static Int16CompFlag Less(const UInt15 &a, const UInt15 &b) + { + Int16CompFlag result; + result.m_value = _mm_cmplt_epi16(a.m_value, b.m_value); + return result; + } + + static Int16CompFlag LessOrEqual(const UInt15 &a, const UInt15 &b) + { + Int16CompFlag result; + result.m_value = _mm_cmplt_epi16(a.m_value, b.m_value); + return result; + } + + static FloatCompFlag Less(const Float &a, const Float &b) + { + FloatCompFlag result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_cmplt_ps(a.m_values[i], b.m_values[i]); + return result; + } + + static FloatCompFlag LessOrEqual(Float a, Float b) + { + FloatCompFlag result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_cmple_ps(a.m_values[i], b.m_values[i]); + return result; + } + + template<int TSubtype> + static Int16CompFlag Equal(const VInt16<TSubtype> &a, const VInt16<TSubtype> &b) + { + Int16CompFlag result; + result.m_value = _mm_cmpeq_epi16(a.m_value, b.m_value); + return result; + } + + static FloatCompFlag Equal(Float a, Float b) + { + FloatCompFlag result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_cmpeq_ps(a.m_values[i], b.m_values[i]); + return result; + } + + static Float ToFloat(const UInt16 &v) + { + Float result; + result.m_values[0] = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v.m_value, _mm_setzero_si128())); + result.m_values[1] = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v.m_value, _mm_setzero_si128())); + return result; + } + + static UInt31 ToUInt31(const UInt16 &v) + { + UInt31 result; + result.m_values[0] = _mm_unpacklo_epi16(v.m_value, _mm_setzero_si128()); + result.m_values[1] = _mm_unpackhi_epi16(v.m_value, _mm_setzero_si128()); + return result; + } + + static SInt32 ToInt32(const UInt16 &v) + { + SInt32 result; + result.m_values[0] = _mm_unpacklo_epi16(v.m_value, _mm_setzero_si128()); + result.m_values[1] = _mm_unpackhi_epi16(v.m_value, _mm_setzero_si128()); + return result; + } + + static SInt32 ToInt32(const SInt16 &v) + { + SInt32 result; + result.m_values[0] = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), v.m_value), 16); + result.m_values[1] = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), v.m_value), 16); + return result; + } + + static Float ToFloat(const SInt16 &v) + { + Float result; + result.m_values[0] = _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), v.m_value), 16)); + result.m_values[1] = _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), v.m_value), 16)); + return result; + } + + static Float ToFloat(const UInt15 &v) + { + Float result; + result.m_values[0] = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v.m_value, _mm_setzero_si128())); + result.m_values[1] = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v.m_value, _mm_setzero_si128())); + return result; + } + + static Float ToFloat(const UInt31 &v) + { + Float result; + result.m_values[0] = _mm_cvtepi32_ps(v.m_values[0]); + result.m_values[1] = _mm_cvtepi32_ps(v.m_values[1]); + return result; + } + + static Int16CompFlag FloatFlagToInt16(const FloatCompFlag &v) + { + __m128i lo = _mm_castps_si128(v.m_values[0]); + __m128i hi = _mm_castps_si128(v.m_values[1]); + + Int16CompFlag result; + result.m_value = _mm_packs_epi32(lo, hi); + return result; + } + + static FloatCompFlag Int16FlagToFloat(const Int16CompFlag &v) + { + __m128i lo = _mm_unpacklo_epi16(v.m_value, v.m_value); + __m128i hi = _mm_unpackhi_epi16(v.m_value, v.m_value); + + FloatCompFlag result; + result.m_values[0] = _mm_castsi128_ps(lo); + result.m_values[1] = _mm_castsi128_ps(hi); + return result; + } + + static Int16CompFlag MakeBoolInt16(bool b) + { + Int16CompFlag result; + if (b) + result.m_value = _mm_set1_epi16(-1); + else + result.m_value = _mm_setzero_si128(); + return result; + } + + static FloatCompFlag MakeBoolFloat(bool b) + { + FloatCompFlag result; + if (b) + result.m_values[0] = result.m_values[1] = _mm_castsi128_ps(_mm_set1_epi32(-1)); + else + result.m_values[0] = result.m_values[1] = _mm_setzero_ps(); + return result; + } + + static Int16CompFlag AndNot(const Int16CompFlag &a, const Int16CompFlag &b) + { + Int16CompFlag result; + result.m_value = _mm_andnot_si128(b.m_value, a.m_value); + return result; + } + + static UInt16 RoundAndConvertToU16(Float v, const void* /*roundingMode*/) + { + __m128i lo = _mm_cvtps_epi32(_mm_add_ps(v.m_values[0], _mm_set1_ps(-32768))); + __m128i hi = _mm_cvtps_epi32(_mm_add_ps(v.m_values[1], _mm_set1_ps(-32768))); + + __m128i packed = _mm_packs_epi32(lo, hi); + + UInt16 result; + result.m_value = _mm_xor_si128(packed, _mm_set1_epi16(-32768)); + return result; + } + + static UInt15 RoundAndConvertToU15(Float v, const void* /*roundingMode*/) + { + __m128i lo = _mm_cvtps_epi32(v.m_values[0]); + __m128i hi = _mm_cvtps_epi32(v.m_values[1]); + + __m128i packed = _mm_packs_epi32(lo, hi); + + UInt15 result; + result.m_value = _mm_packs_epi32(lo, hi); + return result; + } + + static SInt16 RoundAndConvertToS16(Float v, const void* /*roundingMode*/) + { + __m128i lo = _mm_cvtps_epi32(v.m_values[0]); + __m128i hi = _mm_cvtps_epi32(v.m_values[1]); + + __m128i packed = _mm_packs_epi32(lo, hi); + + SInt16 result; + result.m_value = _mm_packs_epi32(lo, hi); + return result; + } + + static Float Sqrt(Float f) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_sqrt_ps(f.m_values[i]); + return result; + } + + static UInt16 Abs(const SInt16 &a) + { + __m128i signBitsXor = _mm_srai_epi16(a.m_value, 15); + __m128i signBitsAdd = _mm_srli_epi16(a.m_value, 15); + + UInt16 result; + result.m_value = _mm_add_epi16(_mm_xor_si128(a.m_value, signBitsXor), signBitsAdd); + return result; + } + + static Float Abs(const Float& a) + { + __m128 invMask = _mm_set1_ps(-0.0f); + + Float result; + result.m_values[0] = _mm_andnot_ps(invMask, a.m_values[0]); + result.m_values[1] = _mm_andnot_ps(invMask, a.m_values[1]); + return result; + } + + static UInt16 SqDiffUInt8(const UInt15 &a, const UInt15 &b) + { + __m128i diff = _mm_sub_epi16(a.m_value, b.m_value); + + UInt16 result; + result.m_value = _mm_mullo_epi16(diff, diff); + return result; + } + + static Float SqDiffSInt16(const SInt16 &a, const SInt16 &b) + { + __m128i diffU = _mm_sub_epi16(_mm_max_epi16(a.m_value, b.m_value), _mm_min_epi16(a.m_value, b.m_value)); + + __m128i mulHi = _mm_mulhi_epu16(diffU, diffU); + __m128i mulLo = _mm_mullo_epi16(diffU, diffU); + __m128i sqDiffHi = _mm_unpackhi_epi16(mulLo, mulHi); + __m128i sqDiffLo = _mm_unpacklo_epi16(mulLo, mulHi); + + Float result; + result.m_values[0] = _mm_cvtepi32_ps(sqDiffLo); + result.m_values[1] = _mm_cvtepi32_ps(sqDiffHi); + + return result; + } + + static Float TwosCLHalfToFloat(const SInt16 &v) + { + __m128i absV = _mm_add_epi16(_mm_xor_si128(v.m_value, _mm_srai_epi16(v.m_value, 15)), _mm_srli_epi16(v.m_value, 15)); + + __m128i signBits = _mm_and_si128(v.m_value, _mm_set1_epi16(-32768)); + __m128i mantissa = _mm_and_si128(v.m_value, _mm_set1_epi16(0x03ff)); + __m128i exponent = _mm_and_si128(v.m_value, _mm_set1_epi16(0x7c00)); + + __m128i isDenormal = _mm_cmpeq_epi16(exponent, _mm_setzero_si128()); + + // Convert exponent to high-bits + exponent = _mm_add_epi16(_mm_srli_epi16(exponent, 3), _mm_set1_epi16(14336)); + + __m128i denormalCorrectionHigh = _mm_and_si128(isDenormal, _mm_or_si128(signBits, _mm_set1_epi16(14336))); + + __m128i highBits = _mm_or_si128(signBits, _mm_or_si128(exponent, _mm_srli_epi16(mantissa, 3))); + __m128i lowBits = _mm_slli_epi16(mantissa, 13); + + __m128i flow = _mm_unpacklo_epi16(lowBits, highBits); + __m128i fhigh = _mm_unpackhi_epi16(lowBits, highBits); + + __m128i correctionLow = _mm_unpacklo_epi16(_mm_setzero_si128(), denormalCorrectionHigh); + __m128i correctionHigh = _mm_unpackhi_epi16(_mm_setzero_si128(), denormalCorrectionHigh); + + Float result; + result.m_values[0] = _mm_sub_ps(_mm_castsi128_ps(flow), _mm_castsi128_ps(correctionLow)); + result.m_values[1] = _mm_sub_ps(_mm_castsi128_ps(fhigh), _mm_castsi128_ps(correctionHigh)); + + return result; + } + + static Float SqDiff2CLFloat(const SInt16 &a, const Float &b) + { + Float fa = TwosCLHalfToFloat(a); + + Float diff = fa - b; + return diff * diff; + } + + static Float SqDiff2CL(const SInt16 &a, const SInt16 &b) + { + Float fa = TwosCLHalfToFloat(a); + Float fb = TwosCLHalfToFloat(b); + + Float diff = fa - fb; + return diff * diff; + } + + static Float SqDiff2CLFloat(const SInt16 &a, float aWeight, const Float &b) + { + Float fa = TwosCLHalfToFloat(a) * aWeight; + + Float diff = fa - b; + return diff * diff; + } + + static UInt16 RightShift(const UInt16 &v, int bits) + { + UInt16 result; + result.m_value = _mm_srli_epi16(v.m_value, bits); + return result; + } + + static UInt31 RightShift(const UInt31 &v, int bits) + { + UInt31 result; + result.m_values[0] = _mm_srli_epi32(v.m_values[0], bits); + result.m_values[1] = _mm_srli_epi32(v.m_values[1], bits); + return result; + } + + static SInt16 RightShift(const SInt16 &v, int bits) + { + SInt16 result; + result.m_value = _mm_srai_epi16(v.m_value, bits); + return result; + } + + static UInt15 RightShift(const UInt15 &v, int bits) + { + UInt15 result; + result.m_value = _mm_srli_epi16(v.m_value, bits); + return result; + } + + static SInt32 RightShift(const SInt32 &v, int bits) + { + SInt32 result; + result.m_values[0] = _mm_srai_epi32(v.m_values[0], bits); + result.m_values[1] = _mm_srai_epi32(v.m_values[1], bits); + return result; + } + + static SInt16 ToSInt16(const SInt32 &v) + { + SInt16 result; + result.m_value = _mm_packs_epi32(v.m_values[0], v.m_values[1]); + return result; + } + + static UInt16 ToUInt16(const UInt32 &v) + { + __m128i low = _mm_srai_epi32(_mm_slli_epi32(v.m_values[0], 16), 16); + __m128i high = _mm_srai_epi32(_mm_slli_epi32(v.m_values[1], 16), 16); + + UInt16 result; + result.m_value = _mm_packs_epi32(low, high); + return result; + } + + static UInt16 ToUInt16(const UInt31 &v) + { + __m128i low = _mm_srai_epi32(_mm_slli_epi32(v.m_values[0], 16), 16); + __m128i high = _mm_srai_epi32(_mm_slli_epi32(v.m_values[1], 16), 16); + + UInt16 result; + result.m_value = _mm_packs_epi32(low, high); + return result; + } + + static UInt15 ToUInt15(const UInt31 &v) + { + UInt15 result; + result.m_value = _mm_packs_epi32(v.m_values[0], v.m_values[1]); + return result; + } + + static SInt32 XMultiply(const SInt16 &a, const SInt16 &b) + { + __m128i high = _mm_mulhi_epi16(a.m_value, b.m_value); + __m128i low = _mm_mullo_epi16(a.m_value, b.m_value); + + SInt32 result; + result.m_values[0] = _mm_unpacklo_epi16(low, high); + result.m_values[1] = _mm_unpackhi_epi16(low, high); + return result; + } + + static SInt32 XMultiply(const SInt16 &a, const UInt15 &b) + { + __m128i high = _mm_mulhi_epi16(a.m_value, b.m_value); + __m128i low = _mm_mullo_epi16(a.m_value, b.m_value); + + SInt32 result; + result.m_values[0] = _mm_unpacklo_epi16(low, high); + result.m_values[1] = _mm_unpackhi_epi16(low, high); + return result; + } + + static SInt32 XMultiply(const UInt15 &a, const SInt16 &b) + { + return XMultiply(b, a); + } + + static UInt32 XMultiply(const UInt16 &a, const UInt16 &b) + { + __m128i high = _mm_mulhi_epu16(a.m_value, b.m_value); + __m128i low = _mm_mullo_epi16(a.m_value, b.m_value); + + UInt32 result; + result.m_values[0] = _mm_unpacklo_epi16(low, high); + result.m_values[1] = _mm_unpackhi_epi16(low, high); + return result; + } + + static UInt16 CompactMultiply(const UInt16 &a, const UInt15 &b) + { + UInt16 result; + result.m_value = _mm_mullo_epi16(a.m_value, b.m_value); + return result; + } + + static UInt16 CompactMultiply(const UInt15 &a, const UInt15 &b) + { + UInt16 result; + result.m_value = _mm_mullo_epi16(a.m_value, b.m_value); + return result; + } + + static UInt31 XMultiply(const UInt15 &a, const UInt15 &b) + { + __m128i high = _mm_mulhi_epu16(a.m_value, b.m_value); + __m128i low = _mm_mullo_epi16(a.m_value, b.m_value); + + UInt31 result; + result.m_values[0] = _mm_unpacklo_epi16(low, high); + result.m_values[1] = _mm_unpackhi_epi16(low, high); + return result; + } + + static UInt31 XMultiply(const UInt16 &a, const UInt15 &b) + { + __m128i high = _mm_mulhi_epu16(a.m_value, b.m_value); + __m128i low = _mm_mullo_epi16(a.m_value, b.m_value); + + UInt31 result; + result.m_values[0] = _mm_unpacklo_epi16(low, high); + result.m_values[1] = _mm_unpackhi_epi16(low, high); + return result; + } + + static UInt31 XMultiply(const UInt15 &a, const UInt16 &b) + { + return XMultiply(b, a); + } + + static bool AnySet(Int16CompFlag v) + { + return _mm_movemask_epi8(v.m_value) != 0; + } + + static bool AllSet(Int16CompFlag v) + { + return _mm_movemask_epi8(v.m_value) == 0xffff; + } + + static bool AnySet(FloatCompFlag v) + { + return _mm_movemask_ps(v.m_values[0]) != 0 || _mm_movemask_ps(v.m_values[1]) != 0; + } + + static bool AllSet(FloatCompFlag v) + { + return _mm_movemask_ps(v.m_values[0]) == 0xf && _mm_movemask_ps(v.m_values[1]) == 0xf; + } + }; + +#else + // Scalar version + struct ParallelMath + { + struct RoundTowardZeroForScope + { + }; + + struct RoundTowardNearestForScope + { + }; + + struct RoundUpForScope + { + }; + + struct RoundDownForScope + { + }; + + static const int ParallelSize = 1; + + enum Int16Subtype + { + IntSubtype_Signed, + IntSubtype_UnsignedFull, + IntSubtype_UnsignedTruncated, + IntSubtype_Abstract, + }; + + typedef int32_t SInt16; + typedef int32_t UInt15; + typedef int32_t UInt16; + typedef int32_t AInt16; + + typedef int32_t SInt32; + typedef int32_t UInt31; + typedef int32_t UInt32; + typedef int32_t AInt32; + + typedef int32_t ScalarUInt16; + typedef int32_t ScalarSInt16; + + typedef float Float; + + template<class TTargetType> + struct LosslessCast + { + static const int32_t& Cast(const int32_t &src) + { + return src; + } + }; + + typedef bool Int16CompFlag; + typedef bool FloatCompFlag; + + static int32_t AbstractAdd(const int32_t &a, const int32_t &b) + { + return a + b; + } + + static int32_t AbstractSubtract(const int32_t &a, const int32_t &b) + { + return a - b; + } + + static float Select(bool flag, float a, float b) + { + return flag ? a : b; + } + + static int32_t Select(bool flag, int32_t a, int32_t b) + { + return flag ? a : b; + } + + static int32_t SelectOrZero(bool flag, int32_t a) + { + return flag ? a : 0; + } + + static void ConditionalSet(int32_t& dest, bool flag, int32_t src) + { + if (flag) + dest = src; + } + + static int32_t ConditionalNegate(bool flag, int32_t v) + { + return (flag) ? -v : v; + } + + static void NotConditionalSet(int32_t& dest, bool flag, int32_t src) + { + if (!flag) + dest = src; + } + + static void ConditionalSet(float& dest, bool flag, float src) + { + if (flag) + dest = src; + } + + static void NotConditionalSet(float& dest, bool flag, float src) + { + if (!flag) + dest = src; + } + + static void MakeSafeDenominator(float& v) + { + if (v == 0.0f) + v = 1.0f; + } + + static int32_t SignedRightShift(int32_t v, int bits) + { + return v >> bits; + } + + static int32_t TruncateToPrecisionSigned(int32_t v, int precision) + { + v = (v << (32 - precision)) & 0xffffffff; + return SignedRightShift(v, 32 - precision); + } + + static int32_t TruncateToPrecisionUnsigned(int32_t v, int precision) + { + return v & ((1 << precision) - 1); + } + + static int32_t Min(int32_t a, int32_t b) + { + if (a < b) + return a; + return b; + } + + static float Min(float a, float b) + { + if (a < b) + return a; + return b; + } + + static int32_t Max(int32_t a, int32_t b) + { + if (a > b) + return a; + return b; + } + + static float Max(float a, float b) + { + if (a > b) + return a; + return b; + } + + static float Abs(float a) + { + return fabsf(a); + } + + static int32_t Abs(int32_t a) + { + if (a < 0) + return -a; + return a; + } + + static float Clamp(float v, float min, float max) + { + if (v < min) + return min; + if (v > max) + return max; + return v; + } + + static float Reciprocal(float v) + { + return 1.0f / v; + } + + static void ConvertLDRInputs(const PixelBlockU8* inputBlocks, int pxOffset, int channel, int32_t& chOut) + { + chOut = inputBlocks[0].m_pixels[pxOffset][channel]; + } + + static void ConvertHDRInputs(const PixelBlockF16* inputBlocks, int pxOffset, int channel, int32_t& chOut) + { + chOut = inputBlocks[0].m_pixels[pxOffset][channel]; + } + + static float MakeFloat(float v) + { + return v; + } + + static float MakeFloatZero() + { + return 0.0f; + } + + static int32_t MakeUInt16(uint16_t v) + { + return v; + } + + static int32_t MakeSInt16(int16_t v) + { + return v; + } + + static int32_t MakeAInt16(int16_t v) + { + return v; + } + + static int32_t MakeUInt15(uint16_t v) + { + return v; + } + + static int32_t MakeSInt32(int32_t v) + { + return v; + } + + static int32_t MakeUInt31(int32_t v) + { + return v; + } + + static int32_t Extract(int32_t v, int offset) + { + UNREFERENCED_PARAMETER(offset); + return v; + } + + static void PutUInt16(int32_t &dest, int offset, ParallelMath::ScalarUInt16 v) + { + UNREFERENCED_PARAMETER(offset); + dest = v; + } + + static void PutUInt15(int32_t &dest, int offset, ParallelMath::ScalarUInt16 v) + { + UNREFERENCED_PARAMETER(offset); + dest = v; + } + + static void PutSInt16(int32_t &dest, int offset, ParallelMath::ScalarSInt16 v) + { + UNREFERENCED_PARAMETER(offset); + dest = v; + } + + static float ExtractFloat(float v, int offset) + { + UNREFERENCED_PARAMETER(offset); + return v; + } + + static void PutFloat(float &dest, int offset, float v) + { + UNREFERENCED_PARAMETER(offset); + dest = v; + } + + static bool Less(int32_t a, int32_t b) + { + return a < b; + } + + static bool Less(float a, float b) + { + return a < b; + } + + static bool LessOrEqual(int32_t a, int32_t b) + { + return a < b; + } + + static bool LessOrEqual(float a, float b) + { + return a < b; + } + + static bool Equal(int32_t a, int32_t b) + { + return a == b; + } + + static bool Equal(float a, float b) + { + return a == b; + } + + static float ToFloat(int32_t v) + { + return static_cast<float>(v); + } + + static int32_t ToUInt31(int32_t v) + { + return v; + } + + static int32_t ToInt32(int32_t v) + { + return v; + } + + static bool FloatFlagToInt16(bool v) + { + return v; + } + + static bool Int16FlagToFloat(bool v) + { + return v; + } + + static bool AndNot(bool a, bool b) + { + return a && !b; + } + + static int32_t RoundAndConvertToInt(float v, const ParallelMath::RoundTowardZeroForScope *rtz) + { + UNREFERENCED_PARAMETER(rtz); + return static_cast<int>(v); + } + + static int32_t RoundAndConvertToInt(float v, const ParallelMath::RoundUpForScope *ru) + { + UNREFERENCED_PARAMETER(ru); + return static_cast<int>(ceilf(v)); + } + + static int32_t RoundAndConvertToInt(float v, const ParallelMath::RoundDownForScope *rd) + { + UNREFERENCED_PARAMETER(rd); + return static_cast<int>(floorf(v)); + } + + static int32_t RoundAndConvertToInt(float v, const ParallelMath::RoundTowardNearestForScope *rtn) + { + UNREFERENCED_PARAMETER(rtn); + return static_cast<int>(floorf(v + 0.5f)); + } + + template<class TRoundMode> + static int32_t RoundAndConvertToU16(float v, const TRoundMode *roundingMode) + { + return RoundAndConvertToInt(v, roundingMode); + } + + template<class TRoundMode> + static int32_t RoundAndConvertToU15(float v, const TRoundMode *roundingMode) + { + return RoundAndConvertToInt(v, roundingMode); + } + + template<class TRoundMode> + static int32_t RoundAndConvertToS16(float v, const TRoundMode *roundingMode) + { + return RoundAndConvertToInt(v, roundingMode); + } + + static float Sqrt(float f) + { + return sqrtf(f); + } + + static int32_t SqDiffUInt8(int32_t a, int32_t b) + { + int32_t delta = a - b; + return delta * delta; + } + + static int32_t SqDiffInt16(int32_t a, int32_t b) + { + int32_t delta = a - b; + return delta * delta; + } + + static int32_t SqDiffSInt16(int32_t a, int32_t b) + { + int32_t delta = a - b; + return delta * delta; + } + + static float TwosCLHalfToFloat(int32_t v) + { + int32_t absV = (v < 0) ? -v : v; + + int32_t signBits = (absV & -32768); + int32_t mantissa = (absV & 0x03ff); + int32_t exponent = (absV & 0x7c00); + + bool isDenormal = (exponent == 0); + + // Convert exponent to high-bits + exponent = (exponent >> 3) + 14336; + + int32_t denormalCorrection = (isDenormal ? (signBits | 14336) : 0) << 16; + + int32_t fBits = ((exponent | signBits) << 16) | (mantissa << 13); + + float f, correction; + memcpy(&f, &fBits, 4); + memcpy(&correction, &denormalCorrection, 4); + + return f - correction; + } + + static Float SqDiff2CLFloat(const SInt16 &a, const Float &b) + { + Float fa = TwosCLHalfToFloat(a); + + Float diff = fa - b; + return diff * diff; + } + + static Float SqDiff2CL(const SInt16 &a, const SInt16 &b) + { + Float fa = TwosCLHalfToFloat(a); + Float fb = TwosCLHalfToFloat(b); + + Float diff = fa - fb; + return diff * diff; + } + + static Float SqDiff2CLFloat(const SInt16 &a, float aWeight, const Float &b) + { + Float fa = TwosCLHalfToFloat(a) * aWeight; + + Float diff = fa - b; + return diff * diff; + } + + static int32_t RightShift(int32_t v, int bits) + { + return SignedRightShift(v, bits); + } + + static int32_t ToSInt16(int32_t v) + { + return v; + } + + static int32_t ToUInt16(int32_t v) + { + return v; + } + + static int32_t ToUInt15(int32_t v) + { + return v; + } + + static int32_t XMultiply(int32_t a, int32_t b) + { + return a * b; + } + + static int32_t CompactMultiply(int32_t a, int32_t b) + { + return a * b; + } + + static bool AnySet(bool v) + { + return v; + } + + static bool AllSet(bool v) + { + return v; + } + }; + +#endif + + namespace Internal + { + namespace BC7Data + { + enum AlphaMode + { + AlphaMode_Combined, + AlphaMode_Separate, + AlphaMode_None, + }; + + enum PBitMode + { + PBitMode_PerEndpoint, + PBitMode_PerSubset, + PBitMode_None + }; + + struct BC7ModeInfo + { + PBitMode m_pBitMode; + AlphaMode m_alphaMode; + int m_rgbBits; + int m_alphaBits; + int m_partitionBits; + int m_numSubsets; + int m_indexBits; + int m_alphaIndexBits; + bool m_hasIndexSelector; + }; + + BC7ModeInfo g_modes[] = + { + { PBitMode_PerEndpoint, AlphaMode_None, 4, 0, 4, 3, 3, 0, false }, // 0 + { PBitMode_PerSubset, AlphaMode_None, 6, 0, 6, 2, 3, 0, false }, // 1 + { PBitMode_None, AlphaMode_None, 5, 0, 6, 3, 2, 0, false }, // 2 + { PBitMode_PerEndpoint, AlphaMode_None, 7, 0, 6, 2, 2, 0, false }, // 3 (Mode reference has an error, P-bit is really per-endpoint) + + { PBitMode_None, AlphaMode_Separate, 5, 6, 0, 1, 2, 3, true }, // 4 + { PBitMode_None, AlphaMode_Separate, 7, 8, 0, 1, 2, 2, false }, // 5 + { PBitMode_PerEndpoint, AlphaMode_Combined, 7, 7, 0, 1, 4, 0, false }, // 6 + { PBitMode_PerEndpoint, AlphaMode_Combined, 5, 5, 6, 2, 2, 0, false } // 7 + }; + + const int g_weight2[] = { 0, 21, 43, 64 }; + const int g_weight3[] = { 0, 9, 18, 27, 37, 46, 55, 64 }; + const int g_weight4[] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; + + const int *g_weightTables[] = + { + NULL, + NULL, + g_weight2, + g_weight3, + g_weight4 + }; + + struct BC6HModeInfo + { + uint16_t m_modeID; + bool m_partitioned; + bool m_transformed; + int m_aPrec; + int m_bPrec[3]; + }; + + // [partitioned][precision] + bool g_hdrModesExistForPrecision[2][17] = + { + //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + { false, false, false, false, false, false, false, false, false, false, true, true, true, false, false, false, true }, + { false, false, false, false, false, false, true, true, true, true, true, true, false, false, false, false, false }, + }; + + BC6HModeInfo g_hdrModes[] = + { + { 0x00, true, true, 10,{ 5, 5, 5 } }, + { 0x01, true, true, 7,{ 6, 6, 6 } }, + { 0x02, true, true, 11,{ 5, 4, 4 } }, + { 0x06, true, true, 11,{ 4, 5, 4 } }, + { 0x0a, true, true, 11,{ 4, 4, 5 } }, + { 0x0e, true, true, 9,{ 5, 5, 5 } }, + { 0x12, true, true, 8,{ 6, 5, 5 } }, + { 0x16, true, true, 8,{ 5, 6, 5 } }, + { 0x1a, true, true, 8,{ 5, 5, 6 } }, + { 0x1e, true, false, 6,{ 6, 6, 6 } }, + { 0x03, false, false, 10,{ 10, 10, 10 } }, + { 0x07, false, true, 11,{ 9, 9, 9 } }, + { 0x0b, false, true, 12,{ 8, 8, 8 } }, + { 0x0f, false, true, 16,{ 4, 4, 4 } }, + }; + + const int g_maxHDRPrecision = 16; + + static const size_t g_numHDRModes = sizeof(g_hdrModes) / sizeof(g_hdrModes[0]); + + static uint16_t g_partitionMap[64] = + { + 0xCCCC, 0x8888, 0xEEEE, 0xECC8, + 0xC880, 0xFEEC, 0xFEC8, 0xEC80, + 0xC800, 0xFFEC, 0xFE80, 0xE800, + 0xFFE8, 0xFF00, 0xFFF0, 0xF000, + 0xF710, 0x008E, 0x7100, 0x08CE, + 0x008C, 0x7310, 0x3100, 0x8CCE, + 0x088C, 0x3110, 0x6666, 0x366C, + 0x17E8, 0x0FF0, 0x718E, 0x399C, + 0xaaaa, 0xf0f0, 0x5a5a, 0x33cc, + 0x3c3c, 0x55aa, 0x9696, 0xa55a, + 0x73ce, 0x13c8, 0x324c, 0x3bdc, + 0x6996, 0xc33c, 0x9966, 0x660, + 0x272, 0x4e4, 0x4e40, 0x2720, + 0xc936, 0x936c, 0x39c6, 0x639c, + 0x9336, 0x9cc6, 0x817e, 0xe718, + 0xccf0, 0xfcc, 0x7744, 0xee22, + }; + + static uint32_t g_partitionMap2[64] = + { + 0xaa685050, 0x6a5a5040, 0x5a5a4200, 0x5450a0a8, + 0xa5a50000, 0xa0a05050, 0x5555a0a0, 0x5a5a5050, + 0xaa550000, 0xaa555500, 0xaaaa5500, 0x90909090, + 0x94949494, 0xa4a4a4a4, 0xa9a59450, 0x2a0a4250, + 0xa5945040, 0x0a425054, 0xa5a5a500, 0x55a0a0a0, + 0xa8a85454, 0x6a6a4040, 0xa4a45000, 0x1a1a0500, + 0x0050a4a4, 0xaaa59090, 0x14696914, 0x69691400, + 0xa08585a0, 0xaa821414, 0x50a4a450, 0x6a5a0200, + 0xa9a58000, 0x5090a0a8, 0xa8a09050, 0x24242424, + 0x00aa5500, 0x24924924, 0x24499224, 0x50a50a50, + 0x500aa550, 0xaaaa4444, 0x66660000, 0xa5a0a5a0, + 0x50a050a0, 0x69286928, 0x44aaaa44, 0x66666600, + 0xaa444444, 0x54a854a8, 0x95809580, 0x96969600, + 0xa85454a8, 0x80959580, 0xaa141414, 0x96960000, + 0xaaaa1414, 0xa05050a0, 0xa0a5a5a0, 0x96000000, + 0x40804080, 0xa9a8a9a8, 0xaaaaaa44, 0x2a4a5254, + }; + + static int g_fixupIndexes2[64] = + { + 15,15,15,15, + 15,15,15,15, + 15,15,15,15, + 15,15,15,15, + 15, 2, 8, 2, + 2, 8, 8,15, + 2, 8, 2, 2, + 8, 8, 2, 2, + + 15,15, 6, 8, + 2, 8,15,15, + 2, 8, 2, 2, + 2,15,15, 6, + 6, 2, 6, 8, + 15,15, 2, 2, + 15,15,15,15, + 15, 2, 2,15, + }; + + static int g_fixupIndexes3[64][2] = + { + { 3,15 },{ 3, 8 },{ 15, 8 },{ 15, 3 }, + { 8,15 },{ 3,15 },{ 15, 3 },{ 15, 8 }, + { 8,15 },{ 8,15 },{ 6,15 },{ 6,15 }, + { 6,15 },{ 5,15 },{ 3,15 },{ 3, 8 }, + { 3,15 },{ 3, 8 },{ 8,15 },{ 15, 3 }, + { 3,15 },{ 3, 8 },{ 6,15 },{ 10, 8 }, + { 5, 3 },{ 8,15 },{ 8, 6 },{ 6,10 }, + { 8,15 },{ 5,15 },{ 15,10 },{ 15, 8 }, + + { 8,15 },{ 15, 3 },{ 3,15 },{ 5,10 }, + { 6,10 },{ 10, 8 },{ 8, 9 },{ 15,10 }, + { 15, 6 },{ 3,15 },{ 15, 8 },{ 5,15 }, + { 15, 3 },{ 15, 6 },{ 15, 6 },{ 15, 8 }, + { 3,15 },{ 15, 3 },{ 5,15 },{ 5,15 }, + { 5,15 },{ 8,15 },{ 5,15 },{ 10,15 }, + { 5,15 },{ 10,15 },{ 8,15 },{ 13,15 }, + { 15, 3 },{ 12,15 },{ 3,15 },{ 3, 8 }, + }; + + static const unsigned char g_fragments[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0, 16 + 0, 1, 2, 3, // 16, 4 + 0, 1, 4, // 20, 3 + 0, 1, 2, 4, // 23, 4 + 2, 3, 7, // 27, 3 + 1, 2, 3, 7, // 30, 4 + 0, 1, 2, 3, 4, 5, 6, 7, // 34, 8 + 0, 1, 4, 8, // 42, 4 + 0, 1, 2, 4, 5, 8, // 46, 6 + 0, 1, 2, 3, 4, 5, 6, 8, // 52, 8 + 1, 4, 5, 6, 9, // 60, 5 + 2, 5, 6, 7, 10, // 65, 5 + 5, 6, 9, 10, // 70, 4 + 2, 3, 7, 11, // 74, 4 + 1, 2, 3, 6, 7, 11, // 78, 6 + 0, 1, 2, 3, 5, 6, 7, 11, // 84, 8 + 0, 1, 2, 3, 8, 9, 10, 11, // 92, 8 + 2, 3, 6, 7, 8, 9, 10, 11, // 100, 8 + 4, 5, 6, 7, 8, 9, 10, 11, // 108, 8 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, // 116, 12 + 0, 4, 8, 12, // 128, 4 + 0, 2, 3, 4, 6, 7, 8, 12, // 132, 8 + 0, 1, 2, 4, 5, 8, 9, 12, // 140, 8 + 0, 1, 2, 3, 4, 5, 6, 8, 9, 12, // 148, 10 + 3, 6, 7, 8, 9, 12, // 158, 6 + 3, 5, 6, 7, 8, 9, 10, 12, // 164, 8 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, // 172, 12 + 0, 1, 2, 5, 6, 7, 11, 12, // 184, 8 + 5, 8, 9, 10, 13, // 192, 5 + 8, 12, 13, // 197, 3 + 4, 8, 12, 13, // 200, 4 + 2, 3, 6, 9, 12, 13, // 204, 6 + 0, 1, 2, 3, 8, 9, 12, 13, // 210, 8 + 0, 1, 4, 5, 8, 9, 12, 13, // 218, 8 + 2, 3, 6, 7, 8, 9, 12, 13, // 226, 8 + 2, 3, 5, 6, 9, 10, 12, 13, // 234, 8 + 0, 3, 6, 7, 9, 10, 12, 13, // 242, 8 + 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 13, // 250, 12 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, // 262, 13 + 2, 3, 4, 7, 8, 11, 12, 13, // 275, 8 + 1, 2, 6, 7, 8, 11, 12, 13, // 283, 8 + 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, // 291, 10 + 2, 3, 4, 5, 10, 11, 12, 13, // 301, 8 + 0, 1, 6, 7, 10, 11, 12, 13, // 309, 8 + 6, 9, 10, 11, 14, // 317, 5 + 0, 2, 4, 6, 8, 10, 12, 14, // 322, 8 + 1, 3, 5, 7, 8, 10, 12, 14, // 330, 8 + 1, 3, 4, 6, 9, 11, 12, 14, // 338, 8 + 0, 2, 5, 7, 9, 11, 12, 14, // 346, 8 + 0, 3, 4, 5, 8, 9, 13, 14, // 354, 8 + 2, 3, 4, 7, 8, 9, 13, 14, // 362, 8 + 1, 2, 5, 6, 9, 10, 13, 14, // 370, 8 + 0, 3, 4, 7, 9, 10, 13, 14, // 378, 8 + 0, 3, 5, 6, 8, 11, 13, 14, // 386, 8 + 1, 2, 4, 7, 8, 11, 13, 14, // 394, 8 + 0, 1, 4, 7, 10, 11, 13, 14, // 402, 8 + 0, 3, 6, 7, 10, 11, 13, 14, // 410, 8 + 8, 12, 13, 14, // 418, 4 + 1, 2, 3, 7, 8, 12, 13, 14, // 422, 8 + 4, 8, 9, 12, 13, 14, // 430, 6 + 0, 4, 5, 8, 9, 12, 13, 14, // 436, 8 + 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, // 444, 10 + 2, 6, 8, 9, 10, 12, 13, 14, // 454, 8 + 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, // 462, 12 + 0, 7, 9, 10, 11, 12, 13, 14, // 474, 8 + 1, 2, 3, 4, 5, 6, 8, 15, // 482, 8 + 3, 7, 11, 15, // 490, 4 + 0, 1, 3, 4, 5, 7, 11, 15, // 494, 8 + 0, 4, 5, 10, 11, 15, // 502, 6 + 1, 2, 3, 6, 7, 10, 11, 15, // 508, 8 + 0, 1, 2, 3, 5, 6, 7, 10, 11, 15, // 516, 10 + 0, 4, 5, 6, 9, 10, 11, 15, // 526, 8 + 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 15, // 534, 12 + 1, 2, 4, 5, 8, 9, 12, 15, // 546, 8 + 2, 3, 5, 6, 8, 9, 12, 15, // 554, 8 + 0, 3, 5, 6, 9, 10, 12, 15, // 562, 8 + 1, 2, 4, 7, 9, 10, 12, 15, // 570, 8 + 1, 2, 5, 6, 8, 11, 12, 15, // 578, 8 + 0, 3, 4, 7, 8, 11, 12, 15, // 586, 8 + 0, 1, 5, 6, 10, 11, 12, 15, // 594, 8 + 1, 2, 6, 7, 10, 11, 12, 15, // 602, 8 + 1, 3, 4, 6, 8, 10, 13, 15, // 610, 8 + 0, 2, 5, 7, 8, 10, 13, 15, // 618, 8 + 0, 2, 4, 6, 9, 11, 13, 15, // 626, 8 + 1, 3, 5, 7, 9, 11, 13, 15, // 634, 8 + 0, 1, 2, 3, 4, 5, 7, 8, 12, 13, 15, // 642, 11 + 2, 3, 4, 5, 8, 9, 14, 15, // 653, 8 + 0, 1, 6, 7, 8, 9, 14, 15, // 661, 8 + 0, 1, 5, 10, 14, 15, // 669, 6 + 0, 3, 4, 5, 9, 10, 14, 15, // 675, 8 + 0, 1, 5, 6, 9, 10, 14, 15, // 683, 8 + 11, 14, 15, // 691, 3 + 7, 11, 14, 15, // 694, 4 + 1, 2, 4, 5, 8, 11, 14, 15, // 698, 8 + 0, 1, 4, 7, 8, 11, 14, 15, // 706, 8 + 0, 1, 4, 5, 10, 11, 14, 15, // 714, 8 + 2, 3, 6, 7, 10, 11, 14, 15, // 722, 8 + 4, 5, 6, 7, 10, 11, 14, 15, // 730, 8 + 0, 1, 4, 5, 7, 8, 10, 11, 14, 15, // 738, 10 + 0, 1, 2, 3, 5, 6, 7, 9, 10, 11, 14, 15, // 748, 12 + 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 14, 15, // 760, 13 + 0, 1, 2, 3, 4, 6, 7, 11, 12, 14, 15, // 773, 11 + 3, 4, 8, 9, 10, 13, 14, 15, // 784, 8 + 11, 13, 14, 15, // 792, 4 + 0, 1, 2, 4, 11, 13, 14, 15, // 796, 8 + 0, 1, 2, 4, 5, 10, 11, 13, 14, 15, // 804, 10 + 7, 10, 11, 13, 14, 15, // 814, 6 + 3, 6, 7, 10, 11, 13, 14, 15, // 820, 8 + 1, 5, 9, 10, 11, 13, 14, 15, // 828, 8 + 1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, // 836, 12 + 12, 13, 14, 15, // 848, 4 + 0, 1, 2, 3, 12, 13, 14, 15, // 852, 8 + 0, 1, 4, 5, 12, 13, 14, 15, // 860, 8 + 4, 5, 6, 7, 12, 13, 14, 15, // 868, 8 + 4, 8, 9, 10, 12, 13, 14, 15, // 876, 8 + 0, 4, 5, 8, 9, 10, 12, 13, 14, 15, // 884, 10 + 0, 1, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, // 894, 12 + 0, 1, 2, 3, 4, 7, 8, 11, 12, 13, 14, 15, // 906, 12 + 0, 1, 3, 4, 8, 9, 11, 12, 13, 14, 15, // 918, 11 + 0, 2, 3, 7, 8, 10, 11, 12, 13, 14, 15, // 929, 11 + 7, 9, 10, 11, 12, 13, 14, 15, // 940, 8 + 3, 6, 7, 9, 10, 11, 12, 13, 14, 15, // 948, 10 + 2, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, // 958, 12 + 8, 9, 10, 11, 12, 13, 14, 15, // 970, 8 + 0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, // 978, 12 + 0, 1, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, // 990, 13 + 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 1003, 12 + 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 1015, 13 + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 1028, 12 + 0, 2, // 1040, 2 + 1, 3, // 1042, 2 + 0, 1, 4, 5, // 1044, 4 + 0, 1, 2, 4, 5, // 1048, 5 + 2, 3, 6, // 1053, 3 + 0, 2, 4, 6, // 1056, 4 + 1, 2, 5, 6, // 1060, 4 + 0, 1, 2, 3, 5, 6, // 1064, 6 + 0, 1, 2, 4, 5, 6, // 1070, 6 + 0, 1, 2, 3, 4, 5, 6, // 1076, 7 + 0, 3, 4, 7, // 1083, 4 + 0, 1, 2, 3, 4, 7, // 1087, 6 + 1, 3, 5, 7, // 1093, 4 + 2, 3, 6, 7, // 1097, 4 + 1, 2, 3, 6, 7, // 1101, 5 + 1, 2, 3, 5, 6, 7, // 1106, 6 + 0, 1, 2, 3, 5, 6, 7, // 1112, 7 + 4, 5, 6, 7, // 1119, 4 + 0, 8, // 1123, 2 + 0, 1, 4, 5, 8, // 1125, 5 + 0, 1, 8, 9, // 1130, 4 + 4, 5, 8, 9, // 1134, 4 + 0, 1, 4, 5, 8, 9, // 1138, 6 + 2, 6, 8, 9, // 1144, 4 + 6, 7, 8, 9, // 1148, 4 + 0, 2, 4, 6, 8, 10, // 1152, 6 + 1, 2, 5, 6, 9, 10, // 1158, 6 + 0, 3, 4, 7, 9, 10, // 1164, 6 + 0, 1, 2, 8, 9, 10, // 1170, 6 + 4, 5, 6, 8, 9, 10, // 1176, 6 + 3, 11, // 1182, 2 + 2, 3, 6, 7, 11, // 1184, 5 + 0, 3, 8, 11, // 1189, 4 + 0, 3, 4, 7, 8, 11, // 1193, 6 + 1, 3, 5, 7, 9, 11, // 1199, 6 + 2, 3, 10, 11, // 1205, 4 + 1, 5, 10, 11, // 1209, 4 + 4, 5, 10, 11, // 1213, 4 + 6, 7, 10, 11, // 1217, 4 + 2, 3, 6, 7, 10, 11, // 1221, 6 + 1, 2, 3, 9, 10, 11, // 1227, 6 + 5, 6, 7, 9, 10, 11, // 1233, 6 + 8, 9, 10, 11, // 1239, 4 + 4, 12, // 1243, 2 + 0, 1, 2, 3, 4, 5, 8, 12, // 1245, 8 + 8, 9, 12, // 1253, 3 + 0, 4, 5, 8, 9, 12, // 1256, 6 + 0, 1, 4, 5, 8, 9, 12, // 1262, 7 + 2, 3, 5, 6, 8, 9, 12, // 1269, 7 + 1, 5, 9, 13, // 1276, 4 + 6, 7, 9, 13, // 1280, 4 + 1, 4, 7, 10, 13, // 1284, 5 + 1, 6, 8, 11, 13, // 1289, 5 + 0, 1, 12, 13, // 1294, 4 + 4, 5, 12, 13, // 1298, 4 + 0, 1, 6, 7, 12, 13, // 1302, 6 + 0, 1, 4, 8, 12, 13, // 1308, 6 + 8, 9, 12, 13, // 1314, 4 + 4, 8, 9, 12, 13, // 1318, 5 + 4, 5, 8, 9, 12, 13, // 1323, 6 + 0, 4, 5, 8, 9, 12, 13, // 1329, 7 + 0, 1, 6, 10, 12, 13, // 1336, 6 + 3, 6, 7, 9, 10, 12, 13, // 1342, 7 + 0, 1, 10, 11, 12, 13, // 1349, 6 + 2, 4, 7, 9, 14, // 1355, 5 + 4, 5, 10, 14, // 1360, 4 + 2, 6, 10, 14, // 1364, 4 + 2, 5, 8, 11, 14, // 1368, 5 + 0, 2, 12, 14, // 1373, 4 + 8, 10, 12, 14, // 1377, 4 + 4, 6, 8, 10, 12, 14, // 1381, 6 + 13, 14, // 1387, 2 + 9, 10, 13, 14, // 1389, 4 + 5, 6, 9, 10, 13, 14, // 1393, 6 + 0, 1, 2, 12, 13, 14, // 1399, 6 + 4, 5, 6, 12, 13, 14, // 1405, 6 + 8, 9, 12, 13, 14, // 1411, 5 + 8, 9, 10, 12, 13, 14, // 1416, 6 + 7, 15, // 1422, 2 + 0, 5, 10, 15, // 1424, 4 + 0, 1, 2, 3, 6, 7, 11, 15, // 1428, 8 + 10, 11, 15, // 1436, 3 + 0, 1, 5, 6, 10, 11, 15, // 1439, 7 + 3, 6, 7, 10, 11, 15, // 1446, 6 + 12, 15, // 1452, 2 + 0, 3, 12, 15, // 1454, 4 + 4, 7, 12, 15, // 1458, 4 + 0, 3, 6, 9, 12, 15, // 1462, 6 + 0, 3, 5, 10, 12, 15, // 1468, 6 + 8, 11, 12, 15, // 1474, 4 + 5, 6, 8, 11, 12, 15, // 1478, 6 + 4, 7, 8, 11, 12, 15, // 1484, 6 + 1, 3, 13, 15, // 1490, 4 + 9, 11, 13, 15, // 1494, 4 + 5, 7, 9, 11, 13, 15, // 1498, 6 + 2, 3, 14, 15, // 1504, 4 + 2, 3, 4, 5, 14, 15, // 1508, 6 + 6, 7, 14, 15, // 1514, 4 + 2, 3, 5, 9, 14, 15, // 1518, 6 + 2, 3, 8, 9, 14, 15, // 1524, 6 + 10, 14, 15, // 1530, 3 + 0, 4, 5, 9, 10, 14, 15, // 1533, 7 + 2, 3, 7, 11, 14, 15, // 1540, 6 + 10, 11, 14, 15, // 1546, 4 + 7, 10, 11, 14, 15, // 1550, 5 + 6, 7, 10, 11, 14, 15, // 1555, 6 + 1, 2, 3, 13, 14, 15, // 1561, 6 + 5, 6, 7, 13, 14, 15, // 1567, 6 + 10, 11, 13, 14, 15, // 1573, 5 + 9, 10, 11, 13, 14, 15, // 1578, 6 + 0, 4, 8, 9, 12, 13, 14, 15, // 1584, 8 + 9, 10, 12, 13, 14, 15, // 1592, 6 + 8, 11, 12, 13, 14, 15, // 1598, 6 + 3, 7, 10, 11, 12, 13, 14, 15, // 1604, 8 + }; + static const int g_shapeRanges[][2] = + { + { 0, 16 },{ 16, 4 },{ 20, 3 },{ 23, 4 },{ 27, 3 },{ 30, 4 },{ 34, 8 },{ 42, 4 },{ 46, 6 },{ 52, 8 },{ 60, 5 }, + { 65, 5 },{ 70, 4 },{ 74, 4 },{ 78, 6 },{ 84, 8 },{ 92, 8 },{ 100, 8 },{ 108, 8 },{ 116, 12 },{ 128, 4 },{ 132, 8 }, + { 140, 8 },{ 148, 10 },{ 158, 6 },{ 164, 8 },{ 172, 12 },{ 184, 8 },{ 192, 5 },{ 197, 3 },{ 200, 4 },{ 204, 6 },{ 210, 8 }, + { 218, 8 },{ 226, 8 },{ 234, 8 },{ 242, 8 },{ 250, 12 },{ 262, 13 },{ 275, 8 },{ 283, 8 },{ 291, 10 },{ 301, 8 },{ 309, 8 }, + { 317, 5 },{ 322, 8 },{ 330, 8 },{ 338, 8 },{ 346, 8 },{ 354, 8 },{ 362, 8 },{ 370, 8 },{ 378, 8 },{ 386, 8 },{ 394, 8 }, + { 402, 8 },{ 410, 8 },{ 418, 4 },{ 422, 8 },{ 430, 6 },{ 436, 8 },{ 444, 10 },{ 454, 8 },{ 462, 12 },{ 474, 8 },{ 482, 8 }, + { 490, 4 },{ 494, 8 },{ 502, 6 },{ 508, 8 },{ 516, 10 },{ 526, 8 },{ 534, 12 },{ 546, 8 },{ 554, 8 },{ 562, 8 },{ 570, 8 }, + { 578, 8 },{ 586, 8 },{ 594, 8 },{ 602, 8 },{ 610, 8 },{ 618, 8 },{ 626, 8 },{ 634, 8 },{ 642, 11 },{ 653, 8 },{ 661, 8 }, + { 669, 6 },{ 675, 8 },{ 683, 8 },{ 691, 3 },{ 694, 4 },{ 698, 8 },{ 706, 8 },{ 714, 8 },{ 722, 8 },{ 730, 8 },{ 738, 10 }, + { 748, 12 },{ 760, 13 },{ 773, 11 },{ 784, 8 },{ 792, 4 },{ 796, 8 },{ 804, 10 },{ 814, 6 },{ 820, 8 },{ 828, 8 },{ 836, 12 }, + { 848, 4 },{ 852, 8 },{ 860, 8 },{ 868, 8 },{ 876, 8 },{ 884, 10 },{ 894, 12 },{ 906, 12 },{ 918, 11 },{ 929, 11 },{ 940, 8 }, + { 948, 10 },{ 958, 12 },{ 970, 8 },{ 978, 12 },{ 990, 13 },{ 1003, 12 },{ 1015, 13 },{ 1028, 12 },{ 1040, 2 },{ 1042, 2 },{ 1044, 4 }, + { 1048, 5 },{ 1053, 3 },{ 1056, 4 },{ 1060, 4 },{ 1064, 6 },{ 1070, 6 },{ 1076, 7 },{ 1083, 4 },{ 1087, 6 },{ 1093, 4 },{ 1097, 4 }, + { 1101, 5 },{ 1106, 6 },{ 1112, 7 },{ 1119, 4 },{ 1123, 2 },{ 1125, 5 },{ 1130, 4 },{ 1134, 4 },{ 1138, 6 },{ 1144, 4 },{ 1148, 4 }, + { 1152, 6 },{ 1158, 6 },{ 1164, 6 },{ 1170, 6 },{ 1176, 6 },{ 1182, 2 },{ 1184, 5 },{ 1189, 4 },{ 1193, 6 },{ 1199, 6 },{ 1205, 4 }, + { 1209, 4 },{ 1213, 4 },{ 1217, 4 },{ 1221, 6 },{ 1227, 6 },{ 1233, 6 },{ 1239, 4 },{ 1243, 2 },{ 1245, 8 },{ 1253, 3 },{ 1256, 6 }, + { 1262, 7 },{ 1269, 7 },{ 1276, 4 },{ 1280, 4 },{ 1284, 5 },{ 1289, 5 },{ 1294, 4 },{ 1298, 4 },{ 1302, 6 },{ 1308, 6 },{ 1314, 4 }, + { 1318, 5 },{ 1323, 6 },{ 1329, 7 },{ 1336, 6 },{ 1342, 7 },{ 1349, 6 },{ 1355, 5 },{ 1360, 4 },{ 1364, 4 },{ 1368, 5 },{ 1373, 4 }, + { 1377, 4 },{ 1381, 6 },{ 1387, 2 },{ 1389, 4 },{ 1393, 6 },{ 1399, 6 },{ 1405, 6 },{ 1411, 5 },{ 1416, 6 },{ 1422, 2 },{ 1424, 4 }, + { 1428, 8 },{ 1436, 3 },{ 1439, 7 },{ 1446, 6 },{ 1452, 2 },{ 1454, 4 },{ 1458, 4 },{ 1462, 6 },{ 1468, 6 },{ 1474, 4 },{ 1478, 6 }, + { 1484, 6 },{ 1490, 4 },{ 1494, 4 },{ 1498, 6 },{ 1504, 4 },{ 1508, 6 },{ 1514, 4 },{ 1518, 6 },{ 1524, 6 },{ 1530, 3 },{ 1533, 7 }, + { 1540, 6 },{ 1546, 4 },{ 1550, 5 },{ 1555, 6 },{ 1561, 6 },{ 1567, 6 },{ 1573, 5 },{ 1578, 6 },{ 1584, 8 },{ 1592, 6 },{ 1598, 6 }, + { 1604, 8 }, + }; + static const int g_shapes1[][2] = + { + { 0, 16 } + }; + static const int g_shapes2[64][2] = + { + { 33, 96 },{ 63, 66 },{ 20, 109 },{ 22, 107 },{ 37, 92 },{ 7, 122 },{ 8, 121 },{ 23, 106 }, + { 38, 91 },{ 2, 127 },{ 9, 120 },{ 26, 103 },{ 3, 126 },{ 6, 123 },{ 1, 128 },{ 19, 110 }, + { 15, 114 },{ 124, 5 },{ 72, 57 },{ 115, 14 },{ 125, 4 },{ 70, 59 },{ 100, 29 },{ 60, 69 }, + { 116, 13 },{ 99, 30 },{ 78, 51 },{ 94, 35 },{ 104, 25 },{ 111, 18 },{ 71, 58 },{ 90, 39 }, + { 45, 84 },{ 16, 113 },{ 82, 47 },{ 95, 34 },{ 87, 42 },{ 83, 46 },{ 53, 76 },{ 48, 81 }, + { 68, 61 },{ 105, 24 },{ 98, 31 },{ 88, 41 },{ 75, 54 },{ 43, 86 },{ 52, 77 },{ 117, 12 }, + { 119, 10 },{ 118, 11 },{ 85, 44 },{ 101, 28 },{ 36, 93 },{ 55, 74 },{ 89, 40 },{ 79, 50 }, + { 56, 73 },{ 49, 80 },{ 64, 65 },{ 27, 102 },{ 32, 97 },{ 112, 17 },{ 67, 62 },{ 21, 108 }, + }; + static const int g_shapes3[64][3] = + { + { 148, 160, 240 },{ 132, 212, 205 },{ 136, 233, 187 },{ 175, 237, 143 },{ 6, 186, 232 },{ 33, 142, 232 },{ 131, 123, 142 },{ 131, 96, 186 }, + { 6, 171, 110 },{ 1, 18, 110 },{ 1, 146, 123 },{ 33, 195, 66 },{ 20, 51, 66 },{ 20, 178, 96 },{ 2, 177, 106 },{ 211, 4, 59 }, + { 8, 191, 91 },{ 230, 14, 29 },{ 1, 188, 234 },{ 151, 110, 168 },{ 20, 144, 238 },{ 137, 66, 206 },{ 173, 179, 232 },{ 209, 194, 186 }, + { 239, 165, 142 },{ 131, 152, 242 },{ 214, 54, 12 },{ 140, 219, 201 },{ 190, 150, 231 },{ 156, 135, 241 },{ 185, 227, 167 },{ 145, 210, 59 }, + { 138, 174, 106 },{ 189, 229, 14 },{ 176, 133, 106 },{ 78, 178, 195 },{ 111, 146, 171 },{ 216, 180, 196 },{ 217, 181, 193 },{ 184, 228, 166 }, + { 192, 225, 153 },{ 134, 141, 123 },{ 6, 222, 198 },{ 149, 183, 96 },{ 33, 226, 164 },{ 161, 215, 51 },{ 197, 221, 18 },{ 1, 223, 199 }, + { 154, 163, 110 },{ 20, 236, 169 },{ 157, 204, 66 },{ 1, 202, 220 },{ 20, 170, 235 },{ 203, 158, 66 },{ 162, 155, 110 },{ 6, 201, 218 }, + { 139, 135, 123 },{ 33, 167, 224 },{ 182, 150, 96 },{ 19, 200, 213 },{ 63, 207, 159 },{ 147, 172, 109 },{ 129, 130, 128 },{ 208, 14, 59 }, + }; + + static const int g_shapeList1[] = + { + 0, + }; + + static const int g_shapeList1Collapse[] = + { + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, + }; + static const int g_shapeList2[] = + { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, + }; + static const int g_shapeList2Collapse[] = + { + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, + }; + + static const int g_shapeList12[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, + }; + + static const int g_shapeList12Collapse[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, + }; + + static const int g_shapeList3[] = + { + 1, 2, 4, 6, 8, 12, 14, 18, 19, 20, 29, + 33, 51, 54, 59, 63, 66, 78, 91, 96, 106, 109, + 110, 111, 123, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, 241, 242, + }; + + static const int g_shapeList3Collapse[] = + { + -1, 0, 1, -1, 2, -1, 3, -1, 4, -1, -1, + -1, 5, -1, 6, -1, -1, -1, 7, 8, 9, -1, + -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, + 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, 13, + -1, -1, -1, -1, 14, -1, -1, -1, 15, -1, -1, + 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 18, -1, -1, -1, -1, 19, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, 21, + 22, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 24, -1, -1, -1, -1, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, + }; + + static const int g_shapeList3Short[] = + { + 1, 2, 4, 6, 18, 20, 33, 51, 59, 66, 96, + 106, 110, 123, 131, 132, 136, 142, 143, 146, 148, 160, + 171, 175, 177, 178, 186, 187, 195, 205, 211, 212, 232, + 233, 237, 240, + }; + + static const int g_shapeList3ShortCollapse[] = + { + -1, 0, 1, -1, 2, -1, 3, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 4, -1, 5, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, + -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, + 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, + 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, 14, + 15, -1, -1, -1, 16, -1, -1, -1, -1, -1, 17, + 18, -1, -1, 19, -1, 20, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, 23, + -1, 24, 25, -1, -1, -1, -1, -1, -1, -1, 26, + 27, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, + -1, -1, 30, 31, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 32, 33, -1, -1, -1, 34, -1, -1, 35, -1, + -1, + }; + + static const int g_shapeListAll[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, + }; + + static const int g_numShapes1 = sizeof(g_shapeList1) / sizeof(g_shapeList1[0]); + static const int g_numShapes2 = sizeof(g_shapeList2) / sizeof(g_shapeList2[0]); + static const int g_numShapes12 = sizeof(g_shapeList12) / sizeof(g_shapeList12[0]); + static const int g_numShapes3 = sizeof(g_shapeList3) / sizeof(g_shapeList3[0]); + static const int g_numShapes3Short = sizeof(g_shapeList3Short) / sizeof(g_shapeList3Short[0]); + static const int g_numShapesAll = sizeof(g_shapeListAll) / sizeof(g_shapeListAll[0]); + static const int g_numFragments = sizeof(g_fragments) / sizeof(g_fragments[0]); + + static const int g_maxFragmentsPerMode = (g_numShapes2 > g_numShapes3) ? g_numShapes2 : g_numShapes3; + } + + namespace BC6HData + { + enum EField + { + NA, // N/A + M, // Mode + D, // Shape + RW, + RX, + RY, + RZ, + GW, + GX, + GY, + GZ, + BW, + BX, + BY, + BZ, + }; + + struct ModeDescriptor + { + EField m_eField; + uint8_t m_uBit; + }; + + const ModeDescriptor g_modeDescriptors[14][82] = + { + { // Mode 1 (0x00) - 10 5 5 5 + { M, 0 },{ M, 1 },{ GY, 4 },{ BY, 4 },{ BZ, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 2 (0x01) - 7 6 6 6 + { M, 0 },{ M, 1 },{ GY, 5 },{ GZ, 4 },{ GZ, 5 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ BZ, 0 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ BY, 5 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BZ, 3 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 3 (0x02) - 11 5 4 4 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RW,10 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,10 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,10 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 4 (0x06) - 11 4 5 4 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,10 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GW,10 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,10 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ BZ, 0 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ GY, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 5 (0x0a) - 11 4 4 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,10 }, + { BY, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,10 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BW,10 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ BZ, 1 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ BZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 6 (0x0e) - 9 5 5 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 7 (0x12) - 8 6 5 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ GZ, 4 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BZ, 3 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 8 (0x16) - 8 5 6 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ BZ, 0 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GY, 5 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ GZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 9 (0x1a) - 8 5 5 6 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ BY, 5 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 10 (0x1e) - 6 6 6 6 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ GZ, 4 },{ BZ, 0 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GY, 5 },{ BY, 5 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ GZ, 5 },{ BZ, 3 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 11 (0x03) - 10 10 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ RX, 6 },{ RX, 7 },{ RX, 8 },{ RX, 9 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GX, 6 },{ GX, 7 },{ GX, 8 },{ GX, 9 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BX, 6 },{ BX, 7 },{ BX, 8 },{ BX, 9 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + + { // Mode 12 (0x07) - 11 9 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ RX, 6 },{ RX, 7 },{ RX, 8 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GX, 6 },{ GX, 7 },{ GX, 8 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BX, 6 },{ BX, 7 },{ BX, 8 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + + { // Mode 13 (0x0b) - 12 8 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ RX, 6 },{ RX, 7 },{ RW,11 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GX, 6 },{ GX, 7 },{ GW,11 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BX, 6 },{ BX, 7 },{ BW,11 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + + { // Mode 14 (0x0f) - 16 4 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,15 }, + { RW,14 },{ RW,13 },{ RW,12 },{ RW,11 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,15 }, + { GW,14 },{ GW,13 },{ GW,12 },{ GW,11 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,15 }, + { BW,14 },{ BW,13 },{ BW,12 },{ BW,11 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + }; + } + + struct PackingVector + { + uint32_t m_vector[4]; + int m_offset; + + void Init() + { + for (int i = 0; i < 4; i++) + m_vector[i] = 0; + + m_offset = 0; + } + + inline void Pack(ParallelMath::ScalarUInt16 value, int bits) + { + int vOffset = m_offset >> 5; + int bitOffset = m_offset & 0x1f; + + m_vector[vOffset] |= (static_cast<uint32_t>(value) << bitOffset) & static_cast<uint32_t>(0xffffffff); + + int overflowBits = bitOffset + bits - 32; + if (overflowBits > 0) + m_vector[vOffset + 1] |= (static_cast<uint32_t>(value) >> (bits - overflowBits)); + + m_offset += bits; + } + + inline void Flush(uint8_t* output) + { + assert(m_offset == 128); + + for (int v = 0; v < 4; v++) + { + uint32_t chunk = m_vector[v]; + for (int b = 0; b < 4; b++) + output[v * 4 + b] = static_cast<uint8_t>((chunk >> (b * 8)) & 0xff); + } + } + }; + + + struct UnpackingVector + { + uint32_t m_vector[4]; + + void Init(const uint8_t *bytes) + { + for (int i = 0; i < 4; i++) + m_vector[i] = 0; + + for (int b = 0; b < 16; b++) + m_vector[b / 4] |= (bytes[b] << ((b % 4) * 8)); + } + + inline ParallelMath::ScalarUInt16 Unpack(int bits) + { + uint32_t bitMask = (1 << bits) - 1; + + ParallelMath::ScalarUInt16 result = static_cast<ParallelMath::ScalarUInt16>(m_vector[0] & bitMask); + + for (int i = 0; i < 4; i++) + { + m_vector[i] >>= bits; + if (i != 3) + m_vector[i] |= (m_vector[i + 1] & bitMask) << (32 - bits); + } + + return result; + } + }; + + void ComputeTweakFactors2(int tweak, int range, float* outFactors) + { + int totalUnits = range - 1; + int minOutsideUnits = ((tweak >> 1) & 1); + int maxOutsideUnits = (tweak & 1); + int insideUnits = totalUnits - minOutsideUnits - maxOutsideUnits; + + outFactors[0] = -static_cast<float>(minOutsideUnits) / static_cast<float>(insideUnits); + outFactors[1] = static_cast<float>(maxOutsideUnits) / static_cast<float>(insideUnits) + 1.0f; + } + + ParallelMath::Float ScaleHDRValue(ParallelMath::Float v, bool isSigned) + { + if (isSigned) + { + ParallelMath::Float offset = ParallelMath::Select(ParallelMath::Less(v, ParallelMath::MakeFloatZero()), ParallelMath::MakeFloat(-30.0f), ParallelMath::MakeFloat(30.0f)); + return (v * 32.0f + offset) / 31.0f; + } + else + return (v * 64.0f + 30.0f) / 31.0f; + } + + ParallelMath::SInt16 UnscaleHDRValueSigned(const ParallelMath::SInt16 &v) + { +#ifdef CVTT_ENABLE_ASSERTS + for (int i = 0; i < ParallelMath::ParallelSize; i++) + assert(ParallelMath::Extract(v, i) != -32768) +#endif + + ParallelMath::Int16CompFlag negative = ParallelMath::Less(v, ParallelMath::MakeSInt16(0)); + ParallelMath::UInt15 absComp = ParallelMath::LosslessCast<ParallelMath::UInt15>::Cast(ParallelMath::Select(negative, ParallelMath::SInt16(ParallelMath::MakeSInt16(0) - v), v)); + + ParallelMath::UInt31 multiplied = ParallelMath::XMultiply(absComp, ParallelMath::MakeUInt15(31)); + ParallelMath::UInt31 shifted = ParallelMath::RightShift(multiplied, 5); + ParallelMath::UInt15 absCompScaled = ParallelMath::ToUInt15(shifted); + ParallelMath::SInt16 signBits = ParallelMath::SelectOrZero(negative, ParallelMath::MakeSInt16(-32768)); + + return ParallelMath::LosslessCast<ParallelMath::SInt16>::Cast(absCompScaled) | signBits; + } + + ParallelMath::UInt15 UnscaleHDRValueUnsigned(const ParallelMath::UInt16 &v) + { + return ParallelMath::ToUInt15(ParallelMath::RightShift(ParallelMath::XMultiply(v, ParallelMath::MakeUInt15(31)), 6)); + } + + void UnscaleHDREndpoints(const ParallelMath::AInt16 inEP[2][3], ParallelMath::AInt16 outEP[2][3], bool isSigned) + { + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + { + if (isSigned) + outEP[epi][ch] = ParallelMath::LosslessCast<ParallelMath::AInt16>::Cast(UnscaleHDRValueSigned(ParallelMath::LosslessCast<ParallelMath::SInt16>::Cast(inEP[epi][ch]))); + else + outEP[epi][ch] = ParallelMath::LosslessCast<ParallelMath::AInt16>::Cast(UnscaleHDRValueUnsigned(ParallelMath::LosslessCast<ParallelMath::UInt16>::Cast(inEP[epi][ch]))); + } + } + } + + template<int TVectorSize> + class UnfinishedEndpoints + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::SInt32 MSInt32; + + UnfinishedEndpoints() + { + } + + UnfinishedEndpoints(const MFloat base[TVectorSize], const MFloat offset[TVectorSize]) + { + for (int ch = 0; ch < TVectorSize; ch++) + m_base[ch] = base[ch]; + for (int ch = 0; ch < TVectorSize; ch++) + m_offset[ch] = offset[ch]; + } + + UnfinishedEndpoints(const UnfinishedEndpoints& other) + { + for (int ch = 0; ch < TVectorSize; ch++) + m_base[ch] = other.m_base[ch]; + for (int ch = 0; ch < TVectorSize; ch++) + m_offset[ch] = other.m_offset[ch]; + } + + void FinishHDRUnsigned(int tweak, int range, MSInt16* outEP0, MSInt16* outEP1, ParallelMath::RoundTowardNearestForScope* roundingMode) + { + float tweakFactors[2]; + ComputeTweakFactors2(tweak, range, tweakFactors); + + for (int ch = 0; ch < TVectorSize; ch++) + { + MUInt15 channelEPs[2]; + for (int epi = 0; epi < 2; epi++) + { + MFloat f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[epi], 0.0f, 31743.0f); + channelEPs[epi] = ParallelMath::RoundAndConvertToU15(f, roundingMode); + } + + outEP0[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(channelEPs[0]); + outEP1[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(channelEPs[1]); + } + } + + void FinishHDRSigned(int tweak, int range, MSInt16* outEP0, MSInt16* outEP1, ParallelMath::RoundTowardNearestForScope* roundingMode) + { + float tweakFactors[2]; + ComputeTweakFactors2(tweak, range, tweakFactors); + + for (int ch = 0; ch < TVectorSize; ch++) + { + MSInt16 channelEPs[2]; + for (int epi = 0; epi < 2; epi++) + { + MFloat f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[epi], -31743.0f, 31743.0f); + channelEPs[epi] = ParallelMath::RoundAndConvertToS16(f, roundingMode); + } + + outEP0[ch] = channelEPs[0]; + outEP1[ch] = channelEPs[1]; + } + } + + void FinishLDR(int tweak, int range, MUInt15* outEP0, MUInt15* outEP1) + { + ParallelMath::RoundTowardNearestForScope roundingMode; + + float tweakFactors[2]; + ComputeTweakFactors2(tweak, range, tweakFactors); + + for (int ch = 0; ch < TVectorSize; ch++) + { + MFloat ep0f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[0], 0.0f, 255.0f); + MFloat ep1f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[1], 0.0f, 255.0f); + outEP0[ch] = ParallelMath::RoundAndConvertToU15(ep0f, &roundingMode); + outEP1[ch] = ParallelMath::RoundAndConvertToU15(ep1f, &roundingMode); + } + } + + template<int TNewVectorSize> + UnfinishedEndpoints<TNewVectorSize> ExpandTo(float filler) + { + MFloat newBase[TNewVectorSize]; + MFloat newOffset[TNewVectorSize]; + + for (int ch = 0; ch < TNewVectorSize && ch < TVectorSize; ch++) + { + newBase[ch] = m_base[ch]; + newOffset[ch] = m_offset[ch]; + } + + MFloat fillerV = ParallelMath::MakeFloat(filler); + + for (int ch = TVectorSize; ch < TNewVectorSize; ch++) + { + newBase[ch] = fillerV; + newOffset[ch] = ParallelMath::MakeFloatZero(); + } + + return UnfinishedEndpoints<TNewVectorSize>(newBase, newOffset); + } + + private: + MFloat m_base[TVectorSize]; + MFloat m_offset[TVectorSize]; + }; + + template<int TMatrixSize> + class PackedCovarianceMatrix + { + public: + // 0: xx, + // 1: xy, yy + // 3: xz, yz, zz + // 6: xw, yw, zw, ww + // ... etc. + static const int PyramidSize = (TMatrixSize * (TMatrixSize + 1)) / 2; + + typedef ParallelMath::Float MFloat; + + PackedCovarianceMatrix() + { + for (int i = 0; i < PyramidSize; i++) + m_values[i] = ParallelMath::MakeFloatZero(); + } + + void Add(const ParallelMath::Float vec[TMatrixSize], ParallelMath::Float weight) + { + int index = 0; + for (int row = 0; row < TMatrixSize; row++) + { + for (int col = 0; col <= row; col++) + { + m_values[index] = m_values[index] + vec[row] * vec[col] * weight; + index++; + } + } + } + + void Product(MFloat outVec[TMatrixSize], const MFloat inVec[TMatrixSize]) + { + for (int row = 0; row < TMatrixSize; row++) + { + MFloat sum = ParallelMath::MakeFloatZero(); + + int index = (row * (row + 1)) >> 1; + for (int col = 0; col < TMatrixSize; col++) + { + sum = sum + inVec[col] * m_values[index]; + if (col >= row) + index += col + 1; + else + index++; + } + + outVec[row] = sum; + } + } + + private: + ParallelMath::Float m_values[PyramidSize]; + }; + + static const int NumEndpointSelectorPasses = 3; + + template<int TVectorSize, int TIterationCount> + class EndpointSelector + { + public: + typedef ParallelMath::Float MFloat; + + EndpointSelector() + { + for (int ch = 0; ch < TVectorSize; ch++) + { + m_centroid[ch] = ParallelMath::MakeFloatZero(); + m_direction[ch] = ParallelMath::MakeFloatZero(); + } + m_weightTotal = ParallelMath::MakeFloatZero(); + m_minDist = ParallelMath::MakeFloat(FLT_MAX); + m_maxDist = ParallelMath::MakeFloat(-FLT_MAX); + } + + void ContributePass(const MFloat value[TVectorSize], int pass, MFloat weight) + { + if (pass == 0) + ContributeCentroid(value, weight); + else if (pass == 1) + ContributeDirection(value, weight); + else if (pass == 2) + ContributeMinMax(value); + } + + void FinishPass(int pass) + { + if (pass == 0) + FinishCentroid(); + else if (pass == 1) + FinishDirection(); + } + + UnfinishedEndpoints<TVectorSize> GetEndpoints(const float channelWeights[TVectorSize]) const + { + MFloat unweightedBase[TVectorSize]; + MFloat unweightedOffset[TVectorSize]; + + for (int ch = 0; ch < TVectorSize; ch++) + { + MFloat min = m_centroid[ch] + m_direction[ch] * m_minDist; + MFloat max = m_centroid[ch] + m_direction[ch] * m_maxDist; + + float safeWeight = channelWeights[ch]; + if (safeWeight == 0.f) + safeWeight = 1.0f; + + unweightedBase[ch] = min / channelWeights[ch]; + unweightedOffset[ch] = (max - min) / channelWeights[ch]; + } + + return UnfinishedEndpoints<TVectorSize>(unweightedBase, unweightedOffset); + } + + private: + void ContributeCentroid(const MFloat value[TVectorSize], MFloat weight) + { + for (int ch = 0; ch < TVectorSize; ch++) + m_centroid[ch] = m_centroid[ch] + value[ch] * weight; + m_weightTotal = m_weightTotal + weight; + } + + void FinishCentroid() + { + MFloat denom = m_weightTotal; + ParallelMath::MakeSafeDenominator(denom); + + for (int ch = 0; ch < TVectorSize; ch++) + m_centroid[ch] = m_centroid[ch] / denom; + } + + void ContributeDirection(const MFloat value[TVectorSize], MFloat weight) + { + MFloat diff[TVectorSize]; + for (int ch = 0; ch < TVectorSize; ch++) + diff[ch] = value[ch] - m_centroid[ch]; + + m_covarianceMatrix.Add(diff, weight); + } + + void FinishDirection() + { + MFloat approx[TVectorSize]; + for (int ch = 0; ch < TVectorSize; ch++) + approx[ch] = ParallelMath::MakeFloat(1.0f); + + for (int i = 0; i < TIterationCount; i++) + { + MFloat product[TVectorSize]; + m_covarianceMatrix.Product(product, approx); + + MFloat largestComponent = product[0]; + for (int ch = 1; ch < TVectorSize; ch++) + largestComponent = ParallelMath::Max(largestComponent, product[ch]); + + // product = largestComponent*newApprox + ParallelMath::MakeSafeDenominator(largestComponent); + for (int ch = 0; ch < TVectorSize; ch++) + approx[ch] = product[ch] / largestComponent; + } + + // Normalize + MFloat approxLen = ParallelMath::MakeFloatZero(); + for (int ch = 0; ch < TVectorSize; ch++) + approxLen = approxLen + approx[ch] * approx[ch]; + + approxLen = ParallelMath::Sqrt(approxLen); + + ParallelMath::MakeSafeDenominator(approxLen); + + for (int ch = 0; ch < TVectorSize; ch++) + m_direction[ch] = approx[ch] / approxLen; + } + + void ContributeMinMax(const MFloat value[TVectorSize]) + { + MFloat dist = ParallelMath::MakeFloatZero(); + for (int ch = 0; ch < TVectorSize; ch++) + dist = dist + m_direction[ch] * (value[ch] - m_centroid[ch]); + + m_minDist = ParallelMath::Min(m_minDist, dist); + m_maxDist = ParallelMath::Max(m_maxDist, dist); + } + + ParallelMath::Float m_centroid[TVectorSize]; + ParallelMath::Float m_direction[TVectorSize]; + PackedCovarianceMatrix<TVectorSize> m_covarianceMatrix; + ParallelMath::Float m_weightTotal; + + ParallelMath::Float m_minDist; + ParallelMath::Float m_maxDist; + }; + + static const ParallelMath::UInt16 g_weightReciprocals[] = + { + ParallelMath::MakeUInt16(0), // -1 + ParallelMath::MakeUInt16(0), // 0 + ParallelMath::MakeUInt16(32768), // 1 + ParallelMath::MakeUInt16(16384), // 2 + ParallelMath::MakeUInt16(10923), // 3 + ParallelMath::MakeUInt16(8192), // 4 + ParallelMath::MakeUInt16(6554), // 5 + ParallelMath::MakeUInt16(5461), // 6 + ParallelMath::MakeUInt16(4681), // 7 + ParallelMath::MakeUInt16(4096), // 8 + ParallelMath::MakeUInt16(3641), // 9 + ParallelMath::MakeUInt16(3277), // 10 + ParallelMath::MakeUInt16(2979), // 11 + ParallelMath::MakeUInt16(2731), // 12 + ParallelMath::MakeUInt16(2521), // 13 + ParallelMath::MakeUInt16(2341), // 14 + ParallelMath::MakeUInt16(2185), // 15 + }; + + template<int TVectorSize> + class IndexSelector + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::AInt16 MAInt16; + typedef ParallelMath::SInt32 MSInt32; + typedef ParallelMath::UInt31 MUInt31; + + template<class TInterpolationEPType, class TColorEPType> + void Init(const float channelWeights[TVectorSize], const TInterpolationEPType interpolationEndPoints[2][TVectorSize], const TColorEPType colorSpaceEndpoints[2][TVectorSize], int range) + { + // In BC6H, the interpolation endpoints are higher-precision than the endpoints in color space. + // We need to select indexes using the color-space endpoints. + + m_isUniform = true; + for (int ch = 1; ch < TVectorSize; ch++) + { + if (channelWeights[ch] != channelWeights[0]) + m_isUniform = false; + } + + // To work with channel weights, we need something where: + // pxDiff = px - ep[0] + // epDiff = ep[1] - ep[0] + // + // weightedEPDiff = epDiff * channelWeights + // normalizedWeightedAxis = weightedEPDiff / len(weightedEPDiff) + // normalizedIndex = dot(pxDiff * channelWeights, normalizedWeightedAxis) / len(weightedEPDiff) + // index = normalizedIndex * maxValue + // + // Equivalent to: + // axis = channelWeights * maxValue * epDiff * channelWeights / lenSquared(epDiff * channelWeights) + // index = dot(axis, pxDiff) + + for (int ep = 0; ep < 2; ep++) + for (int ch = 0; ch < TVectorSize; ch++) + m_endPoint[ep][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(interpolationEndPoints[ep][ch]); + + m_range = range; + m_maxValue = static_cast<float>(range - 1); + + MFloat epDiffWeighted[TVectorSize]; + for (int ch = 0; ch < TVectorSize; ch++) + { + m_origin[ch] = ParallelMath::ToFloat(colorSpaceEndpoints[0][ch]); + MFloat opposingOriginCh = ParallelMath::ToFloat(colorSpaceEndpoints[1][ch]); + epDiffWeighted[ch] = (opposingOriginCh - m_origin[ch]) * channelWeights[ch]; + } + + MFloat lenSquared = epDiffWeighted[0] * epDiffWeighted[0]; + for (int ch = 1; ch < TVectorSize; ch++) + lenSquared = lenSquared + epDiffWeighted[ch] * epDiffWeighted[ch]; + + ParallelMath::MakeSafeDenominator(lenSquared); + + MFloat maxValueDividedByLengthSquared = ParallelMath::MakeFloat(m_maxValue) / lenSquared; + + for (int ch = 0; ch < TVectorSize; ch++) + m_axis[ch] = epDiffWeighted[ch] * channelWeights[ch] * maxValueDividedByLengthSquared; + } + + template<bool TSigned> + void Init(const float channelWeights[TVectorSize], const MUInt15 endPoints[2][TVectorSize], int range) + { + MAInt16 converted[2][TVectorSize]; + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < TVectorSize; ch++) + converted[epi][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(endPoints[epi][ch]); + + Init<MUInt15, MUInt15>(channelWeights, endPoints, endPoints, range); + } + + void ReconstructLDR_BC7(const MUInt15 &index, MUInt15* pixel, int numRealChannels) + { + MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9)); + + for (int ch = 0; ch < numRealChannels; ch++) + { + MUInt15 ep0f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply((ParallelMath::MakeUInt15(64) - weight), ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[0][ch]))); + MUInt15 ep1f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply(weight, ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[1][ch]))); + pixel[ch] = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ep0f + ep1f + ParallelMath::MakeUInt15(32), 6)); + } + } + + void ReconstructLDRPrecise(const MUInt15 &index, MUInt15* pixel, int numRealChannels) + { + MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 64, 7)); + + for (int ch = 0; ch < numRealChannels; ch++) + { + MUInt15 ep0f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply((ParallelMath::MakeUInt15(256) - weight), ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[0][ch]))); + MUInt15 ep1f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply(weight, ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[1][ch]))); + pixel[ch] = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ep0f + ep1f + ParallelMath::MakeUInt15(128), 8)); + } + } + + void ReconstructLDR_BC7(const MUInt15 &index, MUInt15* pixel) + { + ReconstructLDR_BC7(index, pixel, TVectorSize); + } + + void ReconstructLDRPrecise(const MUInt15 &index, MUInt15* pixel) + { + ReconstructLDRPrecise(index, pixel, TVectorSize); + } + + MUInt15 SelectIndexLDR(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope* rtn) const + { + MFloat dist = (pixel[0] - m_origin[0]) * m_axis[0]; + for (int ch = 1; ch < TVectorSize; ch++) + dist = dist + (pixel[ch] - m_origin[ch]) * m_axis[ch]; + + return ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(dist, 0.0f, m_maxValue), rtn); + } + + protected: + MAInt16 m_endPoint[2][TVectorSize]; + + private: + MFloat m_origin[TVectorSize]; + MFloat m_axis[TVectorSize]; + int m_range; + float m_maxValue; + bool m_isUniform; + }; + + + template<int TVectorSize> + class IndexSelectorHDR : public IndexSelector<TVectorSize> + { + public: + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt31 MUInt31; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::SInt32 MSInt32; + typedef ParallelMath::Float MFloat; + + private: + + MUInt15 InvertSingle(const MUInt15& anIndex) const + { + MUInt15 inverted = m_maxValueMinusOne - anIndex; + return ParallelMath::Select(m_isInverted, inverted, anIndex); + } + + void ReconstructHDRSignedUninverted(const MUInt15 &index, MSInt16* pixel) const + { + MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9)); + + for (int ch = 0; ch < TVectorSize; ch++) + { + MSInt16 ep0 = ParallelMath::LosslessCast<MSInt16>::Cast(this->m_endPoint[0][ch]); + MSInt16 ep1 = ParallelMath::LosslessCast<MSInt16>::Cast(this->m_endPoint[1][ch]); + + MSInt32 pixel32 = ParallelMath::XMultiply((ParallelMath::MakeUInt15(64) - weight), ep0) + ParallelMath::XMultiply(weight, ep1); + + pixel32 = ParallelMath::RightShift(pixel32 + ParallelMath::MakeSInt32(32), 6); + + pixel[ch] = UnscaleHDRValueSigned(ParallelMath::ToSInt16(pixel32)); + } + } + + void ReconstructHDRUnsignedUninverted(const MUInt15 &index, MSInt16* pixel) const + { + MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9)); + + for (int ch = 0; ch < TVectorSize; ch++) + { + MUInt16 ep0 = ParallelMath::LosslessCast<MUInt16>::Cast(this->m_endPoint[0][ch]); + MUInt16 ep1 = ParallelMath::LosslessCast<MUInt16>::Cast(this->m_endPoint[1][ch]); + + MUInt31 pixel31 = ParallelMath::XMultiply((ParallelMath::MakeUInt15(64) - weight), ep0) + ParallelMath::XMultiply(weight, ep1); + + pixel31 = ParallelMath::RightShift(pixel31 + ParallelMath::MakeUInt31(32), 6); + + pixel[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(UnscaleHDRValueUnsigned(ParallelMath::ToUInt16(pixel31))); + } + } + + MFloat ErrorForInterpolatorComponent(int index, int ch, const MFloat *pixel) const + { + MFloat diff = pixel[ch] - m_reconstructedInterpolators[index][ch]; + return diff * diff; + } + + MFloat ErrorForInterpolator(int index, const MFloat *pixel) const + { + MFloat error = ErrorForInterpolatorComponent(index, 0, pixel); + for (int ch = 1; ch < TVectorSize; ch++) + error = error + ErrorForInterpolatorComponent(index, ch, pixel); + return error; + } + + public: + + void InitHDR(int range, bool isSigned, bool fastIndexing, const float *channelWeights) + { + assert(range <= 16); + + m_range = range; + + m_isInverted = ParallelMath::MakeBoolInt16(false); + m_maxValueMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>(range - 1)); + + if (!fastIndexing) + { + for (int i = 0; i < range; i++) + { + MSInt16 recon2CL[TVectorSize]; + + if (isSigned) + ReconstructHDRSignedUninverted(ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), recon2CL); + else + ReconstructHDRUnsignedUninverted(ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), recon2CL); + + for (int ch = 0; ch < TVectorSize; ch++) + m_reconstructedInterpolators[i][ch] = ParallelMath::TwosCLHalfToFloat(recon2CL[ch]) * channelWeights[ch]; + } + } + } + + void ReconstructHDRSigned(const MUInt15 &index, MSInt16* pixel) const + { + ReconstructHDRSignedUninverted(InvertSingle(index), pixel); + } + + void ReconstructHDRUnsigned(const MUInt15 &index, MSInt16* pixel) const + { + ReconstructHDRUnsignedUninverted(InvertSingle(index), pixel); + } + + void ConditionalInvert(ParallelMath::Int16CompFlag invert) + { + m_isInverted = invert; + } + + MUInt15 SelectIndexHDRSlow(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope*) const + { + MUInt15 index = ParallelMath::MakeUInt15(0); + + MFloat bestError = ErrorForInterpolator(0, pixel); + for (int i = 1; i < m_range; i++) + { + MFloat error = ErrorForInterpolator(i, pixel); + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(error, bestError); + ParallelMath::ConditionalSet(index, ParallelMath::FloatFlagToInt16(errorBetter), ParallelMath::MakeUInt15(static_cast<uint16_t>(i))); + bestError = ParallelMath::Min(bestError, error); + } + + return InvertSingle(index); + } + + MUInt15 SelectIndexHDRFast(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope* rtn) const + { + return InvertSingle(this->SelectIndexLDR(pixel, rtn)); + } + + private: + MFloat m_reconstructedInterpolators[16][TVectorSize]; + ParallelMath::Int16CompFlag m_isInverted; + MUInt15 m_maxValueMinusOne; + int m_range; + }; + + // Solve for a, b where v = a*t + b + // This allows endpoints to be mapped to where T=0 and T=1 + // Least squares from totals: + // a = (tv - t*v/w)/(tt - t*t/w) + // b = (v - a*t)/w + template<int TVectorSize> + class EndpointRefiner + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::AInt16 MAInt16; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::SInt32 MSInt32; + + MFloat m_tv[TVectorSize]; + MFloat m_v[TVectorSize]; + MFloat m_tt; + MFloat m_t; + MFloat m_w; + int m_wu; + + float m_rcpMaxIndex; + float m_channelWeights[TVectorSize]; + float m_rcpChannelWeights[TVectorSize]; + + void Init(int indexRange, const float channelWeights[TVectorSize]) + { + for (int ch = 0; ch < TVectorSize; ch++) + { + m_tv[ch] = ParallelMath::MakeFloatZero(); + m_v[ch] = ParallelMath::MakeFloatZero(); + } + m_tt = ParallelMath::MakeFloatZero(); + m_t = ParallelMath::MakeFloatZero(); + m_w = ParallelMath::MakeFloatZero(); + + m_rcpMaxIndex = 1.0f / static_cast<float>(indexRange - 1); + + for (int ch = 0; ch < TVectorSize; ch++) + { + m_channelWeights[ch] = channelWeights[ch]; + m_rcpChannelWeights[ch] = 1.0f; + if (m_channelWeights[ch] != 0.0f) + m_rcpChannelWeights[ch] = 1.0f / channelWeights[ch]; + } + + m_wu = 0; + } + + void ContributePW(const MFloat *pwFloatPixel, const MUInt15 &index, MFloat weight) + { + MFloat t = ParallelMath::ToFloat(index) * m_rcpMaxIndex; + + for (int ch = 0; ch < TVectorSize; ch++) + { + MFloat v = pwFloatPixel[ch] * weight; + + m_tv[ch] = m_tv[ch] + t * v; + m_v[ch] = m_v[ch] + v; + } + m_tt = m_tt + weight * t * t; + m_t = m_t + weight * t; + m_w = m_w + weight; + } + + void ContributeUnweightedPW(const MFloat *pwFloatPixel, const MUInt15 &index, int numRealChannels) + { + MFloat t = ParallelMath::ToFloat(index) * m_rcpMaxIndex; + + for (int ch = 0; ch < numRealChannels; ch++) + { + MFloat v = pwFloatPixel[ch]; + + m_tv[ch] = m_tv[ch] + t * v; + m_v[ch] = m_v[ch] + v; + } + m_tt = m_tt + t * t; + m_t = m_t + t; + m_wu++; + } + + void ContributeUnweightedPW(const MFloat *floatPixel, const MUInt15 &index) + { + ContributeUnweightedPW(floatPixel, index, TVectorSize); + } + + void GetRefinedEndpoints(MFloat endPoint[2][TVectorSize]) + { + // a = (tv - t*v/w)/(tt - t*t/w) + // b = (v - a*t)/w + MFloat w = m_w + ParallelMath::MakeFloat(static_cast<float>(m_wu)); + + ParallelMath::MakeSafeDenominator(w); + MFloat wRcp = ParallelMath::Reciprocal(w); + + MFloat adenom = (m_tt * w - m_t * m_t) * wRcp; + + ParallelMath::FloatCompFlag adenomZero = ParallelMath::Equal(adenom, ParallelMath::MakeFloatZero()); + ParallelMath::ConditionalSet(adenom, adenomZero, ParallelMath::MakeFloat(1.0f)); + + for (int ch = 0; ch < TVectorSize; ch++) + { + /* + if (adenom == 0.0) + p1 = p2 = er.v / er.w; + else + { + float4 a = (er.tv - er.t*er.v / er.w) / adenom; + float4 b = (er.v - a * er.t) / er.w; + p1 = b; + p2 = a + b; + } + */ + + MFloat a = (m_tv[ch] - m_t * m_v[ch] * wRcp) / adenom; + MFloat b = (m_v[ch] - a * m_t) * wRcp; + + MFloat p1 = b; + MFloat p2 = a + b; + + ParallelMath::ConditionalSet(p1, adenomZero, (m_v[ch] * wRcp)); + ParallelMath::ConditionalSet(p2, adenomZero, p1); + + // Unweight + float inverseWeight = m_rcpChannelWeights[ch]; + + endPoint[0][ch] = p1 * inverseWeight; + endPoint[1][ch] = p2 * inverseWeight; + } + } + + void GetRefinedEndpointsLDR(MUInt15 endPoint[2][TVectorSize], int numRealChannels, const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + MFloat floatEndPoint[2][TVectorSize]; + GetRefinedEndpoints(floatEndPoint); + + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < TVectorSize; ch++) + endPoint[epi][ch] = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(floatEndPoint[epi][ch], 0.0f, 255.0f), roundingMode); + } + + void GetRefinedEndpointsLDR(MUInt15 endPoint[2][TVectorSize], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + GetRefinedEndpointsLDR(endPoint, TVectorSize, roundingMode); + } + + void GetRefinedEndpointsHDR(MSInt16 endPoint[2][TVectorSize], bool isSigned, const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + MFloat floatEndPoint[2][TVectorSize]; + GetRefinedEndpoints(floatEndPoint); + + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < TVectorSize; ch++) + { + MFloat f = floatEndPoint[epi][ch]; + if (isSigned) + endPoint[epi][ch] = ParallelMath::LosslessCast<MSInt16>::Cast(ParallelMath::RoundAndConvertToS16(ParallelMath::Clamp(f, -31743.0f, 31743.0f), roundingMode)); + else + endPoint[epi][ch] = ParallelMath::LosslessCast<MSInt16>::Cast(ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(f, 0.0f, 31743.0f), roundingMode)); + } + } + } + }; + + template<int TVectorSize> + class AggregatedError + { + public: + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt31 MUInt31; + typedef ParallelMath::Float MFloat; + + AggregatedError() + { + for (int ch = 0; ch < TVectorSize; ch++) + m_errorUnweighted[ch] = ParallelMath::MakeUInt31(0); + } + + void Add(const MUInt16 &channelErrorUnweighted, int ch) + { + m_errorUnweighted[ch] = m_errorUnweighted[ch] + ParallelMath::ToUInt31(channelErrorUnweighted); + } + + MFloat Finalize(uint32_t flags, const float channelWeightsSq[TVectorSize]) const + { + if (flags & cvtt::Flags::Uniform) + { + MUInt31 total = m_errorUnweighted[0]; + for (int ch = 1; ch < TVectorSize; ch++) + total = total + m_errorUnweighted[ch]; + return ParallelMath::ToFloat(total); + } + else + { + MFloat total = ParallelMath::ToFloat(m_errorUnweighted[0]) * channelWeightsSq[0]; + for (int ch = 1; ch < TVectorSize; ch++) + total = total + ParallelMath::ToFloat(m_errorUnweighted[ch]) * channelWeightsSq[ch]; + return total; + } + } + + private: + MUInt31 m_errorUnweighted[TVectorSize]; + }; + + class BCCommon + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::AInt16 MAInt16; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::SInt32 MSInt32; + + static int TweakRoundsForRange(int range) + { + if (range == 3) + return 3; + return 4; + } + + template<int TVectorSize> + static void ComputeErrorLDR(uint32_t flags, const MUInt15 reconstructed[TVectorSize], const MUInt15 original[TVectorSize], int numRealChannels, AggregatedError<TVectorSize> &aggError) + { + for (int ch = 0; ch < numRealChannels; ch++) + aggError.Add(ParallelMath::SqDiffUInt8(reconstructed[ch], original[ch]), ch); + } + + template<int TVectorSize> + static void ComputeErrorLDR(uint32_t flags, const MUInt15 reconstructed[TVectorSize], const MUInt15 original[TVectorSize], AggregatedError<TVectorSize> &aggError) + { + ComputeErrorLDR<TVectorSize>(flags, reconstructed, original, TVectorSize, aggError); + } + + template<int TVectorSize> + static MFloat ComputeErrorLDRSimple(uint32_t flags, const MUInt15 reconstructed[TVectorSize], const MUInt15 original[TVectorSize], int numRealChannels, const float *channelWeightsSq) + { + AggregatedError<TVectorSize> aggError; + ComputeErrorLDR<TVectorSize>(flags, reconstructed, original, numRealChannels, aggError); + return aggError.Finalize(flags, channelWeightsSq); + } + + template<int TVectorSize> + static MFloat ComputeErrorHDRFast(uint32_t flags, const MSInt16 reconstructed[TVectorSize], const MSInt16 original[TVectorSize], const float channelWeightsSq[TVectorSize]) + { + MFloat error = ParallelMath::MakeFloatZero(); + if (flags & Flags::Uniform) + { + for (int ch = 0; ch < TVectorSize; ch++) + error = error + ParallelMath::SqDiffSInt16(reconstructed[ch], original[ch]); + } + else + { + for (int ch = 0; ch < TVectorSize; ch++) + error = error + ParallelMath::SqDiffSInt16(reconstructed[ch], original[ch]) * ParallelMath::MakeFloat(channelWeightsSq[ch]); + } + + return error; + } + + template<int TVectorSize> + static MFloat ComputeErrorHDRSlow(uint32_t flags, const MSInt16 reconstructed[TVectorSize], const MSInt16 original[TVectorSize], const float channelWeightsSq[TVectorSize]) + { + MFloat error = ParallelMath::MakeFloatZero(); + if (flags & Flags::Uniform) + { + for (int ch = 0; ch < TVectorSize; ch++) + error = error + ParallelMath::SqDiff2CL(reconstructed[ch], original[ch]); + } + else + { + for (int ch = 0; ch < TVectorSize; ch++) + error = error + ParallelMath::SqDiff2CL(reconstructed[ch], original[ch]) * ParallelMath::MakeFloat(channelWeightsSq[ch]); + } + + return error; + } + + template<int TChannelCount> + static void PreWeightPixelsLDR(MFloat preWeightedPixels[16][TChannelCount], const MUInt15 pixels[16][TChannelCount], const float channelWeights[TChannelCount]) + { + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < TChannelCount; ch++) + preWeightedPixels[px][ch] = ParallelMath::ToFloat(pixels[px][ch]) * channelWeights[ch]; + } + } + + template<int TChannelCount> + static void PreWeightPixelsHDR(MFloat preWeightedPixels[16][TChannelCount], const MSInt16 pixels[16][TChannelCount], const float channelWeights[TChannelCount]) + { + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < TChannelCount; ch++) + preWeightedPixels[px][ch] = ParallelMath::ToFloat(pixels[px][ch]) * channelWeights[ch]; + } + } + }; + + class BC7Computer + { + public: + static const int MaxTweakRounds = 4; + + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::SInt32 MSInt32; + typedef ParallelMath::Float MFloat; + + struct WorkInfo + { + MUInt15 m_mode; + MFloat m_error; + MUInt15 m_ep[3][2][4]; + MUInt15 m_indexes[16]; + MUInt15 m_indexes2[16]; + + union + { + MUInt15 m_partition; + struct IndexSelectorAndRotation + { + MUInt15 m_indexSelector; + MUInt15 m_rotation; + } m_isr; + } m_u; + }; + + static void TweakAlpha(const MUInt15 original[2], int tweak, int range, MUInt15 result[2]) + { + ParallelMath::RoundTowardNearestForScope roundingMode; + + float tf[2]; + ComputeTweakFactors2(tweak, range, tf); + + MFloat base = ParallelMath::ToFloat(original[0]); + MFloat offs = ParallelMath::ToFloat(original[1]) - base; + + result[0] = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(base + offs * tf[0], 0.0f, 255.0f), &roundingMode); + result[1] = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(base + offs * tf[1], 0.0f, 255.0f), &roundingMode); + } + + static void Quantize(MUInt15* color, int bits, int channels, const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + float maxColor = static_cast<float>((1 << bits) - 1); + + for (int i = 0; i < channels; i++) + color[i] = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(ParallelMath::ToFloat(color[i]) * ParallelMath::MakeFloat(1.0f / 255.0f) * maxColor, 0.f, 255.f), roundingMode); + } + + static void QuantizeP(MUInt15* color, int bits, uint16_t p, int channels, const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + uint16_t pShift = static_cast<uint16_t>(1 << (7 - bits)); + MUInt15 pShiftV = ParallelMath::MakeUInt15(pShift); + + float maxColorF = static_cast<float>(255 - (1 << (7 - bits))); + + float maxQuantized = static_cast<float>((1 << bits) - 1); + + for (int ch = 0; ch < channels; ch++) + { + MUInt15 clr = color[ch]; + if (p) + clr = ParallelMath::Max(clr, pShiftV) - pShiftV; + + MFloat rerangedColor = ParallelMath::ToFloat(clr) * maxQuantized / maxColorF; + + clr = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(rerangedColor, 0.0f, maxQuantized), roundingMode) << 1; + if (p) + clr = clr | ParallelMath::MakeUInt15(1); + + color[ch] = clr; + } + } + + static void Unquantize(MUInt15* color, int bits, int channels) + { + for (int ch = 0; ch < channels; ch++) + { + MUInt15 clr = color[ch]; + clr = clr << (8 - bits); + color[ch] = clr | ParallelMath::RightShift(clr, bits); + } + } + + static void CompressEndpoints0(MUInt15 ep[2][4], uint16_t p[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + QuantizeP(ep[j], 4, p[j], 3, roundingMode); + Unquantize(ep[j], 5, 3); + ep[j][3] = ParallelMath::MakeUInt15(255); + } + } + + static void CompressEndpoints1(MUInt15 ep[2][4], uint16_t p, const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + QuantizeP(ep[j], 6, p, 3, roundingMode); + Unquantize(ep[j], 7, 3); + ep[j][3] = ParallelMath::MakeUInt15(255); + } + } + + static void CompressEndpoints2(MUInt15 ep[2][4], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + Quantize(ep[j], 5, 3, roundingMode); + Unquantize(ep[j], 5, 3); + ep[j][3] = ParallelMath::MakeUInt15(255); + } + } + + static void CompressEndpoints3(MUInt15 ep[2][4], uint16_t p[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + QuantizeP(ep[j], 7, p[j], 3, roundingMode); + ep[j][3] = ParallelMath::MakeUInt15(255); + } + } + + static void CompressEndpoints4(MUInt15 epRGB[2][3], MUInt15 epA[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + Quantize(epRGB[j], 5, 3, roundingMode); + Unquantize(epRGB[j], 5, 3); + + Quantize(epA + j, 6, 1, roundingMode); + Unquantize(epA + j, 6, 1); + } + } + + static void CompressEndpoints5(MUInt15 epRGB[2][3], MUInt15 epA[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + Quantize(epRGB[j], 7, 3, roundingMode); + Unquantize(epRGB[j], 7, 3); + } + + // Alpha is full precision + (void)epA; + } + + static void CompressEndpoints6(MUInt15 ep[2][4], uint16_t p[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + QuantizeP(ep[j], 7, p[j], 4, roundingMode); + } + + static void CompressEndpoints7(MUInt15 ep[2][4], uint16_t p[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + QuantizeP(ep[j], 5, p[j], 4, roundingMode); + Unquantize(ep[j], 6, 4); + } + } + + struct SinglePlaneTemporaries + { + UnfinishedEndpoints<3> unfinishedRGB[BC7Data::g_numShapesAll]; + UnfinishedEndpoints<4> unfinishedRGBA[BC7Data::g_numShapes12]; + + MUInt15 fragmentBestIndexes[BC7Data::g_numFragments]; + MUInt15 shapeBestEP[BC7Data::g_maxFragmentsPerMode][2][4]; + MFloat shapeBestError[BC7Data::g_maxFragmentsPerMode]; + }; + + static void TrySingleColorRGBAMultiTable(uint32_t flags, const MUInt15 pixels[16][4], const MFloat average[4], int numRealChannels, const uint8_t *fragmentStart, int shapeLength, const MFloat &staticAlphaError, const ParallelMath::Int16CompFlag punchThroughInvalid[4], MFloat& shapeBestError, MUInt15 shapeBestEP[2][4], MUInt15 *fragmentBestIndexes, const float *channelWeightsSq, const cvtt::Tables::BC7SC::Table*const* tables, int numTables, const ParallelMath::RoundTowardNearestForScope *rtn) + { + MFloat bestAverageError = ParallelMath::MakeFloat(FLT_MAX); + + MUInt15 intAverage[4]; + for (int ch = 0; ch < 4; ch++) + intAverage[ch] = ParallelMath::RoundAndConvertToU15(average[ch], rtn); + + MUInt15 eps[2][4]; + MUInt15 reconstructed[4]; + MUInt15 index = ParallelMath::MakeUInt15(0); + + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + eps[epi][ch] = ParallelMath::MakeUInt15(0); + eps[epi][3] = ParallelMath::MakeUInt15(255); + } + + for (int ch = 0; ch < 3; ch++) + reconstructed[ch] = ParallelMath::MakeUInt15(0); + reconstructed[3] = ParallelMath::MakeUInt15(255); + + // Depending on the target index and parity bits, there are multiple valid solid colors. + // We want to find the one closest to the actual average. + MFloat epsAverageDiff = ParallelMath::MakeFloat(FLT_MAX); + for (int t = 0; t < numTables; t++) + { + const cvtt::Tables::BC7SC::Table& table = *(tables[t]); + + ParallelMath::Int16CompFlag pti = punchThroughInvalid[table.m_pBits]; + + MUInt15 candidateReconstructed[4]; + MUInt15 candidateEPs[2][4]; + + for (int i = 0; i < ParallelMath::ParallelSize; i++) + { + for (int ch = 0; ch < numRealChannels; ch++) + { + ParallelMath::ScalarUInt16 avgValue = ParallelMath::Extract(intAverage[ch], i); + assert(avgValue >= 0 && avgValue <= 255); + + const cvtt::Tables::BC7SC::TableEntry &entry = table.m_entries[avgValue]; + + ParallelMath::PutUInt15(candidateEPs[0][ch], i, entry.m_min); + ParallelMath::PutUInt15(candidateEPs[1][ch], i, entry.m_max); + ParallelMath::PutUInt15(candidateReconstructed[ch], i, entry.m_actualColor); + } + } + + MFloat avgError = ParallelMath::MakeFloatZero(); + for (int ch = 0; ch < numRealChannels; ch++) + { + MFloat delta = ParallelMath::ToFloat(candidateReconstructed[ch]) - average[ch]; + avgError = avgError + delta * delta * channelWeightsSq[ch]; + } + + ParallelMath::Int16CompFlag better = ParallelMath::FloatFlagToInt16(ParallelMath::Less(avgError, bestAverageError)); + better = ParallelMath::AndNot(pti, better); // Mask out punch-through invalidations + + if (ParallelMath::AnySet(better)) + { + ParallelMath::ConditionalSet(bestAverageError, ParallelMath::Int16FlagToFloat(better), avgError); + + MUInt15 candidateIndex = ParallelMath::MakeUInt15(table.m_index); + + ParallelMath::ConditionalSet(index, better, candidateIndex); + + for (int ch = 0; ch < numRealChannels; ch++) + ParallelMath::ConditionalSet(reconstructed[ch], better, candidateReconstructed[ch]); + + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < numRealChannels; ch++) + ParallelMath::ConditionalSet(eps[epi][ch], better, candidateEPs[epi][ch]); + } + } + + AggregatedError<4> aggError; + for (int pxi = 0; pxi < shapeLength; pxi++) + { + int px = fragmentStart[pxi]; + + BCCommon::ComputeErrorLDR<4>(flags, reconstructed, pixels[px], numRealChannels, aggError); + } + + MFloat error = aggError.Finalize(flags, channelWeightsSq) + staticAlphaError; + + ParallelMath::Int16CompFlag better = ParallelMath::FloatFlagToInt16(ParallelMath::Less(error, shapeBestError)); + if (ParallelMath::AnySet(better)) + { + shapeBestError = ParallelMath::Min(shapeBestError, error); + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < numRealChannels; ch++) + ParallelMath::ConditionalSet(shapeBestEP[epi][ch], better, eps[epi][ch]); + } + + for (int pxi = 0; pxi < shapeLength; pxi++) + ParallelMath::ConditionalSet(fragmentBestIndexes[pxi], better, index); + } + } + + + static void TrySinglePlane(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const float channelWeights[4], int numTweakRounds, int numRefineRounds, WorkInfo& work, const ParallelMath::RoundTowardNearestForScope *rtn) + { + if (numRefineRounds < 1) + numRefineRounds = 1; + + if (numTweakRounds < 1) + numTweakRounds = 1; + else if (numTweakRounds > MaxTweakRounds) + numTweakRounds = MaxTweakRounds; + + float channelWeightsSq[4]; + + for (int ch = 0; ch < 4; ch++) + channelWeightsSq[ch] = channelWeights[ch] * channelWeights[ch]; + + SinglePlaneTemporaries temps; + + MUInt15 maxAlpha = ParallelMath::MakeUInt15(0); + MUInt15 minAlpha = ParallelMath::MakeUInt15(255); + ParallelMath::Int16CompFlag isPunchThrough = ParallelMath::MakeBoolInt16(true); + for (int px = 0; px < 16; px++) + { + MUInt15 a = pixels[px][3]; + maxAlpha = ParallelMath::Max(maxAlpha, a); + minAlpha = ParallelMath::Min(minAlpha, a); + + isPunchThrough = (isPunchThrough & (ParallelMath::Equal(a, ParallelMath::MakeUInt15(0)) | ParallelMath::Equal(a, ParallelMath::MakeUInt15(255)))); + } + + ParallelMath::Int16CompFlag blockHasNonMaxAlpha = ParallelMath::Less(minAlpha, ParallelMath::MakeUInt15(255)); + ParallelMath::Int16CompFlag blockHasNonZeroAlpha = ParallelMath::Less(ParallelMath::MakeUInt15(0), maxAlpha); + + bool anyBlockHasAlpha = ParallelMath::AnySet(blockHasNonMaxAlpha); + + // Try RGB modes if any block has a min alpha 251 or higher + bool allowRGBModes = ParallelMath::AnySet(ParallelMath::Less(ParallelMath::MakeUInt15(250), minAlpha)); + + // Try mode 7 if any block has alpha. + // Mode 7 is almost never selected for RGB blocks because mode 4 has very accurate 7.7.7.1 endpoints + // and its parity bit doesn't affect alpha, meaning mode 7 can only be better in extremely specific + // situations, and only by at most 1 unit of error per pixel. + bool allowMode7 = anyBlockHasAlpha; + + MFloat preWeightedPixels[16][4]; + + BCCommon::PreWeightPixelsLDR<4>(preWeightedPixels, pixels, channelWeights); + + const int *rgbInitialEPCollapseList = NULL; + + // Get initial RGB endpoints + if (allowRGBModes) + { + const int *shapeList; + int numShapesToEvaluate; + + if (flags & Flags::BC7_EnablePartitioning) + { + if (flags & Flags::BC7_Enable3Subsets) + { + shapeList = BC7Data::g_shapeListAll; + rgbInitialEPCollapseList = BC7Data::g_shapeListAll; + numShapesToEvaluate = BC7Data::g_numShapesAll; + } + else + { + shapeList = BC7Data::g_shapeList12; + rgbInitialEPCollapseList = BC7Data::g_shapeList12Collapse; + numShapesToEvaluate = BC7Data::g_numShapes12; + } + } + else + { + shapeList = BC7Data::g_shapeList1; + rgbInitialEPCollapseList = BC7Data::g_shapeList1Collapse; + numShapesToEvaluate = BC7Data::g_numShapes1; + } + + for (int shapeIter = 0; shapeIter < numShapesToEvaluate; shapeIter++) + { + int shape = shapeList[shapeIter]; + + int shapeStart = BC7Data::g_shapeRanges[shape][0]; + int shapeSize = BC7Data::g_shapeRanges[shape][1]; + + EndpointSelector<3, 8> epSelector; + + for (int epPass = 0; epPass < NumEndpointSelectorPasses; epPass++) + { + for (int spx = 0; spx < shapeSize; spx++) + { + int px = BC7Data::g_fragments[shapeStart + spx]; + epSelector.ContributePass(preWeightedPixels[px], epPass, ParallelMath::MakeFloat(1.0f)); + } + epSelector.FinishPass(epPass); + } + temps.unfinishedRGB[shapeIter] = epSelector.GetEndpoints(channelWeights); + } + } + + const int *rgbaInitialEPCollapseList = BC7Data::g_shapeList12Collapse; + + // Get initial RGBA endpoints + { + const int *shapeList = BC7Data::g_shapeList12; + int numShapesToEvaluate = BC7Data::g_numShapes12; + + for (int shapeIter = 0; shapeIter < numShapesToEvaluate; shapeIter++) + { + int shape = shapeList[shapeIter]; + + if (anyBlockHasAlpha || !allowRGBModes) + { + int shapeStart = BC7Data::g_shapeRanges[shape][0]; + int shapeSize = BC7Data::g_shapeRanges[shape][1]; + + EndpointSelector<4, 8> epSelector; + + for (int epPass = 0; epPass < NumEndpointSelectorPasses; epPass++) + { + for (int spx = 0; spx < shapeSize; spx++) + { + int px = BC7Data::g_fragments[shapeStart + spx]; + epSelector.ContributePass(preWeightedPixels[px], epPass, ParallelMath::MakeFloat(1.0f)); + } + epSelector.FinishPass(epPass); + } + temps.unfinishedRGBA[shapeIter] = epSelector.GetEndpoints(channelWeights); + } + else + { + temps.unfinishedRGBA[shapeIter] = temps.unfinishedRGB[rgbInitialEPCollapseList[shape]].ExpandTo<4>(255); + } + } + } + + for (uint16_t mode = 0; mode <= 7; mode++) + { + if (!(flags & Flags::BC7_EnablePartitioning) && BC7Data::g_modes[mode].m_numSubsets != 1) + continue; + + if (!(flags & Flags::BC7_Enable3Subsets) && BC7Data::g_modes[mode].m_numSubsets == 3) + continue; + + if (mode == 4 || mode == 5) + continue; + + if (mode < 4 && !allowRGBModes) + continue; + + if (mode == 7 && !allowMode7) + continue; + + bool isRGB = (mode < 4); + + unsigned int numPartitions = 1 << BC7Data::g_modes[mode].m_partitionBits; + int numSubsets = BC7Data::g_modes[mode].m_numSubsets; + int indexPrec = BC7Data::g_modes[mode].m_indexBits; + + int parityBitMax = 1; + if (BC7Data::g_modes[mode].m_pBitMode == BC7Data::PBitMode_PerEndpoint) + parityBitMax = 4; + else if (BC7Data::g_modes[mode].m_pBitMode == BC7Data::PBitMode_PerSubset) + parityBitMax = 2; + + int numRealChannels = isRGB ? 3 : 4; + + int numShapes; + const int *shapeList; + const int *shapeCollapseList; + + if (numSubsets == 1) + { + numShapes = BC7Data::g_numShapes1; + shapeList = BC7Data::g_shapeList1; + shapeCollapseList = BC7Data::g_shapeList1Collapse; + } + else if (numSubsets == 2) + { + numShapes = BC7Data::g_numShapes2; + shapeList = BC7Data::g_shapeList2; + shapeCollapseList = BC7Data::g_shapeList2Collapse; + } + else + { + assert(numSubsets == 3); + if (numPartitions == 16) + { + numShapes = BC7Data::g_numShapes3Short; + shapeList = BC7Data::g_shapeList3Short; + shapeCollapseList = BC7Data::g_shapeList3ShortCollapse; + } + else + { + assert(numPartitions == 64); + numShapes = BC7Data::g_numShapes3; + shapeList = BC7Data::g_shapeList3; + shapeCollapseList = BC7Data::g_shapeList3Collapse; + } + } + + for (int slot = 0; slot < BC7Data::g_maxFragmentsPerMode; slot++) + temps.shapeBestError[slot] = ParallelMath::MakeFloat(FLT_MAX); + + for (int shapeIter = 0; shapeIter < numShapes; shapeIter++) + { + int shape = shapeList[shapeIter]; + int shapeStart = BC7Data::g_shapeRanges[shape][0]; + int shapeLength = BC7Data::g_shapeRanges[shape][1]; + int shapeCollapsedEvalIndex = shapeCollapseList[shape]; + + AggregatedError<1> alphaAggError; + if (isRGB && anyBlockHasAlpha) + { + MUInt15 filledAlpha[1] = { ParallelMath::MakeUInt15(255) }; + + for (int pxi = 0; pxi < shapeLength; pxi++) + { + int px = BC7Data::g_fragments[shapeStart + pxi]; + MUInt15 original[1] = { pixels[px][3] }; + BCCommon::ComputeErrorLDR<1>(flags, filledAlpha, original, alphaAggError); + } + } + + float alphaWeightsSq[1] = { channelWeightsSq[3] }; + MFloat staticAlphaError = alphaAggError.Finalize(flags, alphaWeightsSq); + + assert(shapeCollapsedEvalIndex >= 0); + + MUInt15 tweakBaseEP[MaxTweakRounds][2][4]; + + for (int tweak = 0; tweak < numTweakRounds; tweak++) + { + if (isRGB) + { + temps.unfinishedRGB[rgbInitialEPCollapseList[shape]].FinishLDR(tweak, 1 << indexPrec, tweakBaseEP[tweak][0], tweakBaseEP[tweak][1]); + tweakBaseEP[tweak][0][3] = tweakBaseEP[tweak][1][3] = ParallelMath::MakeUInt15(255); + } + else + { + temps.unfinishedRGBA[rgbaInitialEPCollapseList[shape]].FinishLDR(tweak, 1 << indexPrec, tweakBaseEP[tweak][0], tweakBaseEP[tweak][1]); + } + } + + ParallelMath::Int16CompFlag punchThroughInvalid[4]; + for (int pIter = 0; pIter < parityBitMax; pIter++) + { + punchThroughInvalid[pIter] = ParallelMath::MakeBoolInt16(false); + + if ((flags & Flags::BC7_RespectPunchThrough) && (mode == 6 || mode == 7)) + { + // Modes 6 and 7 have parity bits that affect alpha + if (pIter == 0) + punchThroughInvalid[pIter] = (isPunchThrough & blockHasNonZeroAlpha); + else if (pIter == parityBitMax - 1) + punchThroughInvalid[pIter] = (isPunchThrough & blockHasNonMaxAlpha); + else + punchThroughInvalid[pIter] = isPunchThrough; + } + } + + for (int pIter = 0; pIter < parityBitMax; pIter++) + { + if (ParallelMath::AllSet(punchThroughInvalid[pIter])) + continue; + + bool needPunchThroughCheck = ParallelMath::AnySet(punchThroughInvalid[pIter]); + + for (int tweak = 0; tweak < numTweakRounds; tweak++) + { + uint16_t p[2]; + p[0] = (pIter & 1); + p[1] = ((pIter >> 1) & 1); + + MUInt15 ep[2][4]; + + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 4; ch++) + ep[epi][ch] = tweakBaseEP[tweak][epi][ch]; + + for (int refine = 0; refine < numRefineRounds; refine++) + { + switch (mode) + { + case 0: + CompressEndpoints0(ep, p, rtn); + break; + case 1: + CompressEndpoints1(ep, p[0], rtn); + break; + case 2: + CompressEndpoints2(ep, rtn); + break; + case 3: + CompressEndpoints3(ep, p, rtn); + break; + case 6: + CompressEndpoints6(ep, p, rtn); + break; + case 7: + CompressEndpoints7(ep, p, rtn); + break; + default: + assert(false); + break; + }; + + MFloat shapeError = ParallelMath::MakeFloatZero(); + + IndexSelector<4> indexSelector; + indexSelector.Init<false>(channelWeights, ep, 1 << indexPrec); + + EndpointRefiner<4> epRefiner; + epRefiner.Init(1 << indexPrec, channelWeights); + + MUInt15 indexes[16]; + + AggregatedError<4> aggError; + for (int pxi = 0; pxi < shapeLength; pxi++) + { + int px = BC7Data::g_fragments[shapeStart + pxi]; + + MUInt15 index; + MUInt15 reconstructed[4]; + + index = indexSelector.SelectIndexLDR(floatPixels[px], rtn); + indexSelector.ReconstructLDR_BC7(index, reconstructed, numRealChannels); + + if (flags & cvtt::Flags::BC7_FastIndexing) + BCCommon::ComputeErrorLDR<4>(flags, reconstructed, pixels[px], numRealChannels, aggError); + else + { + MFloat error = BCCommon::ComputeErrorLDRSimple<4>(flags, reconstructed, pixels[px], numRealChannels, channelWeightsSq); + + MUInt15 altIndexes[2]; + altIndexes[0] = ParallelMath::Max(index, ParallelMath::MakeUInt15(1)) - ParallelMath::MakeUInt15(1); + altIndexes[1] = ParallelMath::Min(index + ParallelMath::MakeUInt15(1), ParallelMath::MakeUInt15(static_cast<uint16_t>((1 << indexPrec) - 1))); + + for (int ii = 0; ii < 2; ii++) + { + indexSelector.ReconstructLDR_BC7(altIndexes[ii], reconstructed, numRealChannels); + + MFloat altError = BCCommon::ComputeErrorLDRSimple<4>(flags, reconstructed, pixels[px], numRealChannels, channelWeightsSq); + ParallelMath::Int16CompFlag better = ParallelMath::FloatFlagToInt16(ParallelMath::Less(altError, error)); + error = ParallelMath::Min(error, altError); + ParallelMath::ConditionalSet(index, better, altIndexes[ii]); + } + + shapeError = shapeError + error; + } + + if (refine != numRefineRounds - 1) + epRefiner.ContributeUnweightedPW(preWeightedPixels[px], index, numRealChannels); + + indexes[pxi] = index; + } + + if (flags & cvtt::Flags::BC7_FastIndexing) + shapeError = aggError.Finalize(flags, channelWeightsSq); + + if (isRGB) + shapeError = shapeError + staticAlphaError; + + ParallelMath::FloatCompFlag shapeErrorBetter; + ParallelMath::Int16CompFlag shapeErrorBetter16; + + shapeErrorBetter = ParallelMath::Less(shapeError, temps.shapeBestError[shapeCollapsedEvalIndex]); + shapeErrorBetter16 = ParallelMath::FloatFlagToInt16(shapeErrorBetter); + + if (ParallelMath::AnySet(shapeErrorBetter16)) + { + bool punchThroughOK = true; + if (needPunchThroughCheck) + { + shapeErrorBetter16 = ParallelMath::AndNot(punchThroughInvalid[pIter], shapeErrorBetter16); + shapeErrorBetter = ParallelMath::Int16FlagToFloat(shapeErrorBetter16); + + if (!ParallelMath::AnySet(shapeErrorBetter16)) + punchThroughOK = false; + } + + if (punchThroughOK) + { + ParallelMath::ConditionalSet(temps.shapeBestError[shapeCollapsedEvalIndex], shapeErrorBetter, shapeError); + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < numRealChannels; ch++) + ParallelMath::ConditionalSet(temps.shapeBestEP[shapeCollapsedEvalIndex][epi][ch], shapeErrorBetter16, ep[epi][ch]); + + for (int pxi = 0; pxi < shapeLength; pxi++) + ParallelMath::ConditionalSet(temps.fragmentBestIndexes[shapeStart + pxi], shapeErrorBetter16, indexes[pxi]); + } + } + + if (refine != numRefineRounds - 1) + epRefiner.GetRefinedEndpointsLDR(ep, numRealChannels, rtn); + } // refine + } // tweak + } // p + + if (flags & cvtt::Flags::BC7_TrySingleColor) + { + MUInt15 total[4]; + for (int ch = 0; ch < 4; ch++) + total[ch] = ParallelMath::MakeUInt15(0); + + for (int pxi = 0; pxi < shapeLength; pxi++) + { + int px = BC7Data::g_fragments[shapeStart + pxi]; + for (int ch = 0; ch < 4; ch++) + total[ch] = total[ch] + pixels[pxi][ch]; + } + + MFloat rcpShapeLength = ParallelMath::MakeFloat(1.0f / static_cast<float>(shapeLength)); + MFloat average[4]; + for (int ch = 0; ch < 4; ch++) + average[ch] = ParallelMath::ToFloat(total[ch]) * rcpShapeLength; + + const uint8_t *fragment = BC7Data::g_fragments + shapeStart; + MFloat &shapeBestError = temps.shapeBestError[shapeCollapsedEvalIndex]; + MUInt15(&shapeBestEP)[2][4] = temps.shapeBestEP[shapeCollapsedEvalIndex]; + MUInt15 *fragmentBestIndexes = temps.fragmentBestIndexes + shapeStart; + + const cvtt::Tables::BC7SC::Table **scTables = NULL; + int numSCTables = 0; + + switch (mode) + { + case 0: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode0_p00_i1, + &cvtt::Tables::BC7SC::g_mode0_p00_i2, + &cvtt::Tables::BC7SC::g_mode0_p00_i3, + &cvtt::Tables::BC7SC::g_mode0_p01_i1, + &cvtt::Tables::BC7SC::g_mode0_p01_i2, + &cvtt::Tables::BC7SC::g_mode0_p01_i3, + &cvtt::Tables::BC7SC::g_mode0_p10_i1, + &cvtt::Tables::BC7SC::g_mode0_p10_i2, + &cvtt::Tables::BC7SC::g_mode0_p10_i3, + &cvtt::Tables::BC7SC::g_mode0_p11_i1, + &cvtt::Tables::BC7SC::g_mode0_p11_i2, + &cvtt::Tables::BC7SC::g_mode0_p11_i3, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + case 1: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode1_p0_i1, + &cvtt::Tables::BC7SC::g_mode1_p0_i2, + &cvtt::Tables::BC7SC::g_mode1_p0_i3, + &cvtt::Tables::BC7SC::g_mode1_p1_i1, + &cvtt::Tables::BC7SC::g_mode1_p1_i2, + &cvtt::Tables::BC7SC::g_mode1_p1_i3, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + case 2: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode2, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + case 3: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode3_p0, + &cvtt::Tables::BC7SC::g_mode3_p1, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + case 6: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode6_p0_i1, + &cvtt::Tables::BC7SC::g_mode6_p0_i2, + &cvtt::Tables::BC7SC::g_mode6_p0_i3, + &cvtt::Tables::BC7SC::g_mode6_p0_i4, + &cvtt::Tables::BC7SC::g_mode6_p0_i5, + &cvtt::Tables::BC7SC::g_mode6_p0_i6, + &cvtt::Tables::BC7SC::g_mode6_p0_i7, + &cvtt::Tables::BC7SC::g_mode6_p1_i1, + &cvtt::Tables::BC7SC::g_mode6_p1_i2, + &cvtt::Tables::BC7SC::g_mode6_p1_i3, + &cvtt::Tables::BC7SC::g_mode6_p1_i4, + &cvtt::Tables::BC7SC::g_mode6_p1_i5, + &cvtt::Tables::BC7SC::g_mode6_p1_i6, + &cvtt::Tables::BC7SC::g_mode6_p1_i7, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + case 7: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode7_p00, + &cvtt::Tables::BC7SC::g_mode7_p01, + &cvtt::Tables::BC7SC::g_mode7_p10, + &cvtt::Tables::BC7SC::g_mode7_p11, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + default: + assert(false); + break; + } + + TrySingleColorRGBAMultiTable(flags, pixels, average, numRealChannels, fragment, shapeLength, staticAlphaError, punchThroughInvalid, shapeBestError, shapeBestEP, fragmentBestIndexes, channelWeightsSq, scTables, numSCTables, rtn); + } + } // shapeIter + + for (uint16_t partition = 0; partition < numPartitions; partition++) + { + const int *partitionShapes; + if (numSubsets == 1) + partitionShapes = BC7Data::g_shapes1[partition]; + else if (numSubsets == 2) + partitionShapes = BC7Data::g_shapes2[partition]; + else + { + assert(numSubsets == 3); + partitionShapes = BC7Data::g_shapes3[partition]; + } + + MFloat totalError = ParallelMath::MakeFloatZero(); + for (int subset = 0; subset < numSubsets; subset++) + totalError = totalError + temps.shapeBestError[shapeCollapseList[partitionShapes[subset]]]; + + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(totalError, work.m_error); + ParallelMath::Int16CompFlag errorBetter16 = ParallelMath::FloatFlagToInt16(errorBetter); + + if (ParallelMath::AnySet(errorBetter16)) + { + for (int subset = 0; subset < numSubsets; subset++) + { + int shape = partitionShapes[subset]; + int shapeStart = BC7Data::g_shapeRanges[shape][0]; + int shapeLength = BC7Data::g_shapeRanges[shape][1]; + int shapeCollapsedEvalIndex = shapeCollapseList[shape]; + + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 4; ch++) + ParallelMath::ConditionalSet(work.m_ep[subset][epi][ch], errorBetter16, temps.shapeBestEP[shapeCollapsedEvalIndex][epi][ch]); + + for (int pxi = 0; pxi < shapeLength; pxi++) + { + int px = BC7Data::g_fragments[shapeStart + pxi]; + ParallelMath::ConditionalSet(work.m_indexes[px], errorBetter16, temps.fragmentBestIndexes[shapeStart + pxi]); + } + } + + work.m_error = ParallelMath::Min(totalError, work.m_error); + ParallelMath::ConditionalSet(work.m_mode, errorBetter16, ParallelMath::MakeUInt15(mode)); + ParallelMath::ConditionalSet(work.m_u.m_partition, errorBetter16, ParallelMath::MakeUInt15(partition)); + } + } + } + } + + static void TryDualPlane(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const float channelWeights[4], int numTweakRounds, int numRefineRounds, WorkInfo& work, const ParallelMath::RoundTowardNearestForScope *rtn) + { + // TODO: These error calculations are not optimal for weight-by-alpha, but this routine needs to be mostly rewritten for that. + // The alpha/color solutions are co-dependent in that case, but a good way to solve it would probably be to + // solve the alpha channel first, then solve the RGB channels, which in turn breaks down into two cases: + // - Separate alpha channel, then weighted RGB + // - Alpha+2 other channels, then the independent channel + + if (!(flags & Flags::BC7_EnableDualPlane)) + return; + + if (numRefineRounds < 1) + numRefineRounds = 1; + + if (numTweakRounds < 1) + numTweakRounds = 1; + else if (numTweakRounds > MaxTweakRounds) + numTweakRounds = MaxTweakRounds; + + float channelWeightsSq[4]; + for (int ch = 0; ch < 4; ch++) + channelWeightsSq[ch] = channelWeights[ch] * channelWeights[ch]; + + for (uint16_t mode = 4; mode <= 5; mode++) + { + for (uint16_t rotation = 0; rotation < 4; rotation++) + { + int alphaChannel = (rotation + 3) & 3; + int redChannel = (rotation == 1) ? 3 : 0; + int greenChannel = (rotation == 2) ? 3 : 1; + int blueChannel = (rotation == 3) ? 3 : 2; + + MUInt15 rotatedRGB[16][3]; + MFloat floatRotatedRGB[16][3]; + + for (int px = 0; px < 16; px++) + { + rotatedRGB[px][0] = pixels[px][redChannel]; + rotatedRGB[px][1] = pixels[px][greenChannel]; + rotatedRGB[px][2] = pixels[px][blueChannel]; + + for (int ch = 0; ch < 3; ch++) + floatRotatedRGB[px][ch] = ParallelMath::ToFloat(rotatedRGB[px][ch]); + } + + uint16_t maxIndexSelector = (mode == 4) ? 2 : 1; + + float rotatedRGBWeights[3] = { channelWeights[redChannel], channelWeights[greenChannel], channelWeights[blueChannel] }; + float rotatedRGBWeightsSq[3] = { channelWeightsSq[redChannel], channelWeightsSq[greenChannel], channelWeightsSq[blueChannel] }; + float rotatedAlphaWeight[1] = { channelWeights[alphaChannel] }; + float rotatedAlphaWeightSq[1] = { channelWeightsSq[alphaChannel] }; + + float uniformWeight[1] = { 1.0f }; // Since the alpha channel is independent, there's no need to bother with weights when doing refinement or selection, only error + + MFloat preWeightedRotatedRGB[16][3]; + BCCommon::PreWeightPixelsLDR<3>(preWeightedRotatedRGB, rotatedRGB, rotatedRGBWeights); + + for (uint16_t indexSelector = 0; indexSelector < maxIndexSelector; indexSelector++) + { + EndpointSelector<3, 8> rgbSelector; + + for (int epPass = 0; epPass < NumEndpointSelectorPasses; epPass++) + { + for (int px = 0; px < 16; px++) + rgbSelector.ContributePass(preWeightedRotatedRGB[px], epPass, ParallelMath::MakeFloat(1.0f)); + + rgbSelector.FinishPass(epPass); + } + + MUInt15 alphaRange[2]; + + alphaRange[0] = alphaRange[1] = pixels[0][alphaChannel]; + for (int px = 1; px < 16; px++) + { + alphaRange[0] = ParallelMath::Min(pixels[px][alphaChannel], alphaRange[0]); + alphaRange[1] = ParallelMath::Max(pixels[px][alphaChannel], alphaRange[1]); + } + + int rgbPrec = 0; + int alphaPrec = 0; + + if (mode == 4) + { + rgbPrec = indexSelector ? 3 : 2; + alphaPrec = indexSelector ? 2 : 3; + } + else + rgbPrec = alphaPrec = 2; + + UnfinishedEndpoints<3> unfinishedRGB = rgbSelector.GetEndpoints(rotatedRGBWeights); + + MFloat bestRGBError = ParallelMath::MakeFloat(FLT_MAX); + MFloat bestAlphaError = ParallelMath::MakeFloat(FLT_MAX); + + MUInt15 bestRGBIndexes[16]; + MUInt15 bestAlphaIndexes[16]; + MUInt15 bestEP[2][4]; + + for (int px = 0; px < 16; px++) + bestRGBIndexes[px] = bestAlphaIndexes[px] = ParallelMath::MakeUInt15(0); + + for (int tweak = 0; tweak < numTweakRounds; tweak++) + { + MUInt15 rgbEP[2][3]; + MUInt15 alphaEP[2]; + + unfinishedRGB.FinishLDR(tweak, 1 << rgbPrec, rgbEP[0], rgbEP[1]); + + TweakAlpha(alphaRange, tweak, 1 << alphaPrec, alphaEP); + + for (int refine = 0; refine < numRefineRounds; refine++) + { + if (mode == 4) + CompressEndpoints4(rgbEP, alphaEP, rtn); + else + CompressEndpoints5(rgbEP, alphaEP, rtn); + + + IndexSelector<1> alphaIndexSelector; + IndexSelector<3> rgbIndexSelector; + + { + MUInt15 alphaEPTemp[2][1] = { { alphaEP[0] },{ alphaEP[1] } }; + alphaIndexSelector.Init<false>(uniformWeight, alphaEPTemp, 1 << alphaPrec); + } + rgbIndexSelector.Init<false>(rotatedRGBWeights, rgbEP, 1 << rgbPrec); + + EndpointRefiner<3> rgbRefiner; + EndpointRefiner<1> alphaRefiner; + + rgbRefiner.Init(1 << rgbPrec, rotatedRGBWeights); + alphaRefiner.Init(1 << alphaPrec, uniformWeight); + + MFloat errorRGB = ParallelMath::MakeFloatZero(); + MFloat errorA = ParallelMath::MakeFloatZero(); + + MUInt15 rgbIndexes[16]; + MUInt15 alphaIndexes[16]; + + AggregatedError<3> rgbAggError; + AggregatedError<1> alphaAggError; + + for (int px = 0; px < 16; px++) + { + MUInt15 rgbIndex = rgbIndexSelector.SelectIndexLDR(floatRotatedRGB[px], rtn); + MUInt15 alphaIndex = alphaIndexSelector.SelectIndexLDR(floatPixels[px] + alphaChannel, rtn); + + MUInt15 reconstructedRGB[3]; + MUInt15 reconstructedAlpha[1]; + + rgbIndexSelector.ReconstructLDR_BC7(rgbIndex, reconstructedRGB); + alphaIndexSelector.ReconstructLDR_BC7(alphaIndex, reconstructedAlpha); + + if (flags & cvtt::Flags::BC7_FastIndexing) + { + BCCommon::ComputeErrorLDR<3>(flags, reconstructedRGB, rotatedRGB[px], rgbAggError); + BCCommon::ComputeErrorLDR<1>(flags, reconstructedAlpha, pixels[px] + alphaChannel, alphaAggError); + } + else + { + AggregatedError<3> baseRGBAggError; + AggregatedError<1> baseAlphaAggError; + + BCCommon::ComputeErrorLDR<3>(flags, reconstructedRGB, rotatedRGB[px], baseRGBAggError); + BCCommon::ComputeErrorLDR<1>(flags, reconstructedAlpha, pixels[px] + alphaChannel, baseAlphaAggError); + + MFloat rgbError = baseRGBAggError.Finalize(flags, rotatedRGBWeightsSq); + MFloat alphaError = baseAlphaAggError.Finalize(flags, rotatedAlphaWeightSq); + + MUInt15 altRGBIndexes[2]; + MUInt15 altAlphaIndexes[2]; + + altRGBIndexes[0] = ParallelMath::Max(rgbIndex, ParallelMath::MakeUInt15(1)) - ParallelMath::MakeUInt15(1); + altRGBIndexes[1] = ParallelMath::Min(rgbIndex + ParallelMath::MakeUInt15(1), ParallelMath::MakeUInt15(static_cast<uint16_t>((1 << rgbPrec) - 1))); + + altAlphaIndexes[0] = ParallelMath::Max(alphaIndex, ParallelMath::MakeUInt15(1)) - ParallelMath::MakeUInt15(1); + altAlphaIndexes[1] = ParallelMath::Min(alphaIndex + ParallelMath::MakeUInt15(1), ParallelMath::MakeUInt15(static_cast<uint16_t>((1 << alphaPrec) - 1))); + + for (int ii = 0; ii < 2; ii++) + { + rgbIndexSelector.ReconstructLDR_BC7(altRGBIndexes[ii], reconstructedRGB); + alphaIndexSelector.ReconstructLDR_BC7(altAlphaIndexes[ii], reconstructedAlpha); + + AggregatedError<3> altRGBAggError; + AggregatedError<1> altAlphaAggError; + + BCCommon::ComputeErrorLDR<3>(flags, reconstructedRGB, rotatedRGB[px], altRGBAggError); + BCCommon::ComputeErrorLDR<1>(flags, reconstructedAlpha, pixels[px] + alphaChannel, altAlphaAggError); + + MFloat altRGBError = altRGBAggError.Finalize(flags, rotatedRGBWeightsSq); + MFloat altAlphaError = altAlphaAggError.Finalize(flags, rotatedAlphaWeightSq); + + ParallelMath::Int16CompFlag rgbBetter = ParallelMath::FloatFlagToInt16(ParallelMath::Less(altRGBError, rgbError)); + ParallelMath::Int16CompFlag alphaBetter = ParallelMath::FloatFlagToInt16(ParallelMath::Less(altAlphaError, alphaError)); + + rgbError = ParallelMath::Min(altRGBError, rgbError); + alphaError = ParallelMath::Min(altAlphaError, alphaError); + + ParallelMath::ConditionalSet(rgbIndex, rgbBetter, altRGBIndexes[ii]); + ParallelMath::ConditionalSet(alphaIndex, alphaBetter, altAlphaIndexes[ii]); + } + + errorRGB = errorRGB + rgbError; + errorA = errorA + alphaError; + } + + if (refine != numRefineRounds - 1) + { + rgbRefiner.ContributeUnweightedPW(preWeightedRotatedRGB[px], rgbIndex); + alphaRefiner.ContributeUnweightedPW(floatPixels[px] + alphaChannel, alphaIndex); + } + + if (flags & Flags::BC7_FastIndexing) + { + errorRGB = rgbAggError.Finalize(flags, rotatedRGBWeightsSq); + errorA = rgbAggError.Finalize(flags, rotatedAlphaWeightSq); + } + + rgbIndexes[px] = rgbIndex; + alphaIndexes[px] = alphaIndex; + } + + ParallelMath::FloatCompFlag rgbBetter = ParallelMath::Less(errorRGB, bestRGBError); + ParallelMath::FloatCompFlag alphaBetter = ParallelMath::Less(errorA, bestAlphaError); + + ParallelMath::Int16CompFlag rgbBetterInt16 = ParallelMath::FloatFlagToInt16(rgbBetter); + ParallelMath::Int16CompFlag alphaBetterInt16 = ParallelMath::FloatFlagToInt16(alphaBetter); + + if (ParallelMath::AnySet(rgbBetterInt16)) + { + bestRGBError = ParallelMath::Min(errorRGB, bestRGBError); + + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestRGBIndexes[px], rgbBetterInt16, rgbIndexes[px]); + + for (int ep = 0; ep < 2; ep++) + { + for (int ch = 0; ch < 3; ch++) + ParallelMath::ConditionalSet(bestEP[ep][ch], rgbBetterInt16, rgbEP[ep][ch]); + } + } + + if (ParallelMath::AnySet(alphaBetterInt16)) + { + bestAlphaError = ParallelMath::Min(errorA, bestAlphaError); + + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestAlphaIndexes[px], alphaBetterInt16, alphaIndexes[px]); + + for (int ep = 0; ep < 2; ep++) + ParallelMath::ConditionalSet(bestEP[ep][3], alphaBetterInt16, alphaEP[ep]); + } + + if (refine != numRefineRounds - 1) + { + rgbRefiner.GetRefinedEndpointsLDR(rgbEP, rtn); + + MUInt15 alphaEPTemp[2][1]; + alphaRefiner.GetRefinedEndpointsLDR(alphaEPTemp, rtn); + + for (int i = 0; i < 2; i++) + alphaEP[i] = alphaEPTemp[i][0]; + } + } // refine + } // tweak + + MFloat combinedError = bestRGBError + bestAlphaError; + + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(combinedError, work.m_error); + ParallelMath::Int16CompFlag errorBetter16 = ParallelMath::FloatFlagToInt16(errorBetter); + + work.m_error = ParallelMath::Min(combinedError, work.m_error); + + ParallelMath::ConditionalSet(work.m_mode, errorBetter16, ParallelMath::MakeUInt15(mode)); + ParallelMath::ConditionalSet(work.m_u.m_isr.m_rotation, errorBetter16, ParallelMath::MakeUInt15(rotation)); + ParallelMath::ConditionalSet(work.m_u.m_isr.m_indexSelector, errorBetter16, ParallelMath::MakeUInt15(indexSelector)); + + for (int px = 0; px < 16; px++) + { + ParallelMath::ConditionalSet(work.m_indexes[px], errorBetter16, indexSelector ? bestAlphaIndexes[px] : bestRGBIndexes[px]); + ParallelMath::ConditionalSet(work.m_indexes2[px], errorBetter16, indexSelector ? bestRGBIndexes[px] : bestAlphaIndexes[px]); + } + + for (int ep = 0; ep < 2; ep++) + for (int ch = 0; ch < 4; ch++) + ParallelMath::ConditionalSet(work.m_ep[0][ep][ch], errorBetter16, bestEP[ep][ch]); + } + } + } + } + + template<class T> + static void Swap(T& a, T& b) + { + T temp = a; + a = b; + b = temp; + } + + static void Pack(uint32_t flags, const PixelBlockU8* inputs, uint8_t* packedBlocks, const float channelWeights[4], int numTweakRounds, int numRefineRounds) + { + MUInt15 pixels[16][4]; + MFloat floatPixels[16][4]; + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 4; ch++) + ParallelMath::ConvertLDRInputs(inputs, px, ch, pixels[px][ch]); + } + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 4; ch++) + floatPixels[px][ch] = ParallelMath::ToFloat(pixels[px][ch]); + } + + WorkInfo work; + memset(&work, 0, sizeof(work)); + + work.m_error = ParallelMath::MakeFloat(FLT_MAX); + + { + ParallelMath::RoundTowardNearestForScope rtn; + TrySinglePlane(flags, pixels, floatPixels, channelWeights, numTweakRounds, numRefineRounds, work, &rtn); + TryDualPlane(flags, pixels, floatPixels, channelWeights, numTweakRounds, numRefineRounds, work, &rtn); + } + + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + PackingVector pv; + pv.Init(); + + ParallelMath::ScalarUInt16 mode = ParallelMath::Extract(work.m_mode, block); + ParallelMath::ScalarUInt16 partition = ParallelMath::Extract(work.m_u.m_partition, block); + ParallelMath::ScalarUInt16 indexSelector = ParallelMath::Extract(work.m_u.m_isr.m_indexSelector, block); + + const BC7Data::BC7ModeInfo& modeInfo = BC7Data::g_modes[mode]; + + ParallelMath::ScalarUInt16 indexes[16]; + ParallelMath::ScalarUInt16 indexes2[16]; + ParallelMath::ScalarUInt16 endPoints[3][2][4]; + + for (int i = 0; i < 16; i++) + { + indexes[i] = ParallelMath::Extract(work.m_indexes[i], block); + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + indexes2[i] = ParallelMath::Extract(work.m_indexes2[i], block); + } + + for (int subset = 0; subset < 3; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + for (int ch = 0; ch < 4; ch++) + endPoints[subset][ep][ch] = ParallelMath::Extract(work.m_ep[subset][ep][ch], block); + } + } + + int fixups[3] = { 0, 0, 0 }; + + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + { + bool flipRGB = ((indexes[0] & (1 << (modeInfo.m_indexBits - 1))) != 0); + bool flipAlpha = ((indexes2[0] & (1 << (modeInfo.m_alphaIndexBits - 1))) != 0); + + if (flipRGB) + { + uint16_t highIndex = (1 << modeInfo.m_indexBits) - 1; + for (int px = 0; px < 16; px++) + indexes[px] = highIndex - indexes[px]; + } + + if (flipAlpha) + { + uint16_t highIndex = (1 << modeInfo.m_alphaIndexBits) - 1; + for (int px = 0; px < 16; px++) + indexes2[px] = highIndex - indexes2[px]; + } + + if (indexSelector) + Swap(flipRGB, flipAlpha); + + if (flipRGB) + { + for (int ch = 0; ch < 3; ch++) + Swap(endPoints[0][0][ch], endPoints[0][1][ch]); + } + if (flipAlpha) + Swap(endPoints[0][0][3], endPoints[0][1][3]); + + } + else + { + if (modeInfo.m_numSubsets == 2) + fixups[1] = BC7Data::g_fixupIndexes2[partition]; + else if (modeInfo.m_numSubsets == 3) + { + fixups[1] = BC7Data::g_fixupIndexes3[partition][0]; + fixups[2] = BC7Data::g_fixupIndexes3[partition][1]; + } + + bool flip[3] = { false, false, false }; + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + flip[subset] = ((indexes[fixups[subset]] & (1 << (modeInfo.m_indexBits - 1))) != 0); + + if (flip[0] || flip[1] || flip[2]) + { + uint16_t highIndex = (1 << modeInfo.m_indexBits) - 1; + for (int px = 0; px < 16; px++) + { + int subset = 0; + if (modeInfo.m_numSubsets == 2) + subset = (BC7Data::g_partitionMap[partition] >> px) & 1; + else if (modeInfo.m_numSubsets == 3) + subset = (BC7Data::g_partitionMap2[partition] >> (px * 2)) & 3; + + if (flip[subset]) + indexes[px] = highIndex - indexes[px]; + } + + int maxCH = (modeInfo.m_alphaMode == BC7Data::AlphaMode_Combined) ? 4 : 3; + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + if (flip[subset]) + for (int ch = 0; ch < maxCH; ch++) + Swap(endPoints[subset][0][ch], endPoints[subset][1][ch]); + } + } + } + + pv.Pack(static_cast<uint8_t>(1 << mode), mode + 1); + + if (modeInfo.m_partitionBits) + pv.Pack(partition, modeInfo.m_partitionBits); + + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + { + ParallelMath::ScalarUInt16 rotation = ParallelMath::Extract(work.m_u.m_isr.m_rotation, block); + pv.Pack(rotation, 2); + } + + if (modeInfo.m_hasIndexSelector) + pv.Pack(indexSelector, 1); + + // Encode RGB + for (int ch = 0; ch < 3; ch++) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + ParallelMath::ScalarUInt16 epPart = endPoints[subset][ep][ch]; + epPart >>= (8 - modeInfo.m_rgbBits); + + pv.Pack(epPart, modeInfo.m_rgbBits); + } + } + } + + // Encode alpha + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + ParallelMath::ScalarUInt16 epPart = endPoints[subset][ep][3]; + epPart >>= (8 - modeInfo.m_alphaBits); + + pv.Pack(epPart, modeInfo.m_alphaBits); + } + } + } + + // Encode parity bits + if (modeInfo.m_pBitMode == BC7Data::PBitMode_PerSubset) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + ParallelMath::ScalarUInt16 epPart = endPoints[subset][0][0]; + epPart >>= (7 - modeInfo.m_rgbBits); + epPart &= 1; + + pv.Pack(epPart, 1); + } + } + else if (modeInfo.m_pBitMode == BC7Data::PBitMode_PerEndpoint) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + ParallelMath::ScalarUInt16 epPart = endPoints[subset][ep][0]; + epPart >>= (7 - modeInfo.m_rgbBits); + epPart &= 1; + + pv.Pack(epPart, 1); + } + } + } + + // Encode indexes + for (int px = 0; px < 16; px++) + { + int bits = modeInfo.m_indexBits; + if ((px == 0) || (px == fixups[1]) || (px == fixups[2])) + bits--; + + pv.Pack(indexes[px], bits); + } + + // Encode secondary indexes + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + { + for (int px = 0; px < 16; px++) + { + int bits = modeInfo.m_alphaIndexBits; + if (px == 0) + bits--; + + pv.Pack(indexes2[px], bits); + } + } + + pv.Flush(packedBlocks); + + packedBlocks += 16; + } + } + + static void UnpackOne(PixelBlockU8 &output, const uint8_t* packedBlock) + { + UnpackingVector pv; + pv.Init(packedBlock); + + int mode = 8; + for (int i = 0; i < 8; i++) + { + if (pv.Unpack(1) == 1) + { + mode = i; + break; + } + } + + if (mode > 7) + { + for (int px = 0; px < 16; px++) + for (int ch = 0; ch < 4; ch++) + output.m_pixels[px][ch] = 0; + + return; + } + + const BC7Data::BC7ModeInfo &modeInfo = BC7Data::g_modes[mode]; + + int partition = 0; + if (modeInfo.m_partitionBits) + partition = pv.Unpack(modeInfo.m_partitionBits); + + int rotation = 0; + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + rotation = pv.Unpack(2); + + int indexSelector = 0; + if (modeInfo.m_hasIndexSelector) + indexSelector = pv.Unpack(1); + + // Resolve fixups + int fixups[3] = { 0, 0, 0 }; + + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_Separate) + { + if (modeInfo.m_numSubsets == 2) + fixups[1] = BC7Data::g_fixupIndexes2[partition]; + else if (modeInfo.m_numSubsets == 3) + { + fixups[1] = BC7Data::g_fixupIndexes3[partition][0]; + fixups[2] = BC7Data::g_fixupIndexes3[partition][1]; + } + } + + int endPoints[3][2][4]; + + // Decode RGB + for (int ch = 0; ch < 3; ch++) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + endPoints[subset][ep][ch] = (pv.Unpack(modeInfo.m_rgbBits) << (8 - modeInfo.m_rgbBits)); + } + } + + // Decode alpha + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + endPoints[subset][ep][3] = (pv.Unpack(modeInfo.m_alphaBits) << (8 - modeInfo.m_alphaBits)); + } + } + else + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + endPoints[subset][ep][3] = 255; + } + } + + int parityBits = 0; + + // Decode parity bits + if (modeInfo.m_pBitMode == BC7Data::PBitMode_PerSubset) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + int p = pv.Unpack(1); + + for (int ep = 0; ep < 2; ep++) + { + for (int ch = 0; ch < 3; ch++) + endPoints[subset][ep][ch] |= p << (7 - modeInfo.m_rgbBits); + + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + endPoints[subset][ep][3] |= p << (7 - modeInfo.m_alphaBits); + } + } + + parityBits = 1; + } + else if (modeInfo.m_pBitMode == BC7Data::PBitMode_PerEndpoint) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + int p = pv.Unpack(1); + + for (int ch = 0; ch < 3; ch++) + endPoints[subset][ep][ch] |= p << (7 - modeInfo.m_rgbBits); + + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + endPoints[subset][ep][3] |= p << (7 - modeInfo.m_alphaBits); + } + } + + parityBits = 1; + } + + // Fill endpoint bits + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + for (int ch = 0; ch < 3; ch++) + endPoints[subset][ep][ch] |= (endPoints[subset][ep][ch] >> (modeInfo.m_rgbBits + parityBits)); + + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + endPoints[subset][ep][3] |= (endPoints[subset][ep][3] >> (modeInfo.m_alphaBits + parityBits)); + } + } + + int indexes[16]; + int indexes2[16]; + + // Decode indexes + for (int px = 0; px < 16; px++) + { + int bits = modeInfo.m_indexBits; + if ((px == 0) || (px == fixups[1]) || (px == fixups[2])) + bits--; + + indexes[px] = pv.Unpack(bits); + } + + // Decode secondary indexes + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + { + for (int px = 0; px < 16; px++) + { + int bits = modeInfo.m_alphaIndexBits; + if (px == 0) + bits--; + + indexes2[px] = pv.Unpack(bits); + } + } + else + { + for (int px = 0; px < 16; px++) + indexes2[px] = 0; + } + + const int *alphaWeights = BC7Data::g_weightTables[modeInfo.m_alphaIndexBits]; + const int *rgbWeights = BC7Data::g_weightTables[modeInfo.m_indexBits]; + + // Decode each pixel + for (int px = 0; px < 16; px++) + { + int rgbWeight = 0; + int alphaWeight = 0; + + int rgbIndex = indexes[px]; + + rgbWeight = rgbWeights[indexes[px]]; + + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Combined) + alphaWeight = rgbWeight; + else if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + alphaWeight = alphaWeights[indexes2[px]]; + + if (indexSelector == 1) + { + int temp = rgbWeight; + rgbWeight = alphaWeight; + alphaWeight = temp; + } + + int pixel[4] = { 0, 0, 0, 255 }; + + int subset = 0; + + if (modeInfo.m_numSubsets == 2) + subset = (BC7Data::g_partitionMap[partition] >> px) & 1; + else if (modeInfo.m_numSubsets == 3) + subset = (BC7Data::g_partitionMap2[partition] >> (px * 2)) & 3; + + for (int ch = 0; ch < 3; ch++) + pixel[ch] = ((64 - rgbWeight) * endPoints[subset][0][ch] + rgbWeight * endPoints[subset][1][ch] + 32) >> 6; + + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + pixel[3] = ((64 - alphaWeight) * endPoints[subset][0][3] + alphaWeight * endPoints[subset][1][3] + 32) >> 6; + + if (rotation != 0) + { + int ch = rotation - 1; + int temp = pixel[ch]; + pixel[ch] = pixel[3]; + pixel[3] = temp; + } + + for (int ch = 0; ch < 4; ch++) + output.m_pixels[px][ch] = static_cast<uint8_t>(pixel[ch]); + } + } + }; + + class BC6HComputer + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::AInt16 MAInt16; + typedef ParallelMath::SInt32 MSInt32; + typedef ParallelMath::UInt31 MUInt31; + + static const int MaxTweakRounds = 4; + static const int MaxRefineRounds = 3; + + static MSInt16 QuantizeSingleEndpointElementSigned(const MSInt16 &elem2CL, int precision, const ParallelMath::RoundUpForScope* ru) + { + assert(ParallelMath::AllSet(ParallelMath::Less(elem2CL, ParallelMath::MakeSInt16(31744)))); + assert(ParallelMath::AllSet(ParallelMath::Less(ParallelMath::MakeSInt16(-31744), elem2CL))); + + // Expand to full range + ParallelMath::Int16CompFlag isNegative = ParallelMath::Less(elem2CL, ParallelMath::MakeSInt16(0)); + MUInt15 absElem = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::Select(isNegative, ParallelMath::MakeSInt16(0) - elem2CL, elem2CL)); + + absElem = ParallelMath::RightShift(ParallelMath::RoundAndConvertToU15(ParallelMath::ToFloat(absElem) * 32.0f / 31.0f, ru), 16 - precision); + + MSInt16 absElemS16 = ParallelMath::LosslessCast<MSInt16>::Cast(absElem); + + return ParallelMath::Select(isNegative, ParallelMath::MakeSInt16(0) - absElemS16, absElemS16); + } + + static MUInt15 QuantizeSingleEndpointElementUnsigned(const MUInt15 &elem, int precision, const ParallelMath::RoundUpForScope* ru) + { + MUInt16 expandedElem = ParallelMath::RoundAndConvertToU16(ParallelMath::Min(ParallelMath::ToFloat(elem) * 64.0f / 31.0f, ParallelMath::MakeFloat(65535.0f)), ru); + return ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(expandedElem, 16 - precision)); + } + + static void UnquantizeSingleEndpointElementSigned(const MSInt16 &comp, int precision, MSInt16 &outUnquantized, MSInt16 &outUnquantizedFinished2CL) + { + MSInt16 zero = ParallelMath::MakeSInt16(0); + + ParallelMath::Int16CompFlag negative = ParallelMath::Less(comp, zero); + MUInt15 absComp = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::Select(negative, MSInt16(zero - comp), comp)); + + MSInt16 unq; + MUInt15 absUnq; + + if (precision >= 16) + { + unq = comp; + absUnq = absComp; + } + else + { + MSInt16 maxCompMinusOne = ParallelMath::MakeSInt16(static_cast<int16_t>((1 << (precision - 1)) - 2)); + ParallelMath::Int16CompFlag isZero = ParallelMath::Equal(comp, zero); + ParallelMath::Int16CompFlag isMax = ParallelMath::Less(maxCompMinusOne, comp); + + absUnq = (absComp << (16 - precision)) + ParallelMath::MakeUInt15(static_cast<uint16_t>(0x4000 >> (precision - 1))); + ParallelMath::ConditionalSet(absUnq, isZero, ParallelMath::MakeUInt15(0)); + ParallelMath::ConditionalSet(absUnq, isMax, ParallelMath::MakeUInt15(0x7fff)); + + unq = ParallelMath::ConditionalNegate(negative, ParallelMath::LosslessCast<MSInt16>::Cast(absUnq)); + } + + outUnquantized = unq; + + MUInt15 funq = ParallelMath::ToUInt15(ParallelMath::RightShift(ParallelMath::XMultiply(absUnq, ParallelMath::MakeUInt15(31)), 5)); + + outUnquantizedFinished2CL = ParallelMath::ConditionalNegate(negative, ParallelMath::LosslessCast<MSInt16>::Cast(funq)); + } + + static void UnquantizeSingleEndpointElementUnsigned(const MUInt15 &comp, int precision, MUInt16 &outUnquantized, MUInt16 &outUnquantizedFinished) + { + MUInt16 unq = ParallelMath::LosslessCast<MUInt16>::Cast(comp); + if (precision < 15) + { + MUInt15 zero = ParallelMath::MakeUInt15(0); + MUInt15 maxCompMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>((1 << precision) - 2)); + + ParallelMath::Int16CompFlag isZero = ParallelMath::Equal(comp, zero); + ParallelMath::Int16CompFlag isMax = ParallelMath::Less(maxCompMinusOne, comp); + + unq = (ParallelMath::LosslessCast<MUInt16>::Cast(comp) << (16 - precision)) + ParallelMath::MakeUInt16(static_cast<uint16_t>(0x8000 >> precision)); + + ParallelMath::ConditionalSet(unq, isZero, ParallelMath::MakeUInt16(0)); + ParallelMath::ConditionalSet(unq, isMax, ParallelMath::MakeUInt16(0xffff)); + } + + outUnquantized = unq; + outUnquantizedFinished = ParallelMath::ToUInt16(ParallelMath::RightShift(ParallelMath::XMultiply(unq, ParallelMath::MakeUInt15(31)), 6)); + } + + static void QuantizeEndpointsSigned(const MSInt16 endPoints[2][3], const MFloat floatPixelsColorSpace[16][3], const MFloat floatPixelsLinearWeighted[16][3], MAInt16 quantizedEndPoints[2][3], MUInt15 indexes[16], IndexSelectorHDR<3> &indexSelector, int fixupIndex, int precision, int indexRange, const float *channelWeights, bool fastIndexing, const ParallelMath::RoundTowardNearestForScope *rtn) + { + MSInt16 unquantizedEP[2][3]; + MSInt16 finishedUnquantizedEP[2][3]; + + { + ParallelMath::RoundUpForScope ru; + + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + { + MSInt16 qee = QuantizeSingleEndpointElementSigned(endPoints[epi][ch], precision, &ru); + UnquantizeSingleEndpointElementSigned(qee, precision, unquantizedEP[epi][ch], finishedUnquantizedEP[epi][ch]); + quantizedEndPoints[epi][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(qee); + } + } + } + + indexSelector.Init(channelWeights, unquantizedEP, finishedUnquantizedEP, indexRange); + indexSelector.InitHDR(indexRange, true, fastIndexing, channelWeights); + + MUInt15 halfRangeMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>(indexRange / 2) - 1); + + MUInt15 index = fastIndexing ? indexSelector.SelectIndexHDRFast(floatPixelsColorSpace[fixupIndex], rtn) : indexSelector.SelectIndexHDRSlow(floatPixelsLinearWeighted[fixupIndex], rtn); + + ParallelMath::Int16CompFlag invert = ParallelMath::Less(halfRangeMinusOne, index); + + if (ParallelMath::AnySet(invert)) + { + ParallelMath::ConditionalSet(index, invert, MUInt15(ParallelMath::MakeUInt15(static_cast<uint16_t>(indexRange - 1)) - index)); + + indexSelector.ConditionalInvert(invert); + + for (int ch = 0; ch < 3; ch++) + { + MAInt16 firstEP = quantizedEndPoints[0][ch]; + MAInt16 secondEP = quantizedEndPoints[1][ch]; + + quantizedEndPoints[0][ch] = ParallelMath::Select(invert, secondEP, firstEP); + quantizedEndPoints[1][ch] = ParallelMath::Select(invert, firstEP, secondEP); + } + } + + indexes[fixupIndex] = index; + } + + static void QuantizeEndpointsUnsigned(const MSInt16 endPoints[2][3], const MFloat floatPixelsColorSpace[16][3], const MFloat floatPixelsLinearWeighted[16][3], MAInt16 quantizedEndPoints[2][3], MUInt15 indexes[16], IndexSelectorHDR<3> &indexSelector, int fixupIndex, int precision, int indexRange, const float *channelWeights, bool fastIndexing, const ParallelMath::RoundTowardNearestForScope *rtn) + { + MUInt16 unquantizedEP[2][3]; + MUInt16 finishedUnquantizedEP[2][3]; + + { + ParallelMath::RoundUpForScope ru; + + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + { + MUInt15 qee = QuantizeSingleEndpointElementUnsigned(ParallelMath::LosslessCast<MUInt15>::Cast(endPoints[epi][ch]), precision, &ru); + UnquantizeSingleEndpointElementUnsigned(qee, precision, unquantizedEP[epi][ch], finishedUnquantizedEP[epi][ch]); + quantizedEndPoints[epi][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(qee); + } + } + } + + indexSelector.Init(channelWeights, unquantizedEP, finishedUnquantizedEP, indexRange); + indexSelector.InitHDR(indexRange, false, fastIndexing, channelWeights); + + MUInt15 halfRangeMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>(indexRange / 2) - 1); + + MUInt15 index = fastIndexing ? indexSelector.SelectIndexHDRFast(floatPixelsColorSpace[fixupIndex], rtn) : indexSelector.SelectIndexHDRSlow(floatPixelsLinearWeighted[fixupIndex], rtn); + + ParallelMath::Int16CompFlag invert = ParallelMath::Less(halfRangeMinusOne, index); + + if (ParallelMath::AnySet(invert)) + { + ParallelMath::ConditionalSet(index, invert, MUInt15(ParallelMath::MakeUInt15(static_cast<uint16_t>(indexRange - 1)) - index)); + + indexSelector.ConditionalInvert(invert); + + for (int ch = 0; ch < 3; ch++) + { + MAInt16 firstEP = quantizedEndPoints[0][ch]; + MAInt16 secondEP = quantizedEndPoints[1][ch]; + + quantizedEndPoints[0][ch] = ParallelMath::Select(invert, secondEP, firstEP); + quantizedEndPoints[1][ch] = ParallelMath::Select(invert, firstEP, secondEP); + } + } + + indexes[fixupIndex] = index; + } + + static void EvaluatePartitionedLegality(const MAInt16 ep0[2][3], const MAInt16 ep1[2][3], int aPrec, const int bPrec[3], bool isTransformed, MAInt16 outEncodedEPs[2][2][3], ParallelMath::Int16CompFlag& outIsLegal) + { + ParallelMath::Int16CompFlag allLegal = ParallelMath::MakeBoolInt16(true); + + MAInt16 aSignificantMask = ParallelMath::MakeAInt16(static_cast<int16_t>((1 << aPrec) - 1)); + + for (int ch = 0; ch < 3; ch++) + { + outEncodedEPs[0][0][ch] = ep0[0][ch]; + outEncodedEPs[0][1][ch] = ep0[1][ch]; + outEncodedEPs[1][0][ch] = ep1[0][ch]; + outEncodedEPs[1][1][ch] = ep1[1][ch]; + + if (isTransformed) + { + for (int subset = 0; subset < 2; subset++) + { + for (int epi = 0; epi < 2; epi++) + { + if (epi == 0 && subset == 0) + continue; + + MAInt16 bReduced = (outEncodedEPs[subset][epi][ch] & aSignificantMask); + + MSInt16 delta = ParallelMath::TruncateToPrecisionSigned(ParallelMath::LosslessCast<MSInt16>::Cast(ParallelMath::AbstractSubtract(outEncodedEPs[subset][epi][ch], outEncodedEPs[0][0][ch])), bPrec[ch]); + + outEncodedEPs[subset][epi][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(delta); + + MAInt16 reconstructed = (ParallelMath::AbstractAdd(outEncodedEPs[subset][epi][ch], outEncodedEPs[0][0][ch]) & aSignificantMask); + allLegal = allLegal & ParallelMath::Equal(reconstructed, bReduced); + } + } + } + + if (!ParallelMath::AnySet(allLegal)) + break; + } + + outIsLegal = allLegal; + } + + static void EvaluateSingleLegality(const MAInt16 ep[2][3], int aPrec, const int bPrec[3], bool isTransformed, MAInt16 outEncodedEPs[2][3], ParallelMath::Int16CompFlag& outIsLegal) + { + ParallelMath::Int16CompFlag allLegal = ParallelMath::MakeBoolInt16(true); + + MAInt16 aSignificantMask = ParallelMath::MakeAInt16(static_cast<int16_t>((1 << aPrec) - 1)); + + for (int ch = 0; ch < 3; ch++) + { + outEncodedEPs[0][ch] = ep[0][ch]; + outEncodedEPs[1][ch] = ep[1][ch]; + + if (isTransformed) + { + MAInt16 bReduced = (outEncodedEPs[1][ch] & aSignificantMask); + + MSInt16 delta = ParallelMath::TruncateToPrecisionSigned(ParallelMath::LosslessCast<MSInt16>::Cast(ParallelMath::AbstractSubtract(outEncodedEPs[1][ch], outEncodedEPs[0][ch])), bPrec[ch]); + + outEncodedEPs[1][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(delta); + + MAInt16 reconstructed = (ParallelMath::AbstractAdd(outEncodedEPs[1][ch], outEncodedEPs[0][ch]) & aSignificantMask); + allLegal = allLegal & ParallelMath::Equal(reconstructed, bReduced); + } + } + + outIsLegal = allLegal; + } + + static void Pack(uint32_t flags, const PixelBlockF16* inputs, uint8_t* packedBlocks, const float channelWeights[4], bool isSigned, int numTweakRounds, int numRefineRounds) + { + if (numTweakRounds < 1) + numTweakRounds = 1; + else if (numTweakRounds > MaxTweakRounds) + numTweakRounds = MaxTweakRounds; + + if (numRefineRounds < 1) + numRefineRounds = 1; + else if (numRefineRounds > MaxRefineRounds) + numRefineRounds = MaxRefineRounds; + + bool fastIndexing = (flags & cvtt::Flags::BC6H_FastIndexing); + float channelWeightsSq[3]; + + ParallelMath::RoundTowardNearestForScope rtn; + + MSInt16 pixels[16][3]; + MFloat floatPixels2CL[16][3]; + MFloat floatPixelsLinearWeighted[16][3]; + + MSInt16 low15Bits = ParallelMath::MakeSInt16(32767); + + for (int ch = 0; ch < 3; ch++) + channelWeightsSq[ch] = channelWeights[ch] * channelWeights[ch]; + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 3; ch++) + { + MSInt16 pixelValue; + ParallelMath::ConvertHDRInputs(inputs, px, ch, pixelValue); + + // Convert from sign+magnitude to 2CL + if (isSigned) + { + ParallelMath::Int16CompFlag negative = ParallelMath::Less(pixelValue, ParallelMath::MakeSInt16(0)); + MSInt16 magnitude = (pixelValue & low15Bits); + ParallelMath::ConditionalSet(pixelValue, negative, ParallelMath::MakeSInt16(0) - magnitude); + pixelValue = ParallelMath::Max(pixelValue, ParallelMath::MakeSInt16(-31743)); + } + else + pixelValue = ParallelMath::Max(pixelValue, ParallelMath::MakeSInt16(0)); + + pixelValue = ParallelMath::Min(pixelValue, ParallelMath::MakeSInt16(31743)); + + pixels[px][ch] = pixelValue; + floatPixels2CL[px][ch] = ParallelMath::ToFloat(pixelValue); + floatPixelsLinearWeighted[px][ch] = ParallelMath::TwosCLHalfToFloat(pixelValue) * channelWeights[ch]; + } + } + + MFloat preWeightedPixels[16][3]; + + BCCommon::PreWeightPixelsHDR<3>(preWeightedPixels, pixels, channelWeights); + + MAInt16 bestEndPoints[2][2][3]; + MUInt15 bestIndexes[16]; + MFloat bestError = ParallelMath::MakeFloat(FLT_MAX); + MUInt15 bestMode = ParallelMath::MakeUInt15(0); + MUInt15 bestPartition = ParallelMath::MakeUInt15(0); + + for (int px = 0; px < 16; px++) + bestIndexes[px] = ParallelMath::MakeUInt15(0); + + for (int subset = 0; subset < 2; subset++) + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 3; ch++) + bestEndPoints[subset][epi][ch] = ParallelMath::MakeAInt16(0); + + UnfinishedEndpoints<3> partitionedUFEP[32][2]; + UnfinishedEndpoints<3> singleUFEP; + + // Generate UFEP for partitions + for (int p = 0; p < 32; p++) + { + int partitionMask = BC7Data::g_partitionMap[p]; + + EndpointSelector<3, 8> epSelectors[2]; + + for (int pass = 0; pass < NumEndpointSelectorPasses; pass++) + { + for (int px = 0; px < 16; px++) + { + int subset = (partitionMask >> px) & 1; + epSelectors[subset].ContributePass(preWeightedPixels[px], pass, ParallelMath::MakeFloat(1.0f)); + } + + for (int subset = 0; subset < 2; subset++) + epSelectors[subset].FinishPass(pass); + } + + for (int subset = 0; subset < 2; subset++) + partitionedUFEP[p][subset] = epSelectors[subset].GetEndpoints(channelWeights); + } + + // Generate UFEP for single + { + EndpointSelector<3, 8> epSelector; + + for (int pass = 0; pass < NumEndpointSelectorPasses; pass++) + { + for (int px = 0; px < 16; px++) + epSelector.ContributePass(preWeightedPixels[px], pass, ParallelMath::MakeFloat(1.0f)); + + epSelector.FinishPass(pass); + } + + singleUFEP = epSelector.GetEndpoints(channelWeights); + } + + for (int partitionedInt = 0; partitionedInt < 2; partitionedInt++) + { + bool partitioned = (partitionedInt == 1); + + for (int aPrec = BC7Data::g_maxHDRPrecision; aPrec >= 0; aPrec--) + { + if (!BC7Data::g_hdrModesExistForPrecision[partitionedInt][aPrec]) + continue; + + int numPartitions = partitioned ? 32 : 1; + int numSubsets = partitioned ? 2 : 1; + int indexBits = partitioned ? 3 : 4; + int indexRange = (1 << indexBits); + + for (int p = 0; p < numPartitions; p++) + { + int partitionMask = partitioned ? BC7Data::g_partitionMap[p] : 0; + + const int MaxMetaRounds = MaxTweakRounds * MaxRefineRounds; + + MAInt16 metaEndPointsQuantized[MaxMetaRounds][2][2][3]; + MUInt15 metaIndexes[MaxMetaRounds][16]; + MFloat metaError[MaxMetaRounds][2]; + + bool roundValid[MaxMetaRounds][2]; + + for (int r = 0; r < MaxMetaRounds; r++) + for (int subset = 0; subset < 2; subset++) + roundValid[r][subset] = true; + + for (int subset = 0; subset < numSubsets; subset++) + { + for (int tweak = 0; tweak < MaxTweakRounds; tweak++) + { + EndpointRefiner<3> refiners[2]; + + bool abortRemainingRefines = false; + for (int refinePass = 0; refinePass < MaxRefineRounds; refinePass++) + { + int metaRound = tweak * MaxRefineRounds + refinePass; + + if (tweak >= numTweakRounds || refinePass >= numRefineRounds) + abortRemainingRefines = true; + + if (abortRemainingRefines) + { + roundValid[metaRound][subset] = false; + continue; + } + + MAInt16(&mrQuantizedEndPoints)[2][2][3] = metaEndPointsQuantized[metaRound]; + MUInt15(&mrIndexes)[16] = metaIndexes[metaRound]; + + MSInt16 endPointsColorSpace[2][3]; + + if (refinePass == 0) + { + UnfinishedEndpoints<3> ufep = partitioned ? partitionedUFEP[p][subset] : singleUFEP; + + if (isSigned) + ufep.FinishHDRSigned(tweak, indexRange, endPointsColorSpace[0], endPointsColorSpace[1], &rtn); + else + ufep.FinishHDRUnsigned(tweak, indexRange, endPointsColorSpace[0], endPointsColorSpace[1], &rtn); + } + else + refiners[subset].GetRefinedEndpointsHDR(endPointsColorSpace, isSigned, &rtn); + + refiners[subset].Init(indexRange, channelWeights); + + int fixupIndex = (subset == 0) ? 0 : BC7Data::g_fixupIndexes2[p]; + + IndexSelectorHDR<3> indexSelector; + if (isSigned) + QuantizeEndpointsSigned(endPointsColorSpace, floatPixels2CL, floatPixelsLinearWeighted, mrQuantizedEndPoints[subset], mrIndexes, indexSelector, fixupIndex, aPrec, indexRange, channelWeights, fastIndexing, &rtn); + else + QuantizeEndpointsUnsigned(endPointsColorSpace, floatPixels2CL, floatPixelsLinearWeighted, mrQuantizedEndPoints[subset], mrIndexes, indexSelector, fixupIndex, aPrec, indexRange, channelWeights, fastIndexing, &rtn); + + if (metaRound > 0) + { + ParallelMath::Int16CompFlag anySame = ParallelMath::MakeBoolInt16(false); + + for (int prevRound = 0; prevRound < metaRound; prevRound++) + { + MAInt16(&prevRoundEPs)[2][3] = metaEndPointsQuantized[prevRound][subset]; + + ParallelMath::Int16CompFlag same = ParallelMath::MakeBoolInt16(true); + + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 3; ch++) + same = (same & ParallelMath::Equal(prevRoundEPs[epi][ch], mrQuantizedEndPoints[subset][epi][ch])); + + anySame = (anySame | same); + if (ParallelMath::AllSet(anySame)) + break; + } + + if (ParallelMath::AllSet(anySame)) + { + roundValid[metaRound][subset] = false; + continue; + } + } + + MFloat subsetError = ParallelMath::MakeFloatZero(); + + { + for (int px = 0; px < 16; px++) + { + if (subset != ((partitionMask >> px) & 1)) + continue; + + MUInt15 index; + if (px == fixupIndex) + index = mrIndexes[px]; + else + { + index = fastIndexing ? indexSelector.SelectIndexHDRFast(floatPixels2CL[px], &rtn) : indexSelector.SelectIndexHDRSlow(floatPixelsLinearWeighted[px], &rtn); + mrIndexes[px] = index; + } + + MSInt16 reconstructed[3]; + if (isSigned) + indexSelector.ReconstructHDRSigned(mrIndexes[px], reconstructed); + else + indexSelector.ReconstructHDRUnsigned(mrIndexes[px], reconstructed); + + subsetError = subsetError + (fastIndexing ? BCCommon::ComputeErrorHDRFast<3>(flags, reconstructed, pixels[px], channelWeightsSq) : BCCommon::ComputeErrorHDRSlow<3>(flags, reconstructed, pixels[px], channelWeightsSq)); + + if (refinePass != numRefineRounds - 1) + refiners[subset].ContributeUnweightedPW(preWeightedPixels[px], index); + } + } + + metaError[metaRound][subset] = subsetError; + } + } + } + + // Now we have a bunch of attempts, but not all of them will fit in the delta coding scheme + int numMeta1 = partitioned ? MaxMetaRounds : 1; + for (int meta0 = 0; meta0 < MaxMetaRounds; meta0++) + { + if (!roundValid[meta0][0]) + continue; + + for (int meta1 = 0; meta1 < numMeta1; meta1++) + { + MFloat combinedError = metaError[meta0][0]; + if (partitioned) + { + if (!roundValid[meta1][1]) + continue; + + combinedError = combinedError + metaError[meta1][1]; + } + + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(combinedError, bestError); + if (!ParallelMath::AnySet(errorBetter)) + continue; + + ParallelMath::Int16CompFlag needsCommit = ParallelMath::FloatFlagToInt16(errorBetter); + + // Figure out if this is encodable + for (int mode = 0; mode < BC7Data::g_numHDRModes; mode++) + { + const BC7Data::BC6HModeInfo &modeInfo = BC7Data::g_hdrModes[mode]; + + if (modeInfo.m_partitioned != partitioned || modeInfo.m_aPrec != aPrec) + continue; + + MAInt16 encodedEPs[2][2][3]; + ParallelMath::Int16CompFlag isLegal; + if (partitioned) + EvaluatePartitionedLegality(metaEndPointsQuantized[meta0][0], metaEndPointsQuantized[meta1][1], modeInfo.m_aPrec, modeInfo.m_bPrec, modeInfo.m_transformed, encodedEPs, isLegal); + else + EvaluateSingleLegality(metaEndPointsQuantized[meta0][0], modeInfo.m_aPrec, modeInfo.m_bPrec, modeInfo.m_transformed, encodedEPs[0], isLegal); + + ParallelMath::Int16CompFlag isLegalAndBetter = (ParallelMath::FloatFlagToInt16(errorBetter) & isLegal); + if (!ParallelMath::AnySet(isLegalAndBetter)) + continue; + + ParallelMath::FloatCompFlag isLegalAndBetterFloat = ParallelMath::Int16FlagToFloat(isLegalAndBetter); + + ParallelMath::ConditionalSet(bestError, isLegalAndBetterFloat, combinedError); + ParallelMath::ConditionalSet(bestMode, isLegalAndBetter, ParallelMath::MakeUInt15(static_cast<uint16_t>(mode))); + ParallelMath::ConditionalSet(bestPartition, isLegalAndBetter, ParallelMath::MakeUInt15(static_cast<uint16_t>(p))); + + for (int subset = 0; subset < numSubsets; subset++) + { + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + ParallelMath::ConditionalSet(bestEndPoints[subset][epi][ch], isLegalAndBetter, encodedEPs[subset][epi][ch]); + } + } + + for (int px = 0; px < 16; px++) + { + int subset = ((partitionMask >> px) & 1); + if (subset == 0) + ParallelMath::ConditionalSet(bestIndexes[px], isLegalAndBetter, metaIndexes[meta0][px]); + else + ParallelMath::ConditionalSet(bestIndexes[px], isLegalAndBetter, metaIndexes[meta1][px]); + } + + needsCommit = ParallelMath::AndNot(needsCommit, isLegalAndBetter); + if (!ParallelMath::AnySet(needsCommit)) + break; + } + } + } + } + } + } + + // At this point, everything should be set + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + ParallelMath::ScalarUInt16 mode = ParallelMath::Extract(bestMode, block); + ParallelMath::ScalarUInt16 partition = ParallelMath::Extract(bestPartition, block); + int32_t eps[2][2][3]; + ParallelMath::ScalarUInt16 indexes[16]; + + const BC7Data::BC6HModeInfo& modeInfo = BC7Data::g_hdrModes[mode]; + + const BC6HData::ModeDescriptor* desc = BC6HData::g_modeDescriptors[mode]; + + const size_t headerBits = modeInfo.m_partitioned ? 82 : 65; + + for (int subset = 0; subset < 2; subset++) + { + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + eps[subset][epi][ch] = ParallelMath::Extract(bestEndPoints[subset][epi][ch], block); + } + } + + for (int px = 0; px < 16; px++) + indexes[px] = ParallelMath::Extract(bestIndexes[px], block); + + uint16_t modeID = modeInfo.m_modeID; + + PackingVector pv; + pv.Init(); + + for (size_t i = 0; i < headerBits; i++) + { + int32_t codedValue = 0; + switch (desc[i].m_eField) + { + case BC6HData::M: codedValue = modeID; break; + case BC6HData::D: codedValue = partition; break; + case BC6HData::RW: codedValue = eps[0][0][0]; break; + case BC6HData::RX: codedValue = eps[0][1][0]; break; + case BC6HData::RY: codedValue = eps[1][0][0]; break; + case BC6HData::RZ: codedValue = eps[1][1][0]; break; + case BC6HData::GW: codedValue = eps[0][0][1]; break; + case BC6HData::GX: codedValue = eps[0][1][1]; break; + case BC6HData::GY: codedValue = eps[1][0][1]; break; + case BC6HData::GZ: codedValue = eps[1][1][1]; break; + case BC6HData::BW: codedValue = eps[0][0][2]; break; + case BC6HData::BX: codedValue = eps[0][1][2]; break; + case BC6HData::BY: codedValue = eps[1][0][2]; break; + case BC6HData::BZ: codedValue = eps[1][1][2]; break; + default: assert(false); break; + } + + pv.Pack(static_cast<uint16_t>((codedValue >> desc[i].m_uBit) & 1), 1); + } + + int fixupIndex1 = 0; + int indexBits = 4; + if (modeInfo.m_partitioned) + { + fixupIndex1 = BC7Data::g_fixupIndexes2[partition]; + indexBits = 3; + } + + for (int px = 0; px < 16; px++) + { + ParallelMath::ScalarUInt16 index = ParallelMath::Extract(bestIndexes[px], block); + if (px == 0 || px == fixupIndex1) + pv.Pack(index, indexBits - 1); + else + pv.Pack(index, indexBits); + } + + pv.Flush(packedBlocks + 16 * block); + } + } + + static void SignExtendSingle(int &v, int bits) + { + if (v & (1 << (bits - 1))) + v |= -(1 << bits); + } + + static void UnpackOne(PixelBlockF16 &output, const uint8_t *pBC, bool isSigned) + { + UnpackingVector pv; + pv.Init(pBC); + + int numModeBits = 2; + int modeBits = pv.Unpack(2); + if (modeBits != 0 && modeBits != 1) + { + modeBits |= pv.Unpack(3) << 2; + numModeBits += 3; + } + + int mode = -1; + for (int possibleMode = 0; possibleMode < BC7Data::g_numHDRModes; possibleMode++) + { + if (BC7Data::g_hdrModes[possibleMode].m_modeID == modeBits) + { + mode = possibleMode; + break; + } + } + + if (mode < 0) + { + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 3; ch++) + output.m_pixels[px][ch] = 0; + output.m_pixels[px][3] = 0x3c00; // 1.0 + } + return; + } + + const BC7Data::BC6HModeInfo& modeInfo = BC7Data::g_hdrModes[mode]; + const size_t headerBits = modeInfo.m_partitioned ? 82 : 65; + const BC6HData::ModeDescriptor* desc = BC6HData::g_modeDescriptors[mode]; + + int32_t partition = 0; + int32_t eps[2][2][3]; + + for (int subset = 0; subset < 2; subset++) + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 3; ch++) + eps[subset][epi][ch] = 0; + + for (size_t i = numModeBits; i < headerBits; i++) + { + int32_t *pCodedValue = NULL; + + switch (desc[i].m_eField) + { + case BC6HData::D: pCodedValue = &partition; break; + case BC6HData::RW: pCodedValue = &eps[0][0][0]; break; + case BC6HData::RX: pCodedValue = &eps[0][1][0]; break; + case BC6HData::RY: pCodedValue = &eps[1][0][0]; break; + case BC6HData::RZ: pCodedValue = &eps[1][1][0]; break; + case BC6HData::GW: pCodedValue = &eps[0][0][1]; break; + case BC6HData::GX: pCodedValue = &eps[0][1][1]; break; + case BC6HData::GY: pCodedValue = &eps[1][0][1]; break; + case BC6HData::GZ: pCodedValue = &eps[1][1][1]; break; + case BC6HData::BW: pCodedValue = &eps[0][0][2]; break; + case BC6HData::BX: pCodedValue = &eps[0][1][2]; break; + case BC6HData::BY: pCodedValue = &eps[1][0][2]; break; + case BC6HData::BZ: pCodedValue = &eps[1][1][2]; break; + default: assert(false); break; + } + + (*pCodedValue) |= pv.Unpack(1) << desc[i].m_uBit; + } + + + uint16_t modeID = modeInfo.m_modeID; + + int fixupIndex1 = 0; + int indexBits = 4; + int numSubsets = 1; + if (modeInfo.m_partitioned) + { + fixupIndex1 = BC7Data::g_fixupIndexes2[partition]; + indexBits = 3; + numSubsets = 2; + } + + int indexes[16]; + for (int px = 0; px < 16; px++) + { + if (px == 0 || px == fixupIndex1) + indexes[px] = pv.Unpack(indexBits - 1); + else + indexes[px] = pv.Unpack(indexBits); + } + + if (modeInfo.m_partitioned) + { + for (int ch = 0; ch < 3; ch++) + { + if (isSigned) + SignExtendSingle(eps[0][0][ch], modeInfo.m_aPrec); + if (modeInfo.m_transformed || isSigned) + { + SignExtendSingle(eps[0][1][ch], modeInfo.m_bPrec[ch]); + SignExtendSingle(eps[1][0][ch], modeInfo.m_bPrec[ch]); + SignExtendSingle(eps[1][1][ch], modeInfo.m_bPrec[ch]); + } + } + } + else + { + for (int ch = 0; ch < 3; ch++) + { + if (isSigned) + SignExtendSingle(eps[0][0][ch], modeInfo.m_aPrec); + if (modeInfo.m_transformed || isSigned) + SignExtendSingle(eps[0][1][ch], modeInfo.m_bPrec[ch]); + } + } + + int aPrec = modeInfo.m_aPrec; + + if (modeInfo.m_transformed) + { + for (int ch = 0; ch < 3; ch++) + { + int wrapMask = (1 << aPrec) - 1; + + eps[0][1][ch] = ((eps[0][0][ch] + eps[0][1][ch]) & wrapMask); + if (isSigned) + SignExtendSingle(eps[0][1][ch], aPrec); + + if (modeInfo.m_partitioned) + { + eps[1][0][ch] = ((eps[0][0][ch] + eps[1][0][ch]) & wrapMask); + eps[1][1][ch] = ((eps[0][0][ch] + eps[1][1][ch]) & wrapMask); + + if (isSigned) + { + SignExtendSingle(eps[1][0][ch], aPrec); + SignExtendSingle(eps[1][1][ch], aPrec); + } + } + } + } + + // Unquantize endpoints + for (int subset = 0; subset < numSubsets; subset++) + { + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + { + int &v = eps[subset][epi][ch]; + + if (isSigned) + { + if (aPrec >= 16) + { + // Nothing + } + else + { + bool s = false; + int comp = v; + if (v < 0) + { + s = true; + comp = -comp; + } + + int unq = 0; + if (comp == 0) + unq = 0; + else if (comp >= ((1 << (aPrec - 1)) - 1)) + unq = 0x7fff; + else + unq = ((comp << 15) + 0x4000) >> (aPrec - 1); + + if (s) + unq = -unq; + + v = unq; + } + } + else + { + if (aPrec >= 15) + { + // Nothing + } + else if (v == 0) + { + // Nothing + } + else if (v == ((1 << aPrec) - 1)) + v = 0xffff; + else + v = ((v << 16) + 0x8000) >> aPrec; + } + } + } + } + + const int *weights = BC7Data::g_weightTables[indexBits]; + + for (int px = 0; px < 16; px++) + { + int subset = 0; + if (modeInfo.m_partitioned) + subset = (BC7Data::g_partitionMap[partition] >> px) & 1; + + int w = weights[indexes[px]]; + for (int ch = 0; ch < 3; ch++) + { + int comp = ((64 - w) * eps[subset][0][ch] + w * eps[subset][1][ch] + 32) >> 6; + + if (isSigned) + { + if (comp < 0) + comp = -(((-comp) * 31) >> 5); + else + comp = (comp * 31) >> 5; + + int s = 0; + if (comp < 0) + { + s = 0x8000; + comp = -comp; + } + + output.m_pixels[px][ch] = static_cast<uint16_t>(s | comp); + } + else + { + comp = (comp * 31) >> 6; + output.m_pixels[px][ch] = static_cast<uint16_t>(comp); + } + } + output.m_pixels[px][3] = 0x3c00; // 1.0 + } + } + }; + + namespace S3TCSingleColorTables + { + struct SingleColorTableEntry + { + uint8_t m_min; + uint8_t m_max; + uint8_t m_actualColor; + uint8_t m_span; + }; + + SingleColorTableEntry g_singleColor5_3[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 8, 0, 2, 8 }, { 8, 0, 2, 8 }, { 0, 8, 5, 8 }, { 0, 8, 5, 8 }, { 0, 8, 5, 8 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 16, 8, 10, 8 }, { 33, 0, 11, 33 }, { 8, 16, 13, 8 }, { 8, 16, 13, 8 }, { 8, 16, 13, 8 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 24, 16, 18, 8 }, { 41, 8, 19, 33 }, { 16, 24, 21, 8 }, { 16, 24, 21, 8 }, { 0, 33, 22, 33 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 33, 24, 27, 9 }, { 33, 24, 27, 9 }, { 33, 24, 27, 9 }, { 41, 24, 29, 17 }, { 24, 33, 30, 9 }, { 24, 33, 30, 9 }, + { 16, 41, 32, 25 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 41, 33, 35, 8 }, { 41, 33, 35, 8 }, { 33, 41, 38, 8 }, { 33, 41, 38, 8 }, { 33, 41, 38, 8 }, + { 24, 49, 40, 25 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 49, 41, 43, 8 }, { 66, 33, 44, 33 }, { 41, 49, 46, 8 }, { 41, 49, 46, 8 }, { 41, 49, 46, 8 }, + { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 57, 49, 51, 8 }, { 74, 41, 52, 33 }, { 49, 57, 54, 8 }, { 49, 57, 54, 8 }, { 33, 66, 55, 33 }, + { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 66, 57, 60, 9 }, { 66, 57, 60, 9 }, { 66, 57, 60, 9 }, { 74, 57, 62, 17 }, { 57, 66, 63, 9 }, + { 57, 66, 63, 9 }, { 49, 74, 65, 25 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 74, 66, 68, 8 }, { 74, 66, 68, 8 }, { 66, 74, 71, 8 }, { 66, 74, 71, 8 }, + { 66, 74, 71, 8 }, { 57, 82, 73, 25 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 82, 74, 76, 8 }, { 99, 66, 77, 33 }, { 74, 82, 79, 8 }, { 74, 82, 79, 8 }, + { 74, 82, 79, 8 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 90, 82, 84, 8 }, { 107, 74, 85, 33 }, { 82, 90, 87, 8 }, { 82, 90, 87, 8 }, + { 66, 99, 88, 33 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 99, 90, 93, 9 }, { 99, 90, 93, 9 }, { 99, 90, 93, 9 }, { 107, 90, 95, 17 }, + { 90, 99, 96, 9 }, { 90, 99, 96, 9 }, { 82, 107, 98, 25 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 107, 99, 101, 8 }, { 107, 99, 101, 8 }, { 99, 107, 104, 8 }, + { 99, 107, 104, 8 }, { 99, 107, 104, 8 }, { 90, 115, 106, 25 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 115, 107, 109, 8 }, { 132, 99, 110, 33 }, { 107, 115, 112, 8 }, + { 107, 115, 112, 8 }, { 107, 115, 112, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 123, 115, 117, 8 }, { 140, 107, 118, 33 }, { 115, 123, 120, 8 }, + { 115, 123, 120, 8 }, { 99, 132, 121, 33 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 132, 123, 126, 9 }, { 132, 123, 126, 9 }, { 132, 123, 126, 9 }, + { 140, 123, 128, 17 }, { 123, 132, 129, 9 }, { 123, 132, 129, 9 }, { 115, 140, 131, 25 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 140, 132, 134, 8 }, { 140, 132, 134, 8 }, + { 132, 140, 137, 8 }, { 132, 140, 137, 8 }, { 132, 140, 137, 8 }, { 123, 148, 139, 25 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 148, 140, 142, 8 }, { 165, 132, 143, 33 }, + { 140, 148, 145, 8 }, { 140, 148, 145, 8 }, { 140, 148, 145, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 156, 148, 150, 8 }, { 173, 140, 151, 33 }, + { 148, 156, 153, 8 }, { 148, 156, 153, 8 }, { 132, 165, 154, 33 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 165, 156, 159, 9 }, { 165, 156, 159, 9 }, + { 165, 156, 159, 9 }, { 173, 156, 161, 17 }, { 156, 165, 162, 9 }, { 156, 165, 162, 9 }, { 148, 173, 164, 25 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 173, 165, 167, 8 }, + { 173, 165, 167, 8 }, { 165, 173, 170, 8 }, { 165, 173, 170, 8 }, { 165, 173, 170, 8 }, { 156, 181, 172, 25 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 181, 173, 175, 8 }, + { 198, 165, 176, 33 }, { 173, 181, 178, 8 }, { 173, 181, 178, 8 }, { 173, 181, 178, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 189, 181, 183, 8 }, + { 206, 173, 184, 33 }, { 181, 189, 186, 8 }, { 181, 189, 186, 8 }, { 165, 198, 187, 33 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 198, 189, 192, 9 }, + { 198, 189, 192, 9 }, { 198, 189, 192, 9 }, { 206, 189, 194, 17 }, { 189, 198, 195, 9 }, { 189, 198, 195, 9 }, { 181, 206, 197, 25 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 }, + { 206, 198, 200, 8 }, { 206, 198, 200, 8 }, { 198, 206, 203, 8 }, { 198, 206, 203, 8 }, { 198, 206, 203, 8 }, { 189, 214, 205, 25 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 }, + { 214, 206, 208, 8 }, { 231, 198, 209, 33 }, { 206, 214, 211, 8 }, { 206, 214, 211, 8 }, { 206, 214, 211, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, + { 222, 214, 216, 8 }, { 239, 206, 217, 33 }, { 214, 222, 219, 8 }, { 214, 222, 219, 8 }, { 198, 231, 220, 33 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, + { 231, 222, 225, 9 }, { 231, 222, 225, 9 }, { 231, 222, 225, 9 }, { 239, 222, 227, 17 }, { 222, 231, 228, 9 }, { 222, 231, 228, 9 }, { 214, 239, 230, 25 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 239, 231, 233, 8 }, { 239, 231, 233, 8 }, { 231, 239, 236, 8 }, { 231, 239, 236, 8 }, { 231, 239, 236, 8 }, { 222, 247, 238, 25 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 247, 239, 241, 8 }, { 247, 239, 241, 8 }, { 239, 247, 244, 8 }, { 239, 247, 244, 8 }, { 239, 247, 244, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 255, 247, 249, 8 }, { 255, 247, 249, 8 }, { 247, 255, 252, 8 }, { 247, 255, 252, 8 }, { 247, 255, 252, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor6_3[256] = + { + { 0, 0, 0, 0 }, { 4, 0, 1, 4 }, { 0, 4, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 8, 4, 5, 4 }, { 4, 8, 6, 4 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 12, 8, 9, 4 }, { 8, 12, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 16, 12, 13, 4 }, { 12, 16, 14, 4 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 20, 16, 17, 4 }, { 16, 20, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 24, 20, 21, 4 }, { 20, 24, 22, 4 }, { 69, 0, 23, 69 }, + { 24, 24, 24, 0 }, { 28, 24, 25, 4 }, { 24, 28, 26, 4 }, { 65, 8, 27, 57 }, { 28, 28, 28, 0 }, { 32, 28, 29, 4 }, { 28, 32, 30, 4 }, { 69, 12, 31, 57 }, + { 32, 32, 32, 0 }, { 36, 32, 33, 4 }, { 32, 36, 34, 4 }, { 65, 20, 35, 45 }, { 36, 36, 36, 0 }, { 40, 36, 37, 4 }, { 36, 40, 38, 4 }, { 69, 24, 39, 45 }, + { 40, 40, 40, 0 }, { 44, 40, 41, 4 }, { 40, 44, 42, 4 }, { 65, 32, 43, 33 }, { 44, 44, 44, 0 }, { 48, 44, 45, 4 }, { 44, 48, 46, 4 }, { 69, 36, 47, 33 }, + { 48, 48, 48, 0 }, { 52, 48, 49, 4 }, { 48, 52, 50, 4 }, { 65, 44, 51, 21 }, { 52, 52, 52, 0 }, { 56, 52, 53, 4 }, { 52, 56, 54, 4 }, { 69, 48, 55, 21 }, + { 56, 56, 56, 0 }, { 60, 56, 57, 4 }, { 56, 60, 58, 4 }, { 65, 56, 59, 9 }, { 60, 60, 60, 0 }, { 65, 60, 61, 5 }, { 56, 65, 62, 9 }, { 60, 65, 63, 5 }, + { 56, 69, 64, 13 }, { 65, 65, 65, 0 }, { 69, 65, 66, 4 }, { 65, 69, 67, 4 }, { 60, 73, 68, 13 }, { 69, 69, 69, 0 }, { 73, 69, 70, 4 }, { 69, 73, 71, 4 }, + { 56, 81, 72, 25 }, { 73, 73, 73, 0 }, { 77, 73, 74, 4 }, { 73, 77, 75, 4 }, { 60, 85, 76, 25 }, { 77, 77, 77, 0 }, { 81, 77, 78, 4 }, { 77, 81, 79, 4 }, + { 56, 93, 80, 37 }, { 81, 81, 81, 0 }, { 85, 81, 82, 4 }, { 81, 85, 83, 4 }, { 60, 97, 84, 37 }, { 85, 85, 85, 0 }, { 89, 85, 86, 4 }, { 85, 89, 87, 4 }, + { 56, 105, 88, 49 }, { 89, 89, 89, 0 }, { 93, 89, 90, 4 }, { 89, 93, 91, 4 }, { 60, 109, 92, 49 }, { 93, 93, 93, 0 }, { 97, 93, 94, 4 }, { 93, 97, 95, 4 }, + { 134, 77, 96, 57 }, { 97, 97, 97, 0 }, { 101, 97, 98, 4 }, { 97, 101, 99, 4 }, { 130, 85, 100, 45 }, { 101, 101, 101, 0 }, { 105, 101, 102, 4 }, { 101, 105, 103, 4 }, + { 134, 89, 104, 45 }, { 105, 105, 105, 0 }, { 109, 105, 106, 4 }, { 105, 109, 107, 4 }, { 130, 97, 108, 33 }, { 109, 109, 109, 0 }, { 113, 109, 110, 4 }, { 109, 113, 111, 4 }, + { 134, 101, 112, 33 }, { 113, 113, 113, 0 }, { 117, 113, 114, 4 }, { 113, 117, 115, 4 }, { 130, 109, 116, 21 }, { 117, 117, 117, 0 }, { 121, 117, 118, 4 }, { 117, 121, 119, 4 }, + { 134, 113, 120, 21 }, { 121, 121, 121, 0 }, { 125, 121, 122, 4 }, { 121, 125, 123, 4 }, { 130, 121, 124, 9 }, { 125, 125, 125, 0 }, { 130, 125, 126, 5 }, { 121, 130, 127, 9 }, + { 125, 130, 128, 5 }, { 121, 134, 129, 13 }, { 130, 130, 130, 0 }, { 134, 130, 131, 4 }, { 130, 134, 132, 4 }, { 125, 138, 133, 13 }, { 134, 134, 134, 0 }, { 138, 134, 135, 4 }, + { 134, 138, 136, 4 }, { 121, 146, 137, 25 }, { 138, 138, 138, 0 }, { 142, 138, 139, 4 }, { 138, 142, 140, 4 }, { 125, 150, 141, 25 }, { 142, 142, 142, 0 }, { 146, 142, 143, 4 }, + { 142, 146, 144, 4 }, { 121, 158, 145, 37 }, { 146, 146, 146, 0 }, { 150, 146, 147, 4 }, { 146, 150, 148, 4 }, { 125, 162, 149, 37 }, { 150, 150, 150, 0 }, { 154, 150, 151, 4 }, + { 150, 154, 152, 4 }, { 121, 170, 153, 49 }, { 154, 154, 154, 0 }, { 158, 154, 155, 4 }, { 154, 158, 156, 4 }, { 125, 174, 157, 49 }, { 158, 158, 158, 0 }, { 162, 158, 159, 4 }, + { 158, 162, 160, 4 }, { 199, 142, 161, 57 }, { 162, 162, 162, 0 }, { 166, 162, 163, 4 }, { 162, 166, 164, 4 }, { 195, 150, 165, 45 }, { 166, 166, 166, 0 }, { 170, 166, 167, 4 }, + { 166, 170, 168, 4 }, { 199, 154, 169, 45 }, { 170, 170, 170, 0 }, { 174, 170, 171, 4 }, { 170, 174, 172, 4 }, { 195, 162, 173, 33 }, { 174, 174, 174, 0 }, { 178, 174, 175, 4 }, + { 174, 178, 176, 4 }, { 199, 166, 177, 33 }, { 178, 178, 178, 0 }, { 182, 178, 179, 4 }, { 178, 182, 180, 4 }, { 195, 174, 181, 21 }, { 182, 182, 182, 0 }, { 186, 182, 183, 4 }, + { 182, 186, 184, 4 }, { 199, 178, 185, 21 }, { 186, 186, 186, 0 }, { 190, 186, 187, 4 }, { 186, 190, 188, 4 }, { 195, 186, 189, 9 }, { 190, 190, 190, 0 }, { 195, 190, 191, 5 }, + { 186, 195, 192, 9 }, { 190, 195, 193, 5 }, { 186, 199, 194, 13 }, { 195, 195, 195, 0 }, { 199, 195, 196, 4 }, { 195, 199, 197, 4 }, { 190, 203, 198, 13 }, { 199, 199, 199, 0 }, + { 203, 199, 200, 4 }, { 199, 203, 201, 4 }, { 186, 211, 202, 25 }, { 203, 203, 203, 0 }, { 207, 203, 204, 4 }, { 203, 207, 205, 4 }, { 190, 215, 206, 25 }, { 207, 207, 207, 0 }, + { 211, 207, 208, 4 }, { 207, 211, 209, 4 }, { 186, 223, 210, 37 }, { 211, 211, 211, 0 }, { 215, 211, 212, 4 }, { 211, 215, 213, 4 }, { 190, 227, 214, 37 }, { 215, 215, 215, 0 }, + { 219, 215, 216, 4 }, { 215, 219, 217, 4 }, { 186, 235, 218, 49 }, { 219, 219, 219, 0 }, { 223, 219, 220, 4 }, { 219, 223, 221, 4 }, { 190, 239, 222, 49 }, { 223, 223, 223, 0 }, + { 227, 223, 224, 4 }, { 223, 227, 225, 4 }, { 186, 247, 226, 61 }, { 227, 227, 227, 0 }, { 231, 227, 228, 4 }, { 227, 231, 229, 4 }, { 190, 251, 230, 61 }, { 231, 231, 231, 0 }, + { 235, 231, 232, 4 }, { 231, 235, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 239, 235, 236, 4 }, { 235, 239, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, + { 243, 239, 240, 4 }, { 239, 243, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 247, 243, 244, 4 }, { 243, 247, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 251, 247, 248, 4 }, { 247, 251, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 255, 251, 252, 4 }, { 251, 255, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor5_2[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 41, 32, 17 }, + { 24, 41, 32, 17 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 24, 49, 36, 25 }, { 24, 49, 36, 25 }, { 33, 41, 37, 8 }, { 33, 41, 37, 8 }, { 24, 57, 40, 33 }, + { 24, 57, 40, 33 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 49, 49, 49, 0 }, + { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 57, 57, 57, 0 }, + { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, + { 57, 74, 65, 17 }, { 57, 74, 65, 17 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 57, 82, 69, 25 }, { 57, 82, 69, 25 }, { 66, 74, 70, 8 }, { 66, 74, 70, 8 }, + { 57, 90, 73, 33 }, { 57, 90, 73, 33 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 }, + { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 }, + { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 }, + { 90, 99, 94, 9 }, { 90, 107, 98, 17 }, { 90, 107, 98, 17 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 90, 115, 102, 25 }, { 90, 115, 102, 25 }, { 99, 107, 103, 8 }, + { 99, 107, 103, 8 }, { 90, 123, 106, 33 }, { 90, 123, 106, 33 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 115, 111, 8 }, { 107, 115, 111, 8 }, + { 107, 115, 111, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 123, 119, 8 }, { 115, 123, 119, 8 }, + { 115, 123, 119, 8 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 132, 127, 9 }, { 123, 132, 127, 9 }, + { 123, 132, 127, 9 }, { 123, 132, 127, 9 }, { 123, 140, 131, 17 }, { 123, 140, 131, 17 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 123, 148, 135, 25 }, { 123, 148, 135, 25 }, + { 132, 140, 136, 8 }, { 132, 140, 136, 8 }, { 123, 156, 139, 33 }, { 123, 156, 139, 33 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 148, 144, 8 }, + { 140, 148, 144, 8 }, { 140, 148, 144, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 156, 152, 8 }, + { 148, 156, 152, 8 }, { 148, 156, 152, 8 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 165, 160, 9 }, + { 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 173, 164, 17 }, { 156, 173, 164, 17 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 156, 181, 168, 25 }, + { 156, 181, 168, 25 }, { 165, 173, 169, 8 }, { 165, 173, 169, 8 }, { 156, 189, 172, 33 }, { 156, 189, 172, 33 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, + { 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, + { 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, + { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 206, 197, 17 }, { 189, 206, 197, 17 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 }, + { 189, 214, 201, 25 }, { 189, 214, 201, 25 }, { 198, 206, 202, 8 }, { 198, 206, 202, 8 }, { 189, 222, 205, 33 }, { 189, 222, 205, 33 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 }, + { 206, 206, 206, 0 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, + { 214, 214, 214, 0 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, + { 222, 222, 222, 0 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 239, 230, 17 }, { 222, 239, 230, 17 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 222, 247, 234, 25 }, { 222, 247, 234, 25 }, { 231, 239, 235, 8 }, { 231, 239, 235, 8 }, { 222, 255, 238, 33 }, { 222, 255, 238, 33 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor6_2[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 4, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 8, 6, 4 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 12, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 16, 14, 4 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 20, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 24, 22, 4 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 28, 26, 4 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 32, 30, 4 }, { 32, 32, 32, 0 }, + { 32, 32, 32, 0 }, { 32, 32, 32, 0 }, { 32, 36, 34, 4 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 40, 38, 4 }, { 40, 40, 40, 0 }, + { 40, 40, 40, 0 }, { 40, 40, 40, 0 }, { 40, 44, 42, 4 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 48, 46, 4 }, { 48, 48, 48, 0 }, + { 48, 48, 48, 0 }, { 48, 48, 48, 0 }, { 48, 52, 50, 4 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 56, 54, 4 }, { 56, 56, 56, 0 }, + { 56, 56, 56, 0 }, { 56, 56, 56, 0 }, { 56, 60, 58, 4 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 65, 62, 5 }, { 60, 65, 62, 5 }, + { 60, 69, 64, 9 }, { 65, 65, 65, 0 }, { 60, 73, 66, 13 }, { 65, 69, 67, 4 }, { 60, 77, 68, 17 }, { 69, 69, 69, 0 }, { 60, 81, 70, 21 }, { 69, 73, 71, 4 }, + { 60, 85, 72, 25 }, { 73, 73, 73, 0 }, { 60, 89, 74, 29 }, { 73, 77, 75, 4 }, { 60, 93, 76, 33 }, { 77, 77, 77, 0 }, { 60, 97, 78, 37 }, { 77, 81, 79, 4 }, + { 60, 101, 80, 41 }, { 81, 81, 81, 0 }, { 60, 105, 82, 45 }, { 81, 85, 83, 4 }, { 60, 109, 84, 49 }, { 85, 85, 85, 0 }, { 60, 113, 86, 53 }, { 85, 89, 87, 4 }, + { 60, 117, 88, 57 }, { 89, 89, 89, 0 }, { 60, 121, 90, 61 }, { 89, 93, 91, 4 }, { 60, 125, 92, 65 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 93, 97, 95, 4 }, + { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 101, 99, 4 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 105, 103, 4 }, + { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 109, 107, 4 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 113, 111, 4 }, + { 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 117, 115, 4 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 121, 119, 4 }, + { 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 125, 123, 4 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 130, 127, 5 }, + { 125, 130, 127, 5 }, { 125, 134, 129, 9 }, { 130, 130, 130, 0 }, { 125, 138, 131, 13 }, { 130, 134, 132, 4 }, { 125, 142, 133, 17 }, { 134, 134, 134, 0 }, { 125, 146, 135, 21 }, + { 134, 138, 136, 4 }, { 125, 150, 137, 25 }, { 138, 138, 138, 0 }, { 125, 154, 139, 29 }, { 138, 142, 140, 4 }, { 125, 158, 141, 33 }, { 142, 142, 142, 0 }, { 125, 162, 143, 37 }, + { 142, 146, 144, 4 }, { 125, 166, 145, 41 }, { 146, 146, 146, 0 }, { 125, 170, 147, 45 }, { 146, 150, 148, 4 }, { 125, 174, 149, 49 }, { 150, 150, 150, 0 }, { 125, 178, 151, 53 }, + { 150, 154, 152, 4 }, { 125, 182, 153, 57 }, { 154, 154, 154, 0 }, { 125, 186, 155, 61 }, { 154, 158, 156, 4 }, { 125, 190, 157, 65 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 }, + { 158, 162, 160, 4 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 166, 164, 4 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, + { 166, 170, 168, 4 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 174, 172, 4 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 }, + { 174, 178, 176, 4 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 182, 180, 4 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 }, + { 182, 186, 184, 4 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 190, 188, 4 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 }, + { 190, 195, 192, 5 }, { 190, 195, 192, 5 }, { 190, 199, 194, 9 }, { 195, 195, 195, 0 }, { 190, 203, 196, 13 }, { 195, 199, 197, 4 }, { 190, 207, 198, 17 }, { 199, 199, 199, 0 }, + { 190, 211, 200, 21 }, { 199, 203, 201, 4 }, { 190, 215, 202, 25 }, { 203, 203, 203, 0 }, { 190, 219, 204, 29 }, { 203, 207, 205, 4 }, { 190, 223, 206, 33 }, { 207, 207, 207, 0 }, + { 190, 227, 208, 37 }, { 207, 211, 209, 4 }, { 190, 231, 210, 41 }, { 211, 211, 211, 0 }, { 190, 235, 212, 45 }, { 211, 215, 213, 4 }, { 190, 239, 214, 49 }, { 215, 215, 215, 0 }, + { 190, 243, 216, 53 }, { 215, 219, 217, 4 }, { 190, 247, 218, 57 }, { 219, 219, 219, 0 }, { 190, 251, 220, 61 }, { 219, 223, 221, 4 }, { 190, 255, 222, 65 }, { 223, 223, 223, 0 }, + { 223, 223, 223, 0 }, { 223, 227, 225, 4 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 231, 229, 4 }, { 231, 231, 231, 0 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 231, 235, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 239, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 239, 243, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 247, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 247, 251, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 255, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor5_3_p[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 8, 0, 2, 8 }, { 8, 0, 2, 8 }, { 0, 8, 5, 8 }, { 0, 8, 5, 8 }, { 0, 8, 5, 8 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 16, 8, 10, 8 }, { 33, 0, 11, 33 }, { 8, 16, 13, 8 }, { 8, 16, 13, 8 }, { 8, 16, 13, 8 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 24, 16, 18, 8 }, { 41, 8, 19, 33 }, { 16, 24, 21, 8 }, { 16, 24, 21, 8 }, { 0, 33, 22, 33 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 33, 24, 27, 9 }, { 33, 24, 27, 9 }, { 33, 24, 27, 9 }, { 41, 24, 29, 17 }, { 24, 33, 30, 9 }, { 24, 33, 30, 9 }, + { 16, 41, 32, 25 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 41, 33, 35, 8 }, { 41, 33, 35, 8 }, { 33, 41, 38, 8 }, { 33, 41, 38, 8 }, { 33, 41, 38, 8 }, + { 24, 49, 40, 25 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 49, 41, 43, 8 }, { 66, 33, 44, 33 }, { 41, 49, 46, 8 }, { 41, 49, 46, 8 }, { 41, 49, 46, 8 }, + { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 57, 49, 51, 8 }, { 74, 41, 52, 33 }, { 49, 57, 54, 8 }, { 49, 57, 54, 8 }, { 33, 66, 55, 33 }, + { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 66, 57, 60, 9 }, { 66, 57, 60, 9 }, { 66, 57, 60, 9 }, { 74, 57, 62, 17 }, { 57, 66, 63, 9 }, + { 57, 66, 63, 9 }, { 49, 74, 65, 25 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 74, 66, 68, 8 }, { 74, 66, 68, 8 }, { 66, 74, 71, 8 }, { 66, 74, 71, 8 }, + { 66, 74, 71, 8 }, { 57, 82, 73, 25 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 82, 74, 76, 8 }, { 99, 66, 77, 33 }, { 74, 82, 79, 8 }, { 74, 82, 79, 8 }, + { 74, 82, 79, 8 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 90, 82, 84, 8 }, { 107, 74, 85, 33 }, { 82, 90, 87, 8 }, { 82, 90, 87, 8 }, + { 66, 99, 88, 33 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 99, 90, 93, 9 }, { 99, 90, 93, 9 }, { 99, 90, 93, 9 }, { 107, 90, 95, 17 }, + { 90, 99, 96, 9 }, { 90, 99, 96, 9 }, { 82, 107, 98, 25 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 107, 99, 101, 8 }, { 107, 99, 101, 8 }, { 99, 107, 104, 8 }, + { 99, 107, 104, 8 }, { 99, 107, 104, 8 }, { 90, 115, 106, 25 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 115, 107, 109, 8 }, { 132, 99, 110, 33 }, { 107, 115, 112, 8 }, + { 107, 115, 112, 8 }, { 107, 115, 112, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 123, 115, 117, 8 }, { 140, 107, 118, 33 }, { 115, 123, 120, 8 }, + { 115, 123, 120, 8 }, { 99, 132, 121, 33 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 132, 123, 126, 9 }, { 132, 123, 126, 9 }, { 132, 123, 126, 9 }, + { 140, 123, 128, 17 }, { 123, 132, 129, 9 }, { 123, 132, 129, 9 }, { 115, 140, 131, 25 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 140, 132, 134, 8 }, { 140, 132, 134, 8 }, + { 132, 140, 137, 8 }, { 132, 140, 137, 8 }, { 132, 140, 137, 8 }, { 123, 148, 139, 25 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 148, 140, 142, 8 }, { 165, 132, 143, 33 }, + { 140, 148, 145, 8 }, { 140, 148, 145, 8 }, { 140, 148, 145, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 156, 148, 150, 8 }, { 173, 140, 151, 33 }, + { 148, 156, 153, 8 }, { 148, 156, 153, 8 }, { 132, 165, 154, 33 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 165, 156, 159, 9 }, { 165, 156, 159, 9 }, + { 165, 156, 159, 9 }, { 173, 156, 161, 17 }, { 156, 165, 162, 9 }, { 156, 165, 162, 9 }, { 148, 173, 164, 25 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 173, 165, 167, 8 }, + { 173, 165, 167, 8 }, { 165, 173, 170, 8 }, { 165, 173, 170, 8 }, { 165, 173, 170, 8 }, { 156, 181, 172, 25 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 181, 173, 175, 8 }, + { 198, 165, 176, 33 }, { 173, 181, 178, 8 }, { 173, 181, 178, 8 }, { 173, 181, 178, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 189, 181, 183, 8 }, + { 206, 173, 184, 33 }, { 181, 189, 186, 8 }, { 181, 189, 186, 8 }, { 165, 198, 187, 33 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 198, 189, 192, 9 }, + { 198, 189, 192, 9 }, { 198, 189, 192, 9 }, { 206, 189, 194, 17 }, { 189, 198, 195, 9 }, { 189, 198, 195, 9 }, { 181, 206, 197, 25 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 }, + { 206, 198, 200, 8 }, { 206, 198, 200, 8 }, { 198, 206, 203, 8 }, { 198, 206, 203, 8 }, { 198, 206, 203, 8 }, { 189, 214, 205, 25 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 }, + { 214, 206, 208, 8 }, { 231, 198, 209, 33 }, { 206, 214, 211, 8 }, { 206, 214, 211, 8 }, { 206, 214, 211, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, + { 222, 214, 216, 8 }, { 239, 206, 217, 33 }, { 214, 222, 219, 8 }, { 214, 222, 219, 8 }, { 198, 231, 220, 33 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, + { 231, 222, 225, 9 }, { 231, 222, 225, 9 }, { 231, 222, 225, 9 }, { 239, 222, 227, 17 }, { 222, 231, 228, 9 }, { 222, 231, 228, 9 }, { 214, 239, 230, 25 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 239, 231, 233, 8 }, { 239, 231, 233, 8 }, { 231, 239, 236, 8 }, { 231, 239, 236, 8 }, { 231, 239, 236, 8 }, { 222, 247, 238, 25 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 247, 239, 241, 8 }, { 247, 239, 241, 8 }, { 239, 247, 244, 8 }, { 239, 247, 244, 8 }, { 239, 247, 244, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 255, 247, 249, 8 }, { 255, 247, 249, 8 }, { 247, 255, 252, 8 }, { 247, 255, 252, 8 }, { 247, 255, 252, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor6_3_p[256] = + { + { 0, 0, 0, 0 }, { 4, 0, 1, 4 }, { 0, 4, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 8, 4, 5, 4 }, { 4, 8, 6, 4 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 12, 8, 9, 4 }, { 8, 12, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 16, 12, 13, 4 }, { 12, 16, 14, 4 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 20, 16, 17, 4 }, { 16, 20, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 24, 20, 21, 4 }, { 20, 24, 22, 4 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 28, 24, 25, 4 }, { 24, 28, 26, 4 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 32, 28, 29, 4 }, { 28, 32, 30, 4 }, { 32, 32, 32, 0 }, + { 32, 32, 32, 0 }, { 36, 32, 33, 4 }, { 32, 36, 34, 4 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 40, 36, 37, 4 }, { 36, 40, 38, 4 }, { 40, 40, 40, 0 }, + { 40, 40, 40, 0 }, { 44, 40, 41, 4 }, { 40, 44, 42, 4 }, { 65, 32, 43, 33 }, { 44, 44, 44, 0 }, { 48, 44, 45, 4 }, { 44, 48, 46, 4 }, { 69, 36, 47, 33 }, + { 48, 48, 48, 0 }, { 52, 48, 49, 4 }, { 48, 52, 50, 4 }, { 65, 44, 51, 21 }, { 52, 52, 52, 0 }, { 56, 52, 53, 4 }, { 52, 56, 54, 4 }, { 69, 48, 55, 21 }, + { 56, 56, 56, 0 }, { 60, 56, 57, 4 }, { 56, 60, 58, 4 }, { 65, 56, 59, 9 }, { 60, 60, 60, 0 }, { 65, 60, 61, 5 }, { 56, 65, 62, 9 }, { 60, 65, 63, 5 }, + { 56, 69, 64, 13 }, { 65, 65, 65, 0 }, { 69, 65, 66, 4 }, { 65, 69, 67, 4 }, { 60, 73, 68, 13 }, { 69, 69, 69, 0 }, { 73, 69, 70, 4 }, { 69, 73, 71, 4 }, + { 56, 81, 72, 25 }, { 73, 73, 73, 0 }, { 77, 73, 74, 4 }, { 73, 77, 75, 4 }, { 60, 85, 76, 25 }, { 77, 77, 77, 0 }, { 81, 77, 78, 4 }, { 77, 81, 79, 4 }, + { 81, 81, 81, 0 }, { 81, 81, 81, 0 }, { 85, 81, 82, 4 }, { 81, 85, 83, 4 }, { 85, 85, 85, 0 }, { 85, 85, 85, 0 }, { 89, 85, 86, 4 }, { 85, 89, 87, 4 }, + { 89, 89, 89, 0 }, { 89, 89, 89, 0 }, { 93, 89, 90, 4 }, { 89, 93, 91, 4 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 97, 93, 94, 4 }, { 93, 97, 95, 4 }, + { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 101, 97, 98, 4 }, { 97, 101, 99, 4 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 105, 101, 102, 4 }, { 101, 105, 103, 4 }, + { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 109, 105, 106, 4 }, { 105, 109, 107, 4 }, { 130, 97, 108, 33 }, { 109, 109, 109, 0 }, { 113, 109, 110, 4 }, { 109, 113, 111, 4 }, + { 134, 101, 112, 33 }, { 113, 113, 113, 0 }, { 117, 113, 114, 4 }, { 113, 117, 115, 4 }, { 130, 109, 116, 21 }, { 117, 117, 117, 0 }, { 121, 117, 118, 4 }, { 117, 121, 119, 4 }, + { 134, 113, 120, 21 }, { 121, 121, 121, 0 }, { 125, 121, 122, 4 }, { 121, 125, 123, 4 }, { 130, 121, 124, 9 }, { 125, 125, 125, 0 }, { 130, 125, 126, 5 }, { 121, 130, 127, 9 }, + { 125, 130, 128, 5 }, { 121, 134, 129, 13 }, { 130, 130, 130, 0 }, { 134, 130, 131, 4 }, { 130, 134, 132, 4 }, { 125, 138, 133, 13 }, { 134, 134, 134, 0 }, { 138, 134, 135, 4 }, + { 134, 138, 136, 4 }, { 121, 146, 137, 25 }, { 138, 138, 138, 0 }, { 142, 138, 139, 4 }, { 138, 142, 140, 4 }, { 125, 150, 141, 25 }, { 142, 142, 142, 0 }, { 146, 142, 143, 4 }, + { 142, 146, 144, 4 }, { 146, 146, 146, 0 }, { 146, 146, 146, 0 }, { 150, 146, 147, 4 }, { 146, 150, 148, 4 }, { 150, 150, 150, 0 }, { 150, 150, 150, 0 }, { 154, 150, 151, 4 }, + { 150, 154, 152, 4 }, { 154, 154, 154, 0 }, { 154, 154, 154, 0 }, { 158, 154, 155, 4 }, { 154, 158, 156, 4 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 }, { 162, 158, 159, 4 }, + { 158, 162, 160, 4 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 166, 162, 163, 4 }, { 162, 166, 164, 4 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, { 170, 166, 167, 4 }, + { 166, 170, 168, 4 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 174, 170, 171, 4 }, { 170, 174, 172, 4 }, { 195, 162, 173, 33 }, { 174, 174, 174, 0 }, { 178, 174, 175, 4 }, + { 174, 178, 176, 4 }, { 199, 166, 177, 33 }, { 178, 178, 178, 0 }, { 182, 178, 179, 4 }, { 178, 182, 180, 4 }, { 195, 174, 181, 21 }, { 182, 182, 182, 0 }, { 186, 182, 183, 4 }, + { 182, 186, 184, 4 }, { 199, 178, 185, 21 }, { 186, 186, 186, 0 }, { 190, 186, 187, 4 }, { 186, 190, 188, 4 }, { 195, 186, 189, 9 }, { 190, 190, 190, 0 }, { 195, 190, 191, 5 }, + { 186, 195, 192, 9 }, { 190, 195, 193, 5 }, { 186, 199, 194, 13 }, { 195, 195, 195, 0 }, { 199, 195, 196, 4 }, { 195, 199, 197, 4 }, { 190, 203, 198, 13 }, { 199, 199, 199, 0 }, + { 203, 199, 200, 4 }, { 199, 203, 201, 4 }, { 186, 211, 202, 25 }, { 203, 203, 203, 0 }, { 207, 203, 204, 4 }, { 203, 207, 205, 4 }, { 190, 215, 206, 25 }, { 207, 207, 207, 0 }, + { 211, 207, 208, 4 }, { 207, 211, 209, 4 }, { 211, 211, 211, 0 }, { 211, 211, 211, 0 }, { 215, 211, 212, 4 }, { 211, 215, 213, 4 }, { 215, 215, 215, 0 }, { 215, 215, 215, 0 }, + { 219, 215, 216, 4 }, { 215, 219, 217, 4 }, { 219, 219, 219, 0 }, { 219, 219, 219, 0 }, { 223, 219, 220, 4 }, { 219, 223, 221, 4 }, { 223, 223, 223, 0 }, { 223, 223, 223, 0 }, + { 227, 223, 224, 4 }, { 223, 227, 225, 4 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 231, 227, 228, 4 }, { 227, 231, 229, 4 }, { 231, 231, 231, 0 }, { 231, 231, 231, 0 }, + { 235, 231, 232, 4 }, { 231, 235, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 239, 235, 236, 4 }, { 235, 239, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, + { 243, 239, 240, 4 }, { 239, 243, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 247, 243, 244, 4 }, { 243, 247, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 251, 247, 248, 4 }, { 247, 251, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 255, 251, 252, 4 }, { 251, 255, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor5_2_p[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 41, 32, 17 }, + { 24, 41, 32, 17 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 24, 49, 36, 25 }, { 24, 49, 36, 25 }, { 33, 41, 37, 8 }, { 33, 41, 37, 8 }, { 24, 57, 40, 33 }, + { 24, 57, 40, 33 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 49, 49, 49, 0 }, + { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 57, 57, 57, 0 }, + { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, + { 57, 74, 65, 17 }, { 57, 74, 65, 17 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 57, 82, 69, 25 }, { 57, 82, 69, 25 }, { 66, 74, 70, 8 }, { 66, 74, 70, 8 }, + { 57, 90, 73, 33 }, { 57, 90, 73, 33 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 }, + { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 }, + { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 }, + { 90, 99, 94, 9 }, { 90, 107, 98, 17 }, { 90, 107, 98, 17 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 90, 115, 102, 25 }, { 90, 115, 102, 25 }, { 99, 107, 103, 8 }, + { 99, 107, 103, 8 }, { 90, 123, 106, 33 }, { 90, 123, 106, 33 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 115, 111, 8 }, { 107, 115, 111, 8 }, + { 107, 115, 111, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 123, 119, 8 }, { 115, 123, 119, 8 }, + { 115, 123, 119, 8 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 132, 127, 9 }, { 123, 132, 127, 9 }, + { 123, 132, 127, 9 }, { 123, 132, 127, 9 }, { 123, 140, 131, 17 }, { 123, 140, 131, 17 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 123, 148, 135, 25 }, { 123, 148, 135, 25 }, + { 132, 140, 136, 8 }, { 132, 140, 136, 8 }, { 123, 156, 139, 33 }, { 123, 156, 139, 33 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 148, 144, 8 }, + { 140, 148, 144, 8 }, { 140, 148, 144, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 156, 152, 8 }, + { 148, 156, 152, 8 }, { 148, 156, 152, 8 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 165, 160, 9 }, + { 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 173, 164, 17 }, { 156, 173, 164, 17 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 156, 181, 168, 25 }, + { 156, 181, 168, 25 }, { 165, 173, 169, 8 }, { 165, 173, 169, 8 }, { 156, 189, 172, 33 }, { 156, 189, 172, 33 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, + { 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, + { 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, + { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 206, 197, 17 }, { 189, 206, 197, 17 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 }, + { 189, 214, 201, 25 }, { 189, 214, 201, 25 }, { 198, 206, 202, 8 }, { 198, 206, 202, 8 }, { 189, 222, 205, 33 }, { 189, 222, 205, 33 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 }, + { 206, 206, 206, 0 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, + { 214, 214, 214, 0 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, + { 222, 222, 222, 0 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 239, 230, 17 }, { 222, 239, 230, 17 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 222, 247, 234, 25 }, { 222, 247, 234, 25 }, { 231, 239, 235, 8 }, { 231, 239, 235, 8 }, { 222, 255, 238, 33 }, { 222, 255, 238, 33 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor6_2_p[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 4, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 8, 6, 4 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 12, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 16, 14, 4 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 20, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 24, 22, 4 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 28, 26, 4 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 32, 30, 4 }, { 32, 32, 32, 0 }, + { 32, 32, 32, 0 }, { 32, 32, 32, 0 }, { 32, 36, 34, 4 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 40, 38, 4 }, { 40, 40, 40, 0 }, + { 40, 40, 40, 0 }, { 40, 40, 40, 0 }, { 40, 44, 42, 4 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 48, 46, 4 }, { 48, 48, 48, 0 }, + { 48, 48, 48, 0 }, { 48, 48, 48, 0 }, { 48, 52, 50, 4 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 56, 54, 4 }, { 56, 56, 56, 0 }, + { 56, 56, 56, 0 }, { 56, 56, 56, 0 }, { 56, 60, 58, 4 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 65, 62, 5 }, { 60, 65, 62, 5 }, + { 60, 69, 64, 9 }, { 65, 65, 65, 0 }, { 60, 73, 66, 13 }, { 65, 69, 67, 4 }, { 60, 77, 68, 17 }, { 69, 69, 69, 0 }, { 60, 81, 70, 21 }, { 69, 73, 71, 4 }, + { 60, 85, 72, 25 }, { 73, 73, 73, 0 }, { 60, 89, 74, 29 }, { 73, 77, 75, 4 }, { 60, 93, 76, 33 }, { 77, 77, 77, 0 }, { 77, 77, 77, 0 }, { 77, 81, 79, 4 }, + { 81, 81, 81, 0 }, { 81, 81, 81, 0 }, { 81, 81, 81, 0 }, { 81, 85, 83, 4 }, { 85, 85, 85, 0 }, { 85, 85, 85, 0 }, { 85, 85, 85, 0 }, { 85, 89, 87, 4 }, + { 89, 89, 89, 0 }, { 89, 89, 89, 0 }, { 89, 89, 89, 0 }, { 89, 93, 91, 4 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 93, 97, 95, 4 }, + { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 101, 99, 4 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 105, 103, 4 }, + { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 109, 107, 4 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 113, 111, 4 }, + { 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 117, 115, 4 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 121, 119, 4 }, + { 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 125, 123, 4 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 130, 127, 5 }, + { 125, 130, 127, 5 }, { 125, 134, 129, 9 }, { 130, 130, 130, 0 }, { 125, 138, 131, 13 }, { 130, 134, 132, 4 }, { 125, 142, 133, 17 }, { 134, 134, 134, 0 }, { 125, 146, 135, 21 }, + { 134, 138, 136, 4 }, { 125, 150, 137, 25 }, { 138, 138, 138, 0 }, { 125, 154, 139, 29 }, { 138, 142, 140, 4 }, { 125, 158, 141, 33 }, { 142, 142, 142, 0 }, { 142, 142, 142, 0 }, + { 142, 146, 144, 4 }, { 146, 146, 146, 0 }, { 146, 146, 146, 0 }, { 146, 146, 146, 0 }, { 146, 150, 148, 4 }, { 150, 150, 150, 0 }, { 150, 150, 150, 0 }, { 150, 150, 150, 0 }, + { 150, 154, 152, 4 }, { 154, 154, 154, 0 }, { 154, 154, 154, 0 }, { 154, 154, 154, 0 }, { 154, 158, 156, 4 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 }, + { 158, 162, 160, 4 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 166, 164, 4 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, + { 166, 170, 168, 4 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 174, 172, 4 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 }, + { 174, 178, 176, 4 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 182, 180, 4 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 }, + { 182, 186, 184, 4 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 190, 188, 4 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 }, + { 190, 195, 192, 5 }, { 190, 195, 192, 5 }, { 190, 199, 194, 9 }, { 195, 195, 195, 0 }, { 190, 203, 196, 13 }, { 195, 199, 197, 4 }, { 190, 207, 198, 17 }, { 199, 199, 199, 0 }, + { 190, 211, 200, 21 }, { 199, 203, 201, 4 }, { 190, 215, 202, 25 }, { 203, 203, 203, 0 }, { 190, 219, 204, 29 }, { 203, 207, 205, 4 }, { 190, 223, 206, 33 }, { 207, 207, 207, 0 }, + { 207, 207, 207, 0 }, { 207, 211, 209, 4 }, { 211, 211, 211, 0 }, { 211, 211, 211, 0 }, { 211, 211, 211, 0 }, { 211, 215, 213, 4 }, { 215, 215, 215, 0 }, { 215, 215, 215, 0 }, + { 215, 215, 215, 0 }, { 215, 219, 217, 4 }, { 219, 219, 219, 0 }, { 219, 219, 219, 0 }, { 219, 219, 219, 0 }, { 219, 223, 221, 4 }, { 223, 223, 223, 0 }, { 223, 223, 223, 0 }, + { 223, 223, 223, 0 }, { 223, 227, 225, 4 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 231, 229, 4 }, { 231, 231, 231, 0 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 231, 235, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 239, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 239, 243, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 247, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 247, 251, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 255, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + } + + class S3TCComputer + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::SInt32 MSInt32; + + static void Init(MFloat& error) + { + error = ParallelMath::MakeFloat(FLT_MAX); + } + + static void QuantizeTo6Bits(MUInt15& v) + { + MUInt15 reduced = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(v, ParallelMath::MakeUInt15(253)) + ParallelMath::MakeUInt16(512), 10)); + v = (reduced << 2) | ParallelMath::RightShift(reduced, 4); + } + + static void QuantizeTo5Bits(MUInt15& v) + { + MUInt15 reduced = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(v, ParallelMath::MakeUInt15(249)) + ParallelMath::MakeUInt16(1024), 11)); + v = (reduced << 3) | ParallelMath::RightShift(reduced, 2); + } + + static void QuantizeTo565(MUInt15 endPoint[3]) + { + QuantizeTo5Bits(endPoint[0]); + QuantizeTo6Bits(endPoint[1]); + QuantizeTo5Bits(endPoint[2]); + } + + static MFloat ParanoidFactorForSpan(const MSInt16& span) + { + return ParallelMath::Abs(ParallelMath::ToFloat(span)) * 0.03f; + } + + static MFloat ParanoidDiff(const MUInt15& a, const MUInt15& b, const MFloat& d) + { + MFloat absDiff = ParallelMath::Abs(ParallelMath::ToFloat(ParallelMath::LosslessCast<MSInt16>::Cast(a) - ParallelMath::LosslessCast<MSInt16>::Cast(b))); + absDiff = absDiff + d; + return absDiff * absDiff; + } + + static void TestSingleColor(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], int range, const float* channelWeights, + MFloat &bestError, MUInt15 bestEndpoints[2][3], MUInt15 bestIndexes[16], MUInt15 &bestRange, const ParallelMath::RoundTowardNearestForScope *rtn) + { + float channelWeightsSq[3]; + + for (int ch = 0; ch < 3; ch++) + channelWeightsSq[ch] = channelWeights[ch] * channelWeights[ch]; + + MUInt15 totals[3] = { ParallelMath::MakeUInt15(0), ParallelMath::MakeUInt15(0), ParallelMath::MakeUInt15(0) }; + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 3; ch++) + totals[ch] = totals[ch] + pixels[px][ch]; + } + + MUInt15 average[3]; + for (int ch = 0; ch < 3; ch++) + average[ch] = ParallelMath::RightShift(totals[ch] + ParallelMath::MakeUInt15(8), 4); + + const S3TCSingleColorTables::SingleColorTableEntry* rbTable = NULL; + const S3TCSingleColorTables::SingleColorTableEntry* gTable = NULL; + if (flags & cvtt::Flags::S3TC_Paranoid) + { + if (range == 4) + { + rbTable = S3TCSingleColorTables::g_singleColor5_3_p; + gTable = S3TCSingleColorTables::g_singleColor6_3_p; + } + else + { + assert(range == 3); + rbTable = S3TCSingleColorTables::g_singleColor5_2_p; + gTable = S3TCSingleColorTables::g_singleColor6_2_p; + } + } + else + { + if (range == 4) + { + rbTable = S3TCSingleColorTables::g_singleColor5_3; + gTable = S3TCSingleColorTables::g_singleColor6_3; + } + else + { + assert(range == 3); + rbTable = S3TCSingleColorTables::g_singleColor5_2; + gTable = S3TCSingleColorTables::g_singleColor6_2; + } + } + + MUInt15 interpolated[3]; + MUInt15 eps[2][3]; + MSInt16 spans[3]; + for (int i = 0; i < ParallelMath::ParallelSize; i++) + { + for (int ch = 0; ch < 3; ch++) + { + uint16_t avg = ParallelMath::Extract(average[ch], i); + const S3TCSingleColorTables::SingleColorTableEntry& tableEntry = ((ch == 1) ? gTable[avg] : rbTable[avg]); + ParallelMath::PutUInt15(eps[0][ch], i, tableEntry.m_min); + ParallelMath::PutUInt15(eps[1][ch], i, tableEntry.m_max); + ParallelMath::PutUInt15(interpolated[ch], i, tableEntry.m_actualColor); + ParallelMath::PutSInt16(spans[ch], i, tableEntry.m_span); + } + } + + MFloat error = ParallelMath::MakeFloatZero(); + if (flags & cvtt::Flags::S3TC_Paranoid) + { + MFloat spanParanoidFactors[3]; + for (int ch = 0; ch < 3; ch++) + spanParanoidFactors[ch] = ParanoidFactorForSpan(spans[ch]); + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 3; ch++) + error = error + ParanoidDiff(interpolated[ch], pixels[px][ch], spanParanoidFactors[ch]) * channelWeightsSq[ch]; + } + } + else + { + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 3; ch++) + error = error + ParallelMath::ToFloat(ParallelMath::SqDiffUInt8(interpolated[ch], pixels[px][ch])) * channelWeightsSq[ch]; + } + } + + ParallelMath::FloatCompFlag better = ParallelMath::Less(error, bestError); + ParallelMath::Int16CompFlag better16 = ParallelMath::FloatFlagToInt16(better); + + if (ParallelMath::AnySet(better16)) + { + bestError = ParallelMath::Min(bestError, error); + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 3; ch++) + ParallelMath::ConditionalSet(bestEndpoints[epi][ch], better16, eps[epi][ch]); + + MUInt15 vindexes = ParallelMath::MakeUInt15(1); + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestIndexes[px], better16, vindexes); + + ParallelMath::ConditionalSet(bestRange, better16, ParallelMath::MakeUInt15(range)); + } + } + + static void TestEndpoints(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const MFloat preWeightedPixels[16][4], const MUInt15 unquantizedEndPoints[2][3], int range, const float* channelWeights, + MFloat &bestError, MUInt15 bestEndpoints[2][3], MUInt15 bestIndexes[16], MUInt15 &bestRange, EndpointRefiner<3> *refiner, const ParallelMath::RoundTowardNearestForScope *rtn) + { + float channelWeightsSq[3]; + + for (int ch = 0; ch < 3; ch++) + channelWeightsSq[ch] = channelWeights[ch] * channelWeights[ch]; + + MUInt15 endPoints[2][3]; + + for (int ep = 0; ep < 2; ep++) + for (int ch = 0; ch < 3; ch++) + endPoints[ep][ch] = unquantizedEndPoints[ep][ch]; + + QuantizeTo565(endPoints[0]); + QuantizeTo565(endPoints[1]); + + IndexSelector<3> selector; + selector.Init<false>(channelWeights, endPoints, range); + + MUInt15 indexes[16]; + + MFloat paranoidFactors[3]; + for (int ch = 0; ch < 3; ch++) + paranoidFactors[ch] = ParanoidFactorForSpan(ParallelMath::LosslessCast<MSInt16>::Cast(endPoints[0][ch]) - ParallelMath::LosslessCast<MSInt16>::Cast(endPoints[1][ch])); + + MFloat error = ParallelMath::MakeFloatZero(); + AggregatedError<3> aggError; + for (int px = 0; px < 16; px++) + { + MUInt15 index = selector.SelectIndexLDR(floatPixels[px], rtn); + indexes[px] = index; + + if (refiner) + refiner->ContributeUnweightedPW(preWeightedPixels[px], index); + + MUInt15 reconstructed[3]; + selector.ReconstructLDRPrecise(index, reconstructed); + + if (flags & Flags::S3TC_Paranoid) + { + for (int ch = 0; ch < 3; ch++) + error = error + ParanoidDiff(reconstructed[ch], pixels[px][ch], paranoidFactors[ch]) * channelWeightsSq[ch]; + } + else + BCCommon::ComputeErrorLDR<3>(flags, reconstructed, pixels[px], aggError); + } + + if (!(flags & Flags::S3TC_Paranoid)) + error = aggError.Finalize(flags, channelWeightsSq); + + ParallelMath::FloatCompFlag better = ParallelMath::Less(error, bestError); + + if (ParallelMath::AnySet(better)) + { + ParallelMath::Int16CompFlag betterInt16 = ParallelMath::FloatFlagToInt16(better); + + ParallelMath::ConditionalSet(bestError, better, error); + + for (int ep = 0; ep < 2; ep++) + for (int ch = 0; ch < 3; ch++) + ParallelMath::ConditionalSet(bestEndpoints[ep][ch], betterInt16, endPoints[ep][ch]); + + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestIndexes[px], betterInt16, indexes[px]); + + ParallelMath::ConditionalSet(bestRange, betterInt16, ParallelMath::MakeUInt15(static_cast<uint16_t>(range))); + } + } + + static void TestCounts(uint32_t flags, const int *counts, int nCounts, MUInt15 numElements, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const MFloat preWeightedPixels[16][4], bool alphaTest, + const MFloat floatSortedInputs[16][4], const MFloat preWeightedFloatSortedInputs[16][4], const float *channelWeights, MFloat &bestError, MUInt15 bestEndpoints[2][3], MUInt15 bestIndexes[16], MUInt15 &bestRange, + const ParallelMath::RoundTowardNearestForScope* rtn) + { + UNREFERENCED_PARAMETER(alphaTest); + UNREFERENCED_PARAMETER(flags); + + EndpointRefiner<3> refiner; + + refiner.Init(nCounts, channelWeights); + + bool escape = false; + int e = 0; + for (int i = 0; i < nCounts; i++) + { + for (int n = 0; n < counts[i]; n++) + { + ParallelMath::Int16CompFlag valid = ParallelMath::Less(ParallelMath::MakeUInt15(static_cast<uint16_t>(n)), numElements); + if (!ParallelMath::AnySet(valid)) + { + escape = true; + break; + } + + if (ParallelMath::AllSet(valid)) + refiner.ContributeUnweightedPW(preWeightedFloatSortedInputs[e++], ParallelMath::MakeUInt15(static_cast<uint16_t>(i))); + else + { + MFloat weight = ParallelMath::Select(ParallelMath::Int16FlagToFloat(valid), ParallelMath::MakeFloat(1.0f), ParallelMath::MakeFloat(0.0f)); + refiner.ContributePW(preWeightedFloatSortedInputs[e++], ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), weight); + } + } + + if (escape) + break; + } + + MUInt15 endPoints[2][3]; + refiner.GetRefinedEndpointsLDR(endPoints, rtn); + + TestEndpoints(flags, pixels, floatPixels, preWeightedPixels, endPoints, nCounts, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, NULL, rtn); + } + + static void PackExplicitAlpha(uint32_t flags, const PixelBlockU8* inputs, int inputChannel, uint8_t* packedBlocks, size_t packedBlockStride) + { + UNREFERENCED_PARAMETER(flags); + ParallelMath::RoundTowardNearestForScope rtn; + + float weights[1] = { 1.0f }; + + MUInt15 pixels[16]; + MFloat floatPixels[16]; + + for (int px = 0; px < 16; px++) + { + ParallelMath::ConvertLDRInputs(inputs, px, inputChannel, pixels[px]); + floatPixels[px] = ParallelMath::ToFloat(pixels[px]); + } + + MUInt15 ep[2][1] = { { ParallelMath::MakeUInt15(0) },{ ParallelMath::MakeUInt15(255) } }; + + IndexSelector<1> selector; + selector.Init<false>(weights, ep, 16); + + MUInt15 indexes[16]; + + for (int px = 0; px < 16; px++) + indexes[px] = selector.SelectIndexLDR(&floatPixels[px], &rtn); + + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + for (int px = 0; px < 16; px += 8) + { + int index0 = ParallelMath::Extract(indexes[px], block); + int index1 = ParallelMath::Extract(indexes[px], block); + + packedBlocks[px / 2] = static_cast<uint8_t>(index0 | (index1 << 4)); + } + + packedBlocks += packedBlockStride; + } + } + + static void PackInterpolatedAlpha(uint32_t flags, const PixelBlockU8* inputs, int inputChannel, uint8_t* packedBlocks, size_t packedBlockStride, bool isSigned, int maxTweakRounds, int numRefineRounds) + { + if (maxTweakRounds < 1) + maxTweakRounds = 1; + + if (numRefineRounds < 1) + numRefineRounds = 1; + + ParallelMath::RoundTowardNearestForScope rtn; + + float oneWeight[1] = { 1.0f }; + + MUInt15 pixels[16]; + MFloat floatPixels[16]; + + MUInt15 highTerminal = isSigned ? ParallelMath::MakeUInt15(254) : ParallelMath::MakeUInt15(255); + MUInt15 highTerminalMinusOne = highTerminal - ParallelMath::MakeUInt15(1); + + for (int px = 0; px < 16; px++) + { + ParallelMath::ConvertLDRInputs(inputs, px, inputChannel, pixels[px]); + + if (isSigned) + pixels[px] = ParallelMath::Min(pixels[px], highTerminal); + + floatPixels[px] = ParallelMath::ToFloat(pixels[px]); + } + + MUInt15 sortedPixels[16]; + for (int px = 0; px < 16; px++) + sortedPixels[px] = pixels[px]; + + for (int sortEnd = 15; sortEnd > 0; sortEnd--) + { + for (int sortOffset = 0; sortOffset < sortEnd; sortOffset++) + { + MUInt15 a = sortedPixels[sortOffset]; + MUInt15 b = sortedPixels[sortOffset + 1]; + + sortedPixels[sortOffset] = ParallelMath::Min(a, b); + sortedPixels[sortOffset + 1] = ParallelMath::Max(a, b); + } + } + + MUInt15 zero = ParallelMath::MakeUInt15(0); + MUInt15 one = ParallelMath::MakeUInt15(1); + + MUInt15 bestIsFullRange = zero; + MFloat bestError = ParallelMath::MakeFloat(FLT_MAX); + MUInt15 bestEP[2] = { zero, zero }; + MUInt15 bestIndexes[16] = { + zero, zero, zero, zero, + zero, zero, zero, zero, + zero, zero, zero, zero, + zero, zero, zero, zero + }; + + // Full-precision + { + MUInt15 minEP = sortedPixels[0]; + MUInt15 maxEP = sortedPixels[15]; + + MFloat base[1] = { ParallelMath::ToFloat(minEP) }; + MFloat offset[1] = { ParallelMath::ToFloat(maxEP - minEP) }; + + UnfinishedEndpoints<1> ufep = UnfinishedEndpoints<1>(base, offset); + + int numTweakRounds = BCCommon::TweakRoundsForRange(8); + if (numTweakRounds > maxTweakRounds) + numTweakRounds = maxTweakRounds; + + for (int tweak = 0; tweak < numTweakRounds; tweak++) + { + MUInt15 ep[2][1]; + + ufep.FinishLDR(tweak, 8, ep[0], ep[1]); + + for (int refinePass = 0; refinePass < numRefineRounds; refinePass++) + { + EndpointRefiner<1> refiner; + refiner.Init(8, oneWeight); + + if (isSigned) + for (int epi = 0; epi < 2; epi++) + ep[epi][0] = ParallelMath::Min(ep[epi][0], highTerminal); + + IndexSelector<1> indexSelector; + indexSelector.Init<false>(oneWeight, ep, 8); + + MUInt15 indexes[16]; + + AggregatedError<1> aggError; + for (int px = 0; px < 16; px++) + { + MUInt15 index = indexSelector.SelectIndexLDR(&floatPixels[px], &rtn); + + MUInt15 reconstructedPixel; + + indexSelector.ReconstructLDRPrecise(index, &reconstructedPixel); + BCCommon::ComputeErrorLDR<1>(flags, &reconstructedPixel, &pixels[px], aggError); + + if (refinePass != numRefineRounds - 1) + refiner.ContributeUnweightedPW(&floatPixels[px], index); + + indexes[px] = index; + } + MFloat error = aggError.Finalize(flags | Flags::Uniform, oneWeight); + + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(error, bestError); + ParallelMath::Int16CompFlag errorBetter16 = ParallelMath::FloatFlagToInt16(errorBetter); + + if (ParallelMath::AnySet(errorBetter16)) + { + bestError = ParallelMath::Min(error, bestError); + ParallelMath::ConditionalSet(bestIsFullRange, errorBetter16, one); + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestIndexes[px], errorBetter16, indexes[px]); + + for (int epi = 0; epi < 2; epi++) + ParallelMath::ConditionalSet(bestEP[epi], errorBetter16, ep[epi][0]); + } + + if (refinePass != numRefineRounds - 1) + refiner.GetRefinedEndpointsLDR(ep, &rtn); + } + } + } + + // Reduced precision with special endpoints + { + MUInt15 bestHeuristicMin = sortedPixels[0]; + MUInt15 bestHeuristicMax = sortedPixels[15]; + + ParallelMath::Int16CompFlag canTryClipping; + + // In reduced precision, we want try putting endpoints at the reserved indexes at the ends. + // The heuristic we use is to assign indexes to the end as long as they aren't off by more than half of the index range. + // This will usually not find anything, but it's cheap to check. + + { + MUInt15 largestPossibleRange = bestHeuristicMax - bestHeuristicMin; // Max: 255 + MUInt15 lowestPossibleClearance = ParallelMath::Min(bestHeuristicMin, static_cast<MUInt15>(highTerminal - bestHeuristicMax)); + + MUInt15 lowestPossibleClearanceTimes10 = (lowestPossibleClearance << 2) + (lowestPossibleClearance << 4); + canTryClipping = ParallelMath::LessOrEqual(lowestPossibleClearanceTimes10, largestPossibleRange); + } + + if (ParallelMath::AnySet(canTryClipping)) + { + MUInt15 lowClearances[16]; + MUInt15 highClearances[16]; + MUInt15 bestSkipCount = ParallelMath::MakeUInt15(0); + + lowClearances[0] = highClearances[0] = ParallelMath::MakeUInt15(0); + + for (int px = 1; px < 16; px++) + { + lowClearances[px] = sortedPixels[px - 1]; + highClearances[px] = highTerminal - sortedPixels[16 - px]; + } + + for (uint16_t firstIndex = 0; firstIndex < 16; firstIndex++) + { + uint16_t numSkippedLow = firstIndex; + + MUInt15 lowClearance = lowClearances[firstIndex]; + + for (uint16_t lastIndex = firstIndex; lastIndex < 16; lastIndex++) + { + uint16_t numSkippedHigh = 15 - lastIndex; + uint16_t numSkipped = numSkippedLow + numSkippedHigh; + + MUInt15 numSkippedV = ParallelMath::MakeUInt15(numSkipped); + + ParallelMath::Int16CompFlag areMoreSkipped = ParallelMath::Less(bestSkipCount, numSkippedV); + + if (!ParallelMath::AnySet(areMoreSkipped)) + continue; + + MUInt15 clearance = ParallelMath::Max(highClearances[numSkippedHigh], lowClearance); + MUInt15 clearanceTimes10 = (clearance << 2) + (clearance << 4); + + MUInt15 range = sortedPixels[lastIndex] - sortedPixels[firstIndex]; + + ParallelMath::Int16CompFlag isBetter = (areMoreSkipped & ParallelMath::LessOrEqual(clearanceTimes10, range)); + ParallelMath::ConditionalSet(bestHeuristicMin, isBetter, sortedPixels[firstIndex]); + ParallelMath::ConditionalSet(bestHeuristicMax, isBetter, sortedPixels[lastIndex]); + } + } + } + + MUInt15 bestSimpleMin = one; + MUInt15 bestSimpleMax = highTerminalMinusOne; + + for (int px = 0; px < 16; px++) + { + ParallelMath::ConditionalSet(bestSimpleMin, ParallelMath::Less(zero, sortedPixels[15 - px]), sortedPixels[15 - px]); + ParallelMath::ConditionalSet(bestSimpleMax, ParallelMath::Less(sortedPixels[px], highTerminal), sortedPixels[px]); + } + + MUInt15 minEPs[2] = { bestSimpleMin, bestHeuristicMin }; + MUInt15 maxEPs[2] = { bestSimpleMax, bestHeuristicMax }; + + int minEPRange = 2; + if (ParallelMath::AllSet(ParallelMath::Equal(minEPs[0], minEPs[1]))) + minEPRange = 1; + + int maxEPRange = 2; + if (ParallelMath::AllSet(ParallelMath::Equal(maxEPs[0], maxEPs[1]))) + maxEPRange = 1; + + for (int minEPIndex = 0; minEPIndex < minEPRange; minEPIndex++) + { + for (int maxEPIndex = 0; maxEPIndex < maxEPRange; maxEPIndex++) + { + MFloat base[1] = { ParallelMath::ToFloat(minEPs[minEPIndex]) }; + MFloat offset[1] = { ParallelMath::ToFloat(maxEPs[maxEPIndex] - minEPs[minEPIndex]) }; + + UnfinishedEndpoints<1> ufep = UnfinishedEndpoints<1>(base, offset); + + int numTweakRounds = BCCommon::TweakRoundsForRange(6); + if (numTweakRounds > maxTweakRounds) + numTweakRounds = maxTweakRounds; + + for (int tweak = 0; tweak < numTweakRounds; tweak++) + { + MUInt15 ep[2][1]; + + ufep.FinishLDR(tweak, 8, ep[0], ep[1]); + + for (int refinePass = 0; refinePass < numRefineRounds; refinePass++) + { + EndpointRefiner<1> refiner; + refiner.Init(6, oneWeight); + + if (isSigned) + for (int epi = 0; epi < 2; epi++) + ep[epi][0] = ParallelMath::Min(ep[epi][0], highTerminal); + + IndexSelector<1> indexSelector; + indexSelector.Init<false>(oneWeight, ep, 6); + + MUInt15 indexes[16]; + MFloat error = ParallelMath::MakeFloatZero(); + + for (int px = 0; px < 16; px++) + { + MUInt15 selectedIndex = indexSelector.SelectIndexLDR(&floatPixels[px], &rtn); + + MUInt15 reconstructedPixel; + + indexSelector.ReconstructLDRPrecise(selectedIndex, &reconstructedPixel); + + MFloat zeroError = BCCommon::ComputeErrorLDRSimple<1>(flags | Flags::Uniform, &zero, &pixels[px], 1, oneWeight); + MFloat highTerminalError = BCCommon::ComputeErrorLDRSimple<1>(flags | Flags::Uniform, &highTerminal, &pixels[px], 1, oneWeight); + MFloat selectedIndexError = BCCommon::ComputeErrorLDRSimple<1>(flags | Flags::Uniform, &reconstructedPixel, &pixels[px], 1, oneWeight); + + MFloat bestPixelError = zeroError; + MUInt15 index = ParallelMath::MakeUInt15(6); + + ParallelMath::ConditionalSet(index, ParallelMath::FloatFlagToInt16(ParallelMath::Less(highTerminalError, bestPixelError)), ParallelMath::MakeUInt15(7)); + bestPixelError = ParallelMath::Min(bestPixelError, highTerminalError); + + ParallelMath::FloatCompFlag selectedIndexBetter = ParallelMath::Less(selectedIndexError, bestPixelError); + + if (ParallelMath::AllSet(selectedIndexBetter)) + { + if (refinePass != numRefineRounds - 1) + refiner.ContributeUnweightedPW(&floatPixels[px], selectedIndex); + } + else + { + MFloat refineWeight = ParallelMath::Select(selectedIndexBetter, ParallelMath::MakeFloat(1.0f), ParallelMath::MakeFloatZero()); + + if (refinePass != numRefineRounds - 1) + refiner.ContributePW(&floatPixels[px], selectedIndex, refineWeight); + } + + ParallelMath::ConditionalSet(index, ParallelMath::FloatFlagToInt16(selectedIndexBetter), selectedIndex); + bestPixelError = ParallelMath::Min(bestPixelError, selectedIndexError); + + error = error + bestPixelError; + + indexes[px] = index; + } + + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(error, bestError); + ParallelMath::Int16CompFlag errorBetter16 = ParallelMath::FloatFlagToInt16(errorBetter); + + if (ParallelMath::AnySet(errorBetter16)) + { + bestError = ParallelMath::Min(error, bestError); + ParallelMath::ConditionalSet(bestIsFullRange, errorBetter16, zero); + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestIndexes[px], errorBetter16, indexes[px]); + + for (int epi = 0; epi < 2; epi++) + ParallelMath::ConditionalSet(bestEP[epi], errorBetter16, ep[epi][0]); + } + + if (refinePass != numRefineRounds - 1) + refiner.GetRefinedEndpointsLDR(ep, &rtn); + } + } + } + } + } + + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + int ep0 = ParallelMath::Extract(bestEP[0], block); + int ep1 = ParallelMath::Extract(bestEP[1], block); + int isFullRange = ParallelMath::Extract(bestIsFullRange, block); + + if (isSigned) + { + ep0 -= 127; + ep1 -= 127; + + assert(ep0 >= -127 && ep0 <= 127); + assert(ep1 >= -127 && ep1 <= 127); + } + + + bool swapEndpoints = (isFullRange != 0) != (ep0 > ep1); + + if (swapEndpoints) + std::swap(ep0, ep1); + + uint16_t dumpBits = 0; + int dumpBitsOffset = 0; + int dumpByteOffset = 2; + packedBlocks[0] = static_cast<uint8_t>(ep0 & 0xff); + packedBlocks[1] = static_cast<uint8_t>(ep1 & 0xff); + + int maxValue = (isFullRange != 0) ? 7 : 5; + + for (int px = 0; px < 16; px++) + { + int index = ParallelMath::Extract(bestIndexes[px], block); + + if (swapEndpoints && index <= maxValue) + index = maxValue - index; + + if (index != 0) + { + if (index == maxValue) + index = 1; + else if (index < maxValue) + index++; + } + + assert(index >= 0 && index < 8); + + dumpBits |= static_cast<uint16_t>(index << dumpBitsOffset); + dumpBitsOffset += 3; + + if (dumpBitsOffset >= 8) + { + assert(dumpByteOffset < 8); + packedBlocks[dumpByteOffset] = static_cast<uint8_t>(dumpBits & 0xff); + dumpBits >>= 8; + dumpBitsOffset -= 8; + dumpByteOffset++; + } + } + + assert(dumpBitsOffset == 0); + assert(dumpByteOffset == 8); + + packedBlocks += packedBlockStride; + } + } + + static void PackRGB(uint32_t flags, const PixelBlockU8* inputs, uint8_t* packedBlocks, size_t packedBlockStride, const float channelWeights[4], bool alphaTest, float alphaThreshold, bool exhaustive, int maxTweakRounds, int numRefineRounds) + { + ParallelMath::RoundTowardNearestForScope rtn; + + if (numRefineRounds < 1) + numRefineRounds = 1; + + if (maxTweakRounds < 1) + maxTweakRounds = 1; + + EndpointSelector<3, 8> endpointSelector; + + MUInt15 pixels[16][4]; + MFloat floatPixels[16][4]; + + MFloat preWeightedPixels[16][4]; + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 4; ch++) + ParallelMath::ConvertLDRInputs(inputs, px, ch, pixels[px][ch]); + } + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 4; ch++) + floatPixels[px][ch] = ParallelMath::ToFloat(pixels[px][ch]); + } + + if (alphaTest) + { + MUInt15 threshold = ParallelMath::MakeUInt15(static_cast<uint16_t>(floor(alphaThreshold * 255.0f + 0.5f))); + + for (int px = 0; px < 16; px++) + { + ParallelMath::Int16CompFlag belowThreshold = ParallelMath::Less(pixels[px][3], threshold); + pixels[px][3] = ParallelMath::Select(belowThreshold, ParallelMath::MakeUInt15(0), ParallelMath::MakeUInt15(255)); + } + } + + BCCommon::PreWeightPixelsLDR<4>(preWeightedPixels, pixels, channelWeights); + + MUInt15 minAlpha = ParallelMath::MakeUInt15(255); + + for (int px = 0; px < 16; px++) + minAlpha = ParallelMath::Min(minAlpha, pixels[px][3]); + + MFloat pixelWeights[16]; + for (int px = 0; px < 16; px++) + { + pixelWeights[px] = ParallelMath::MakeFloat(1.0f); + if (alphaTest) + { + ParallelMath::Int16CompFlag isTransparent = ParallelMath::Less(pixels[px][3], ParallelMath::MakeUInt15(255)); + + ParallelMath::ConditionalSet(pixelWeights[px], ParallelMath::Int16FlagToFloat(isTransparent), ParallelMath::MakeFloatZero()); + } + } + + for (int pass = 0; pass < NumEndpointSelectorPasses; pass++) + { + for (int px = 0; px < 16; px++) + endpointSelector.ContributePass(preWeightedPixels[px], pass, pixelWeights[px]); + + endpointSelector.FinishPass(pass); + } + + UnfinishedEndpoints<3> ufep = endpointSelector.GetEndpoints(channelWeights); + + MUInt15 bestEndpoints[2][3]; + MUInt15 bestIndexes[16]; + MUInt15 bestRange = ParallelMath::MakeUInt15(0); + MFloat bestError = ParallelMath::MakeFloat(FLT_MAX); + + for (int px = 0; px < 16; px++) + bestIndexes[px] = ParallelMath::MakeUInt15(0); + + for (int ep = 0; ep < 2; ep++) + for (int ch = 0; ch < 3; ch++) + bestEndpoints[ep][ch] = ParallelMath::MakeUInt15(0); + + if (exhaustive) + { + MSInt16 sortBins[16]; + + { + // Compute an 11-bit index, change it to signed, stuff it in the high bits of the sort bins, + // and pack the original indexes into the low bits. + + MUInt15 sortEP[2][3]; + ufep.FinishLDR(0, 11, sortEP[0], sortEP[1]); + + IndexSelector<3> sortSelector; + sortSelector.Init<false>(channelWeights, sortEP, 1 << 11); + + for (int16_t px = 0; px < 16; px++) + { + MSInt16 sortBin = ParallelMath::LosslessCast<MSInt16>::Cast(sortSelector.SelectIndexLDR(floatPixels[px], &rtn) << 4); + + if (alphaTest) + { + ParallelMath::Int16CompFlag isTransparent = ParallelMath::Less(pixels[px][3], ParallelMath::MakeUInt15(255)); + + ParallelMath::ConditionalSet(sortBin, isTransparent, ParallelMath::MakeSInt16(-16)); // 0xfff0 + } + + sortBin = sortBin + ParallelMath::MakeSInt16(px); + + sortBins[px] = sortBin; + } + } + + // Sort bins + for (int sortEnd = 1; sortEnd < 16; sortEnd++) + { + for (int sortLoc = sortEnd; sortLoc > 0; sortLoc--) + { + MSInt16 a = sortBins[sortLoc]; + MSInt16 b = sortBins[sortLoc - 1]; + + sortBins[sortLoc] = ParallelMath::Max(a, b); + sortBins[sortLoc - 1] = ParallelMath::Min(a, b); + } + } + + MUInt15 firstElement = ParallelMath::MakeUInt15(0); + for (uint16_t e = 0; e < 16; e++) + { + ParallelMath::Int16CompFlag isInvalid = ParallelMath::Less(sortBins[e], ParallelMath::MakeSInt16(0)); + ParallelMath::ConditionalSet(firstElement, isInvalid, ParallelMath::MakeUInt15(e + 1)); + if (!ParallelMath::AnySet(isInvalid)) + break; + } + + MUInt15 numElements = ParallelMath::MakeUInt15(16) - firstElement; + + MUInt15 sortedInputs[16][4]; + MFloat floatSortedInputs[16][4]; + MFloat pwFloatSortedInputs[16][4]; + + for (int e = 0; e < 16; e++) + { + for (int ch = 0; ch < 4; ch++) + sortedInputs[e][ch] = ParallelMath::MakeUInt15(0); + } + + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + for (int e = ParallelMath::Extract(firstElement, block); e < 16; e++) + { + ParallelMath::ScalarUInt16 sortBin = ParallelMath::Extract(sortBins[e], block); + int originalIndex = (sortBin & 15); + + for (int ch = 0; ch < 4; ch++) + ParallelMath::PutUInt15(sortedInputs[15 - e][ch], block, ParallelMath::Extract(pixels[originalIndex][ch], block)); + } + } + + for (int e = 0; e < 16; e++) + { + for (int ch = 0; ch < 4; ch++) + { + MFloat f = ParallelMath::ToFloat(sortedInputs[e][ch]); + floatSortedInputs[e][ch] = f; + pwFloatSortedInputs[e][ch] = f * channelWeights[ch]; + } + } + + for (int n0 = 0; n0 <= 15; n0++) + { + int remainingFor1 = 16 - n0; + if (remainingFor1 == 16) + remainingFor1 = 15; + + for (int n1 = 0; n1 <= remainingFor1; n1++) + { + int remainingFor2 = 16 - n1 - n0; + if (remainingFor2 == 16) + remainingFor2 = 15; + + for (int n2 = 0; n2 <= remainingFor2; n2++) + { + int n3 = 16 - n2 - n1 - n0; + + if (n3 == 16) + continue; + + int counts[4] = { n0, n1, n2, n3 }; + + TestCounts(flags, counts, 4, numElements, pixels, floatPixels, preWeightedPixels, alphaTest, floatSortedInputs, pwFloatSortedInputs, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, &rtn); + } + } + } + + TestSingleColor(flags, pixels, floatPixels, 4, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, &rtn); + + if (alphaTest) + { + for (int n0 = 0; n0 <= 15; n0++) + { + int remainingFor1 = 16 - n0; + if (remainingFor1 == 16) + remainingFor1 = 15; + + for (int n1 = 0; n1 <= remainingFor1; n1++) + { + int n2 = 16 - n1 - n0; + + if (n2 == 16) + continue; + + int counts[3] = { n0, n1, n2 }; + + TestCounts(flags, counts, 3, numElements, pixels, floatPixels, preWeightedPixels, alphaTest, floatSortedInputs, pwFloatSortedInputs, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, &rtn); + } + } + + TestSingleColor(flags, pixels, floatPixels, 3, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, &rtn); + } + } + else + { + int minRange = alphaTest ? 3 : 4; + + for (int range = minRange; range <= 4; range++) + { + int tweakRounds = BCCommon::TweakRoundsForRange(range); + if (tweakRounds > maxTweakRounds) + tweakRounds = maxTweakRounds; + + for (int tweak = 0; tweak < tweakRounds; tweak++) + { + MUInt15 endPoints[2][3]; + + ufep.FinishLDR(tweak, range, endPoints[0], endPoints[1]); + + for (int refine = 0; refine < numRefineRounds; refine++) + { + EndpointRefiner<3> refiner; + refiner.Init(range, channelWeights); + + TestEndpoints(flags, pixels, floatPixels, preWeightedPixels, endPoints, range, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, &refiner, &rtn); + + if (refine != numRefineRounds - 1) + refiner.GetRefinedEndpointsLDR(endPoints, &rtn); + } + } + } + } + + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + ParallelMath::ScalarUInt16 range = ParallelMath::Extract(bestRange, block); + assert(range == 3 || range == 4); + + ParallelMath::ScalarUInt16 compressedEP[2]; + for (int ep = 0; ep < 2; ep++) + { + ParallelMath::ScalarUInt16 endPoint[3]; + for (int ch = 0; ch < 3; ch++) + endPoint[ch] = ParallelMath::Extract(bestEndpoints[ep][ch], block); + + int compressed = (endPoint[0] & 0xf8) << 8; + compressed |= (endPoint[1] & 0xfc) << 3; + compressed |= (endPoint[2] & 0xf8) >> 3; + + compressedEP[ep] = static_cast<ParallelMath::ScalarUInt16>(compressed); + } + + int indexOrder[4]; + + if (range == 4) + { + if (compressedEP[0] == compressedEP[1]) + { + indexOrder[0] = 0; + indexOrder[1] = 0; + indexOrder[2] = 0; + indexOrder[3] = 0; + } + else if (compressedEP[0] < compressedEP[1]) + { + std::swap(compressedEP[0], compressedEP[1]); + indexOrder[0] = 1; + indexOrder[1] = 3; + indexOrder[2] = 2; + indexOrder[3] = 0; + } + else + { + indexOrder[0] = 0; + indexOrder[1] = 2; + indexOrder[2] = 3; + indexOrder[3] = 1; + } + } + else + { + assert(range == 3); + + if (compressedEP[0] > compressedEP[1]) + { + std::swap(compressedEP[0], compressedEP[1]); + indexOrder[0] = 1; + indexOrder[1] = 2; + indexOrder[2] = 0; + } + else + { + indexOrder[0] = 0; + indexOrder[1] = 2; + indexOrder[2] = 1; + } + indexOrder[3] = 3; + } + + packedBlocks[0] = static_cast<uint8_t>(compressedEP[0] & 0xff); + packedBlocks[1] = static_cast<uint8_t>((compressedEP[0] >> 8) & 0xff); + packedBlocks[2] = static_cast<uint8_t>(compressedEP[1] & 0xff); + packedBlocks[3] = static_cast<uint8_t>((compressedEP[1] >> 8) & 0xff); + + for (int i = 0; i < 16; i += 4) + { + int packedIndexes = 0; + for (int subi = 0; subi < 4; subi++) + { + ParallelMath::ScalarUInt16 index = ParallelMath::Extract(bestIndexes[i + subi], block); + packedIndexes |= (indexOrder[index] << (subi * 2)); + } + + packedBlocks[4 + i / 4] = static_cast<uint8_t>(packedIndexes); + } + + packedBlocks += packedBlockStride; + } + } + }; + + // Signed input blocks are converted into unsigned space, with the maximum value being 254 + void BiasSignedInput(PixelBlockU8 inputNormalized[ParallelMath::ParallelSize], const PixelBlockS8 inputSigned[ParallelMath::ParallelSize]) + { + for (size_t block = 0; block < ParallelMath::ParallelSize; block++) + { + const PixelBlockS8& inputSignedBlock = inputSigned[block]; + PixelBlockU8& inputNormalizedBlock = inputNormalized[block]; + + for (size_t px = 0; px < 16; px++) + { + for (size_t ch = 0; ch < 4; ch++) + inputNormalizedBlock.m_pixels[px][ch] = static_cast<uint8_t>(std::max<int>(inputSignedBlock.m_pixels[px][ch], -127) + 127); + } + } + } + + void FillWeights(const Options &options, float channelWeights[4]) + { + if (options.flags & Flags::Uniform) + channelWeights[0] = channelWeights[1] = channelWeights[2] = channelWeights[3] = 1.0f; + else + { + channelWeights[0] = options.redWeight; + channelWeights[1] = options.greenWeight; + channelWeights[2] = options.blueWeight; + channelWeights[3] = options.alphaWeight; + } + } + } + + namespace Kernels + { + void EncodeBC7(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::BC7Computer::Pack(options.flags, pBlocks + blockBase, pBC, channelWeights, options.seedPoints, options.refineRoundsBC7); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC6HU(uint8_t *pBC, const PixelBlockF16 *pBlocks, const cvtt::Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::BC6HComputer::Pack(options.flags, pBlocks + blockBase, pBC, channelWeights, false, options.seedPoints, options.refineRoundsBC6H); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC6HS(uint8_t *pBC, const PixelBlockF16 *pBlocks, const cvtt::Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::BC6HComputer::Pack(options.flags, pBlocks + blockBase, pBC, channelWeights, true, options.seedPoints, options.refineRoundsBC6H); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC1(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::S3TCComputer::PackRGB(options.flags, pBlocks + blockBase, pBC, 8, channelWeights, true, options.threshold, (options.flags & Flags::S3TC_Exhaustive) != 0, options.seedPoints, options.refineRoundsS3TC); + pBC += ParallelMath::ParallelSize * 8; + } + } + + void EncodeBC2(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::S3TCComputer::PackRGB(options.flags, pBlocks + blockBase, pBC + 8, 16, channelWeights, false, 1.0f, (options.flags & Flags::S3TC_Exhaustive) != 0, options.seedPoints, options.refineRoundsS3TC); + Internal::S3TCComputer::PackExplicitAlpha(options.flags, pBlocks + blockBase, 3, pBC, 16); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC3(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::S3TCComputer::PackRGB(options.flags, pBlocks + blockBase, pBC + 8, 16, channelWeights, false, 1.0f, (options.flags & Flags::S3TC_Exhaustive) != 0, options.seedPoints, options.refineRoundsS3TC); + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 3, pBC, 16, false, options.seedPoints, options.refineRoundsIIC); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC4U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 0, pBC, 8, false, options.seedPoints, options.refineRoundsIIC); + pBC += ParallelMath::ParallelSize * 8; + } + } + + void EncodeBC4S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + PixelBlockU8 inputBlocks[ParallelMath::ParallelSize]; + Internal::BiasSignedInput(inputBlocks, pBlocks + blockBase); + + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, inputBlocks, 0, pBC, 8, true, options.seedPoints, options.refineRoundsIIC); + pBC += ParallelMath::ParallelSize * 8; + } + } + + void EncodeBC5U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 0, pBC, 16, false, options.seedPoints, options.refineRoundsIIC); + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 1, pBC + 8, 16, false, options.seedPoints, options.refineRoundsIIC); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC5S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + PixelBlockU8 inputBlocks[ParallelMath::ParallelSize]; + Internal::BiasSignedInput(inputBlocks, pBlocks + blockBase); + + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, inputBlocks, 0, pBC, 16, true, options.seedPoints, options.refineRoundsIIC); + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, inputBlocks, 1, pBC + 8, 16, true, options.seedPoints, options.refineRoundsIIC); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void DecodeBC7(PixelBlockU8 *pBlocks, const uint8_t *pBC) + { + assert(pBlocks); + assert(pBC); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase++) + { + Internal::BC7Computer::UnpackOne(pBlocks[blockBase], pBC); + pBC += 16; + } + } + + void DecodeBC6HU(PixelBlockF16 *pBlocks, const uint8_t *pBC) + { + assert(pBlocks); + assert(pBC); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase++) + { + Internal::BC6HComputer::UnpackOne(pBlocks[blockBase], pBC, false); + pBC += 16; + } + } + + void DecodeBC6HS(PixelBlockF16 *pBlocks, const uint8_t *pBC) + { + assert(pBlocks); + assert(pBC); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase++) + { + Internal::BC6HComputer::UnpackOne(pBlocks[blockBase], pBC, true); + pBC += 16; + } + } + } +} diff --git a/thirdparty/cvtt/ConvectionKernels.h b/thirdparty/cvtt/ConvectionKernels.h new file mode 100644 index 0000000000..fb5ca130f9 --- /dev/null +++ b/thirdparty/cvtt/ConvectionKernels.h @@ -0,0 +1,145 @@ +/* +Convection Texture Tools +Copyright (c) 2018 Eric Lasota + +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. +*/ +#pragma once +#ifndef __CVTT_CONVECTION_KERNELS__ +#define __CVTT_CONVECTION_KERNELS__ + +#include <stdint.h> + +namespace cvtt +{ + namespace Flags + { + // Enable partitioned modes in BC7 encoding (slower, better quality) + const uint32_t BC7_EnablePartitioning = 0x001; + + // Enable 3-partition modes in BC7 encoding (slower, better quality, requires BC7_EnablePartitioning) + const uint32_t BC7_Enable3Subsets = 0x002; + + // Enable dual-plane modes in BC7 encoding (slower, better quality) + const uint32_t BC7_EnableDualPlane = 0x004; + + // Use fast indexing in BC7 encoding (about 2x faster, slightly worse quality) + const uint32_t BC7_FastIndexing = 0x008; + + // Try precomputed single-color lookups where applicable (slightly slower, small quality increase on specific blocks) + const uint32_t BC7_TrySingleColor = 0x010; + + // Don't allow non-zero or non-max alpha values in blocks that only contain one or the other + const uint32_t BC7_RespectPunchThrough = 0x020; + + // Use fast indexing in HDR formats (faster, worse quality) + const uint32_t BC6H_FastIndexing = 0x040; + + // Exhaustive search RGB orderings when encoding BC1-BC3 (much slower, better quality) + const uint32_t S3TC_Exhaustive = 0x080; + + // Penalize distant endpoints, improving quality on inaccurate GPU decoders + const uint32_t S3TC_Paranoid = 0x100; + + // Uniform color channel importance + const uint32_t Uniform = 0x200; + + // Misc useful default flag combinations + const uint32_t Fastest = (BC6H_FastIndexing | S3TC_Paranoid); + const uint32_t Faster = (BC7_EnableDualPlane | BC6H_FastIndexing | S3TC_Paranoid); + const uint32_t Fast = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_FastIndexing | S3TC_Paranoid); + const uint32_t Default = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_Enable3Subsets | BC7_FastIndexing | S3TC_Paranoid); + const uint32_t Better = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_Enable3Subsets | S3TC_Paranoid | S3TC_Exhaustive); + const uint32_t Ultra = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_Enable3Subsets | BC7_TrySingleColor | S3TC_Paranoid | S3TC_Exhaustive); + } + + const unsigned int NumParallelBlocks = 8; + + struct Options + { + uint32_t flags; // Bitmask of cvtt::Flags values + float threshold; // Alpha test threshold for BC1 + float redWeight; // Red channel importance + float greenWeight; // Green channel importance + float blueWeight; // Blue channel importance + float alphaWeight; // Alpha channel importance + + int refineRoundsBC7; // Number of refine rounds for BC7 + int refineRoundsBC6H; // Number of refine rounds for BC6H (max 3) + int refineRoundsIIC; // Number of refine rounds for independent interpolated channels (BC3 alpha, BC4, BC5) + int refineRoundsS3TC; // Number of refine rounds for S3TC RGB + + int seedPoints; // Number of seed points (min 1, max 4) + + Options() + : flags(Flags::Default) + , threshold(0.5f) + , redWeight(0.2125f / 0.7154f) + , greenWeight(1.0f) + , blueWeight(0.0721f / 0.7154f) + , alphaWeight(1.0f) + , refineRoundsBC7(2) + , refineRoundsBC6H(3) + , refineRoundsIIC(8) + , refineRoundsS3TC(2) + , seedPoints(4) + { + } + }; + + // RGBA input block for unsigned 8-bit formats + struct PixelBlockU8 + { + uint8_t m_pixels[16][4]; + }; + + // RGBA input block for signed 8-bit formats + struct PixelBlockS8 + { + int8_t m_pixels[16][4]; + }; + + // RGBA input block for half-precision float formats (bit-cast to int16_t) + struct PixelBlockF16 + { + int16_t m_pixels[16][4]; + }; + + namespace Kernels + { + // NOTE: All functions accept and output NumParallelBlocks blocks at once + void EncodeBC1(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + void EncodeBC2(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + void EncodeBC3(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + void EncodeBC4U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + void EncodeBC4S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options); + void EncodeBC5U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + void EncodeBC5S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options); + void EncodeBC6HU(uint8_t *pBC, const PixelBlockF16 *pBlocks, const Options &options); + void EncodeBC6HS(uint8_t *pBC, const PixelBlockF16 *pBlocks, const Options &options); + void EncodeBC7(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + + void DecodeBC6HU(PixelBlockF16 *pBlocks, const uint8_t *pBC); + void DecodeBC6HS(PixelBlockF16 *pBlocks, const uint8_t *pBC); + void DecodeBC7(PixelBlockU8 *pBlocks, const uint8_t *pBC); + } +} + +#endif diff --git a/thirdparty/cvtt/ConvectionKernels_BC7_SingleColor.h b/thirdparty/cvtt/ConvectionKernels_BC7_SingleColor.h new file mode 100644 index 0000000000..b5564c0dab --- /dev/null +++ b/thirdparty/cvtt/ConvectionKernels_BC7_SingleColor.h @@ -0,0 +1,1940 @@ +#pragma once +#include <stdint.h> + +namespace cvtt { namespace Tables { namespace BC7SC { + +struct TableEntry +{ + uint8_t m_min; + uint8_t m_max; + uint8_t m_actualColor; +}; + +struct Table +{ + uint8_t m_index; + uint8_t m_pBits; + TableEntry m_entries[256]; +}; + +Table g_mode0_p00_i1= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 16, 2 }, { 0, 16, 2 }, { 0, 33, 5 }, { 0, 33, 5 }, { 0, 33, 5 }, { 0, 49, 7 }, + { 0, 49, 7 }, { 0, 66, 9 }, { 0, 66, 9 }, { 0, 82, 12 }, { 0, 82, 12 }, { 0, 82, 12 }, { 0, 99, 14 }, { 0, 99, 14 }, + { 0, 115, 16 }, { 0, 115, 16 }, { 16, 33, 18 }, { 0, 132, 19 }, { 0, 132, 19 }, { 0, 148, 21 }, { 0, 148, 21 }, { 0, 165, 23 }, + { 0, 165, 23 }, { 0, 181, 25 }, { 0, 181, 25 }, { 0, 198, 28 }, { 0, 198, 28 }, { 0, 198, 28 }, { 0, 214, 30 }, { 33, 16, 31 }, + { 0, 231, 32 }, { 33, 33, 33 }, { 0, 247, 35 }, { 0, 247, 35 }, { 0, 247, 35 }, { 16, 165, 37 }, { 33, 66, 38 }, { 16, 181, 39 }, + { 33, 82, 40 }, { 16, 198, 42 }, { 16, 198, 42 }, { 16, 198, 42 }, { 16, 214, 44 }, { 33, 115, 45 }, { 16, 231, 46 }, { 33, 132, 47 }, + { 16, 247, 48 }, { 33, 148, 49 }, { 33, 148, 49 }, { 49, 66, 51 }, { 33, 165, 52 }, { 33, 165, 52 }, { 33, 181, 54 }, { 33, 181, 54 }, + { 33, 198, 56 }, { 66, 0, 57 }, { 33, 214, 58 }, { 66, 16, 59 }, { 33, 231, 61 }, { 33, 231, 61 }, { 33, 231, 61 }, { 33, 247, 63 }, + { 66, 49, 64 }, { 49, 165, 65 }, { 66, 66, 66 }, { 49, 181, 68 }, { 49, 181, 68 }, { 49, 181, 68 }, { 49, 198, 70 }, { 66, 99, 71 }, + { 49, 214, 72 }, { 66, 115, 73 }, { 49, 231, 75 }, { 49, 231, 75 }, { 49, 231, 75 }, { 49, 247, 77 }, { 66, 148, 78 }, { 66, 148, 78 }, + { 66, 165, 80 }, { 66, 165, 80 }, { 66, 181, 82 }, { 66, 181, 82 }, { 82, 99, 84 }, { 66, 198, 85 }, { 66, 198, 85 }, { 66, 214, 87 }, + { 66, 214, 87 }, { 66, 231, 89 }, { 99, 33, 90 }, { 66, 247, 91 }, { 99, 49, 92 }, { 82, 165, 94 }, { 82, 165, 94 }, { 82, 165, 94 }, + { 82, 181, 96 }, { 99, 82, 97 }, { 82, 198, 98 }, { 99, 99, 99 }, { 82, 214, 101 }, { 82, 214, 101 }, { 82, 214, 101 }, { 82, 231, 103 }, + { 99, 132, 104 }, { 82, 247, 105 }, { 99, 148, 106 }, { 99, 148, 106 }, { 99, 165, 108 }, { 99, 165, 108 }, { 115, 82, 110 }, { 99, 181, 111 }, + { 99, 181, 111 }, { 99, 198, 113 }, { 99, 198, 113 }, { 99, 214, 115 }, { 132, 16, 116 }, { 115, 132, 117 }, { 99, 231, 118 }, { 99, 231, 118 }, + { 99, 247, 120 }, { 99, 247, 120 }, { 115, 165, 122 }, { 132, 66, 123 }, { 115, 181, 124 }, { 132, 82, 125 }, { 115, 198, 127 }, { 115, 198, 127 }, + { 115, 198, 127 }, { 115, 214, 129 }, { 132, 115, 130 }, { 115, 231, 131 }, { 132, 132, 132 }, { 115, 247, 134 }, { 115, 247, 134 }, { 115, 247, 134 }, + { 148, 66, 136 }, { 132, 165, 137 }, { 132, 165, 137 }, { 132, 181, 139 }, { 132, 181, 139 }, { 132, 198, 141 }, { 165, 0, 142 }, { 148, 115, 143 }, + { 132, 214, 144 }, { 132, 214, 144 }, { 132, 231, 146 }, { 132, 231, 146 }, { 132, 247, 148 }, { 165, 49, 149 }, { 148, 165, 150 }, { 165, 66, 151 }, + { 148, 181, 153 }, { 148, 181, 153 }, { 148, 181, 153 }, { 148, 198, 155 }, { 165, 99, 156 }, { 148, 214, 157 }, { 165, 115, 158 }, { 148, 231, 160 }, + { 148, 231, 160 }, { 148, 231, 160 }, { 148, 247, 162 }, { 165, 148, 163 }, { 165, 148, 163 }, { 165, 165, 165 }, { 165, 165, 165 }, { 165, 181, 167 }, + { 165, 181, 167 }, { 181, 99, 169 }, { 165, 198, 170 }, { 165, 198, 170 }, { 165, 214, 172 }, { 165, 214, 172 }, { 165, 231, 174 }, { 198, 33, 175 }, + { 181, 148, 176 }, { 165, 247, 177 }, { 165, 247, 177 }, { 181, 165, 179 }, { 181, 165, 179 }, { 181, 181, 181 }, { 198, 82, 182 }, { 181, 198, 183 }, + { 198, 99, 184 }, { 181, 214, 186 }, { 181, 214, 186 }, { 181, 214, 186 }, { 181, 231, 188 }, { 198, 132, 189 }, { 181, 247, 190 }, { 198, 148, 191 }, + { 198, 148, 191 }, { 198, 165, 193 }, { 198, 165, 193 }, { 214, 82, 195 }, { 198, 181, 196 }, { 198, 181, 196 }, { 198, 198, 198 }, { 231, 0, 199 }, + { 198, 214, 200 }, { 231, 16, 201 }, { 214, 132, 202 }, { 198, 231, 203 }, { 198, 231, 203 }, { 198, 247, 205 }, { 198, 247, 205 }, { 214, 165, 207 }, + { 231, 66, 208 }, { 214, 181, 209 }, { 231, 82, 210 }, { 214, 198, 212 }, { 214, 198, 212 }, { 214, 198, 212 }, { 214, 214, 214 }, { 231, 115, 215 }, + { 214, 231, 216 }, { 231, 132, 217 }, { 214, 247, 219 }, { 214, 247, 219 }, { 214, 247, 219 }, { 231, 165, 222 }, { 231, 165, 222 }, { 231, 165, 222 }, + { 231, 181, 224 }, { 231, 181, 224 }, { 231, 198, 226 }, { 231, 198, 226 }, { 247, 115, 228 }, { 231, 214, 229 }, { 231, 214, 229 }, { 231, 231, 231 }, + { 231, 231, 231 }, { 231, 247, 233 }, { 231, 247, 233 }, { 247, 165, 235 }, { 247, 165, 235 }, { 247, 181, 238 }, { 247, 181, 238 }, { 247, 181, 238 }, + { 247, 198, 240 }, { 247, 198, 240 }, { 247, 214, 242 }, { 247, 214, 242 }, { 247, 231, 245 }, { 247, 231, 245 }, { 247, 231, 245 }, { 247, 247, 247 }, + { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, + } +}; + +Table g_mode0_p00_i2= +{ + 2, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 16, 5 }, + { 0, 33, 9 }, { 0, 33, 9 }, { 0, 33, 9 }, { 16, 0, 12 }, { 16, 0, 12 }, { 0, 49, 14 }, { 0, 49, 14 }, { 0, 49, 14 }, + { 16, 16, 16 }, { 16, 16, 16 }, { 0, 66, 19 }, { 0, 66, 19 }, { 0, 66, 19 }, { 16, 33, 21 }, { 0, 82, 23 }, { 0, 82, 23 }, + { 33, 0, 24 }, { 16, 49, 25 }, { 16, 49, 25 }, { 0, 99, 28 }, { 0, 99, 28 }, { 0, 99, 28 }, { 16, 66, 30 }, { 0, 115, 32 }, + { 0, 115, 32 }, { 33, 33, 33 }, { 16, 82, 35 }, { 16, 82, 35 }, { 0, 132, 37 }, { 0, 132, 37 }, { 33, 49, 38 }, { 16, 99, 39 }, + { 49, 16, 40 }, { 0, 148, 42 }, { 0, 148, 42 }, { 0, 148, 42 }, { 16, 115, 44 }, { 49, 33, 45 }, { 0, 165, 46 }, { 33, 82, 47 }, + { 16, 132, 49 }, { 16, 132, 49 }, { 0, 181, 51 }, { 0, 181, 51 }, { 33, 99, 52 }, { 16, 148, 53 }, { 49, 66, 54 }, { 0, 198, 56 }, + { 0, 198, 56 }, { 66, 33, 57 }, { 16, 165, 58 }, { 82, 0, 59 }, { 0, 214, 60 }, { 33, 132, 61 }, { 16, 181, 62 }, { 49, 99, 63 }, + { 0, 231, 65 }, { 0, 231, 65 }, { 66, 66, 66 }, { 16, 198, 67 }, { 49, 115, 68 }, { 0, 247, 69 }, { 33, 165, 70 }, { 66, 82, 71 }, + { 16, 214, 72 }, { 82, 49, 73 }, { 33, 181, 75 }, { 33, 181, 75 }, { 16, 231, 76 }, { 49, 148, 77 }, { 82, 66, 78 }, { 33, 198, 79 }, + { 66, 115, 80 }, { 16, 247, 81 }, { 49, 165, 82 }, { 115, 0, 83 }, { 33, 214, 84 }, { 66, 132, 85 }, { 49, 181, 86 }, { 82, 99, 87 }, + { 33, 231, 89 }, { 33, 231, 89 }, { 99, 66, 90 }, { 49, 198, 91 }, { 115, 33, 92 }, { 33, 247, 93 }, { 66, 165, 94 }, { 49, 214, 95 }, + { 82, 132, 96 }, { 66, 181, 98 }, { 66, 181, 98 }, { 99, 99, 99 }, { 49, 231, 100 }, { 82, 148, 101 }, { 66, 198, 103 }, { 66, 198, 103 }, + { 99, 115, 104 }, { 49, 247, 105 }, { 115, 82, 106 }, { 66, 214, 108 }, { 66, 214, 108 }, { 132, 49, 109 }, { 82, 181, 110 }, { 115, 99, 111 }, + { 66, 231, 112 }, { 99, 148, 113 }, { 82, 198, 115 }, { 82, 198, 115 }, { 148, 33, 116 }, { 66, 247, 117 }, { 99, 165, 118 }, { 82, 214, 119 }, + { 115, 132, 120 }, { 99, 181, 122 }, { 99, 181, 122 }, { 132, 99, 123 }, { 82, 231, 124 }, { 148, 66, 125 }, { 99, 198, 127 }, { 99, 198, 127 }, + { 82, 247, 128 }, { 115, 165, 129 }, { 181, 0, 130 }, { 99, 214, 131 }, { 132, 132, 132 }, { 115, 181, 134 }, { 115, 181, 134 }, { 181, 16, 135 }, + { 99, 231, 136 }, { 132, 148, 137 }, { 115, 198, 138 }, { 148, 115, 139 }, { 99, 247, 141 }, { 99, 247, 141 }, { 165, 82, 142 }, { 115, 214, 143 }, + { 148, 132, 144 }, { 132, 181, 146 }, { 132, 181, 146 }, { 198, 16, 147 }, { 115, 231, 148 }, { 181, 66, 149 }, { 132, 198, 151 }, { 132, 198, 151 }, + { 115, 247, 152 }, { 148, 165, 153 }, { 214, 0, 154 }, { 132, 214, 155 }, { 165, 132, 156 }, { 148, 181, 157 }, { 181, 99, 158 }, { 132, 231, 160 }, + { 132, 231, 160 }, { 198, 66, 161 }, { 148, 198, 162 }, { 214, 33, 163 }, { 132, 247, 164 }, { 165, 165, 165 }, { 231, 0, 166 }, { 148, 214, 167 }, + { 214, 49, 168 }, { 165, 181, 170 }, { 165, 181, 170 }, { 148, 231, 171 }, { 181, 148, 172 }, { 165, 198, 174 }, { 165, 198, 174 }, { 198, 115, 175 }, + { 148, 247, 176 }, { 181, 165, 177 }, { 247, 0, 178 }, { 165, 214, 179 }, { 231, 49, 180 }, { 181, 181, 181 }, { 214, 99, 182 }, { 165, 231, 184 }, + { 165, 231, 184 }, { 231, 66, 185 }, { 181, 198, 186 }, { 247, 33, 187 }, { 165, 247, 188 }, { 198, 165, 189 }, { 181, 214, 190 }, { 214, 132, 191 }, + { 198, 181, 193 }, { 198, 181, 193 }, { 231, 99, 194 }, { 181, 231, 195 }, { 247, 66, 196 }, { 198, 198, 198 }, { 198, 198, 198 }, { 181, 247, 200 }, + { 181, 247, 200 }, { 247, 82, 201 }, { 198, 214, 203 }, { 198, 214, 203 }, { 198, 214, 203 }, { 214, 181, 205 }, { 198, 231, 207 }, { 198, 231, 207 }, + { 231, 148, 208 }, { 214, 198, 210 }, { 214, 198, 210 }, { 198, 247, 212 }, { 198, 247, 212 }, { 198, 247, 212 }, { 214, 214, 214 }, { 247, 132, 215 }, + { 231, 181, 217 }, { 231, 181, 217 }, { 214, 231, 219 }, { 214, 231, 219 }, { 214, 231, 219 }, { 231, 198, 222 }, { 231, 198, 222 }, { 214, 247, 223 }, + { 247, 165, 224 }, { 231, 214, 226 }, { 231, 214, 226 }, { 231, 214, 226 }, { 247, 181, 228 }, { 247, 181, 228 }, { 231, 231, 231 }, { 231, 231, 231 }, + { 231, 231, 231 }, { 247, 198, 233 }, { 247, 198, 233 }, { 231, 247, 236 }, { 231, 247, 236 }, { 231, 247, 236 }, { 247, 214, 238 }, { 247, 214, 238 }, + { 247, 214, 238 }, { 247, 231, 243 }, { 247, 231, 243 }, { 247, 231, 243 }, { 247, 231, 243 }, { 247, 231, 243 }, { 247, 247, 247 }, { 247, 247, 247 }, + { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, + } +}; + +Table g_mode0_p00_i3= +{ + 3, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 16, 7 }, { 0, 16, 7 }, { 0, 16, 7 }, { 0, 16, 7 }, + { 0, 16, 7 }, { 16, 0, 9 }, { 16, 0, 9 }, { 16, 0, 9 }, { 0, 33, 14 }, { 0, 33, 14 }, { 0, 33, 14 }, { 0, 33, 14 }, + { 16, 16, 16 }, { 16, 16, 16 }, { 33, 0, 19 }, { 33, 0, 19 }, { 0, 49, 21 }, { 0, 49, 21 }, { 0, 49, 21 }, { 16, 33, 23 }, + { 16, 33, 23 }, { 33, 16, 26 }, { 33, 16, 26 }, { 0, 66, 28 }, { 0, 66, 28 }, { 0, 66, 28 }, { 16, 49, 30 }, { 16, 49, 30 }, + { 33, 33, 33 }, { 33, 33, 33 }, { 0, 82, 35 }, { 0, 82, 35 }, { 0, 82, 35 }, { 16, 66, 37 }, { 66, 0, 38 }, { 33, 49, 40 }, + { 33, 49, 40 }, { 0, 99, 42 }, { 0, 99, 42 }, { 0, 99, 42 }, { 16, 82, 44 }, { 66, 16, 45 }, { 33, 66, 47 }, { 33, 66, 47 }, + { 0, 115, 49 }, { 0, 115, 49 }, { 0, 115, 49 }, { 16, 99, 51 }, { 66, 33, 52 }, { 33, 82, 54 }, { 33, 82, 54 }, { 0, 132, 56 }, + { 0, 132, 56 }, { 99, 0, 57 }, { 16, 115, 58 }, { 66, 49, 59 }, { 33, 99, 61 }, { 33, 99, 61 }, { 0, 148, 62 }, { 49, 82, 63 }, + { 99, 16, 64 }, { 16, 132, 65 }, { 66, 66, 66 }, { 33, 115, 68 }, { 33, 115, 68 }, { 0, 165, 70 }, { 0, 165, 70 }, { 99, 33, 71 }, + { 16, 148, 72 }, { 66, 82, 73 }, { 33, 132, 75 }, { 33, 132, 75 }, { 0, 181, 76 }, { 49, 115, 77 }, { 99, 49, 78 }, { 16, 165, 79 }, + { 66, 99, 80 }, { 33, 148, 82 }, { 33, 148, 82 }, { 132, 16, 83 }, { 0, 198, 84 }, { 99, 66, 85 }, { 16, 181, 86 }, { 66, 115, 87 }, + { 33, 165, 89 }, { 33, 165, 89 }, { 0, 214, 90 }, { 49, 148, 91 }, { 99, 82, 92 }, { 16, 198, 93 }, { 66, 132, 94 }, { 33, 181, 95 }, + { 82, 115, 96 }, { 0, 231, 97 }, { 49, 165, 98 }, { 99, 99, 99 }, { 16, 214, 100 }, { 66, 148, 101 }, { 165, 16, 102 }, { 33, 198, 103 }, + { 0, 247, 104 }, { 49, 181, 105 }, { 99, 115, 106 }, { 16, 231, 107 }, { 66, 165, 108 }, { 33, 214, 109 }, { 82, 148, 110 }, { 132, 82, 111 }, + { 49, 198, 112 }, { 16, 247, 113 }, { 198, 0, 114 }, { 66, 181, 115 }, { 165, 49, 116 }, { 33, 231, 117 }, { 132, 99, 118 }, { 49, 214, 119 }, + { 99, 148, 120 }, { 198, 16, 121 }, { 66, 198, 122 }, { 33, 247, 123 }, { 82, 181, 124 }, { 132, 115, 125 }, { 49, 231, 126 }, { 99, 165, 127 }, + { 66, 214, 128 }, { 115, 148, 129 }, { 165, 82, 130 }, { 82, 198, 131 }, { 132, 132, 132 }, { 49, 247, 133 }, { 99, 181, 134 }, { 198, 49, 135 }, + { 66, 231, 136 }, { 165, 99, 137 }, { 82, 214, 138 }, { 132, 148, 139 }, { 231, 16, 140 }, { 99, 198, 141 }, { 66, 247, 142 }, { 115, 181, 143 }, + { 165, 115, 144 }, { 82, 231, 145 }, { 132, 165, 146 }, { 231, 33, 147 }, { 99, 214, 148 }, { 198, 82, 149 }, { 115, 198, 150 }, { 165, 132, 151 }, + { 82, 247, 152 }, { 132, 181, 153 }, { 231, 49, 154 }, { 99, 231, 155 }, { 198, 99, 156 }, { 115, 214, 157 }, { 165, 148, 158 }, { 132, 198, 160 }, + { 132, 198, 160 }, { 99, 247, 161 }, { 148, 181, 162 }, { 198, 115, 163 }, { 115, 231, 164 }, { 165, 165, 165 }, { 132, 214, 167 }, { 132, 214, 167 }, + { 231, 82, 168 }, { 148, 198, 169 }, { 198, 132, 170 }, { 115, 247, 171 }, { 165, 181, 172 }, { 132, 231, 174 }, { 132, 231, 174 }, { 231, 99, 175 }, + { 148, 214, 176 }, { 198, 148, 177 }, { 165, 198, 179 }, { 165, 198, 179 }, { 132, 247, 181 }, { 132, 247, 181 }, { 231, 115, 182 }, { 148, 231, 183 }, + { 198, 165, 184 }, { 247, 99, 185 }, { 165, 214, 186 }, { 165, 214, 186 }, { 181, 198, 188 }, { 231, 132, 189 }, { 148, 247, 190 }, { 198, 181, 191 }, + { 165, 231, 193 }, { 165, 231, 193 }, { 165, 231, 193 }, { 181, 214, 195 }, { 231, 148, 196 }, { 198, 198, 198 }, { 198, 198, 198 }, { 165, 247, 200 }, + { 165, 247, 200 }, { 165, 247, 200 }, { 181, 231, 202 }, { 231, 165, 203 }, { 198, 214, 205 }, { 198, 214, 205 }, { 198, 214, 205 }, { 214, 198, 207 }, + { 181, 247, 209 }, { 181, 247, 209 }, { 231, 181, 210 }, { 198, 231, 212 }, { 198, 231, 212 }, { 198, 231, 212 }, { 214, 214, 214 }, { 214, 214, 214 }, + { 231, 198, 217 }, { 231, 198, 217 }, { 198, 247, 219 }, { 198, 247, 219 }, { 198, 247, 219 }, { 214, 231, 221 }, { 214, 231, 221 }, { 231, 214, 224 }, + { 231, 214, 224 }, { 231, 214, 224 }, { 247, 198, 226 }, { 214, 247, 228 }, { 214, 247, 228 }, { 214, 247, 228 }, { 231, 231, 231 }, { 231, 231, 231 }, + { 231, 231, 231 }, { 247, 214, 233 }, { 247, 214, 233 }, { 247, 214, 233 }, { 231, 247, 238 }, { 231, 247, 238 }, { 231, 247, 238 }, { 231, 247, 238 }, + { 247, 231, 240 }, { 247, 231, 240 }, { 247, 231, 240 }, { 247, 231, 240 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, + { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, + } +}; + +Table g_mode0_p01_i1= +{ + 1, + 2, + { + { 0, 8, 1 }, { 0, 8, 1 }, { 0, 8, 1 }, { 0, 24, 3 }, { 0, 24, 3 }, { 0, 41, 6 }, { 0, 41, 6 }, { 0, 41, 6 }, + { 0, 57, 8 }, { 0, 57, 8 }, { 0, 74, 10 }, { 0, 74, 10 }, { 0, 90, 13 }, { 0, 90, 13 }, { 0, 90, 13 }, { 0, 107, 15 }, + { 0, 107, 15 }, { 0, 123, 17 }, { 0, 123, 17 }, { 0, 140, 20 }, { 0, 140, 20 }, { 0, 140, 20 }, { 0, 156, 22 }, { 0, 156, 22 }, + { 0, 173, 24 }, { 0, 173, 24 }, { 16, 90, 26 }, { 0, 189, 27 }, { 0, 189, 27 }, { 0, 206, 29 }, { 0, 206, 29 }, { 0, 222, 31 }, + { 33, 24, 32 }, { 16, 140, 33 }, { 0, 239, 34 }, { 0, 239, 34 }, { 0, 255, 36 }, { 0, 255, 36 }, { 16, 173, 38 }, { 33, 74, 39 }, + { 16, 189, 40 }, { 33, 90, 41 }, { 16, 206, 43 }, { 16, 206, 43 }, { 16, 206, 43 }, { 16, 222, 45 }, { 33, 123, 46 }, { 16, 239, 47 }, + { 33, 140, 48 }, { 16, 255, 50 }, { 16, 255, 50 }, { 16, 255, 50 }, { 33, 173, 53 }, { 33, 173, 53 }, { 33, 173, 53 }, { 33, 189, 55 }, + { 33, 189, 55 }, { 33, 206, 57 }, { 66, 8, 58 }, { 49, 123, 59 }, { 33, 222, 60 }, { 33, 222, 60 }, { 33, 239, 62 }, { 33, 239, 62 }, + { 33, 255, 64 }, { 66, 57, 65 }, { 49, 173, 66 }, { 66, 74, 67 }, { 49, 189, 69 }, { 49, 189, 69 }, { 49, 189, 69 }, { 49, 206, 71 }, + { 66, 107, 72 }, { 49, 222, 73 }, { 66, 123, 74 }, { 49, 239, 76 }, { 49, 239, 76 }, { 49, 239, 76 }, { 49, 255, 78 }, { 66, 156, 79 }, + { 66, 156, 79 }, { 66, 173, 81 }, { 66, 173, 81 }, { 66, 189, 83 }, { 66, 189, 83 }, { 66, 206, 86 }, { 66, 206, 86 }, { 66, 206, 86 }, + { 66, 222, 88 }, { 66, 222, 88 }, { 66, 239, 90 }, { 99, 41, 91 }, { 82, 156, 92 }, { 66, 255, 93 }, { 66, 255, 93 }, { 82, 173, 95 }, + { 82, 173, 95 }, { 82, 189, 97 }, { 99, 90, 98 }, { 82, 206, 99 }, { 99, 107, 100 }, { 82, 222, 102 }, { 82, 222, 102 }, { 82, 222, 102 }, + { 82, 239, 104 }, { 99, 140, 105 }, { 82, 255, 106 }, { 99, 156, 107 }, { 99, 156, 107 }, { 99, 173, 109 }, { 99, 173, 109 }, { 115, 90, 111 }, + { 99, 189, 112 }, { 99, 189, 112 }, { 99, 206, 114 }, { 132, 8, 115 }, { 99, 222, 116 }, { 132, 24, 117 }, { 99, 239, 119 }, { 99, 239, 119 }, + { 99, 239, 119 }, { 99, 255, 121 }, { 99, 255, 121 }, { 115, 173, 123 }, { 132, 74, 124 }, { 115, 189, 125 }, { 132, 90, 126 }, { 115, 206, 128 }, + { 115, 206, 128 }, { 115, 206, 128 }, { 115, 222, 130 }, { 132, 123, 131 }, { 115, 239, 132 }, { 132, 140, 133 }, { 115, 255, 135 }, { 115, 255, 135 }, + { 115, 255, 135 }, { 132, 173, 138 }, { 132, 173, 138 }, { 132, 173, 138 }, { 132, 189, 140 }, { 132, 189, 140 }, { 132, 206, 142 }, { 165, 8, 143 }, + { 148, 123, 144 }, { 132, 222, 145 }, { 132, 222, 145 }, { 132, 239, 147 }, { 165, 41, 148 }, { 132, 255, 149 }, { 165, 57, 150 }, { 148, 173, 152 }, + { 148, 173, 152 }, { 148, 173, 152 }, { 148, 189, 154 }, { 148, 189, 154 }, { 148, 206, 156 }, { 165, 107, 157 }, { 148, 222, 158 }, { 165, 123, 159 }, + { 148, 239, 161 }, { 148, 239, 161 }, { 148, 239, 161 }, { 148, 255, 163 }, { 165, 156, 164 }, { 165, 156, 164 }, { 165, 173, 166 }, { 165, 173, 166 }, + { 165, 189, 168 }, { 165, 189, 168 }, { 165, 206, 171 }, { 165, 206, 171 }, { 165, 206, 171 }, { 165, 222, 173 }, { 198, 24, 174 }, { 165, 239, 175 }, + { 198, 41, 176 }, { 181, 156, 177 }, { 165, 255, 178 }, { 165, 255, 178 }, { 181, 173, 180 }, { 198, 74, 181 }, { 181, 189, 182 }, { 198, 90, 183 }, + { 181, 206, 185 }, { 181, 206, 185 }, { 181, 206, 185 }, { 181, 222, 187 }, { 181, 222, 187 }, { 181, 239, 189 }, { 198, 140, 190 }, { 181, 255, 191 }, + { 198, 156, 192 }, { 198, 156, 192 }, { 198, 173, 194 }, { 198, 173, 194 }, { 198, 189, 197 }, { 198, 189, 197 }, { 198, 189, 197 }, { 198, 206, 199 }, + { 231, 8, 200 }, { 198, 222, 201 }, { 231, 24, 202 }, { 198, 239, 204 }, { 198, 239, 204 }, { 198, 239, 204 }, { 198, 255, 206 }, { 231, 57, 207 }, + { 214, 173, 208 }, { 231, 74, 209 }, { 214, 189, 210 }, { 231, 90, 211 }, { 214, 206, 213 }, { 214, 206, 213 }, { 231, 107, 214 }, { 214, 222, 215 }, + { 231, 123, 216 }, { 214, 239, 218 }, { 214, 239, 218 }, { 214, 239, 218 }, { 214, 255, 220 }, { 214, 255, 220 }, { 231, 173, 223 }, { 231, 173, 223 }, + { 231, 173, 223 }, { 231, 189, 225 }, { 231, 189, 225 }, { 231, 206, 227 }, { 231, 206, 227 }, { 231, 222, 230 }, { 231, 222, 230 }, { 231, 222, 230 }, + { 231, 239, 232 }, { 231, 239, 232 }, { 231, 255, 234 }, { 231, 255, 234 }, { 247, 173, 237 }, { 247, 173, 237 }, { 247, 173, 237 }, { 247, 189, 239 }, + { 247, 189, 239 }, { 247, 206, 241 }, { 247, 206, 241 }, { 247, 222, 243 }, { 247, 222, 243 }, { 247, 239, 246 }, { 247, 239, 246 }, { 247, 239, 246 }, + { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, + } +}; + +Table g_mode0_p01_i2= +{ + 2, + 2, + { + { 0, 8, 2 }, { 0, 8, 2 }, { 0, 8, 2 }, { 0, 8, 2 }, { 0, 8, 2 }, { 0, 24, 7 }, { 0, 24, 7 }, { 0, 24, 7 }, + { 0, 24, 7 }, { 0, 24, 7 }, { 0, 41, 12 }, { 0, 41, 12 }, { 0, 41, 12 }, { 0, 41, 12 }, { 16, 8, 14 }, { 0, 57, 16 }, + { 0, 57, 16 }, { 0, 57, 16 }, { 16, 24, 18 }, { 16, 24, 18 }, { 0, 74, 21 }, { 0, 74, 21 }, { 0, 74, 21 }, { 16, 41, 23 }, + { 0, 90, 25 }, { 0, 90, 25 }, { 33, 8, 26 }, { 16, 57, 28 }, { 16, 57, 28 }, { 0, 107, 30 }, { 0, 107, 30 }, { 0, 107, 30 }, + { 16, 74, 32 }, { 16, 74, 32 }, { 0, 123, 35 }, { 0, 123, 35 }, { 0, 123, 35 }, { 16, 90, 37 }, { 0, 140, 39 }, { 0, 140, 39 }, + { 33, 57, 40 }, { 16, 107, 42 }, { 16, 107, 42 }, { 0, 156, 44 }, { 0, 156, 44 }, { 33, 74, 45 }, { 16, 123, 46 }, { 49, 41, 47 }, + { 0, 173, 49 }, { 0, 173, 49 }, { 66, 8, 50 }, { 16, 140, 51 }, { 0, 189, 53 }, { 0, 189, 53 }, { 33, 107, 54 }, { 16, 156, 55 }, + { 49, 74, 56 }, { 0, 206, 58 }, { 0, 206, 58 }, { 66, 41, 59 }, { 16, 173, 60 }, { 49, 90, 61 }, { 0, 222, 62 }, { 33, 140, 63 }, + { 16, 189, 65 }, { 16, 189, 65 }, { 82, 24, 66 }, { 0, 239, 67 }, { 33, 156, 68 }, { 16, 206, 69 }, { 49, 123, 70 }, { 0, 255, 72 }, + { 0, 255, 72 }, { 66, 90, 73 }, { 16, 222, 74 }, { 49, 140, 75 }, { 33, 189, 77 }, { 33, 189, 77 }, { 66, 107, 78 }, { 16, 239, 79 }, + { 82, 74, 80 }, { 33, 206, 82 }, { 33, 206, 82 }, { 16, 255, 83 }, { 49, 173, 84 }, { 115, 8, 85 }, { 33, 222, 86 }, { 66, 140, 87 }, + { 49, 189, 88 }, { 82, 107, 89 }, { 33, 239, 91 }, { 33, 239, 91 }, { 99, 74, 92 }, { 49, 206, 93 }, { 82, 123, 94 }, { 33, 255, 95 }, + { 66, 173, 96 }, { 132, 8, 97 }, { 49, 222, 98 }, { 115, 57, 99 }, { 66, 189, 101 }, { 66, 189, 101 }, { 49, 239, 102 }, { 82, 156, 103 }, + { 66, 206, 105 }, { 66, 206, 105 }, { 99, 123, 106 }, { 49, 255, 107 }, { 82, 173, 108 }, { 148, 8, 109 }, { 66, 222, 110 }, { 99, 140, 111 }, + { 82, 189, 112 }, { 115, 107, 113 }, { 66, 239, 115 }, { 66, 239, 115 }, { 132, 74, 116 }, { 82, 206, 117 }, { 148, 41, 118 }, { 66, 255, 119 }, + { 99, 173, 120 }, { 82, 222, 121 }, { 115, 140, 122 }, { 99, 189, 124 }, { 99, 189, 124 }, { 132, 107, 125 }, { 82, 239, 126 }, { 115, 156, 127 }, + { 99, 206, 129 }, { 99, 206, 129 }, { 165, 41, 130 }, { 82, 255, 131 }, { 148, 90, 132 }, { 99, 222, 134 }, { 99, 222, 134 }, { 165, 57, 135 }, + { 115, 189, 136 }, { 181, 24, 137 }, { 99, 239, 138 }, { 132, 156, 139 }, { 115, 206, 141 }, { 115, 206, 141 }, { 181, 41, 142 }, { 99, 255, 143 }, + { 132, 173, 144 }, { 115, 222, 145 }, { 148, 140, 146 }, { 132, 189, 148 }, { 132, 189, 148 }, { 165, 107, 149 }, { 115, 239, 150 }, { 181, 74, 151 }, + { 132, 206, 153 }, { 132, 206, 153 }, { 115, 255, 154 }, { 148, 173, 155 }, { 214, 8, 156 }, { 132, 222, 157 }, { 165, 140, 158 }, { 148, 189, 160 }, + { 148, 189, 160 }, { 214, 24, 161 }, { 132, 239, 162 }, { 198, 74, 163 }, { 148, 206, 164 }, { 181, 123, 165 }, { 132, 255, 167 }, { 132, 255, 167 }, + { 198, 90, 168 }, { 148, 222, 169 }, { 214, 57, 170 }, { 165, 189, 172 }, { 165, 189, 172 }, { 231, 24, 173 }, { 148, 239, 174 }, { 214, 74, 175 }, + { 165, 206, 177 }, { 165, 206, 177 }, { 148, 255, 178 }, { 181, 173, 179 }, { 247, 8, 180 }, { 165, 222, 181 }, { 198, 140, 182 }, { 181, 189, 183 }, + { 214, 107, 184 }, { 165, 239, 186 }, { 165, 239, 186 }, { 231, 74, 187 }, { 181, 206, 188 }, { 247, 41, 189 }, { 165, 255, 190 }, { 198, 173, 191 }, + { 181, 222, 193 }, { 181, 222, 193 }, { 247, 57, 194 }, { 198, 189, 195 }, { 231, 107, 196 }, { 181, 239, 197 }, { 214, 156, 198 }, { 198, 206, 200 }, + { 198, 206, 200 }, { 231, 123, 201 }, { 181, 255, 202 }, { 247, 90, 203 }, { 198, 222, 205 }, { 198, 222, 205 }, { 198, 222, 205 }, { 214, 189, 207 }, + { 247, 107, 208 }, { 198, 239, 210 }, { 198, 239, 210 }, { 198, 239, 210 }, { 214, 206, 212 }, { 198, 255, 214 }, { 198, 255, 214 }, { 231, 173, 215 }, + { 214, 222, 216 }, { 247, 140, 217 }, { 231, 189, 219 }, { 231, 189, 219 }, { 214, 239, 221 }, { 214, 239, 221 }, { 214, 239, 221 }, { 231, 206, 224 }, + { 231, 206, 224 }, { 214, 255, 226 }, { 214, 255, 226 }, { 214, 255, 226 }, { 231, 222, 228 }, { 231, 222, 228 }, { 247, 189, 231 }, { 247, 189, 231 }, + { 231, 239, 233 }, { 231, 239, 233 }, { 231, 239, 233 }, { 247, 206, 235 }, { 247, 206, 235 }, { 231, 255, 238 }, { 231, 255, 238 }, { 231, 255, 238 }, + { 247, 222, 240 }, { 247, 222, 240 }, { 247, 222, 240 }, { 247, 239, 245 }, { 247, 239, 245 }, { 247, 239, 245 }, { 247, 239, 245 }, { 247, 239, 245 }, + { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, + } +}; + +Table g_mode0_p01_i3= +{ + 3, + 2, + { + { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 24, 10 }, + { 0, 24, 10 }, { 0, 24, 10 }, { 0, 24, 10 }, { 0, 24, 10 }, { 16, 8, 13 }, { 16, 8, 13 }, { 16, 8, 13 }, { 0, 41, 17 }, + { 0, 41, 17 }, { 0, 41, 17 }, { 0, 41, 17 }, { 16, 24, 19 }, { 16, 24, 19 }, { 33, 8, 22 }, { 33, 8, 22 }, { 0, 57, 24 }, + { 0, 57, 24 }, { 0, 57, 24 }, { 16, 41, 27 }, { 16, 41, 27 }, { 16, 41, 27 }, { 33, 24, 29 }, { 0, 74, 31 }, { 0, 74, 31 }, + { 49, 8, 32 }, { 16, 57, 33 }, { 16, 57, 33 }, { 33, 41, 36 }, { 33, 41, 36 }, { 0, 90, 38 }, { 0, 90, 38 }, { 0, 90, 38 }, + { 16, 74, 40 }, { 16, 74, 40 }, { 66, 8, 42 }, { 33, 57, 43 }, { 0, 107, 45 }, { 0, 107, 45 }, { 49, 41, 46 }, { 16, 90, 47 }, + { 66, 24, 48 }, { 33, 74, 50 }, { 33, 74, 50 }, { 82, 8, 51 }, { 0, 123, 52 }, { 0, 123, 52 }, { 16, 107, 54 }, { 66, 41, 55 }, + { 33, 90, 57 }, { 33, 90, 57 }, { 82, 24, 58 }, { 0, 140, 59 }, { 49, 74, 60 }, { 16, 123, 61 }, { 66, 57, 62 }, { 33, 107, 64 }, + { 33, 107, 64 }, { 82, 41, 65 }, { 0, 156, 66 }, { 99, 24, 67 }, { 16, 140, 68 }, { 66, 74, 69 }, { 115, 8, 70 }, { 33, 123, 71 }, + { 0, 173, 73 }, { 0, 173, 73 }, { 0, 173, 73 }, { 16, 156, 75 }, { 66, 90, 76 }, { 115, 24, 77 }, { 33, 140, 78 }, { 82, 74, 79 }, + { 0, 189, 80 }, { 99, 57, 81 }, { 16, 173, 82 }, { 66, 107, 83 }, { 115, 41, 84 }, { 33, 156, 85 }, { 132, 24, 86 }, { 0, 206, 87 }, + { 99, 74, 88 }, { 16, 189, 89 }, { 66, 123, 90 }, { 115, 57, 91 }, { 33, 173, 92 }, { 82, 107, 93 }, { 0, 222, 94 }, { 99, 90, 95 }, + { 16, 206, 96 }, { 66, 140, 97 }, { 115, 74, 98 }, { 33, 189, 99 }, { 132, 57, 100 }, { 0, 239, 101 }, { 99, 107, 102 }, { 16, 222, 103 }, + { 66, 156, 104 }, { 33, 206, 106 }, { 33, 206, 106 }, { 0, 255, 108 }, { 0, 255, 108 }, { 99, 123, 109 }, { 16, 239, 110 }, { 66, 173, 111 }, + { 115, 107, 112 }, { 33, 222, 113 }, { 132, 90, 114 }, { 49, 206, 115 }, { 99, 140, 116 }, { 16, 255, 117 }, { 66, 189, 118 }, { 165, 57, 119 }, + { 33, 239, 120 }, { 132, 107, 121 }, { 49, 222, 122 }, { 99, 156, 123 }, { 148, 90, 124 }, { 66, 206, 125 }, { 115, 140, 126 }, { 33, 255, 127 }, + { 132, 123, 128 }, { 49, 239, 129 }, { 99, 173, 130 }, { 148, 107, 131 }, { 66, 222, 132 }, { 165, 90, 133 }, { 82, 206, 134 }, { 132, 140, 135 }, + { 49, 255, 136 }, { 99, 189, 137 }, { 66, 239, 139 }, { 66, 239, 139 }, { 66, 239, 139 }, { 82, 222, 141 }, { 132, 156, 142 }, { 181, 90, 143 }, + { 99, 206, 144 }, { 148, 140, 145 }, { 66, 255, 146 }, { 165, 123, 147 }, { 82, 239, 148 }, { 132, 173, 149 }, { 181, 107, 150 }, { 99, 222, 151 }, + { 198, 90, 152 }, { 115, 206, 153 }, { 165, 140, 154 }, { 82, 255, 155 }, { 132, 189, 156 }, { 181, 123, 157 }, { 99, 239, 158 }, { 148, 173, 159 }, + { 115, 222, 160 }, { 165, 156, 161 }, { 214, 90, 162 }, { 132, 206, 163 }, { 181, 140, 164 }, { 99, 255, 165 }, { 198, 123, 166 }, { 115, 239, 167 }, + { 165, 173, 168 }, { 214, 107, 169 }, { 132, 222, 170 }, { 132, 222, 170 }, { 148, 206, 172 }, { 115, 255, 174 }, { 115, 255, 174 }, { 165, 189, 175 }, + { 214, 123, 176 }, { 132, 239, 177 }, { 181, 173, 178 }, { 148, 222, 179 }, { 198, 156, 180 }, { 247, 90, 181 }, { 165, 206, 182 }, { 214, 140, 183 }, + { 132, 255, 184 }, { 231, 123, 185 }, { 148, 239, 186 }, { 198, 173, 187 }, { 247, 107, 188 }, { 165, 222, 189 }, { 214, 156, 190 }, { 181, 206, 192 }, + { 181, 206, 192 }, { 148, 255, 193 }, { 198, 189, 194 }, { 247, 123, 195 }, { 165, 239, 196 }, { 214, 173, 197 }, { 181, 222, 198 }, { 231, 156, 199 }, + { 198, 206, 201 }, { 198, 206, 201 }, { 247, 140, 202 }, { 165, 255, 203 }, { 165, 255, 203 }, { 181, 239, 205 }, { 181, 239, 205 }, { 231, 173, 207 }, + { 198, 222, 208 }, { 247, 156, 209 }, { 214, 206, 211 }, { 214, 206, 211 }, { 181, 255, 212 }, { 231, 189, 213 }, { 198, 239, 215 }, { 198, 239, 215 }, + { 247, 173, 216 }, { 214, 222, 217 }, { 214, 222, 217 }, { 231, 206, 220 }, { 231, 206, 220 }, { 198, 255, 222 }, { 198, 255, 222 }, { 247, 189, 223 }, + { 214, 239, 225 }, { 214, 239, 225 }, { 214, 239, 225 }, { 231, 222, 227 }, { 231, 222, 227 }, { 247, 206, 230 }, { 247, 206, 230 }, { 214, 255, 231 }, + { 214, 255, 231 }, { 231, 239, 234 }, { 231, 239, 234 }, { 231, 239, 234 }, { 247, 222, 236 }, { 247, 222, 236 }, { 247, 222, 236 }, { 231, 255, 241 }, + { 231, 255, 241 }, { 231, 255, 241 }, { 231, 255, 241 }, { 247, 239, 244 }, { 247, 239, 244 }, { 247, 239, 244 }, { 247, 239, 244 }, { 247, 239, 244 }, + { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, + } +}; + +Table g_mode0_p10_i1= +{ + 1, + 1, + { + { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, + { 8, 0, 7 }, { 8, 16, 9 }, { 8, 16, 9 }, { 8, 33, 12 }, { 8, 33, 12 }, { 8, 33, 12 }, { 8, 49, 14 }, { 8, 49, 14 }, + { 8, 66, 16 }, { 8, 66, 16 }, { 8, 82, 18 }, { 8, 82, 18 }, { 8, 99, 21 }, { 8, 99, 21 }, { 8, 99, 21 }, { 8, 115, 23 }, + { 8, 115, 23 }, { 8, 132, 25 }, { 8, 132, 25 }, { 8, 148, 28 }, { 8, 148, 28 }, { 8, 148, 28 }, { 8, 165, 30 }, { 8, 165, 30 }, + { 8, 181, 32 }, { 8, 181, 32 }, { 8, 198, 35 }, { 8, 198, 35 }, { 8, 198, 35 }, { 8, 214, 37 }, { 8, 214, 37 }, { 8, 231, 39 }, + { 41, 33, 40 }, { 24, 148, 41 }, { 8, 247, 42 }, { 8, 247, 42 }, { 24, 165, 44 }, { 41, 66, 45 }, { 24, 181, 46 }, { 41, 82, 47 }, + { 24, 198, 48 }, { 41, 99, 49 }, { 24, 214, 51 }, { 24, 214, 51 }, { 24, 214, 51 }, { 24, 231, 53 }, { 41, 132, 54 }, { 24, 247, 55 }, + { 41, 148, 56 }, { 41, 148, 56 }, { 41, 165, 58 }, { 41, 165, 58 }, { 41, 181, 61 }, { 41, 181, 61 }, { 41, 181, 61 }, { 41, 198, 63 }, + { 74, 0, 64 }, { 41, 214, 65 }, { 74, 16, 66 }, { 41, 231, 68 }, { 41, 231, 68 }, { 41, 231, 68 }, { 41, 247, 70 }, { 41, 247, 70 }, + { 57, 165, 72 }, { 74, 66, 73 }, { 57, 181, 74 }, { 74, 82, 75 }, { 57, 198, 77 }, { 57, 198, 77 }, { 74, 99, 78 }, { 57, 214, 79 }, + { 74, 115, 80 }, { 57, 231, 81 }, { 74, 132, 82 }, { 57, 247, 84 }, { 57, 247, 84 }, { 57, 247, 84 }, { 74, 165, 87 }, { 74, 165, 87 }, + { 74, 165, 87 }, { 74, 181, 89 }, { 74, 181, 89 }, { 74, 198, 91 }, { 107, 0, 92 }, { 74, 214, 94 }, { 74, 214, 94 }, { 74, 214, 94 }, + { 74, 231, 96 }, { 107, 33, 97 }, { 74, 247, 98 }, { 107, 49, 99 }, { 90, 165, 101 }, { 90, 165, 101 }, { 90, 165, 101 }, { 90, 181, 103 }, + { 90, 181, 103 }, { 90, 198, 105 }, { 107, 99, 106 }, { 90, 214, 107 }, { 107, 115, 108 }, { 90, 231, 110 }, { 90, 231, 110 }, { 107, 132, 111 }, + { 90, 247, 112 }, { 107, 148, 113 }, { 107, 148, 113 }, { 107, 165, 115 }, { 107, 165, 115 }, { 107, 181, 117 }, { 107, 181, 117 }, { 107, 198, 120 }, + { 107, 198, 120 }, { 107, 198, 120 }, { 107, 214, 122 }, { 140, 16, 123 }, { 107, 231, 124 }, { 140, 33, 125 }, { 107, 247, 127 }, { 107, 247, 127 }, + { 107, 247, 127 }, { 123, 165, 129 }, { 140, 66, 130 }, { 123, 181, 131 }, { 140, 82, 132 }, { 123, 198, 134 }, { 123, 198, 134 }, { 123, 198, 134 }, + { 123, 214, 136 }, { 123, 214, 136 }, { 123, 231, 138 }, { 140, 132, 139 }, { 123, 247, 140 }, { 140, 148, 141 }, { 140, 148, 141 }, { 156, 66, 143 }, + { 140, 165, 144 }, { 140, 165, 144 }, { 140, 181, 146 }, { 140, 181, 146 }, { 140, 198, 148 }, { 173, 0, 149 }, { 140, 214, 150 }, { 173, 16, 151 }, + { 140, 231, 153 }, { 140, 231, 153 }, { 140, 231, 153 }, { 140, 247, 155 }, { 173, 49, 156 }, { 156, 165, 157 }, { 173, 66, 158 }, { 156, 181, 160 }, + { 156, 181, 160 }, { 156, 181, 160 }, { 156, 198, 162 }, { 173, 99, 163 }, { 156, 214, 164 }, { 173, 115, 165 }, { 156, 231, 167 }, { 156, 231, 167 }, + { 156, 231, 167 }, { 156, 247, 169 }, { 156, 247, 169 }, { 173, 165, 172 }, { 173, 165, 172 }, { 173, 165, 172 }, { 173, 181, 174 }, { 173, 181, 174 }, + { 189, 99, 176 }, { 173, 198, 177 }, { 173, 198, 177 }, { 173, 214, 179 }, { 173, 214, 179 }, { 173, 231, 181 }, { 206, 33, 182 }, { 173, 247, 183 }, + { 206, 49, 184 }, { 189, 165, 186 }, { 189, 165, 186 }, { 189, 165, 186 }, { 189, 181, 188 }, { 206, 82, 189 }, { 189, 198, 190 }, { 206, 99, 191 }, + { 189, 214, 193 }, { 189, 214, 193 }, { 189, 214, 193 }, { 189, 231, 195 }, { 206, 132, 196 }, { 189, 247, 197 }, { 206, 148, 198 }, { 206, 148, 198 }, + { 206, 165, 200 }, { 206, 165, 200 }, { 206, 181, 202 }, { 206, 181, 202 }, { 206, 198, 205 }, { 206, 198, 205 }, { 206, 198, 205 }, { 206, 214, 207 }, + { 239, 16, 208 }, { 222, 132, 209 }, { 206, 231, 210 }, { 206, 231, 210 }, { 206, 247, 212 }, { 206, 247, 212 }, { 222, 165, 214 }, { 239, 66, 215 }, + { 222, 181, 216 }, { 239, 82, 217 }, { 222, 198, 219 }, { 222, 198, 219 }, { 222, 198, 219 }, { 222, 214, 221 }, { 239, 115, 222 }, { 222, 231, 223 }, + { 239, 132, 224 }, { 222, 247, 226 }, { 222, 247, 226 }, { 222, 247, 226 }, { 255, 66, 228 }, { 239, 165, 229 }, { 239, 165, 229 }, { 239, 181, 231 }, + { 239, 181, 231 }, { 239, 198, 233 }, { 239, 198, 233 }, { 239, 214, 235 }, { 239, 214, 235 }, { 239, 231, 238 }, { 239, 231, 238 }, { 239, 231, 238 }, + { 239, 247, 240 }, { 239, 247, 240 }, { 255, 165, 242 }, { 255, 165, 242 }, { 255, 181, 245 }, { 255, 181, 245 }, { 255, 181, 245 }, { 255, 198, 247 }, + { 255, 198, 247 }, { 255, 214, 249 }, { 255, 214, 249 }, { 255, 231, 252 }, { 255, 231, 252 }, { 255, 231, 252 }, { 255, 247, 254 }, { 255, 247, 254 }, + } +}; + +Table g_mode0_p10_i2= +{ + 2, + 1, + { + { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, + { 8, 0, 6 }, { 8, 16, 10 }, { 8, 16, 10 }, { 8, 16, 10 }, { 8, 16, 10 }, { 8, 33, 15 }, { 8, 33, 15 }, { 8, 33, 15 }, + { 8, 33, 15 }, { 24, 0, 17 }, { 24, 0, 17 }, { 8, 49, 20 }, { 8, 49, 20 }, { 8, 49, 20 }, { 24, 16, 22 }, { 8, 66, 24 }, + { 8, 66, 24 }, { 8, 66, 24 }, { 24, 33, 27 }, { 24, 33, 27 }, { 8, 82, 29 }, { 8, 82, 29 }, { 8, 82, 29 }, { 24, 49, 31 }, + { 24, 49, 31 }, { 8, 99, 34 }, { 8, 99, 34 }, { 8, 99, 34 }, { 24, 66, 36 }, { 8, 115, 38 }, { 8, 115, 38 }, { 41, 33, 39 }, + { 24, 82, 40 }, { 57, 0, 41 }, { 8, 132, 43 }, { 8, 132, 43 }, { 8, 132, 43 }, { 24, 99, 45 }, { 8, 148, 47 }, { 8, 148, 47 }, + { 41, 66, 48 }, { 24, 115, 50 }, { 24, 115, 50 }, { 8, 165, 52 }, { 8, 165, 52 }, { 41, 82, 53 }, { 24, 132, 54 }, { 57, 49, 55 }, + { 8, 181, 57 }, { 8, 181, 57 }, { 74, 16, 58 }, { 24, 148, 59 }, { 57, 66, 60 }, { 8, 198, 61 }, { 41, 115, 62 }, { 24, 165, 64 }, + { 24, 165, 64 }, { 90, 0, 65 }, { 8, 214, 66 }, { 41, 132, 67 }, { 24, 181, 68 }, { 57, 99, 69 }, { 8, 231, 71 }, { 8, 231, 71 }, + { 74, 66, 72 }, { 24, 198, 73 }, { 90, 33, 74 }, { 8, 247, 75 }, { 41, 165, 76 }, { 24, 214, 77 }, { 57, 132, 78 }, { 41, 181, 80 }, + { 41, 181, 80 }, { 74, 99, 81 }, { 24, 231, 82 }, { 57, 148, 83 }, { 41, 198, 85 }, { 41, 198, 85 }, { 74, 115, 86 }, { 24, 247, 87 }, + { 90, 82, 88 }, { 41, 214, 90 }, { 41, 214, 90 }, { 107, 49, 91 }, { 57, 181, 92 }, { 90, 99, 93 }, { 41, 231, 94 }, { 74, 148, 95 }, + { 57, 198, 97 }, { 57, 198, 97 }, { 123, 33, 98 }, { 41, 247, 99 }, { 74, 165, 100 }, { 57, 214, 101 }, { 90, 132, 102 }, { 74, 181, 104 }, + { 74, 181, 104 }, { 107, 99, 105 }, { 57, 231, 106 }, { 123, 66, 107 }, { 74, 198, 109 }, { 74, 198, 109 }, { 57, 247, 110 }, { 90, 165, 111 }, + { 156, 0, 112 }, { 74, 214, 113 }, { 107, 132, 114 }, { 90, 181, 116 }, { 90, 181, 116 }, { 156, 16, 117 }, { 74, 231, 118 }, { 107, 148, 119 }, + { 90, 198, 120 }, { 123, 115, 121 }, { 74, 247, 123 }, { 74, 247, 123 }, { 140, 82, 124 }, { 90, 214, 125 }, { 123, 132, 126 }, { 107, 181, 128 }, + { 107, 181, 128 }, { 173, 16, 129 }, { 90, 231, 130 }, { 156, 66, 131 }, { 107, 198, 133 }, { 107, 198, 133 }, { 90, 247, 134 }, { 123, 165, 135 }, + { 189, 0, 136 }, { 107, 214, 137 }, { 140, 132, 138 }, { 123, 181, 139 }, { 156, 99, 140 }, { 107, 231, 142 }, { 107, 231, 142 }, { 173, 66, 143 }, + { 123, 198, 144 }, { 189, 33, 145 }, { 107, 247, 146 }, { 140, 165, 147 }, { 206, 0, 148 }, { 123, 214, 149 }, { 189, 49, 150 }, { 140, 181, 152 }, + { 140, 181, 152 }, { 123, 231, 153 }, { 156, 148, 154 }, { 140, 198, 156 }, { 140, 198, 156 }, { 173, 115, 157 }, { 123, 247, 158 }, { 156, 165, 159 }, + { 222, 0, 160 }, { 140, 214, 161 }, { 206, 49, 162 }, { 156, 181, 163 }, { 189, 99, 164 }, { 140, 231, 166 }, { 140, 231, 166 }, { 206, 66, 167 }, + { 156, 198, 168 }, { 222, 33, 169 }, { 140, 247, 170 }, { 173, 165, 171 }, { 156, 214, 172 }, { 189, 132, 173 }, { 173, 181, 175 }, { 173, 181, 175 }, + { 206, 99, 176 }, { 156, 231, 177 }, { 222, 66, 178 }, { 173, 198, 180 }, { 173, 198, 180 }, { 239, 33, 181 }, { 156, 247, 182 }, { 222, 82, 183 }, + { 173, 214, 185 }, { 173, 214, 185 }, { 239, 49, 186 }, { 189, 181, 187 }, { 255, 16, 188 }, { 173, 231, 189 }, { 206, 148, 190 }, { 189, 198, 192 }, + { 189, 198, 192 }, { 255, 33, 193 }, { 173, 247, 194 }, { 239, 82, 195 }, { 189, 214, 196 }, { 222, 132, 197 }, { 206, 181, 199 }, { 206, 181, 199 }, + { 239, 99, 200 }, { 189, 231, 201 }, { 255, 66, 202 }, { 206, 198, 204 }, { 206, 198, 204 }, { 189, 247, 205 }, { 222, 165, 206 }, { 206, 214, 208 }, + { 206, 214, 208 }, { 239, 132, 209 }, { 222, 181, 210 }, { 255, 99, 211 }, { 206, 231, 213 }, { 206, 231, 213 }, { 206, 231, 213 }, { 222, 198, 215 }, + { 255, 115, 216 }, { 206, 247, 218 }, { 206, 247, 218 }, { 206, 247, 218 }, { 222, 214, 220 }, { 222, 214, 220 }, { 239, 181, 223 }, { 239, 181, 223 }, + { 222, 231, 225 }, { 222, 231, 225 }, { 222, 231, 225 }, { 239, 198, 227 }, { 222, 247, 229 }, { 222, 247, 229 }, { 255, 165, 230 }, { 239, 214, 232 }, + { 239, 214, 232 }, { 239, 214, 232 }, { 255, 181, 234 }, { 255, 181, 234 }, { 239, 231, 237 }, { 239, 231, 237 }, { 239, 231, 237 }, { 255, 198, 239 }, + { 239, 247, 241 }, { 239, 247, 241 }, { 239, 247, 241 }, { 255, 214, 243 }, { 255, 214, 243 }, { 255, 214, 243 }, { 255, 231, 248 }, { 255, 231, 248 }, + { 255, 231, 248 }, { 255, 231, 248 }, { 255, 231, 248 }, { 255, 247, 253 }, { 255, 247, 253 }, { 255, 247, 253 }, { 255, 247, 253 }, { 255, 247, 253 }, + } +}; + +Table g_mode0_p10_i3= +{ + 3, + 3, + { + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 24, 15 }, { 8, 24, 15 }, { 8, 24, 15 }, { 8, 24, 15 }, + { 8, 24, 15 }, { 24, 8, 17 }, { 24, 8, 17 }, { 24, 8, 17 }, { 8, 41, 22 }, { 8, 41, 22 }, { 8, 41, 22 }, { 8, 41, 22 }, + { 24, 24, 24 }, { 24, 24, 24 }, { 41, 8, 27 }, { 41, 8, 27 }, { 8, 57, 29 }, { 8, 57, 29 }, { 8, 57, 29 }, { 24, 41, 31 }, + { 24, 41, 31 }, { 41, 24, 34 }, { 41, 24, 34 }, { 8, 74, 36 }, { 8, 74, 36 }, { 8, 74, 36 }, { 24, 57, 38 }, { 24, 57, 38 }, + { 41, 41, 41 }, { 41, 41, 41 }, { 8, 90, 43 }, { 8, 90, 43 }, { 8, 90, 43 }, { 24, 74, 45 }, { 74, 8, 46 }, { 41, 57, 48 }, + { 41, 57, 48 }, { 8, 107, 50 }, { 8, 107, 50 }, { 8, 107, 50 }, { 24, 90, 52 }, { 74, 24, 53 }, { 41, 74, 55 }, { 41, 74, 55 }, + { 8, 123, 57 }, { 8, 123, 57 }, { 8, 123, 57 }, { 24, 107, 59 }, { 74, 41, 60 }, { 41, 90, 62 }, { 41, 90, 62 }, { 8, 140, 64 }, + { 8, 140, 64 }, { 107, 8, 65 }, { 24, 123, 66 }, { 74, 57, 67 }, { 41, 107, 69 }, { 41, 107, 69 }, { 8, 156, 70 }, { 57, 90, 71 }, + { 107, 24, 72 }, { 24, 140, 73 }, { 74, 74, 74 }, { 41, 123, 76 }, { 41, 123, 76 }, { 8, 173, 78 }, { 8, 173, 78 }, { 107, 41, 79 }, + { 24, 156, 80 }, { 74, 90, 81 }, { 41, 140, 83 }, { 41, 140, 83 }, { 8, 189, 84 }, { 57, 123, 85 }, { 107, 57, 86 }, { 24, 173, 87 }, + { 74, 107, 88 }, { 41, 156, 90 }, { 41, 156, 90 }, { 140, 24, 91 }, { 8, 206, 92 }, { 107, 74, 93 }, { 24, 189, 94 }, { 74, 123, 95 }, + { 41, 173, 97 }, { 41, 173, 97 }, { 8, 222, 98 }, { 57, 156, 99 }, { 107, 90, 100 }, { 24, 206, 101 }, { 74, 140, 102 }, { 41, 189, 103 }, + { 90, 123, 104 }, { 8, 239, 105 }, { 57, 173, 106 }, { 107, 107, 107 }, { 24, 222, 108 }, { 74, 156, 109 }, { 173, 24, 110 }, { 41, 206, 111 }, + { 8, 255, 112 }, { 57, 189, 113 }, { 107, 123, 114 }, { 24, 239, 115 }, { 74, 173, 116 }, { 41, 222, 117 }, { 90, 156, 118 }, { 140, 90, 119 }, + { 57, 206, 120 }, { 24, 255, 121 }, { 206, 8, 122 }, { 74, 189, 123 }, { 173, 57, 124 }, { 41, 239, 125 }, { 140, 107, 126 }, { 57, 222, 127 }, + { 107, 156, 128 }, { 206, 24, 129 }, { 74, 206, 130 }, { 41, 255, 131 }, { 90, 189, 132 }, { 140, 123, 133 }, { 57, 239, 134 }, { 107, 173, 135 }, + { 74, 222, 136 }, { 123, 156, 137 }, { 173, 90, 138 }, { 90, 206, 139 }, { 140, 140, 140 }, { 57, 255, 141 }, { 107, 189, 142 }, { 206, 57, 143 }, + { 74, 239, 144 }, { 173, 107, 145 }, { 90, 222, 146 }, { 140, 156, 147 }, { 239, 24, 148 }, { 107, 206, 149 }, { 74, 255, 150 }, { 123, 189, 151 }, + { 173, 123, 152 }, { 90, 239, 153 }, { 140, 173, 154 }, { 239, 41, 155 }, { 107, 222, 156 }, { 206, 90, 157 }, { 123, 206, 158 }, { 173, 140, 159 }, + { 90, 255, 160 }, { 140, 189, 161 }, { 239, 57, 162 }, { 107, 239, 163 }, { 206, 107, 164 }, { 123, 222, 165 }, { 173, 156, 166 }, { 140, 206, 168 }, + { 140, 206, 168 }, { 107, 255, 169 }, { 156, 189, 170 }, { 206, 123, 171 }, { 123, 239, 172 }, { 173, 173, 173 }, { 140, 222, 175 }, { 140, 222, 175 }, + { 239, 90, 176 }, { 156, 206, 177 }, { 206, 140, 178 }, { 123, 255, 179 }, { 173, 189, 180 }, { 140, 239, 182 }, { 140, 239, 182 }, { 239, 107, 183 }, + { 156, 222, 184 }, { 206, 156, 185 }, { 173, 206, 187 }, { 173, 206, 187 }, { 140, 255, 189 }, { 140, 255, 189 }, { 239, 123, 190 }, { 156, 239, 191 }, + { 206, 173, 192 }, { 255, 107, 193 }, { 173, 222, 194 }, { 173, 222, 194 }, { 189, 206, 196 }, { 239, 140, 197 }, { 156, 255, 198 }, { 206, 189, 199 }, + { 173, 239, 201 }, { 173, 239, 201 }, { 173, 239, 201 }, { 189, 222, 203 }, { 239, 156, 204 }, { 206, 206, 206 }, { 206, 206, 206 }, { 173, 255, 208 }, + { 173, 255, 208 }, { 173, 255, 208 }, { 189, 239, 210 }, { 239, 173, 211 }, { 206, 222, 213 }, { 206, 222, 213 }, { 206, 222, 213 }, { 222, 206, 215 }, + { 189, 255, 217 }, { 189, 255, 217 }, { 239, 189, 218 }, { 206, 239, 220 }, { 206, 239, 220 }, { 206, 239, 220 }, { 222, 222, 222 }, { 222, 222, 222 }, + { 239, 206, 225 }, { 239, 206, 225 }, { 206, 255, 227 }, { 206, 255, 227 }, { 206, 255, 227 }, { 222, 239, 229 }, { 222, 239, 229 }, { 239, 222, 232 }, + { 239, 222, 232 }, { 239, 222, 232 }, { 255, 206, 234 }, { 222, 255, 236 }, { 222, 255, 236 }, { 222, 255, 236 }, { 239, 239, 239 }, { 239, 239, 239 }, + { 239, 239, 239 }, { 255, 222, 241 }, { 255, 222, 241 }, { 255, 222, 241 }, { 239, 255, 246 }, { 239, 255, 246 }, { 239, 255, 246 }, { 239, 255, 246 }, + { 255, 239, 248 }, { 255, 239, 248 }, { 255, 239, 248 }, { 255, 239, 248 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode0_p11_i1= +{ + 1, + 3, + { + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 24, 10 }, { 8, 24, 10 }, { 8, 41, 13 }, { 8, 41, 13 }, { 8, 41, 13 }, { 8, 57, 15 }, + { 8, 57, 15 }, { 8, 74, 17 }, { 8, 74, 17 }, { 8, 90, 20 }, { 8, 90, 20 }, { 8, 90, 20 }, { 8, 107, 22 }, { 8, 107, 22 }, + { 8, 123, 24 }, { 8, 123, 24 }, { 24, 41, 26 }, { 8, 140, 27 }, { 8, 140, 27 }, { 8, 156, 29 }, { 8, 156, 29 }, { 8, 173, 31 }, + { 8, 173, 31 }, { 8, 189, 33 }, { 8, 189, 33 }, { 8, 206, 36 }, { 8, 206, 36 }, { 8, 206, 36 }, { 8, 222, 38 }, { 41, 24, 39 }, + { 8, 239, 40 }, { 41, 41, 41 }, { 8, 255, 43 }, { 8, 255, 43 }, { 8, 255, 43 }, { 24, 173, 45 }, { 41, 74, 46 }, { 24, 189, 47 }, + { 41, 90, 48 }, { 24, 206, 50 }, { 24, 206, 50 }, { 24, 206, 50 }, { 24, 222, 52 }, { 41, 123, 53 }, { 24, 239, 54 }, { 41, 140, 55 }, + { 24, 255, 56 }, { 41, 156, 57 }, { 41, 156, 57 }, { 57, 74, 59 }, { 41, 173, 60 }, { 41, 173, 60 }, { 41, 189, 62 }, { 41, 189, 62 }, + { 41, 206, 64 }, { 74, 8, 65 }, { 41, 222, 66 }, { 74, 24, 67 }, { 41, 239, 69 }, { 41, 239, 69 }, { 41, 239, 69 }, { 41, 255, 71 }, + { 74, 57, 72 }, { 57, 173, 73 }, { 74, 74, 74 }, { 57, 189, 76 }, { 57, 189, 76 }, { 57, 189, 76 }, { 57, 206, 78 }, { 74, 107, 79 }, + { 57, 222, 80 }, { 74, 123, 81 }, { 57, 239, 83 }, { 57, 239, 83 }, { 57, 239, 83 }, { 57, 255, 85 }, { 74, 156, 86 }, { 74, 156, 86 }, + { 74, 173, 88 }, { 74, 173, 88 }, { 74, 189, 90 }, { 74, 189, 90 }, { 90, 107, 92 }, { 74, 206, 93 }, { 74, 206, 93 }, { 74, 222, 95 }, + { 74, 222, 95 }, { 74, 239, 97 }, { 107, 41, 98 }, { 74, 255, 99 }, { 107, 57, 100 }, { 90, 173, 102 }, { 90, 173, 102 }, { 90, 173, 102 }, + { 90, 189, 104 }, { 107, 90, 105 }, { 90, 206, 106 }, { 107, 107, 107 }, { 90, 222, 109 }, { 90, 222, 109 }, { 90, 222, 109 }, { 90, 239, 111 }, + { 107, 140, 112 }, { 90, 255, 113 }, { 107, 156, 114 }, { 107, 156, 114 }, { 107, 173, 116 }, { 107, 173, 116 }, { 123, 90, 118 }, { 107, 189, 119 }, + { 107, 189, 119 }, { 107, 206, 121 }, { 107, 206, 121 }, { 107, 222, 123 }, { 140, 24, 124 }, { 123, 140, 125 }, { 107, 239, 126 }, { 107, 239, 126 }, + { 107, 255, 128 }, { 107, 255, 128 }, { 123, 173, 130 }, { 140, 74, 131 }, { 123, 189, 132 }, { 140, 90, 133 }, { 123, 206, 135 }, { 123, 206, 135 }, + { 123, 206, 135 }, { 123, 222, 137 }, { 140, 123, 138 }, { 123, 239, 139 }, { 140, 140, 140 }, { 123, 255, 142 }, { 123, 255, 142 }, { 123, 255, 142 }, + { 156, 74, 144 }, { 140, 173, 145 }, { 140, 173, 145 }, { 140, 189, 147 }, { 140, 189, 147 }, { 140, 206, 149 }, { 173, 8, 150 }, { 156, 123, 151 }, + { 140, 222, 152 }, { 140, 222, 152 }, { 140, 239, 154 }, { 140, 239, 154 }, { 140, 255, 156 }, { 173, 57, 157 }, { 156, 173, 158 }, { 173, 74, 159 }, + { 156, 189, 161 }, { 156, 189, 161 }, { 156, 189, 161 }, { 156, 206, 163 }, { 173, 107, 164 }, { 156, 222, 165 }, { 173, 123, 166 }, { 156, 239, 168 }, + { 156, 239, 168 }, { 156, 239, 168 }, { 156, 255, 170 }, { 173, 156, 171 }, { 173, 156, 171 }, { 173, 173, 173 }, { 173, 173, 173 }, { 173, 189, 175 }, + { 173, 189, 175 }, { 189, 107, 177 }, { 173, 206, 178 }, { 173, 206, 178 }, { 173, 222, 180 }, { 173, 222, 180 }, { 173, 239, 182 }, { 206, 41, 183 }, + { 189, 156, 184 }, { 173, 255, 185 }, { 173, 255, 185 }, { 189, 173, 187 }, { 189, 173, 187 }, { 189, 189, 189 }, { 206, 90, 190 }, { 189, 206, 191 }, + { 206, 107, 192 }, { 189, 222, 194 }, { 189, 222, 194 }, { 189, 222, 194 }, { 189, 239, 196 }, { 206, 140, 197 }, { 189, 255, 198 }, { 206, 156, 199 }, + { 206, 156, 199 }, { 206, 173, 201 }, { 206, 173, 201 }, { 222, 90, 203 }, { 206, 189, 204 }, { 206, 189, 204 }, { 206, 206, 206 }, { 239, 8, 207 }, + { 206, 222, 208 }, { 239, 24, 209 }, { 222, 140, 210 }, { 206, 239, 211 }, { 206, 239, 211 }, { 206, 255, 213 }, { 206, 255, 213 }, { 222, 173, 215 }, + { 239, 74, 216 }, { 222, 189, 217 }, { 239, 90, 218 }, { 222, 206, 220 }, { 222, 206, 220 }, { 222, 206, 220 }, { 222, 222, 222 }, { 239, 123, 223 }, + { 222, 239, 224 }, { 239, 140, 225 }, { 222, 255, 227 }, { 222, 255, 227 }, { 222, 255, 227 }, { 239, 173, 230 }, { 239, 173, 230 }, { 239, 173, 230 }, + { 239, 189, 232 }, { 239, 189, 232 }, { 239, 206, 234 }, { 239, 206, 234 }, { 255, 123, 236 }, { 239, 222, 237 }, { 239, 222, 237 }, { 239, 239, 239 }, + { 239, 239, 239 }, { 239, 255, 241 }, { 239, 255, 241 }, { 255, 173, 243 }, { 255, 173, 243 }, { 255, 189, 246 }, { 255, 189, 246 }, { 255, 189, 246 }, + { 255, 206, 248 }, { 255, 206, 248 }, { 255, 222, 250 }, { 255, 222, 250 }, { 255, 239, 253 }, { 255, 239, 253 }, { 255, 239, 253 }, { 255, 255, 255 }, + } +}; + +Table g_mode0_p11_i2= +{ + 2, + 3, + { + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 24, 13 }, { 8, 24, 13 }, { 8, 24, 13 }, { 8, 24, 13 }, { 8, 24, 13 }, + { 8, 41, 17 }, { 8, 41, 17 }, { 8, 41, 17 }, { 24, 8, 20 }, { 24, 8, 20 }, { 8, 57, 22 }, { 8, 57, 22 }, { 8, 57, 22 }, + { 24, 24, 24 }, { 24, 24, 24 }, { 8, 74, 27 }, { 8, 74, 27 }, { 8, 74, 27 }, { 24, 41, 29 }, { 8, 90, 31 }, { 8, 90, 31 }, + { 41, 8, 32 }, { 24, 57, 33 }, { 24, 57, 33 }, { 8, 107, 36 }, { 8, 107, 36 }, { 8, 107, 36 }, { 24, 74, 38 }, { 8, 123, 40 }, + { 8, 123, 40 }, { 41, 41, 41 }, { 24, 90, 43 }, { 24, 90, 43 }, { 8, 140, 45 }, { 8, 140, 45 }, { 41, 57, 46 }, { 24, 107, 47 }, + { 57, 24, 48 }, { 8, 156, 50 }, { 8, 156, 50 }, { 8, 156, 50 }, { 24, 123, 52 }, { 57, 41, 53 }, { 8, 173, 54 }, { 41, 90, 55 }, + { 24, 140, 57 }, { 24, 140, 57 }, { 8, 189, 59 }, { 8, 189, 59 }, { 41, 107, 60 }, { 24, 156, 61 }, { 57, 74, 62 }, { 8, 206, 64 }, + { 8, 206, 64 }, { 74, 41, 65 }, { 24, 173, 66 }, { 90, 8, 67 }, { 8, 222, 68 }, { 41, 140, 69 }, { 24, 189, 70 }, { 57, 107, 71 }, + { 8, 239, 73 }, { 8, 239, 73 }, { 74, 74, 74 }, { 24, 206, 75 }, { 57, 123, 76 }, { 8, 255, 77 }, { 41, 173, 78 }, { 74, 90, 79 }, + { 24, 222, 80 }, { 90, 57, 81 }, { 41, 189, 83 }, { 41, 189, 83 }, { 24, 239, 84 }, { 57, 156, 85 }, { 90, 74, 86 }, { 41, 206, 87 }, + { 74, 123, 88 }, { 24, 255, 89 }, { 57, 173, 90 }, { 123, 8, 91 }, { 41, 222, 92 }, { 74, 140, 93 }, { 57, 189, 94 }, { 90, 107, 95 }, + { 41, 239, 97 }, { 41, 239, 97 }, { 107, 74, 98 }, { 57, 206, 99 }, { 123, 41, 100 }, { 41, 255, 101 }, { 74, 173, 102 }, { 57, 222, 103 }, + { 90, 140, 104 }, { 74, 189, 106 }, { 74, 189, 106 }, { 107, 107, 107 }, { 57, 239, 108 }, { 90, 156, 109 }, { 74, 206, 111 }, { 74, 206, 111 }, + { 107, 123, 112 }, { 57, 255, 113 }, { 123, 90, 114 }, { 74, 222, 116 }, { 74, 222, 116 }, { 140, 57, 117 }, { 90, 189, 118 }, { 123, 107, 119 }, + { 74, 239, 120 }, { 107, 156, 121 }, { 90, 206, 123 }, { 90, 206, 123 }, { 156, 41, 124 }, { 74, 255, 125 }, { 107, 173, 126 }, { 90, 222, 127 }, + { 123, 140, 128 }, { 107, 189, 130 }, { 107, 189, 130 }, { 140, 107, 131 }, { 90, 239, 132 }, { 156, 74, 133 }, { 107, 206, 135 }, { 107, 206, 135 }, + { 90, 255, 136 }, { 123, 173, 137 }, { 189, 8, 138 }, { 107, 222, 139 }, { 140, 140, 140 }, { 123, 189, 142 }, { 123, 189, 142 }, { 189, 24, 143 }, + { 107, 239, 144 }, { 140, 156, 145 }, { 123, 206, 146 }, { 156, 123, 147 }, { 107, 255, 149 }, { 107, 255, 149 }, { 173, 90, 150 }, { 123, 222, 151 }, + { 156, 140, 152 }, { 140, 189, 154 }, { 140, 189, 154 }, { 206, 24, 155 }, { 123, 239, 156 }, { 189, 74, 157 }, { 140, 206, 159 }, { 140, 206, 159 }, + { 123, 255, 160 }, { 156, 173, 161 }, { 222, 8, 162 }, { 140, 222, 163 }, { 173, 140, 164 }, { 156, 189, 165 }, { 189, 107, 166 }, { 140, 239, 168 }, + { 140, 239, 168 }, { 206, 74, 169 }, { 156, 206, 170 }, { 222, 41, 171 }, { 140, 255, 172 }, { 173, 173, 173 }, { 239, 8, 174 }, { 156, 222, 175 }, + { 222, 57, 176 }, { 173, 189, 178 }, { 173, 189, 178 }, { 156, 239, 179 }, { 189, 156, 180 }, { 173, 206, 182 }, { 173, 206, 182 }, { 206, 123, 183 }, + { 156, 255, 184 }, { 189, 173, 185 }, { 255, 8, 186 }, { 173, 222, 187 }, { 239, 57, 188 }, { 189, 189, 189 }, { 222, 107, 190 }, { 173, 239, 192 }, + { 173, 239, 192 }, { 239, 74, 193 }, { 189, 206, 194 }, { 255, 41, 195 }, { 173, 255, 196 }, { 206, 173, 197 }, { 189, 222, 198 }, { 222, 140, 199 }, + { 206, 189, 201 }, { 206, 189, 201 }, { 239, 107, 202 }, { 189, 239, 203 }, { 255, 74, 204 }, { 206, 206, 206 }, { 206, 206, 206 }, { 189, 255, 208 }, + { 189, 255, 208 }, { 255, 90, 209 }, { 206, 222, 211 }, { 206, 222, 211 }, { 206, 222, 211 }, { 222, 189, 213 }, { 206, 239, 215 }, { 206, 239, 215 }, + { 239, 156, 216 }, { 222, 206, 218 }, { 222, 206, 218 }, { 206, 255, 220 }, { 206, 255, 220 }, { 206, 255, 220 }, { 222, 222, 222 }, { 255, 140, 223 }, + { 239, 189, 225 }, { 239, 189, 225 }, { 222, 239, 227 }, { 222, 239, 227 }, { 222, 239, 227 }, { 239, 206, 230 }, { 239, 206, 230 }, { 222, 255, 231 }, + { 255, 173, 232 }, { 239, 222, 234 }, { 239, 222, 234 }, { 239, 222, 234 }, { 255, 189, 236 }, { 255, 189, 236 }, { 239, 239, 239 }, { 239, 239, 239 }, + { 239, 239, 239 }, { 255, 206, 241 }, { 255, 206, 241 }, { 239, 255, 244 }, { 239, 255, 244 }, { 239, 255, 244 }, { 255, 222, 246 }, { 255, 222, 246 }, + { 255, 222, 246 }, { 255, 239, 251 }, { 255, 239, 251 }, { 255, 239, 251 }, { 255, 239, 251 }, { 255, 239, 251 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode0_p11_i3= +{ + 3, + 3, + { + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 24, 15 }, { 8, 24, 15 }, { 8, 24, 15 }, { 8, 24, 15 }, + { 8, 24, 15 }, { 24, 8, 17 }, { 24, 8, 17 }, { 24, 8, 17 }, { 8, 41, 22 }, { 8, 41, 22 }, { 8, 41, 22 }, { 8, 41, 22 }, + { 24, 24, 24 }, { 24, 24, 24 }, { 41, 8, 27 }, { 41, 8, 27 }, { 8, 57, 29 }, { 8, 57, 29 }, { 8, 57, 29 }, { 24, 41, 31 }, + { 24, 41, 31 }, { 41, 24, 34 }, { 41, 24, 34 }, { 8, 74, 36 }, { 8, 74, 36 }, { 8, 74, 36 }, { 24, 57, 38 }, { 24, 57, 38 }, + { 41, 41, 41 }, { 41, 41, 41 }, { 8, 90, 43 }, { 8, 90, 43 }, { 8, 90, 43 }, { 24, 74, 45 }, { 74, 8, 46 }, { 41, 57, 48 }, + { 41, 57, 48 }, { 8, 107, 50 }, { 8, 107, 50 }, { 8, 107, 50 }, { 24, 90, 52 }, { 74, 24, 53 }, { 41, 74, 55 }, { 41, 74, 55 }, + { 8, 123, 57 }, { 8, 123, 57 }, { 8, 123, 57 }, { 24, 107, 59 }, { 74, 41, 60 }, { 41, 90, 62 }, { 41, 90, 62 }, { 8, 140, 64 }, + { 8, 140, 64 }, { 107, 8, 65 }, { 24, 123, 66 }, { 74, 57, 67 }, { 41, 107, 69 }, { 41, 107, 69 }, { 8, 156, 70 }, { 57, 90, 71 }, + { 107, 24, 72 }, { 24, 140, 73 }, { 74, 74, 74 }, { 41, 123, 76 }, { 41, 123, 76 }, { 8, 173, 78 }, { 8, 173, 78 }, { 107, 41, 79 }, + { 24, 156, 80 }, { 74, 90, 81 }, { 41, 140, 83 }, { 41, 140, 83 }, { 8, 189, 84 }, { 57, 123, 85 }, { 107, 57, 86 }, { 24, 173, 87 }, + { 74, 107, 88 }, { 41, 156, 90 }, { 41, 156, 90 }, { 140, 24, 91 }, { 8, 206, 92 }, { 107, 74, 93 }, { 24, 189, 94 }, { 74, 123, 95 }, + { 41, 173, 97 }, { 41, 173, 97 }, { 8, 222, 98 }, { 57, 156, 99 }, { 107, 90, 100 }, { 24, 206, 101 }, { 74, 140, 102 }, { 41, 189, 103 }, + { 90, 123, 104 }, { 8, 239, 105 }, { 57, 173, 106 }, { 107, 107, 107 }, { 24, 222, 108 }, { 74, 156, 109 }, { 173, 24, 110 }, { 41, 206, 111 }, + { 8, 255, 112 }, { 57, 189, 113 }, { 107, 123, 114 }, { 24, 239, 115 }, { 74, 173, 116 }, { 41, 222, 117 }, { 90, 156, 118 }, { 140, 90, 119 }, + { 57, 206, 120 }, { 24, 255, 121 }, { 206, 8, 122 }, { 74, 189, 123 }, { 173, 57, 124 }, { 41, 239, 125 }, { 140, 107, 126 }, { 57, 222, 127 }, + { 107, 156, 128 }, { 206, 24, 129 }, { 74, 206, 130 }, { 41, 255, 131 }, { 90, 189, 132 }, { 140, 123, 133 }, { 57, 239, 134 }, { 107, 173, 135 }, + { 74, 222, 136 }, { 123, 156, 137 }, { 173, 90, 138 }, { 90, 206, 139 }, { 140, 140, 140 }, { 57, 255, 141 }, { 107, 189, 142 }, { 206, 57, 143 }, + { 74, 239, 144 }, { 173, 107, 145 }, { 90, 222, 146 }, { 140, 156, 147 }, { 239, 24, 148 }, { 107, 206, 149 }, { 74, 255, 150 }, { 123, 189, 151 }, + { 173, 123, 152 }, { 90, 239, 153 }, { 140, 173, 154 }, { 239, 41, 155 }, { 107, 222, 156 }, { 206, 90, 157 }, { 123, 206, 158 }, { 173, 140, 159 }, + { 90, 255, 160 }, { 140, 189, 161 }, { 239, 57, 162 }, { 107, 239, 163 }, { 206, 107, 164 }, { 123, 222, 165 }, { 173, 156, 166 }, { 140, 206, 168 }, + { 140, 206, 168 }, { 107, 255, 169 }, { 156, 189, 170 }, { 206, 123, 171 }, { 123, 239, 172 }, { 173, 173, 173 }, { 140, 222, 175 }, { 140, 222, 175 }, + { 239, 90, 176 }, { 156, 206, 177 }, { 206, 140, 178 }, { 123, 255, 179 }, { 173, 189, 180 }, { 140, 239, 182 }, { 140, 239, 182 }, { 239, 107, 183 }, + { 156, 222, 184 }, { 206, 156, 185 }, { 173, 206, 187 }, { 173, 206, 187 }, { 140, 255, 189 }, { 140, 255, 189 }, { 239, 123, 190 }, { 156, 239, 191 }, + { 206, 173, 192 }, { 255, 107, 193 }, { 173, 222, 194 }, { 173, 222, 194 }, { 189, 206, 196 }, { 239, 140, 197 }, { 156, 255, 198 }, { 206, 189, 199 }, + { 173, 239, 201 }, { 173, 239, 201 }, { 173, 239, 201 }, { 189, 222, 203 }, { 239, 156, 204 }, { 206, 206, 206 }, { 206, 206, 206 }, { 173, 255, 208 }, + { 173, 255, 208 }, { 173, 255, 208 }, { 189, 239, 210 }, { 239, 173, 211 }, { 206, 222, 213 }, { 206, 222, 213 }, { 206, 222, 213 }, { 222, 206, 215 }, + { 189, 255, 217 }, { 189, 255, 217 }, { 239, 189, 218 }, { 206, 239, 220 }, { 206, 239, 220 }, { 206, 239, 220 }, { 222, 222, 222 }, { 222, 222, 222 }, + { 239, 206, 225 }, { 239, 206, 225 }, { 206, 255, 227 }, { 206, 255, 227 }, { 206, 255, 227 }, { 222, 239, 229 }, { 222, 239, 229 }, { 239, 222, 232 }, + { 239, 222, 232 }, { 239, 222, 232 }, { 255, 206, 234 }, { 222, 255, 236 }, { 222, 255, 236 }, { 222, 255, 236 }, { 239, 239, 239 }, { 239, 239, 239 }, + { 239, 239, 239 }, { 255, 222, 241 }, { 255, 222, 241 }, { 255, 222, 241 }, { 239, 255, 246 }, { 239, 255, 246 }, { 239, 255, 246 }, { 239, 255, 246 }, + { 255, 239, 248 }, { 255, 239, 248 }, { 255, 239, 248 }, { 255, 239, 248 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode1_p0_i1= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 12, 2 }, { 0, 20, 3 }, { 0, 28, 4 }, { 0, 32, 5 }, { 0, 40, 6 }, { 0, 48, 7 }, + { 0, 56, 8 }, { 0, 64, 9 }, { 0, 68, 10 }, { 0, 76, 11 }, { 0, 84, 12 }, { 0, 92, 13 }, { 0, 96, 14 }, { 0, 104, 15 }, + { 0, 112, 16 }, { 0, 120, 17 }, { 0, 129, 18 }, { 0, 133, 19 }, { 0, 141, 20 }, { 0, 149, 21 }, { 0, 153, 22 }, { 0, 161, 23 }, + { 0, 169, 24 }, { 0, 177, 25 }, { 0, 185, 26 }, { 0, 189, 27 }, { 0, 197, 28 }, { 0, 205, 29 }, { 0, 213, 30 }, { 0, 217, 31 }, + { 0, 225, 32 }, { 0, 233, 33 }, { 0, 241, 34 }, { 0, 249, 35 }, { 0, 253, 36 }, { 4, 237, 37 }, { 4, 245, 38 }, { 4, 253, 39 }, + { 8, 233, 40 }, { 8, 241, 41 }, { 8, 249, 42 }, { 12, 229, 43 }, { 12, 237, 44 }, { 12, 245, 45 }, { 12, 253, 46 }, { 16, 233, 47 }, + { 16, 241, 48 }, { 16, 249, 49 }, { 20, 233, 50 }, { 20, 237, 51 }, { 20, 245, 52 }, { 20, 253, 53 }, { 24, 237, 54 }, { 24, 241, 55 }, + { 24, 249, 56 }, { 28, 233, 57 }, { 28, 241, 58 }, { 28, 245, 59 }, { 28, 253, 60 }, { 32, 237, 61 }, { 32, 245, 62 }, { 32, 249, 63 }, + { 36, 233, 64 }, { 36, 241, 65 }, { 36, 249, 66 }, { 36, 253, 67 }, { 40, 237, 68 }, { 40, 245, 69 }, { 40, 253, 70 }, { 44, 233, 71 }, + { 44, 241, 72 }, { 44, 249, 73 }, { 48, 233, 74 }, { 48, 237, 75 }, { 48, 245, 76 }, { 48, 253, 77 }, { 52, 237, 78 }, { 52, 241, 79 }, + { 52, 249, 80 }, { 56, 233, 81 }, { 56, 241, 82 }, { 56, 245, 83 }, { 56, 253, 84 }, { 60, 237, 85 }, { 60, 245, 86 }, { 60, 249, 87 }, + { 64, 233, 88 }, { 64, 241, 89 }, { 64, 249, 90 }, { 64, 253, 91 }, { 68, 237, 92 }, { 68, 245, 93 }, { 68, 253, 94 }, { 72, 233, 95 }, + { 72, 241, 96 }, { 72, 249, 97 }, { 76, 229, 98 }, { 76, 237, 99 }, { 76, 245, 100 }, { 76, 253, 101 }, { 80, 233, 102 }, { 80, 241, 103 }, + { 80, 249, 104 }, { 84, 233, 105 }, { 84, 237, 106 }, { 84, 245, 107 }, { 84, 253, 108 }, { 88, 237, 109 }, { 88, 241, 110 }, { 88, 249, 111 }, + { 92, 233, 112 }, { 92, 241, 113 }, { 92, 245, 114 }, { 92, 253, 115 }, { 96, 237, 116 }, { 96, 245, 117 }, { 96, 249, 118 }, { 100, 233, 119 }, + { 100, 241, 120 }, { 100, 249, 121 }, { 100, 253, 122 }, { 104, 237, 123 }, { 104, 245, 124 }, { 104, 253, 125 }, { 108, 233, 126 }, { 108, 241, 127 }, + { 108, 249, 128 }, { 112, 233, 129 }, { 112, 237, 130 }, { 112, 245, 131 }, { 112, 253, 132 }, { 116, 237, 133 }, { 116, 241, 134 }, { 116, 249, 135 }, + { 120, 233, 136 }, { 120, 241, 137 }, { 120, 245, 138 }, { 120, 253, 139 }, { 124, 237, 140 }, { 124, 245, 141 }, { 124, 249, 142 }, { 129, 225, 143 }, + { 129, 233, 144 }, { 129, 241, 145 }, { 129, 249, 146 }, { 133, 229, 147 }, { 133, 237, 148 }, { 133, 245, 149 }, { 133, 253, 150 }, { 137, 233, 151 }, + { 137, 241, 152 }, { 137, 249, 153 }, { 141, 233, 154 }, { 141, 237, 155 }, { 141, 245, 156 }, { 141, 253, 157 }, { 145, 237, 158 }, { 145, 241, 159 }, + { 145, 249, 160 }, { 149, 233, 161 }, { 149, 241, 162 }, { 149, 245, 163 }, { 149, 253, 164 }, { 153, 237, 165 }, { 153, 245, 166 }, { 153, 249, 167 }, + { 157, 233, 168 }, { 157, 241, 169 }, { 157, 249, 170 }, { 157, 253, 171 }, { 161, 237, 172 }, { 161, 245, 173 }, { 161, 253, 174 }, { 165, 233, 175 }, + { 165, 241, 176 }, { 165, 249, 177 }, { 169, 233, 178 }, { 169, 237, 179 }, { 169, 245, 180 }, { 169, 253, 181 }, { 173, 237, 182 }, { 173, 241, 183 }, + { 173, 249, 184 }, { 177, 233, 185 }, { 177, 241, 186 }, { 177, 245, 187 }, { 177, 253, 188 }, { 181, 237, 189 }, { 181, 245, 190 }, { 181, 249, 191 }, + { 185, 233, 192 }, { 185, 241, 193 }, { 185, 249, 194 }, { 185, 253, 195 }, { 189, 237, 196 }, { 189, 245, 197 }, { 189, 253, 198 }, { 193, 233, 199 }, + { 193, 241, 200 }, { 193, 249, 201 }, { 197, 229, 202 }, { 197, 237, 203 }, { 197, 245, 204 }, { 197, 253, 205 }, { 201, 233, 206 }, { 201, 241, 207 }, + { 201, 249, 208 }, { 205, 233, 209 }, { 205, 237, 210 }, { 205, 245, 211 }, { 205, 253, 212 }, { 209, 237, 213 }, { 209, 241, 214 }, { 209, 249, 215 }, + { 213, 233, 216 }, { 213, 241, 217 }, { 213, 245, 218 }, { 213, 253, 219 }, { 217, 237, 220 }, { 217, 245, 221 }, { 217, 249, 222 }, { 221, 233, 223 }, + { 221, 241, 224 }, { 221, 249, 225 }, { 221, 253, 226 }, { 225, 237, 227 }, { 225, 245, 228 }, { 225, 253, 229 }, { 229, 233, 230 }, { 229, 241, 231 }, + { 229, 249, 232 }, { 233, 233, 233 }, { 233, 237, 234 }, { 233, 245, 235 }, { 233, 253, 236 }, { 237, 237, 237 }, { 237, 241, 238 }, { 237, 249, 239 }, + { 241, 233, 240 }, { 241, 241, 241 }, { 241, 245, 242 }, { 241, 253, 243 }, { 245, 237, 244 }, { 245, 245, 245 }, { 245, 249, 246 }, { 249, 233, 247 }, + { 249, 241, 248 }, { 249, 249, 249 }, { 249, 253, 250 }, { 253, 237, 251 }, { 253, 245, 252 }, { 253, 253, 253 }, { 253, 253, 253 }, { 253, 253, 253 }, + } +}; + +Table g_mode1_p0_i2= +{ + 2, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 8, 2 }, { 0, 12, 3 }, { 4, 4, 4 }, { 0, 16, 5 }, { 0, 20, 6 }, { 0, 24, 7 }, + { 0, 28, 8 }, { 0, 32, 9 }, { 0, 36, 10 }, { 0, 40, 11 }, { 0, 44, 12 }, { 4, 36, 13 }, { 0, 48, 14 }, { 0, 52, 15 }, + { 0, 56, 16 }, { 0, 60, 17 }, { 0, 64, 18 }, { 0, 68, 19 }, { 0, 72, 20 }, { 0, 76, 21 }, { 4, 68, 22 }, { 0, 80, 23 }, + { 0, 84, 24 }, { 0, 88, 25 }, { 0, 92, 26 }, { 0, 96, 27 }, { 0, 100, 28 }, { 0, 104, 29 }, { 0, 108, 30 }, { 4, 100, 31 }, + { 0, 112, 32 }, { 0, 116, 33 }, { 0, 120, 34 }, { 0, 124, 35 }, { 0, 129, 36 }, { 0, 133, 37 }, { 4, 124, 38 }, { 0, 137, 39 }, + { 0, 141, 40 }, { 0, 145, 41 }, { 0, 149, 42 }, { 0, 153, 43 }, { 0, 157, 44 }, { 0, 161, 45 }, { 0, 165, 46 }, { 4, 157, 47 }, + { 0, 169, 48 }, { 0, 173, 49 }, { 0, 177, 50 }, { 0, 181, 51 }, { 0, 185, 52 }, { 0, 189, 53 }, { 0, 193, 54 }, { 0, 197, 55 }, + { 4, 189, 56 }, { 0, 201, 57 }, { 0, 205, 58 }, { 0, 209, 59 }, { 0, 213, 60 }, { 0, 217, 61 }, { 0, 221, 62 }, { 0, 225, 63 }, + { 0, 229, 64 }, { 4, 221, 65 }, { 0, 233, 66 }, { 0, 237, 67 }, { 0, 241, 68 }, { 0, 245, 69 }, { 0, 249, 70 }, { 0, 253, 71 }, + { 4, 245, 72 }, { 4, 249, 73 }, { 4, 253, 74 }, { 8, 245, 75 }, { 8, 249, 76 }, { 8, 253, 77 }, { 12, 245, 78 }, { 12, 249, 79 }, + { 12, 253, 80 }, { 20, 237, 81 }, { 16, 249, 82 }, { 16, 253, 83 }, { 20, 249, 84 }, { 24, 241, 85 }, { 20, 253, 86 }, { 24, 249, 87 }, + { 24, 253, 88 }, { 28, 245, 89 }, { 28, 249, 90 }, { 28, 253, 91 }, { 32, 245, 92 }, { 32, 249, 93 }, { 32, 253, 94 }, { 36, 245, 95 }, + { 36, 249, 96 }, { 36, 253, 97 }, { 40, 245, 98 }, { 40, 249, 99 }, { 40, 253, 100 }, { 44, 245, 101 }, { 44, 249, 102 }, { 44, 253, 103 }, + { 52, 237, 104 }, { 48, 249, 105 }, { 48, 253, 106 }, { 52, 249, 107 }, { 56, 241, 108 }, { 52, 253, 109 }, { 56, 249, 110 }, { 56, 253, 111 }, + { 60, 245, 112 }, { 60, 249, 113 }, { 60, 253, 114 }, { 64, 245, 115 }, { 64, 249, 116 }, { 64, 253, 117 }, { 68, 245, 118 }, { 68, 249, 119 }, + { 68, 253, 120 }, { 72, 245, 121 }, { 72, 249, 122 }, { 72, 253, 123 }, { 76, 245, 124 }, { 76, 249, 125 }, { 76, 253, 126 }, { 84, 237, 127 }, + { 80, 249, 128 }, { 80, 253, 129 }, { 84, 249, 130 }, { 88, 241, 131 }, { 84, 253, 132 }, { 88, 249, 133 }, { 88, 253, 134 }, { 92, 245, 135 }, + { 92, 249, 136 }, { 92, 253, 137 }, { 96, 245, 138 }, { 96, 249, 139 }, { 96, 253, 140 }, { 100, 245, 141 }, { 100, 249, 142 }, { 100, 253, 143 }, + { 104, 245, 144 }, { 104, 249, 145 }, { 104, 253, 146 }, { 108, 245, 147 }, { 108, 249, 148 }, { 108, 253, 149 }, { 116, 237, 150 }, { 112, 249, 151 }, + { 112, 253, 152 }, { 116, 249, 153 }, { 120, 241, 154 }, { 116, 253, 155 }, { 120, 249, 156 }, { 120, 253, 157 }, { 124, 245, 158 }, { 124, 249, 159 }, + { 124, 253, 160 }, { 129, 241, 161 }, { 129, 245, 162 }, { 129, 249, 163 }, { 129, 253, 164 }, { 133, 245, 165 }, { 133, 249, 166 }, { 133, 253, 167 }, + { 141, 237, 168 }, { 137, 249, 169 }, { 137, 253, 170 }, { 141, 249, 171 }, { 145, 241, 172 }, { 141, 253, 173 }, { 145, 249, 174 }, { 145, 253, 175 }, + { 149, 245, 176 }, { 149, 249, 177 }, { 149, 253, 178 }, { 153, 245, 179 }, { 153, 249, 180 }, { 153, 253, 181 }, { 157, 245, 182 }, { 157, 249, 183 }, + { 157, 253, 184 }, { 161, 245, 185 }, { 161, 249, 186 }, { 161, 253, 187 }, { 165, 245, 188 }, { 165, 249, 189 }, { 165, 253, 190 }, { 173, 237, 191 }, + { 169, 249, 192 }, { 169, 253, 193 }, { 173, 249, 194 }, { 177, 241, 195 }, { 173, 253, 196 }, { 177, 249, 197 }, { 177, 253, 198 }, { 181, 245, 199 }, + { 181, 249, 200 }, { 181, 253, 201 }, { 185, 245, 202 }, { 185, 249, 203 }, { 185, 253, 204 }, { 189, 245, 205 }, { 189, 249, 206 }, { 189, 253, 207 }, + { 193, 245, 208 }, { 193, 249, 209 }, { 193, 253, 210 }, { 197, 245, 211 }, { 197, 249, 212 }, { 197, 253, 213 }, { 205, 237, 214 }, { 201, 249, 215 }, + { 201, 253, 216 }, { 205, 249, 217 }, { 209, 241, 218 }, { 205, 253, 219 }, { 209, 249, 220 }, { 209, 253, 221 }, { 213, 245, 222 }, { 213, 249, 223 }, + { 213, 253, 224 }, { 217, 245, 225 }, { 217, 249, 226 }, { 217, 253, 227 }, { 221, 245, 228 }, { 221, 249, 229 }, { 221, 253, 230 }, { 225, 245, 231 }, + { 225, 249, 232 }, { 225, 253, 233 }, { 229, 245, 234 }, { 229, 249, 235 }, { 229, 253, 236 }, { 237, 237, 237 }, { 233, 249, 238 }, { 233, 253, 239 }, + { 237, 249, 240 }, { 241, 241, 241 }, { 237, 253, 242 }, { 241, 249, 243 }, { 241, 253, 244 }, { 245, 245, 245 }, { 245, 249, 246 }, { 245, 253, 247 }, + { 249, 245, 248 }, { 249, 249, 249 }, { 249, 253, 250 }, { 253, 245, 251 }, { 253, 249, 252 }, { 253, 253, 253 }, { 253, 253, 253 }, { 253, 253, 253 }, + } +}; + +Table g_mode1_p0_i3= +{ + 3, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 4, 2 }, { 0, 8, 3 }, { 4, 4, 4 }, { 0, 12, 5 }, { 4, 8, 6 }, { 0, 16, 7 }, + { 0, 20, 8 }, { 4, 16, 9 }, { 0, 24, 10 }, { 4, 20, 11 }, { 0, 28, 12 }, { 8, 20, 13 }, { 0, 32, 14 }, { 0, 36, 15 }, + { 4, 32, 16 }, { 0, 40, 17 }, { 4, 36, 18 }, { 0, 44, 19 }, { 0, 48, 20 }, { 4, 44, 21 }, { 0, 52, 22 }, { 4, 48, 23 }, + { 0, 56, 24 }, { 0, 60, 25 }, { 4, 56, 26 }, { 0, 64, 27 }, { 4, 60, 28 }, { 0, 68, 29 }, { 0, 72, 30 }, { 4, 68, 31 }, + { 0, 76, 32 }, { 4, 72, 33 }, { 0, 80, 34 }, { 0, 84, 35 }, { 4, 80, 36 }, { 0, 88, 37 }, { 4, 84, 38 }, { 0, 92, 39 }, + { 8, 84, 40 }, { 0, 96, 41 }, { 0, 100, 42 }, { 4, 96, 43 }, { 0, 104, 44 }, { 4, 100, 45 }, { 0, 108, 46 }, { 0, 112, 47 }, + { 4, 108, 48 }, { 0, 116, 49 }, { 4, 112, 50 }, { 0, 120, 51 }, { 0, 124, 52 }, { 4, 120, 53 }, { 0, 129, 54 }, { 4, 124, 55 }, + { 0, 133, 56 }, { 4, 129, 57 }, { 0, 137, 58 }, { 0, 141, 59 }, { 4, 137, 60 }, { 0, 145, 61 }, { 4, 141, 62 }, { 0, 149, 63 }, + { 8, 141, 64 }, { 0, 153, 65 }, { 0, 157, 66 }, { 4, 153, 67 }, { 0, 161, 68 }, { 4, 157, 69 }, { 0, 165, 70 }, { 0, 169, 71 }, + { 4, 165, 72 }, { 0, 173, 73 }, { 4, 169, 74 }, { 0, 177, 75 }, { 0, 181, 76 }, { 4, 177, 77 }, { 0, 185, 78 }, { 4, 181, 79 }, + { 0, 189, 80 }, { 0, 193, 81 }, { 4, 189, 82 }, { 0, 197, 83 }, { 4, 193, 84 }, { 0, 201, 85 }, { 0, 205, 86 }, { 4, 201, 87 }, + { 0, 209, 88 }, { 4, 205, 89 }, { 0, 213, 90 }, { 8, 205, 91 }, { 0, 217, 92 }, { 0, 221, 93 }, { 4, 217, 94 }, { 0, 225, 95 }, + { 4, 221, 96 }, { 0, 229, 97 }, { 0, 233, 98 }, { 4, 229, 99 }, { 0, 237, 100 }, { 4, 233, 101 }, { 0, 241, 102 }, { 0, 245, 103 }, + { 4, 241, 104 }, { 0, 249, 105 }, { 4, 245, 106 }, { 0, 253, 107 }, { 8, 245, 108 }, { 4, 253, 109 }, { 8, 249, 110 }, { 8, 253, 111 }, + { 12, 249, 112 }, { 16, 245, 113 }, { 12, 253, 114 }, { 20, 245, 115 }, { 16, 253, 116 }, { 20, 249, 117 }, { 20, 253, 118 }, { 24, 249, 119 }, + { 28, 245, 120 }, { 24, 253, 121 }, { 32, 245, 122 }, { 28, 253, 123 }, { 32, 249, 124 }, { 32, 253, 125 }, { 36, 249, 126 }, { 44, 241, 127 }, + { 36, 253, 128 }, { 44, 245, 129 }, { 40, 253, 130 }, { 48, 245, 131 }, { 44, 253, 132 }, { 48, 249, 133 }, { 48, 253, 134 }, { 52, 249, 135 }, + { 56, 245, 136 }, { 52, 253, 137 }, { 60, 245, 138 }, { 56, 253, 139 }, { 60, 249, 140 }, { 60, 253, 141 }, { 64, 249, 142 }, { 68, 245, 143 }, + { 64, 253, 144 }, { 72, 245, 145 }, { 68, 253, 146 }, { 72, 249, 147 }, { 72, 253, 148 }, { 76, 249, 149 }, { 80, 245, 150 }, { 76, 253, 151 }, + { 84, 245, 152 }, { 80, 253, 153 }, { 84, 249, 154 }, { 84, 253, 155 }, { 88, 249, 156 }, { 92, 245, 157 }, { 88, 253, 158 }, { 96, 245, 159 }, + { 92, 253, 160 }, { 96, 249, 161 }, { 96, 253, 162 }, { 100, 249, 163 }, { 108, 241, 164 }, { 100, 253, 165 }, { 108, 245, 166 }, { 104, 253, 167 }, + { 112, 245, 168 }, { 108, 253, 169 }, { 112, 249, 170 }, { 112, 253, 171 }, { 116, 249, 172 }, { 120, 245, 173 }, { 116, 253, 174 }, { 124, 245, 175 }, + { 120, 253, 176 }, { 124, 249, 177 }, { 124, 253, 178 }, { 133, 241, 179 }, { 129, 249, 180 }, { 129, 253, 181 }, { 133, 249, 182 }, { 137, 245, 183 }, + { 133, 253, 184 }, { 141, 245, 185 }, { 137, 253, 186 }, { 141, 249, 187 }, { 141, 253, 188 }, { 145, 249, 189 }, { 149, 245, 190 }, { 145, 253, 191 }, + { 153, 245, 192 }, { 149, 253, 193 }, { 153, 249, 194 }, { 153, 253, 195 }, { 157, 249, 196 }, { 165, 241, 197 }, { 157, 253, 198 }, { 165, 245, 199 }, + { 161, 253, 200 }, { 169, 245, 201 }, { 165, 253, 202 }, { 169, 249, 203 }, { 169, 253, 204 }, { 173, 249, 205 }, { 177, 245, 206 }, { 173, 253, 207 }, + { 181, 245, 208 }, { 177, 253, 209 }, { 181, 249, 210 }, { 181, 253, 211 }, { 185, 249, 212 }, { 189, 245, 213 }, { 185, 253, 214 }, { 193, 245, 215 }, + { 189, 253, 216 }, { 193, 249, 217 }, { 193, 253, 218 }, { 197, 249, 219 }, { 201, 245, 220 }, { 197, 253, 221 }, { 205, 245, 222 }, { 201, 253, 223 }, + { 205, 249, 224 }, { 205, 253, 225 }, { 209, 249, 226 }, { 213, 245, 227 }, { 209, 253, 228 }, { 217, 245, 229 }, { 213, 253, 230 }, { 217, 249, 231 }, + { 217, 253, 232 }, { 221, 249, 233 }, { 229, 241, 234 }, { 221, 253, 235 }, { 229, 245, 236 }, { 225, 253, 237 }, { 233, 245, 238 }, { 229, 253, 239 }, + { 233, 249, 240 }, { 233, 253, 241 }, { 237, 249, 242 }, { 241, 245, 243 }, { 237, 253, 244 }, { 245, 245, 245 }, { 241, 253, 246 }, { 245, 249, 247 }, + { 245, 253, 248 }, { 249, 249, 249 }, { 253, 245, 250 }, { 249, 253, 251 }, { 249, 253, 251 }, { 253, 253, 253 }, { 253, 253, 253 }, { 253, 253, 253 }, + } +}; + +Table g_mode1_p1_i1= +{ + 1, + 1, + { + { 2, 2, 2 }, { 2, 2, 2 }, { 2, 2, 2 }, { 2, 6, 3 }, { 2, 14, 4 }, { 2, 22, 5 }, { 2, 30, 6 }, { 2, 34, 7 }, + { 2, 42, 8 }, { 2, 50, 9 }, { 2, 58, 10 }, { 2, 66, 11 }, { 2, 70, 12 }, { 2, 78, 13 }, { 2, 86, 14 }, { 2, 94, 15 }, + { 2, 98, 16 }, { 2, 106, 17 }, { 2, 114, 18 }, { 2, 122, 19 }, { 2, 131, 20 }, { 2, 135, 21 }, { 2, 143, 22 }, { 2, 151, 23 }, + { 2, 155, 24 }, { 2, 163, 25 }, { 2, 171, 26 }, { 2, 179, 27 }, { 2, 187, 28 }, { 2, 191, 29 }, { 2, 199, 30 }, { 2, 207, 31 }, + { 2, 215, 32 }, { 2, 219, 33 }, { 2, 227, 34 }, { 2, 235, 35 }, { 2, 243, 36 }, { 2, 251, 37 }, { 2, 255, 38 }, { 6, 239, 39 }, + { 6, 247, 40 }, { 6, 255, 41 }, { 10, 235, 42 }, { 10, 243, 43 }, { 10, 251, 44 }, { 14, 231, 45 }, { 14, 239, 46 }, { 14, 247, 47 }, + { 14, 255, 48 }, { 18, 235, 49 }, { 18, 243, 50 }, { 18, 251, 51 }, { 22, 235, 52 }, { 22, 239, 53 }, { 22, 247, 54 }, { 22, 255, 55 }, + { 26, 239, 56 }, { 26, 243, 57 }, { 26, 251, 58 }, { 30, 235, 59 }, { 30, 243, 60 }, { 30, 247, 61 }, { 30, 255, 62 }, { 34, 239, 63 }, + { 34, 247, 64 }, { 34, 251, 65 }, { 38, 235, 66 }, { 38, 243, 67 }, { 38, 251, 68 }, { 38, 255, 69 }, { 42, 239, 70 }, { 42, 247, 71 }, + { 42, 255, 72 }, { 46, 235, 73 }, { 46, 243, 74 }, { 46, 251, 75 }, { 50, 235, 76 }, { 50, 239, 77 }, { 50, 247, 78 }, { 50, 255, 79 }, + { 54, 239, 80 }, { 54, 243, 81 }, { 54, 251, 82 }, { 58, 235, 83 }, { 58, 243, 84 }, { 58, 247, 85 }, { 58, 255, 86 }, { 62, 239, 87 }, + { 62, 247, 88 }, { 62, 251, 89 }, { 66, 235, 90 }, { 66, 243, 91 }, { 66, 251, 92 }, { 66, 255, 93 }, { 70, 239, 94 }, { 70, 247, 95 }, + { 70, 255, 96 }, { 74, 235, 97 }, { 74, 243, 98 }, { 74, 251, 99 }, { 78, 231, 100 }, { 78, 239, 101 }, { 78, 247, 102 }, { 78, 255, 103 }, + { 82, 235, 104 }, { 82, 243, 105 }, { 82, 251, 106 }, { 86, 235, 107 }, { 86, 239, 108 }, { 86, 247, 109 }, { 86, 255, 110 }, { 90, 239, 111 }, + { 90, 243, 112 }, { 90, 251, 113 }, { 94, 235, 114 }, { 94, 243, 115 }, { 94, 247, 116 }, { 94, 255, 117 }, { 98, 239, 118 }, { 98, 247, 119 }, + { 98, 251, 120 }, { 102, 235, 121 }, { 102, 243, 122 }, { 102, 251, 123 }, { 102, 255, 124 }, { 106, 239, 125 }, { 106, 247, 126 }, { 106, 255, 127 }, + { 110, 235, 128 }, { 110, 243, 129 }, { 110, 251, 130 }, { 114, 235, 131 }, { 114, 239, 132 }, { 114, 247, 133 }, { 114, 255, 134 }, { 118, 239, 135 }, + { 118, 243, 136 }, { 118, 251, 137 }, { 122, 235, 138 }, { 122, 243, 139 }, { 122, 247, 140 }, { 122, 255, 141 }, { 126, 239, 142 }, { 126, 247, 143 }, + { 126, 251, 144 }, { 131, 227, 145 }, { 131, 235, 146 }, { 131, 243, 147 }, { 131, 251, 148 }, { 135, 231, 149 }, { 135, 239, 150 }, { 135, 247, 151 }, + { 135, 255, 152 }, { 139, 235, 153 }, { 139, 243, 154 }, { 139, 251, 155 }, { 143, 235, 156 }, { 143, 239, 157 }, { 143, 247, 158 }, { 143, 255, 159 }, + { 147, 239, 160 }, { 147, 243, 161 }, { 147, 251, 162 }, { 151, 235, 163 }, { 151, 243, 164 }, { 151, 247, 165 }, { 151, 255, 166 }, { 155, 239, 167 }, + { 155, 247, 168 }, { 155, 251, 169 }, { 159, 235, 170 }, { 159, 243, 171 }, { 159, 251, 172 }, { 159, 255, 173 }, { 163, 239, 174 }, { 163, 247, 175 }, + { 163, 255, 176 }, { 167, 235, 177 }, { 167, 243, 178 }, { 167, 251, 179 }, { 171, 235, 180 }, { 171, 239, 181 }, { 171, 247, 182 }, { 171, 255, 183 }, + { 175, 239, 184 }, { 175, 243, 185 }, { 175, 251, 186 }, { 179, 235, 187 }, { 179, 243, 188 }, { 179, 247, 189 }, { 179, 255, 190 }, { 183, 239, 191 }, + { 183, 247, 192 }, { 183, 251, 193 }, { 187, 235, 194 }, { 187, 243, 195 }, { 187, 251, 196 }, { 187, 255, 197 }, { 191, 239, 198 }, { 191, 247, 199 }, + { 191, 255, 200 }, { 195, 235, 201 }, { 195, 243, 202 }, { 195, 251, 203 }, { 199, 231, 204 }, { 199, 239, 205 }, { 199, 247, 206 }, { 199, 255, 207 }, + { 203, 235, 208 }, { 203, 243, 209 }, { 203, 251, 210 }, { 207, 235, 211 }, { 207, 239, 212 }, { 207, 247, 213 }, { 207, 255, 214 }, { 211, 239, 215 }, + { 211, 243, 216 }, { 211, 251, 217 }, { 215, 235, 218 }, { 215, 243, 219 }, { 215, 247, 220 }, { 215, 255, 221 }, { 219, 239, 222 }, { 219, 247, 223 }, + { 219, 251, 224 }, { 223, 235, 225 }, { 223, 243, 226 }, { 223, 251, 227 }, { 223, 255, 228 }, { 227, 239, 229 }, { 227, 247, 230 }, { 227, 255, 231 }, + { 231, 235, 232 }, { 231, 243, 233 }, { 231, 251, 234 }, { 235, 235, 235 }, { 235, 239, 236 }, { 235, 247, 237 }, { 235, 255, 238 }, { 239, 239, 239 }, + { 239, 243, 240 }, { 239, 251, 241 }, { 243, 235, 242 }, { 243, 243, 243 }, { 243, 247, 244 }, { 243, 255, 245 }, { 247, 239, 246 }, { 247, 247, 247 }, + { 247, 251, 248 }, { 251, 235, 249 }, { 251, 243, 250 }, { 251, 251, 251 }, { 251, 255, 252 }, { 255, 239, 253 }, { 255, 247, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode1_p1_i2= +{ + 2, + 1, + { + { 2, 2, 2 }, { 2, 2, 2 }, { 2, 2, 2 }, { 2, 6, 3 }, { 2, 10, 4 }, { 2, 14, 5 }, { 6, 6, 6 }, { 2, 18, 7 }, + { 2, 22, 8 }, { 2, 26, 9 }, { 2, 30, 10 }, { 2, 34, 11 }, { 2, 38, 12 }, { 2, 42, 13 }, { 2, 46, 14 }, { 6, 38, 15 }, + { 2, 50, 16 }, { 2, 54, 17 }, { 2, 58, 18 }, { 2, 62, 19 }, { 2, 66, 20 }, { 2, 70, 21 }, { 2, 74, 22 }, { 2, 78, 23 }, + { 6, 70, 24 }, { 2, 82, 25 }, { 2, 86, 26 }, { 2, 90, 27 }, { 2, 94, 28 }, { 2, 98, 29 }, { 2, 102, 30 }, { 2, 106, 31 }, + { 2, 110, 32 }, { 6, 102, 33 }, { 2, 114, 34 }, { 2, 118, 35 }, { 2, 122, 36 }, { 2, 126, 37 }, { 2, 131, 38 }, { 2, 135, 39 }, + { 6, 126, 40 }, { 2, 139, 41 }, { 2, 143, 42 }, { 2, 147, 43 }, { 2, 151, 44 }, { 2, 155, 45 }, { 2, 159, 46 }, { 2, 163, 47 }, + { 2, 167, 48 }, { 6, 159, 49 }, { 2, 171, 50 }, { 2, 175, 51 }, { 2, 179, 52 }, { 2, 183, 53 }, { 2, 187, 54 }, { 2, 191, 55 }, + { 2, 195, 56 }, { 2, 199, 57 }, { 6, 191, 58 }, { 2, 203, 59 }, { 2, 207, 60 }, { 2, 211, 61 }, { 2, 215, 62 }, { 2, 219, 63 }, + { 2, 223, 64 }, { 2, 227, 65 }, { 2, 231, 66 }, { 6, 223, 67 }, { 2, 235, 68 }, { 2, 239, 69 }, { 2, 243, 70 }, { 2, 247, 71 }, + { 2, 251, 72 }, { 2, 255, 73 }, { 6, 247, 74 }, { 6, 251, 75 }, { 6, 255, 76 }, { 10, 247, 77 }, { 10, 251, 78 }, { 10, 255, 79 }, + { 14, 247, 80 }, { 14, 251, 81 }, { 14, 255, 82 }, { 22, 239, 83 }, { 18, 251, 84 }, { 18, 255, 85 }, { 22, 251, 86 }, { 26, 243, 87 }, + { 22, 255, 88 }, { 26, 251, 89 }, { 26, 255, 90 }, { 30, 247, 91 }, { 30, 251, 92 }, { 30, 255, 93 }, { 34, 247, 94 }, { 34, 251, 95 }, + { 34, 255, 96 }, { 38, 247, 97 }, { 38, 251, 98 }, { 38, 255, 99 }, { 42, 247, 100 }, { 42, 251, 101 }, { 42, 255, 102 }, { 46, 247, 103 }, + { 46, 251, 104 }, { 46, 255, 105 }, { 54, 239, 106 }, { 50, 251, 107 }, { 50, 255, 108 }, { 54, 251, 109 }, { 58, 243, 110 }, { 54, 255, 111 }, + { 58, 251, 112 }, { 58, 255, 113 }, { 62, 247, 114 }, { 62, 251, 115 }, { 62, 255, 116 }, { 66, 247, 117 }, { 66, 251, 118 }, { 66, 255, 119 }, + { 70, 247, 120 }, { 70, 251, 121 }, { 70, 255, 122 }, { 74, 247, 123 }, { 74, 251, 124 }, { 74, 255, 125 }, { 78, 247, 126 }, { 78, 251, 127 }, + { 78, 255, 128 }, { 86, 239, 129 }, { 82, 251, 130 }, { 82, 255, 131 }, { 86, 251, 132 }, { 90, 243, 133 }, { 86, 255, 134 }, { 90, 251, 135 }, + { 90, 255, 136 }, { 94, 247, 137 }, { 94, 251, 138 }, { 94, 255, 139 }, { 98, 247, 140 }, { 98, 251, 141 }, { 98, 255, 142 }, { 102, 247, 143 }, + { 102, 251, 144 }, { 102, 255, 145 }, { 106, 247, 146 }, { 106, 251, 147 }, { 106, 255, 148 }, { 110, 247, 149 }, { 110, 251, 150 }, { 110, 255, 151 }, + { 118, 239, 152 }, { 114, 251, 153 }, { 114, 255, 154 }, { 118, 251, 155 }, { 122, 243, 156 }, { 118, 255, 157 }, { 122, 251, 158 }, { 122, 255, 159 }, + { 126, 247, 160 }, { 126, 251, 161 }, { 126, 255, 162 }, { 131, 243, 163 }, { 131, 247, 164 }, { 131, 251, 165 }, { 131, 255, 166 }, { 135, 247, 167 }, + { 135, 251, 168 }, { 135, 255, 169 }, { 143, 239, 170 }, { 139, 251, 171 }, { 139, 255, 172 }, { 143, 251, 173 }, { 147, 243, 174 }, { 143, 255, 175 }, + { 147, 251, 176 }, { 147, 255, 177 }, { 151, 247, 178 }, { 151, 251, 179 }, { 151, 255, 180 }, { 155, 247, 181 }, { 155, 251, 182 }, { 155, 255, 183 }, + { 159, 247, 184 }, { 159, 251, 185 }, { 159, 255, 186 }, { 163, 247, 187 }, { 163, 251, 188 }, { 163, 255, 189 }, { 167, 247, 190 }, { 167, 251, 191 }, + { 167, 255, 192 }, { 175, 239, 193 }, { 171, 251, 194 }, { 171, 255, 195 }, { 175, 251, 196 }, { 179, 243, 197 }, { 175, 255, 198 }, { 179, 251, 199 }, + { 179, 255, 200 }, { 183, 247, 201 }, { 183, 251, 202 }, { 183, 255, 203 }, { 187, 247, 204 }, { 187, 251, 205 }, { 187, 255, 206 }, { 191, 247, 207 }, + { 191, 251, 208 }, { 191, 255, 209 }, { 195, 247, 210 }, { 195, 251, 211 }, { 195, 255, 212 }, { 199, 247, 213 }, { 199, 251, 214 }, { 199, 255, 215 }, + { 207, 239, 216 }, { 203, 251, 217 }, { 203, 255, 218 }, { 207, 251, 219 }, { 211, 243, 220 }, { 207, 255, 221 }, { 211, 251, 222 }, { 211, 255, 223 }, + { 215, 247, 224 }, { 215, 251, 225 }, { 215, 255, 226 }, { 219, 247, 227 }, { 219, 251, 228 }, { 219, 255, 229 }, { 223, 247, 230 }, { 223, 251, 231 }, + { 223, 255, 232 }, { 227, 247, 233 }, { 227, 251, 234 }, { 227, 255, 235 }, { 231, 247, 236 }, { 231, 251, 237 }, { 231, 255, 238 }, { 239, 239, 239 }, + { 235, 251, 240 }, { 235, 255, 241 }, { 239, 251, 242 }, { 243, 243, 243 }, { 239, 255, 244 }, { 243, 251, 245 }, { 243, 255, 246 }, { 247, 247, 247 }, + { 247, 251, 248 }, { 247, 255, 249 }, { 251, 247, 250 }, { 251, 251, 251 }, { 251, 255, 252 }, { 255, 247, 253 }, { 255, 251, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode1_p1_i3= +{ + 3, + 1, + { + { 2, 2, 2 }, { 2, 2, 2 }, { 2, 2, 2 }, { 2, 2, 2 }, { 2, 6, 4 }, { 2, 10, 5 }, { 6, 6, 6 }, { 2, 14, 7 }, + { 6, 10, 8 }, { 2, 18, 9 }, { 2, 22, 10 }, { 6, 18, 11 }, { 2, 26, 12 }, { 6, 22, 13 }, { 2, 30, 14 }, { 10, 22, 15 }, + { 2, 34, 16 }, { 2, 38, 17 }, { 6, 34, 18 }, { 2, 42, 19 }, { 6, 38, 20 }, { 2, 46, 21 }, { 2, 50, 22 }, { 6, 46, 23 }, + { 2, 54, 24 }, { 6, 50, 25 }, { 2, 58, 26 }, { 2, 62, 27 }, { 6, 58, 28 }, { 2, 66, 29 }, { 6, 62, 30 }, { 2, 70, 31 }, + { 2, 74, 32 }, { 6, 70, 33 }, { 2, 78, 34 }, { 6, 74, 35 }, { 2, 82, 36 }, { 2, 86, 37 }, { 6, 82, 38 }, { 2, 90, 39 }, + { 6, 86, 40 }, { 2, 94, 41 }, { 10, 86, 42 }, { 2, 98, 43 }, { 2, 102, 44 }, { 6, 98, 45 }, { 2, 106, 46 }, { 6, 102, 47 }, + { 2, 110, 48 }, { 2, 114, 49 }, { 6, 110, 50 }, { 2, 118, 51 }, { 6, 114, 52 }, { 2, 122, 53 }, { 2, 126, 54 }, { 6, 122, 55 }, + { 2, 131, 56 }, { 6, 126, 57 }, { 2, 135, 58 }, { 6, 131, 59 }, { 2, 139, 60 }, { 2, 143, 61 }, { 6, 139, 62 }, { 2, 147, 63 }, + { 6, 143, 64 }, { 2, 151, 65 }, { 10, 143, 66 }, { 2, 155, 67 }, { 2, 159, 68 }, { 6, 155, 69 }, { 2, 163, 70 }, { 6, 159, 71 }, + { 2, 167, 72 }, { 2, 171, 73 }, { 6, 167, 74 }, { 2, 175, 75 }, { 6, 171, 76 }, { 2, 179, 77 }, { 2, 183, 78 }, { 6, 179, 79 }, + { 2, 187, 80 }, { 6, 183, 81 }, { 2, 191, 82 }, { 2, 195, 83 }, { 6, 191, 84 }, { 2, 199, 85 }, { 6, 195, 86 }, { 2, 203, 87 }, + { 2, 207, 88 }, { 6, 203, 89 }, { 2, 211, 90 }, { 6, 207, 91 }, { 2, 215, 92 }, { 10, 207, 93 }, { 2, 219, 94 }, { 2, 223, 95 }, + { 6, 219, 96 }, { 2, 227, 97 }, { 6, 223, 98 }, { 2, 231, 99 }, { 2, 235, 100 }, { 6, 231, 101 }, { 2, 239, 102 }, { 6, 235, 103 }, + { 2, 243, 104 }, { 2, 247, 105 }, { 6, 243, 106 }, { 2, 251, 107 }, { 6, 247, 108 }, { 2, 255, 109 }, { 10, 247, 110 }, { 6, 255, 111 }, + { 10, 251, 112 }, { 10, 255, 113 }, { 14, 251, 114 }, { 18, 247, 115 }, { 14, 255, 116 }, { 22, 247, 117 }, { 18, 255, 118 }, { 22, 251, 119 }, + { 22, 255, 120 }, { 26, 251, 121 }, { 30, 247, 122 }, { 26, 255, 123 }, { 34, 247, 124 }, { 30, 255, 125 }, { 34, 251, 126 }, { 34, 255, 127 }, + { 38, 251, 128 }, { 46, 243, 129 }, { 38, 255, 130 }, { 46, 247, 131 }, { 42, 255, 132 }, { 50, 247, 133 }, { 46, 255, 134 }, { 50, 251, 135 }, + { 50, 255, 136 }, { 54, 251, 137 }, { 58, 247, 138 }, { 54, 255, 139 }, { 62, 247, 140 }, { 58, 255, 141 }, { 62, 251, 142 }, { 62, 255, 143 }, + { 66, 251, 144 }, { 70, 247, 145 }, { 66, 255, 146 }, { 74, 247, 147 }, { 70, 255, 148 }, { 74, 251, 149 }, { 74, 255, 150 }, { 78, 251, 151 }, + { 82, 247, 152 }, { 78, 255, 153 }, { 86, 247, 154 }, { 82, 255, 155 }, { 86, 251, 156 }, { 86, 255, 157 }, { 90, 251, 158 }, { 94, 247, 159 }, + { 90, 255, 160 }, { 98, 247, 161 }, { 94, 255, 162 }, { 98, 251, 163 }, { 98, 255, 164 }, { 102, 251, 165 }, { 110, 243, 166 }, { 102, 255, 167 }, + { 110, 247, 168 }, { 106, 255, 169 }, { 114, 247, 170 }, { 110, 255, 171 }, { 114, 251, 172 }, { 114, 255, 173 }, { 118, 251, 174 }, { 122, 247, 175 }, + { 118, 255, 176 }, { 126, 247, 177 }, { 122, 255, 178 }, { 126, 251, 179 }, { 126, 255, 180 }, { 135, 243, 181 }, { 131, 251, 182 }, { 131, 255, 183 }, + { 135, 251, 184 }, { 139, 247, 185 }, { 135, 255, 186 }, { 143, 247, 187 }, { 139, 255, 188 }, { 143, 251, 189 }, { 143, 255, 190 }, { 147, 251, 191 }, + { 151, 247, 192 }, { 147, 255, 193 }, { 155, 247, 194 }, { 151, 255, 195 }, { 155, 251, 196 }, { 155, 255, 197 }, { 159, 251, 198 }, { 167, 243, 199 }, + { 159, 255, 200 }, { 167, 247, 201 }, { 163, 255, 202 }, { 171, 247, 203 }, { 167, 255, 204 }, { 171, 251, 205 }, { 171, 255, 206 }, { 175, 251, 207 }, + { 179, 247, 208 }, { 175, 255, 209 }, { 183, 247, 210 }, { 179, 255, 211 }, { 183, 251, 212 }, { 183, 255, 213 }, { 187, 251, 214 }, { 191, 247, 215 }, + { 187, 255, 216 }, { 195, 247, 217 }, { 191, 255, 218 }, { 195, 251, 219 }, { 195, 255, 220 }, { 199, 251, 221 }, { 203, 247, 222 }, { 199, 255, 223 }, + { 207, 247, 224 }, { 203, 255, 225 }, { 207, 251, 226 }, { 207, 255, 227 }, { 211, 251, 228 }, { 215, 247, 229 }, { 211, 255, 230 }, { 219, 247, 231 }, + { 215, 255, 232 }, { 219, 251, 233 }, { 219, 255, 234 }, { 223, 251, 235 }, { 231, 243, 236 }, { 223, 255, 237 }, { 231, 247, 238 }, { 227, 255, 239 }, + { 235, 247, 240 }, { 231, 255, 241 }, { 235, 251, 242 }, { 235, 255, 243 }, { 239, 251, 244 }, { 243, 247, 245 }, { 239, 255, 246 }, { 247, 247, 247 }, + { 243, 255, 248 }, { 247, 251, 249 }, { 247, 255, 250 }, { 251, 251, 251 }, { 255, 247, 252 }, { 251, 255, 253 }, { 251, 255, 253 }, { 255, 255, 255 }, + } +}; + +Table g_mode2= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 24, 8 }, + { 0, 24, 8 }, { 0, 24, 8 }, { 0, 33, 11 }, { 0, 33, 11 }, { 0, 33, 11 }, { 0, 41, 13 }, { 0, 41, 13 }, { 0, 49, 16 }, + { 0, 49, 16 }, { 0, 49, 16 }, { 0, 57, 19 }, { 0, 57, 19 }, { 0, 57, 19 }, { 8, 49, 21 }, { 0, 66, 22 }, { 0, 66, 22 }, + { 0, 74, 24 }, { 33, 8, 25 }, { 0, 82, 27 }, { 0, 82, 27 }, { 41, 0, 28 }, { 16, 57, 29 }, { 0, 90, 30 }, { 0, 90, 30 }, + { 0, 99, 32 }, { 33, 33, 33 }, { 0, 107, 35 }, { 0, 107, 35 }, { 33, 41, 36 }, { 0, 115, 38 }, { 0, 115, 38 }, { 0, 115, 38 }, + { 0, 123, 40 }, { 33, 57, 41 }, { 0, 132, 43 }, { 0, 132, 43 }, { 33, 66, 44 }, { 0, 140, 46 }, { 0, 140, 46 }, { 66, 8, 47 }, + { 16, 115, 48 }, { 0, 148, 49 }, { 66, 16, 50 }, { 0, 156, 51 }, { 33, 90, 52 }, { 0, 165, 54 }, { 0, 165, 54 }, { 33, 99, 55 }, + { 24, 123, 56 }, { 0, 173, 57 }, { 66, 41, 58 }, { 0, 181, 59 }, { 8, 165, 60 }, { 74, 33, 61 }, { 0, 189, 62 }, { 33, 123, 63 }, + { 0, 198, 65 }, { 0, 198, 65 }, { 66, 66, 66 }, { 8, 189, 67 }, { 0, 206, 68 }, { 66, 74, 69 }, { 0, 214, 70 }, { 33, 148, 71 }, + { 99, 16, 72 }, { 0, 222, 73 }, { 66, 90, 74 }, { 107, 8, 75 }, { 0, 231, 76 }, { 66, 99, 77 }, { 0, 239, 78 }, { 33, 173, 79 }, + { 99, 41, 80 }, { 0, 247, 81 }, { 33, 181, 82 }, { 99, 49, 83 }, { 0, 255, 84 }, { 66, 123, 85 }, { 8, 247, 86 }, { 16, 231, 87 }, + { 66, 132, 88 }, { 8, 255, 89 }, { 33, 206, 90 }, { 99, 74, 91 }, { 16, 247, 92 }, { 41, 198, 93 }, { 16, 255, 94 }, { 24, 239, 95 }, + { 66, 156, 96 }, { 24, 247, 97 }, { 33, 231, 98 }, { 99, 99, 99 }, { 24, 255, 100 }, { 33, 239, 101 }, { 99, 107, 102 }, { 33, 247, 103 }, + { 66, 181, 104 }, { 132, 49, 105 }, { 33, 255, 106 }, { 99, 123, 107 }, { 140, 41, 108 }, { 41, 247, 109 }, { 99, 132, 110 }, { 41, 255, 111 }, + { 66, 206, 112 }, { 132, 74, 113 }, { 49, 247, 114 }, { 66, 214, 115 }, { 132, 82, 116 }, { 49, 255, 117 }, { 99, 156, 118 }, { 57, 247, 119 }, + { 66, 231, 120 }, { 99, 165, 121 }, { 57, 255, 122 }, { 66, 239, 123 }, { 132, 107, 124 }, { 66, 247, 125 }, { 74, 231, 126 }, { 140, 99, 127 }, + { 66, 255, 128 }, { 99, 189, 129 }, { 165, 57, 130 }, { 74, 247, 131 }, { 132, 132, 132 }, { 74, 255, 133 }, { 82, 239, 134 }, { 132, 140, 135 }, + { 82, 247, 136 }, { 99, 214, 137 }, { 165, 82, 138 }, { 82, 255, 139 }, { 132, 156, 140 }, { 173, 74, 141 }, { 90, 247, 142 }, { 132, 165, 143 }, + { 90, 255, 144 }, { 99, 239, 145 }, { 165, 107, 146 }, { 115, 214, 147 }, { 99, 247, 148 }, { 165, 115, 149 }, { 99, 255, 150 }, { 132, 189, 151 }, + { 198, 57, 152 }, { 107, 247, 153 }, { 132, 198, 154 }, { 123, 222, 155 }, { 107, 255, 156 }, { 165, 140, 157 }, { 115, 247, 158 }, { 132, 214, 159 }, + { 173, 132, 160 }, { 115, 255, 161 }, { 132, 222, 162 }, { 198, 90, 163 }, { 123, 247, 164 }, { 165, 165, 165 }, { 123, 255, 166 }, { 132, 239, 167 }, + { 165, 173, 168 }, { 231, 41, 169 }, { 132, 247, 170 }, { 198, 115, 171 }, { 132, 255, 172 }, { 165, 189, 173 }, { 206, 107, 174 }, { 140, 247, 175 }, + { 165, 198, 176 }, { 231, 66, 177 }, { 140, 255, 178 }, { 198, 140, 179 }, { 148, 247, 180 }, { 156, 231, 181 }, { 198, 148, 182 }, { 148, 255, 183 }, + { 165, 222, 184 }, { 231, 90, 185 }, { 156, 247, 186 }, { 165, 231, 187 }, { 156, 255, 188 }, { 165, 239, 189 }, { 198, 173, 190 }, { 165, 247, 192 }, + { 165, 247, 192 }, { 206, 165, 193 }, { 181, 222, 194 }, { 165, 255, 195 }, { 231, 123, 196 }, { 173, 247, 197 }, { 198, 198, 198 }, { 231, 132, 199 }, + { 173, 255, 200 }, { 198, 206, 201 }, { 181, 247, 203 }, { 181, 247, 203 }, { 231, 148, 204 }, { 181, 255, 205 }, { 198, 222, 206 }, { 239, 140, 207 }, + { 189, 247, 208 }, { 198, 231, 209 }, { 189, 255, 211 }, { 189, 255, 211 }, { 231, 173, 212 }, { 198, 247, 214 }, { 198, 247, 214 }, { 231, 181, 215 }, + { 198, 255, 217 }, { 198, 255, 217 }, { 198, 255, 217 }, { 206, 247, 219 }, { 214, 231, 220 }, { 206, 255, 222 }, { 206, 255, 222 }, { 231, 206, 223 }, + { 214, 247, 225 }, { 214, 247, 225 }, { 239, 198, 226 }, { 214, 255, 227 }, { 222, 239, 228 }, { 222, 239, 228 }, { 222, 247, 230 }, { 231, 231, 231 }, + { 222, 255, 233 }, { 222, 255, 233 }, { 231, 239, 234 }, { 231, 239, 234 }, { 231, 247, 236 }, { 231, 247, 236 }, { 231, 255, 239 }, { 231, 255, 239 }, + { 231, 255, 239 }, { 239, 247, 242 }, { 239, 247, 242 }, { 239, 247, 242 }, { 239, 255, 244 }, { 239, 255, 244 }, { 247, 247, 247 }, { 247, 247, 247 }, + { 247, 247, 247 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 255, 247, 252 }, { 255, 247, 252 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode3_p0= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 6, 2 }, { 0, 8, 3 }, { 0, 12, 4 }, { 0, 14, 5 }, { 0, 18, 6 }, { 0, 20, 7 }, + { 0, 24, 8 }, { 0, 26, 9 }, { 0, 30, 10 }, { 0, 32, 11 }, { 0, 36, 12 }, { 0, 40, 13 }, { 0, 42, 14 }, { 0, 46, 15 }, + { 0, 48, 16 }, { 0, 52, 17 }, { 0, 54, 18 }, { 0, 58, 19 }, { 0, 60, 20 }, { 0, 64, 21 }, { 0, 66, 22 }, { 0, 70, 23 }, + { 0, 72, 24 }, { 0, 76, 25 }, { 0, 78, 26 }, { 0, 82, 27 }, { 0, 84, 28 }, { 0, 88, 29 }, { 0, 90, 30 }, { 0, 94, 31 }, + { 0, 96, 32 }, { 0, 100, 33 }, { 0, 104, 34 }, { 0, 106, 35 }, { 0, 110, 36 }, { 0, 112, 37 }, { 0, 116, 38 }, { 0, 118, 39 }, + { 0, 122, 40 }, { 0, 124, 41 }, { 0, 128, 42 }, { 0, 130, 43 }, { 0, 134, 44 }, { 0, 136, 45 }, { 0, 140, 46 }, { 0, 142, 47 }, + { 0, 146, 48 }, { 0, 148, 49 }, { 0, 152, 50 }, { 0, 154, 51 }, { 0, 158, 52 }, { 0, 160, 53 }, { 0, 164, 54 }, { 0, 168, 55 }, + { 0, 170, 56 }, { 0, 174, 57 }, { 0, 176, 58 }, { 0, 180, 59 }, { 0, 182, 60 }, { 0, 186, 61 }, { 0, 188, 62 }, { 0, 192, 63 }, + { 0, 194, 64 }, { 0, 198, 65 }, { 0, 200, 66 }, { 0, 204, 67 }, { 0, 206, 68 }, { 0, 210, 69 }, { 0, 212, 70 }, { 0, 216, 71 }, + { 0, 218, 72 }, { 0, 222, 73 }, { 0, 224, 74 }, { 0, 228, 75 }, { 0, 232, 76 }, { 0, 234, 77 }, { 0, 238, 78 }, { 0, 240, 79 }, + { 0, 244, 80 }, { 0, 246, 81 }, { 0, 250, 82 }, { 0, 252, 83 }, { 2, 252, 84 }, { 2, 254, 85 }, { 4, 254, 86 }, { 6, 252, 87 }, + { 8, 252, 88 }, { 8, 254, 89 }, { 10, 254, 90 }, { 12, 252, 91 }, { 14, 252, 92 }, { 14, 254, 93 }, { 16, 254, 94 }, { 18, 252, 95 }, + { 20, 252, 96 }, { 20, 254, 97 }, { 22, 254, 98 }, { 24, 252, 99 }, { 26, 250, 100 }, { 26, 254, 101 }, { 28, 252, 102 }, { 30, 252, 103 }, + { 30, 254, 104 }, { 32, 254, 105 }, { 34, 252, 106 }, { 36, 252, 107 }, { 36, 254, 108 }, { 38, 254, 109 }, { 40, 252, 110 }, { 42, 252, 111 }, + { 42, 254, 112 }, { 44, 254, 113 }, { 46, 252, 114 }, { 48, 252, 115 }, { 48, 254, 116 }, { 50, 254, 117 }, { 52, 252, 118 }, { 54, 252, 119 }, + { 54, 254, 120 }, { 56, 254, 121 }, { 58, 252, 122 }, { 60, 252, 123 }, { 60, 254, 124 }, { 62, 254, 125 }, { 64, 252, 126 }, { 66, 252, 127 }, + { 66, 254, 128 }, { 68, 254, 129 }, { 70, 252, 130 }, { 72, 252, 131 }, { 72, 254, 132 }, { 74, 254, 133 }, { 76, 252, 134 }, { 78, 252, 135 }, + { 78, 254, 136 }, { 80, 254, 137 }, { 82, 252, 138 }, { 84, 252, 139 }, { 84, 254, 140 }, { 86, 254, 141 }, { 88, 252, 142 }, { 90, 250, 143 }, + { 90, 254, 144 }, { 92, 252, 145 }, { 94, 252, 146 }, { 94, 254, 147 }, { 96, 254, 148 }, { 98, 252, 149 }, { 100, 252, 150 }, { 100, 254, 151 }, + { 102, 254, 152 }, { 104, 252, 153 }, { 106, 252, 154 }, { 106, 254, 155 }, { 108, 254, 156 }, { 110, 252, 157 }, { 112, 252, 158 }, { 112, 254, 159 }, + { 114, 254, 160 }, { 116, 252, 161 }, { 118, 252, 162 }, { 118, 254, 163 }, { 120, 254, 164 }, { 122, 252, 165 }, { 124, 252, 166 }, { 124, 254, 167 }, + { 126, 254, 168 }, { 128, 252, 169 }, { 130, 252, 170 }, { 130, 254, 171 }, { 132, 254, 172 }, { 134, 252, 173 }, { 136, 252, 174 }, { 136, 254, 175 }, + { 138, 254, 176 }, { 140, 252, 177 }, { 142, 252, 178 }, { 142, 254, 179 }, { 144, 254, 180 }, { 146, 252, 181 }, { 148, 252, 182 }, { 148, 254, 183 }, + { 150, 254, 184 }, { 152, 252, 185 }, { 154, 250, 186 }, { 154, 254, 187 }, { 156, 252, 188 }, { 158, 252, 189 }, { 158, 254, 190 }, { 160, 254, 191 }, + { 162, 252, 192 }, { 164, 252, 193 }, { 164, 254, 194 }, { 166, 254, 195 }, { 168, 252, 196 }, { 170, 252, 197 }, { 170, 254, 198 }, { 172, 254, 199 }, + { 174, 252, 200 }, { 176, 252, 201 }, { 176, 254, 202 }, { 178, 254, 203 }, { 180, 252, 204 }, { 182, 252, 205 }, { 182, 254, 206 }, { 184, 254, 207 }, + { 186, 252, 208 }, { 188, 252, 209 }, { 188, 254, 210 }, { 190, 254, 211 }, { 192, 252, 212 }, { 194, 252, 213 }, { 194, 254, 214 }, { 196, 254, 215 }, + { 198, 252, 216 }, { 200, 252, 217 }, { 200, 254, 218 }, { 202, 254, 219 }, { 204, 252, 220 }, { 206, 252, 221 }, { 206, 254, 222 }, { 208, 254, 223 }, + { 210, 252, 224 }, { 212, 252, 225 }, { 212, 254, 226 }, { 214, 254, 227 }, { 216, 252, 228 }, { 218, 250, 229 }, { 218, 254, 230 }, { 220, 252, 231 }, + { 222, 252, 232 }, { 222, 254, 233 }, { 224, 254, 234 }, { 226, 252, 235 }, { 228, 252, 236 }, { 228, 254, 237 }, { 230, 254, 238 }, { 232, 252, 239 }, + { 234, 252, 240 }, { 234, 254, 241 }, { 236, 254, 242 }, { 238, 252, 243 }, { 240, 252, 244 }, { 240, 254, 245 }, { 242, 254, 246 }, { 244, 252, 247 }, + { 246, 252, 248 }, { 246, 254, 249 }, { 248, 254, 250 }, { 250, 252, 251 }, { 252, 252, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode3_p1= +{ + 1, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 7, 3 }, { 1, 9, 4 }, { 1, 13, 5 }, { 1, 15, 6 }, { 1, 19, 7 }, + { 1, 21, 8 }, { 1, 25, 9 }, { 1, 27, 10 }, { 1, 31, 11 }, { 1, 33, 12 }, { 1, 37, 13 }, { 1, 41, 14 }, { 1, 43, 15 }, + { 1, 47, 16 }, { 1, 49, 17 }, { 1, 53, 18 }, { 1, 55, 19 }, { 1, 59, 20 }, { 1, 61, 21 }, { 1, 65, 22 }, { 1, 67, 23 }, + { 1, 71, 24 }, { 1, 73, 25 }, { 1, 77, 26 }, { 1, 79, 27 }, { 1, 83, 28 }, { 1, 85, 29 }, { 1, 89, 30 }, { 1, 91, 31 }, + { 1, 95, 32 }, { 1, 97, 33 }, { 1, 101, 34 }, { 1, 105, 35 }, { 1, 107, 36 }, { 1, 111, 37 }, { 1, 113, 38 }, { 1, 117, 39 }, + { 1, 119, 40 }, { 1, 123, 41 }, { 1, 125, 42 }, { 1, 129, 43 }, { 1, 131, 44 }, { 1, 135, 45 }, { 1, 137, 46 }, { 1, 141, 47 }, + { 1, 143, 48 }, { 1, 147, 49 }, { 1, 149, 50 }, { 1, 153, 51 }, { 1, 155, 52 }, { 1, 159, 53 }, { 1, 161, 54 }, { 1, 165, 55 }, + { 1, 169, 56 }, { 1, 171, 57 }, { 1, 175, 58 }, { 1, 177, 59 }, { 1, 181, 60 }, { 1, 183, 61 }, { 1, 187, 62 }, { 1, 189, 63 }, + { 1, 193, 64 }, { 1, 195, 65 }, { 1, 199, 66 }, { 1, 201, 67 }, { 1, 205, 68 }, { 1, 207, 69 }, { 1, 211, 70 }, { 1, 213, 71 }, + { 1, 217, 72 }, { 1, 219, 73 }, { 1, 223, 74 }, { 1, 225, 75 }, { 1, 229, 76 }, { 1, 233, 77 }, { 1, 235, 78 }, { 1, 239, 79 }, + { 1, 241, 80 }, { 1, 245, 81 }, { 1, 247, 82 }, { 1, 251, 83 }, { 1, 253, 84 }, { 3, 253, 85 }, { 3, 255, 86 }, { 5, 255, 87 }, + { 7, 253, 88 }, { 9, 253, 89 }, { 9, 255, 90 }, { 11, 255, 91 }, { 13, 253, 92 }, { 15, 253, 93 }, { 15, 255, 94 }, { 17, 255, 95 }, + { 19, 253, 96 }, { 21, 253, 97 }, { 21, 255, 98 }, { 23, 255, 99 }, { 25, 253, 100 }, { 27, 251, 101 }, { 27, 255, 102 }, { 29, 253, 103 }, + { 31, 253, 104 }, { 31, 255, 105 }, { 33, 255, 106 }, { 35, 253, 107 }, { 37, 253, 108 }, { 37, 255, 109 }, { 39, 255, 110 }, { 41, 253, 111 }, + { 43, 253, 112 }, { 43, 255, 113 }, { 45, 255, 114 }, { 47, 253, 115 }, { 49, 253, 116 }, { 49, 255, 117 }, { 51, 255, 118 }, { 53, 253, 119 }, + { 55, 253, 120 }, { 55, 255, 121 }, { 57, 255, 122 }, { 59, 253, 123 }, { 61, 253, 124 }, { 61, 255, 125 }, { 63, 255, 126 }, { 65, 253, 127 }, + { 67, 253, 128 }, { 67, 255, 129 }, { 69, 255, 130 }, { 71, 253, 131 }, { 73, 253, 132 }, { 73, 255, 133 }, { 75, 255, 134 }, { 77, 253, 135 }, + { 79, 253, 136 }, { 79, 255, 137 }, { 81, 255, 138 }, { 83, 253, 139 }, { 85, 253, 140 }, { 85, 255, 141 }, { 87, 255, 142 }, { 89, 253, 143 }, + { 91, 251, 144 }, { 91, 255, 145 }, { 93, 253, 146 }, { 95, 253, 147 }, { 95, 255, 148 }, { 97, 255, 149 }, { 99, 253, 150 }, { 101, 253, 151 }, + { 101, 255, 152 }, { 103, 255, 153 }, { 105, 253, 154 }, { 107, 253, 155 }, { 107, 255, 156 }, { 109, 255, 157 }, { 111, 253, 158 }, { 113, 253, 159 }, + { 113, 255, 160 }, { 115, 255, 161 }, { 117, 253, 162 }, { 119, 253, 163 }, { 119, 255, 164 }, { 121, 255, 165 }, { 123, 253, 166 }, { 125, 253, 167 }, + { 125, 255, 168 }, { 127, 255, 169 }, { 129, 253, 170 }, { 131, 253, 171 }, { 131, 255, 172 }, { 133, 255, 173 }, { 135, 253, 174 }, { 137, 253, 175 }, + { 137, 255, 176 }, { 139, 255, 177 }, { 141, 253, 178 }, { 143, 253, 179 }, { 143, 255, 180 }, { 145, 255, 181 }, { 147, 253, 182 }, { 149, 253, 183 }, + { 149, 255, 184 }, { 151, 255, 185 }, { 153, 253, 186 }, { 155, 251, 187 }, { 155, 255, 188 }, { 157, 253, 189 }, { 159, 253, 190 }, { 159, 255, 191 }, + { 161, 255, 192 }, { 163, 253, 193 }, { 165, 253, 194 }, { 165, 255, 195 }, { 167, 255, 196 }, { 169, 253, 197 }, { 171, 253, 198 }, { 171, 255, 199 }, + { 173, 255, 200 }, { 175, 253, 201 }, { 177, 253, 202 }, { 177, 255, 203 }, { 179, 255, 204 }, { 181, 253, 205 }, { 183, 253, 206 }, { 183, 255, 207 }, + { 185, 255, 208 }, { 187, 253, 209 }, { 189, 253, 210 }, { 189, 255, 211 }, { 191, 255, 212 }, { 193, 253, 213 }, { 195, 253, 214 }, { 195, 255, 215 }, + { 197, 255, 216 }, { 199, 253, 217 }, { 201, 253, 218 }, { 201, 255, 219 }, { 203, 255, 220 }, { 205, 253, 221 }, { 207, 253, 222 }, { 207, 255, 223 }, + { 209, 255, 224 }, { 211, 253, 225 }, { 213, 253, 226 }, { 213, 255, 227 }, { 215, 255, 228 }, { 217, 253, 229 }, { 219, 251, 230 }, { 219, 255, 231 }, + { 221, 253, 232 }, { 223, 253, 233 }, { 223, 255, 234 }, { 225, 255, 235 }, { 227, 253, 236 }, { 229, 253, 237 }, { 229, 255, 238 }, { 231, 255, 239 }, + { 233, 253, 240 }, { 235, 253, 241 }, { 235, 255, 242 }, { 237, 255, 243 }, { 239, 253, 244 }, { 241, 253, 245 }, { 241, 255, 246 }, { 243, 255, 247 }, + { 245, 253, 248 }, { 247, 253, 249 }, { 247, 255, 250 }, { 249, 255, 251 }, { 251, 253, 252 }, { 253, 253, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_rgb_low= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 24, 8 }, + { 0, 24, 8 }, { 0, 24, 8 }, { 0, 33, 11 }, { 0, 33, 11 }, { 0, 33, 11 }, { 0, 41, 13 }, { 0, 41, 13 }, { 0, 49, 16 }, + { 0, 49, 16 }, { 0, 49, 16 }, { 0, 57, 19 }, { 0, 57, 19 }, { 0, 57, 19 }, { 8, 49, 21 }, { 0, 66, 22 }, { 0, 66, 22 }, + { 0, 74, 24 }, { 33, 8, 25 }, { 0, 82, 27 }, { 0, 82, 27 }, { 41, 0, 28 }, { 16, 57, 29 }, { 0, 90, 30 }, { 0, 90, 30 }, + { 0, 99, 32 }, { 33, 33, 33 }, { 0, 107, 35 }, { 0, 107, 35 }, { 33, 41, 36 }, { 0, 115, 38 }, { 0, 115, 38 }, { 0, 115, 38 }, + { 0, 123, 40 }, { 33, 57, 41 }, { 0, 132, 43 }, { 0, 132, 43 }, { 33, 66, 44 }, { 0, 140, 46 }, { 0, 140, 46 }, { 66, 8, 47 }, + { 16, 115, 48 }, { 0, 148, 49 }, { 66, 16, 50 }, { 0, 156, 51 }, { 33, 90, 52 }, { 0, 165, 54 }, { 0, 165, 54 }, { 33, 99, 55 }, + { 24, 123, 56 }, { 0, 173, 57 }, { 66, 41, 58 }, { 0, 181, 59 }, { 8, 165, 60 }, { 74, 33, 61 }, { 0, 189, 62 }, { 33, 123, 63 }, + { 0, 198, 65 }, { 0, 198, 65 }, { 66, 66, 66 }, { 8, 189, 67 }, { 0, 206, 68 }, { 66, 74, 69 }, { 0, 214, 70 }, { 33, 148, 71 }, + { 99, 16, 72 }, { 0, 222, 73 }, { 66, 90, 74 }, { 107, 8, 75 }, { 0, 231, 76 }, { 66, 99, 77 }, { 0, 239, 78 }, { 33, 173, 79 }, + { 99, 41, 80 }, { 0, 247, 81 }, { 33, 181, 82 }, { 99, 49, 83 }, { 0, 255, 84 }, { 66, 123, 85 }, { 8, 247, 86 }, { 16, 231, 87 }, + { 66, 132, 88 }, { 8, 255, 89 }, { 33, 206, 90 }, { 99, 74, 91 }, { 16, 247, 92 }, { 41, 198, 93 }, { 16, 255, 94 }, { 24, 239, 95 }, + { 66, 156, 96 }, { 24, 247, 97 }, { 33, 231, 98 }, { 99, 99, 99 }, { 24, 255, 100 }, { 33, 239, 101 }, { 99, 107, 102 }, { 33, 247, 103 }, + { 66, 181, 104 }, { 132, 49, 105 }, { 33, 255, 106 }, { 99, 123, 107 }, { 140, 41, 108 }, { 41, 247, 109 }, { 99, 132, 110 }, { 41, 255, 111 }, + { 66, 206, 112 }, { 132, 74, 113 }, { 49, 247, 114 }, { 66, 214, 115 }, { 132, 82, 116 }, { 49, 255, 117 }, { 99, 156, 118 }, { 57, 247, 119 }, + { 66, 231, 120 }, { 99, 165, 121 }, { 57, 255, 122 }, { 66, 239, 123 }, { 132, 107, 124 }, { 66, 247, 125 }, { 74, 231, 126 }, { 140, 99, 127 }, + { 66, 255, 128 }, { 99, 189, 129 }, { 165, 57, 130 }, { 74, 247, 131 }, { 132, 132, 132 }, { 74, 255, 133 }, { 82, 239, 134 }, { 132, 140, 135 }, + { 82, 247, 136 }, { 99, 214, 137 }, { 165, 82, 138 }, { 82, 255, 139 }, { 132, 156, 140 }, { 173, 74, 141 }, { 90, 247, 142 }, { 132, 165, 143 }, + { 90, 255, 144 }, { 99, 239, 145 }, { 165, 107, 146 }, { 115, 214, 147 }, { 99, 247, 148 }, { 165, 115, 149 }, { 99, 255, 150 }, { 132, 189, 151 }, + { 198, 57, 152 }, { 107, 247, 153 }, { 132, 198, 154 }, { 123, 222, 155 }, { 107, 255, 156 }, { 165, 140, 157 }, { 115, 247, 158 }, { 132, 214, 159 }, + { 173, 132, 160 }, { 115, 255, 161 }, { 132, 222, 162 }, { 198, 90, 163 }, { 123, 247, 164 }, { 165, 165, 165 }, { 123, 255, 166 }, { 132, 239, 167 }, + { 165, 173, 168 }, { 231, 41, 169 }, { 132, 247, 170 }, { 198, 115, 171 }, { 132, 255, 172 }, { 165, 189, 173 }, { 206, 107, 174 }, { 140, 247, 175 }, + { 165, 198, 176 }, { 231, 66, 177 }, { 140, 255, 178 }, { 198, 140, 179 }, { 148, 247, 180 }, { 156, 231, 181 }, { 198, 148, 182 }, { 148, 255, 183 }, + { 165, 222, 184 }, { 231, 90, 185 }, { 156, 247, 186 }, { 165, 231, 187 }, { 156, 255, 188 }, { 165, 239, 189 }, { 198, 173, 190 }, { 165, 247, 192 }, + { 165, 247, 192 }, { 206, 165, 193 }, { 181, 222, 194 }, { 165, 255, 195 }, { 231, 123, 196 }, { 173, 247, 197 }, { 198, 198, 198 }, { 231, 132, 199 }, + { 173, 255, 200 }, { 198, 206, 201 }, { 181, 247, 203 }, { 181, 247, 203 }, { 231, 148, 204 }, { 181, 255, 205 }, { 198, 222, 206 }, { 239, 140, 207 }, + { 189, 247, 208 }, { 198, 231, 209 }, { 189, 255, 211 }, { 189, 255, 211 }, { 231, 173, 212 }, { 198, 247, 214 }, { 198, 247, 214 }, { 231, 181, 215 }, + { 198, 255, 217 }, { 198, 255, 217 }, { 198, 255, 217 }, { 206, 247, 219 }, { 214, 231, 220 }, { 206, 255, 222 }, { 206, 255, 222 }, { 231, 206, 223 }, + { 214, 247, 225 }, { 214, 247, 225 }, { 239, 198, 226 }, { 214, 255, 227 }, { 222, 239, 228 }, { 222, 239, 228 }, { 222, 247, 230 }, { 231, 231, 231 }, + { 222, 255, 233 }, { 222, 255, 233 }, { 231, 239, 234 }, { 231, 239, 234 }, { 231, 247, 236 }, { 231, 247, 236 }, { 231, 255, 239 }, { 231, 255, 239 }, + { 231, 255, 239 }, { 239, 247, 242 }, { 239, 247, 242 }, { 239, 247, 242 }, { 239, 255, 244 }, { 239, 255, 244 }, { 247, 247, 247 }, { 247, 247, 247 }, + { 247, 247, 247 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 255, 247, 252 }, { 255, 247, 252 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_rgb_high_i1= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 8, 1 }, { 0, 16, 2 }, { 0, 24, 3 }, { 0, 24, 3 }, { 0, 33, 5 }, { 0, 41, 6 }, { 0, 49, 7 }, + { 0, 57, 8 }, { 0, 66, 9 }, { 0, 74, 10 }, { 0, 74, 10 }, { 0, 82, 12 }, { 0, 90, 13 }, { 0, 99, 14 }, { 0, 107, 15 }, + { 0, 115, 16 }, { 0, 123, 17 }, { 8, 82, 18 }, { 0, 132, 19 }, { 0, 140, 20 }, { 0, 148, 21 }, { 0, 156, 22 }, { 0, 165, 23 }, + { 0, 173, 24 }, { 0, 181, 25 }, { 16, 90, 26 }, { 0, 189, 27 }, { 0, 198, 28 }, { 0, 206, 29 }, { 0, 214, 30 }, { 0, 222, 31 }, + { 0, 231, 32 }, { 8, 189, 33 }, { 0, 239, 34 }, { 0, 247, 35 }, { 0, 255, 36 }, { 8, 214, 37 }, { 8, 222, 38 }, { 8, 231, 39 }, + { 8, 239, 40 }, { 24, 148, 41 }, { 8, 247, 42 }, { 8, 255, 43 }, { 16, 214, 44 }, { 16, 222, 45 }, { 16, 231, 46 }, { 16, 239, 47 }, + { 16, 247, 48 }, { 33, 148, 49 }, { 16, 255, 50 }, { 24, 214, 51 }, { 24, 222, 52 }, { 24, 231, 53 }, { 24, 239, 54 }, { 24, 247, 55 }, + { 24, 255, 56 }, { 33, 206, 57 }, { 33, 214, 58 }, { 49, 123, 59 }, { 33, 222, 60 }, { 33, 231, 61 }, { 33, 239, 62 }, { 33, 247, 63 }, + { 33, 255, 64 }, { 41, 214, 65 }, { 41, 222, 66 }, { 66, 74, 67 }, { 41, 231, 68 }, { 41, 239, 69 }, { 41, 247, 70 }, { 41, 255, 71 }, + { 49, 214, 72 }, { 49, 222, 73 }, { 57, 181, 74 }, { 49, 231, 75 }, { 49, 239, 76 }, { 49, 247, 77 }, { 49, 255, 78 }, { 57, 214, 79 }, + { 57, 222, 80 }, { 57, 231, 81 }, { 66, 181, 82 }, { 57, 239, 83 }, { 57, 247, 84 }, { 57, 255, 85 }, { 66, 206, 86 }, { 66, 214, 87 }, + { 66, 222, 88 }, { 66, 231, 89 }, { 66, 239, 90 }, { 66, 247, 91 }, { 82, 156, 92 }, { 66, 255, 93 }, { 74, 214, 94 }, { 74, 222, 95 }, + { 74, 231, 96 }, { 74, 239, 97 }, { 74, 247, 98 }, { 74, 255, 99 }, { 99, 107, 100 }, { 82, 214, 101 }, { 82, 222, 102 }, { 82, 231, 103 }, + { 82, 239, 104 }, { 82, 247, 105 }, { 82, 255, 106 }, { 90, 214, 107 }, { 99, 165, 108 }, { 90, 222, 109 }, { 90, 231, 110 }, { 90, 239, 111 }, + { 90, 247, 112 }, { 90, 255, 113 }, { 99, 206, 114 }, { 99, 214, 115 }, { 99, 222, 116 }, { 107, 181, 117 }, { 99, 231, 118 }, { 99, 239, 119 }, + { 99, 247, 120 }, { 99, 255, 121 }, { 107, 214, 122 }, { 107, 222, 123 }, { 107, 231, 124 }, { 115, 189, 125 }, { 107, 239, 126 }, { 107, 247, 127 }, + { 107, 255, 128 }, { 115, 214, 129 }, { 115, 222, 130 }, { 115, 231, 131 }, { 115, 239, 132 }, { 132, 140, 133 }, { 115, 247, 134 }, { 115, 255, 135 }, + { 123, 214, 136 }, { 123, 222, 137 }, { 123, 231, 138 }, { 123, 239, 139 }, { 123, 247, 140 }, { 132, 198, 141 }, { 123, 255, 142 }, { 148, 115, 143 }, + { 132, 214, 144 }, { 132, 222, 145 }, { 132, 231, 146 }, { 132, 239, 147 }, { 132, 247, 148 }, { 132, 255, 149 }, { 140, 214, 150 }, { 156, 123, 151 }, + { 140, 222, 152 }, { 140, 231, 153 }, { 140, 239, 154 }, { 140, 247, 155 }, { 140, 255, 156 }, { 148, 214, 157 }, { 148, 222, 158 }, { 165, 123, 159 }, + { 148, 231, 160 }, { 148, 239, 161 }, { 148, 247, 162 }, { 148, 255, 163 }, { 156, 214, 164 }, { 156, 222, 165 }, { 165, 173, 166 }, { 156, 231, 167 }, + { 156, 239, 168 }, { 156, 247, 169 }, { 156, 255, 170 }, { 165, 206, 171 }, { 165, 214, 172 }, { 165, 222, 173 }, { 165, 231, 174 }, { 165, 239, 175 }, + { 181, 148, 176 }, { 165, 247, 177 }, { 165, 255, 178 }, { 173, 214, 179 }, { 173, 222, 180 }, { 173, 231, 181 }, { 173, 239, 182 }, { 173, 247, 183 }, + { 189, 156, 184 }, { 173, 255, 185 }, { 181, 214, 186 }, { 181, 222, 187 }, { 181, 231, 188 }, { 181, 239, 189 }, { 181, 247, 190 }, { 181, 255, 191 }, + { 198, 156, 192 }, { 189, 214, 193 }, { 189, 222, 194 }, { 189, 231, 195 }, { 189, 239, 196 }, { 189, 247, 197 }, { 189, 255, 198 }, { 198, 206, 199 }, + { 198, 214, 200 }, { 198, 222, 201 }, { 206, 181, 202 }, { 198, 231, 203 }, { 198, 239, 204 }, { 198, 247, 205 }, { 198, 255, 206 }, { 206, 214, 207 }, + { 206, 222, 208 }, { 214, 181, 209 }, { 206, 231, 210 }, { 206, 239, 211 }, { 206, 247, 212 }, { 206, 255, 213 }, { 214, 214, 214 }, { 214, 222, 215 }, + { 214, 231, 216 }, { 222, 189, 217 }, { 214, 239, 218 }, { 214, 247, 219 }, { 214, 255, 220 }, { 222, 214, 221 }, { 222, 222, 222 }, { 222, 231, 223 }, + { 222, 239, 224 }, { 231, 189, 225 }, { 222, 247, 226 }, { 222, 255, 227 }, { 247, 115, 228 }, { 231, 214, 229 }, { 231, 222, 230 }, { 231, 231, 231 }, + { 231, 239, 232 }, { 231, 247, 233 }, { 231, 255, 234 }, { 239, 214, 235 }, { 255, 123, 236 }, { 239, 222, 237 }, { 239, 231, 238 }, { 239, 239, 239 }, + { 239, 247, 240 }, { 239, 255, 241 }, { 247, 214, 242 }, { 247, 222, 243 }, { 247, 222, 243 }, { 247, 231, 245 }, { 247, 239, 246 }, { 247, 247, 247 }, + { 247, 255, 248 }, { 255, 214, 249 }, { 255, 222, 250 }, { 255, 222, 250 }, { 255, 231, 252 }, { 255, 239, 253 }, { 255, 247, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_rgb_high_i2= +{ + 2, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 2 }, { 0, 8, 2 }, { 0, 16, 5 }, { 0, 16, 5 }, { 8, 0, 6 }, { 0, 24, 7 }, + { 8, 8, 8 }, { 0, 33, 9 }, { 8, 16, 10 }, { 0, 41, 12 }, { 0, 41, 12 }, { 8, 24, 13 }, { 0, 49, 14 }, { 8, 33, 15 }, + { 0, 57, 16 }, { 8, 41, 17 }, { 16, 24, 18 }, { 0, 66, 19 }, { 8, 49, 20 }, { 0, 74, 21 }, { 8, 57, 22 }, { 0, 82, 23 }, + { 8, 66, 24 }, { 0, 90, 25 }, { 33, 8, 26 }, { 8, 74, 27 }, { 0, 99, 28 }, { 8, 82, 29 }, { 0, 107, 30 }, { 8, 90, 31 }, + { 0, 115, 32 }, { 24, 57, 33 }, { 8, 99, 34 }, { 0, 123, 35 }, { 8, 107, 36 }, { 0, 132, 37 }, { 8, 115, 38 }, { 0, 140, 39 }, + { 8, 123, 40 }, { 41, 41, 41 }, { 0, 148, 42 }, { 8, 132, 43 }, { 0, 156, 44 }, { 8, 140, 45 }, { 0, 165, 46 }, { 8, 148, 47 }, + { 41, 66, 48 }, { 0, 173, 49 }, { 8, 156, 50 }, { 0, 181, 51 }, { 8, 165, 52 }, { 0, 189, 53 }, { 8, 173, 54 }, { 16, 156, 55 }, + { 0, 198, 56 }, { 8, 181, 57 }, { 0, 206, 58 }, { 8, 189, 59 }, { 0, 214, 60 }, { 8, 198, 61 }, { 0, 222, 62 }, { 33, 140, 63 }, + { 8, 206, 64 }, { 0, 231, 65 }, { 8, 214, 66 }, { 0, 239, 67 }, { 8, 222, 68 }, { 0, 247, 69 }, { 24, 189, 70 }, { 8, 231, 71 }, + { 0, 255, 72 }, { 8, 239, 73 }, { 16, 222, 74 }, { 8, 247, 75 }, { 16, 231, 76 }, { 8, 255, 77 }, { 41, 173, 78 }, { 16, 239, 79 }, + { 24, 222, 80 }, { 16, 247, 81 }, { 24, 231, 82 }, { 16, 255, 83 }, { 24, 239, 84 }, { 41, 198, 85 }, { 33, 222, 86 }, { 24, 247, 87 }, + { 49, 189, 88 }, { 24, 255, 89 }, { 41, 214, 90 }, { 33, 239, 91 }, { 41, 222, 92 }, { 33, 247, 93 }, { 41, 231, 94 }, { 33, 255, 95 }, + { 66, 173, 96 }, { 41, 239, 97 }, { 49, 222, 98 }, { 41, 247, 99 }, { 49, 231, 100 }, { 41, 255, 101 }, { 49, 239, 102 }, { 57, 222, 103 }, + { 74, 181, 104 }, { 49, 247, 105 }, { 57, 231, 106 }, { 49, 255, 107 }, { 57, 239, 108 }, { 74, 198, 109 }, { 57, 247, 110 }, { 74, 206, 111 }, + { 66, 231, 112 }, { 57, 255, 113 }, { 107, 132, 114 }, { 66, 239, 115 }, { 74, 222, 116 }, { 66, 247, 117 }, { 74, 231, 118 }, { 66, 255, 119 }, + { 74, 239, 120 }, { 82, 222, 121 }, { 99, 181, 122 }, { 74, 247, 123 }, { 82, 231, 124 }, { 74, 255, 125 }, { 82, 239, 126 }, { 90, 222, 127 }, + { 82, 247, 128 }, { 99, 206, 129 }, { 90, 231, 130 }, { 82, 255, 131 }, { 90, 239, 132 }, { 107, 198, 133 }, { 90, 247, 134 }, { 107, 206, 135 }, + { 90, 255, 136 }, { 107, 214, 137 }, { 99, 239, 138 }, { 107, 222, 139 }, { 140, 140, 140 }, { 99, 247, 141 }, { 107, 231, 142 }, { 99, 255, 143 }, + { 107, 239, 144 }, { 115, 222, 145 }, { 107, 247, 146 }, { 140, 165, 147 }, { 115, 231, 148 }, { 107, 255, 149 }, { 115, 239, 150 }, { 123, 222, 151 }, + { 115, 247, 152 }, { 123, 231, 153 }, { 115, 255, 154 }, { 132, 214, 155 }, { 123, 239, 156 }, { 132, 222, 157 }, { 123, 247, 158 }, { 140, 206, 159 }, + { 123, 255, 160 }, { 140, 214, 161 }, { 132, 239, 162 }, { 140, 222, 163 }, { 132, 247, 164 }, { 156, 189, 165 }, { 140, 231, 166 }, { 132, 255, 167 }, + { 140, 239, 168 }, { 148, 222, 169 }, { 140, 247, 170 }, { 148, 231, 171 }, { 140, 255, 172 }, { 173, 173, 173 }, { 148, 239, 174 }, { 156, 222, 175 }, + { 148, 247, 176 }, { 156, 231, 177 }, { 148, 255, 178 }, { 156, 239, 179 }, { 173, 198, 180 }, { 165, 222, 181 }, { 156, 247, 182 }, { 181, 189, 183 }, + { 156, 255, 184 }, { 173, 214, 185 }, { 165, 239, 186 }, { 173, 222, 187 }, { 165, 247, 188 }, { 173, 231, 189 }, { 165, 255, 190 }, { 198, 173, 191 }, + { 173, 239, 192 }, { 181, 222, 193 }, { 173, 247, 194 }, { 181, 231, 195 }, { 173, 255, 196 }, { 181, 239, 197 }, { 189, 222, 198 }, { 206, 181, 199 }, + { 181, 247, 200 }, { 189, 231, 201 }, { 181, 255, 202 }, { 189, 239, 203 }, { 206, 198, 204 }, { 189, 247, 205 }, { 206, 206, 206 }, { 198, 231, 207 }, + { 189, 255, 208 }, { 239, 132, 209 }, { 198, 239, 210 }, { 206, 222, 211 }, { 198, 247, 212 }, { 206, 231, 213 }, { 198, 255, 214 }, { 206, 239, 215 }, + { 214, 222, 216 }, { 231, 181, 217 }, { 206, 247, 218 }, { 214, 231, 219 }, { 206, 255, 220 }, { 214, 239, 221 }, { 222, 222, 222 }, { 214, 247, 223 }, + { 231, 206, 224 }, { 222, 231, 225 }, { 214, 255, 226 }, { 222, 239, 227 }, { 231, 222, 228 }, { 222, 247, 229 }, { 239, 206, 230 }, { 222, 255, 231 }, + { 239, 214, 232 }, { 231, 239, 233 }, { 239, 222, 234 }, { 247, 206, 235 }, { 231, 247, 236 }, { 239, 231, 237 }, { 231, 255, 238 }, { 239, 239, 239 }, + { 247, 222, 240 }, { 239, 247, 241 }, { 239, 247, 241 }, { 247, 231, 243 }, { 239, 255, 244 }, { 247, 239, 245 }, { 255, 222, 246 }, { 247, 247, 247 }, + { 255, 231, 248 }, { 247, 255, 249 }, { 247, 255, 249 }, { 255, 239, 251 }, { 255, 239, 251 }, { 255, 247, 253 }, { 255, 247, 253 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_rgb_high_i3= +{ + 3, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 8, 0, 5 }, { 0, 16, 7 }, { 0, 16, 7 }, + { 8, 8, 8 }, { 16, 0, 9 }, { 0, 24, 10 }, { 8, 16, 11 }, { 8, 16, 11 }, { 16, 8, 13 }, { 0, 33, 14 }, { 8, 24, 15 }, + { 16, 16, 16 }, { 0, 41, 17 }, { 0, 41, 17 }, { 8, 33, 19 }, { 0, 49, 21 }, { 0, 49, 21 }, { 8, 41, 22 }, { 16, 33, 23 }, + { 0, 57, 24 }, { 8, 49, 25 }, { 33, 16, 26 }, { 16, 41, 27 }, { 0, 66, 28 }, { 8, 57, 29 }, { 16, 49, 30 }, { 0, 74, 31 }, + { 8, 66, 32 }, { 16, 57, 33 }, { 41, 24, 34 }, { 0, 82, 35 }, { 8, 74, 36 }, { 16, 66, 37 }, { 0, 90, 38 }, { 8, 82, 39 }, + { 16, 74, 40 }, { 41, 41, 41 }, { 0, 99, 42 }, { 8, 90, 43 }, { 16, 82, 44 }, { 0, 107, 45 }, { 8, 99, 46 }, { 16, 90, 47 }, + { 24, 82, 48 }, { 0, 115, 49 }, { 8, 107, 50 }, { 16, 99, 51 }, { 0, 123, 52 }, { 8, 115, 53 }, { 16, 107, 54 }, { 41, 74, 55 }, + { 0, 132, 56 }, { 8, 123, 57 }, { 16, 115, 58 }, { 0, 140, 59 }, { 8, 132, 60 }, { 16, 123, 61 }, { 0, 148, 62 }, { 49, 82, 63 }, + { 8, 140, 64 }, { 16, 132, 65 }, { 0, 156, 66 }, { 8, 148, 67 }, { 16, 140, 68 }, { 41, 107, 69 }, { 0, 165, 70 }, { 33, 123, 71 }, + { 16, 148, 72 }, { 0, 173, 73 }, { 8, 165, 74 }, { 16, 156, 75 }, { 0, 181, 76 }, { 49, 115, 77 }, { 8, 173, 78 }, { 16, 165, 79 }, + { 0, 189, 80 }, { 8, 181, 81 }, { 16, 173, 82 }, { 24, 165, 83 }, { 0, 198, 84 }, { 33, 156, 85 }, { 16, 181, 86 }, { 0, 206, 87 }, + { 8, 198, 88 }, { 16, 189, 89 }, { 0, 214, 90 }, { 49, 148, 91 }, { 8, 206, 92 }, { 16, 198, 93 }, { 0, 222, 94 }, { 8, 214, 95 }, + { 16, 206, 96 }, { 0, 231, 97 }, { 8, 222, 98 }, { 33, 189, 99 }, { 16, 214, 100 }, { 0, 239, 101 }, { 8, 231, 102 }, { 16, 222, 103 }, + { 0, 247, 104 }, { 8, 239, 105 }, { 33, 206, 106 }, { 16, 231, 107 }, { 0, 255, 108 }, { 8, 247, 109 }, { 16, 239, 110 }, { 24, 231, 111 }, + { 8, 255, 112 }, { 16, 247, 113 }, { 41, 214, 114 }, { 24, 239, 115 }, { 57, 198, 116 }, { 16, 255, 117 }, { 24, 247, 118 }, { 49, 214, 119 }, + { 33, 239, 120 }, { 24, 255, 121 }, { 49, 222, 122 }, { 33, 247, 123 }, { 82, 181, 124 }, { 41, 239, 125 }, { 49, 231, 126 }, { 33, 255, 127 }, + { 41, 247, 128 }, { 49, 239, 129 }, { 57, 231, 130 }, { 41, 255, 131 }, { 66, 222, 132 }, { 49, 247, 133 }, { 57, 239, 134 }, { 107, 173, 135 }, + { 49, 255, 136 }, { 57, 247, 137 }, { 82, 214, 138 }, { 66, 239, 139 }, { 74, 231, 140 }, { 57, 255, 141 }, { 66, 247, 142 }, { 115, 181, 143 }, + { 74, 239, 144 }, { 82, 231, 145 }, { 66, 255, 146 }, { 74, 247, 147 }, { 82, 239, 148 }, { 90, 231, 149 }, { 74, 255, 150 }, { 99, 222, 151 }, + { 82, 247, 152 }, { 90, 239, 153 }, { 140, 173, 154 }, { 82, 255, 155 }, { 90, 247, 156 }, { 115, 214, 157 }, { 99, 239, 158 }, { 107, 231, 159 }, + { 90, 255, 160 }, { 99, 247, 161 }, { 148, 181, 162 }, { 107, 239, 163 }, { 115, 231, 164 }, { 99, 255, 165 }, { 107, 247, 166 }, { 115, 239, 167 }, + { 140, 206, 168 }, { 107, 255, 169 }, { 132, 222, 170 }, { 115, 247, 171 }, { 123, 239, 172 }, { 173, 173, 173 }, { 115, 255, 174 }, { 123, 247, 175 }, + { 148, 214, 176 }, { 132, 239, 177 }, { 140, 231, 178 }, { 123, 255, 179 }, { 156, 214, 180 }, { 132, 247, 181 }, { 140, 239, 182 }, { 148, 231, 183 }, + { 132, 255, 184 }, { 140, 247, 185 }, { 148, 239, 186 }, { 173, 206, 187 }, { 156, 231, 188 }, { 140, 255, 189 }, { 148, 247, 190 }, { 156, 239, 191 }, + { 181, 206, 192 }, { 148, 255, 193 }, { 156, 247, 194 }, { 181, 214, 195 }, { 165, 239, 196 }, { 173, 231, 197 }, { 156, 255, 198 }, { 206, 189, 199 }, + { 165, 247, 200 }, { 173, 239, 201 }, { 181, 231, 202 }, { 165, 255, 203 }, { 173, 247, 204 }, { 181, 239, 205 }, { 206, 206, 206 }, { 189, 231, 207 }, + { 173, 255, 208 }, { 181, 247, 209 }, { 189, 239, 210 }, { 214, 206, 211 }, { 181, 255, 212 }, { 189, 247, 213 }, { 214, 214, 214 }, { 198, 239, 215 }, + { 247, 173, 216 }, { 189, 255, 217 }, { 239, 189, 218 }, { 198, 247, 219 }, { 206, 239, 220 }, { 214, 231, 221 }, { 198, 255, 222 }, { 206, 247, 223 }, + { 231, 214, 224 }, { 214, 239, 225 }, { 222, 231, 226 }, { 206, 255, 227 }, { 214, 247, 228 }, { 222, 239, 229 }, { 247, 206, 230 }, { 214, 255, 231 }, + { 239, 222, 232 }, { 222, 247, 233 }, { 231, 239, 234 }, { 222, 255, 236 }, { 222, 255, 236 }, { 222, 255, 236 }, { 231, 247, 238 }, { 239, 239, 239 }, + { 247, 231, 240 }, { 231, 255, 241 }, { 239, 247, 242 }, { 239, 247, 242 }, { 247, 239, 244 }, { 255, 231, 245 }, { 239, 255, 246 }, { 247, 247, 247 }, + { 255, 239, 248 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 255, 247, 252 }, { 255, 247, 252 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_a_low= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 4, 1 }, { 0, 8, 3 }, { 0, 12, 4 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 20, 7 }, + { 0, 24, 8 }, { 0, 28, 9 }, { 0, 28, 9 }, { 0, 32, 11 }, { 0, 36, 12 }, { 0, 40, 13 }, { 0, 44, 14 }, { 4, 36, 15 }, + { 0, 48, 16 }, { 0, 52, 17 }, { 0, 56, 18 }, { 8, 40, 19 }, { 0, 60, 20 }, { 0, 65, 21 }, { 4, 60, 22 }, { 0, 69, 23 }, + { 0, 73, 24 }, { 0, 77, 25 }, { 12, 56, 26 }, { 0, 81, 27 }, { 0, 85, 28 }, { 0, 89, 29 }, { 16, 60, 30 }, { 0, 93, 31 }, + { 0, 97, 32 }, { 0, 101, 33 }, { 0, 105, 34 }, { 4, 97, 35 }, { 0, 109, 36 }, { 0, 113, 37 }, { 0, 117, 38 }, { 8, 101, 39 }, + { 0, 121, 40 }, { 0, 125, 41 }, { 4, 121, 42 }, { 0, 130, 43 }, { 0, 134, 44 }, { 0, 138, 45 }, { 8, 125, 46 }, { 0, 142, 47 }, + { 0, 146, 48 }, { 0, 150, 49 }, { 16, 121, 50 }, { 0, 154, 51 }, { 0, 158, 52 }, { 0, 162, 53 }, { 0, 166, 54 }, { 4, 158, 55 }, + { 0, 170, 56 }, { 0, 174, 57 }, { 0, 178, 58 }, { 8, 162, 59 }, { 0, 182, 60 }, { 0, 186, 61 }, { 0, 190, 62 }, { 12, 166, 63 }, + { 0, 195, 64 }, { 0, 199, 65 }, { 8, 186, 66 }, { 0, 203, 67 }, { 0, 207, 68 }, { 0, 211, 69 }, { 12, 190, 70 }, { 0, 215, 71 }, + { 0, 219, 72 }, { 0, 223, 73 }, { 0, 227, 74 }, { 4, 219, 75 }, { 0, 231, 76 }, { 0, 235, 77 }, { 0, 239, 78 }, { 8, 223, 79 }, + { 0, 243, 80 }, { 0, 247, 81 }, { 0, 251, 82 }, { 12, 227, 83 }, { 0, 255, 84 }, { 4, 251, 85 }, { 4, 255, 86 }, { 16, 231, 87 }, + { 8, 251, 88 }, { 8, 255, 89 }, { 12, 251, 90 }, { 20, 235, 91 }, { 12, 255, 92 }, { 16, 251, 93 }, { 16, 255, 94 }, { 24, 239, 95 }, + { 20, 251, 96 }, { 20, 255, 97 }, { 24, 251, 98 }, { 28, 243, 99 }, { 24, 255, 100 }, { 28, 251, 101 }, { 28, 255, 102 }, { 32, 247, 103 }, + { 32, 251, 104 }, { 32, 255, 105 }, { 56, 207, 106 }, { 36, 251, 107 }, { 36, 255, 108 }, { 40, 251, 109 }, { 60, 211, 110 }, { 40, 255, 111 }, + { 44, 251, 112 }, { 44, 255, 113 }, { 65, 215, 114 }, { 48, 251, 115 }, { 48, 255, 116 }, { 52, 251, 117 }, { 65, 227, 118 }, { 52, 255, 119 }, + { 56, 251, 120 }, { 56, 255, 121 }, { 65, 239, 122 }, { 60, 251, 123 }, { 60, 255, 124 }, { 65, 247, 125 }, { 65, 251, 126 }, { 65, 255, 127 }, + { 77, 231, 128 }, { 69, 251, 129 }, { 69, 255, 130 }, { 73, 251, 131 }, { 81, 235, 132 }, { 73, 255, 133 }, { 77, 251, 134 }, { 77, 255, 135 }, + { 85, 239, 136 }, { 81, 251, 137 }, { 81, 255, 138 }, { 85, 251, 139 }, { 89, 243, 140 }, { 85, 255, 141 }, { 89, 251, 142 }, { 89, 255, 143 }, + { 93, 247, 144 }, { 93, 251, 145 }, { 93, 255, 146 }, { 117, 207, 147 }, { 97, 251, 148 }, { 97, 255, 149 }, { 101, 251, 150 }, { 121, 211, 151 }, + { 101, 255, 152 }, { 105, 251, 153 }, { 105, 255, 154 }, { 125, 215, 155 }, { 109, 251, 156 }, { 109, 255, 157 }, { 113, 251, 158 }, { 130, 219, 159 }, + { 113, 255, 160 }, { 117, 251, 161 }, { 117, 255, 162 }, { 130, 231, 163 }, { 121, 251, 164 }, { 121, 255, 165 }, { 125, 251, 166 }, { 130, 243, 167 }, + { 125, 255, 168 }, { 138, 231, 169 }, { 130, 251, 170 }, { 130, 255, 171 }, { 134, 251, 172 }, { 142, 235, 173 }, { 134, 255, 174 }, { 138, 251, 175 }, + { 138, 255, 176 }, { 146, 239, 177 }, { 142, 251, 178 }, { 142, 255, 179 }, { 146, 251, 180 }, { 150, 243, 181 }, { 146, 255, 182 }, { 150, 251, 183 }, + { 150, 255, 184 }, { 154, 247, 185 }, { 154, 251, 186 }, { 154, 255, 187 }, { 178, 207, 188 }, { 158, 251, 189 }, { 158, 255, 190 }, { 162, 251, 191 }, + { 182, 211, 192 }, { 162, 255, 193 }, { 166, 251, 194 }, { 166, 255, 195 }, { 186, 215, 196 }, { 170, 251, 197 }, { 170, 255, 198 }, { 174, 251, 199 }, + { 190, 219, 200 }, { 174, 255, 201 }, { 178, 251, 202 }, { 178, 255, 203 }, { 195, 223, 204 }, { 182, 251, 205 }, { 182, 255, 206 }, { 186, 251, 207 }, + { 195, 235, 208 }, { 186, 255, 209 }, { 190, 251, 210 }, { 190, 255, 211 }, { 195, 247, 212 }, { 195, 251, 213 }, { 203, 235, 214 }, { 195, 255, 215 }, + { 199, 251, 216 }, { 199, 255, 217 }, { 207, 239, 218 }, { 203, 251, 219 }, { 203, 255, 220 }, { 207, 251, 221 }, { 211, 243, 222 }, { 207, 255, 223 }, + { 211, 251, 224 }, { 211, 255, 225 }, { 215, 247, 226 }, { 215, 251, 227 }, { 215, 255, 228 }, { 239, 207, 229 }, { 219, 251, 230 }, { 219, 255, 231 }, + { 223, 251, 232 }, { 243, 211, 233 }, { 223, 255, 234 }, { 227, 251, 235 }, { 227, 255, 236 }, { 247, 215, 237 }, { 231, 251, 238 }, { 231, 255, 239 }, + { 235, 251, 240 }, { 251, 219, 241 }, { 235, 255, 242 }, { 239, 251, 243 }, { 239, 255, 244 }, { 255, 223, 245 }, { 243, 251, 246 }, { 243, 255, 247 }, + { 247, 251, 248 }, { 247, 251, 248 }, { 247, 255, 250 }, { 251, 251, 251 }, { 251, 255, 252 }, { 251, 255, 252 }, { 255, 251, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_a_high_i1= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 12, 2 }, { 0, 20, 3 }, { 0, 28, 4 }, { 0, 32, 5 }, { 0, 40, 6 }, { 0, 48, 7 }, + { 0, 56, 8 }, { 0, 65, 9 }, { 0, 69, 10 }, { 0, 77, 11 }, { 0, 85, 12 }, { 0, 89, 13 }, { 0, 97, 14 }, { 0, 105, 15 }, + { 0, 113, 16 }, { 0, 121, 17 }, { 0, 125, 18 }, { 0, 134, 19 }, { 0, 142, 20 }, { 0, 146, 21 }, { 0, 154, 22 }, { 0, 162, 23 }, + { 0, 170, 24 }, { 0, 178, 25 }, { 0, 182, 26 }, { 0, 190, 27 }, { 0, 199, 28 }, { 0, 203, 29 }, { 0, 211, 30 }, { 0, 219, 31 }, + { 0, 227, 32 }, { 0, 235, 33 }, { 0, 239, 34 }, { 0, 247, 35 }, { 0, 255, 36 }, { 4, 239, 37 }, { 4, 243, 38 }, { 4, 251, 39 }, + { 8, 235, 40 }, { 8, 243, 41 }, { 8, 247, 42 }, { 8, 255, 43 }, { 12, 239, 44 }, { 12, 247, 45 }, { 12, 251, 46 }, { 16, 235, 47 }, + { 16, 243, 48 }, { 16, 251, 49 }, { 16, 255, 50 }, { 20, 239, 51 }, { 20, 247, 52 }, { 20, 255, 53 }, { 24, 235, 54 }, { 24, 243, 55 }, + { 24, 251, 56 }, { 28, 231, 57 }, { 28, 239, 58 }, { 28, 247, 59 }, { 28, 255, 60 }, { 32, 235, 61 }, { 32, 243, 62 }, { 32, 251, 63 }, + { 36, 235, 64 }, { 36, 239, 65 }, { 36, 247, 66 }, { 36, 255, 67 }, { 40, 239, 68 }, { 40, 243, 69 }, { 40, 251, 70 }, { 44, 235, 71 }, + { 44, 243, 72 }, { 44, 247, 73 }, { 44, 255, 74 }, { 48, 239, 75 }, { 48, 247, 76 }, { 48, 251, 77 }, { 52, 235, 78 }, { 52, 243, 79 }, + { 52, 251, 80 }, { 52, 255, 81 }, { 56, 239, 82 }, { 56, 247, 83 }, { 56, 255, 84 }, { 60, 235, 85 }, { 60, 243, 86 }, { 60, 251, 87 }, + { 65, 227, 88 }, { 65, 235, 89 }, { 65, 243, 90 }, { 65, 247, 91 }, { 65, 255, 92 }, { 69, 239, 93 }, { 69, 247, 94 }, { 69, 251, 95 }, + { 73, 235, 96 }, { 73, 243, 97 }, { 73, 251, 98 }, { 73, 255, 99 }, { 77, 239, 100 }, { 77, 247, 101 }, { 77, 255, 102 }, { 81, 235, 103 }, + { 81, 243, 104 }, { 81, 251, 105 }, { 85, 231, 106 }, { 85, 239, 107 }, { 85, 247, 108 }, { 85, 255, 109 }, { 89, 235, 110 }, { 89, 243, 111 }, + { 89, 251, 112 }, { 93, 235, 113 }, { 93, 239, 114 }, { 93, 247, 115 }, { 93, 255, 116 }, { 97, 239, 117 }, { 97, 243, 118 }, { 97, 251, 119 }, + { 101, 235, 120 }, { 101, 243, 121 }, { 101, 247, 122 }, { 101, 255, 123 }, { 105, 239, 124 }, { 105, 247, 125 }, { 105, 251, 126 }, { 109, 235, 127 }, + { 109, 243, 128 }, { 109, 251, 129 }, { 109, 255, 130 }, { 113, 239, 131 }, { 113, 247, 132 }, { 113, 255, 133 }, { 117, 235, 134 }, { 117, 243, 135 }, + { 117, 251, 136 }, { 121, 235, 137 }, { 121, 239, 138 }, { 121, 247, 139 }, { 121, 255, 140 }, { 125, 239, 141 }, { 125, 243, 142 }, { 125, 251, 143 }, + { 130, 227, 144 }, { 130, 235, 145 }, { 130, 243, 146 }, { 130, 251, 147 }, { 130, 255, 148 }, { 134, 239, 149 }, { 134, 247, 150 }, { 134, 255, 151 }, + { 138, 235, 152 }, { 138, 243, 153 }, { 138, 251, 154 }, { 142, 231, 155 }, { 142, 239, 156 }, { 142, 247, 157 }, { 142, 255, 158 }, { 146, 235, 159 }, + { 146, 243, 160 }, { 146, 251, 161 }, { 150, 235, 162 }, { 150, 239, 163 }, { 150, 247, 164 }, { 150, 255, 165 }, { 154, 239, 166 }, { 154, 243, 167 }, + { 154, 251, 168 }, { 158, 235, 169 }, { 158, 243, 170 }, { 158, 247, 171 }, { 158, 255, 172 }, { 162, 239, 173 }, { 162, 247, 174 }, { 162, 251, 175 }, + { 166, 235, 176 }, { 166, 243, 177 }, { 166, 251, 178 }, { 166, 255, 179 }, { 170, 239, 180 }, { 170, 247, 181 }, { 170, 255, 182 }, { 174, 235, 183 }, + { 174, 243, 184 }, { 174, 251, 185 }, { 178, 235, 186 }, { 178, 239, 187 }, { 178, 247, 188 }, { 178, 255, 189 }, { 182, 239, 190 }, { 182, 243, 191 }, + { 182, 251, 192 }, { 186, 235, 193 }, { 186, 243, 194 }, { 186, 247, 195 }, { 186, 255, 196 }, { 190, 239, 197 }, { 190, 247, 198 }, { 190, 251, 199 }, + { 195, 227, 200 }, { 195, 235, 201 }, { 195, 243, 202 }, { 195, 251, 203 }, { 199, 231, 204 }, { 199, 239, 205 }, { 199, 247, 206 }, { 199, 255, 207 }, + { 203, 235, 208 }, { 203, 243, 209 }, { 203, 251, 210 }, { 207, 235, 211 }, { 207, 239, 212 }, { 207, 247, 213 }, { 207, 255, 214 }, { 211, 239, 215 }, + { 211, 243, 216 }, { 211, 251, 217 }, { 215, 235, 218 }, { 215, 243, 219 }, { 215, 247, 220 }, { 215, 255, 221 }, { 219, 239, 222 }, { 219, 247, 223 }, + { 219, 251, 224 }, { 223, 235, 225 }, { 223, 243, 226 }, { 223, 251, 227 }, { 223, 255, 228 }, { 227, 239, 229 }, { 227, 247, 230 }, { 227, 255, 231 }, + { 231, 235, 232 }, { 231, 243, 233 }, { 231, 251, 234 }, { 235, 235, 235 }, { 235, 239, 236 }, { 235, 247, 237 }, { 235, 255, 238 }, { 239, 239, 239 }, + { 239, 243, 240 }, { 239, 251, 241 }, { 243, 235, 242 }, { 243, 243, 243 }, { 243, 247, 244 }, { 243, 255, 245 }, { 247, 239, 246 }, { 247, 247, 247 }, + { 247, 251, 248 }, { 251, 235, 249 }, { 251, 243, 250 }, { 251, 251, 251 }, { 251, 255, 252 }, { 255, 239, 253 }, { 255, 247, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_a_high_i2= +{ + 2, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 8, 2 }, { 0, 12, 3 }, { 4, 4, 4 }, { 0, 16, 5 }, { 0, 20, 6 }, { 0, 24, 7 }, + { 0, 28, 8 }, { 0, 32, 9 }, { 0, 36, 10 }, { 0, 40, 11 }, { 0, 44, 12 }, { 4, 36, 13 }, { 0, 48, 14 }, { 0, 52, 15 }, + { 0, 56, 16 }, { 0, 60, 17 }, { 0, 65, 18 }, { 0, 69, 19 }, { 4, 60, 20 }, { 0, 73, 21 }, { 0, 77, 22 }, { 0, 81, 23 }, + { 0, 85, 24 }, { 0, 89, 25 }, { 0, 93, 26 }, { 0, 97, 27 }, { 0, 101, 28 }, { 4, 93, 29 }, { 0, 105, 30 }, { 0, 109, 31 }, + { 0, 113, 32 }, { 0, 117, 33 }, { 0, 121, 34 }, { 0, 125, 35 }, { 4, 117, 36 }, { 0, 130, 37 }, { 0, 134, 38 }, { 0, 138, 39 }, + { 0, 142, 40 }, { 0, 146, 41 }, { 0, 150, 42 }, { 0, 154, 43 }, { 0, 158, 44 }, { 4, 150, 45 }, { 0, 162, 46 }, { 0, 166, 47 }, + { 0, 170, 48 }, { 0, 174, 49 }, { 0, 178, 50 }, { 0, 182, 51 }, { 0, 186, 52 }, { 0, 190, 53 }, { 4, 182, 54 }, { 0, 195, 55 }, + { 0, 199, 56 }, { 0, 203, 57 }, { 0, 207, 58 }, { 0, 211, 59 }, { 0, 215, 60 }, { 4, 207, 61 }, { 0, 219, 62 }, { 0, 223, 63 }, + { 0, 227, 64 }, { 0, 231, 65 }, { 0, 235, 66 }, { 0, 239, 67 }, { 0, 243, 68 }, { 0, 247, 69 }, { 4, 239, 70 }, { 0, 251, 71 }, + { 0, 255, 72 }, { 4, 251, 73 }, { 8, 243, 74 }, { 4, 255, 75 }, { 8, 251, 76 }, { 8, 255, 77 }, { 12, 247, 78 }, { 12, 251, 79 }, + { 12, 255, 80 }, { 16, 247, 81 }, { 16, 251, 82 }, { 16, 255, 83 }, { 20, 247, 84 }, { 20, 251, 85 }, { 20, 255, 86 }, { 24, 247, 87 }, + { 24, 251, 88 }, { 24, 255, 89 }, { 28, 247, 90 }, { 28, 251, 91 }, { 28, 255, 92 }, { 36, 239, 93 }, { 32, 251, 94 }, { 32, 255, 95 }, + { 36, 251, 96 }, { 40, 243, 97 }, { 36, 255, 98 }, { 40, 251, 99 }, { 40, 255, 100 }, { 44, 247, 101 }, { 44, 251, 102 }, { 44, 255, 103 }, + { 48, 247, 104 }, { 48, 251, 105 }, { 48, 255, 106 }, { 52, 247, 107 }, { 52, 251, 108 }, { 52, 255, 109 }, { 56, 247, 110 }, { 56, 251, 111 }, + { 56, 255, 112 }, { 60, 247, 113 }, { 60, 251, 114 }, { 60, 255, 115 }, { 65, 247, 116 }, { 65, 251, 117 }, { 65, 255, 118 }, { 69, 247, 119 }, + { 69, 251, 120 }, { 69, 255, 121 }, { 73, 247, 122 }, { 73, 251, 123 }, { 73, 255, 124 }, { 77, 247, 125 }, { 77, 251, 126 }, { 77, 255, 127 }, + { 81, 247, 128 }, { 81, 251, 129 }, { 81, 255, 130 }, { 85, 247, 131 }, { 85, 251, 132 }, { 85, 255, 133 }, { 93, 239, 134 }, { 89, 251, 135 }, + { 89, 255, 136 }, { 93, 251, 137 }, { 97, 243, 138 }, { 93, 255, 139 }, { 97, 251, 140 }, { 97, 255, 141 }, { 101, 247, 142 }, { 101, 251, 143 }, + { 101, 255, 144 }, { 105, 247, 145 }, { 105, 251, 146 }, { 105, 255, 147 }, { 109, 247, 148 }, { 109, 251, 149 }, { 109, 255, 150 }, { 113, 247, 151 }, + { 113, 251, 152 }, { 113, 255, 153 }, { 117, 247, 154 }, { 117, 251, 155 }, { 117, 255, 156 }, { 125, 239, 157 }, { 121, 251, 158 }, { 121, 255, 159 }, + { 125, 251, 160 }, { 130, 239, 161 }, { 125, 255, 162 }, { 130, 247, 163 }, { 130, 251, 164 }, { 130, 255, 165 }, { 134, 247, 166 }, { 134, 251, 167 }, + { 134, 255, 168 }, { 138, 247, 169 }, { 138, 251, 170 }, { 138, 255, 171 }, { 142, 247, 172 }, { 142, 251, 173 }, { 142, 255, 174 }, { 150, 239, 175 }, + { 146, 251, 176 }, { 146, 255, 177 }, { 150, 251, 178 }, { 154, 243, 179 }, { 150, 255, 180 }, { 154, 251, 181 }, { 154, 255, 182 }, { 158, 247, 183 }, + { 158, 251, 184 }, { 158, 255, 185 }, { 162, 247, 186 }, { 162, 251, 187 }, { 162, 255, 188 }, { 166, 247, 189 }, { 166, 251, 190 }, { 166, 255, 191 }, + { 170, 247, 192 }, { 170, 251, 193 }, { 170, 255, 194 }, { 174, 247, 195 }, { 174, 251, 196 }, { 174, 255, 197 }, { 182, 239, 198 }, { 178, 251, 199 }, + { 178, 255, 200 }, { 182, 251, 201 }, { 186, 243, 202 }, { 182, 255, 203 }, { 186, 251, 204 }, { 186, 255, 205 }, { 190, 247, 206 }, { 190, 251, 207 }, + { 190, 255, 208 }, { 195, 243, 209 }, { 195, 247, 210 }, { 195, 251, 211 }, { 195, 255, 212 }, { 199, 247, 213 }, { 199, 251, 214 }, { 199, 255, 215 }, + { 207, 239, 216 }, { 203, 251, 217 }, { 203, 255, 218 }, { 207, 251, 219 }, { 211, 243, 220 }, { 207, 255, 221 }, { 211, 251, 222 }, { 211, 255, 223 }, + { 215, 247, 224 }, { 215, 251, 225 }, { 215, 255, 226 }, { 219, 247, 227 }, { 219, 251, 228 }, { 219, 255, 229 }, { 223, 247, 230 }, { 223, 251, 231 }, + { 223, 255, 232 }, { 227, 247, 233 }, { 227, 251, 234 }, { 227, 255, 235 }, { 231, 247, 236 }, { 231, 251, 237 }, { 231, 255, 238 }, { 239, 239, 239 }, + { 235, 251, 240 }, { 235, 255, 241 }, { 239, 251, 242 }, { 243, 243, 243 }, { 239, 255, 244 }, { 243, 251, 245 }, { 243, 255, 246 }, { 247, 247, 247 }, + { 247, 251, 248 }, { 247, 255, 249 }, { 251, 247, 250 }, { 251, 251, 251 }, { 251, 255, 252 }, { 255, 247, 253 }, { 255, 251, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_a_high_i3= +{ + 3, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 4, 2 }, { 0, 8, 3 }, { 4, 4, 4 }, { 0, 12, 5 }, { 4, 8, 6 }, { 0, 16, 7 }, + { 0, 20, 8 }, { 4, 16, 9 }, { 0, 24, 10 }, { 4, 20, 11 }, { 0, 28, 12 }, { 8, 20, 13 }, { 0, 32, 14 }, { 0, 36, 15 }, + { 4, 32, 16 }, { 0, 40, 17 }, { 4, 36, 18 }, { 0, 44, 19 }, { 0, 48, 20 }, { 4, 44, 21 }, { 0, 52, 22 }, { 4, 48, 23 }, + { 0, 56, 24 }, { 0, 60, 25 }, { 4, 56, 26 }, { 0, 65, 27 }, { 4, 60, 28 }, { 0, 69, 29 }, { 4, 65, 30 }, { 0, 73, 31 }, + { 0, 77, 32 }, { 4, 73, 33 }, { 0, 81, 34 }, { 4, 77, 35 }, { 0, 85, 36 }, { 8, 77, 37 }, { 0, 89, 38 }, { 0, 93, 39 }, + { 4, 89, 40 }, { 0, 97, 41 }, { 4, 93, 42 }, { 0, 101, 43 }, { 0, 105, 44 }, { 4, 101, 45 }, { 0, 109, 46 }, { 4, 105, 47 }, + { 0, 113, 48 }, { 0, 117, 49 }, { 4, 113, 50 }, { 0, 121, 51 }, { 4, 117, 52 }, { 0, 125, 53 }, { 8, 117, 54 }, { 0, 130, 55 }, + { 8, 121, 56 }, { 0, 134, 57 }, { 0, 138, 58 }, { 4, 134, 59 }, { 0, 142, 60 }, { 4, 138, 61 }, { 0, 146, 62 }, { 0, 150, 63 }, + { 4, 146, 64 }, { 0, 154, 65 }, { 4, 150, 66 }, { 0, 158, 67 }, { 0, 162, 68 }, { 4, 158, 69 }, { 0, 166, 70 }, { 4, 162, 71 }, + { 0, 170, 72 }, { 0, 174, 73 }, { 4, 170, 74 }, { 0, 178, 75 }, { 4, 174, 76 }, { 0, 182, 77 }, { 0, 186, 78 }, { 4, 182, 79 }, + { 0, 190, 80 }, { 4, 186, 81 }, { 0, 195, 82 }, { 8, 186, 83 }, { 0, 199, 84 }, { 4, 195, 85 }, { 0, 203, 86 }, { 0, 207, 87 }, + { 4, 203, 88 }, { 0, 211, 89 }, { 4, 207, 90 }, { 0, 215, 91 }, { 0, 219, 92 }, { 4, 215, 93 }, { 0, 223, 94 }, { 4, 219, 95 }, + { 0, 227, 96 }, { 0, 231, 97 }, { 4, 227, 98 }, { 0, 235, 99 }, { 4, 231, 100 }, { 0, 239, 101 }, { 8, 231, 102 }, { 0, 243, 103 }, + { 0, 247, 104 }, { 4, 243, 105 }, { 0, 251, 106 }, { 4, 247, 107 }, { 0, 255, 108 }, { 8, 247, 109 }, { 4, 255, 110 }, { 8, 251, 111 }, + { 8, 255, 112 }, { 12, 251, 113 }, { 20, 243, 114 }, { 12, 255, 115 }, { 20, 247, 116 }, { 16, 255, 117 }, { 24, 247, 118 }, { 20, 255, 119 }, + { 24, 251, 120 }, { 24, 255, 121 }, { 28, 251, 122 }, { 32, 247, 123 }, { 28, 255, 124 }, { 36, 247, 125 }, { 32, 255, 126 }, { 36, 251, 127 }, + { 36, 255, 128 }, { 40, 251, 129 }, { 44, 247, 130 }, { 40, 255, 131 }, { 48, 247, 132 }, { 44, 255, 133 }, { 48, 251, 134 }, { 48, 255, 135 }, + { 52, 251, 136 }, { 56, 247, 137 }, { 52, 255, 138 }, { 60, 247, 139 }, { 56, 255, 140 }, { 60, 251, 141 }, { 60, 255, 142 }, { 65, 251, 143 }, + { 69, 247, 144 }, { 65, 255, 145 }, { 69, 251, 146 }, { 69, 255, 147 }, { 73, 251, 148 }, { 77, 247, 149 }, { 73, 255, 150 }, { 81, 247, 151 }, + { 77, 255, 152 }, { 81, 251, 153 }, { 81, 255, 154 }, { 85, 251, 155 }, { 89, 247, 156 }, { 85, 255, 157 }, { 93, 247, 158 }, { 89, 255, 159 }, + { 93, 251, 160 }, { 93, 255, 161 }, { 97, 251, 162 }, { 101, 247, 163 }, { 97, 255, 164 }, { 105, 247, 165 }, { 101, 255, 166 }, { 105, 251, 167 }, + { 105, 255, 168 }, { 109, 251, 169 }, { 113, 247, 170 }, { 109, 255, 171 }, { 117, 247, 172 }, { 113, 255, 173 }, { 117, 251, 174 }, { 117, 255, 175 }, + { 121, 251, 176 }, { 134, 235, 177 }, { 121, 255, 178 }, { 130, 247, 179 }, { 125, 255, 180 }, { 130, 251, 181 }, { 134, 247, 182 }, { 130, 255, 183 }, + { 138, 247, 184 }, { 134, 255, 185 }, { 138, 251, 186 }, { 138, 255, 187 }, { 142, 251, 188 }, { 146, 247, 189 }, { 142, 255, 190 }, { 150, 247, 191 }, + { 146, 255, 192 }, { 150, 251, 193 }, { 150, 255, 194 }, { 154, 251, 195 }, { 158, 247, 196 }, { 154, 255, 197 }, { 162, 247, 198 }, { 158, 255, 199 }, + { 162, 251, 200 }, { 162, 255, 201 }, { 166, 251, 202 }, { 174, 243, 203 }, { 166, 255, 204 }, { 174, 247, 205 }, { 170, 255, 206 }, { 178, 247, 207 }, + { 174, 255, 208 }, { 178, 251, 209 }, { 178, 255, 210 }, { 182, 251, 211 }, { 186, 247, 212 }, { 182, 255, 213 }, { 190, 247, 214 }, { 186, 255, 215 }, + { 190, 251, 216 }, { 190, 255, 217 }, { 199, 243, 218 }, { 195, 251, 219 }, { 195, 255, 220 }, { 199, 251, 221 }, { 203, 247, 222 }, { 199, 255, 223 }, + { 207, 247, 224 }, { 203, 255, 225 }, { 207, 251, 226 }, { 207, 255, 227 }, { 211, 251, 228 }, { 215, 247, 229 }, { 211, 255, 230 }, { 219, 247, 231 }, + { 215, 255, 232 }, { 219, 251, 233 }, { 219, 255, 234 }, { 223, 251, 235 }, { 231, 243, 236 }, { 223, 255, 237 }, { 231, 247, 238 }, { 227, 255, 239 }, + { 235, 247, 240 }, { 231, 255, 241 }, { 235, 251, 242 }, { 235, 255, 243 }, { 239, 251, 244 }, { 243, 247, 245 }, { 239, 255, 246 }, { 247, 247, 247 }, + { 243, 255, 248 }, { 247, 251, 249 }, { 247, 255, 250 }, { 251, 251, 251 }, { 255, 247, 252 }, { 251, 255, 253 }, { 251, 255, 253 }, { 255, 255, 255 }, + } +}; + +Table g_mode5_rgb_low= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 6, 2 }, { 0, 8, 3 }, { 0, 12, 4 }, { 0, 14, 5 }, { 0, 18, 6 }, { 0, 20, 7 }, + { 0, 24, 8 }, { 0, 26, 9 }, { 0, 30, 10 }, { 0, 32, 11 }, { 0, 36, 12 }, { 0, 40, 13 }, { 0, 42, 14 }, { 0, 46, 15 }, + { 0, 48, 16 }, { 0, 52, 17 }, { 0, 54, 18 }, { 0, 58, 19 }, { 0, 60, 20 }, { 0, 64, 21 }, { 0, 66, 22 }, { 0, 70, 23 }, + { 0, 72, 24 }, { 0, 76, 25 }, { 0, 78, 26 }, { 0, 82, 27 }, { 0, 84, 28 }, { 0, 88, 29 }, { 0, 90, 30 }, { 0, 94, 31 }, + { 0, 96, 32 }, { 0, 100, 33 }, { 0, 104, 34 }, { 0, 106, 35 }, { 0, 110, 36 }, { 0, 112, 37 }, { 0, 116, 38 }, { 0, 118, 39 }, + { 0, 122, 40 }, { 0, 124, 41 }, { 0, 129, 42 }, { 0, 131, 43 }, { 0, 133, 44 }, { 0, 137, 45 }, { 0, 139, 46 }, { 0, 143, 47 }, + { 0, 145, 48 }, { 0, 149, 49 }, { 0, 151, 50 }, { 0, 155, 51 }, { 0, 157, 52 }, { 0, 161, 53 }, { 0, 165, 54 }, { 0, 167, 55 }, + { 0, 171, 56 }, { 0, 173, 57 }, { 0, 177, 58 }, { 0, 179, 59 }, { 0, 183, 60 }, { 0, 185, 61 }, { 0, 189, 62 }, { 0, 191, 63 }, + { 0, 195, 64 }, { 0, 197, 65 }, { 0, 201, 66 }, { 0, 203, 67 }, { 0, 207, 68 }, { 0, 209, 69 }, { 0, 213, 70 }, { 0, 215, 71 }, + { 0, 219, 72 }, { 0, 221, 73 }, { 0, 225, 74 }, { 0, 229, 75 }, { 0, 231, 76 }, { 0, 235, 77 }, { 0, 237, 78 }, { 0, 241, 79 }, + { 0, 243, 80 }, { 0, 247, 81 }, { 0, 249, 82 }, { 0, 253, 83 }, { 0, 255, 84 }, { 2, 255, 85 }, { 4, 253, 86 }, { 6, 253, 87 }, + { 6, 255, 88 }, { 8, 255, 89 }, { 10, 253, 90 }, { 12, 253, 91 }, { 12, 255, 92 }, { 14, 255, 93 }, { 16, 253, 94 }, { 18, 253, 95 }, + { 18, 255, 96 }, { 20, 255, 97 }, { 22, 253, 98 }, { 24, 253, 99 }, { 24, 255, 100 }, { 26, 255, 101 }, { 28, 253, 102 }, { 30, 251, 103 }, + { 30, 255, 104 }, { 32, 253, 105 }, { 34, 253, 106 }, { 34, 255, 107 }, { 36, 255, 108 }, { 38, 253, 109 }, { 40, 253, 110 }, { 40, 255, 111 }, + { 42, 255, 112 }, { 44, 253, 113 }, { 46, 253, 114 }, { 46, 255, 115 }, { 48, 255, 116 }, { 50, 253, 117 }, { 52, 253, 118 }, { 52, 255, 119 }, + { 54, 255, 120 }, { 56, 253, 121 }, { 58, 253, 122 }, { 58, 255, 123 }, { 60, 255, 124 }, { 62, 253, 125 }, { 64, 253, 126 }, { 64, 255, 127 }, + { 66, 255, 128 }, { 68, 253, 129 }, { 70, 253, 130 }, { 70, 255, 131 }, { 72, 255, 132 }, { 74, 253, 133 }, { 76, 253, 134 }, { 76, 255, 135 }, + { 78, 255, 136 }, { 80, 253, 137 }, { 82, 253, 138 }, { 82, 255, 139 }, { 84, 255, 140 }, { 86, 253, 141 }, { 88, 253, 142 }, { 88, 255, 143 }, + { 90, 255, 144 }, { 92, 253, 145 }, { 94, 251, 146 }, { 94, 255, 147 }, { 96, 253, 148 }, { 98, 253, 149 }, { 98, 255, 150 }, { 100, 255, 151 }, + { 102, 253, 152 }, { 104, 253, 153 }, { 104, 255, 154 }, { 106, 255, 155 }, { 108, 253, 156 }, { 110, 253, 157 }, { 110, 255, 158 }, { 112, 255, 159 }, + { 114, 253, 160 }, { 116, 253, 161 }, { 116, 255, 162 }, { 118, 255, 163 }, { 120, 253, 164 }, { 122, 253, 165 }, { 122, 255, 166 }, { 124, 255, 167 }, + { 126, 253, 168 }, { 129, 251, 169 }, { 129, 253, 170 }, { 131, 253, 171 }, { 131, 255, 172 }, { 133, 255, 173 }, { 135, 253, 174 }, { 137, 253, 175 }, + { 137, 255, 176 }, { 139, 255, 177 }, { 141, 253, 178 }, { 143, 253, 179 }, { 143, 255, 180 }, { 145, 255, 181 }, { 147, 253, 182 }, { 149, 253, 183 }, + { 149, 255, 184 }, { 151, 255, 185 }, { 153, 253, 186 }, { 155, 251, 187 }, { 155, 255, 188 }, { 157, 253, 189 }, { 159, 253, 190 }, { 159, 255, 191 }, + { 161, 255, 192 }, { 163, 253, 193 }, { 165, 253, 194 }, { 165, 255, 195 }, { 167, 255, 196 }, { 169, 253, 197 }, { 171, 253, 198 }, { 171, 255, 199 }, + { 173, 255, 200 }, { 175, 253, 201 }, { 177, 253, 202 }, { 177, 255, 203 }, { 179, 255, 204 }, { 181, 253, 205 }, { 183, 253, 206 }, { 183, 255, 207 }, + { 185, 255, 208 }, { 187, 253, 209 }, { 189, 253, 210 }, { 189, 255, 211 }, { 191, 255, 212 }, { 193, 253, 213 }, { 195, 253, 214 }, { 195, 255, 215 }, + { 197, 255, 216 }, { 199, 253, 217 }, { 201, 253, 218 }, { 201, 255, 219 }, { 203, 255, 220 }, { 205, 253, 221 }, { 207, 253, 222 }, { 207, 255, 223 }, + { 209, 255, 224 }, { 211, 253, 225 }, { 213, 253, 226 }, { 213, 255, 227 }, { 215, 255, 228 }, { 217, 253, 229 }, { 219, 251, 230 }, { 219, 255, 231 }, + { 221, 253, 232 }, { 223, 253, 233 }, { 223, 255, 234 }, { 225, 255, 235 }, { 227, 253, 236 }, { 229, 253, 237 }, { 229, 255, 238 }, { 231, 255, 239 }, + { 233, 253, 240 }, { 235, 253, 241 }, { 235, 255, 242 }, { 237, 255, 243 }, { 239, 253, 244 }, { 241, 253, 245 }, { 241, 255, 246 }, { 243, 255, 247 }, + { 245, 253, 248 }, { 247, 253, 249 }, { 247, 255, 250 }, { 249, 255, 251 }, { 251, 253, 252 }, { 253, 253, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode6_p0_i1= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 8, 1 }, { 0, 24, 2 }, { 0, 40, 3 }, { 0, 56, 4 }, { 0, 72, 5 }, { 0, 88, 6 }, { 0, 104, 7 }, + { 0, 120, 8 }, { 0, 136, 9 }, { 0, 152, 10 }, { 0, 168, 11 }, { 0, 184, 12 }, { 0, 200, 13 }, { 0, 216, 14 }, { 0, 232, 15 }, + { 0, 248, 16 }, { 2, 234, 17 }, { 2, 250, 18 }, { 4, 236, 19 }, { 4, 252, 20 }, { 6, 238, 21 }, { 6, 254, 22 }, { 8, 240, 23 }, + { 10, 226, 24 }, { 10, 242, 25 }, { 12, 228, 26 }, { 12, 244, 27 }, { 14, 230, 28 }, { 14, 246, 29 }, { 16, 232, 30 }, { 16, 248, 31 }, + { 18, 234, 32 }, { 18, 250, 33 }, { 20, 236, 34 }, { 20, 252, 35 }, { 22, 238, 36 }, { 22, 254, 37 }, { 24, 240, 38 }, { 26, 226, 39 }, + { 26, 242, 40 }, { 28, 228, 41 }, { 28, 244, 42 }, { 30, 230, 43 }, { 30, 246, 44 }, { 32, 232, 45 }, { 32, 248, 46 }, { 34, 234, 47 }, + { 34, 250, 48 }, { 36, 236, 49 }, { 36, 252, 50 }, { 38, 238, 51 }, { 38, 254, 52 }, { 40, 240, 53 }, { 42, 226, 54 }, { 42, 242, 55 }, + { 44, 228, 56 }, { 44, 244, 57 }, { 46, 230, 58 }, { 46, 246, 59 }, { 48, 232, 60 }, { 48, 248, 61 }, { 50, 234, 62 }, { 50, 250, 63 }, + { 52, 236, 64 }, { 52, 252, 65 }, { 54, 238, 66 }, { 54, 254, 67 }, { 56, 240, 68 }, { 58, 226, 69 }, { 58, 242, 70 }, { 60, 228, 71 }, + { 60, 244, 72 }, { 62, 230, 73 }, { 62, 246, 74 }, { 64, 232, 75 }, { 64, 248, 76 }, { 66, 234, 77 }, { 66, 250, 78 }, { 68, 236, 79 }, + { 68, 252, 80 }, { 70, 238, 81 }, { 70, 254, 82 }, { 72, 240, 83 }, { 74, 226, 84 }, { 74, 242, 85 }, { 76, 228, 86 }, { 76, 244, 87 }, + { 78, 230, 88 }, { 78, 246, 89 }, { 80, 232, 90 }, { 80, 248, 91 }, { 82, 234, 92 }, { 82, 250, 93 }, { 84, 236, 94 }, { 84, 252, 95 }, + { 86, 238, 96 }, { 86, 254, 97 }, { 88, 240, 98 }, { 90, 226, 99 }, { 90, 242, 100 }, { 92, 228, 101 }, { 92, 244, 102 }, { 94, 230, 103 }, + { 94, 246, 104 }, { 96, 232, 105 }, { 96, 248, 106 }, { 98, 234, 107 }, { 98, 250, 108 }, { 100, 236, 109 }, { 100, 252, 110 }, { 102, 238, 111 }, + { 102, 254, 112 }, { 104, 240, 113 }, { 106, 226, 114 }, { 106, 242, 115 }, { 108, 228, 116 }, { 108, 244, 117 }, { 110, 230, 118 }, { 110, 246, 119 }, + { 112, 232, 120 }, { 112, 248, 121 }, { 114, 234, 122 }, { 114, 250, 123 }, { 116, 236, 124 }, { 116, 252, 125 }, { 118, 238, 126 }, { 118, 254, 127 }, + { 120, 240, 128 }, { 122, 226, 129 }, { 122, 242, 130 }, { 124, 228, 131 }, { 124, 244, 132 }, { 126, 230, 133 }, { 126, 246, 134 }, { 128, 232, 135 }, + { 128, 248, 136 }, { 130, 234, 137 }, { 130, 250, 138 }, { 132, 236, 139 }, { 132, 252, 140 }, { 134, 238, 141 }, { 134, 254, 142 }, { 136, 240, 143 }, + { 138, 226, 144 }, { 138, 242, 145 }, { 140, 228, 146 }, { 140, 244, 147 }, { 142, 230, 148 }, { 142, 246, 149 }, { 144, 232, 150 }, { 144, 248, 151 }, + { 146, 234, 152 }, { 146, 250, 153 }, { 148, 236, 154 }, { 148, 252, 155 }, { 150, 238, 156 }, { 150, 254, 157 }, { 152, 240, 158 }, { 154, 226, 159 }, + { 154, 242, 160 }, { 156, 228, 161 }, { 156, 244, 162 }, { 158, 230, 163 }, { 158, 246, 164 }, { 160, 232, 165 }, { 160, 248, 166 }, { 162, 234, 167 }, + { 162, 250, 168 }, { 164, 236, 169 }, { 164, 252, 170 }, { 166, 238, 171 }, { 166, 254, 172 }, { 168, 240, 173 }, { 170, 226, 174 }, { 170, 242, 175 }, + { 172, 228, 176 }, { 172, 244, 177 }, { 174, 230, 178 }, { 174, 246, 179 }, { 176, 232, 180 }, { 176, 248, 181 }, { 178, 234, 182 }, { 178, 250, 183 }, + { 180, 236, 184 }, { 180, 252, 185 }, { 182, 238, 186 }, { 182, 254, 187 }, { 184, 240, 188 }, { 186, 226, 189 }, { 186, 242, 190 }, { 188, 228, 191 }, + { 188, 244, 192 }, { 190, 230, 193 }, { 190, 246, 194 }, { 192, 232, 195 }, { 192, 248, 196 }, { 194, 234, 197 }, { 194, 250, 198 }, { 196, 236, 199 }, + { 196, 252, 200 }, { 198, 238, 201 }, { 198, 254, 202 }, { 200, 240, 203 }, { 202, 226, 204 }, { 202, 242, 205 }, { 204, 228, 206 }, { 204, 244, 207 }, + { 206, 230, 208 }, { 206, 246, 209 }, { 208, 232, 210 }, { 208, 248, 211 }, { 210, 234, 212 }, { 210, 250, 213 }, { 212, 236, 214 }, { 212, 252, 215 }, + { 214, 238, 216 }, { 214, 254, 217 }, { 216, 240, 218 }, { 218, 226, 219 }, { 218, 242, 220 }, { 220, 228, 221 }, { 220, 244, 222 }, { 222, 230, 223 }, + { 222, 246, 224 }, { 224, 232, 225 }, { 224, 248, 226 }, { 226, 234, 227 }, { 226, 250, 228 }, { 228, 236, 229 }, { 228, 252, 230 }, { 230, 238, 231 }, + { 230, 254, 232 }, { 232, 240, 233 }, { 234, 226, 234 }, { 234, 242, 235 }, { 236, 228, 236 }, { 236, 244, 237 }, { 238, 230, 238 }, { 238, 246, 239 }, + { 240, 232, 240 }, { 240, 248, 241 }, { 242, 234, 242 }, { 242, 250, 243 }, { 244, 236, 244 }, { 244, 252, 245 }, { 246, 238, 246 }, { 246, 254, 247 }, + { 248, 240, 248 }, { 250, 226, 249 }, { 250, 242, 250 }, { 252, 228, 251 }, { 252, 244, 252 }, { 254, 230, 253 }, { 254, 246, 254 }, { 254, 246, 254 }, + } +}; + +Table g_mode6_p0_i2= +{ + 2, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 12, 2 }, { 0, 18, 3 }, { 0, 26, 4 }, { 0, 32, 5 }, { 0, 40, 6 }, { 0, 48, 7 }, + { 0, 54, 8 }, { 0, 62, 9 }, { 0, 68, 10 }, { 0, 76, 11 }, { 0, 82, 12 }, { 0, 90, 13 }, { 0, 96, 14 }, { 0, 104, 15 }, + { 0, 112, 16 }, { 0, 118, 17 }, { 0, 126, 18 }, { 0, 132, 19 }, { 0, 140, 20 }, { 0, 146, 21 }, { 0, 154, 22 }, { 0, 160, 23 }, + { 0, 168, 24 }, { 0, 176, 25 }, { 0, 182, 26 }, { 0, 190, 27 }, { 0, 196, 28 }, { 0, 204, 29 }, { 0, 210, 30 }, { 0, 218, 31 }, + { 0, 224, 32 }, { 0, 232, 33 }, { 0, 240, 34 }, { 0, 246, 35 }, { 0, 254, 36 }, { 2, 248, 37 }, { 4, 244, 38 }, { 4, 250, 39 }, + { 6, 246, 40 }, { 6, 252, 41 }, { 8, 248, 42 }, { 8, 254, 43 }, { 10, 250, 44 }, { 12, 244, 45 }, { 12, 252, 46 }, { 14, 246, 47 }, + { 14, 254, 48 }, { 16, 248, 49 }, { 18, 242, 50 }, { 18, 250, 51 }, { 20, 244, 52 }, { 20, 252, 53 }, { 22, 246, 54 }, { 22, 254, 55 }, + { 24, 248, 56 }, { 26, 244, 57 }, { 26, 250, 58 }, { 28, 246, 59 }, { 28, 252, 60 }, { 30, 248, 61 }, { 30, 254, 62 }, { 32, 250, 63 }, + { 34, 244, 64 }, { 34, 252, 65 }, { 36, 246, 66 }, { 36, 254, 67 }, { 38, 248, 68 }, { 40, 244, 69 }, { 40, 250, 70 }, { 42, 246, 71 }, + { 42, 252, 72 }, { 44, 248, 73 }, { 44, 254, 74 }, { 46, 250, 75 }, { 48, 244, 76 }, { 48, 252, 77 }, { 50, 246, 78 }, { 50, 254, 79 }, + { 52, 248, 80 }, { 54, 244, 81 }, { 54, 250, 82 }, { 56, 246, 83 }, { 56, 252, 84 }, { 58, 248, 85 }, { 58, 254, 86 }, { 60, 250, 87 }, + { 62, 244, 88 }, { 62, 252, 89 }, { 64, 246, 90 }, { 64, 254, 91 }, { 66, 248, 92 }, { 68, 244, 93 }, { 68, 250, 94 }, { 70, 246, 95 }, + { 70, 252, 96 }, { 72, 248, 97 }, { 72, 254, 98 }, { 74, 250, 99 }, { 76, 244, 100 }, { 76, 252, 101 }, { 78, 246, 102 }, { 78, 254, 103 }, + { 80, 248, 104 }, { 82, 242, 105 }, { 82, 250, 106 }, { 84, 244, 107 }, { 84, 252, 108 }, { 86, 246, 109 }, { 86, 254, 110 }, { 88, 248, 111 }, + { 90, 244, 112 }, { 90, 250, 113 }, { 92, 246, 114 }, { 92, 252, 115 }, { 94, 248, 116 }, { 94, 254, 117 }, { 96, 250, 118 }, { 98, 244, 119 }, + { 98, 252, 120 }, { 100, 246, 121 }, { 100, 254, 122 }, { 102, 248, 123 }, { 104, 244, 124 }, { 104, 250, 125 }, { 106, 246, 126 }, { 106, 252, 127 }, + { 108, 248, 128 }, { 108, 254, 129 }, { 110, 250, 130 }, { 112, 244, 131 }, { 112, 252, 132 }, { 114, 246, 133 }, { 114, 254, 134 }, { 116, 248, 135 }, + { 118, 244, 136 }, { 118, 250, 137 }, { 120, 246, 138 }, { 120, 252, 139 }, { 122, 248, 140 }, { 122, 254, 141 }, { 124, 250, 142 }, { 126, 244, 143 }, + { 126, 252, 144 }, { 128, 246, 145 }, { 128, 254, 146 }, { 130, 248, 147 }, { 132, 244, 148 }, { 132, 250, 149 }, { 134, 246, 150 }, { 134, 252, 151 }, + { 136, 248, 152 }, { 136, 254, 153 }, { 138, 250, 154 }, { 140, 244, 155 }, { 140, 252, 156 }, { 142, 246, 157 }, { 142, 254, 158 }, { 144, 248, 159 }, + { 146, 242, 160 }, { 146, 250, 161 }, { 148, 244, 162 }, { 148, 252, 163 }, { 150, 246, 164 }, { 150, 254, 165 }, { 152, 248, 166 }, { 154, 244, 167 }, + { 154, 250, 168 }, { 156, 246, 169 }, { 156, 252, 170 }, { 158, 248, 171 }, { 158, 254, 172 }, { 160, 250, 173 }, { 162, 244, 174 }, { 162, 252, 175 }, + { 164, 246, 176 }, { 164, 254, 177 }, { 166, 248, 178 }, { 168, 244, 179 }, { 168, 250, 180 }, { 170, 246, 181 }, { 170, 252, 182 }, { 172, 248, 183 }, + { 172, 254, 184 }, { 174, 250, 185 }, { 176, 244, 186 }, { 176, 252, 187 }, { 178, 246, 188 }, { 178, 254, 189 }, { 180, 248, 190 }, { 182, 244, 191 }, + { 182, 250, 192 }, { 184, 246, 193 }, { 184, 252, 194 }, { 186, 248, 195 }, { 186, 254, 196 }, { 188, 250, 197 }, { 190, 244, 198 }, { 190, 252, 199 }, + { 192, 246, 200 }, { 192, 254, 201 }, { 194, 248, 202 }, { 196, 244, 203 }, { 196, 250, 204 }, { 198, 246, 205 }, { 198, 252, 206 }, { 200, 248, 207 }, + { 200, 254, 208 }, { 202, 250, 209 }, { 204, 244, 210 }, { 204, 252, 211 }, { 206, 246, 212 }, { 206, 254, 213 }, { 208, 248, 214 }, { 210, 242, 215 }, + { 210, 250, 216 }, { 212, 244, 217 }, { 212, 252, 218 }, { 214, 246, 219 }, { 214, 254, 220 }, { 216, 248, 221 }, { 218, 244, 222 }, { 218, 250, 223 }, + { 220, 246, 224 }, { 220, 252, 225 }, { 222, 248, 226 }, { 222, 254, 227 }, { 224, 250, 228 }, { 226, 244, 229 }, { 226, 252, 230 }, { 228, 246, 231 }, + { 228, 254, 232 }, { 230, 248, 233 }, { 232, 244, 234 }, { 232, 250, 235 }, { 234, 246, 236 }, { 234, 252, 237 }, { 236, 248, 238 }, { 236, 254, 239 }, + { 238, 250, 240 }, { 240, 244, 241 }, { 240, 252, 242 }, { 242, 246, 243 }, { 242, 254, 244 }, { 244, 248, 245 }, { 246, 244, 246 }, { 246, 250, 247 }, + { 248, 246, 248 }, { 248, 252, 249 }, { 250, 248, 250 }, { 250, 254, 251 }, { 252, 250, 252 }, { 254, 244, 253 }, { 254, 252, 254 }, { 254, 252, 254 }, + } +}; + +Table g_mode6_p0_i3= +{ + 3, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 8, 2 }, { 0, 14, 3 }, { 0, 18, 4 }, { 0, 24, 5 }, { 0, 28, 6 }, { 0, 32, 7 }, + { 0, 38, 8 }, { 0, 42, 9 }, { 0, 48, 10 }, { 0, 52, 11 }, { 0, 58, 12 }, { 0, 62, 13 }, { 0, 68, 14 }, { 0, 72, 15 }, + { 0, 78, 16 }, { 0, 82, 17 }, { 0, 88, 18 }, { 0, 92, 19 }, { 0, 96, 20 }, { 0, 102, 21 }, { 0, 106, 22 }, { 0, 112, 23 }, + { 0, 116, 24 }, { 0, 122, 25 }, { 0, 126, 26 }, { 0, 132, 27 }, { 0, 136, 28 }, { 0, 142, 29 }, { 0, 146, 30 }, { 0, 152, 31 }, + { 0, 156, 32 }, { 0, 160, 33 }, { 0, 166, 34 }, { 0, 170, 35 }, { 0, 176, 36 }, { 0, 180, 37 }, { 0, 186, 38 }, { 0, 190, 39 }, + { 0, 196, 40 }, { 0, 200, 41 }, { 0, 206, 42 }, { 0, 210, 43 }, { 0, 216, 44 }, { 0, 220, 45 }, { 0, 224, 46 }, { 0, 230, 47 }, + { 0, 234, 48 }, { 0, 240, 49 }, { 0, 244, 50 }, { 0, 250, 51 }, { 0, 254, 52 }, { 2, 252, 53 }, { 4, 248, 54 }, { 4, 254, 55 }, + { 6, 250, 56 }, { 8, 248, 57 }, { 8, 252, 58 }, { 10, 250, 59 }, { 10, 254, 60 }, { 12, 252, 61 }, { 14, 248, 62 }, { 14, 254, 63 }, + { 16, 250, 64 }, { 18, 248, 65 }, { 18, 252, 66 }, { 20, 250, 67 }, { 20, 254, 68 }, { 22, 252, 69 }, { 24, 248, 70 }, { 24, 254, 71 }, + { 26, 250, 72 }, { 28, 248, 73 }, { 28, 252, 74 }, { 30, 250, 75 }, { 30, 254, 76 }, { 32, 252, 77 }, { 34, 250, 78 }, { 34, 254, 79 }, + { 36, 252, 80 }, { 38, 248, 81 }, { 38, 254, 82 }, { 40, 250, 83 }, { 42, 248, 84 }, { 42, 252, 85 }, { 44, 250, 86 }, { 44, 254, 87 }, + { 46, 252, 88 }, { 48, 248, 89 }, { 48, 254, 90 }, { 50, 250, 91 }, { 52, 248, 92 }, { 52, 252, 93 }, { 54, 250, 94 }, { 54, 254, 95 }, + { 56, 252, 96 }, { 58, 248, 97 }, { 58, 254, 98 }, { 60, 250, 99 }, { 62, 248, 100 }, { 62, 252, 101 }, { 64, 250, 102 }, { 64, 254, 103 }, + { 66, 252, 104 }, { 68, 248, 105 }, { 68, 254, 106 }, { 70, 250, 107 }, { 72, 248, 108 }, { 72, 252, 109 }, { 74, 250, 110 }, { 74, 254, 111 }, + { 76, 252, 112 }, { 78, 248, 113 }, { 78, 254, 114 }, { 80, 250, 115 }, { 82, 248, 116 }, { 82, 252, 117 }, { 84, 250, 118 }, { 84, 254, 119 }, + { 86, 252, 120 }, { 88, 248, 121 }, { 88, 254, 122 }, { 90, 250, 123 }, { 92, 248, 124 }, { 92, 252, 125 }, { 94, 250, 126 }, { 94, 254, 127 }, + { 96, 252, 128 }, { 98, 250, 129 }, { 98, 254, 130 }, { 100, 252, 131 }, { 102, 248, 132 }, { 102, 254, 133 }, { 104, 250, 134 }, { 106, 248, 135 }, + { 106, 252, 136 }, { 108, 250, 137 }, { 108, 254, 138 }, { 110, 252, 139 }, { 112, 248, 140 }, { 112, 254, 141 }, { 114, 250, 142 }, { 116, 248, 143 }, + { 116, 252, 144 }, { 118, 250, 145 }, { 118, 254, 146 }, { 120, 252, 147 }, { 122, 248, 148 }, { 122, 254, 149 }, { 124, 250, 150 }, { 126, 248, 151 }, + { 126, 252, 152 }, { 128, 250, 153 }, { 128, 254, 154 }, { 130, 252, 155 }, { 132, 248, 156 }, { 132, 254, 157 }, { 134, 250, 158 }, { 136, 248, 159 }, + { 136, 252, 160 }, { 138, 250, 161 }, { 138, 254, 162 }, { 140, 252, 163 }, { 142, 248, 164 }, { 142, 254, 165 }, { 144, 250, 166 }, { 146, 248, 167 }, + { 146, 252, 168 }, { 148, 250, 169 }, { 148, 254, 170 }, { 150, 252, 171 }, { 152, 248, 172 }, { 152, 254, 173 }, { 154, 250, 174 }, { 156, 248, 175 }, + { 156, 252, 176 }, { 158, 250, 177 }, { 158, 254, 178 }, { 160, 252, 179 }, { 162, 250, 180 }, { 162, 254, 181 }, { 164, 252, 182 }, { 166, 248, 183 }, + { 166, 254, 184 }, { 168, 250, 185 }, { 170, 248, 186 }, { 170, 252, 187 }, { 172, 250, 188 }, { 172, 254, 189 }, { 174, 252, 190 }, { 176, 248, 191 }, + { 176, 254, 192 }, { 178, 250, 193 }, { 180, 248, 194 }, { 180, 252, 195 }, { 182, 250, 196 }, { 182, 254, 197 }, { 184, 252, 198 }, { 186, 248, 199 }, + { 186, 254, 200 }, { 188, 250, 201 }, { 190, 248, 202 }, { 190, 252, 203 }, { 192, 250, 204 }, { 192, 254, 205 }, { 194, 252, 206 }, { 196, 248, 207 }, + { 196, 254, 208 }, { 198, 250, 209 }, { 200, 248, 210 }, { 200, 252, 211 }, { 202, 250, 212 }, { 202, 254, 213 }, { 204, 252, 214 }, { 206, 248, 215 }, + { 206, 254, 216 }, { 208, 250, 217 }, { 210, 248, 218 }, { 210, 252, 219 }, { 212, 250, 220 }, { 212, 254, 221 }, { 214, 252, 222 }, { 216, 248, 223 }, + { 216, 254, 224 }, { 218, 250, 225 }, { 220, 248, 226 }, { 220, 252, 227 }, { 222, 250, 228 }, { 222, 254, 229 }, { 224, 252, 230 }, { 226, 250, 231 }, + { 226, 254, 232 }, { 228, 252, 233 }, { 230, 248, 234 }, { 230, 254, 235 }, { 232, 250, 236 }, { 234, 248, 237 }, { 234, 252, 238 }, { 236, 250, 239 }, + { 236, 254, 240 }, { 238, 252, 241 }, { 240, 248, 242 }, { 240, 254, 243 }, { 242, 250, 244 }, { 244, 248, 245 }, { 244, 252, 246 }, { 246, 250, 247 }, + { 246, 254, 248 }, { 248, 252, 249 }, { 250, 248, 250 }, { 250, 254, 251 }, { 252, 250, 252 }, { 254, 248, 253 }, { 254, 252, 254 }, { 254, 252, 254 }, + } +}; + +Table g_mode6_p0_i4= +{ + 4, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 6, 2 }, { 0, 10, 3 }, { 0, 14, 4 }, { 0, 18, 5 }, { 0, 22, 6 }, { 0, 26, 7 }, + { 0, 30, 8 }, { 0, 32, 9 }, { 0, 36, 10 }, { 0, 40, 11 }, { 0, 44, 12 }, { 0, 48, 13 }, { 0, 52, 14 }, { 0, 56, 15 }, + { 0, 60, 16 }, { 0, 64, 17 }, { 0, 66, 18 }, { 0, 70, 19 }, { 0, 74, 20 }, { 0, 78, 21 }, { 0, 82, 22 }, { 0, 86, 23 }, + { 0, 90, 24 }, { 0, 94, 25 }, { 0, 96, 26 }, { 0, 100, 27 }, { 0, 104, 28 }, { 0, 108, 29 }, { 0, 112, 30 }, { 0, 116, 31 }, + { 0, 120, 32 }, { 0, 124, 33 }, { 0, 128, 34 }, { 0, 130, 35 }, { 0, 134, 36 }, { 0, 138, 37 }, { 0, 142, 38 }, { 0, 146, 39 }, + { 0, 150, 40 }, { 0, 154, 41 }, { 0, 158, 42 }, { 0, 160, 43 }, { 0, 164, 44 }, { 0, 168, 45 }, { 0, 172, 46 }, { 0, 176, 47 }, + { 0, 180, 48 }, { 0, 184, 49 }, { 0, 188, 50 }, { 0, 192, 51 }, { 0, 194, 52 }, { 0, 198, 53 }, { 0, 202, 54 }, { 0, 206, 55 }, + { 0, 210, 56 }, { 0, 214, 57 }, { 0, 218, 58 }, { 0, 222, 59 }, { 0, 224, 60 }, { 0, 228, 61 }, { 0, 232, 62 }, { 0, 236, 63 }, + { 0, 240, 64 }, { 0, 244, 65 }, { 0, 248, 66 }, { 0, 252, 67 }, { 2, 250, 68 }, { 2, 254, 69 }, { 4, 252, 70 }, { 6, 250, 71 }, + { 6, 254, 72 }, { 8, 252, 73 }, { 10, 250, 74 }, { 10, 254, 75 }, { 12, 252, 76 }, { 14, 250, 77 }, { 14, 254, 78 }, { 16, 252, 79 }, + { 18, 250, 80 }, { 18, 254, 81 }, { 20, 252, 82 }, { 22, 250, 83 }, { 22, 254, 84 }, { 24, 252, 85 }, { 26, 250, 86 }, { 26, 254, 87 }, + { 28, 252, 88 }, { 30, 252, 89 }, { 30, 254, 90 }, { 32, 254, 91 }, { 34, 252, 92 }, { 36, 250, 93 }, { 36, 254, 94 }, { 38, 252, 95 }, + { 40, 250, 96 }, { 40, 254, 97 }, { 42, 252, 98 }, { 44, 250, 99 }, { 44, 254, 100 }, { 46, 252, 101 }, { 48, 250, 102 }, { 48, 254, 103 }, + { 50, 252, 104 }, { 52, 250, 105 }, { 52, 254, 106 }, { 54, 252, 107 }, { 56, 250, 108 }, { 56, 254, 109 }, { 58, 252, 110 }, { 60, 252, 111 }, + { 60, 254, 112 }, { 62, 254, 113 }, { 64, 252, 114 }, { 66, 250, 115 }, { 66, 254, 116 }, { 68, 252, 117 }, { 70, 250, 118 }, { 70, 254, 119 }, + { 72, 252, 120 }, { 74, 250, 121 }, { 74, 254, 122 }, { 76, 252, 123 }, { 78, 250, 124 }, { 78, 254, 125 }, { 80, 252, 126 }, { 82, 250, 127 }, + { 82, 254, 128 }, { 84, 252, 129 }, { 86, 250, 130 }, { 86, 254, 131 }, { 88, 252, 132 }, { 90, 250, 133 }, { 90, 254, 134 }, { 92, 252, 135 }, + { 94, 252, 136 }, { 94, 254, 137 }, { 96, 254, 138 }, { 98, 252, 139 }, { 100, 250, 140 }, { 100, 254, 141 }, { 102, 252, 142 }, { 104, 250, 143 }, + { 104, 254, 144 }, { 106, 252, 145 }, { 108, 250, 146 }, { 108, 254, 147 }, { 110, 252, 148 }, { 112, 250, 149 }, { 112, 254, 150 }, { 114, 252, 151 }, + { 116, 250, 152 }, { 116, 254, 153 }, { 118, 252, 154 }, { 120, 250, 155 }, { 120, 254, 156 }, { 122, 252, 157 }, { 124, 252, 158 }, { 124, 254, 159 }, + { 126, 254, 160 }, { 128, 252, 161 }, { 130, 250, 162 }, { 130, 254, 163 }, { 132, 252, 164 }, { 134, 250, 165 }, { 134, 254, 166 }, { 136, 252, 167 }, + { 138, 250, 168 }, { 138, 254, 169 }, { 140, 252, 170 }, { 142, 250, 171 }, { 142, 254, 172 }, { 144, 252, 173 }, { 146, 250, 174 }, { 146, 254, 175 }, + { 148, 252, 176 }, { 150, 250, 177 }, { 150, 254, 178 }, { 152, 252, 179 }, { 154, 250, 180 }, { 154, 254, 181 }, { 156, 252, 182 }, { 158, 252, 183 }, + { 158, 254, 184 }, { 160, 254, 185 }, { 162, 252, 186 }, { 164, 250, 187 }, { 164, 254, 188 }, { 166, 252, 189 }, { 168, 250, 190 }, { 168, 254, 191 }, + { 170, 252, 192 }, { 172, 250, 193 }, { 172, 254, 194 }, { 174, 252, 195 }, { 176, 250, 196 }, { 176, 254, 197 }, { 178, 252, 198 }, { 180, 250, 199 }, + { 180, 254, 200 }, { 182, 252, 201 }, { 184, 250, 202 }, { 184, 254, 203 }, { 186, 252, 204 }, { 188, 252, 205 }, { 188, 254, 206 }, { 190, 254, 207 }, + { 192, 252, 208 }, { 194, 250, 209 }, { 194, 254, 210 }, { 196, 252, 211 }, { 198, 250, 212 }, { 198, 254, 213 }, { 200, 252, 214 }, { 202, 250, 215 }, + { 202, 254, 216 }, { 204, 252, 217 }, { 206, 250, 218 }, { 206, 254, 219 }, { 208, 252, 220 }, { 210, 250, 221 }, { 210, 254, 222 }, { 212, 252, 223 }, + { 214, 250, 224 }, { 214, 254, 225 }, { 216, 252, 226 }, { 218, 250, 227 }, { 218, 254, 228 }, { 220, 252, 229 }, { 222, 252, 230 }, { 222, 254, 231 }, + { 224, 254, 232 }, { 226, 252, 233 }, { 228, 250, 234 }, { 228, 254, 235 }, { 230, 252, 236 }, { 232, 250, 237 }, { 232, 254, 238 }, { 234, 252, 239 }, + { 236, 250, 240 }, { 236, 254, 241 }, { 238, 252, 242 }, { 240, 250, 243 }, { 240, 254, 244 }, { 242, 252, 245 }, { 244, 250, 246 }, { 244, 254, 247 }, + { 246, 252, 248 }, { 248, 250, 249 }, { 248, 254, 250 }, { 250, 252, 251 }, { 252, 252, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode6_p0_i5= +{ + 5, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 6, 2 }, { 0, 8, 3 }, { 0, 12, 4 }, { 0, 14, 5 }, { 0, 18, 6 }, { 0, 20, 7 }, + { 0, 24, 8 }, { 0, 26, 9 }, { 0, 30, 10 }, { 0, 32, 11 }, { 0, 36, 12 }, { 0, 40, 13 }, { 0, 42, 14 }, { 0, 46, 15 }, + { 0, 48, 16 }, { 0, 52, 17 }, { 0, 54, 18 }, { 0, 58, 19 }, { 0, 60, 20 }, { 0, 64, 21 }, { 0, 66, 22 }, { 0, 70, 23 }, + { 0, 72, 24 }, { 0, 76, 25 }, { 0, 78, 26 }, { 0, 82, 27 }, { 0, 84, 28 }, { 0, 88, 29 }, { 0, 90, 30 }, { 0, 94, 31 }, + { 0, 96, 32 }, { 0, 100, 33 }, { 0, 104, 34 }, { 0, 106, 35 }, { 0, 110, 36 }, { 0, 112, 37 }, { 0, 116, 38 }, { 0, 118, 39 }, + { 0, 122, 40 }, { 0, 124, 41 }, { 0, 128, 42 }, { 0, 130, 43 }, { 0, 134, 44 }, { 0, 136, 45 }, { 0, 140, 46 }, { 0, 142, 47 }, + { 0, 146, 48 }, { 0, 148, 49 }, { 0, 152, 50 }, { 0, 154, 51 }, { 0, 158, 52 }, { 0, 160, 53 }, { 0, 164, 54 }, { 0, 168, 55 }, + { 0, 170, 56 }, { 0, 174, 57 }, { 0, 176, 58 }, { 0, 180, 59 }, { 0, 182, 60 }, { 0, 186, 61 }, { 0, 188, 62 }, { 0, 192, 63 }, + { 0, 194, 64 }, { 0, 198, 65 }, { 0, 200, 66 }, { 0, 204, 67 }, { 0, 206, 68 }, { 0, 210, 69 }, { 0, 212, 70 }, { 0, 216, 71 }, + { 0, 218, 72 }, { 0, 222, 73 }, { 0, 224, 74 }, { 0, 228, 75 }, { 0, 232, 76 }, { 0, 234, 77 }, { 0, 238, 78 }, { 0, 240, 79 }, + { 0, 244, 80 }, { 0, 246, 81 }, { 0, 250, 82 }, { 0, 252, 83 }, { 2, 252, 84 }, { 2, 254, 85 }, { 4, 254, 86 }, { 6, 252, 87 }, + { 8, 252, 88 }, { 8, 254, 89 }, { 10, 254, 90 }, { 12, 252, 91 }, { 14, 252, 92 }, { 14, 254, 93 }, { 16, 254, 94 }, { 18, 252, 95 }, + { 20, 252, 96 }, { 20, 254, 97 }, { 22, 254, 98 }, { 24, 252, 99 }, { 26, 250, 100 }, { 26, 254, 101 }, { 28, 252, 102 }, { 30, 252, 103 }, + { 30, 254, 104 }, { 32, 254, 105 }, { 34, 252, 106 }, { 36, 252, 107 }, { 36, 254, 108 }, { 38, 254, 109 }, { 40, 252, 110 }, { 42, 252, 111 }, + { 42, 254, 112 }, { 44, 254, 113 }, { 46, 252, 114 }, { 48, 252, 115 }, { 48, 254, 116 }, { 50, 254, 117 }, { 52, 252, 118 }, { 54, 252, 119 }, + { 54, 254, 120 }, { 56, 254, 121 }, { 58, 252, 122 }, { 60, 252, 123 }, { 60, 254, 124 }, { 62, 254, 125 }, { 64, 252, 126 }, { 66, 252, 127 }, + { 66, 254, 128 }, { 68, 254, 129 }, { 70, 252, 130 }, { 72, 252, 131 }, { 72, 254, 132 }, { 74, 254, 133 }, { 76, 252, 134 }, { 78, 252, 135 }, + { 78, 254, 136 }, { 80, 254, 137 }, { 82, 252, 138 }, { 84, 252, 139 }, { 84, 254, 140 }, { 86, 254, 141 }, { 88, 252, 142 }, { 90, 250, 143 }, + { 90, 254, 144 }, { 92, 252, 145 }, { 94, 252, 146 }, { 94, 254, 147 }, { 96, 254, 148 }, { 98, 252, 149 }, { 100, 252, 150 }, { 100, 254, 151 }, + { 102, 254, 152 }, { 104, 252, 153 }, { 106, 252, 154 }, { 106, 254, 155 }, { 108, 254, 156 }, { 110, 252, 157 }, { 112, 252, 158 }, { 112, 254, 159 }, + { 114, 254, 160 }, { 116, 252, 161 }, { 118, 252, 162 }, { 118, 254, 163 }, { 120, 254, 164 }, { 122, 252, 165 }, { 124, 252, 166 }, { 124, 254, 167 }, + { 126, 254, 168 }, { 128, 252, 169 }, { 130, 252, 170 }, { 130, 254, 171 }, { 132, 254, 172 }, { 134, 252, 173 }, { 136, 252, 174 }, { 136, 254, 175 }, + { 138, 254, 176 }, { 140, 252, 177 }, { 142, 252, 178 }, { 142, 254, 179 }, { 144, 254, 180 }, { 146, 252, 181 }, { 148, 252, 182 }, { 148, 254, 183 }, + { 150, 254, 184 }, { 152, 252, 185 }, { 154, 250, 186 }, { 154, 254, 187 }, { 156, 252, 188 }, { 158, 252, 189 }, { 158, 254, 190 }, { 160, 254, 191 }, + { 162, 252, 192 }, { 164, 252, 193 }, { 164, 254, 194 }, { 166, 254, 195 }, { 168, 252, 196 }, { 170, 252, 197 }, { 170, 254, 198 }, { 172, 254, 199 }, + { 174, 252, 200 }, { 176, 252, 201 }, { 176, 254, 202 }, { 178, 254, 203 }, { 180, 252, 204 }, { 182, 252, 205 }, { 182, 254, 206 }, { 184, 254, 207 }, + { 186, 252, 208 }, { 188, 252, 209 }, { 188, 254, 210 }, { 190, 254, 211 }, { 192, 252, 212 }, { 194, 252, 213 }, { 194, 254, 214 }, { 196, 254, 215 }, + { 198, 252, 216 }, { 200, 252, 217 }, { 200, 254, 218 }, { 202, 254, 219 }, { 204, 252, 220 }, { 206, 252, 221 }, { 206, 254, 222 }, { 208, 254, 223 }, + { 210, 252, 224 }, { 212, 252, 225 }, { 212, 254, 226 }, { 214, 254, 227 }, { 216, 252, 228 }, { 218, 250, 229 }, { 218, 254, 230 }, { 220, 252, 231 }, + { 222, 252, 232 }, { 222, 254, 233 }, { 224, 254, 234 }, { 226, 252, 235 }, { 228, 252, 236 }, { 228, 254, 237 }, { 230, 254, 238 }, { 232, 252, 239 }, + { 234, 252, 240 }, { 234, 254, 241 }, { 236, 254, 242 }, { 238, 252, 243 }, { 240, 252, 244 }, { 240, 254, 245 }, { 242, 254, 246 }, { 244, 252, 247 }, + { 246, 252, 248 }, { 246, 254, 249 }, { 248, 254, 250 }, { 250, 252, 251 }, { 252, 252, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode6_p0_i6= +{ + 6, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 4, 2 }, { 0, 8, 3 }, { 0, 10, 4 }, { 0, 12, 5 }, { 0, 14, 6 }, { 0, 16, 7 }, + { 0, 20, 8 }, { 0, 22, 9 }, { 0, 24, 10 }, { 0, 26, 11 }, { 0, 30, 12 }, { 0, 32, 13 }, { 0, 34, 14 }, { 0, 36, 15 }, + { 0, 40, 16 }, { 0, 42, 17 }, { 0, 44, 18 }, { 0, 46, 19 }, { 0, 48, 20 }, { 0, 52, 21 }, { 0, 54, 22 }, { 0, 56, 23 }, + { 0, 58, 24 }, { 0, 62, 25 }, { 0, 64, 26 }, { 0, 66, 27 }, { 0, 68, 28 }, { 0, 72, 29 }, { 0, 74, 30 }, { 0, 76, 31 }, + { 0, 78, 32 }, { 0, 80, 33 }, { 0, 84, 34 }, { 0, 86, 35 }, { 0, 88, 36 }, { 0, 90, 37 }, { 0, 94, 38 }, { 0, 96, 39 }, + { 0, 98, 40 }, { 0, 100, 41 }, { 0, 104, 42 }, { 0, 106, 43 }, { 0, 108, 44 }, { 0, 110, 45 }, { 0, 112, 46 }, { 0, 116, 47 }, + { 0, 118, 48 }, { 0, 120, 49 }, { 0, 122, 50 }, { 0, 126, 51 }, { 0, 128, 52 }, { 0, 130, 53 }, { 0, 132, 54 }, { 0, 136, 55 }, + { 0, 138, 56 }, { 0, 140, 57 }, { 0, 142, 58 }, { 0, 144, 59 }, { 0, 148, 60 }, { 0, 150, 61 }, { 0, 152, 62 }, { 0, 154, 63 }, + { 0, 158, 64 }, { 0, 160, 65 }, { 0, 162, 66 }, { 0, 164, 67 }, { 0, 168, 68 }, { 0, 170, 69 }, { 0, 172, 70 }, { 0, 174, 71 }, + { 0, 176, 72 }, { 0, 180, 73 }, { 0, 182, 74 }, { 0, 184, 75 }, { 0, 186, 76 }, { 0, 190, 77 }, { 0, 192, 78 }, { 0, 194, 79 }, + { 0, 196, 80 }, { 0, 200, 81 }, { 0, 202, 82 }, { 0, 204, 83 }, { 0, 206, 84 }, { 0, 208, 85 }, { 0, 212, 86 }, { 0, 214, 87 }, + { 0, 216, 88 }, { 0, 218, 89 }, { 0, 222, 90 }, { 0, 224, 91 }, { 0, 226, 92 }, { 0, 228, 93 }, { 0, 232, 94 }, { 0, 234, 95 }, + { 0, 236, 96 }, { 0, 238, 97 }, { 0, 240, 98 }, { 0, 244, 99 }, { 0, 246, 100 }, { 0, 248, 101 }, { 0, 250, 102 }, { 0, 254, 103 }, + { 2, 252, 104 }, { 4, 252, 105 }, { 4, 254, 106 }, { 6, 254, 107 }, { 8, 254, 108 }, { 10, 254, 109 }, { 12, 252, 110 }, { 14, 252, 111 }, + { 14, 254, 112 }, { 16, 254, 113 }, { 18, 254, 114 }, { 20, 254, 115 }, { 22, 254, 116 }, { 24, 252, 117 }, { 26, 252, 118 }, { 26, 254, 119 }, + { 28, 254, 120 }, { 30, 254, 121 }, { 32, 254, 122 }, { 34, 252, 123 }, { 36, 252, 124 }, { 36, 254, 125 }, { 38, 254, 126 }, { 40, 254, 127 }, + { 42, 254, 128 }, { 44, 252, 129 }, { 46, 252, 130 }, { 46, 254, 131 }, { 48, 254, 132 }, { 50, 254, 133 }, { 52, 254, 134 }, { 54, 254, 135 }, + { 56, 252, 136 }, { 58, 252, 137 }, { 58, 254, 138 }, { 60, 254, 139 }, { 62, 254, 140 }, { 64, 254, 141 }, { 66, 252, 142 }, { 68, 252, 143 }, + { 68, 254, 144 }, { 70, 254, 145 }, { 72, 254, 146 }, { 74, 254, 147 }, { 76, 252, 148 }, { 78, 252, 149 }, { 78, 254, 150 }, { 80, 254, 151 }, + { 82, 254, 152 }, { 84, 254, 153 }, { 86, 254, 154 }, { 88, 252, 155 }, { 90, 252, 156 }, { 90, 254, 157 }, { 92, 254, 158 }, { 94, 254, 159 }, + { 96, 254, 160 }, { 98, 252, 161 }, { 100, 252, 162 }, { 100, 254, 163 }, { 102, 254, 164 }, { 104, 254, 165 }, { 106, 254, 166 }, { 108, 252, 167 }, + { 110, 252, 168 }, { 110, 254, 169 }, { 112, 254, 170 }, { 114, 254, 171 }, { 116, 254, 172 }, { 118, 254, 173 }, { 120, 252, 174 }, { 122, 252, 175 }, + { 122, 254, 176 }, { 124, 254, 177 }, { 126, 254, 178 }, { 128, 254, 179 }, { 130, 252, 180 }, { 132, 252, 181 }, { 132, 254, 182 }, { 134, 254, 183 }, + { 136, 254, 184 }, { 138, 254, 185 }, { 140, 252, 186 }, { 142, 252, 187 }, { 142, 254, 188 }, { 144, 254, 189 }, { 146, 254, 190 }, { 148, 254, 191 }, + { 150, 254, 192 }, { 152, 252, 193 }, { 154, 252, 194 }, { 154, 254, 195 }, { 156, 254, 196 }, { 158, 254, 197 }, { 160, 254, 198 }, { 162, 252, 199 }, + { 164, 252, 200 }, { 164, 254, 201 }, { 166, 254, 202 }, { 168, 254, 203 }, { 170, 254, 204 }, { 172, 252, 205 }, { 174, 252, 206 }, { 174, 254, 207 }, + { 176, 254, 208 }, { 178, 254, 209 }, { 180, 254, 210 }, { 182, 254, 211 }, { 184, 252, 212 }, { 186, 252, 213 }, { 186, 254, 214 }, { 188, 254, 215 }, + { 190, 254, 216 }, { 192, 254, 217 }, { 194, 252, 218 }, { 196, 252, 219 }, { 196, 254, 220 }, { 198, 254, 221 }, { 200, 254, 222 }, { 202, 254, 223 }, + { 204, 252, 224 }, { 206, 252, 225 }, { 206, 254, 226 }, { 208, 254, 227 }, { 210, 254, 228 }, { 212, 254, 229 }, { 214, 254, 230 }, { 216, 252, 231 }, + { 218, 252, 232 }, { 218, 254, 233 }, { 220, 254, 234 }, { 222, 254, 235 }, { 224, 254, 236 }, { 226, 252, 237 }, { 228, 252, 238 }, { 228, 254, 239 }, + { 230, 254, 240 }, { 232, 254, 241 }, { 234, 254, 242 }, { 236, 252, 243 }, { 238, 252, 244 }, { 238, 254, 245 }, { 240, 254, 246 }, { 242, 254, 247 }, + { 244, 254, 248 }, { 246, 254, 249 }, { 248, 252, 250 }, { 250, 252, 251 }, { 250, 254, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode6_p0_i7= +{ + 7, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 4, 2 }, { 0, 6, 3 }, { 0, 8, 4 }, { 0, 10, 5 }, { 0, 12, 6 }, { 0, 14, 7 }, + { 0, 16, 8 }, { 0, 20, 9 }, { 0, 22, 10 }, { 0, 24, 11 }, { 0, 26, 12 }, { 0, 28, 13 }, { 0, 30, 14 }, { 0, 32, 15 }, + { 0, 34, 16 }, { 0, 36, 17 }, { 0, 38, 18 }, { 0, 40, 19 }, { 0, 42, 20 }, { 0, 44, 21 }, { 0, 46, 22 }, { 0, 48, 23 }, + { 0, 52, 24 }, { 0, 54, 25 }, { 0, 56, 26 }, { 0, 58, 27 }, { 0, 60, 28 }, { 0, 62, 29 }, { 0, 64, 30 }, { 0, 66, 31 }, + { 0, 68, 32 }, { 0, 70, 33 }, { 0, 72, 34 }, { 0, 74, 35 }, { 0, 76, 36 }, { 0, 78, 37 }, { 0, 80, 38 }, { 0, 84, 39 }, + { 0, 86, 40 }, { 0, 88, 41 }, { 0, 90, 42 }, { 0, 92, 43 }, { 0, 94, 44 }, { 0, 96, 45 }, { 0, 98, 46 }, { 0, 100, 47 }, + { 0, 102, 48 }, { 0, 104, 49 }, { 0, 106, 50 }, { 0, 108, 51 }, { 0, 110, 52 }, { 0, 112, 53 }, { 0, 116, 54 }, { 0, 118, 55 }, + { 0, 120, 56 }, { 0, 122, 57 }, { 0, 124, 58 }, { 0, 126, 59 }, { 0, 128, 60 }, { 0, 130, 61 }, { 0, 132, 62 }, { 0, 134, 63 }, + { 0, 136, 64 }, { 0, 138, 65 }, { 0, 140, 66 }, { 0, 142, 67 }, { 0, 144, 68 }, { 0, 148, 69 }, { 0, 150, 70 }, { 0, 152, 71 }, + { 0, 154, 72 }, { 0, 156, 73 }, { 0, 158, 74 }, { 0, 160, 75 }, { 0, 162, 76 }, { 0, 164, 77 }, { 0, 166, 78 }, { 0, 168, 79 }, + { 0, 170, 80 }, { 0, 172, 81 }, { 0, 174, 82 }, { 0, 176, 83 }, { 0, 180, 84 }, { 0, 182, 85 }, { 0, 184, 86 }, { 0, 186, 87 }, + { 0, 188, 88 }, { 0, 190, 89 }, { 0, 192, 90 }, { 0, 194, 91 }, { 0, 196, 92 }, { 0, 198, 93 }, { 0, 200, 94 }, { 0, 202, 95 }, + { 0, 204, 96 }, { 0, 206, 97 }, { 0, 208, 98 }, { 0, 212, 99 }, { 0, 214, 100 }, { 0, 216, 101 }, { 0, 218, 102 }, { 0, 220, 103 }, + { 0, 222, 104 }, { 0, 224, 105 }, { 0, 226, 106 }, { 0, 228, 107 }, { 0, 230, 108 }, { 0, 232, 109 }, { 0, 234, 110 }, { 0, 236, 111 }, + { 0, 238, 112 }, { 0, 240, 113 }, { 0, 244, 114 }, { 0, 246, 115 }, { 0, 248, 116 }, { 0, 250, 117 }, { 0, 252, 118 }, { 0, 254, 119 }, + { 2, 254, 120 }, { 4, 254, 121 }, { 6, 254, 122 }, { 8, 254, 123 }, { 10, 254, 124 }, { 12, 252, 125 }, { 14, 252, 126 }, { 14, 254, 127 }, + { 16, 254, 128 }, { 18, 254, 129 }, { 20, 254, 130 }, { 22, 254, 131 }, { 24, 254, 132 }, { 26, 254, 133 }, { 28, 254, 134 }, { 30, 254, 135 }, + { 32, 254, 136 }, { 34, 254, 137 }, { 36, 254, 138 }, { 38, 254, 139 }, { 40, 254, 140 }, { 42, 254, 141 }, { 44, 252, 142 }, { 46, 252, 143 }, + { 46, 254, 144 }, { 48, 254, 145 }, { 50, 254, 146 }, { 52, 254, 147 }, { 54, 254, 148 }, { 56, 254, 149 }, { 58, 254, 150 }, { 60, 254, 151 }, + { 62, 254, 152 }, { 64, 254, 153 }, { 66, 254, 154 }, { 68, 254, 155 }, { 70, 254, 156 }, { 72, 254, 157 }, { 74, 254, 158 }, { 76, 252, 159 }, + { 78, 252, 160 }, { 78, 254, 161 }, { 80, 254, 162 }, { 82, 254, 163 }, { 84, 254, 164 }, { 86, 254, 165 }, { 88, 254, 166 }, { 90, 254, 167 }, + { 92, 254, 168 }, { 94, 254, 169 }, { 96, 254, 170 }, { 98, 254, 171 }, { 100, 254, 172 }, { 102, 254, 173 }, { 104, 254, 174 }, { 106, 254, 175 }, + { 108, 252, 176 }, { 110, 252, 177 }, { 110, 254, 178 }, { 112, 254, 179 }, { 114, 254, 180 }, { 116, 254, 181 }, { 118, 254, 182 }, { 120, 254, 183 }, + { 122, 254, 184 }, { 124, 254, 185 }, { 126, 254, 186 }, { 128, 254, 187 }, { 130, 254, 188 }, { 132, 254, 189 }, { 134, 254, 190 }, { 136, 254, 191 }, + { 138, 254, 192 }, { 140, 252, 193 }, { 142, 252, 194 }, { 142, 254, 195 }, { 144, 254, 196 }, { 146, 254, 197 }, { 148, 254, 198 }, { 150, 254, 199 }, + { 152, 254, 200 }, { 154, 254, 201 }, { 156, 254, 202 }, { 158, 254, 203 }, { 160, 254, 204 }, { 162, 254, 205 }, { 164, 254, 206 }, { 166, 254, 207 }, + { 168, 254, 208 }, { 170, 254, 209 }, { 172, 252, 210 }, { 174, 252, 211 }, { 174, 254, 212 }, { 176, 254, 213 }, { 178, 254, 214 }, { 180, 254, 215 }, + { 182, 254, 216 }, { 184, 254, 217 }, { 186, 254, 218 }, { 188, 254, 219 }, { 190, 254, 220 }, { 192, 254, 221 }, { 194, 254, 222 }, { 196, 254, 223 }, + { 198, 254, 224 }, { 200, 254, 225 }, { 202, 254, 226 }, { 204, 252, 227 }, { 206, 252, 228 }, { 206, 254, 229 }, { 208, 254, 230 }, { 210, 254, 231 }, + { 212, 254, 232 }, { 214, 254, 233 }, { 216, 254, 234 }, { 218, 254, 235 }, { 220, 254, 236 }, { 222, 254, 237 }, { 224, 254, 238 }, { 226, 254, 239 }, + { 228, 254, 240 }, { 230, 254, 241 }, { 232, 254, 242 }, { 234, 254, 243 }, { 236, 252, 244 }, { 238, 252, 245 }, { 238, 254, 246 }, { 240, 254, 247 }, + { 242, 254, 248 }, { 244, 254, 249 }, { 246, 254, 250 }, { 248, 254, 251 }, { 250, 254, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode6_p1_i1= +{ + 1, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 9, 2 }, { 1, 25, 3 }, { 1, 41, 4 }, { 1, 57, 5 }, { 1, 73, 6 }, { 1, 89, 7 }, + { 1, 105, 8 }, { 1, 121, 9 }, { 1, 137, 10 }, { 1, 153, 11 }, { 1, 169, 12 }, { 1, 185, 13 }, { 1, 201, 14 }, { 1, 217, 15 }, + { 1, 233, 16 }, { 1, 249, 17 }, { 3, 235, 18 }, { 3, 251, 19 }, { 5, 237, 20 }, { 5, 253, 21 }, { 7, 239, 22 }, { 7, 255, 23 }, + { 9, 241, 24 }, { 11, 227, 25 }, { 11, 243, 26 }, { 13, 229, 27 }, { 13, 245, 28 }, { 15, 231, 29 }, { 15, 247, 30 }, { 17, 233, 31 }, + { 17, 249, 32 }, { 19, 235, 33 }, { 19, 251, 34 }, { 21, 237, 35 }, { 21, 253, 36 }, { 23, 239, 37 }, { 23, 255, 38 }, { 25, 241, 39 }, + { 27, 227, 40 }, { 27, 243, 41 }, { 29, 229, 42 }, { 29, 245, 43 }, { 31, 231, 44 }, { 31, 247, 45 }, { 33, 233, 46 }, { 33, 249, 47 }, + { 35, 235, 48 }, { 35, 251, 49 }, { 37, 237, 50 }, { 37, 253, 51 }, { 39, 239, 52 }, { 39, 255, 53 }, { 41, 241, 54 }, { 43, 227, 55 }, + { 43, 243, 56 }, { 45, 229, 57 }, { 45, 245, 58 }, { 47, 231, 59 }, { 47, 247, 60 }, { 49, 233, 61 }, { 49, 249, 62 }, { 51, 235, 63 }, + { 51, 251, 64 }, { 53, 237, 65 }, { 53, 253, 66 }, { 55, 239, 67 }, { 55, 255, 68 }, { 57, 241, 69 }, { 59, 227, 70 }, { 59, 243, 71 }, + { 61, 229, 72 }, { 61, 245, 73 }, { 63, 231, 74 }, { 63, 247, 75 }, { 65, 233, 76 }, { 65, 249, 77 }, { 67, 235, 78 }, { 67, 251, 79 }, + { 69, 237, 80 }, { 69, 253, 81 }, { 71, 239, 82 }, { 71, 255, 83 }, { 73, 241, 84 }, { 75, 227, 85 }, { 75, 243, 86 }, { 77, 229, 87 }, + { 77, 245, 88 }, { 79, 231, 89 }, { 79, 247, 90 }, { 81, 233, 91 }, { 81, 249, 92 }, { 83, 235, 93 }, { 83, 251, 94 }, { 85, 237, 95 }, + { 85, 253, 96 }, { 87, 239, 97 }, { 87, 255, 98 }, { 89, 241, 99 }, { 91, 227, 100 }, { 91, 243, 101 }, { 93, 229, 102 }, { 93, 245, 103 }, + { 95, 231, 104 }, { 95, 247, 105 }, { 97, 233, 106 }, { 97, 249, 107 }, { 99, 235, 108 }, { 99, 251, 109 }, { 101, 237, 110 }, { 101, 253, 111 }, + { 103, 239, 112 }, { 103, 255, 113 }, { 105, 241, 114 }, { 107, 227, 115 }, { 107, 243, 116 }, { 109, 229, 117 }, { 109, 245, 118 }, { 111, 231, 119 }, + { 111, 247, 120 }, { 113, 233, 121 }, { 113, 249, 122 }, { 115, 235, 123 }, { 115, 251, 124 }, { 117, 237, 125 }, { 117, 253, 126 }, { 119, 239, 127 }, + { 119, 255, 128 }, { 121, 241, 129 }, { 123, 227, 130 }, { 123, 243, 131 }, { 125, 229, 132 }, { 125, 245, 133 }, { 127, 231, 134 }, { 127, 247, 135 }, + { 129, 233, 136 }, { 129, 249, 137 }, { 131, 235, 138 }, { 131, 251, 139 }, { 133, 237, 140 }, { 133, 253, 141 }, { 135, 239, 142 }, { 135, 255, 143 }, + { 137, 241, 144 }, { 139, 227, 145 }, { 139, 243, 146 }, { 141, 229, 147 }, { 141, 245, 148 }, { 143, 231, 149 }, { 143, 247, 150 }, { 145, 233, 151 }, + { 145, 249, 152 }, { 147, 235, 153 }, { 147, 251, 154 }, { 149, 237, 155 }, { 149, 253, 156 }, { 151, 239, 157 }, { 151, 255, 158 }, { 153, 241, 159 }, + { 155, 227, 160 }, { 155, 243, 161 }, { 157, 229, 162 }, { 157, 245, 163 }, { 159, 231, 164 }, { 159, 247, 165 }, { 161, 233, 166 }, { 161, 249, 167 }, + { 163, 235, 168 }, { 163, 251, 169 }, { 165, 237, 170 }, { 165, 253, 171 }, { 167, 239, 172 }, { 167, 255, 173 }, { 169, 241, 174 }, { 171, 227, 175 }, + { 171, 243, 176 }, { 173, 229, 177 }, { 173, 245, 178 }, { 175, 231, 179 }, { 175, 247, 180 }, { 177, 233, 181 }, { 177, 249, 182 }, { 179, 235, 183 }, + { 179, 251, 184 }, { 181, 237, 185 }, { 181, 253, 186 }, { 183, 239, 187 }, { 183, 255, 188 }, { 185, 241, 189 }, { 187, 227, 190 }, { 187, 243, 191 }, + { 189, 229, 192 }, { 189, 245, 193 }, { 191, 231, 194 }, { 191, 247, 195 }, { 193, 233, 196 }, { 193, 249, 197 }, { 195, 235, 198 }, { 195, 251, 199 }, + { 197, 237, 200 }, { 197, 253, 201 }, { 199, 239, 202 }, { 199, 255, 203 }, { 201, 241, 204 }, { 203, 227, 205 }, { 203, 243, 206 }, { 205, 229, 207 }, + { 205, 245, 208 }, { 207, 231, 209 }, { 207, 247, 210 }, { 209, 233, 211 }, { 209, 249, 212 }, { 211, 235, 213 }, { 211, 251, 214 }, { 213, 237, 215 }, + { 213, 253, 216 }, { 215, 239, 217 }, { 215, 255, 218 }, { 217, 241, 219 }, { 219, 227, 220 }, { 219, 243, 221 }, { 221, 229, 222 }, { 221, 245, 223 }, + { 223, 231, 224 }, { 223, 247, 225 }, { 225, 233, 226 }, { 225, 249, 227 }, { 227, 235, 228 }, { 227, 251, 229 }, { 229, 237, 230 }, { 229, 253, 231 }, + { 231, 239, 232 }, { 231, 255, 233 }, { 233, 241, 234 }, { 235, 227, 235 }, { 235, 243, 236 }, { 237, 229, 237 }, { 237, 245, 238 }, { 239, 231, 239 }, + { 239, 247, 240 }, { 241, 233, 241 }, { 241, 249, 242 }, { 243, 235, 243 }, { 243, 251, 244 }, { 245, 237, 245 }, { 245, 253, 246 }, { 247, 239, 247 }, + { 247, 255, 248 }, { 249, 241, 249 }, { 251, 227, 250 }, { 251, 243, 251 }, { 253, 229, 252 }, { 253, 245, 253 }, { 255, 231, 254 }, { 255, 247, 255 }, + } +}; + +Table g_mode6_p1_i2= +{ + 2, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 5, 2 }, { 1, 13, 3 }, { 1, 19, 4 }, { 1, 27, 5 }, { 1, 33, 6 }, { 1, 41, 7 }, + { 1, 49, 8 }, { 1, 55, 9 }, { 1, 63, 10 }, { 1, 69, 11 }, { 1, 77, 12 }, { 1, 83, 13 }, { 1, 91, 14 }, { 1, 97, 15 }, + { 1, 105, 16 }, { 1, 113, 17 }, { 1, 119, 18 }, { 1, 127, 19 }, { 1, 133, 20 }, { 1, 141, 21 }, { 1, 147, 22 }, { 1, 155, 23 }, + { 1, 161, 24 }, { 1, 169, 25 }, { 1, 177, 26 }, { 1, 183, 27 }, { 1, 191, 28 }, { 1, 197, 29 }, { 1, 205, 30 }, { 1, 211, 31 }, + { 1, 219, 32 }, { 1, 225, 33 }, { 1, 233, 34 }, { 1, 241, 35 }, { 1, 247, 36 }, { 1, 255, 37 }, { 3, 249, 38 }, { 5, 245, 39 }, + { 5, 251, 40 }, { 7, 247, 41 }, { 7, 253, 42 }, { 9, 249, 43 }, { 9, 255, 44 }, { 11, 251, 45 }, { 13, 245, 46 }, { 13, 253, 47 }, + { 15, 247, 48 }, { 15, 255, 49 }, { 17, 249, 50 }, { 19, 243, 51 }, { 19, 251, 52 }, { 21, 245, 53 }, { 21, 253, 54 }, { 23, 247, 55 }, + { 23, 255, 56 }, { 25, 249, 57 }, { 27, 245, 58 }, { 27, 251, 59 }, { 29, 247, 60 }, { 29, 253, 61 }, { 31, 249, 62 }, { 31, 255, 63 }, + { 33, 251, 64 }, { 35, 245, 65 }, { 35, 253, 66 }, { 37, 247, 67 }, { 37, 255, 68 }, { 39, 249, 69 }, { 41, 245, 70 }, { 41, 251, 71 }, + { 43, 247, 72 }, { 43, 253, 73 }, { 45, 249, 74 }, { 45, 255, 75 }, { 47, 251, 76 }, { 49, 245, 77 }, { 49, 253, 78 }, { 51, 247, 79 }, + { 51, 255, 80 }, { 53, 249, 81 }, { 55, 245, 82 }, { 55, 251, 83 }, { 57, 247, 84 }, { 57, 253, 85 }, { 59, 249, 86 }, { 59, 255, 87 }, + { 61, 251, 88 }, { 63, 245, 89 }, { 63, 253, 90 }, { 65, 247, 91 }, { 65, 255, 92 }, { 67, 249, 93 }, { 69, 245, 94 }, { 69, 251, 95 }, + { 71, 247, 96 }, { 71, 253, 97 }, { 73, 249, 98 }, { 73, 255, 99 }, { 75, 251, 100 }, { 77, 245, 101 }, { 77, 253, 102 }, { 79, 247, 103 }, + { 79, 255, 104 }, { 81, 249, 105 }, { 83, 243, 106 }, { 83, 251, 107 }, { 85, 245, 108 }, { 85, 253, 109 }, { 87, 247, 110 }, { 87, 255, 111 }, + { 89, 249, 112 }, { 91, 245, 113 }, { 91, 251, 114 }, { 93, 247, 115 }, { 93, 253, 116 }, { 95, 249, 117 }, { 95, 255, 118 }, { 97, 251, 119 }, + { 99, 245, 120 }, { 99, 253, 121 }, { 101, 247, 122 }, { 101, 255, 123 }, { 103, 249, 124 }, { 105, 245, 125 }, { 105, 251, 126 }, { 107, 247, 127 }, + { 107, 253, 128 }, { 109, 249, 129 }, { 109, 255, 130 }, { 111, 251, 131 }, { 113, 245, 132 }, { 113, 253, 133 }, { 115, 247, 134 }, { 115, 255, 135 }, + { 117, 249, 136 }, { 119, 245, 137 }, { 119, 251, 138 }, { 121, 247, 139 }, { 121, 253, 140 }, { 123, 249, 141 }, { 123, 255, 142 }, { 125, 251, 143 }, + { 127, 245, 144 }, { 127, 253, 145 }, { 129, 247, 146 }, { 129, 255, 147 }, { 131, 249, 148 }, { 133, 245, 149 }, { 133, 251, 150 }, { 135, 247, 151 }, + { 135, 253, 152 }, { 137, 249, 153 }, { 137, 255, 154 }, { 139, 251, 155 }, { 141, 245, 156 }, { 141, 253, 157 }, { 143, 247, 158 }, { 143, 255, 159 }, + { 145, 249, 160 }, { 147, 243, 161 }, { 147, 251, 162 }, { 149, 245, 163 }, { 149, 253, 164 }, { 151, 247, 165 }, { 151, 255, 166 }, { 153, 249, 167 }, + { 155, 245, 168 }, { 155, 251, 169 }, { 157, 247, 170 }, { 157, 253, 171 }, { 159, 249, 172 }, { 159, 255, 173 }, { 161, 251, 174 }, { 163, 245, 175 }, + { 163, 253, 176 }, { 165, 247, 177 }, { 165, 255, 178 }, { 167, 249, 179 }, { 169, 245, 180 }, { 169, 251, 181 }, { 171, 247, 182 }, { 171, 253, 183 }, + { 173, 249, 184 }, { 173, 255, 185 }, { 175, 251, 186 }, { 177, 245, 187 }, { 177, 253, 188 }, { 179, 247, 189 }, { 179, 255, 190 }, { 181, 249, 191 }, + { 183, 245, 192 }, { 183, 251, 193 }, { 185, 247, 194 }, { 185, 253, 195 }, { 187, 249, 196 }, { 187, 255, 197 }, { 189, 251, 198 }, { 191, 245, 199 }, + { 191, 253, 200 }, { 193, 247, 201 }, { 193, 255, 202 }, { 195, 249, 203 }, { 197, 245, 204 }, { 197, 251, 205 }, { 199, 247, 206 }, { 199, 253, 207 }, + { 201, 249, 208 }, { 201, 255, 209 }, { 203, 251, 210 }, { 205, 245, 211 }, { 205, 253, 212 }, { 207, 247, 213 }, { 207, 255, 214 }, { 209, 249, 215 }, + { 211, 243, 216 }, { 211, 251, 217 }, { 213, 245, 218 }, { 213, 253, 219 }, { 215, 247, 220 }, { 215, 255, 221 }, { 217, 249, 222 }, { 219, 245, 223 }, + { 219, 251, 224 }, { 221, 247, 225 }, { 221, 253, 226 }, { 223, 249, 227 }, { 223, 255, 228 }, { 225, 251, 229 }, { 227, 245, 230 }, { 227, 253, 231 }, + { 229, 247, 232 }, { 229, 255, 233 }, { 231, 249, 234 }, { 233, 245, 235 }, { 233, 251, 236 }, { 235, 247, 237 }, { 235, 253, 238 }, { 237, 249, 239 }, + { 237, 255, 240 }, { 239, 251, 241 }, { 241, 245, 242 }, { 241, 253, 243 }, { 243, 247, 244 }, { 243, 255, 245 }, { 245, 249, 246 }, { 247, 245, 247 }, + { 247, 251, 248 }, { 249, 247, 249 }, { 249, 253, 250 }, { 251, 249, 251 }, { 251, 255, 252 }, { 253, 251, 253 }, { 255, 245, 254 }, { 255, 253, 255 }, + } +}; + +Table g_mode6_p1_i3= +{ + 3, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 5, 2 }, { 1, 9, 3 }, { 1, 15, 4 }, { 1, 19, 5 }, { 1, 25, 6 }, { 1, 29, 7 }, + { 1, 33, 8 }, { 1, 39, 9 }, { 1, 43, 10 }, { 1, 49, 11 }, { 1, 53, 12 }, { 1, 59, 13 }, { 1, 63, 14 }, { 1, 69, 15 }, + { 1, 73, 16 }, { 1, 79, 17 }, { 1, 83, 18 }, { 1, 89, 19 }, { 1, 93, 20 }, { 1, 97, 21 }, { 1, 103, 22 }, { 1, 107, 23 }, + { 1, 113, 24 }, { 1, 117, 25 }, { 1, 123, 26 }, { 1, 127, 27 }, { 1, 133, 28 }, { 1, 137, 29 }, { 1, 143, 30 }, { 1, 147, 31 }, + { 1, 153, 32 }, { 1, 157, 33 }, { 1, 161, 34 }, { 1, 167, 35 }, { 1, 171, 36 }, { 1, 177, 37 }, { 1, 181, 38 }, { 1, 187, 39 }, + { 1, 191, 40 }, { 1, 197, 41 }, { 1, 201, 42 }, { 1, 207, 43 }, { 1, 211, 44 }, { 1, 217, 45 }, { 1, 221, 46 }, { 1, 225, 47 }, + { 1, 231, 48 }, { 1, 235, 49 }, { 1, 241, 50 }, { 1, 245, 51 }, { 1, 251, 52 }, { 1, 255, 53 }, { 3, 253, 54 }, { 5, 249, 55 }, + { 5, 255, 56 }, { 7, 251, 57 }, { 9, 249, 58 }, { 9, 253, 59 }, { 11, 251, 60 }, { 11, 255, 61 }, { 13, 253, 62 }, { 15, 249, 63 }, + { 15, 255, 64 }, { 17, 251, 65 }, { 19, 249, 66 }, { 19, 253, 67 }, { 21, 251, 68 }, { 21, 255, 69 }, { 23, 253, 70 }, { 25, 249, 71 }, + { 25, 255, 72 }, { 27, 251, 73 }, { 29, 249, 74 }, { 29, 253, 75 }, { 31, 251, 76 }, { 31, 255, 77 }, { 33, 253, 78 }, { 35, 251, 79 }, + { 35, 255, 80 }, { 37, 253, 81 }, { 39, 249, 82 }, { 39, 255, 83 }, { 41, 251, 84 }, { 43, 249, 85 }, { 43, 253, 86 }, { 45, 251, 87 }, + { 45, 255, 88 }, { 47, 253, 89 }, { 49, 249, 90 }, { 49, 255, 91 }, { 51, 251, 92 }, { 53, 249, 93 }, { 53, 253, 94 }, { 55, 251, 95 }, + { 55, 255, 96 }, { 57, 253, 97 }, { 59, 249, 98 }, { 59, 255, 99 }, { 61, 251, 100 }, { 63, 249, 101 }, { 63, 253, 102 }, { 65, 251, 103 }, + { 65, 255, 104 }, { 67, 253, 105 }, { 69, 249, 106 }, { 69, 255, 107 }, { 71, 251, 108 }, { 73, 249, 109 }, { 73, 253, 110 }, { 75, 251, 111 }, + { 75, 255, 112 }, { 77, 253, 113 }, { 79, 249, 114 }, { 79, 255, 115 }, { 81, 251, 116 }, { 83, 249, 117 }, { 83, 253, 118 }, { 85, 251, 119 }, + { 85, 255, 120 }, { 87, 253, 121 }, { 89, 249, 122 }, { 89, 255, 123 }, { 91, 251, 124 }, { 93, 249, 125 }, { 93, 253, 126 }, { 95, 251, 127 }, + { 95, 255, 128 }, { 97, 253, 129 }, { 99, 251, 130 }, { 99, 255, 131 }, { 101, 253, 132 }, { 103, 249, 133 }, { 103, 255, 134 }, { 105, 251, 135 }, + { 107, 249, 136 }, { 107, 253, 137 }, { 109, 251, 138 }, { 109, 255, 139 }, { 111, 253, 140 }, { 113, 249, 141 }, { 113, 255, 142 }, { 115, 251, 143 }, + { 117, 249, 144 }, { 117, 253, 145 }, { 119, 251, 146 }, { 119, 255, 147 }, { 121, 253, 148 }, { 123, 249, 149 }, { 123, 255, 150 }, { 125, 251, 151 }, + { 127, 249, 152 }, { 127, 253, 153 }, { 129, 251, 154 }, { 129, 255, 155 }, { 131, 253, 156 }, { 133, 249, 157 }, { 133, 255, 158 }, { 135, 251, 159 }, + { 137, 249, 160 }, { 137, 253, 161 }, { 139, 251, 162 }, { 139, 255, 163 }, { 141, 253, 164 }, { 143, 249, 165 }, { 143, 255, 166 }, { 145, 251, 167 }, + { 147, 249, 168 }, { 147, 253, 169 }, { 149, 251, 170 }, { 149, 255, 171 }, { 151, 253, 172 }, { 153, 249, 173 }, { 153, 255, 174 }, { 155, 251, 175 }, + { 157, 249, 176 }, { 157, 253, 177 }, { 159, 251, 178 }, { 159, 255, 179 }, { 161, 253, 180 }, { 163, 251, 181 }, { 163, 255, 182 }, { 165, 253, 183 }, + { 167, 249, 184 }, { 167, 255, 185 }, { 169, 251, 186 }, { 171, 249, 187 }, { 171, 253, 188 }, { 173, 251, 189 }, { 173, 255, 190 }, { 175, 253, 191 }, + { 177, 249, 192 }, { 177, 255, 193 }, { 179, 251, 194 }, { 181, 249, 195 }, { 181, 253, 196 }, { 183, 251, 197 }, { 183, 255, 198 }, { 185, 253, 199 }, + { 187, 249, 200 }, { 187, 255, 201 }, { 189, 251, 202 }, { 191, 249, 203 }, { 191, 253, 204 }, { 193, 251, 205 }, { 193, 255, 206 }, { 195, 253, 207 }, + { 197, 249, 208 }, { 197, 255, 209 }, { 199, 251, 210 }, { 201, 249, 211 }, { 201, 253, 212 }, { 203, 251, 213 }, { 203, 255, 214 }, { 205, 253, 215 }, + { 207, 249, 216 }, { 207, 255, 217 }, { 209, 251, 218 }, { 211, 249, 219 }, { 211, 253, 220 }, { 213, 251, 221 }, { 213, 255, 222 }, { 215, 253, 223 }, + { 217, 249, 224 }, { 217, 255, 225 }, { 219, 251, 226 }, { 221, 249, 227 }, { 221, 253, 228 }, { 223, 251, 229 }, { 223, 255, 230 }, { 225, 253, 231 }, + { 227, 251, 232 }, { 227, 255, 233 }, { 229, 253, 234 }, { 231, 249, 235 }, { 231, 255, 236 }, { 233, 251, 237 }, { 235, 249, 238 }, { 235, 253, 239 }, + { 237, 251, 240 }, { 237, 255, 241 }, { 239, 253, 242 }, { 241, 249, 243 }, { 241, 255, 244 }, { 243, 251, 245 }, { 245, 249, 246 }, { 245, 253, 247 }, + { 247, 251, 248 }, { 247, 255, 249 }, { 249, 253, 250 }, { 251, 249, 251 }, { 251, 255, 252 }, { 253, 251, 253 }, { 255, 249, 254 }, { 255, 253, 255 }, + } +}; + +Table g_mode6_p1_i4= +{ + 4, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 7, 3 }, { 1, 11, 4 }, { 1, 15, 5 }, { 1, 19, 6 }, { 1, 23, 7 }, + { 1, 27, 8 }, { 1, 31, 9 }, { 1, 33, 10 }, { 1, 37, 11 }, { 1, 41, 12 }, { 1, 45, 13 }, { 1, 49, 14 }, { 1, 53, 15 }, + { 1, 57, 16 }, { 1, 61, 17 }, { 1, 65, 18 }, { 1, 67, 19 }, { 1, 71, 20 }, { 1, 75, 21 }, { 1, 79, 22 }, { 1, 83, 23 }, + { 1, 87, 24 }, { 1, 91, 25 }, { 1, 95, 26 }, { 1, 97, 27 }, { 1, 101, 28 }, { 1, 105, 29 }, { 1, 109, 30 }, { 1, 113, 31 }, + { 1, 117, 32 }, { 1, 121, 33 }, { 1, 125, 34 }, { 1, 129, 35 }, { 1, 131, 36 }, { 1, 135, 37 }, { 1, 139, 38 }, { 1, 143, 39 }, + { 1, 147, 40 }, { 1, 151, 41 }, { 1, 155, 42 }, { 1, 159, 43 }, { 1, 161, 44 }, { 1, 165, 45 }, { 1, 169, 46 }, { 1, 173, 47 }, + { 1, 177, 48 }, { 1, 181, 49 }, { 1, 185, 50 }, { 1, 189, 51 }, { 1, 193, 52 }, { 1, 195, 53 }, { 1, 199, 54 }, { 1, 203, 55 }, + { 1, 207, 56 }, { 1, 211, 57 }, { 1, 215, 58 }, { 1, 219, 59 }, { 1, 223, 60 }, { 1, 225, 61 }, { 1, 229, 62 }, { 1, 233, 63 }, + { 1, 237, 64 }, { 1, 241, 65 }, { 1, 245, 66 }, { 1, 249, 67 }, { 1, 253, 68 }, { 3, 251, 69 }, { 3, 255, 70 }, { 5, 253, 71 }, + { 7, 251, 72 }, { 7, 255, 73 }, { 9, 253, 74 }, { 11, 251, 75 }, { 11, 255, 76 }, { 13, 253, 77 }, { 15, 251, 78 }, { 15, 255, 79 }, + { 17, 253, 80 }, { 19, 251, 81 }, { 19, 255, 82 }, { 21, 253, 83 }, { 23, 251, 84 }, { 23, 255, 85 }, { 25, 253, 86 }, { 27, 251, 87 }, + { 27, 255, 88 }, { 29, 253, 89 }, { 31, 253, 90 }, { 31, 255, 91 }, { 33, 255, 92 }, { 35, 253, 93 }, { 37, 251, 94 }, { 37, 255, 95 }, + { 39, 253, 96 }, { 41, 251, 97 }, { 41, 255, 98 }, { 43, 253, 99 }, { 45, 251, 100 }, { 45, 255, 101 }, { 47, 253, 102 }, { 49, 251, 103 }, + { 49, 255, 104 }, { 51, 253, 105 }, { 53, 251, 106 }, { 53, 255, 107 }, { 55, 253, 108 }, { 57, 251, 109 }, { 57, 255, 110 }, { 59, 253, 111 }, + { 61, 253, 112 }, { 61, 255, 113 }, { 63, 255, 114 }, { 65, 253, 115 }, { 67, 251, 116 }, { 67, 255, 117 }, { 69, 253, 118 }, { 71, 251, 119 }, + { 71, 255, 120 }, { 73, 253, 121 }, { 75, 251, 122 }, { 75, 255, 123 }, { 77, 253, 124 }, { 79, 251, 125 }, { 79, 255, 126 }, { 81, 253, 127 }, + { 83, 251, 128 }, { 83, 255, 129 }, { 85, 253, 130 }, { 87, 251, 131 }, { 87, 255, 132 }, { 89, 253, 133 }, { 91, 251, 134 }, { 91, 255, 135 }, + { 93, 253, 136 }, { 95, 253, 137 }, { 95, 255, 138 }, { 97, 255, 139 }, { 99, 253, 140 }, { 101, 251, 141 }, { 101, 255, 142 }, { 103, 253, 143 }, + { 105, 251, 144 }, { 105, 255, 145 }, { 107, 253, 146 }, { 109, 251, 147 }, { 109, 255, 148 }, { 111, 253, 149 }, { 113, 251, 150 }, { 113, 255, 151 }, + { 115, 253, 152 }, { 117, 251, 153 }, { 117, 255, 154 }, { 119, 253, 155 }, { 121, 251, 156 }, { 121, 255, 157 }, { 123, 253, 158 }, { 125, 253, 159 }, + { 125, 255, 160 }, { 127, 255, 161 }, { 129, 253, 162 }, { 131, 251, 163 }, { 131, 255, 164 }, { 133, 253, 165 }, { 135, 251, 166 }, { 135, 255, 167 }, + { 137, 253, 168 }, { 139, 251, 169 }, { 139, 255, 170 }, { 141, 253, 171 }, { 143, 251, 172 }, { 143, 255, 173 }, { 145, 253, 174 }, { 147, 251, 175 }, + { 147, 255, 176 }, { 149, 253, 177 }, { 151, 251, 178 }, { 151, 255, 179 }, { 153, 253, 180 }, { 155, 251, 181 }, { 155, 255, 182 }, { 157, 253, 183 }, + { 159, 253, 184 }, { 159, 255, 185 }, { 161, 255, 186 }, { 163, 253, 187 }, { 165, 251, 188 }, { 165, 255, 189 }, { 167, 253, 190 }, { 169, 251, 191 }, + { 169, 255, 192 }, { 171, 253, 193 }, { 173, 251, 194 }, { 173, 255, 195 }, { 175, 253, 196 }, { 177, 251, 197 }, { 177, 255, 198 }, { 179, 253, 199 }, + { 181, 251, 200 }, { 181, 255, 201 }, { 183, 253, 202 }, { 185, 251, 203 }, { 185, 255, 204 }, { 187, 253, 205 }, { 189, 253, 206 }, { 189, 255, 207 }, + { 191, 255, 208 }, { 193, 253, 209 }, { 195, 251, 210 }, { 195, 255, 211 }, { 197, 253, 212 }, { 199, 251, 213 }, { 199, 255, 214 }, { 201, 253, 215 }, + { 203, 251, 216 }, { 203, 255, 217 }, { 205, 253, 218 }, { 207, 251, 219 }, { 207, 255, 220 }, { 209, 253, 221 }, { 211, 251, 222 }, { 211, 255, 223 }, + { 213, 253, 224 }, { 215, 251, 225 }, { 215, 255, 226 }, { 217, 253, 227 }, { 219, 251, 228 }, { 219, 255, 229 }, { 221, 253, 230 }, { 223, 253, 231 }, + { 223, 255, 232 }, { 225, 255, 233 }, { 227, 253, 234 }, { 229, 251, 235 }, { 229, 255, 236 }, { 231, 253, 237 }, { 233, 251, 238 }, { 233, 255, 239 }, + { 235, 253, 240 }, { 237, 251, 241 }, { 237, 255, 242 }, { 239, 253, 243 }, { 241, 251, 244 }, { 241, 255, 245 }, { 243, 253, 246 }, { 245, 251, 247 }, + { 245, 255, 248 }, { 247, 253, 249 }, { 249, 251, 250 }, { 249, 255, 251 }, { 251, 253, 252 }, { 253, 253, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode6_p1_i5= +{ + 5, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 7, 3 }, { 1, 9, 4 }, { 1, 13, 5 }, { 1, 15, 6 }, { 1, 19, 7 }, + { 1, 21, 8 }, { 1, 25, 9 }, { 1, 27, 10 }, { 1, 31, 11 }, { 1, 33, 12 }, { 1, 37, 13 }, { 1, 41, 14 }, { 1, 43, 15 }, + { 1, 47, 16 }, { 1, 49, 17 }, { 1, 53, 18 }, { 1, 55, 19 }, { 1, 59, 20 }, { 1, 61, 21 }, { 1, 65, 22 }, { 1, 67, 23 }, + { 1, 71, 24 }, { 1, 73, 25 }, { 1, 77, 26 }, { 1, 79, 27 }, { 1, 83, 28 }, { 1, 85, 29 }, { 1, 89, 30 }, { 1, 91, 31 }, + { 1, 95, 32 }, { 1, 97, 33 }, { 1, 101, 34 }, { 1, 105, 35 }, { 1, 107, 36 }, { 1, 111, 37 }, { 1, 113, 38 }, { 1, 117, 39 }, + { 1, 119, 40 }, { 1, 123, 41 }, { 1, 125, 42 }, { 1, 129, 43 }, { 1, 131, 44 }, { 1, 135, 45 }, { 1, 137, 46 }, { 1, 141, 47 }, + { 1, 143, 48 }, { 1, 147, 49 }, { 1, 149, 50 }, { 1, 153, 51 }, { 1, 155, 52 }, { 1, 159, 53 }, { 1, 161, 54 }, { 1, 165, 55 }, + { 1, 169, 56 }, { 1, 171, 57 }, { 1, 175, 58 }, { 1, 177, 59 }, { 1, 181, 60 }, { 1, 183, 61 }, { 1, 187, 62 }, { 1, 189, 63 }, + { 1, 193, 64 }, { 1, 195, 65 }, { 1, 199, 66 }, { 1, 201, 67 }, { 1, 205, 68 }, { 1, 207, 69 }, { 1, 211, 70 }, { 1, 213, 71 }, + { 1, 217, 72 }, { 1, 219, 73 }, { 1, 223, 74 }, { 1, 225, 75 }, { 1, 229, 76 }, { 1, 233, 77 }, { 1, 235, 78 }, { 1, 239, 79 }, + { 1, 241, 80 }, { 1, 245, 81 }, { 1, 247, 82 }, { 1, 251, 83 }, { 1, 253, 84 }, { 3, 253, 85 }, { 3, 255, 86 }, { 5, 255, 87 }, + { 7, 253, 88 }, { 9, 253, 89 }, { 9, 255, 90 }, { 11, 255, 91 }, { 13, 253, 92 }, { 15, 253, 93 }, { 15, 255, 94 }, { 17, 255, 95 }, + { 19, 253, 96 }, { 21, 253, 97 }, { 21, 255, 98 }, { 23, 255, 99 }, { 25, 253, 100 }, { 27, 251, 101 }, { 27, 255, 102 }, { 29, 253, 103 }, + { 31, 253, 104 }, { 31, 255, 105 }, { 33, 255, 106 }, { 35, 253, 107 }, { 37, 253, 108 }, { 37, 255, 109 }, { 39, 255, 110 }, { 41, 253, 111 }, + { 43, 253, 112 }, { 43, 255, 113 }, { 45, 255, 114 }, { 47, 253, 115 }, { 49, 253, 116 }, { 49, 255, 117 }, { 51, 255, 118 }, { 53, 253, 119 }, + { 55, 253, 120 }, { 55, 255, 121 }, { 57, 255, 122 }, { 59, 253, 123 }, { 61, 253, 124 }, { 61, 255, 125 }, { 63, 255, 126 }, { 65, 253, 127 }, + { 67, 253, 128 }, { 67, 255, 129 }, { 69, 255, 130 }, { 71, 253, 131 }, { 73, 253, 132 }, { 73, 255, 133 }, { 75, 255, 134 }, { 77, 253, 135 }, + { 79, 253, 136 }, { 79, 255, 137 }, { 81, 255, 138 }, { 83, 253, 139 }, { 85, 253, 140 }, { 85, 255, 141 }, { 87, 255, 142 }, { 89, 253, 143 }, + { 91, 251, 144 }, { 91, 255, 145 }, { 93, 253, 146 }, { 95, 253, 147 }, { 95, 255, 148 }, { 97, 255, 149 }, { 99, 253, 150 }, { 101, 253, 151 }, + { 101, 255, 152 }, { 103, 255, 153 }, { 105, 253, 154 }, { 107, 253, 155 }, { 107, 255, 156 }, { 109, 255, 157 }, { 111, 253, 158 }, { 113, 253, 159 }, + { 113, 255, 160 }, { 115, 255, 161 }, { 117, 253, 162 }, { 119, 253, 163 }, { 119, 255, 164 }, { 121, 255, 165 }, { 123, 253, 166 }, { 125, 253, 167 }, + { 125, 255, 168 }, { 127, 255, 169 }, { 129, 253, 170 }, { 131, 253, 171 }, { 131, 255, 172 }, { 133, 255, 173 }, { 135, 253, 174 }, { 137, 253, 175 }, + { 137, 255, 176 }, { 139, 255, 177 }, { 141, 253, 178 }, { 143, 253, 179 }, { 143, 255, 180 }, { 145, 255, 181 }, { 147, 253, 182 }, { 149, 253, 183 }, + { 149, 255, 184 }, { 151, 255, 185 }, { 153, 253, 186 }, { 155, 251, 187 }, { 155, 255, 188 }, { 157, 253, 189 }, { 159, 253, 190 }, { 159, 255, 191 }, + { 161, 255, 192 }, { 163, 253, 193 }, { 165, 253, 194 }, { 165, 255, 195 }, { 167, 255, 196 }, { 169, 253, 197 }, { 171, 253, 198 }, { 171, 255, 199 }, + { 173, 255, 200 }, { 175, 253, 201 }, { 177, 253, 202 }, { 177, 255, 203 }, { 179, 255, 204 }, { 181, 253, 205 }, { 183, 253, 206 }, { 183, 255, 207 }, + { 185, 255, 208 }, { 187, 253, 209 }, { 189, 253, 210 }, { 189, 255, 211 }, { 191, 255, 212 }, { 193, 253, 213 }, { 195, 253, 214 }, { 195, 255, 215 }, + { 197, 255, 216 }, { 199, 253, 217 }, { 201, 253, 218 }, { 201, 255, 219 }, { 203, 255, 220 }, { 205, 253, 221 }, { 207, 253, 222 }, { 207, 255, 223 }, + { 209, 255, 224 }, { 211, 253, 225 }, { 213, 253, 226 }, { 213, 255, 227 }, { 215, 255, 228 }, { 217, 253, 229 }, { 219, 251, 230 }, { 219, 255, 231 }, + { 221, 253, 232 }, { 223, 253, 233 }, { 223, 255, 234 }, { 225, 255, 235 }, { 227, 253, 236 }, { 229, 253, 237 }, { 229, 255, 238 }, { 231, 255, 239 }, + { 233, 253, 240 }, { 235, 253, 241 }, { 235, 255, 242 }, { 237, 255, 243 }, { 239, 253, 244 }, { 241, 253, 245 }, { 241, 255, 246 }, { 243, 255, 247 }, + { 245, 253, 248 }, { 247, 253, 249 }, { 247, 255, 250 }, { 249, 255, 251 }, { 251, 253, 252 }, { 253, 253, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode6_p1_i6= +{ + 6, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 5, 3 }, { 1, 9, 4 }, { 1, 11, 5 }, { 1, 13, 6 }, { 1, 15, 7 }, + { 1, 17, 8 }, { 1, 21, 9 }, { 1, 23, 10 }, { 1, 25, 11 }, { 1, 27, 12 }, { 1, 31, 13 }, { 1, 33, 14 }, { 1, 35, 15 }, + { 1, 37, 16 }, { 1, 41, 17 }, { 1, 43, 18 }, { 1, 45, 19 }, { 1, 47, 20 }, { 1, 49, 21 }, { 1, 53, 22 }, { 1, 55, 23 }, + { 1, 57, 24 }, { 1, 59, 25 }, { 1, 63, 26 }, { 1, 65, 27 }, { 1, 67, 28 }, { 1, 69, 29 }, { 1, 73, 30 }, { 1, 75, 31 }, + { 1, 77, 32 }, { 1, 79, 33 }, { 1, 81, 34 }, { 1, 85, 35 }, { 1, 87, 36 }, { 1, 89, 37 }, { 1, 91, 38 }, { 1, 95, 39 }, + { 1, 97, 40 }, { 1, 99, 41 }, { 1, 101, 42 }, { 1, 105, 43 }, { 1, 107, 44 }, { 1, 109, 45 }, { 1, 111, 46 }, { 1, 113, 47 }, + { 1, 117, 48 }, { 1, 119, 49 }, { 1, 121, 50 }, { 1, 123, 51 }, { 1, 127, 52 }, { 1, 129, 53 }, { 1, 131, 54 }, { 1, 133, 55 }, + { 1, 137, 56 }, { 1, 139, 57 }, { 1, 141, 58 }, { 1, 143, 59 }, { 1, 145, 60 }, { 1, 149, 61 }, { 1, 151, 62 }, { 1, 153, 63 }, + { 1, 155, 64 }, { 1, 159, 65 }, { 1, 161, 66 }, { 1, 163, 67 }, { 1, 165, 68 }, { 1, 169, 69 }, { 1, 171, 70 }, { 1, 173, 71 }, + { 1, 175, 72 }, { 1, 177, 73 }, { 1, 181, 74 }, { 1, 183, 75 }, { 1, 185, 76 }, { 1, 187, 77 }, { 1, 191, 78 }, { 1, 193, 79 }, + { 1, 195, 80 }, { 1, 197, 81 }, { 1, 201, 82 }, { 1, 203, 83 }, { 1, 205, 84 }, { 1, 207, 85 }, { 1, 209, 86 }, { 1, 213, 87 }, + { 1, 215, 88 }, { 1, 217, 89 }, { 1, 219, 90 }, { 1, 223, 91 }, { 1, 225, 92 }, { 1, 227, 93 }, { 1, 229, 94 }, { 1, 233, 95 }, + { 1, 235, 96 }, { 1, 237, 97 }, { 1, 239, 98 }, { 1, 241, 99 }, { 1, 245, 100 }, { 1, 247, 101 }, { 1, 249, 102 }, { 1, 251, 103 }, + { 1, 255, 104 }, { 3, 253, 105 }, { 5, 253, 106 }, { 5, 255, 107 }, { 7, 255, 108 }, { 9, 255, 109 }, { 11, 255, 110 }, { 13, 253, 111 }, + { 15, 253, 112 }, { 15, 255, 113 }, { 17, 255, 114 }, { 19, 255, 115 }, { 21, 255, 116 }, { 23, 255, 117 }, { 25, 253, 118 }, { 27, 253, 119 }, + { 27, 255, 120 }, { 29, 255, 121 }, { 31, 255, 122 }, { 33, 255, 123 }, { 35, 253, 124 }, { 37, 253, 125 }, { 37, 255, 126 }, { 39, 255, 127 }, + { 41, 255, 128 }, { 43, 255, 129 }, { 45, 253, 130 }, { 47, 253, 131 }, { 47, 255, 132 }, { 49, 255, 133 }, { 51, 255, 134 }, { 53, 255, 135 }, + { 55, 255, 136 }, { 57, 253, 137 }, { 59, 253, 138 }, { 59, 255, 139 }, { 61, 255, 140 }, { 63, 255, 141 }, { 65, 255, 142 }, { 67, 253, 143 }, + { 69, 253, 144 }, { 69, 255, 145 }, { 71, 255, 146 }, { 73, 255, 147 }, { 75, 255, 148 }, { 77, 253, 149 }, { 79, 253, 150 }, { 79, 255, 151 }, + { 81, 255, 152 }, { 83, 255, 153 }, { 85, 255, 154 }, { 87, 255, 155 }, { 89, 253, 156 }, { 91, 253, 157 }, { 91, 255, 158 }, { 93, 255, 159 }, + { 95, 255, 160 }, { 97, 255, 161 }, { 99, 253, 162 }, { 101, 253, 163 }, { 101, 255, 164 }, { 103, 255, 165 }, { 105, 255, 166 }, { 107, 255, 167 }, + { 109, 253, 168 }, { 111, 253, 169 }, { 111, 255, 170 }, { 113, 255, 171 }, { 115, 255, 172 }, { 117, 255, 173 }, { 119, 255, 174 }, { 121, 253, 175 }, + { 123, 253, 176 }, { 123, 255, 177 }, { 125, 255, 178 }, { 127, 255, 179 }, { 129, 255, 180 }, { 131, 253, 181 }, { 133, 253, 182 }, { 133, 255, 183 }, + { 135, 255, 184 }, { 137, 255, 185 }, { 139, 255, 186 }, { 141, 253, 187 }, { 143, 253, 188 }, { 143, 255, 189 }, { 145, 255, 190 }, { 147, 255, 191 }, + { 149, 255, 192 }, { 151, 255, 193 }, { 153, 253, 194 }, { 155, 253, 195 }, { 155, 255, 196 }, { 157, 255, 197 }, { 159, 255, 198 }, { 161, 255, 199 }, + { 163, 253, 200 }, { 165, 253, 201 }, { 165, 255, 202 }, { 167, 255, 203 }, { 169, 255, 204 }, { 171, 255, 205 }, { 173, 253, 206 }, { 175, 253, 207 }, + { 175, 255, 208 }, { 177, 255, 209 }, { 179, 255, 210 }, { 181, 255, 211 }, { 183, 255, 212 }, { 185, 253, 213 }, { 187, 253, 214 }, { 187, 255, 215 }, + { 189, 255, 216 }, { 191, 255, 217 }, { 193, 255, 218 }, { 195, 253, 219 }, { 197, 253, 220 }, { 197, 255, 221 }, { 199, 255, 222 }, { 201, 255, 223 }, + { 203, 255, 224 }, { 205, 253, 225 }, { 207, 253, 226 }, { 207, 255, 227 }, { 209, 255, 228 }, { 211, 255, 229 }, { 213, 255, 230 }, { 215, 255, 231 }, + { 217, 253, 232 }, { 219, 253, 233 }, { 219, 255, 234 }, { 221, 255, 235 }, { 223, 255, 236 }, { 225, 255, 237 }, { 227, 253, 238 }, { 229, 253, 239 }, + { 229, 255, 240 }, { 231, 255, 241 }, { 233, 255, 242 }, { 235, 255, 243 }, { 237, 253, 244 }, { 239, 253, 245 }, { 239, 255, 246 }, { 241, 255, 247 }, + { 243, 255, 248 }, { 245, 255, 249 }, { 247, 255, 250 }, { 249, 253, 251 }, { 251, 253, 252 }, { 251, 255, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode6_p1_i7= +{ + 7, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 5, 3 }, { 1, 7, 4 }, { 1, 9, 5 }, { 1, 11, 6 }, { 1, 13, 7 }, + { 1, 15, 8 }, { 1, 17, 9 }, { 1, 21, 10 }, { 1, 23, 11 }, { 1, 25, 12 }, { 1, 27, 13 }, { 1, 29, 14 }, { 1, 31, 15 }, + { 1, 33, 16 }, { 1, 35, 17 }, { 1, 37, 18 }, { 1, 39, 19 }, { 1, 41, 20 }, { 1, 43, 21 }, { 1, 45, 22 }, { 1, 47, 23 }, + { 1, 49, 24 }, { 1, 53, 25 }, { 1, 55, 26 }, { 1, 57, 27 }, { 1, 59, 28 }, { 1, 61, 29 }, { 1, 63, 30 }, { 1, 65, 31 }, + { 1, 67, 32 }, { 1, 69, 33 }, { 1, 71, 34 }, { 1, 73, 35 }, { 1, 75, 36 }, { 1, 77, 37 }, { 1, 79, 38 }, { 1, 81, 39 }, + { 1, 85, 40 }, { 1, 87, 41 }, { 1, 89, 42 }, { 1, 91, 43 }, { 1, 93, 44 }, { 1, 95, 45 }, { 1, 97, 46 }, { 1, 99, 47 }, + { 1, 101, 48 }, { 1, 103, 49 }, { 1, 105, 50 }, { 1, 107, 51 }, { 1, 109, 52 }, { 1, 111, 53 }, { 1, 113, 54 }, { 1, 117, 55 }, + { 1, 119, 56 }, { 1, 121, 57 }, { 1, 123, 58 }, { 1, 125, 59 }, { 1, 127, 60 }, { 1, 129, 61 }, { 1, 131, 62 }, { 1, 133, 63 }, + { 1, 135, 64 }, { 1, 137, 65 }, { 1, 139, 66 }, { 1, 141, 67 }, { 1, 143, 68 }, { 1, 145, 69 }, { 1, 149, 70 }, { 1, 151, 71 }, + { 1, 153, 72 }, { 1, 155, 73 }, { 1, 157, 74 }, { 1, 159, 75 }, { 1, 161, 76 }, { 1, 163, 77 }, { 1, 165, 78 }, { 1, 167, 79 }, + { 1, 169, 80 }, { 1, 171, 81 }, { 1, 173, 82 }, { 1, 175, 83 }, { 1, 177, 84 }, { 1, 181, 85 }, { 1, 183, 86 }, { 1, 185, 87 }, + { 1, 187, 88 }, { 1, 189, 89 }, { 1, 191, 90 }, { 1, 193, 91 }, { 1, 195, 92 }, { 1, 197, 93 }, { 1, 199, 94 }, { 1, 201, 95 }, + { 1, 203, 96 }, { 1, 205, 97 }, { 1, 207, 98 }, { 1, 209, 99 }, { 1, 213, 100 }, { 1, 215, 101 }, { 1, 217, 102 }, { 1, 219, 103 }, + { 1, 221, 104 }, { 1, 223, 105 }, { 1, 225, 106 }, { 1, 227, 107 }, { 1, 229, 108 }, { 1, 231, 109 }, { 1, 233, 110 }, { 1, 235, 111 }, + { 1, 237, 112 }, { 1, 239, 113 }, { 1, 241, 114 }, { 1, 245, 115 }, { 1, 247, 116 }, { 1, 249, 117 }, { 1, 251, 118 }, { 1, 253, 119 }, + { 1, 255, 120 }, { 3, 255, 121 }, { 5, 255, 122 }, { 7, 255, 123 }, { 9, 255, 124 }, { 11, 255, 125 }, { 13, 253, 126 }, { 15, 253, 127 }, + { 15, 255, 128 }, { 17, 255, 129 }, { 19, 255, 130 }, { 21, 255, 131 }, { 23, 255, 132 }, { 25, 255, 133 }, { 27, 255, 134 }, { 29, 255, 135 }, + { 31, 255, 136 }, { 33, 255, 137 }, { 35, 255, 138 }, { 37, 255, 139 }, { 39, 255, 140 }, { 41, 255, 141 }, { 43, 255, 142 }, { 45, 253, 143 }, + { 47, 253, 144 }, { 47, 255, 145 }, { 49, 255, 146 }, { 51, 255, 147 }, { 53, 255, 148 }, { 55, 255, 149 }, { 57, 255, 150 }, { 59, 255, 151 }, + { 61, 255, 152 }, { 63, 255, 153 }, { 65, 255, 154 }, { 67, 255, 155 }, { 69, 255, 156 }, { 71, 255, 157 }, { 73, 255, 158 }, { 75, 255, 159 }, + { 77, 253, 160 }, { 79, 253, 161 }, { 79, 255, 162 }, { 81, 255, 163 }, { 83, 255, 164 }, { 85, 255, 165 }, { 87, 255, 166 }, { 89, 255, 167 }, + { 91, 255, 168 }, { 93, 255, 169 }, { 95, 255, 170 }, { 97, 255, 171 }, { 99, 255, 172 }, { 101, 255, 173 }, { 103, 255, 174 }, { 105, 255, 175 }, + { 107, 255, 176 }, { 109, 253, 177 }, { 111, 253, 178 }, { 111, 255, 179 }, { 113, 255, 180 }, { 115, 255, 181 }, { 117, 255, 182 }, { 119, 255, 183 }, + { 121, 255, 184 }, { 123, 255, 185 }, { 125, 255, 186 }, { 127, 255, 187 }, { 129, 255, 188 }, { 131, 255, 189 }, { 133, 255, 190 }, { 135, 255, 191 }, + { 137, 255, 192 }, { 139, 255, 193 }, { 141, 253, 194 }, { 143, 253, 195 }, { 143, 255, 196 }, { 145, 255, 197 }, { 147, 255, 198 }, { 149, 255, 199 }, + { 151, 255, 200 }, { 153, 255, 201 }, { 155, 255, 202 }, { 157, 255, 203 }, { 159, 255, 204 }, { 161, 255, 205 }, { 163, 255, 206 }, { 165, 255, 207 }, + { 167, 255, 208 }, { 169, 255, 209 }, { 171, 255, 210 }, { 173, 253, 211 }, { 175, 253, 212 }, { 175, 255, 213 }, { 177, 255, 214 }, { 179, 255, 215 }, + { 181, 255, 216 }, { 183, 255, 217 }, { 185, 255, 218 }, { 187, 255, 219 }, { 189, 255, 220 }, { 191, 255, 221 }, { 193, 255, 222 }, { 195, 255, 223 }, + { 197, 255, 224 }, { 199, 255, 225 }, { 201, 255, 226 }, { 203, 255, 227 }, { 205, 253, 228 }, { 207, 253, 229 }, { 207, 255, 230 }, { 209, 255, 231 }, + { 211, 255, 232 }, { 213, 255, 233 }, { 215, 255, 234 }, { 217, 255, 235 }, { 219, 255, 236 }, { 221, 255, 237 }, { 223, 255, 238 }, { 225, 255, 239 }, + { 227, 255, 240 }, { 229, 255, 241 }, { 231, 255, 242 }, { 233, 255, 243 }, { 235, 255, 244 }, { 237, 253, 245 }, { 239, 253, 246 }, { 239, 255, 247 }, + { 241, 255, 248 }, { 243, 255, 249 }, { 245, 255, 250 }, { 247, 255, 251 }, { 249, 255, 252 }, { 251, 255, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode7_p00= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 6, 2 }, { 0, 8, 3 }, { 0, 12, 4 }, { 0, 14, 5 }, { 0, 18, 6 }, { 0, 20, 7 }, + { 0, 24, 8 }, { 0, 26, 9 }, { 0, 30, 10 }, { 0, 32, 11 }, { 0, 36, 12 }, { 0, 40, 13 }, { 0, 42, 14 }, { 0, 46, 15 }, + { 0, 48, 16 }, { 0, 52, 17 }, { 0, 54, 18 }, { 0, 58, 19 }, { 0, 60, 20 }, { 0, 64, 21 }, { 0, 66, 22 }, { 0, 70, 23 }, + { 0, 72, 24 }, { 0, 76, 25 }, { 0, 78, 26 }, { 0, 82, 27 }, { 0, 84, 28 }, { 0, 88, 29 }, { 0, 90, 30 }, { 0, 94, 31 }, + { 0, 96, 32 }, { 0, 100, 33 }, { 0, 104, 34 }, { 0, 106, 35 }, { 0, 110, 36 }, { 0, 112, 37 }, { 0, 116, 38 }, { 0, 118, 39 }, + { 0, 122, 40 }, { 0, 124, 41 }, { 0, 128, 42 }, { 0, 130, 43 }, { 0, 134, 44 }, { 0, 136, 45 }, { 0, 140, 46 }, { 0, 142, 47 }, + { 0, 146, 48 }, { 0, 148, 49 }, { 0, 152, 50 }, { 0, 154, 51 }, { 0, 158, 52 }, { 0, 160, 53 }, { 0, 164, 54 }, { 0, 168, 55 }, + { 0, 170, 56 }, { 0, 174, 57 }, { 0, 176, 58 }, { 0, 180, 59 }, { 0, 182, 60 }, { 0, 186, 61 }, { 0, 188, 62 }, { 0, 192, 63 }, + { 0, 194, 64 }, { 0, 198, 65 }, { 0, 200, 66 }, { 0, 204, 67 }, { 0, 206, 68 }, { 0, 210, 69 }, { 0, 212, 70 }, { 0, 216, 71 }, + { 0, 218, 72 }, { 0, 222, 73 }, { 0, 224, 74 }, { 0, 228, 75 }, { 0, 232, 76 }, { 0, 234, 77 }, { 0, 238, 78 }, { 0, 240, 79 }, + { 0, 244, 80 }, { 0, 246, 81 }, { 0, 250, 82 }, { 0, 252, 83 }, { 2, 252, 84 }, { 2, 254, 85 }, { 4, 254, 86 }, { 6, 252, 87 }, + { 8, 252, 88 }, { 8, 254, 89 }, { 10, 254, 90 }, { 12, 252, 91 }, { 14, 252, 92 }, { 14, 254, 93 }, { 16, 254, 94 }, { 18, 252, 95 }, + { 20, 252, 96 }, { 20, 254, 97 }, { 22, 254, 98 }, { 24, 252, 99 }, { 26, 250, 100 }, { 26, 254, 101 }, { 28, 252, 102 }, { 30, 252, 103 }, + { 30, 254, 104 }, { 32, 254, 105 }, { 34, 252, 106 }, { 36, 252, 107 }, { 36, 254, 108 }, { 38, 254, 109 }, { 40, 252, 110 }, { 42, 252, 111 }, + { 42, 254, 112 }, { 44, 254, 113 }, { 46, 252, 114 }, { 48, 252, 115 }, { 48, 254, 116 }, { 50, 254, 117 }, { 52, 252, 118 }, { 54, 252, 119 }, + { 54, 254, 120 }, { 56, 254, 121 }, { 58, 252, 122 }, { 60, 252, 123 }, { 60, 254, 124 }, { 62, 254, 125 }, { 64, 252, 126 }, { 66, 252, 127 }, + { 66, 254, 128 }, { 68, 254, 129 }, { 70, 252, 130 }, { 72, 252, 131 }, { 72, 254, 132 }, { 74, 254, 133 }, { 76, 252, 134 }, { 78, 252, 135 }, + { 78, 254, 136 }, { 80, 254, 137 }, { 82, 252, 138 }, { 84, 252, 139 }, { 84, 254, 140 }, { 86, 254, 141 }, { 88, 252, 142 }, { 90, 250, 143 }, + { 90, 254, 144 }, { 92, 252, 145 }, { 94, 252, 146 }, { 94, 254, 147 }, { 96, 254, 148 }, { 98, 252, 149 }, { 100, 252, 150 }, { 100, 254, 151 }, + { 102, 254, 152 }, { 104, 252, 153 }, { 106, 252, 154 }, { 106, 254, 155 }, { 108, 254, 156 }, { 110, 252, 157 }, { 112, 252, 158 }, { 112, 254, 159 }, + { 114, 254, 160 }, { 116, 252, 161 }, { 118, 252, 162 }, { 118, 254, 163 }, { 120, 254, 164 }, { 122, 252, 165 }, { 124, 252, 166 }, { 124, 254, 167 }, + { 126, 254, 168 }, { 128, 252, 169 }, { 130, 252, 170 }, { 130, 254, 171 }, { 132, 254, 172 }, { 134, 252, 173 }, { 136, 252, 174 }, { 136, 254, 175 }, + { 138, 254, 176 }, { 140, 252, 177 }, { 142, 252, 178 }, { 142, 254, 179 }, { 144, 254, 180 }, { 146, 252, 181 }, { 148, 252, 182 }, { 148, 254, 183 }, + { 150, 254, 184 }, { 152, 252, 185 }, { 154, 250, 186 }, { 154, 254, 187 }, { 156, 252, 188 }, { 158, 252, 189 }, { 158, 254, 190 }, { 160, 254, 191 }, + { 162, 252, 192 }, { 164, 252, 193 }, { 164, 254, 194 }, { 166, 254, 195 }, { 168, 252, 196 }, { 170, 252, 197 }, { 170, 254, 198 }, { 172, 254, 199 }, + { 174, 252, 200 }, { 176, 252, 201 }, { 176, 254, 202 }, { 178, 254, 203 }, { 180, 252, 204 }, { 182, 252, 205 }, { 182, 254, 206 }, { 184, 254, 207 }, + { 186, 252, 208 }, { 188, 252, 209 }, { 188, 254, 210 }, { 190, 254, 211 }, { 192, 252, 212 }, { 194, 252, 213 }, { 194, 254, 214 }, { 196, 254, 215 }, + { 198, 252, 216 }, { 200, 252, 217 }, { 200, 254, 218 }, { 202, 254, 219 }, { 204, 252, 220 }, { 206, 252, 221 }, { 206, 254, 222 }, { 208, 254, 223 }, + { 210, 252, 224 }, { 212, 252, 225 }, { 212, 254, 226 }, { 214, 254, 227 }, { 216, 252, 228 }, { 218, 250, 229 }, { 218, 254, 230 }, { 220, 252, 231 }, + { 222, 252, 232 }, { 222, 254, 233 }, { 224, 254, 234 }, { 226, 252, 235 }, { 228, 252, 236 }, { 228, 254, 237 }, { 230, 254, 238 }, { 232, 252, 239 }, + { 234, 252, 240 }, { 234, 254, 241 }, { 236, 254, 242 }, { 238, 252, 243 }, { 240, 252, 244 }, { 240, 254, 245 }, { 242, 254, 246 }, { 244, 252, 247 }, + { 246, 252, 248 }, { 246, 254, 249 }, { 248, 254, 250 }, { 250, 252, 251 }, { 252, 252, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode7_p01= +{ + 1, + 2, + { + { 0, 1, 0 }, { 0, 3, 1 }, { 0, 5, 2 }, { 0, 9, 3 }, { 0, 11, 4 }, { 0, 15, 5 }, { 0, 17, 6 }, { 0, 21, 7 }, + { 0, 23, 8 }, { 0, 27, 9 }, { 0, 29, 10 }, { 0, 33, 11 }, { 0, 37, 12 }, { 0, 39, 13 }, { 0, 43, 14 }, { 0, 45, 15 }, + { 0, 49, 16 }, { 0, 51, 17 }, { 0, 55, 18 }, { 0, 57, 19 }, { 0, 61, 20 }, { 0, 63, 21 }, { 0, 67, 22 }, { 0, 69, 23 }, + { 0, 73, 24 }, { 0, 75, 25 }, { 0, 79, 26 }, { 0, 81, 27 }, { 0, 85, 28 }, { 0, 87, 29 }, { 0, 91, 30 }, { 0, 93, 31 }, + { 0, 97, 32 }, { 0, 101, 33 }, { 0, 103, 34 }, { 0, 107, 35 }, { 0, 109, 36 }, { 0, 113, 37 }, { 0, 115, 38 }, { 0, 119, 39 }, + { 0, 121, 40 }, { 0, 125, 41 }, { 0, 127, 42 }, { 0, 131, 43 }, { 0, 133, 44 }, { 0, 137, 45 }, { 0, 139, 46 }, { 0, 143, 47 }, + { 0, 145, 48 }, { 0, 149, 49 }, { 0, 151, 50 }, { 0, 155, 51 }, { 0, 157, 52 }, { 0, 161, 53 }, { 0, 165, 54 }, { 0, 167, 55 }, + { 0, 171, 56 }, { 0, 173, 57 }, { 0, 177, 58 }, { 0, 179, 59 }, { 0, 183, 60 }, { 0, 185, 61 }, { 0, 189, 62 }, { 0, 191, 63 }, + { 0, 195, 64 }, { 0, 197, 65 }, { 0, 201, 66 }, { 0, 203, 67 }, { 0, 207, 68 }, { 0, 209, 69 }, { 0, 213, 70 }, { 0, 215, 71 }, + { 0, 219, 72 }, { 0, 221, 73 }, { 0, 225, 74 }, { 0, 229, 75 }, { 0, 231, 76 }, { 0, 235, 77 }, { 0, 237, 78 }, { 0, 241, 79 }, + { 0, 243, 80 }, { 0, 247, 81 }, { 0, 249, 82 }, { 0, 253, 83 }, { 0, 255, 84 }, { 2, 255, 85 }, { 4, 253, 86 }, { 6, 253, 87 }, + { 6, 255, 88 }, { 8, 255, 89 }, { 10, 253, 90 }, { 12, 253, 91 }, { 12, 255, 92 }, { 14, 255, 93 }, { 16, 253, 94 }, { 18, 253, 95 }, + { 18, 255, 96 }, { 20, 255, 97 }, { 22, 253, 98 }, { 24, 253, 99 }, { 24, 255, 100 }, { 26, 255, 101 }, { 28, 253, 102 }, { 30, 251, 103 }, + { 30, 255, 104 }, { 32, 253, 105 }, { 34, 253, 106 }, { 34, 255, 107 }, { 36, 255, 108 }, { 38, 253, 109 }, { 40, 253, 110 }, { 40, 255, 111 }, + { 42, 255, 112 }, { 44, 253, 113 }, { 46, 253, 114 }, { 46, 255, 115 }, { 48, 255, 116 }, { 50, 253, 117 }, { 52, 253, 118 }, { 52, 255, 119 }, + { 54, 255, 120 }, { 56, 253, 121 }, { 58, 253, 122 }, { 58, 255, 123 }, { 60, 255, 124 }, { 62, 253, 125 }, { 64, 253, 126 }, { 64, 255, 127 }, + { 66, 255, 128 }, { 68, 253, 129 }, { 70, 253, 130 }, { 70, 255, 131 }, { 72, 255, 132 }, { 74, 253, 133 }, { 76, 253, 134 }, { 76, 255, 135 }, + { 78, 255, 136 }, { 80, 253, 137 }, { 82, 253, 138 }, { 82, 255, 139 }, { 84, 255, 140 }, { 86, 253, 141 }, { 88, 253, 142 }, { 88, 255, 143 }, + { 90, 255, 144 }, { 92, 253, 145 }, { 94, 251, 146 }, { 94, 255, 147 }, { 96, 253, 148 }, { 98, 253, 149 }, { 98, 255, 150 }, { 100, 255, 151 }, + { 102, 253, 152 }, { 104, 253, 153 }, { 104, 255, 154 }, { 106, 255, 155 }, { 108, 253, 156 }, { 110, 253, 157 }, { 110, 255, 158 }, { 112, 255, 159 }, + { 114, 253, 160 }, { 116, 253, 161 }, { 116, 255, 162 }, { 118, 255, 163 }, { 120, 253, 164 }, { 122, 253, 165 }, { 122, 255, 166 }, { 124, 255, 167 }, + { 126, 253, 168 }, { 128, 253, 169 }, { 128, 255, 170 }, { 130, 255, 171 }, { 132, 253, 172 }, { 134, 253, 173 }, { 134, 255, 174 }, { 136, 255, 175 }, + { 138, 253, 176 }, { 140, 253, 177 }, { 140, 255, 178 }, { 142, 255, 179 }, { 144, 253, 180 }, { 146, 253, 181 }, { 146, 255, 182 }, { 148, 255, 183 }, + { 150, 253, 184 }, { 152, 253, 185 }, { 152, 255, 186 }, { 154, 255, 187 }, { 156, 253, 188 }, { 158, 251, 189 }, { 158, 255, 190 }, { 160, 253, 191 }, + { 162, 253, 192 }, { 162, 255, 193 }, { 164, 255, 194 }, { 166, 253, 195 }, { 168, 253, 196 }, { 168, 255, 197 }, { 170, 255, 198 }, { 172, 253, 199 }, + { 174, 253, 200 }, { 174, 255, 201 }, { 176, 255, 202 }, { 178, 253, 203 }, { 180, 253, 204 }, { 180, 255, 205 }, { 182, 255, 206 }, { 184, 253, 207 }, + { 186, 253, 208 }, { 186, 255, 209 }, { 188, 255, 210 }, { 190, 253, 211 }, { 192, 253, 212 }, { 192, 255, 213 }, { 194, 255, 214 }, { 196, 253, 215 }, + { 198, 253, 216 }, { 198, 255, 217 }, { 200, 255, 218 }, { 202, 253, 219 }, { 204, 253, 220 }, { 204, 255, 221 }, { 206, 255, 222 }, { 208, 253, 223 }, + { 210, 253, 224 }, { 210, 255, 225 }, { 212, 255, 226 }, { 214, 253, 227 }, { 216, 253, 228 }, { 216, 255, 229 }, { 218, 255, 230 }, { 220, 253, 231 }, + { 222, 251, 232 }, { 222, 255, 233 }, { 224, 253, 234 }, { 226, 253, 235 }, { 226, 255, 236 }, { 228, 255, 237 }, { 230, 253, 238 }, { 232, 253, 239 }, + { 232, 255, 240 }, { 234, 255, 241 }, { 236, 253, 242 }, { 238, 253, 243 }, { 238, 255, 244 }, { 240, 255, 245 }, { 242, 253, 246 }, { 244, 253, 247 }, + { 244, 255, 248 }, { 246, 255, 249 }, { 248, 253, 250 }, { 250, 253, 251 }, { 250, 255, 252 }, { 252, 255, 253 }, { 254, 253, 254 }, { 254, 253, 254 }, + } +}; + +Table g_mode7_p10= +{ + 1, + 1, + { + { 1, 0, 1 }, { 1, 0, 1 }, { 1, 4, 2 }, { 1, 6, 3 }, { 1, 10, 4 }, { 1, 12, 5 }, { 1, 16, 6 }, { 1, 18, 7 }, + { 1, 22, 8 }, { 1, 24, 9 }, { 1, 28, 10 }, { 1, 30, 11 }, { 1, 34, 12 }, { 1, 38, 13 }, { 1, 40, 14 }, { 1, 44, 15 }, + { 1, 46, 16 }, { 1, 50, 17 }, { 1, 52, 18 }, { 1, 56, 19 }, { 1, 58, 20 }, { 1, 62, 21 }, { 1, 64, 22 }, { 1, 68, 23 }, + { 1, 70, 24 }, { 1, 74, 25 }, { 1, 76, 26 }, { 1, 80, 27 }, { 1, 82, 28 }, { 1, 86, 29 }, { 1, 88, 30 }, { 1, 92, 31 }, + { 1, 94, 32 }, { 1, 98, 33 }, { 1, 102, 34 }, { 1, 104, 35 }, { 1, 108, 36 }, { 1, 110, 37 }, { 1, 114, 38 }, { 1, 116, 39 }, + { 1, 120, 40 }, { 1, 122, 41 }, { 1, 126, 42 }, { 1, 128, 43 }, { 1, 132, 44 }, { 1, 134, 45 }, { 1, 138, 46 }, { 1, 140, 47 }, + { 1, 144, 48 }, { 1, 146, 49 }, { 1, 150, 50 }, { 1, 152, 51 }, { 1, 156, 52 }, { 1, 158, 53 }, { 1, 162, 54 }, { 1, 166, 55 }, + { 1, 168, 56 }, { 1, 172, 57 }, { 1, 174, 58 }, { 1, 178, 59 }, { 1, 180, 60 }, { 1, 184, 61 }, { 1, 186, 62 }, { 1, 190, 63 }, + { 1, 192, 64 }, { 1, 196, 65 }, { 1, 198, 66 }, { 1, 202, 67 }, { 1, 204, 68 }, { 1, 208, 69 }, { 1, 210, 70 }, { 1, 214, 71 }, + { 1, 216, 72 }, { 1, 220, 73 }, { 1, 222, 74 }, { 1, 226, 75 }, { 1, 230, 76 }, { 1, 232, 77 }, { 1, 236, 78 }, { 1, 238, 79 }, + { 1, 242, 80 }, { 1, 244, 81 }, { 1, 248, 82 }, { 1, 250, 83 }, { 1, 254, 84 }, { 3, 252, 85 }, { 5, 252, 86 }, { 5, 254, 87 }, + { 7, 254, 88 }, { 9, 252, 89 }, { 11, 252, 90 }, { 11, 254, 91 }, { 13, 254, 92 }, { 15, 252, 93 }, { 17, 252, 94 }, { 17, 254, 95 }, + { 19, 254, 96 }, { 21, 252, 97 }, { 23, 252, 98 }, { 23, 254, 99 }, { 25, 254, 100 }, { 27, 252, 101 }, { 29, 250, 102 }, { 29, 254, 103 }, + { 31, 252, 104 }, { 33, 252, 105 }, { 33, 254, 106 }, { 35, 254, 107 }, { 37, 252, 108 }, { 39, 252, 109 }, { 39, 254, 110 }, { 41, 254, 111 }, + { 43, 252, 112 }, { 45, 252, 113 }, { 45, 254, 114 }, { 47, 254, 115 }, { 49, 252, 116 }, { 51, 252, 117 }, { 51, 254, 118 }, { 53, 254, 119 }, + { 55, 252, 120 }, { 57, 252, 121 }, { 57, 254, 122 }, { 59, 254, 123 }, { 61, 252, 124 }, { 63, 252, 125 }, { 63, 254, 126 }, { 65, 254, 127 }, + { 67, 252, 128 }, { 69, 252, 129 }, { 69, 254, 130 }, { 71, 254, 131 }, { 73, 252, 132 }, { 75, 252, 133 }, { 75, 254, 134 }, { 77, 254, 135 }, + { 79, 252, 136 }, { 81, 252, 137 }, { 81, 254, 138 }, { 83, 254, 139 }, { 85, 252, 140 }, { 87, 252, 141 }, { 87, 254, 142 }, { 89, 254, 143 }, + { 91, 252, 144 }, { 93, 250, 145 }, { 93, 254, 146 }, { 95, 252, 147 }, { 97, 252, 148 }, { 97, 254, 149 }, { 99, 254, 150 }, { 101, 252, 151 }, + { 103, 252, 152 }, { 103, 254, 153 }, { 105, 254, 154 }, { 107, 252, 155 }, { 109, 252, 156 }, { 109, 254, 157 }, { 111, 254, 158 }, { 113, 252, 159 }, + { 115, 252, 160 }, { 115, 254, 161 }, { 117, 254, 162 }, { 119, 252, 163 }, { 121, 252, 164 }, { 121, 254, 165 }, { 123, 254, 166 }, { 125, 252, 167 }, + { 127, 252, 168 }, { 127, 254, 169 }, { 129, 254, 170 }, { 131, 252, 171 }, { 133, 252, 172 }, { 133, 254, 173 }, { 135, 254, 174 }, { 137, 252, 175 }, + { 139, 252, 176 }, { 139, 254, 177 }, { 141, 254, 178 }, { 143, 252, 179 }, { 145, 252, 180 }, { 145, 254, 181 }, { 147, 254, 182 }, { 149, 252, 183 }, + { 151, 252, 184 }, { 151, 254, 185 }, { 153, 254, 186 }, { 155, 252, 187 }, { 157, 250, 188 }, { 157, 254, 189 }, { 159, 252, 190 }, { 161, 252, 191 }, + { 161, 254, 192 }, { 163, 254, 193 }, { 165, 252, 194 }, { 167, 252, 195 }, { 167, 254, 196 }, { 169, 254, 197 }, { 171, 252, 198 }, { 173, 252, 199 }, + { 173, 254, 200 }, { 175, 254, 201 }, { 177, 252, 202 }, { 179, 252, 203 }, { 179, 254, 204 }, { 181, 254, 205 }, { 183, 252, 206 }, { 185, 252, 207 }, + { 185, 254, 208 }, { 187, 254, 209 }, { 189, 252, 210 }, { 191, 252, 211 }, { 191, 254, 212 }, { 193, 254, 213 }, { 195, 252, 214 }, { 197, 252, 215 }, + { 197, 254, 216 }, { 199, 254, 217 }, { 201, 252, 218 }, { 203, 252, 219 }, { 203, 254, 220 }, { 205, 254, 221 }, { 207, 252, 222 }, { 209, 252, 223 }, + { 209, 254, 224 }, { 211, 254, 225 }, { 213, 252, 226 }, { 215, 252, 227 }, { 215, 254, 228 }, { 217, 254, 229 }, { 219, 252, 230 }, { 221, 250, 231 }, + { 221, 254, 232 }, { 223, 252, 233 }, { 225, 252, 234 }, { 225, 254, 235 }, { 227, 254, 236 }, { 229, 252, 237 }, { 231, 252, 238 }, { 231, 254, 239 }, + { 233, 254, 240 }, { 235, 252, 241 }, { 237, 252, 242 }, { 237, 254, 243 }, { 239, 254, 244 }, { 241, 252, 245 }, { 243, 252, 246 }, { 243, 254, 247 }, + { 245, 254, 248 }, { 247, 252, 249 }, { 249, 252, 250 }, { 249, 254, 251 }, { 251, 254, 252 }, { 253, 252, 253 }, { 255, 252, 254 }, { 255, 254, 255 }, + } +}; + +Table g_mode7_p11= +{ + 1, + 3, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 7, 3 }, { 1, 9, 4 }, { 1, 13, 5 }, { 1, 15, 6 }, { 1, 19, 7 }, + { 1, 21, 8 }, { 1, 25, 9 }, { 1, 27, 10 }, { 1, 31, 11 }, { 1, 33, 12 }, { 1, 37, 13 }, { 1, 41, 14 }, { 1, 43, 15 }, + { 1, 47, 16 }, { 1, 49, 17 }, { 1, 53, 18 }, { 1, 55, 19 }, { 1, 59, 20 }, { 1, 61, 21 }, { 1, 65, 22 }, { 1, 67, 23 }, + { 1, 71, 24 }, { 1, 73, 25 }, { 1, 77, 26 }, { 1, 79, 27 }, { 1, 83, 28 }, { 1, 85, 29 }, { 1, 89, 30 }, { 1, 91, 31 }, + { 1, 95, 32 }, { 1, 97, 33 }, { 1, 101, 34 }, { 1, 105, 35 }, { 1, 107, 36 }, { 1, 111, 37 }, { 1, 113, 38 }, { 1, 117, 39 }, + { 1, 119, 40 }, { 1, 123, 41 }, { 1, 125, 42 }, { 1, 129, 43 }, { 1, 131, 44 }, { 1, 135, 45 }, { 1, 137, 46 }, { 1, 141, 47 }, + { 1, 143, 48 }, { 1, 147, 49 }, { 1, 149, 50 }, { 1, 153, 51 }, { 1, 155, 52 }, { 1, 159, 53 }, { 1, 161, 54 }, { 1, 165, 55 }, + { 1, 169, 56 }, { 1, 171, 57 }, { 1, 175, 58 }, { 1, 177, 59 }, { 1, 181, 60 }, { 1, 183, 61 }, { 1, 187, 62 }, { 1, 189, 63 }, + { 1, 193, 64 }, { 1, 195, 65 }, { 1, 199, 66 }, { 1, 201, 67 }, { 1, 205, 68 }, { 1, 207, 69 }, { 1, 211, 70 }, { 1, 213, 71 }, + { 1, 217, 72 }, { 1, 219, 73 }, { 1, 223, 74 }, { 1, 225, 75 }, { 1, 229, 76 }, { 1, 233, 77 }, { 1, 235, 78 }, { 1, 239, 79 }, + { 1, 241, 80 }, { 1, 245, 81 }, { 1, 247, 82 }, { 1, 251, 83 }, { 1, 253, 84 }, { 3, 253, 85 }, { 3, 255, 86 }, { 5, 255, 87 }, + { 7, 253, 88 }, { 9, 253, 89 }, { 9, 255, 90 }, { 11, 255, 91 }, { 13, 253, 92 }, { 15, 253, 93 }, { 15, 255, 94 }, { 17, 255, 95 }, + { 19, 253, 96 }, { 21, 253, 97 }, { 21, 255, 98 }, { 23, 255, 99 }, { 25, 253, 100 }, { 27, 251, 101 }, { 27, 255, 102 }, { 29, 253, 103 }, + { 31, 253, 104 }, { 31, 255, 105 }, { 33, 255, 106 }, { 35, 253, 107 }, { 37, 253, 108 }, { 37, 255, 109 }, { 39, 255, 110 }, { 41, 253, 111 }, + { 43, 253, 112 }, { 43, 255, 113 }, { 45, 255, 114 }, { 47, 253, 115 }, { 49, 253, 116 }, { 49, 255, 117 }, { 51, 255, 118 }, { 53, 253, 119 }, + { 55, 253, 120 }, { 55, 255, 121 }, { 57, 255, 122 }, { 59, 253, 123 }, { 61, 253, 124 }, { 61, 255, 125 }, { 63, 255, 126 }, { 65, 253, 127 }, + { 67, 253, 128 }, { 67, 255, 129 }, { 69, 255, 130 }, { 71, 253, 131 }, { 73, 253, 132 }, { 73, 255, 133 }, { 75, 255, 134 }, { 77, 253, 135 }, + { 79, 253, 136 }, { 79, 255, 137 }, { 81, 255, 138 }, { 83, 253, 139 }, { 85, 253, 140 }, { 85, 255, 141 }, { 87, 255, 142 }, { 89, 253, 143 }, + { 91, 251, 144 }, { 91, 255, 145 }, { 93, 253, 146 }, { 95, 253, 147 }, { 95, 255, 148 }, { 97, 255, 149 }, { 99, 253, 150 }, { 101, 253, 151 }, + { 101, 255, 152 }, { 103, 255, 153 }, { 105, 253, 154 }, { 107, 253, 155 }, { 107, 255, 156 }, { 109, 255, 157 }, { 111, 253, 158 }, { 113, 253, 159 }, + { 113, 255, 160 }, { 115, 255, 161 }, { 117, 253, 162 }, { 119, 253, 163 }, { 119, 255, 164 }, { 121, 255, 165 }, { 123, 253, 166 }, { 125, 253, 167 }, + { 125, 255, 168 }, { 127, 255, 169 }, { 129, 253, 170 }, { 131, 253, 171 }, { 131, 255, 172 }, { 133, 255, 173 }, { 135, 253, 174 }, { 137, 253, 175 }, + { 137, 255, 176 }, { 139, 255, 177 }, { 141, 253, 178 }, { 143, 253, 179 }, { 143, 255, 180 }, { 145, 255, 181 }, { 147, 253, 182 }, { 149, 253, 183 }, + { 149, 255, 184 }, { 151, 255, 185 }, { 153, 253, 186 }, { 155, 251, 187 }, { 155, 255, 188 }, { 157, 253, 189 }, { 159, 253, 190 }, { 159, 255, 191 }, + { 161, 255, 192 }, { 163, 253, 193 }, { 165, 253, 194 }, { 165, 255, 195 }, { 167, 255, 196 }, { 169, 253, 197 }, { 171, 253, 198 }, { 171, 255, 199 }, + { 173, 255, 200 }, { 175, 253, 201 }, { 177, 253, 202 }, { 177, 255, 203 }, { 179, 255, 204 }, { 181, 253, 205 }, { 183, 253, 206 }, { 183, 255, 207 }, + { 185, 255, 208 }, { 187, 253, 209 }, { 189, 253, 210 }, { 189, 255, 211 }, { 191, 255, 212 }, { 193, 253, 213 }, { 195, 253, 214 }, { 195, 255, 215 }, + { 197, 255, 216 }, { 199, 253, 217 }, { 201, 253, 218 }, { 201, 255, 219 }, { 203, 255, 220 }, { 205, 253, 221 }, { 207, 253, 222 }, { 207, 255, 223 }, + { 209, 255, 224 }, { 211, 253, 225 }, { 213, 253, 226 }, { 213, 255, 227 }, { 215, 255, 228 }, { 217, 253, 229 }, { 219, 251, 230 }, { 219, 255, 231 }, + { 221, 253, 232 }, { 223, 253, 233 }, { 223, 255, 234 }, { 225, 255, 235 }, { 227, 253, 236 }, { 229, 253, 237 }, { 229, 255, 238 }, { 231, 255, 239 }, + { 233, 253, 240 }, { 235, 253, 241 }, { 235, 255, 242 }, { 237, 255, 243 }, { 239, 253, 244 }, { 241, 253, 245 }, { 241, 255, 246 }, { 243, 255, 247 }, + { 245, 253, 248 }, { 247, 253, 249 }, { 247, 255, 250 }, { 249, 255, 251 }, { 251, 253, 252 }, { 253, 253, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +}}} diff --git a/thirdparty/cvtt/LICENSE.txt b/thirdparty/cvtt/LICENSE.txt new file mode 100644 index 0000000000..6964f6e43f --- /dev/null +++ b/thirdparty/cvtt/LICENSE.txt @@ -0,0 +1,45 @@ +Convection Texture Tools Stand-Alone Kernels
+
+Copyright (c) 2018 Eric Lasota
+
+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.
+
+**************************************************************************
+
+Based on DirectX Texture Library
+
+Copyright (c) 2018 Microsoft Corp
+
+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.
\ No newline at end of file diff --git a/thirdparty/glad/glad.c b/thirdparty/glad/glad.c index 8f8b2189ec..35469e9031 100644 --- a/thirdparty/glad/glad.c +++ b/thirdparty/glad/glad.c @@ -1,6 +1,6 @@ /* - OpenGL loader generated by glad 0.1.20a0 on Fri May 4 21:44:11 2018. + OpenGL loader generated by glad 0.1.25 on Sat Jul 28 10:59:43 2018. Language/Generator: C/C++ Specification: gl @@ -56,8 +56,9 @@ int open_gl(void) { #ifndef IS_UWP libGL = LoadLibraryW(L"opengl32.dll"); if(libGL != NULL) { - gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE)GetProcAddress( - libGL, "wglGetProcAddress"); + void (* tmp)(void); + tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress"); + gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp; return gladGetProcAddressPtr != NULL; } #endif @@ -76,7 +77,7 @@ void close_gl(void) { #include <dlfcn.h> static void* libGL; -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(__HAIKU__) typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*); static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr; #endif @@ -99,7 +100,7 @@ int open_gl(void) { libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL); if(libGL != NULL) { -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__HAIKU__) return 1; #else gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL, @@ -126,7 +127,7 @@ void* get_proc(const char *namez) { void* result = NULL; if(libGL == NULL) return NULL; -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(__HAIKU__) if(gladGetProcAddressPtr != NULL) { result = gladGetProcAddressPtr(namez); } @@ -164,7 +165,7 @@ static int max_loaded_minor; static const char *exts = NULL; static int num_exts_i = 0; -static const char **exts_i = NULL; +static char **exts_i = NULL; static int get_exts(void) { #ifdef _GLAD_IS_SOME_NEW_VERSION @@ -178,7 +179,7 @@ static int get_exts(void) { num_exts_i = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i); if (num_exts_i > 0) { - exts_i = (const char **)realloc((void *)exts_i, (size_t)num_exts_i * (sizeof *exts_i)); + exts_i = (char **)realloc((void *)exts_i, (size_t)num_exts_i * (sizeof *exts_i)); } if (exts_i == NULL) { @@ -191,11 +192,7 @@ static int get_exts(void) { char *local_str = (char*)malloc((len+1) * sizeof(char)); if(local_str != NULL) { -#if _MSC_VER >= 1400 - strncpy_s(local_str, len+1, gl_str_tmp, len); -#else - strncpy(local_str, gl_str_tmp, len+1); -#endif + memcpy(local_str, gl_str_tmp, (len+1) * sizeof(char)); } exts_i[index] = local_str; } diff --git a/thirdparty/glad/glad/glad.h b/thirdparty/glad/glad/glad.h index 4eebad4f2f..4d92d33b37 100644 --- a/thirdparty/glad/glad/glad.h +++ b/thirdparty/glad/glad/glad.h @@ -1,6 +1,6 @@ /* - OpenGL loader generated by glad 0.1.20a0 on Fri May 4 21:44:11 2018. + OpenGL loader generated by glad 0.1.25 on Sat Jul 28 10:59:43 2018. Language/Generator: C/C++ Specification: gl @@ -156,16 +156,8 @@ typedef unsigned int GLhandleARB; typedef unsigned short GLhalfARB; typedef unsigned short GLhalf; typedef GLint GLfixed; -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) -typedef long GLintptr; -#else -typedef ptrdiff_t GLintptr; -#endif -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) -typedef long GLsizeiptr; -#else -typedef ptrdiff_t GLsizeiptr; -#endif +typedef khronos_intptr_t GLintptr; +typedef khronos_ssize_t GLsizeiptr; typedef int64_t GLint64; typedef uint64_t GLuint64; #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) diff --git a/thirdparty/libpng/LICENSE b/thirdparty/libpng/LICENSE index 4cda4fa0ad..6ee9c8f554 100644 --- a/thirdparty/libpng/LICENSE +++ b/thirdparty/libpng/LICENSE @@ -10,8 +10,8 @@ this sentence. This code is released under the libpng license. -libpng versions 1.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are -Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are +libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are +Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are derived from libpng-1.0.6, and are distributed according to the same disclaimer and license as libpng-1.0.6 with the following individuals added to the list of Contributing Authors: @@ -130,4 +130,4 @@ any encryption software. See the EAR, paragraphs 734.3(b)(3) and Glenn Randers-Pehrson glennrp at users.sourceforge.net -September 29, 2017 +July 15, 2018 diff --git a/thirdparty/libpng/png.c b/thirdparty/libpng/png.c index ff02c56518..a25afebcc8 100644 --- a/thirdparty/libpng/png.c +++ b/thirdparty/libpng/png.c @@ -1,8 +1,8 @@ /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.6.33 [September 28, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -14,7 +14,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_34 Your_png_h_is_not_version_1_6_34; +typedef png_libpng_version_1_6_35 Your_png_h_is_not_version_1_6_35; #ifdef __GNUC__ /* The version tests may need to be added to, but the problem warning has @@ -71,7 +71,7 @@ png_set_sig_bytes(png_structrp png_ptr, int num_bytes) * PNG signature (this is the same behavior as strcmp, memcmp, etc). */ int PNGAPI -png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) +png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check) { png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; @@ -136,7 +136,7 @@ png_reset_crc(png_structrp png_ptr) * trouble of calculating it. */ void /* PRIVATE */ -png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) +png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, size_t length) { int need_crc = 1; @@ -421,7 +421,7 @@ png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr) * those cases where it does anything other than a memset. */ PNG_FUNCTION(void,PNGAPI -png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), +png_info_init_3,(png_infopp ptr_ptr, size_t png_info_struct_size), PNG_DEPRECATED) { png_inforp info_ptr = *ptr_ptr; @@ -816,15 +816,15 @@ png_get_copyright(png_const_structrp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.34 - September 29, 2017" PNG_STRING_NEWLINE \ - "Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson" \ + "libpng version 1.6.35 - July 15, 2018" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.6.34 - September 29, 2017\ - Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson\ + return "libpng version 1.6.35 - July 15, 2018\ + Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; # endif @@ -942,7 +942,7 @@ png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name) /* The code is the fifth byte after each four byte string. Historically this * code was always searched from the end of the list, this is no longer - * necessary because the 'set' routine handles duplicate entries correcty. + * necessary because the 'set' routine handles duplicate entries correctly. */ do /* num_chunk_list > 0, so at least one */ { @@ -2067,7 +2067,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, */ /* Data checks (could be skipped). These checks must be independent of the - * version number; however, the version number doesn't accomodate changes in + * version number; however, the version number doesn't accommodate changes in * the header fields (just the known tags and the interpretation of the * data.) */ @@ -2707,7 +2707,7 @@ png_check_IHDR(png_const_structrp png_ptr, #if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) /* ASCII to fp functions */ -/* Check an ASCII formated floating point value, see the more detailed +/* Check an ASCII formatted floating point value, see the more detailed * comments in pngpriv.h */ /* The following is used internally to preserve the sticky flags */ @@ -2715,11 +2715,11 @@ png_check_IHDR(png_const_structrp png_ptr, #define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) int /* PRIVATE */ -png_check_fp_number(png_const_charp string, png_size_t size, int *statep, +png_check_fp_number(png_const_charp string, size_t size, int *statep, png_size_tp whereami) { int state = *statep; - png_size_t i = *whereami; + size_t i = *whereami; while (i < size) { @@ -2842,10 +2842,10 @@ PNG_FP_End: /* The same but for a complete string. */ int -png_check_fp_string(png_const_charp string, png_size_t size) +png_check_fp_string(png_const_charp string, size_t size) { int state=0; - png_size_t char_index=0; + size_t char_index=0; if (png_check_fp_number(string, size, &state, &char_index) != 0 && (char_index == size || string[char_index] == 0)) @@ -2906,7 +2906,7 @@ png_pow10(int power) #pragma GCC diagnostic warning "-Wstrict-overflow=2" #endif /* GCC_STRICT_OVERFLOW */ void /* PRIVATE */ -png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, +png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size, double fp, unsigned int precision) { /* We use standard functions from math.h, but not printf because @@ -3237,7 +3237,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ void /* PRIVATE */ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, - png_size_t size, png_fixed_point fp) + size_t size, png_fixed_point fp) { /* Require space for 10 decimal digits, a decimal point, a minus sign and a * trailing \0, 13 characters: @@ -4344,7 +4344,7 @@ png_set_option(png_structrp png_ptr, int option, int onoff) png_uint_32 setting = (2U + (onoff != 0)) << option; png_uint_32 current = png_ptr->options; - png_ptr->options = (png_uint_32)(((current & ~mask) | setting) & 0xff); + png_ptr->options = (png_uint_32)((current & ~mask) | setting); return (int)(current & mask) >> option; } diff --git a/thirdparty/libpng/png.h b/thirdparty/libpng/png.h index 4c873f5c22..19e464cc17 100644 --- a/thirdparty/libpng/png.h +++ b/thirdparty/libpng/png.h @@ -1,9 +1,9 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.34, September 29, 2017 + * libpng version 1.6.35, July 15, 2018 * - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -12,7 +12,7 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.34, September 29, 2017: + * libpng versions 0.97, January 1998, through 1.6.35, July 15, 2018: * Glenn Randers-Pehrson. * See also "Contributing Authors", below. */ @@ -25,8 +25,8 @@ * * This code is released under the libpng license. * - * libpng versions 1.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are - * Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are + * libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are * derived from libpng-1.0.6, and are distributed according to the same * disclaimer and license as libpng-1.0.6 with the following individuals * added to the list of Contributing Authors: @@ -213,7 +213,7 @@ * ... * 1.5.30 15 10527 15.so.15.30[.0] * ... - * 1.6.34 16 10633 16.so.16.34[.0] + * 1.6.35 16 10635 16.so.16.35[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be @@ -241,13 +241,13 @@ * Y2K compliance in libpng: * ========================= * - * September 29, 2017 + * July 15, 2018 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. * * This is your unofficial assurance that libpng from version 0.71 and - * upward through 1.6.34 are Y2K compliant. It is my belief that + * upward through 1.6.35 are Y2K compliant. It is my belief that * earlier versions were also Y2K compliant. * * Libpng only has two year fields. One is a 2-byte unsigned integer @@ -309,8 +309,8 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.34" -#define PNG_HEADER_VERSION_STRING " libpng version 1.6.34 - September 29, 2017\n" +#define PNG_LIBPNG_VER_STRING "1.6.35" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.35 - July 15, 2018\n" #define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_DLLNUM 16 @@ -318,13 +318,13 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 34 +#define PNG_LIBPNG_VER_RELEASE 35 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ -#define PNG_LIBPNG_VER_BUILD 0 +#define PNG_LIBPNG_VER_BUILD 02 /* Release Status */ #define PNG_LIBPNG_BUILD_ALPHA 1 @@ -341,7 +341,7 @@ #define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with PNG_LIBPNG_BUILD_PRIVATE */ -#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA /* Careful here. At one time, Guy wanted to use 082, but that would be octal. * We must not include leading zeros. @@ -349,7 +349,7 @@ * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER 10634 /* 1.6.34 */ +#define PNG_LIBPNG_VER 10635 /* 1.6.35 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -459,7 +459,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_34; +typedef char* png_libpng_version_1_6_35; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * @@ -600,8 +600,8 @@ typedef struct png_text_struct png_charp key; /* keyword, 1-79 character description of "text" */ png_charp text; /* comment, may be an empty string (ie "") or a NULL pointer */ - png_size_t text_length; /* length of the text string */ - png_size_t itxt_length; /* length of the itxt string */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ png_charp lang; /* language code, 0-79 characters or a NULL pointer */ png_charp lang_key; /* keyword translated UTF-8 string, 0 or more @@ -654,7 +654,7 @@ typedef struct png_unknown_chunk_t { png_byte name[5]; /* Textual chunk name with '\0' terminator */ png_byte *data; /* Data, should not be modified on read! */ - png_size_t size; + size_t size; /* On write 'location' must be set using the flag values listed below. * Notice that on read it is set by libpng however the values stored have @@ -679,7 +679,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; /* Maximum positive integer used in PNG is (2^31)-1 */ #define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) #define PNG_UINT_32_MAX ((png_uint_32)(-1)) -#define PNG_SIZE_MAX ((png_size_t)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) /* These are constants for fixed point values encoded in the * PNG specification manner (x100000) @@ -785,7 +785,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; typedef struct png_row_info_struct { png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ + size_t rowbytes; /* number of bytes in row */ png_byte color_type; /* color type of row */ png_byte bit_depth; /* bit depth of row */ png_byte channels; /* number of channels (1, 2, 3, or 4) */ @@ -804,7 +804,7 @@ typedef png_row_info * * png_row_infopp; * expected to return the read data in the buffer. */ typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); -typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, int)); @@ -941,8 +941,8 @@ PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); * signature, and non-zero otherwise. Having num_to_check == 0 or * start > 7 will always fail (ie return non-zero). */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, - png_size_t num_to_check)); +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); /* Simple signature checking function. This is the same as calling * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). @@ -961,11 +961,11 @@ PNG_EXPORTA(5, png_structp, png_create_write_struct, png_error_ptr warn_fn), PNG_ALLOCATED); -PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, (png_const_structrp png_ptr)); PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, - png_size_t size)); + size_t size)); /* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp * match up. @@ -1018,7 +1018,7 @@ PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); /* Write a PNG chunk - size, type, (optional) data, CRC. */ PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep - chunk_name, png_const_bytep data, png_size_t length)); + chunk_name, png_const_bytep data, size_t length)); /* Write the start of a PNG chunk - length and chunk name. */ PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, @@ -1026,7 +1026,7 @@ PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, /* Write the data of a PNG chunk started with png_write_chunk_start(). */ PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, - png_const_bytep data, png_size_t length)); + png_const_bytep data, size_t length)); /* Finish a chunk started with png_write_chunk_start() (includes CRC). */ PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); @@ -1040,7 +1040,7 @@ PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), * the API will be removed in the future. */ PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, - png_size_t png_info_struct_size), PNG_DEPRECATED); + size_t png_info_struct_size), PNG_DEPRECATED); /* Writes all the PNG information before the image. */ PNG_EXPORT(20, void, png_write_info_before_PLTE, @@ -1137,7 +1137,7 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, * corresponding composited pixel, and the color channels are unassociated * (not premultiplied). The gamma encoded color channels must be scaled * according to the contribution and to do this it is necessary to undo - * the encoding, scale the color values, perform the composition and reencode + * the encoding, scale the color values, perform the composition and re-encode * the values. This is the 'PNG' mode. * * The alternative is to 'associate' the alpha with the color information by @@ -1193,7 +1193,7 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, * * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); * In this case the output is assumed to be something like an sRGB conformant - * display preceeded by a power-law lookup table of power 1.45. This is how + * display preceded by a power-law lookup table of power 1.45. This is how * early Mac systems behaved. * * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); @@ -1240,7 +1240,7 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, * * When the default gamma of PNG files doesn't match the output gamma. * If you have PNG files with no gamma information png_set_alpha_mode allows - * you to provide a default gamma, but it also sets the ouput gamma to the + * you to provide a default gamma, but it also sets the output gamma to the * matching value. If you know your PNG files have a gamma that doesn't * match the output you can take advantage of the fact that * png_set_alpha_mode always sets the output gamma but only sets the PNG @@ -1691,7 +1691,7 @@ PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); * chunk will cause an error at this point unless it is to be saved. * positive: The chunk was handled, libpng will ignore/discard it. * - * See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about * how this behavior will change in libpng 1.7 */ PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, @@ -1716,7 +1716,7 @@ PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, /* Function to be called when data becomes available */ PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, - png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size)); + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); /* A function which may be called *only* within png_process_data to stop the * processing of any more data. The function returns the number of bytes @@ -1725,7 +1725,7 @@ PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, * 'save' is set to true the routine will first save all the pending data and * will always return 0. */ -PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save)); +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); /* A function which may be called *only* outside (after) a call to * png_process_data. It returns the number of bytes of data to skip in the @@ -1870,7 +1870,7 @@ PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 flag)); /* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structrp png_ptr, +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, png_const_inforp info_ptr)); #ifdef PNG_INFO_IMAGE_SUPPORTED @@ -2239,7 +2239,7 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks * it simply resets the behavior to the libpng default. * - * INTERACTION WTIH USER CHUNK CALLBACKS: + * INTERACTION WITH USER CHUNK CALLBACKS: * The per-chunk handling is always used when there is a png_user_chunk_ptr * callback and the callback returns 0; the chunk is then always stored *unless* * it is critical and the per-chunk setting is other than ALWAYS. Notice that @@ -2658,7 +2658,7 @@ PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, * The simplified API hides the details of both libpng and the PNG file format * itself. It allows PNG files to be read into a very limited number of * in-memory bitmap formats or to be written from the same formats. If these - * formats do not accomodate your needs then you can, and should, use the more + * formats do not accommodate your needs then you can, and should, use the more * sophisticated APIs above - these support a wide variety of in-memory formats * and a wide variety of sophisticated transformations to those formats as well * as a wide variety of APIs to manipulate ancillary information. @@ -3020,7 +3020,7 @@ PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, #endif /* STDIO */ PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, - png_const_voidp memory, png_size_t size)); + png_const_voidp memory, size_t size)); /* The PNG header is read from the given memory buffer. */ PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, @@ -3133,7 +3133,7 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, * than or equal to the original value. * * If the function returns false and *memory_bytes was not changed an error - * occured during write. If *memory_bytes was changed, or is not 0 if + * occurred during write. If *memory_bytes was changed, or is not 0 if * 'memory' was NULL, the write would have succeeded but for the memory * buffer being too small. *memory_bytes contains the required number of * bytes and will be bigger that the original value. @@ -3217,7 +3217,7 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given * by the PNG_OPTION_ defines below. * - * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions, + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, * are detected at run time, however sometimes it may be impossible * to do this in user mode, in which case it is necessary to discover * the capabilities in an OS specific way. Such capabilities are diff --git a/thirdparty/libpng/pngconf.h b/thirdparty/libpng/pngconf.h index d13b13e57a..a4646bab85 100644 --- a/thirdparty/libpng/pngconf.h +++ b/thirdparty/libpng/pngconf.h @@ -1,9 +1,9 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.6.34, September 29, 2017 + * libpng version 1.6.35, July 15, 2018 * - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -127,7 +127,7 @@ * * These cases only differ if the operating system does not use the C * calling convention, at present this just means the above cases - * (x86 DOS/Windows sytems) and, even then, this does not apply to + * (x86 DOS/Windows systems) and, even then, this does not apply to * Cygwin running on those systems. * * Note that the value must be defined in pnglibconf.h so that what @@ -515,8 +515,10 @@ # error "libpng requires an unsigned 32-bit (or more) type" #endif -/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, - * requires an ISOC90 compiler and relies on consistent behavior of sizeof. +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. */ typedef size_t png_size_t; typedef ptrdiff_t png_ptrdiff_t; @@ -537,13 +539,12 @@ typedef ptrdiff_t png_ptrdiff_t; # endif #endif -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no - * smaller than png_uint_32. Casts from png_size_t or png_uint_32 to - * png_alloc_size_t are not necessary; in fact, it is recommended not to use - * them at all so that the compiler can complain when something turns out to be - * problematic. +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. * - * Casts in the other direction (from png_alloc_size_t to png_size_t or + * Casts in the other direction (from png_alloc_size_t to size_t or * png_uint_32) should be explicitly applied; however, we do not expect to * encounter practical situations that require such conversions. * @@ -553,7 +554,7 @@ typedef ptrdiff_t png_ptrdiff_t; #ifdef PNG_SMALL_SIZE_T typedef png_uint_32 png_alloc_size_t; #else - typedef png_size_t png_alloc_size_t; + typedef size_t png_alloc_size_t; #endif /* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler @@ -589,8 +590,8 @@ typedef char * png_charp; typedef const char * png_const_charp; typedef png_fixed_point * png_fixed_point_p; typedef const png_fixed_point * png_const_fixed_point_p; -typedef png_size_t * png_size_tp; -typedef const png_size_t * png_const_size_tp; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; #ifdef PNG_STDIO_SUPPORTED typedef FILE * png_FILE_p; diff --git a/thirdparty/libpng/pngget.c b/thirdparty/libpng/pngget.c index 26e9fb1c35..2325508f1d 100644 --- a/thirdparty/libpng/pngget.c +++ b/thirdparty/libpng/pngget.c @@ -1,8 +1,8 @@ /* pngget.c - retrieval of values from info struct * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -26,7 +26,7 @@ png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr, return(0); } -png_size_t PNGAPI +size_t PNGAPI png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr) { if (png_ptr != NULL && info_ptr != NULL) @@ -367,7 +367,7 @@ png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) static png_fixed_point png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns) { - /* Convert from metres * 1,000,000 to inches * 100,000, meters to + /* Convert from meters * 1,000,000 to inches * 100,000, meters to * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. * Notice that this can overflow - a warning is output and 0 is * returned. @@ -741,8 +741,7 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) != 0 && - name != NULL && compression_type != NULL && profile != NULL && - proflen != NULL) + name != NULL && profile != NULL && proflen != NULL) { *name = info_ptr->iccp_name; *profile = info_ptr->iccp_profile; @@ -750,11 +749,13 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, /* This is somewhat irrelevant since the profile data returned has * actually been uncompressed. */ - *compression_type = PNG_COMPRESSION_TYPE_BASE; + if (compression_type != NULL) + *compression_type = PNG_COMPRESSION_TYPE_BASE; return (PNG_INFO_iCCP); } return (0); + } #endif @@ -1164,7 +1165,7 @@ png_get_user_chunk_ptr(png_const_structrp png_ptr) } #endif -png_size_t PNGAPI +size_t PNGAPI png_get_compression_buffer_size(png_const_structrp png_ptr) { if (png_ptr == NULL) diff --git a/thirdparty/libpng/pnginfo.h b/thirdparty/libpng/pnginfo.h index d5f6149dbd..2fcf868dac 100644 --- a/thirdparty/libpng/pnginfo.h +++ b/thirdparty/libpng/pnginfo.h @@ -1,8 +1,8 @@ /* pnginfo.h - header file for PNG reference library * - * Last changed in libpng 1.6.1 [March 28, 2013] - * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -55,10 +55,10 @@ struct png_info_def { /* The following are necessary for every PNG file */ - png_uint_32 width; /* width of image in pixels (from IHDR) */ - png_uint_32 height; /* height of image in pixels (from IHDR) */ - png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ - png_size_t rowbytes; /* bytes needed to hold an untransformed row */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + size_t rowbytes; /* bytes needed to hold an untransformed row */ png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ @@ -247,7 +247,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) /* The sCAL chunk describes the actual physical dimensions of the * subject matter of the graphic. The chunk contains a unit specification * a byte value, and two ASCII strings representing floating-point - * values. The values are width and height corresponsing to one pixel + * values. The values are width and height corresponding to one pixel * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is * non-zero. */ diff --git a/thirdparty/libpng/pnglibconf.h b/thirdparty/libpng/pnglibconf.h index 53b5e442c4..00acecc69b 100644 --- a/thirdparty/libpng/pnglibconf.h +++ b/thirdparty/libpng/pnglibconf.h @@ -1,10 +1,10 @@ -/* libpng 1.6.34 STANDARD API DEFINITION */ +/* libpng 1.6.35 STANDARD API DEFINITION */ /* pnglibconf.h - library build configuration */ -/* Libpng version 1.6.34 - September 29, 2017 */ +/* Libpng version 1.6.35 - July 15, 2018 */ -/* Copyright (c) 1998-2017 Glenn Randers-Pehrson */ +/* Copyright (c) 1998-2018 Glenn Randers-Pehrson */ /* This code is released under the libpng license. */ /* For conditions of distribution and use, see the disclaimer */ diff --git a/thirdparty/libpng/pngpread.c b/thirdparty/libpng/pngpread.c index fbe361dc34..c4ba51c4d4 100644 --- a/thirdparty/libpng/pngpread.c +++ b/thirdparty/libpng/pngpread.c @@ -1,8 +1,8 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -34,7 +34,7 @@ if (png_ptr->buffer_size < N) \ void PNGAPI png_process_data(png_structrp png_ptr, png_inforp info_ptr, - png_bytep buffer, png_size_t buffer_size) + png_bytep buffer, size_t buffer_size) { if (png_ptr == NULL || info_ptr == NULL) return; @@ -47,7 +47,7 @@ png_process_data(png_structrp png_ptr, png_inforp info_ptr, } } -png_size_t PNGAPI +size_t PNGAPI png_process_data_pause(png_structrp png_ptr, int save) { if (png_ptr != NULL) @@ -60,7 +60,7 @@ png_process_data_pause(png_structrp png_ptr, int save) else { /* This includes any pending saved bytes: */ - png_size_t remaining = png_ptr->buffer_size; + size_t remaining = png_ptr->buffer_size; png_ptr->buffer_size = 0; /* So subtract the saved buffer size, unless all the data @@ -133,8 +133,8 @@ png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) void /* PRIVATE */ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) { - png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ - num_to_check = 8 - num_checked; + size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */ + size_t num_to_check = 8 - num_checked; if (png_ptr->buffer_size < num_to_check) { @@ -418,7 +418,7 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) } void PNGCBAPI -png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, size_t length) { png_bytep ptr; @@ -428,7 +428,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) ptr = buffer; if (png_ptr->save_buffer_size != 0) { - png_size_t save_size; + size_t save_size; if (length < png_ptr->save_buffer_size) save_size = length; @@ -445,7 +445,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) } if (length != 0 && png_ptr->current_buffer_size != 0) { - png_size_t save_size; + size_t save_size; if (length < png_ptr->current_buffer_size) save_size = length; @@ -467,7 +467,7 @@ png_push_save_buffer(png_structrp png_ptr) { if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) { - png_size_t i, istop; + size_t i, istop; png_bytep sp; png_bytep dp; @@ -482,7 +482,7 @@ png_push_save_buffer(png_structrp png_ptr) if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > png_ptr->save_buffer_max) { - png_size_t new_max; + size_t new_max; png_bytep old_buffer; if (png_ptr->save_buffer_size > PNG_SIZE_MAX - @@ -494,7 +494,7 @@ png_push_save_buffer(png_structrp png_ptr) new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; old_buffer = png_ptr->save_buffer; png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, - (png_size_t)new_max); + (size_t)new_max); if (png_ptr->save_buffer == NULL) { @@ -522,7 +522,7 @@ png_push_save_buffer(png_structrp png_ptr) void /* PRIVATE */ png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) + size_t buffer_length) { png_ptr->current_buffer = buffer; png_ptr->current_buffer_size = buffer_length; @@ -562,7 +562,7 @@ png_push_read_IDAT(png_structrp png_ptr) if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0) { - png_size_t save_size = png_ptr->save_buffer_size; + size_t save_size = png_ptr->save_buffer_size; png_uint_32 idat_size = png_ptr->idat_size; /* We want the smaller of 'idat_size' and 'current_buffer_size', but they @@ -572,7 +572,7 @@ png_push_read_IDAT(png_structrp png_ptr) * will break on either 16-bit or 64-bit platforms. */ if (idat_size < save_size) - save_size = (png_size_t)idat_size; + save_size = (size_t)idat_size; else idat_size = (png_uint_32)save_size; @@ -589,7 +589,7 @@ png_push_read_IDAT(png_structrp png_ptr) if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0) { - png_size_t save_size = png_ptr->current_buffer_size; + size_t save_size = png_ptr->current_buffer_size; png_uint_32 idat_size = png_ptr->idat_size; /* We want the smaller of 'idat_size' and 'current_buffer_size', but they @@ -598,7 +598,7 @@ png_push_read_IDAT(png_structrp png_ptr) * larger - this cannot overflow. */ if (idat_size < save_size) - save_size = (png_size_t)idat_size; + save_size = (size_t)idat_size; else idat_size = (png_uint_32)save_size; @@ -625,7 +625,7 @@ png_push_read_IDAT(png_structrp png_ptr) void /* PRIVATE */ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) + size_t buffer_length) { /* The caller checks for a non-zero buffer length. */ if (!(buffer_length > 0) || buffer == NULL) diff --git a/thirdparty/libpng/pngpriv.h b/thirdparty/libpng/pngpriv.h index 1f2e90f2b3..3581f67919 100644 --- a/thirdparty/libpng/pngpriv.h +++ b/thirdparty/libpng/pngpriv.h @@ -1,8 +1,8 @@ /* pngpriv.h - private declarations for use inside libpng * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -210,7 +210,11 @@ defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) # define PNG_INTEL_SSE_OPT 1 +# else +# define PNG_INTEL_SSE_OPT 0 # endif +# else +# define PNG_INTEL_SSE_OPT 0 # endif #endif @@ -234,6 +238,8 @@ # if PNG_INTEL_SSE_IMPLEMENTATION > 0 # define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 # endif +#else +# define PNG_INTEL_SSE_IMPLEMENTATION 0 #endif #if PNG_MIPS_MSA_OPT > 0 @@ -728,8 +734,8 @@ /* Added to libpng-1.2.6 JB */ #define PNG_ROWBYTES(pixel_bits, width) \ ((pixel_bits) >= 8 ? \ - ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ - (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + ((size_t)(width) * (((size_t)(pixel_bits)) >> 3)) : \ + (( ((size_t)(width) * ((size_t)(pixel_bits))) + 7) >> 3) ) /* This returns the number of trailing bits in the last byte of a row, 0 if the * last byte is completely full of pixels. It is, in principle, (pixel_bits x @@ -917,7 +923,7 @@ * PNG files the -I directives must match. * * The most likely explanation is that you passed a -I in CFLAGS. This will - * not work; all the preprocessor directories and in particular all the -I + * not work; all the preprocessor directives and in particular all the -I * directives must be in CPPFLAGS. */ #endif @@ -1046,15 +1052,15 @@ PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY); */ PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); + png_bytep data, size_t length),PNG_EMPTY); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr, - png_bytep buffer, png_size_t length),PNG_EMPTY); + png_bytep buffer, size_t length),PNG_EMPTY); #endif PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); + png_bytep data, size_t length),PNG_EMPTY); #ifdef PNG_WRITE_FLUSH_SUPPORTED # ifdef PNG_STDIO_SUPPORTED @@ -1068,7 +1074,7 @@ PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY); /* Write the "data" buffer to whatever output you are using */ PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr, - png_const_bytep data, png_size_t length),PNG_EMPTY); + png_const_bytep data, size_t length),PNG_EMPTY); /* Read and check the PNG file signature */ PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr, @@ -1080,7 +1086,7 @@ PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr), /* Read data from whatever input you are using into the "data" buffer */ PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data, - png_size_t length),PNG_EMPTY); + size_t length),PNG_EMPTY); /* Read bytes into buf, and update png_ptr->crc */ PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf, @@ -1098,7 +1104,7 @@ PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY); * since this is the maximum buffer size we can specify. */ PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr, - png_const_bytep ptr, png_size_t length),PNG_EMPTY); + png_const_bytep ptr, size_t length),PNG_EMPTY); #ifdef PNG_WRITE_FLUSH_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); @@ -1181,7 +1187,7 @@ PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr, /* Chunks that have keywords */ #ifdef PNG_WRITE_tEXt_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr, - png_const_charp key, png_const_charp text, png_size_t text_len),PNG_EMPTY); + png_const_charp key, png_const_charp text, size_t text_len),PNG_EMPTY); #endif #ifdef PNG_WRITE_zTXt_SUPPORTED @@ -1574,10 +1580,10 @@ PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr), PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); + png_bytep buffer, size_t buffer_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); + png_bytep buffer, size_t buffer_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr), PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr, @@ -1847,13 +1853,13 @@ PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr, #ifdef PNG_FLOATING_POINT_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr, - png_charp ascii, png_size_t size, double fp, unsigned int precision), + png_charp ascii, size_t size, double fp, unsigned int precision), PNG_EMPTY); #endif /* FLOATING_POINT */ #ifdef PNG_FIXED_POINT_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, - png_charp ascii, png_size_t size, png_fixed_point fp),PNG_EMPTY); + png_charp ascii, size_t size, png_fixed_point fp),PNG_EMPTY); #endif /* FIXED_POINT */ #endif /* sCAL */ @@ -1946,7 +1952,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, * the problem character.) This has not been tested within libpng. */ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, - png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); + size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); /* This is the same but it checks a complete string and returns true * only if it just contains a floating point number. As of 1.5.4 this @@ -1955,7 +1961,7 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, * for negative or zero values using the sticky flag. */ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string, - png_size_t size),PNG_EMPTY); + size_t size),PNG_EMPTY); #endif /* pCAL || sCAL */ #if defined(PNG_GAMMA_SUPPORTED) ||\ @@ -2030,7 +2036,7 @@ typedef struct png_control png_voidp error_buf; /* Always a jmp_buf at present. */ png_const_bytep memory; /* Memory buffer. */ - png_size_t size; /* Size of the memory buffer. */ + size_t size; /* Size of the memory buffer. */ unsigned int for_write :1; /* Otherwise it is a read structure */ unsigned int owned_file :1; /* We own the file in io_ptr */ diff --git a/thirdparty/libpng/pngread.c b/thirdparty/libpng/pngread.c index da32e9ad9c..bff7503ee3 100644 --- a/thirdparty/libpng/pngread.c +++ b/thirdparty/libpng/pngread.c @@ -1,8 +1,8 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.6.33 [September 28, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -1532,7 +1532,7 @@ png_image_begin_read_from_file(png_imagep image, const char *file_name) #endif /* STDIO */ static void PNGCBAPI -png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) +png_image_memory_read(png_structp png_ptr, png_bytep out, size_t need) { if (png_ptr != NULL) { @@ -1543,7 +1543,7 @@ png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) if (cp != NULL) { png_const_bytep memory = cp->memory; - png_size_t size = cp->size; + size_t size = cp->size; if (memory != NULL && size >= need) { @@ -1562,7 +1562,7 @@ png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) } int PNGAPI png_image_begin_read_from_memory(png_imagep image, - png_const_voidp memory, png_size_t size) + png_const_voidp memory, size_t size) { if (image != NULL && image->version == PNG_IMAGE_VERSION) { @@ -4150,7 +4150,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background, * * NOTE: this will be changed in 1.7 because PNG_IMAGE_BUFFER_SIZE * will be changed to use png_alloc_size_t; bigger images can be - * accomodated on 64-bit systems. + * accommodated on 64-bit systems. */ if (image->height <= 0xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check) diff --git a/thirdparty/libpng/pngrio.c b/thirdparty/libpng/pngrio.c index 7e26e855ca..372221483f 100644 --- a/thirdparty/libpng/pngrio.c +++ b/thirdparty/libpng/pngrio.c @@ -1,8 +1,8 @@ /* pngrio.c - functions for data input * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -29,7 +29,7 @@ * to read more than 64K on a 16-bit machine. */ void /* PRIVATE */ -png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) +png_read_data(png_structrp png_ptr, png_bytep data, size_t length) { png_debug1(4, "reading %d bytes", (int)length); @@ -47,14 +47,14 @@ png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) * than changing the library. */ void PNGCBAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +png_default_read_data(png_structp png_ptr, png_bytep data, size_t length) { - png_size_t check; + size_t check; if (png_ptr == NULL) return; - /* fread() returns 0 on error, so it is OK to store this in a png_size_t + /* fread() returns 0 on error, so it is OK to store this in a size_t * instead of an int, which is what fread() actually returns. */ check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); diff --git a/thirdparty/libpng/pngrtran.c b/thirdparty/libpng/pngrtran.c index c189650313..67d1f249a6 100644 --- a/thirdparty/libpng/pngrtran.c +++ b/thirdparty/libpng/pngrtran.c @@ -1,8 +1,8 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.6.33 [September 28, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -292,7 +292,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, * who use the inverse of the gamma value accidentally! Since some of these * values are reasonable this may have to be changed: * - * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit + * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit * gamma of 36, and its reciprocal.) */ if (output_gamma < 1000 || output_gamma > 10000000) @@ -747,7 +747,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, int num_red = (1 << PNG_QUANTIZE_RED_BITS); int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); - png_size_t num_entries = ((png_size_t)1 << total_bits); + size_t num_entries = ((size_t)1 << total_bits); png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); @@ -1317,7 +1317,7 @@ png_init_read_transformations(png_structrp png_ptr) else if (png_ptr->screen_gamma != 0) /* The converse - assume the file matches the screen, note that this - * perhaps undesireable default can (from 1.5.4) be changed by calling + * perhaps undesirable default can (from 1.5.4) be changed by calling * png_set_alpha_mode (even if the alpha handling mode isn't required * or isn't changed from the default.) */ @@ -1885,7 +1885,7 @@ png_init_read_transformations(png_structrp png_ptr) png_ptr->transformations &= ~PNG_SHIFT; - /* significant bits can be in the range 1 to 7 for a meaninful result, if + /* significant bits can be in the range 1 to 7 for a meaningful result, if * the number of significant bits is 0 then no shift is done (this is an * error condition which is silently ignored.) */ @@ -2151,8 +2151,8 @@ png_do_unpack(png_row_infop row_info, png_bytep row) { case 1: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); - png_bytep dp = row + (png_size_t)row_width - 1; + png_bytep sp = row + (size_t)((row_width - 1) >> 3); + png_bytep dp = row + (size_t)row_width - 1; png_uint_32 shift = 7U - ((row_width + 7U) & 0x07); for (i = 0; i < row_width; i++) { @@ -2175,8 +2175,8 @@ png_do_unpack(png_row_infop row_info, png_bytep row) case 2: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); - png_bytep dp = row + (png_size_t)row_width - 1; + png_bytep sp = row + (size_t)((row_width - 1) >> 2); + png_bytep dp = row + (size_t)row_width - 1; png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1); for (i = 0; i < row_width; i++) { @@ -2198,8 +2198,8 @@ png_do_unpack(png_row_infop row_info, png_bytep row) case 4: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); - png_bytep dp = row + (png_size_t)row_width - 1; + png_bytep sp = row + (size_t)((row_width - 1) >> 1); + png_bytep dp = row + (size_t)row_width - 1; png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2); for (i = 0; i < row_width; i++) { @@ -2463,95 +2463,94 @@ png_do_chop(png_row_infop row_info, png_bytep row) static void png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) { + png_uint_32 row_width = row_info->width; + png_debug(1, "in png_do_read_swap_alpha"); + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) { - /* This converts from RGBA to ARGB */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; } + } #ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from RRGGBBAA to AARRGGBB */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; } -#endif } +#endif + } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) { - /* This converts from GA to AG */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; } + } #ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from GGAA to AAGG */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; } -#endif } +#endif } } #endif @@ -2681,8 +2680,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from G to GX */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width; + png_bytep dp = sp + (size_t)row_width; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2697,8 +2696,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from G to XG */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width; + png_bytep dp = sp + (size_t)row_width; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2716,8 +2715,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from GG to GGXX */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2735,8 +2734,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from GG to XXGG */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2758,8 +2757,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from RGB to RGBX */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width * 3; + png_bytep dp = sp + (size_t)row_width; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2776,8 +2775,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from RGB to XRGB */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width * 3; + png_bytep dp = sp + (size_t)row_width; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2797,8 +2796,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from RRGGBB to RRGGBBXX */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 6; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2820,8 +2819,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from RRGGBB to XXRRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 6; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2862,8 +2861,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This changes G to RGB */ - png_bytep sp = row + (png_size_t)row_width - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width - 1; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(dp--) = *sp; @@ -2875,8 +2874,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) else { /* This changes GG to RRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; + png_bytep sp = row + (size_t)row_width * 2 - 1; + png_bytep dp = sp + (size_t)row_width * 4; for (i = 0; i < row_width; i++) { *(dp--) = *sp; @@ -2894,8 +2893,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This changes GA to RGBA */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2 - 1; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); @@ -2908,8 +2907,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) else { /* This changes GGAA to RRGGBBAA */ - png_bytep sp = row + (png_size_t)row_width * 4 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; + png_bytep sp = row + (size_t)row_width * 4 - 1; + png_bytep dp = sp + (size_t)row_width * 4; for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); @@ -2980,7 +2979,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) * values this results in an implicit assumption that the original PNG RGB * values were linear. * - * Other integer coefficents can be used via png_set_rgb_to_gray(). Because + * Other integer coefficients can be used via png_set_rgb_to_gray(). Because * the API takes just red and green coefficients the blue coefficient is * calculated to make the sum 32768. This will result in different rounding * to that used above. @@ -3209,720 +3208,718 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) png_debug(1, "in png_do_compose"); + switch (row_info->color_type) { - switch (row_info->color_type) + case PNG_COLOR_TYPE_GRAY: { - case PNG_COLOR_TYPE_GRAY: + switch (row_info->bit_depth) { - switch (row_info->bit_depth) + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); + } + + if (shift == 0) + { + shift = 7; + sp++; + } + + else + shift--; + } + break; + } + + case 2: { - case 1: +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) { sp = row; - shift = 7; + shift = 6; for (i = 0; i < row_width; i++) { - if ((png_uint_16)((*sp >> shift) & 0x01) - == png_ptr->trans_color.gray) + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); tmp |= - (unsigned int)(png_ptr->background.gray << shift); + (unsigned int)png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + else + { + unsigned int p = (*sp >> shift) & 0x03; + unsigned int g = (gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03; + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= (unsigned int)(g << shift); *sp = (png_byte)(tmp & 0xff); } if (shift == 0) { - shift = 7; + shift = 6; sp++; } else - shift--; + shift -= 2; } - break; } - case 2: + else +#endif { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= - (unsigned int)png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x03; - unsigned int g = (gamma_table [p | (p << 2) | - (p << 4) | (p << 6)] >> 6) & 0x03; - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= (unsigned int)(g << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 6; - sp++; - } - - else - shift -= 2; + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= + (unsigned int)png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); } - } - else -#endif - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) + if (shift == 0) { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= - (unsigned int)png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 6; - sp++; - } - - else - shift -= 2; + shift = 6; + sp++; } + + else + shift -= 2; } - break; } + break; + } - case 4: - { + case 4: + { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= - (unsigned int)(png_ptr->background.gray << shift); - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x0f; - unsigned int g = (gamma_table[p | (p << 4)] >> 4) & - 0x0f; - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= (unsigned int)(g << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 4; - sp++; - } - - else - shift -= 4; + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); } - } - else -#endif - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) + else { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= - (unsigned int)(png_ptr->background.gray << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 4; - sp++; - } - - else - shift -= 4; + unsigned int p = (*sp >> shift) & 0x0f; + unsigned int g = (gamma_table[p | (p << 4)] >> 4) & + 0x0f; + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= (unsigned int)(g << shift); + *sp = (png_byte)(tmp & 0xff); } - } - break; - } - case 8: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; - - else - *sp = gamma_table[*sp]; - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp++) + if (shift == 0) { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; + shift = 4; + sp++; } + + else + shift -= 4; } - break; } - case 16: + else +#endif { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL) + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } - - else - { - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } + if (shift == 0) + { + shift = 4; + sp++; } + + else + shift -= 4; } - break; } - - default: - break; + break; } - break; - } - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) + case 8: { #ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_table != NULL) { sp = row; - for (i = 0; i < row_width; i++, sp += 3) + for (i = 0; i < row_width; i++, sp++) { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; else - { *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } } } else #endif { sp = row; - for (i = 0; i < row_width; i++, sp += 3) + for (i = 0; i < row_width; i++, sp++) { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; } } + break; } - else /* if (row_info->bit_depth == 16) */ + + case 16: { #ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_16 != NULL) { sp = row; - for (i = 0; i < row_width; i++, sp += 6) + for (i = 0; i < row_width; i++, sp += 2) { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + png_uint_16 v; - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) + if (v == png_ptr->trans_color.gray) { /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); } else { - png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); } } } - else #endif { sp = row; - for (i = 0; i < row_width; i++, sp += 6) + for (i = 0; i < row_width; i++, sp += 2) { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + png_uint_16 v; - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) + if (v == png_ptr->trans_color.gray) { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); } } } + break; } - break; + + default: + break; } + break; + } - case PNG_COLOR_TYPE_GRAY_ALPHA: + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) { - if (row_info->bit_depth == 8) - { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) { - png_uint_16 a = *(sp + 1); + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } - if (a == 0xff) - *sp = gamma_table[*sp]; + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.gray; - } + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); - else - { - png_byte v, w; + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.gray); - if (optimize == 0) - w = gamma_from_1[w]; - *sp = w; - } + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); } } - else + } + + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) { - png_byte a = *(sp + 1); + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + } + } + } + break; + } - if (a == 0) - *sp = (png_byte)png_ptr->background.gray; + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *sp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.gray; + } + + else + { + png_byte v, w; - else if (a < 0xff) - png_composite(*sp, *sp, a, png_ptr->background.gray); + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.gray); + if (optimize == 0) + w = gamma_from_1[w]; + *sp = w; } } } - else /* if (png_ptr->bit_depth == 16) */ + else +#endif { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_byte a = *(sp + 1); + + if (a == 0) + *sp = (png_byte)png_ptr->background.gray; + + else if (a < 0xff) + png_composite(*sp, *sp, a, png_ptr->background.gray); + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + png_uint_16 v; - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } + else + { + png_uint_16 g, v, w; + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, png_ptr->background_1.gray); + if (optimize != 0) + w = v; else - { - png_uint_16 g, v, w; - - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, png_ptr->background_1.gray); - if (optimize != 0) - w = v; - else - w = gamma_16_from_1[(v & 0xff) >> - gamma_shift][v >> 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - } + w = gamma_16_from_1[(v & 0xff) >> + gamma_shift][v >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); } } - else + } + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } - else if (a < 0xffff) - { - png_uint_16 g, v; + else if (a < 0xffff) + { + png_uint_16 g, v; - g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, png_ptr->background.gray); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, png_ptr->background.gray); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); } } } - break; } + break; + } - case PNG_COLOR_TYPE_RGB_ALPHA: + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) { - if (row_info->bit_depth == 8) - { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) + png_byte a = *(sp + 3); + + if (a == 0xff) { - png_byte a = *(sp + 3); + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } - if (a == 0xff) - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + else + { + png_byte v, w; - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.red); - if (optimize == 0) w = gamma_from_1[w]; - *sp = w; - - v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, png_ptr->background_1.green); - if (optimize == 0) w = gamma_from_1[w]; - *(sp + 1) = w; - - v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, png_ptr->background_1.blue); - if (optimize == 0) w = gamma_from_1[w]; - *(sp + 2) = w; - } + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.red); + if (optimize == 0) w = gamma_from_1[w]; + *sp = w; + + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, png_ptr->background_1.green); + if (optimize == 0) w = gamma_from_1[w]; + *(sp + 1) = w; + + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, png_ptr->background_1.blue); + if (optimize == 0) w = gamma_from_1[w]; + *(sp + 2) = w; } } - else + } + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); + png_byte a = *(sp + 3); - if (a == 0) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + if (a == 0) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } - else if (a < 0xff) - { - png_composite(*sp, *sp, a, png_ptr->background.red); + else if (a < 0xff) + { + png_composite(*sp, *sp, a, png_ptr->background.red); - png_composite(*(sp + 1), *(sp + 1), a, - png_ptr->background.green); + png_composite(*(sp + 1), *(sp + 1), a, + png_ptr->background.green); - png_composite(*(sp + 2), *(sp + 2), a, - png_ptr->background.blue); - } + png_composite(*(sp + 2), *(sp + 2), a, + png_ptr->background.blue); } } } - else /* if (row_info->bit_depth == 16) */ - { + } + else /* if (row_info->bit_depth == 16) */ + { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } - else - { - png_uint_16 v, w; - - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, png_ptr->background_1.red); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, png_ptr->background_1.green); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 2) = (png_byte)((w >> 8) & 0xff); - *(sp + 3) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, png_ptr->background_1.blue); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 4) = (png_byte)((w >> 8) & 0xff); - *(sp + 5) = (png_byte)(w & 0xff); - } + else + { + png_uint_16 v, w; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, png_ptr->background_1.red); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, png_ptr->background_1.green); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 2) = (png_byte)((w >> 8) & 0xff); + *(sp + 3) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, png_ptr->background_1.blue); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 4) = (png_byte)((w >> 8) & 0xff); + *(sp + 5) = (png_byte)(w & 0xff); } } + } - else + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } - else if (a < 0xffff) - { - png_uint_16 v; + else if (a < 0xffff) + { + png_uint_16 v; - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); - png_composite_16(v, r, a, png_ptr->background.red); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, r, a, png_ptr->background.red); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); - png_composite_16(v, g, a, png_ptr->background.green); - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, png_ptr->background.green); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); - png_composite_16(v, b, a, png_ptr->background.blue); - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } + png_composite_16(v, b, a, png_ptr->background.blue); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); } } } - break; } - - default: - break; + break; } + + default: + break; } } #endif /* READ_BACKGROUND || READ_ALPHA_MODE */ @@ -4220,8 +4217,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { case 1: { - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 3); + dp = row + (size_t)row_width - 1; shift = 7 - (int)((row_width + 7) & 0x07); for (i = 0; i < row_width; i++) { @@ -4247,8 +4244,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, case 2: { - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 2); + dp = row + (size_t)row_width - 1; shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); for (i = 0; i < row_width; i++) { @@ -4270,8 +4267,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, case 4: { - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 1); + dp = row + (size_t)row_width - 1; shift = (int)((row_width & 0x01) << 2); for (i = 0; i < row_width; i++) { @@ -4304,8 +4301,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { if (num_trans > 0) { - sp = row + (png_size_t)row_width - 1; - dp = row + ((png_size_t)row_width << 2) - 1; + sp = row + (size_t)row_width - 1; + dp = row + ((size_t)row_width << 2) - 1; for (i = 0; i < row_width; i++) { @@ -4329,8 +4326,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, else { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width * 3) - 1; + sp = row + (size_t)row_width - 1; + dp = row + (size_t)(row_width * 3) - 1; for (i = 0; i < row_width; i++) { @@ -4365,195 +4362,130 @@ png_do_expand(png_row_infop row_info, png_bytep row, png_debug(1, "in png_do_expand"); + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - unsigned int gray = trans_color != NULL ? trans_color->gray : 0; + unsigned int gray = trans_color != NULL ? trans_color->gray : 0; - if (row_info->bit_depth < 8) + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) { - switch (row_info->bit_depth) + case 1: { - case 1: + gray = (gray & 0x01) * 0xff; + sp = row + (size_t)((row_width - 1) >> 3); + dp = row + (size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) { - gray = (gray & 0x01) * 0xff; - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 0xff; - - else - *dp = 0; - - if (shift == 7) - { - shift = 0; - sp--; - } - - else - shift++; + if ((*sp >> shift) & 0x01) + *dp = 0xff; - dp--; - } - break; - } + else + *dp = 0; - case 2: - { - gray = (gray & 0x03) * 0x55; - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) + if (shift == 7) { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)(value | (value << 2) | (value << 4) | - (value << 6)); - if (shift == 6) - { - shift = 0; - sp--; - } - - else - shift += 2; - - dp--; + shift = 0; + sp--; } - break; - } - - case 4: - { - gray = (gray & 0x0f) * 0x11; - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)(value | (value << 4)); - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift = 4; + else + shift++; - dp--; - } - break; + dp--; } - - default: - break; + break; } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (trans_color != NULL) - { - if (row_info->bit_depth == 8) + case 2: { - gray = gray & 0xff; - sp = row + (png_size_t)row_width - 1; - dp = row + ((png_size_t)row_width << 1) - 1; - + gray = (gray & 0x03) * 0x55; + sp = row + (size_t)((row_width - 1) >> 2); + dp = row + (size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); for (i = 0; i < row_width; i++) { - if ((*sp & 0xffU) == gray) - *dp-- = 0; + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } else - *dp-- = 0xff; + shift += 2; - *dp-- = *sp--; + dp--; } + break; } - else if (row_info->bit_depth == 16) + case 4: { - unsigned int gray_high = (gray >> 8) & 0xff; - unsigned int gray_low = gray & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (row_info->rowbytes << 1) - 1; + gray = (gray & 0x0f) * 0x11; + sp = row + (size_t)((row_width - 1) >> 1); + dp = row + (size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); for (i = 0; i < row_width; i++) { - if ((*(sp - 1) & 0xffU) == gray_high && - (*(sp) & 0xffU) == gray_low) + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) { - *dp-- = 0; - *dp-- = 0; + shift = 0; + sp--; } else - { - *dp-- = 0xff; - *dp-- = 0xff; - } + shift = 4; - *dp-- = *sp--; - *dp-- = *sp--; + dp--; } + break; } - row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; - row_info->channels = 2; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_width); + default: + break; } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB && - trans_color != NULL) + + if (trans_color != NULL) { if (row_info->bit_depth == 8) { - png_byte red = (png_byte)(trans_color->red & 0xff); - png_byte green = (png_byte)(trans_color->green & 0xff); - png_byte blue = (png_byte)(trans_color->blue & 0xff); - sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + ((png_size_t)row_width << 2) - 1; + gray = gray & 0xff; + sp = row + (size_t)row_width - 1; + dp = row + ((size_t)row_width << 1) - 1; + for (i = 0; i < row_width; i++) { - if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + if ((*sp & 0xffU) == gray) *dp-- = 0; else *dp-- = 0xff; *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; } } + else if (row_info->bit_depth == 16) { - png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); - png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); - png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); - png_byte red_low = (png_byte)(trans_color->red & 0xff); - png_byte green_low = (png_byte)(trans_color->green & 0xff); - png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + unsigned int gray_high = (gray >> 8) & 0xff; + unsigned int gray_low = gray & 0xff; sp = row + row_info->rowbytes - 1; - dp = row + ((png_size_t)row_width << 3) - 1; + dp = row + (row_info->rowbytes << 1) - 1; for (i = 0; i < row_width; i++) { - if (*(sp - 5) == red_high && - *(sp - 4) == red_low && - *(sp - 3) == green_high && - *(sp - 2) == green_low && - *(sp - 1) == blue_high && - *(sp ) == blue_low) + if ((*(sp - 1) & 0xffU) == gray_high && + (*(sp) & 0xffU) == gray_low) { *dp-- = 0; *dp-- = 0; @@ -4567,18 +4499,81 @@ png_do_expand(png_row_infop row_info, png_bytep row, *dp-- = *sp--; *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; } } - row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - row_info->channels = 4; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); } } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && + trans_color != NULL) + { + if (row_info->bit_depth == 8) + { + png_byte red = (png_byte)(trans_color->red & 0xff); + png_byte green = (png_byte)(trans_color->green & 0xff); + png_byte blue = (png_byte)(trans_color->blue & 0xff); + sp = row + (size_t)row_info->rowbytes - 1; + dp = row + ((size_t)row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_color->red & 0xff); + png_byte green_low = (png_byte)(trans_color->green & 0xff); + png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + ((size_t)row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } } #endif @@ -4760,8 +4755,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) &(png_ptr->trans_color)); else - png_do_expand(row_info, png_ptr->row_buf + 1, - NULL); + png_do_expand(row_info, png_ptr->row_buf + 1, NULL); } } #endif @@ -4985,7 +4979,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) (png_ptr, /* png_ptr */ row_info, /* row_info: */ /* png_uint_32 width; width of row */ - /* png_size_t rowbytes; number of bytes in row */ + /* size_t rowbytes; number of bytes in row */ /* png_byte color_type; color type of pixels */ /* png_byte bit_depth; bit depth of samples */ /* png_byte channels; number of channels (1-4) */ diff --git a/thirdparty/libpng/pngrutil.c b/thirdparty/libpng/pngrutil.c index 8692933bd8..7001f1976e 100644 --- a/thirdparty/libpng/pngrutil.c +++ b/thirdparty/libpng/pngrutil.c @@ -1,8 +1,8 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.6.33 [September 28, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -102,7 +102,7 @@ png_get_int_32)(png_const_bytep buf) png_uint_16 (PNGAPI png_get_uint_16)(png_const_bytep buf) { - /* ANSI-C requires an int value to accomodate at least 16 bits so this + /* ANSI-C requires an int value to accommodate at least 16 bits so this * works and allows the compiler not to worry about possible narrowing * on 32-bit systems. (Pre-ANSI systems did not make integers smaller * than 16 bits either.) @@ -120,7 +120,7 @@ png_get_uint_16)(png_const_bytep buf) void /* PRIVATE */ png_read_sig(png_structrp png_ptr, png_inforp info_ptr) { - png_size_t num_checked, num_to_check; + size_t num_checked, num_to_check; /* Exit if the user application does not expect a signature. */ if (png_ptr->sig_bytes >= 8) @@ -1648,7 +1648,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) int entry_size, i; png_uint_32 skip = 0; png_uint_32 dl; - png_size_t max_dl; + size_t max_dl; png_debug(1, "in png_handle_sPLT"); @@ -1997,6 +1997,15 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) /* GRAY */ { + if (png_ptr->bit_depth <= 8) + { + if (buf[0] != 0 || buf[1] >= (unsigned int)(1 << png_ptr->bit_depth)) + { + png_chunk_benign_error(png_ptr, "invalid gray level"); + return; + } + } + background.index = 0; background.red = background.green = @@ -2006,6 +2015,15 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else { + if (png_ptr->bit_depth <= 8) + { + if (buf[0] != 0 || buf[2] != 0 || buf[4] != 0) + { + png_chunk_benign_error(png_ptr, "invalid color"); + return; + } + } + background.index = 0; background.red = png_get_uint_16(buf); background.green = png_get_uint_16(buf + 2); @@ -2359,7 +2377,7 @@ void /* PRIVATE */ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_bytep buffer; - png_size_t i; + size_t i; int state; png_debug(1, "in png_handle_sCAL"); @@ -2429,7 +2447,7 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else { - png_size_t heighti = i; + size_t heighti = i; state = 0; if (png_check_fp_number((png_const_charp)buffer, length, @@ -2867,7 +2885,7 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) { PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); /* The following is safe because of the PNG_SIZE_MAX init above */ - png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/; + png_ptr->unknown_chunk.size = (size_t)length/*SAFE*/; /* 'mode' is a flag array, only the bottom four bits matter here */ png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/; @@ -3149,10 +3167,13 @@ png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length) { png_alloc_size_t idat_limit = PNG_UINT_31_MAX; size_t row_factor = - (png_ptr->width * png_ptr->channels * (png_ptr->bit_depth > 8? 2: 1) - + 1 + (png_ptr->interlaced? 6: 0)); + (size_t)png_ptr->width + * (size_t)png_ptr->channels + * (png_ptr->bit_depth > 8? 2: 1) + + 1 + + (png_ptr->interlaced? 6: 0); if (png_ptr->height > PNG_UINT_32_MAX/row_factor) - idat_limit=PNG_UINT_31_MAX; + idat_limit = PNG_UINT_31_MAX; else idat_limit = png_ptr->height * row_factor; row_factor = row_factor > 32566? 32566 : row_factor; @@ -3679,8 +3700,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, { case 1: { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + png_bytep sp = row + (size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (size_t)((final_width - 1) >> 3); unsigned int sshift, dshift; unsigned int s_start, s_end; int s_inc; @@ -3806,8 +3827,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, case 4: { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + png_bytep sp = row + (size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (size_t)((final_width - 1) >> 1); unsigned int sshift, dshift; unsigned int s_start, s_end; int s_inc; @@ -3869,12 +3890,12 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, default: { - png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + size_t pixel_bytes = (row_info->pixel_depth >> 3); - png_bytep sp = row + (png_size_t)(row_info->width - 1) + png_bytep sp = row + (size_t)(row_info->width - 1) * pixel_bytes; - png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + png_bytep dp = row + (size_t)(final_width - 1) * pixel_bytes; int jstop = (int)png_pass_inc[pass]; png_uint_32 i; @@ -3911,8 +3932,8 @@ static void png_read_filter_row_sub(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; png_bytep rp = row + bpp; @@ -3929,8 +3950,8 @@ static void png_read_filter_row_up(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; png_bytep rp = row; png_const_bytep pp = prev_row; @@ -3945,11 +3966,11 @@ static void png_read_filter_row_avg(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - png_size_t i; + size_t i; png_bytep rp = row; png_const_bytep pp = prev_row; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop = row_info->rowbytes - bpp; + size_t istop = row_info->rowbytes - bpp; for (i = 0; i < bpp; i++) { @@ -4385,7 +4406,7 @@ png_read_start_row(png_structrp png_ptr) static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; unsigned int max_pixel_depth; - png_size_t row_bytes; + size_t row_bytes; png_debug(1, "in png_read_start_row"); diff --git a/thirdparty/libpng/pngset.c b/thirdparty/libpng/pngset.c index 6f3a1ee11e..7cf54d9248 100644 --- a/thirdparty/libpng/pngset.c +++ b/thirdparty/libpng/pngset.c @@ -1,8 +1,8 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -313,7 +313,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, png_const_charp units, png_charpp params) { - png_size_t length; + size_t length; int i; png_debug1(1, "in %s storage function", "pCAL"); @@ -390,7 +390,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, memcpy(info_ptr->pcal_units, units, length); info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, - (png_size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp))))); + (size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp))))); if (info_ptr->pcal_params == NULL) { @@ -430,7 +430,7 @@ void PNGAPI png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, int unit, png_const_charp swidth, png_const_charp sheight) { - png_size_t lengthw = 0, lengthh = 0; + size_t lengthw = 0, lengthh = 0; png_debug1(1, "in %s storage function", "sCAL"); @@ -691,7 +691,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, { png_charp new_iccp_name; png_bytep new_iccp_profile; - png_size_t length; + size_t length; png_debug1(1, "in %s storage function", "iCCP"); @@ -1018,7 +1018,7 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ info_ptr->trans_alpha = png_voidcast(png_bytep, png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); - memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans); } png_ptr->trans_alpha = info_ptr->trans_alpha; } @@ -1098,7 +1098,7 @@ png_set_sPLT(png_const_structrp png_ptr, do { - png_size_t length; + size_t length; /* Skip invalid input entries */ if (entries->name == NULL || entries->entries == NULL) @@ -1563,7 +1563,7 @@ png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr, #endif void PNGAPI -png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size) +png_set_compression_buffer_size(png_structrp png_ptr, size_t size) { if (png_ptr == NULL) return; diff --git a/thirdparty/libpng/pngstruct.h b/thirdparty/libpng/pngstruct.h index d83f971253..699e8ac68a 100644 --- a/thirdparty/libpng/pngstruct.h +++ b/thirdparty/libpng/pngstruct.h @@ -1,8 +1,8 @@ /* pngstruct.h - header file for PNG reference library * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -47,7 +47,7 @@ /* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib * can handle at once. This type need be no larger than 16 bits (so maximum of * 65535), this define allows us to discover how big it is, but limited by the - * maximuum for png_size_t. The value can be overriden in a library build + * maximum for size_t. The value can be overridden in a library build * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably * lower value (e.g. 255 works). A lower value may help memory usage (slightly) * and may even improve performance on some systems (and degrade it on others.) @@ -214,7 +214,7 @@ struct png_struct_def png_uint_32 height; /* height of image in pixels */ png_uint_32 num_rows; /* number of rows in current pass */ png_uint_32 usr_width; /* width of row at start of write */ - png_size_t rowbytes; /* size of row in bytes */ + size_t rowbytes; /* size of row in bytes */ png_uint_32 iwidth; /* width of current interlaced row in pixels */ png_uint_32 row_number; /* current row in interlace pass */ png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ @@ -232,7 +232,7 @@ struct png_struct_def png_bytep try_row; /* buffer to save trial row when filtering */ png_bytep tst_row; /* buffer to save best trial row when filtering */ #endif - png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ + size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ png_uint_32 idat_size; /* current IDAT size for read */ png_uint_32 crc; /* current chunk CRC value */ @@ -307,7 +307,7 @@ struct png_struct_def #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ + png_color_8 shift; /* shift for significant bit transformation */ #endif #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ @@ -328,10 +328,10 @@ struct png_struct_def png_bytep current_buffer; /* buffer for recently used data */ png_uint_32 push_length; /* size of current input chunk */ png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ - png_size_t current_buffer_size; /* amount of data now in current_buffer */ + size_t save_buffer_size; /* amount of data now in save_buffer */ + size_t save_buffer_max; /* total size of save_buffer */ + size_t buffer_size; /* total amount of available input data */ + size_t current_buffer_size; /* amount of data now in current_buffer */ int process_mode; /* what push library is currently doing */ int cur_palette; /* current push library palette index */ @@ -451,7 +451,7 @@ struct png_struct_def #endif /* New member added in libpng-1.2.26 */ - png_size_t old_big_row_buf_size; + size_t old_big_row_buf_size; #ifdef PNG_READ_SUPPORTED /* New member added in libpng-1.2.30 */ diff --git a/thirdparty/libpng/pngtrans.c b/thirdparty/libpng/pngtrans.c index 6882f0fd7b..de84aa6d6b 100644 --- a/thirdparty/libpng/pngtrans.c +++ b/thirdparty/libpng/pngtrans.c @@ -1,8 +1,8 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.6.33 [September 28, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -269,8 +269,8 @@ png_do_invert(png_row_infop row_info, png_bytep row) if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i++) { @@ -283,8 +283,8 @@ png_do_invert(png_row_infop row_info, png_bytep row) row_info->bit_depth == 8) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i += 2) { @@ -298,8 +298,8 @@ png_do_invert(png_row_infop row_info, png_bytep row) row_info->bit_depth == 16) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i += 4) { @@ -609,7 +609,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) return; /* The filler channel has gone already */ /* Fix the rowbytes value. */ - row_info->rowbytes = (png_size_t)(dp-row); + row_info->rowbytes = (size_t)(dp-row); } #endif diff --git a/thirdparty/libpng/pngwio.c b/thirdparty/libpng/pngwio.c index 37c7c3a7f0..e5391687a2 100644 --- a/thirdparty/libpng/pngwio.c +++ b/thirdparty/libpng/pngwio.c @@ -1,8 +1,8 @@ /* pngwio.c - functions for data output * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2014,2016,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -30,7 +30,7 @@ */ void /* PRIVATE */ -png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) +png_write_data(png_structrp png_ptr, png_const_bytep data, size_t length) { /* NOTE: write_data_fn must not change the buffer! */ if (png_ptr->write_data_fn != NULL ) @@ -48,9 +48,9 @@ png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) * than changing the library. */ void PNGCBAPI -png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +png_default_write_data(png_structp png_ptr, png_bytep data, size_t length) { - png_size_t check; + size_t check; if (png_ptr == NULL) return; diff --git a/thirdparty/libpng/pngwrite.c b/thirdparty/libpng/pngwrite.c index a16d77ce00..5bd87f373e 100644 --- a/thirdparty/libpng/pngwrite.c +++ b/thirdparty/libpng/pngwrite.c @@ -1,8 +1,8 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -1636,7 +1636,7 @@ png_write_image_16bit(png_voidp argument) * calculation can be done to 15 bits of accuracy; however, the output needs to * be scaled in the range 0..255*65535, so include that scaling here. */ -# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) +# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+((alpha)>>1))/(alpha)) static png_byte png_unpremultiply(png_uint_32 component, png_uint_32 alpha, @@ -2162,8 +2162,7 @@ png_image_write_main(png_voidp argument) static void (PNGCBAPI -image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, - png_size_t size) +image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, size_t size) { png_image_write_control *display = png_voidcast(png_image_write_control*, png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/); diff --git a/thirdparty/libpng/pngwtran.c b/thirdparty/libpng/pngwtran.c index 377b43e5ca..3a1e0a21d2 100644 --- a/thirdparty/libpng/pngwtran.c +++ b/thirdparty/libpng/pngwtran.c @@ -1,8 +1,8 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -212,9 +212,9 @@ png_do_shift(png_row_infop row_info, png_bytep row, if (row_info->bit_depth < 8) { png_bytep bp = row; - png_size_t i; + size_t i; unsigned int mask; - png_size_t row_bytes = row_info->rowbytes; + size_t row_bytes = row_info->rowbytes; if (bit_depth->gray == 1 && row_info->bit_depth == 2) mask = 0x55; @@ -514,7 +514,7 @@ png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) (png_ptr, /* png_ptr */ row_info, /* row_info: */ /* png_uint_32 width; width of row */ - /* png_size_t rowbytes; number of bytes in row */ + /* size_t rowbytes; number of bytes in row */ /* png_byte color_type; color type of pixels */ /* png_byte bit_depth; bit depth of samples */ /* png_byte channels; number of channels (1-4) */ diff --git a/thirdparty/libpng/pngwutil.c b/thirdparty/libpng/pngwutil.c index 0d4fb1336c..ab431e712c 100644 --- a/thirdparty/libpng/pngwutil.c +++ b/thirdparty/libpng/pngwutil.c @@ -1,8 +1,8 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -59,7 +59,7 @@ png_write_sig(png_structrp png_ptr) /* Write the rest of the 8 byte signature */ png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], - (png_size_t)(8 - png_ptr->sig_bytes)); + (size_t)(8 - png_ptr->sig_bytes)); if (png_ptr->sig_bytes < 3) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; @@ -124,8 +124,7 @@ png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, * given to png_write_chunk_header(). */ void PNGAPI -png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, - png_size_t length) +png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, size_t length) { /* Write the data, and run the CRC over it */ if (png_ptr == NULL) @@ -160,7 +159,7 @@ png_write_chunk_end(png_structrp png_ptr) /* Write the crc in a single operation */ png_save_uint_32(buf, png_ptr->crc); - png_write_data(png_ptr, buf, (png_size_t)4); + png_write_data(png_ptr, buf, 4); } /* Write a PNG chunk all at once. The type is an array of ASCII characters @@ -174,7 +173,7 @@ png_write_chunk_end(png_structrp png_ptr) */ static void png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, - png_const_bytep data, png_size_t length) + png_const_bytep data, size_t length) { if (png_ptr == NULL) return; @@ -191,7 +190,7 @@ png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, /* This is the API that calls the internal function above. */ void PNGAPI png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, - png_const_bytep data, png_size_t length) + png_const_bytep data, size_t length) { png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, length); @@ -820,7 +819,7 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, buf[12] = (png_byte)interlace_type; /* Write the chunk */ - png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); + png_write_complete_chunk(png_ptr, png_IHDR, buf, 13); if ((png_ptr->do_filter) == PNG_NO_FILTERS) { @@ -889,7 +888,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, buf[0] = pal_ptr->red; buf[1] = pal_ptr->green; buf[2] = pal_ptr->blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); + png_write_chunk_data(png_ptr, buf, 3); } #else @@ -903,7 +902,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, buf[0] = pal_ptr[i].red; buf[1] = pal_ptr[i].green; buf[2] = pal_ptr[i].blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); + png_write_chunk_data(png_ptr, buf, 3); } #endif @@ -1075,7 +1074,7 @@ png_write_IEND(png_structrp png_ptr) { png_debug(1, "in png_write_IEND"); - png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); + png_write_complete_chunk(png_ptr, png_IEND, NULL, 0); png_ptr->mode |= PNG_HAVE_IEND; } @@ -1090,7 +1089,7 @@ png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) /* file_gamma is saved in 1/100,000ths */ png_save_uint_32(buf, (png_uint_32)file_gamma); - png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); + png_write_complete_chunk(png_ptr, png_gAMA, buf, 4); } #endif @@ -1108,7 +1107,7 @@ png_write_sRGB(png_structrp png_ptr, int srgb_intent) "Invalid sRGB rendering intent specified"); buf[0]=(png_byte)srgb_intent; - png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); + png_write_complete_chunk(png_ptr, png_sRGB, buf, 1); } #endif @@ -1182,8 +1181,8 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) png_uint_32 name_len; png_byte new_name[80]; png_byte entrybuf[10]; - png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); - png_size_t palette_size = entry_size * (png_size_t)spalette->nentries; + size_t entry_size = (spalette->depth == 8 ? 6 : 10); + size_t palette_size = entry_size * (size_t)spalette->nentries; png_sPLT_entryp ep; #ifndef PNG_POINTER_INDEXING_SUPPORTED int i; @@ -1200,10 +1199,9 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) png_write_chunk_header(png_ptr, png_sPLT, (png_uint_32)(name_len + 2 + palette_size)); - png_write_chunk_data(png_ptr, (png_bytep)new_name, - (png_size_t)(name_len + 1)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, (size_t)(name_len + 1)); - png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); + png_write_chunk_data(png_ptr, &spalette->depth, 1); /* Loop through each palette entry, writing appropriately */ #ifdef PNG_POINTER_INDEXING_SUPPORTED @@ -1265,7 +1263,7 @@ void /* PRIVATE */ png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) { png_byte buf[4]; - png_size_t size; + size_t size; png_debug(1, "in png_write_sBIT"); @@ -1365,7 +1363,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, /* Write the chunk out as it is */ png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, - (png_size_t)num_trans); + (size_t)num_trans); } else if (color_type == PNG_COLOR_TYPE_GRAY) @@ -1380,7 +1378,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, } png_save_uint_16(buf, tran->gray); - png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); + png_write_complete_chunk(png_ptr, png_tRNS, buf, 2); } else if (color_type == PNG_COLOR_TYPE_RGB) @@ -1400,7 +1398,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, return; } - png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); + png_write_complete_chunk(png_ptr, png_tRNS, buf, 6); } else @@ -1433,7 +1431,7 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) } buf[0] = back->index; - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); + png_write_complete_chunk(png_ptr, png_bKGD, buf, 1); } else if ((color_type & PNG_COLOR_MASK_COLOR) != 0) @@ -1454,7 +1452,7 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) return; } - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); + png_write_complete_chunk(png_ptr, png_bKGD, buf, 6); } else @@ -1468,7 +1466,7 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) } png_save_uint_16(buf, back->gray); - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); + png_write_complete_chunk(png_ptr, png_bKGD, buf, 2); } } #endif @@ -1488,7 +1486,7 @@ png_write_eXIf(png_structrp png_ptr, png_bytep exif, int num_exif) for (i = 0; i < num_exif; i++) { buf[0] = exif[i]; - png_write_chunk_data(png_ptr, buf, (png_size_t)1); + png_write_chunk_data(png_ptr, buf, 1); } png_write_chunk_end(png_ptr); @@ -1519,7 +1517,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) for (i = 0; i < num_hist; i++) { png_save_uint_16(buf, hist[i]); - png_write_chunk_data(png_ptr, buf, (png_size_t)2); + png_write_chunk_data(png_ptr, buf, 2); } png_write_chunk_end(png_ptr); @@ -1530,7 +1528,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) /* Write a tEXt chunk */ void /* PRIVATE */ png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, - png_size_t text_len) + size_t text_len) { png_uint_32 key_len; png_byte new_key[80]; @@ -1627,7 +1625,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, png_const_charp lang, png_const_charp lang_key, png_const_charp text) { png_uint_32 key_len, prefix_len; - png_size_t lang_len, lang_key_len; + size_t lang_len, lang_key_len; png_byte new_key[82]; compression_state comp; @@ -1737,7 +1735,7 @@ png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset, png_save_int_32(buf + 4, y_offset); buf[8] = (png_byte)unit_type; - png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); + png_write_complete_chunk(png_ptr, png_oFFs, buf, 9); } #endif #ifdef PNG_WRITE_pCAL_SUPPORTED @@ -1748,7 +1746,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, png_charpp params) { png_uint_32 purpose_len; - png_size_t units_len, total_len; + size_t units_len, total_len; png_size_tp params_len; png_byte buf[10]; png_byte new_purpose[80]; @@ -1772,7 +1770,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, total_len = purpose_len + units_len + 10; params_len = (png_size_tp)png_malloc(png_ptr, - (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (png_size_t)))); + (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (size_t)))); /* Find the length of each parameter, making sure we don't count the * null terminator for the last parameter. @@ -1792,8 +1790,8 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, png_save_int_32(buf + 4, X1); buf[8] = (png_byte)type; buf[9] = (png_byte)nparams; - png_write_chunk_data(png_ptr, buf, (png_size_t)10); - png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); + png_write_chunk_data(png_ptr, buf, 10); + png_write_chunk_data(png_ptr, (png_const_bytep)units, (size_t)units_len); for (i = 0; i < nparams; i++) { @@ -1812,7 +1810,7 @@ png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, png_const_charp height) { png_byte buf[64]; - png_size_t wlen, hlen, total_len; + size_t wlen, hlen, total_len; png_debug(1, "in png_write_sCAL_s"); @@ -1853,7 +1851,7 @@ png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, png_save_uint_32(buf + 4, y_pixels_per_unit); buf[8] = (png_byte)unit_type; - png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); + png_write_complete_chunk(png_ptr, png_pHYs, buf, 9); } #endif @@ -1883,7 +1881,7 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) buf[5] = mod_time->minute; buf[6] = mod_time->second; - png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); + png_write_complete_chunk(png_ptr, png_tIME, buf, 7); } #endif @@ -2073,8 +2071,8 @@ png_write_finish_row(png_structrp png_ptr) { if (png_ptr->prev_row != NULL) memset(png_ptr->prev_row, 0, - (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* - png_ptr->usr_bit_depth, png_ptr->width)) + 1); + PNG_ROWBYTES(png_ptr->usr_channels * + png_ptr->usr_bit_depth, png_ptr->width) + 1); return; } @@ -2130,7 +2128,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { - sp = row + (png_size_t)(i >> 3); + sp = row + (size_t)(i >> 3); value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; d |= (value << shift); @@ -2168,7 +2166,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { - sp = row + (png_size_t)(i >> 2); + sp = row + (size_t)(i >> 2); value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; d |= (value << shift); @@ -2204,7 +2202,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { - sp = row + (png_size_t)(i >> 1); + sp = row + (size_t)(i >> 1); value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; d |= (value << shift); @@ -2230,7 +2228,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) png_bytep dp; png_uint_32 i; png_uint_32 row_width = row_info->width; - png_size_t pixel_bytes; + size_t pixel_bytes; /* Start at the beginning */ dp = row; @@ -2243,7 +2241,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) i += png_pass_inc[pass]) { /* Find out where the original pixel is */ - sp = row + (png_size_t)i * pixel_bytes; + sp = row + (size_t)i * pixel_bytes; /* Move the pixel */ if (dp != sp) @@ -2274,16 +2272,16 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) */ static void /* PRIVATE */ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t row_bytes); + size_t row_bytes); #ifdef PNG_WRITE_FILTER_SUPPORTED -static png_size_t /* PRIVATE */ +static size_t /* PRIVATE */ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) + size_t row_bytes, size_t lmins) { png_bytep rp, dp, lp; - png_size_t i; - png_size_t sum = 0; + size_t i; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; @@ -2318,10 +2316,10 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, static void /* PRIVATE */ png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes) + size_t row_bytes) { png_bytep rp, dp, lp; - png_size_t i; + size_t i; png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; @@ -2338,13 +2336,12 @@ png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp, } } -static png_size_t /* PRIVATE */ -png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, - const png_size_t lmins) +static size_t /* PRIVATE */ +png_setup_up_row(png_structrp png_ptr, size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp; - png_size_t i; - png_size_t sum = 0; + size_t i; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; @@ -2367,10 +2364,10 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, return (sum); } static void /* PRIVATE */ -png_setup_up_row_only(png_structrp png_ptr, const png_size_t row_bytes) +png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes) { png_bytep rp, dp, pp; - png_size_t i; + size_t i; png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; @@ -2382,13 +2379,13 @@ png_setup_up_row_only(png_structrp png_ptr, const png_size_t row_bytes) } } -static png_size_t /* PRIVATE */ +static size_t /* PRIVATE */ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) + size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp, lp; png_uint_32 i; - png_size_t sum = 0; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; @@ -2424,7 +2421,7 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, } static void /* PRIVATE */ png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes) + size_t row_bytes) { png_bytep rp, dp, pp, lp; png_uint_32 i; @@ -2444,13 +2441,13 @@ png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, } } -static png_size_t /* PRIVATE */ +static size_t /* PRIVATE */ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) + size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp, cp, lp; - png_size_t i; - png_size_t sum = 0; + size_t i; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; @@ -2507,10 +2504,10 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, } static void /* PRIVATE */ png_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes) + size_t row_bytes) { png_bytep rp, dp, pp, cp, lp; - png_size_t i; + size_t i; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; @@ -2559,8 +2556,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) png_bytep row_buf; png_bytep best_row; png_uint_32 bpp; - png_size_t mins; - png_size_t row_bytes = row_info->rowbytes; + size_t mins; + size_t row_bytes = row_info->rowbytes; png_debug(1, "in png_write_find_filter"); @@ -2615,8 +2612,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) * 'none' filter. */ png_bytep rp; - png_size_t sum = 0; - png_size_t i; + size_t sum = 0; + size_t i; unsigned int v; { @@ -2644,8 +2641,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_SUB) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); @@ -2670,8 +2667,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_UP) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_up_row(png_ptr, row_bytes, lmins); @@ -2696,8 +2693,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_AVG) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); @@ -2722,8 +2719,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_PAETH) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); @@ -2748,7 +2745,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* Do the actual writing of a previously filtered row. */ static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t full_row_length/*includes filter byte*/) + size_t full_row_length/*includes filter byte*/) { png_debug(1, "in png_write_filtered_row"); diff --git a/thirdparty/libwebsockets/lws_config.h b/thirdparty/libwebsockets/lws_config.h index 7185a806a5..e5e15cc2fd 100644 --- a/thirdparty/libwebsockets/lws_config.h +++ b/thirdparty/libwebsockets/lws_config.h @@ -174,7 +174,7 @@ #define LWS_HAVE_MALLOC_H #endif -#if !defined(IPHONE_ENABLED) && !defined(OSX_ENABLED) +#if !defined(IPHONE_ENABLED) && !defined(OSX_ENABLED) && !defined(__HAIKU__) #define LWS_HAVE_PIPE2 #endif diff --git a/thirdparty/libwebsockets/lws_config_private.h b/thirdparty/libwebsockets/lws_config_private.h index 9d04078fef..b26d225afa 100644 --- a/thirdparty/libwebsockets/lws_config_private.h +++ b/thirdparty/libwebsockets/lws_config_private.h @@ -81,7 +81,7 @@ /* Define to 1 if you have the <sys/prctl.h> header file. */ #define LWS_HAVE_SYS_PRCTL_H -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) || defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) #undef LWS_HAVE_SYS_PRCTL_H #endif diff --git a/thirdparty/mbedtls/1453.diff b/thirdparty/mbedtls/1453.diff index fef60fc0e6..6630ad861f 100644 --- a/thirdparty/mbedtls/1453.diff +++ b/thirdparty/mbedtls/1453.diff @@ -1,5 +1,5 @@ diff --git a/library/entropy_poll.c b/library/entropy_poll.c -index 67900c46..cefe882d 100644 +index 67900c46c8..cefe882d2a 100644 --- a/library/entropy_poll.c +++ b/library/entropy_poll.c @@ -54,28 +54,43 @@ @@ -54,7 +54,7 @@ index 67900c46..cefe882d 100644 return( 0 ); diff --git a/library/x509_crt.c b/library/x509_crt.c -index 290c1eb3..038eae02 100644 +index 290c1eb3d1..3cf1743821 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -65,6 +65,19 @@ @@ -81,7 +81,7 @@ index 290c1eb3..038eae02 100644 char filename[MAX_PATH]; char *p; size_t len = strlen( path ); -+ int lengthAsInt = 0; ++ int length_as_int = 0; WIN32_FIND_DATAW file_data; HANDLE hFind; @@ -90,7 +90,7 @@ index 290c1eb3..038eae02 100644 filename[len++] = '*'; - w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, -+ if ( FAILED ( SizeTToInt( len, &lengthAsInt ) ) ) ++ if ( FAILED ( SizeTToInt( len, &length_as_int ) ) ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + /* @@ -101,7 +101,7 @@ index 290c1eb3..038eae02 100644 + * incoming string are less than MAX_PATH to avoid a buffer overrun with + * MultiByteToWideChar(). + */ -+ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir, ++ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, length_as_int, szDir, MAX_PATH - 3 ); if( w_ret == 0 ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); @@ -109,12 +109,12 @@ index 290c1eb3..038eae02 100644 if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) continue; -+ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &lengthAsInt ) ) ) ++ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &length_as_int ) ) ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, - lstrlenW( file_data.cFileName ), -+ lengthAsInt, ++ length_as_int, p, (int) len - 1, NULL, NULL ); if( w_ret == 0 ) diff --git a/thirdparty/mbedtls/include/mbedtls/aes.h b/thirdparty/mbedtls/include/mbedtls/aes.h index dd5c1183a5..f6603d5962 100644 --- a/thirdparty/mbedtls/include/mbedtls/aes.h +++ b/thirdparty/mbedtls/include/mbedtls/aes.h @@ -13,6 +13,11 @@ * <em>ISO/IEC 18033-2:2006: Information technology -- Security * techniques -- Encryption algorithms -- Part 2: Asymmetric * ciphers</em>. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * <https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38e.pdf> + * and described in detail by IEEE P1619 + * <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>. */ /* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. @@ -89,6 +94,19 @@ typedef struct } mbedtls_aes_context; +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief The AES XTS context-type definition. + */ +typedef struct +{ + mbedtls_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #else /* MBEDTLS_AES_ALT */ #include "aes_alt.h" #endif /* MBEDTLS_AES_ALT */ @@ -110,6 +128,25 @@ void mbedtls_aes_init( mbedtls_aes_context *ctx ); */ void mbedtls_aes_free( mbedtls_aes_context *ctx ); +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. + */ +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + */ +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /** * \brief This function sets the encryption key. * @@ -142,6 +179,44 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ); +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * \param keybits The size of \p key passed in bits. Valid options are: + * <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li> + * <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul> + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * \param keybits The size of \p key passed in bits. Valid options are: + * <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li> + * <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul> + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /** * \brief This function performs an AES single-block encryption or * decryption operation. @@ -213,6 +288,49 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, unsigned char *output ); #endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function performs an AES-XTS encryption or decryption + * operation for an entire XTS data unit. + * + * AES-XTS encrypts or decrypts blocks based on their location as + * defined by a data unit number. The data unit number must be + * provided by \p data_unit. + * + * NIST SP 800-38E limits the maximum size of a data unit to 2^20 + * AES blocks. If the data unit is larger than this, this function + * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. + * + * \param ctx The AES XTS context to use for AES XTS operations. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of a data unit in bytes. This can be any + * length between 16 bytes and 2^24 bytes inclusive + * (between 1 and 2^20 block cipher blocks). + * \param data_unit The address of the data unit encoded as an array of 16 + * bytes in little-endian format. For disk encryption, this + * is typically the index of the block device sector that + * contains the data. + * \param input The buffer holding the input data (which is an entire + * data unit). This function reads \p length bytes from \p + * input. + * \param output The buffer holding the output data (which is an entire + * data unit). This function writes \p length bytes to \p + * output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is + * smaller than an AES block in size (16 bytes) or if \p + * length is larger than 2^20 blocks (16 MiB). + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_CIPHER_MODE_CFB) /** * \brief This function performs an AES-CFB128 encryption or decryption @@ -296,6 +414,56 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, unsigned char *output ); #endif /*MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * For OFB, you must set up the context with + * mbedtls_aes_setkey_enc(), regardless of whether you are + * performing an encryption or decryption operation. This is + * because OFB mode uses the same key schedule for encryption and + * decryption. + * + * The OFB operation is identical for encryption or decryption, + * therefore no operation mode needs to be specified. + * + * \note Upon exit, the content of iv, the Initialisation Vector, is + * updated so that you can call the same function again on the next + * block(s) of data and get the same result as if it was encrypted + * in one call. This allows a "streaming" usage, by initialising + * iv_off to 0 before the first call, and preserving its value + * between calls. + * + * For non-streaming use, the iv should be initialised on each call + * to a unique value, and iv_off set to 0 on each call. + * + * If you need to retain the contents of the initialisation vector, + * you must either save it manually or use the cipher module + * instead. + * + * \warning For the OFB mode, the initialisation vector must be unique + * every encryption operation. Reuse of an initialisation vector + * will compromise security. + * + * \param ctx The AES context to use for encryption or decryption. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) /** * \brief This function performs an AES-CTR encryption or decryption diff --git a/thirdparty/mbedtls/include/mbedtls/bn_mul.h b/thirdparty/mbedtls/include/mbedtls/bn_mul.h index f4b2b561d1..b587317d95 100644 --- a/thirdparty/mbedtls/include/mbedtls/bn_mul.h +++ b/thirdparty/mbedtls/include/mbedtls/bn_mul.h @@ -49,7 +49,14 @@ /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ #if defined(__GNUC__) && \ ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) -#if defined(__i386__) + +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) #define MULADDC_INIT \ asm( \ @@ -142,7 +149,7 @@ "movl %%esi, %3 \n\t" \ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ ); #else @@ -154,7 +161,7 @@ "movl %%esi, %3 \n\t" \ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ ); #endif /* SSE2 */ #endif /* i386 */ diff --git a/thirdparty/mbedtls/include/mbedtls/ccm.h b/thirdparty/mbedtls/include/mbedtls/ccm.h index 8585ce5e7c..5d727e7cca 100644 --- a/thirdparty/mbedtls/include/mbedtls/ccm.h +++ b/thirdparty/mbedtls/include/mbedtls/ccm.h @@ -14,6 +14,18 @@ * <li>Nonce - A unique value that is assigned to the payload and the * associated data.</li></ul> * + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + * + * Definition of CCM*: + * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks + * Integer representation is fixed most-significant-octet-first order and + * the representation of octets is most-significant-bit-first order. This is + * consistent with RFC 3610. */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved @@ -102,7 +114,6 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); /** * \brief This function encrypts a buffer using CCM. * - * * \note The tag is written to a separate buffer. To concatenate * the \p tag with the \p output, as done in <em>RFC-3610: * Counter with CBC-MAC (CCM)</em>, use @@ -112,15 +123,17 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); * \param ctx The CCM context to use for encryption. * \param length The length of the input data in Bytes. * \param iv Initialization vector (nonce). - * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. * \param add The additional data field. * \param add_len The length of additional data in Bytes. * Must be less than 2^16 - 2^8. * \param input The buffer holding the input data. * \param output The buffer holding the output data. * Must be at least \p length Bytes wide. - * \param tag The buffer holding the tag. - * \param tag_len The length of the tag to generate in Bytes: + * \param tag The buffer holding the authentication field. + * \param tag_len The length of the authentication field to generate in Bytes: * 4, 6, 8, 10, 12, 14 or 16. * * \return \c 0 on success. @@ -133,21 +146,64 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, unsigned char *tag, size_t tag_len ); /** + * \brief This function encrypts a buffer using CCM*. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in <em>RFC-3610: + * Counter with CBC-MAC (CCM)</em>, use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \note When using this function in a variable tag length context, + * the tag length has to be encoded into the \p iv passed to + * this function. + * + * \param ctx The CCM context to use for encryption. + * \param length The length of the input data in Bytes. + * \param iv Initialization vector (nonce). + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. + * \param add_len The length of additional data in Bytes. + * Must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * Must be at least \p length Bytes wide. + * \param tag The buffer holding the authentication field. + * \param tag_len The length of the authentication field to generate in Bytes: + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing 0 as \p tag_len means that the message is no + * longer authenticated. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** * \brief This function performs a CCM authenticated decryption of a * buffer. * * \param ctx The CCM context to use for decryption. * \param length The length of the input data in Bytes. - * \param iv Initialization vector. - * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13. + * \param iv Initialization vector (nonce). + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. * \param add The additional data field. * \param add_len The length of additional data in Bytes. * Must be less than 2^16 - 2^8. * \param input The buffer holding the input data. * \param output The buffer holding the output data. * Must be at least \p length Bytes wide. - * \param tag The buffer holding the tag. - * \param tag_len The length of the tag in Bytes. + * \param tag The buffer holding the authentication field. + * \param tag_len The length of the authentication field in Bytes. * 4, 6, 8, 10, 12, 14 or 16. * * \return \c 0 on success. This indicates that the message is authentic. @@ -160,6 +216,43 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len ); +/** + * \brief This function performs a CCM* authenticated decryption of a + * buffer. + * + * \note When using this function in a variable tag length context, + * the tag length has to be decoded from \p iv and passed to + * this function as \p tag_len. (\p tag needs to be adjusted + * accordingly.) + * + * \param ctx The CCM context to use for decryption. + * \param length The length of the input data in Bytes. + * \param iv Initialization vector (nonce). + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. + * \param add_len The length of additional data in Bytes. + * Must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * Must be at least \p length Bytes wide. + * \param tag The buffer holding the authentication field. + * \param tag_len The length of the authentication field in Bytes. + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing 0 as \p tag_len means that the message is no + * longer authenticated. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /** diff --git a/thirdparty/mbedtls/include/mbedtls/chacha20.h b/thirdparty/mbedtls/include/mbedtls/chacha20.h new file mode 100644 index 0000000000..47bd7d38b9 --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/chacha20.h @@ -0,0 +1,212 @@ +/** + * \file chacha20.h + * + * \brief This file contains ChaCha20 definitions and functions. + * + * ChaCha20 is a stream cipher that can encrypt and decrypt + * information. ChaCha was created by Daniel Bernstein as a variant of + * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf + * ChaCha20 is the variant with 20 rounds, that was also standardized + * in RFC 7539. + * + * \author Daniel King <damaki.gh@gmail.com> + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CHACHA20_H +#define MBEDTLS_CHACHA20_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include <stdint.h> +#include <stddef.h> + +#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */ +#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */ +#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CHACHA20_ALT) + +typedef struct +{ + uint32_t state[16]; /*! The state (before round operations). */ + uint8_t keystream8[64]; /*! Leftover keystream bytes. */ + size_t keystream_bytes_used; /*! Number of keystream bytes already used. */ +} +mbedtls_chacha20_context; + +#else /* MBEDTLS_CHACHA20_ALT */ +#include "chacha20_alt.h" +#endif /* MBEDTLS_CHACHA20_ALT */ + +/** + * \brief This function initializes the specified ChaCha20 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by calls to + * \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts(), then one or more calls to + * to \c mbedtls_chacha20_update(), and finally to + * \c mbedtls_chacha20_free(). + * + * \param ctx The ChaCha20 context to initialize. + */ +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function releases and clears the specified ChaCha20 context. + * + * \param ctx The ChaCha20 context to clear. + */ +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function sets the encryption/decryption key. + * + * \note After using this function, you must also call + * \c mbedtls_chacha20_starts() to set a nonce before you + * start encrypting/decrypting data with + * \c mbedtls_chacha_update(). + * + * \param ctx The ChaCha20 context to which the key should be bound. + * \param key The encryption/decryption key. Must be 32 bytes in length. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. + */ +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function sets the nonce and initial counter value. + * + * \note A ChaCha20 context can be re-used with the same key by + * calling this function to change the nonce. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality guarantees for the + * messages encrypted with the same nonce and key. + * + * \param ctx The ChaCha20 context to which the nonce should be bound. + * \param nonce The nonce. Must be 12 bytes in size. + * \param counter The initial counter value. This is usually 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is + * NULL. + */ +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ); + +/** + * \brief This function encrypts or decrypts data. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \note \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts() must be called at least once + * to setup the context before this function can be called. + * + * \note This function can be called multiple times in a row in + * order to encrypt of decrypt data piecewise with the same + * key and nonce. + * + * \param ctx The ChaCha20 context to use for encryption or decryption. + * \param size The length of the input data in bytes. + * \param input The buffer holding the input data. + * This pointer can be NULL if size == 0. + * \param output The buffer holding the output data. + * Must be able to hold \p size bytes. + * This pointer can be NULL if size == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if the ctx, input, or + * output pointers are NULL. + */ +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function encrypts or decrypts data with ChaCha20 and + * the given key and nonce. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \warning You must never use the same (key, nonce) pair more than + * once. This would void any confidentiality guarantees for + * the messages encrypted with the same nonce and key. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \param key The encryption/decryption key. Must be 32 bytes in length. + * \param nonce The nonce. Must be 12 bytes in size. + * \param counter The initial counter value. This is usually 0. + * \param size The length of the input data in bytes. + * \param input The buffer holding the input data. + * This pointer can be NULL if size == 0. + * \param output The buffer holding the output data. + * Must be able to hold \p size bytes. + * This pointer can be NULL if size == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if key, nonce, input, + * or output is NULL. + */ +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t size, + const unsigned char* input, + unsigned char* output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chacha20_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHA20_H */ diff --git a/thirdparty/mbedtls/include/mbedtls/chachapoly.h b/thirdparty/mbedtls/include/mbedtls/chachapoly.h new file mode 100644 index 0000000000..42b2b230c5 --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/chachapoly.h @@ -0,0 +1,355 @@ +/** + * \file chachapoly.h + * + * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and + * functions. + * + * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption + * with Associated Data (AEAD) that can be used to encrypt and + * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel + * Bernstein and was standardized in RFC 7539. + * + * \author Daniel King <damaki.gh@gmail.com> + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CHACHAPOLY_H +#define MBEDTLS_CHACHAPOLY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* for shared error codes */ +#include "poly1305.h" + +#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /**< The requested operation is not permitted in the current state. */ +#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 /**< Authenticated decryption failed: data was not authentic. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */ + MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */ +} +mbedtls_chachapoly_mode_t; + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#include "chacha20.h" + +typedef struct +{ + mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */ + mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */ + uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */ + uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */ + int state; /**< The current state of the context. */ + mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */ +} +mbedtls_chachapoly_context; + +#else /* !MBEDTLS_CHACHAPOLY_ALT */ +#include "chachapoly_alt.h" +#endif /* !MBEDTLS_CHACHAPOLY_ALT */ + +/** + * \brief This function initializes the specified ChaCha20-Poly1305 context. + * + * It must be the first API called before using + * the context. It must be followed by a call to + * \c mbedtls_chachapoly_setkey() before any operation can be + * done, and to \c mbedtls_chachapoly_free() once all + * operations with that context have been finished. + * + * In order to encrypt or decrypt full messages at once, for + * each message you should make a single call to + * \c mbedtls_chachapoly_crypt_and_tag() or + * \c mbedtls_chachapoly_auth_decrypt(). + * + * In order to encrypt messages piecewise, for each + * message you should make a call to + * \c mbedtls_chachapoly_starts(), then 0 or more calls to + * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to + * \c mbedtls_chachapoly_update(), then one call to + * \c mbedtls_chachapoly_finish(). + * + * \warning Decryption with the piecewise API is discouraged! Always + * use \c mbedtls_chachapoly_auth_decrypt() when possible! + * + * If however this is not possible because the data is too + * large to fit in memory, you need to: + * + * - call \c mbedtls_chachapoly_starts() and (if needed) + * \c mbedtls_chachapoly_update_aad() as above, + * - call \c mbedtls_chachapoly_update() multiple times and + * ensure its output (the plaintext) is NOT used in any other + * way than placing it in temporary storage at this point, + * - call \c mbedtls_chachapoly_finish() to compute the + * authentication tag and compared it in constant time to the + * tag received with the ciphertext. + * + * If the tags are not equal, you must immediately discard + * all previous outputs of \c mbedtls_chachapoly_update(), + * otherwise you can now safely use the plaintext. + * + * \param ctx The ChachaPoly context to initialize. + */ +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function releases and clears the specified ChaCha20-Poly1305 context. + * + * \param ctx The ChachaPoly context to clear. + */ +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function sets the ChaCha20-Poly1305 symmetric encryption key. + * + * \param ctx The ChaCha20-Poly1305 context to which the key should be + * bound. + * \param key The 256-bit (32 bytes) key. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p key are NULL. + */ +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function starts a ChaCha20-Poly1305 encryption or + * decryption operation. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \note If the context is being used for AAD only (no data to + * encrypt or decrypt) then \p mode can be set to any value. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. + * \param nonce The nonce/IV to use for the message. Must be 12 bytes. + * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or + * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p mac are NULL. + */ +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ); + +/** + * \brief This function feeds additional data to be authenticated + * into an ongoing ChaCha20-Poly1305 operation. + * + * The Additional Authenticated Data (AAD), also called + * Associated Data (AD) is only authenticated but not + * encrypted nor included in the encrypted output. It is + * usually transmitted separately from the ciphertext or + * computed locally by each party. + * + * \note This function is called before data is encrypted/decrypted. + * I.e. call this function to process the AAD before calling + * \c mbedtls_chachapoly_update(). + * + * You may call this function multiple times to process + * an arbitrary amount of AAD. It is permitted to call + * this function 0 times, if no AAD is used. + * + * This function cannot be called any more if data has + * been processed by \c mbedtls_chachapoly_update(), + * or if the context has been finished. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context to use. + * \param aad_len The length (in bytes) of the AAD. The length has no + * restrictions. + * \param aad Buffer containing the AAD. + * This pointer can be NULL if aad_len == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p aad are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operations has not been started or has been + * finished, or if the AAD has been finished. + */ +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ); + +/** + * \brief Thus function feeds data to be encrypted or decrypted + * into an on-going ChaCha20-Poly1305 + * operation. + * + * The direction (encryption or decryption) depends on the + * mode that was given when calling + * \c mbedtls_chachapoly_starts(). + * + * You may call this function multiple times to process + * an arbitrary amount of data. It is permitted to call + * this function 0 times, if no data is to be encrypted + * or decrypted. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context to use. + * \param len The length (in bytes) of the data to encrypt or decrypt. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be NULL if len == 0. + * \param output The buffer to where the encrypted or decrypted data is written. + * Must be able to hold \p len bytes. + * This pointer can be NULL if len == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx, \p input, or \p output are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + */ +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finished the ChaCha20-Poly1305 operation and + * generates the MAC (authentication tag). + * + * \param ctx The ChaCha20-Poly1305 context to use. + * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p mac are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + */ +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated encryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * \param length The length (in bytes) of the data to encrypt or decrypt. + * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated data (AAD). + * This pointer can be NULL if aad_len == 0. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be NULL if ilen == 0. + * \param output The buffer to where the encrypted or decrypted data is written. + * This pointer can be NULL if ilen == 0. + * \param tag The buffer to where the computed 128-bit (16 bytes) MAC is written. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if one or more of the required parameters are NULL. + */ +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated decryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * \param length The length (in bytes) of the data to decrypt. + * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated data (AAD). + * This pointer can be NULL if aad_len == 0. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param tag The buffer holding the authentication tag. + * \param input The buffer containing the data to decrypt. + * This pointer can be NULL if ilen == 0. + * \param output The buffer to where the decrypted data is written. + * This pointer can be NULL if ilen == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if one or more of the required parameters are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED + * if the data was not authentic. + */ +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20-Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chachapoly_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHAPOLY_H */ diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h index be80332963..9e6bb8a46a 100644 --- a/thirdparty/mbedtls/include/mbedtls/check_config.h +++ b/thirdparty/mbedtls/include/mbedtls/check_config.h @@ -4,7 +4,7 @@ * \brief Consistency checks for configuration options */ /* - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -87,6 +87,11 @@ #error "MBEDTLS_CMAC_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_NIST_KW_C) && \ + ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECDH_C defined, but not all prerequisites" #endif @@ -191,6 +196,10 @@ #error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HKDF_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) #error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" #endif diff --git a/thirdparty/mbedtls/include/mbedtls/cipher.h b/thirdparty/mbedtls/include/mbedtls/cipher.h index 46b3bdfefa..ea0ce983f1 100644 --- a/thirdparty/mbedtls/include/mbedtls/cipher.h +++ b/thirdparty/mbedtls/include/mbedtls/cipher.h @@ -37,7 +37,7 @@ #include <stddef.h> -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) #define MBEDTLS_CIPHER_MODE_AEAD #endif @@ -45,7 +45,7 @@ #define MBEDTLS_CIPHER_MODE_WITH_PADDING #endif -#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) #define MBEDTLS_CIPHER_MODE_STREAM #endif @@ -87,6 +87,7 @@ typedef enum { MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ } mbedtls_cipher_id_t; /** @@ -164,6 +165,13 @@ typedef enum { MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ + MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ } mbedtls_cipher_type_t; /** Supported cipher modes. */ @@ -172,11 +180,13 @@ typedef enum { MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ - MBEDTLS_MODE_OFB, /**< The OFB cipher mode - unsupported. */ + MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ + MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ } mbedtls_cipher_mode_t; /** Supported cipher padding types. */ @@ -292,7 +302,8 @@ typedef struct { /** Number of Bytes that have not been processed yet. */ size_t unprocessed_len; - /** Current IV or NONCE_COUNTER for CTR-mode. */ + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; /** IV size in Bytes, for ciphers with variable-length IVs. */ @@ -579,11 +590,11 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, */ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** * \brief This function adds additional data for AEAD ciphers. - * Only supported with GCM. Must be called - * exactly once, after mbedtls_cipher_reset(). + * Currently supported with GCM and ChaCha20+Poly1305. + * Must be called exactly once, after mbedtls_cipher_reset(). * * \param ctx The generic cipher context. * \param ad The additional data to use. @@ -594,7 +605,7 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); */ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len ); -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** * \brief The generic cipher update function. It encrypts or @@ -652,10 +663,10 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen ); -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** * \brief This function writes a tag for AEAD ciphers. - * Only supported with GCM. + * Currently supported with GCM and ChaCha20+Poly1305. * Must be called after mbedtls_cipher_finish(). * * \param ctx The generic cipher context. @@ -670,7 +681,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, /** * \brief This function checks the tag for AEAD ciphers. - * Only supported with GCM. + * Currently supported with GCM and ChaCha20+Poly1305. * Must be called after mbedtls_cipher_finish(). * * \param ctx The generic cipher context. @@ -682,7 +693,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, */ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len ); -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** * \brief The generic all-in-one encryption/decryption function, diff --git a/thirdparty/mbedtls/include/mbedtls/cipher_internal.h b/thirdparty/mbedtls/include/mbedtls/cipher_internal.h index 969ff9ccb8..c6def0bef7 100644 --- a/thirdparty/mbedtls/include/mbedtls/cipher_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/cipher_internal.h @@ -64,6 +64,14 @@ struct mbedtls_cipher_base_t unsigned char *output ); #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /** Encrypt using OFB (Full length) */ + int (*ofb_func)( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, + const unsigned char *input, + unsigned char *output ); +#endif + #if defined(MBEDTLS_CIPHER_MODE_CTR) /** Encrypt using CTR */ int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, @@ -71,6 +79,13 @@ struct mbedtls_cipher_base_t const unsigned char *input, unsigned char *output ); #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + /** Encrypt or decrypt using XTS. */ + int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length, + const unsigned char data_unit[16], + const unsigned char *input, unsigned char *output ); +#endif + #if defined(MBEDTLS_CIPHER_MODE_STREAM) /** Encrypt using STREAM */ int (*stream_func)( void *ctx, size_t length, diff --git a/thirdparty/mbedtls/include/mbedtls/cmac.h b/thirdparty/mbedtls/include/mbedtls/cmac.h index 913c05f8a7..a4fd552565 100644 --- a/thirdparty/mbedtls/include/mbedtls/cmac.h +++ b/thirdparty/mbedtls/include/mbedtls/cmac.h @@ -28,7 +28,7 @@ #ifndef MBEDTLS_CMAC_H #define MBEDTLS_CMAC_H -#include "mbedtls/cipher.h" +#include "cipher.h" #ifdef __cplusplus extern "C" { diff --git a/thirdparty/mbedtls/include/mbedtls/compat-1.3.h b/thirdparty/mbedtls/include/mbedtls/compat-1.3.h index 600a0f154c..213b691403 100644 --- a/thirdparty/mbedtls/include/mbedtls/compat-1.3.h +++ b/thirdparty/mbedtls/include/mbedtls/compat-1.3.h @@ -1378,7 +1378,8 @@ #define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED #define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED #define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED -#define SSL_BUFFER_LEN MBEDTLS_SSL_BUFFER_LEN +#define SSL_BUFFER_LEN ( ( ( MBEDTLS_SSL_IN_BUFFER_LEN ) < ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) \ + ? ( MBEDTLS_SSL_IN_BUFFER_LEN ) : ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) #define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES #define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT #define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h index ae10a4d728..70820be56f 100644 --- a/thirdparty/mbedtls/include/mbedtls/config.h +++ b/thirdparty/mbedtls/include/mbedtls/config.h @@ -8,7 +8,7 @@ * memory footprint. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -89,6 +89,28 @@ //#define MBEDTLS_NO_UDBL_DIVISION /** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** * \def MBEDTLS_HAVE_SSE2 * * CPU supports SSE2 instruction set. @@ -279,14 +301,18 @@ //#define MBEDTLS_BLOWFISH_ALT //#define MBEDTLS_CAMELLIA_ALT //#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT //#define MBEDTLS_CMAC_ALT //#define MBEDTLS_DES_ALT //#define MBEDTLS_DHM_ALT //#define MBEDTLS_ECJPAKE_ALT //#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT //#define MBEDTLS_MD2_ALT //#define MBEDTLS_MD4_ALT //#define MBEDTLS_MD5_ALT +//#define MBEDTLS_POLY1305_ALT //#define MBEDTLS_RIPEMD160_ALT //#define MBEDTLS_RSA_ALT //#define MBEDTLS_SHA1_ALT @@ -516,6 +542,20 @@ #define MBEDTLS_CIPHER_MODE_CTR /** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +#define MBEDTLS_CIPHER_MODE_XTS + +/** * \def MBEDTLS_CIPHER_NULL_CIPHER * * Enable NULL cipher. @@ -1135,6 +1175,17 @@ #define MBEDTLS_SSL_ALL_ALERT_MESSAGES /** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** * \def MBEDTLS_SSL_DEBUG_ALL * * Enable the debug messages in SSL module for all issues. @@ -1920,6 +1971,26 @@ #define MBEDTLS_CERTS_C /** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#define MBEDTLS_CHACHAPOLY_C + +/** * \def MBEDTLS_CIPHER_C * * Enable the generic cipher layer. @@ -2150,6 +2221,21 @@ //#define MBEDTLS_HAVEGE_C /** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#define MBEDTLS_HKDF_C + +/** * \def MBEDTLS_HMAC_DRBG_C * * Enable the HMAC_DRBG random generator. @@ -2164,6 +2250,19 @@ #define MBEDTLS_HMAC_DRBG_C /** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** * \def MBEDTLS_MD_C * * Enable the generic message digest layer. @@ -2447,6 +2546,16 @@ #define MBEDTLS_PLATFORM_C /** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#define MBEDTLS_POLY1305_C + +/** * \def MBEDTLS_RIPEMD160_C * * Enable the RIPEMD-160 hash algorithm. @@ -2856,7 +2965,51 @@ //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ /* SSL options */ -//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum fragment length in bytes. + * + * Determines the size of both the incoming and outgoing TLS I/O buffers. + * + * Uncommenting MBEDTLS_SSL_IN_CONTENT_LEN and/or MBEDTLS_SSL_OUT_CONTENT_LEN + * will override this length by setting maximum incoming and/or outgoing + * fragment length, respectively. + */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum incoming fragment length in bytes. + * + * Uncomment to set the size of the inward TLS buffer independently of the + * outward buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum outgoing fragment length in bytes. + * + * Uncomment to set the size of the outward TLS buffer independently of the + * inward buffer. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * For absolute minimum RAM usage, it's best to enable + * MBEDTLS_SSL_MAX_FRAGMENT_LENGTH and reduce MBEDTLS_SSL_MAX_CONTENT_LEN. This + * reduces both incoming and outgoing buffer sizes. However this is only + * guaranteed if the other end of the connection also supports the TLS + * max_fragment_len extension. Otherwise the connection may fail. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + //#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ //#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ //#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ @@ -2933,7 +3086,7 @@ /* \} name SECTION: Customisation configuration options */ /* Target and application specific configurations */ -//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "mbedtls/target_config.h" +//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "target_config.h" #if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE) #include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h index dcbc047924..3835d7299b 100644 --- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h @@ -36,7 +36,7 @@ #include "aes.h" #if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" +#include "threading.h" #endif #define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ diff --git a/thirdparty/mbedtls/include/mbedtls/error.h b/thirdparty/mbedtls/include/mbedtls/error.h index a17f8d8ace..6b82d4fbbe 100644 --- a/thirdparty/mbedtls/include/mbedtls/error.h +++ b/thirdparty/mbedtls/include/mbedtls/error.h @@ -4,7 +4,7 @@ * \brief Error to string translation */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -62,7 +62,7 @@ * DES 2 0x0032-0x0032 0x0033-0x0033 * CTR_DBRG 4 0x0034-0x003A * ENTROPY 3 0x003C-0x0040 0x003D-0x003F - * NET 11 0x0042-0x0052 0x0043-0x0045 + * NET 13 0x0042-0x0052 0x0043-0x0049 * ARIA 4 0x0058-0x005E * ASN1 7 0x0060-0x006C * CMAC 1 0x007A-0x007A @@ -77,6 +77,9 @@ * SHA1 1 0x0035-0x0035 * SHA256 1 0x0037-0x0037 * SHA512 1 0x0039-0x0039 + * CHACHA20 3 0x0051-0x0055 + * POLY1305 3 0x0057-0x005B + * CHACHAPOLY 2 0x0054-0x0056 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors @@ -89,8 +92,9 @@ * RSA 4 11 * ECP 4 9 (Started from top) * MD 5 5 + * HKDF 5 1 (Started from top) * CIPHER 6 8 - * SSL 6 17 (Started from top) + * SSL 6 22 (Started from top) * SSL 7 31 * * Module dependent error code (5 bits 0x.00.-0x.F8.) diff --git a/thirdparty/mbedtls/include/mbedtls/gcm.h b/thirdparty/mbedtls/include/mbedtls/gcm.h index bec5577142..87535ab957 100644 --- a/thirdparty/mbedtls/include/mbedtls/gcm.h +++ b/thirdparty/mbedtls/include/mbedtls/gcm.h @@ -113,21 +113,41 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, * the same as input buffer. If the buffers overlap, the output * buffer must trail at least 8 Bytes behind the input buffer. * + * \warning When this function performs a decryption, it outputs the + * authentication tag and does not verify that the data is + * authentic. You should use this function to perform encryption + * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. + * * \param ctx The GCM context to use for encryption or decryption. - * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or - * #MBEDTLS_GCM_DECRYPT. - * \param length The length of the input data. This must be a multiple of - * 16 except in the last call before mbedtls_gcm_finish(). + * \param mode The operation to perform: + * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. + * The ciphertext is written to \p output and the + * authentication tag is written to \p tag. + * - #MBEDTLS_GCM_DECRYPT to perform decryption. + * The plaintext is written to \p output and the + * authentication tag is written to \p tag. + * Note that this mode is not recommended, because it does + * not verify the authenticity of the data. For this reason, + * you should use mbedtls_gcm_auth_decrypt() instead of + * calling this function in decryption mode. + * \param length The length of the input data, which is equal to the length + * of the output data. * \param iv The initialization vector. * \param iv_len The length of the IV. * \param add The buffer holding the additional data. * \param add_len The length of the additional data. - * \param input The buffer holding the input data. - * \param output The buffer for holding the output data. + * \param input The buffer holding the input data. Its size is \b length. + * \param output The buffer for holding the output data. It must have room + * for \b length bytes. * \param tag_len The length of the tag to generate. * \param tag The buffer for holding the tag. * - * \return \c 0 on success. + * \return \c 0 if the encryption or decryption was performed + * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, + * this does not indicate that the data is authentic. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid. + * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific + * error code if the encryption or decryption failed. */ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, int mode, @@ -150,19 +170,23 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, * must trail at least 8 Bytes behind the input buffer. * * \param ctx The GCM context. - * \param length The length of the input data. This must be a multiple - * of 16 except in the last call before mbedtls_gcm_finish(). + * \param length The length of the ciphertext to decrypt, which is also + * the length of the decrypted plaintext. * \param iv The initialization vector. * \param iv_len The length of the IV. * \param add The buffer holding the additional data. * \param add_len The length of the additional data. - * \param tag The buffer holding the tag. - * \param tag_len The length of the tag. - * \param input The buffer holding the input data. - * \param output The buffer for holding the output data. + * \param tag The buffer holding the tag to verify. + * \param tag_len The length of the tag to verify. + * \param input The buffer holding the ciphertext. Its size is \b length. + * \param output The buffer for holding the decrypted plaintext. It must + * have room for \b length bytes. * - * \return 0 if successful and authenticated. - * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + * \return \c 0 if successful and authenticated. + * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid. + * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific + * error code if the decryption failed. */ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, size_t length, diff --git a/thirdparty/mbedtls/include/mbedtls/hkdf.h b/thirdparty/mbedtls/include/mbedtls/hkdf.h new file mode 100644 index 0000000000..6833e7272e --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/hkdf.h @@ -0,0 +1,125 @@ +/** + * \file hkdf.h + * + * \brief This file contains the HKDF interface. + * + * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is + * specified by RFC 5869. + */ +/* + * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_HKDF_H +#define MBEDTLS_HKDF_H + +#include "md.h" + +/** + * \name HKDF Error codes + * \{ + */ +#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function + * (HKDF). + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros of + * md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ); + +/** + * \brief Take the input keying material \p ikm and extract from it a + * fixed-length pseudorandom key \p prk. + * + * \param md A hash function; md.size denotes the length of the + * hash function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros + * of md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param[out] prk A pseudorandom key of at least md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ); + +/** + * \brief Expand the supplied \p prk into several additional pseudorandom + * keys, which is the output of the HKDF. + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param prk A pseudorandom key of at least md.size bytes. \p prk is usually, + * the output from the HKDF extract step. + * \param prk_len The length in bytes of \p prk. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* hkdf.h */ diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h index e0821cf788..2608de8595 100644 --- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h @@ -27,7 +27,7 @@ #include "md.h" #if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" +#include "threading.h" #endif /* diff --git a/thirdparty/mbedtls/include/mbedtls/net.h b/thirdparty/mbedtls/include/mbedtls/net.h index 28ae8217c0..6c13b53fb9 100644 --- a/thirdparty/mbedtls/include/mbedtls/net.h +++ b/thirdparty/mbedtls/include/mbedtls/net.h @@ -1,7 +1,7 @@ /** * \file net.h * - * \brief Deprecated header file that includes mbedtls/net_sockets.h + * \brief Deprecated header file that includes net_sockets.h * * \deprecated Superseded by mbedtls/net_sockets.h */ @@ -25,7 +25,7 @@ */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) -#include "mbedtls/net_sockets.h" +#include "net_sockets.h" #if defined(MBEDTLS_DEPRECATED_WARNING) #warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" #endif /* MBEDTLS_DEPRECATED_WARNING */ diff --git a/thirdparty/mbedtls/include/mbedtls/net_sockets.h b/thirdparty/mbedtls/include/mbedtls/net_sockets.h index 0f9b31ebcb..9f07eeb4d3 100644 --- a/thirdparty/mbedtls/include/mbedtls/net_sockets.h +++ b/thirdparty/mbedtls/include/mbedtls/net_sockets.h @@ -1,7 +1,23 @@ /** * \file net_sockets.h * - * \brief Network communication functions + * \brief Network sockets abstraction layer to integrate Mbed TLS into a + * BSD-style sockets API. + * + * The network sockets module provides an example integration of the + * Mbed TLS library into a BSD sockets implementation. The module is + * intended to be an example of how Mbed TLS can be integrated into a + * networking stack, as well as to be Mbed TLS's network integration + * for its supported platforms. + * + * The module is intended only to be used with the Mbed TLS library and + * is not intended to be used by third party application software + * directly. + * + * The supported platforms are as follows: + * * Microsoft Windows and Windows CE + * * POSIX/Unix platforms including Linux, OS X + * */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved diff --git a/thirdparty/mbedtls/include/mbedtls/nist_kw.h b/thirdparty/mbedtls/include/mbedtls/nist_kw.h new file mode 100644 index 0000000000..5a0f656a8f --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/nist_kw.h @@ -0,0 +1,178 @@ +/** + * \file nist_kw.h + * + * \brief This file provides an API for key wrapping (KW) and key wrapping with + * padding (KWP) as defined in NIST SP 800-38F. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * + * Key wrapping specifies a deterministic authenticated-encryption mode + * of operation, according to <em>NIST SP 800-38F: Recommendation for + * Block Cipher Modes of Operation: Methods for Key Wrapping</em>. Its + * purpose is to protect cryptographic keys. + * + * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP. + * https://tools.ietf.org/html/rfc3394 + * https://tools.ietf.org/html/rfc5649 + * + */ +/* + * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_NIST_KW_H +#define MBEDTLS_NIST_KW_H + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_KW_MODE_KW = 0, + MBEDTLS_KW_MODE_KWP = 1 +} mbedtls_nist_kw_mode_t; + +#if !defined(MBEDTLS_NIST_KW_ALT) +// Regular implementation +// + +/** + * \brief The key wrapping context-type definition. The key wrapping context is passed + * to the APIs called. + * + * \note The definition of this type may change in future library versions. + * Don't make any assumptions on this context! + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} mbedtls_nist_kw_context; + +#else /* MBEDTLS_NIST_key wrapping_ALT */ +#include "nist_kw_alt.h" +#endif /* MBEDTLS_NIST_KW_ALT */ + +/** + * \brief This function initializes the specified key wrapping context + * to make references valid and prepare the context + * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free(). + * + * \param ctx The key wrapping context to initialize. + * + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function initializes the key wrapping context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The key wrapping context. + * \param cipher The 128-bit block cipher to use. Only AES is supported. + * \param key The Key Encryption Key (KEK). + * \param keybits The KEK size in bits. This must be acceptable by the cipher. + * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input. + * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers + * which are not supported. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ); + +/** + * \brief This function releases and clears the specified key wrapping context + * and underlying cipher sub-context. + * + * \param ctx The key wrapping context to clear. + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function encrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for encryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + * <ul><li>For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive. </li> + * <li>For KWP mode: any length between 1 and 2^32-1 inclusive.</li></ul> + * \param[out] output The buffer holding the output data. + * <ul><li>For KW mode: Must be at least 8 bytes larger than \p in_len.</li> + * <li>For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of + * 8 bytes for KWP (15 bytes at most).</li></ul> + * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size ); + +/** + * \brief This function decrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for decryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + * The input must be a multiple of semiblocks. + * <ul><li>For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive. </li> + * <li>For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.</li></ul> + * \param[out] output The buffer holding the output data. + * The output buffer's minimal length is 8 bytes shorter than \p in_len. + * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * For KWP mode, the length could be up to 15 bytes shorter than \p in_len, + * depending on how much padding was added to the data. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size); + + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The key wrapping checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_nist_kw_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_NIST_KW_H */ diff --git a/thirdparty/mbedtls/include/mbedtls/oid.h b/thirdparty/mbedtls/include/mbedtls/oid.h index 408645ece7..f82554844c 100644 --- a/thirdparty/mbedtls/include/mbedtls/oid.h +++ b/thirdparty/mbedtls/include/mbedtls/oid.h @@ -97,6 +97,8 @@ /* ISO arc for standard certificate and CRL extensions */ #define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ + /** * Private Internet Extensions * { iso(1) identified-organization(3) dod(6) internet(1) @@ -219,12 +221,12 @@ #define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ #define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ #define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ @@ -241,8 +243,21 @@ */ #define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ #define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ /* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ +/* * PKCS#5 OIDs */ #define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ diff --git a/thirdparty/mbedtls/include/mbedtls/platform.h b/thirdparty/mbedtls/include/mbedtls/platform.h index bba770911e..624cc642ac 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform.h +++ b/thirdparty/mbedtls/include/mbedtls/platform.h @@ -40,7 +40,7 @@ #endif #if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" +#include "platform_time.h" #endif #ifdef __cplusplus @@ -121,8 +121,8 @@ extern "C" { #else /* For size_t */ #include <stddef.h> -extern void * (*mbedtls_calloc)( size_t n, size_t size ); -extern void (*mbedtls_free)( void *ptr ); +extern void *mbedtls_calloc( size_t n, size_t size ); +extern void mbedtls_free( void *ptr ); /** * \brief This function dynamically sets the memory-management diff --git a/thirdparty/mbedtls/include/mbedtls/poly1305.h b/thirdparty/mbedtls/include/mbedtls/poly1305.h new file mode 100644 index 0000000000..54b50abc25 --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/poly1305.h @@ -0,0 +1,181 @@ +/** + * \file poly1305.h + * + * \brief This file contains Poly1305 definitions and functions. + * + * Poly1305 is a one-time message authenticator that can be used to + * authenticate messages. Poly1305-AES was created by Daniel + * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic + * Poly1305 algorithm (not tied to AES) was also standardized in RFC + * 7539. + * + * \author Daniel King <damaki.gh@gmail.com> + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_POLY1305_H +#define MBEDTLS_POLY1305_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include <stdint.h> +#include <stddef.h> + +#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */ +#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */ +#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_POLY1305_ALT) + +typedef struct +{ + uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */ + uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */ + uint32_t acc[5]; /** The accumulator number. */ + uint8_t queue[16]; /** The current partial block of data. */ + size_t queue_len; /** The number of bytes stored in 'queue'. */ +} +mbedtls_poly1305_context; + +#else /* MBEDTLS_POLY1305_ALT */ +#include "poly1305_alt.h" +#endif /* MBEDTLS_POLY1305_ALT */ + +/** + * \brief This function initializes the specified Poly1305 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by a call to + * \c mbedtls_poly1305_starts(), then one or more calls to + * \c mbedtls_poly1305_update(), then one call to + * \c mbedtls_poly1305_finish(), then finally + * \c mbedtls_poly1305_free(). + * + * \param ctx The Poly1305 context to initialize. + */ +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function releases and clears the specified Poly1305 context. + * + * \param ctx The Poly1305 context to clear. + */ +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function sets the one-time authentication key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param ctx The Poly1305 context to which the key should be bound. + * \param key The buffer containing the 256-bit key. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if ctx or key are NULL. + */ +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This functions feeds an input buffer into an ongoing + * Poly1305 computation. + * + * It is called between \c mbedtls_cipher_poly1305_starts() and + * \c mbedtls_cipher_poly1305_finish(). + * It can be called repeatedly to process a stream of data. + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * \param ilen The length of the input data (in bytes). Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be NULL if ilen == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if ctx or input are NULL. + */ +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function generates the Poly1305 Message + * Authentication Code (MAC). + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * \param mac The buffer to where the MAC is written. Must be big enough + * to hold the 16-byte MAC. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if ctx or mac are NULL. + */ +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function calculates the Poly1305 MAC of the input + * buffer with the provided key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param key The buffer containing the 256-bit key. + * \param ilen The length of the input data (in bytes). Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be NULL if ilen == 0. + * \param mac The buffer to where the MAC is written. Must be big enough + * to hold the 16-byte MAC. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if key, input, or mac are NULL. + */ +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_poly1305_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_POLY1305_H */ diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h index 250031a6d3..2d511a8ea1 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl.h @@ -62,7 +62,7 @@ #endif #if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" +#include "platform_time.h" #endif /* @@ -120,6 +120,7 @@ #define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ #define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ #define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */ +#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */ /* * Various constants @@ -219,7 +220,7 @@ #endif /* - * Maxium fragment length in bytes, + * Maximum fragment length in bytes, * determines the size of each of the two internal I/O buffers. * * Note: the RFC defines the default size of SSL / TLS messages. If you @@ -233,6 +234,14 @@ #define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ #endif +#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN) +#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + +#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + /* \} name SECTION: Module settings */ /* @@ -536,7 +545,6 @@ typedef void mbedtls_ssl_set_timer_t( void * ctx, */ typedef int mbedtls_ssl_get_timer_t( void * ctx ); - /* Defined below */ typedef struct mbedtls_ssl_session mbedtls_ssl_session; typedef struct mbedtls_ssl_context mbedtls_ssl_context; @@ -553,6 +561,218 @@ typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; #endif +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Callback type: start external signature operation. + * + * This callback is called during an SSL handshake to start + * a signature decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p hash if the value + * is needed for later processing, because the \p hash buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \note For RSA signatures, this function must produce output + * that is consistent with PKCS#1 v1.5 in the same way as + * mbedtls_rsa_pkcs1_sign(). Before the private key operation, + * apply the padding steps described in RFC 8017, section 9.2 + * "EMSA-PKCS1-v1_5" as follows. + * - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the DigestInfo to be + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 3, with `T = hash` and `tLen = hash_len`. + * - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the hash to be encoded and + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 2, with `digestAlgorithm` obtained by calling + * mbedtls_oid_get_oid_by_md() on \p md_alg. + * + * \note For ECDSA signatures, the output format is the DER encoding + * `Ecdsa-Sig-Value` defined in + * [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4). + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param md_alg Hash algorithm. + * \param hash Buffer containing the hash. This buffer is + * no longer valid when the function returns. + * \param hash_len Size of the \c hash buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b> + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + mbedtls_md_type_t md_alg, + const unsigned char *hash, + size_t hash_len ); + +/** + * \brief Callback type: start external decryption operation. + * + * This callback is called during an SSL handshake to start + * an RSA decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p input if the value + * is needed for later processing, because the \p input buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \warning RSA decryption as used in TLS is subject to a potential + * timing side channel attack first discovered by Bleichenbacher + * in 1998. This attack can be remotely exploitable + * in practice. To avoid this attack, you must ensure that + * if the callback performs an RSA decryption, the time it + * takes to execute and return the result does not depend + * on whether the RSA decryption succeeded or reported + * invalid padding. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param input Buffer containing the input ciphertext. This buffer + * is no longer valid when the function returns. + * \param input_len Size of the \p input buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b> + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_decrypt_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + const unsigned char *input, + size_t input_len ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Callback type: resume external operation. + * + * This callback is called during an SSL handshake to resume + * an external operation started by the + * ::mbedtls_ssl_async_sign_t or + * ::mbedtls_ssl_async_decrypt_t callback. + * + * This function typically checks the status of a pending + * request or causes the request queue to make progress, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * It may call mbedtls_ssl_set_async_operation_data() to modify + * this context. + * + * Note that when this function returns a status other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any + * resources associated with the operation. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param output Buffer containing the output (signature or decrypted + * data) on success. + * \param output_len On success, number of bytes written to \p output. + * \param output_size Size of the \p output buffer in bytes. + * + * \return 0 if output of the operation is available in the + * \p output buffer. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * is still in progress. Subsequent requests for progress + * on the SSL connection will call the resume callback + * again. + * \return Any other error means that the operation is aborted. + * The SSL handshake is aborted. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b> + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl, + unsigned char *output, + size_t *output_len, + size_t output_size ); + +/** + * \brief Callback type: cancel external operation. + * + * This callback is called if an SSL connection is closed + * while an asynchronous operation is in progress. Note that + * this callback is not called if the + * ::mbedtls_ssl_async_resume_t callback has run and has + * returned a value other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case + * the asynchronous operation has already completed. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * + * \param ssl The SSL connection instance. It should not be + * modified. + */ +typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + /* * This structure is used for storing current session data. */ @@ -669,6 +889,16 @@ struct mbedtls_ssl_config mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */ + mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */ + mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */ + void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) const int *sig_hashes; /*!< allowed signature hashes */ #endif @@ -1307,6 +1537,85 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, void *p_export_keys ); #endif /* MBEDTLS_SSL_EXPORT_KEYS */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +/** + * \brief Configure asynchronous private key operation callbacks. + * + * \param conf SSL configuration context + * \param f_async_sign Callback to start a signature operation. See + * the description of ::mbedtls_ssl_async_sign_t + * for more information. This may be \c NULL if the + * external processor does not support any signature + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_decrypt Callback to start a decryption operation. See + * the description of ::mbedtls_ssl_async_decrypt_t + * for more information. This may be \c NULL if the + * external processor does not support any decryption + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_resume Callback to resume an asynchronous operation. See + * the description of ::mbedtls_ssl_async_resume_t + * for more information. This may not be \c NULL unless + * \p f_async_sign and \p f_async_decrypt are both + * \c NULL. + * \param f_async_cancel Callback to cancel an asynchronous operation. See + * the description of ::mbedtls_ssl_async_cancel_t + * for more information. This may be \c NULL if + * no cleanup is needed. + * \param config_data A pointer to configuration data which can be + * retrieved with + * mbedtls_ssl_conf_get_async_config_data(). The + * library stores this value without dereferencing it. + */ +void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *config_data ); + +/** + * \brief Retrieve the configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + * + * \param conf SSL configuration context + * \return The configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + */ +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * + * \return The asynchronous operation user context that was last + * set during the current handshake. If + * mbedtls_ssl_set_async_operation_data() has not yet been + * called during the current handshake, this function returns + * \c NULL. + */ +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * \param ctx The new value of the asynchronous operation user context. + * Call mbedtls_ssl_get_async_operation_data() later during the + * same handshake to retrieve this value. + */ +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + /** * \brief Callback type: generate a cookie * @@ -2117,7 +2426,8 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** * \brief Set the maximum fragment length to emit and/or negotiate - * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * (Default: the smaller of MBEDTLS_SSL_IN_CONTENT_LEN and + * MBEDTLS_SSL_OUT_CONTENT_LEN, usually 2^14 bytes) * (Server: set maximum fragment length to emit, * usually negotiated by the client during handshake * (Client: set maximum fragment length to emit *and* @@ -2436,7 +2746,6 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss * \brief Save session in order to resume it later (client-side only) * Session data is copied to presented session structure. * - * \warning Currently, peer certificate is lost in the operation. * * \param ssl SSL context * \param session session context @@ -2444,7 +2753,18 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss * \return 0 if successful, * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or - * arguments are otherwise invalid + * arguments are otherwise invalid. + * + * \note Only the server certificate is copied, and not the full chain, + * so you should not attempt to validate the certificate again + * by calling \c mbedtls_x509_crt_verify() on it. + * Instead, you should use the results from the verification + * in the original handshake by calling \c mbedtls_ssl_get_verify_result() + * after loading the session again into a new SSL context + * using \c mbedtls_ssl_set_session(). + * + * \note Once the session object is not needed anymore, you should + * free it by calling \c mbedtls_ssl_session_free(). * * \sa mbedtls_ssl_set_session() */ @@ -2606,17 +2926,19 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, * or another negative error code. * - * \note If this function returns something other than a positive value - * or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using - * the SSL context for reading or writing, and either free it or - * call \c mbedtls_ssl_session_reset() on it before re-using it - * for a new connection; the current connection must be closed. + * \note If this function returns something other than 0, a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop + * using the SSL context for reading or writing, and either + * free it or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. * * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, * it must be called later with the *same* arguments, - * until it returns a positive value. When the function returns - * MBEDTLS_ERR_SSL_WANT_WRITE there may be some partial - * data in the output buffer, however this is not yet sent. + * until it returns a value greater that or equal to 0. When + * the function returns MBEDTLS_ERR_SSL_WANT_WRITE there may be + * some partial data in the output buffer, however this is not + * yet sent. * * \note If the requested length is greater than the maximum * fragment length (either the built-in limit or the one set @@ -2625,6 +2947,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. * \c mbedtls_ssl_get_max_frag_len() may be used to query the * active maximum fragment length. + * + * \note Attempting to write 0 bytes will result in an empty TLS + * application record being sent. */ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); @@ -2717,6 +3042,9 @@ void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); * \brief Free referenced items in an SSL session including the * peer certificate and clear memory * + * \note A session object can be freed even if the SSL context + * that was used to retrieve the session is still in use. + * * \param session SSL session */ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h b/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h index 7d5eba0916..cda8b4835b 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -271,6 +271,15 @@ extern "C" { #define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ +/* RFC 7905 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */ + /* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below */ diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h index 60b431a0f4..d214703d77 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h @@ -143,32 +143,73 @@ #define MBEDTLS_SSL_PADDING_ADD 0 #endif -#define MBEDTLS_SSL_PAYLOAD_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \ - + MBEDTLS_SSL_COMPRESSION_ADD \ - + MBEDTLS_MAX_IV_LENGTH \ - + MBEDTLS_SSL_MAC_ADD \ - + MBEDTLS_SSL_PADDING_ADD \ - ) +#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_SSL_COMPRESSION_ADD + \ + MBEDTLS_MAX_IV_LENGTH + \ + MBEDTLS_SSL_MAC_ADD + \ + MBEDTLS_SSL_PADDING_ADD \ + ) + +#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_IN_CONTENT_LEN ) ) + +#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_OUT_CONTENT_LEN ) ) + +/* Maximum length we can advertise as our max content length for + RFC 6066 max_fragment_length extension negotiation purposes + (the lesser of both sizes, if they are unequal.) + */ +#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ + (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ + ? ( MBEDTLS_SSL_OUT_CONTENT_LEN ) \ + : ( MBEDTLS_SSL_IN_CONTENT_LEN ) \ + ) /* * Check that we obey the standard's message size bounds */ #if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384 -#error Bad configuration - record content too large. +#error "Bad configuration - record content too large." +#endif + +#if MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - incoming record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_OUT_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - outgoing record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - incoming protected record payload too large." #endif -#if MBEDTLS_SSL_PAYLOAD_LEN > 16384 + 2048 -#error Bad configuration - protected record payload too large. +#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - outgoing protected record payload too large." #endif +/* Calculate buffer sizes */ + /* Note: Even though the TLS record header is only 5 bytes long, we're internally using 8 bytes to store the implicit sequence number. */ #define MBEDTLS_SSL_HEADER_LEN 13 -#define MBEDTLS_SSL_BUFFER_LEN \ - ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_PAYLOAD_LEN ) ) +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) ) + +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) ) + +#ifdef MBEDTLS_ZLIB_SUPPORT +/* Compression buffer holds both IN and OUT buffers, so should be size of the larger */ +#define MBEDTLS_SSL_COMPRESS_BUFFER_LEN ( \ + ( MBEDTLS_SSL_IN_BUFFER_LEN > MBEDTLS_SSL_OUT_BUFFER_LEN ) \ + ? MBEDTLS_SSL_IN_BUFFER_LEN \ + : MBEDTLS_SSL_OUT_BUFFER_LEN \ + ) +#endif /* * TLS extension flags (for extensions with outgoing ServerHello content @@ -243,6 +284,7 @@ struct mbedtls_ssl_handshake_params mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ @@ -307,6 +349,19 @@ struct mbedtls_ssl_handshake_params #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) int extended_ms; /*!< use Extended Master Secret? */ #endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + unsigned int async_in_progress : 1; /*!< an asynchronous operation is in progress */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /** Asynchronous operation context. This field is meant for use by the + * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, + * mbedtls_ssl_config::f_async_decrypt_start, + * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). + * The library does not use it internally. */ + void *user_async_ctx; +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ }; /* @@ -410,9 +465,9 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); * \brief Free referenced items in an SSL handshake context and clear * memory * - * \param handshake SSL handshake context + * \param ssl SSL context */ -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ); +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ); int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); @@ -630,7 +685,13 @@ static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t volatile unsigned char diff = 0; for( i = 0; i < n; i++ ) - diff |= A[i] ^ B[i]; + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } return( diff ); } @@ -646,9 +707,9 @@ int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_2) int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, - unsigned char *output, - unsigned char *data, size_t data_len, - mbedtls_md_type_t md_alg ); + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ); #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ MBEDTLS_SSL_PROTO_TLS1_2 */ diff --git a/thirdparty/mbedtls/include/mbedtls/threading.h b/thirdparty/mbedtls/include/mbedtls/threading.h index aeea5d0e1a..c25daa5cdf 100644 --- a/thirdparty/mbedtls/include/mbedtls/threading.h +++ b/thirdparty/mbedtls/include/mbedtls/threading.h @@ -99,9 +99,6 @@ extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); #if defined(MBEDTLS_FS_IO) extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; #endif -#if defined(MBEDTLS_HAVE_TIME_DATE) -extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; -#endif #endif /* MBEDTLS_THREADING_C */ #ifdef __cplusplus diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h index 83e3c1726b..eaf25d908c 100644 --- a/thirdparty/mbedtls/include/mbedtls/version.h +++ b/thirdparty/mbedtls/include/mbedtls/version.h @@ -39,7 +39,7 @@ * Major, Minor, Patchlevel */ #define MBEDTLS_VERSION_MAJOR 2 -#define MBEDTLS_VERSION_MINOR 10 +#define MBEDTLS_VERSION_MINOR 12 #define MBEDTLS_VERSION_PATCH 0 /** @@ -47,9 +47,9 @@ * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x020A0000 -#define MBEDTLS_VERSION_STRING "2.10.0" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.10.0" +#define MBEDTLS_VERSION_NUMBER 0x020C0000 +#define MBEDTLS_VERSION_STRING "2.12.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.12.0" #if defined(MBEDTLS_VERSION_C) diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c index fea9b5383d..5c939bba47 100644 --- a/thirdparty/mbedtls/library/aes.c +++ b/thirdparty/mbedtls/library/aes.c @@ -521,6 +521,20 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx ) mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) ); } +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ) +{ + mbedtls_aes_init( &ctx->crypt ); + mbedtls_aes_init( &ctx->tweak ); +} + +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) +{ + mbedtls_aes_free( &ctx->crypt ); + mbedtls_aes_free( &ctx->tweak ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /* * AES key schedule (encryption) */ @@ -702,6 +716,78 @@ exit: return( ret ); } + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int mbedtls_aes_xts_decode_keys( const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits ) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch( keybits ) + { + case 256: break; + case 512: break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; +} + +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for encryption. */ + return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits ); +} + +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for decryption. */ + return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ @@ -983,6 +1069,165 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, } #endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + +/* Endianess with 64 bits values */ +#ifndef GET_UINT64_LE +#define GET_UINT64_LE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ + | ( (uint64_t) (b)[(i) + 6] << 48 ) \ + | ( (uint64_t) (b)[(i) + 5] << 40 ) \ + | ( (uint64_t) (b)[(i) + 4] << 32 ) \ + | ( (uint64_t) (b)[(i) + 3] << 24 ) \ + | ( (uint64_t) (b)[(i) + 2] << 16 ) \ + | ( (uint64_t) (b)[(i) + 1] << 8 ) \ + | ( (uint64_t) (b)[(i) ] ); \ +} +#endif + +#ifndef PUT_UINT64_LE +#define PUT_UINT64_LE(n,b,i) \ +{ \ + (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) ] = (unsigned char) ( (n) ); \ +} +#endif + +typedef unsigned char mbedtls_be128[16]; + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void mbedtls_gf128mul_x_ble( unsigned char r[16], + const unsigned char x[16] ) +{ + uint64_t a, b, ra, rb; + + GET_UINT64_LE( a, x, 0 ); + GET_UINT64_LE( b, x, 8 ); + + ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); + rb = ( a >> 63 ) | ( b << 1 ); + + PUT_UINT64_LE( ra, r, 0 ); + PUT_UINT64_LE( rb, r, 8 ); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + /* Sectors must be at least 16 bytes. */ + if( length < 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* NIST SP 80-38E disallows data units larger than 2**20 blocks. */ + if( length > ( 1 << 20 ) * 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* Compute the tweak. */ + ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak ); + if( ret != 0 ) + return( ret ); + + while( blocks-- ) + { + size_t i; + + if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) + { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy( prev_tweak, tweak, sizeof( tweak ) ); + mbedtls_gf128mul_x_ble( tweak, tweak ); + } + + for( i = 0; i < 16; i++ ) + tmp[i] = input[i] ^ tweak[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return( ret ); + + for( i = 0; i < 16; i++ ) + output[i] = tmp[i] ^ tweak[i]; + + /* Update the tweak for the next block. */ + mbedtls_gf128mul_x_ble( tweak, tweak ); + + output += 16; + input += 16; + } + + if( leftover ) + { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for( i = 0; i < leftover; i++ ) + { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for( ; i < 16; i++ ) + tmp[i] = prev_output[i] ^ t[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return ret; + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for( i = 0; i < 16; i++ ) + prev_output[i] = tmp[i] ^ t[i]; + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * AES-CFB128 buffer encryption/decryption @@ -1061,7 +1306,41 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, return( 0 ); } -#endif /*MBEDTLS_CIPHER_MODE_CFB */ +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = 0; + size_t n = *iv_off; + + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + *output++ = *input++ ^ iv[n]; + + n = ( n + 1 ) & 0x0F; + } + + *iv_off = n; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* @@ -1218,6 +1497,72 @@ static const unsigned char aes_test_cfb128_ct[3][64] = }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB test vectors from: + * + * https://csrc.nist.gov/publications/detail/sp/800-38a/final + */ +static const unsigned char aes_test_ofb_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_ofb_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_ofb_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_ofb_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, + 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, + 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, + 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, + 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * AES-CTR test vectors from: @@ -1281,6 +1626,74 @@ static const int aes_test_ctr_len[3] = { 16, 32, 36 }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/* + * AES-XTS test vectors from: + * + * IEEE P1619/D16 Annex B + * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) + */ +static const unsigned char aes_test_xts_key[][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, + { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, +}; + +static const unsigned char aes_test_xts_pt32[][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, +}; + +static const unsigned char aes_test_xts_ct32[][32] = +{ + { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, + 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, + 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, + 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, + { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, + 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, + 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, + 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, + { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, +}; + +static const unsigned char aes_test_xts_data_unit[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /* * Checkup routine */ @@ -1297,11 +1710,14 @@ int mbedtls_aes_self_test( int verbose ) #if defined(MBEDTLS_CIPHER_MODE_CBC) unsigned char prv[16]; #endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_OFB) size_t offset; #endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) int len; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) unsigned char nonce_counter[16]; unsigned char stream_block[16]; #endif @@ -1509,6 +1925,69 @@ int mbedtls_aes_self_test( int verbose ) mbedtls_printf( "\n" ); #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /* + * OFB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-OFB-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_ofb_iv, 16 ); + memcpy( key, aes_test_ofb_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ofb_ct[u], 64 ); + aes_tests = aes_test_ofb_pt; + } + else + { + memcpy( buf, aes_test_ofb_pt, 64 ); + aes_tests = aes_test_ofb_ct[u]; + } + + ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * CTR mode @@ -1561,6 +2040,73 @@ int mbedtls_aes_self_test( int verbose ) mbedtls_printf( "\n" ); #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { + static const int num_tests = + sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); + mbedtls_aes_xts_context ctx_xts; + + /* + * XTS mode + */ + mbedtls_aes_xts_init( &ctx_xts ); + + for( i = 0; i < num_tests << 1; i++ ) + { + const unsigned char *data_unit; + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-XTS-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( key, 0, sizeof( key ) ); + memcpy( key, aes_test_xts_key[u], 32 ); + data_unit = aes_test_xts_data_unit[u]; + + len = sizeof( *aes_test_xts_ct32 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_ct32[u], len ); + aes_tests = aes_test_xts_pt32[u]; + } + else + { + ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_pt32[u], len ); + aes_tests = aes_test_xts_ct32[u]; + } + + + ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit, + buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + mbedtls_aes_xts_free( &ctx_xts ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + ret = 0; exit: diff --git a/thirdparty/mbedtls/library/asn1write.c b/thirdparty/mbedtls/library/asn1write.c index c01c836550..72acdf3012 100644 --- a/thirdparty/mbedtls/library/asn1write.c +++ b/thirdparty/mbedtls/library/asn1write.c @@ -83,7 +83,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len return( 4 ); } +#if SIZE_MAX > 0xFFFFFFFF if( len <= 0xFFFFFFFF ) +#endif { if( *p - start < 5 ) return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); @@ -96,7 +98,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len return( 5 ); } +#if SIZE_MAX > 0xFFFFFFFF return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +#endif } int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) diff --git a/thirdparty/mbedtls/library/ccm.c b/thirdparty/mbedtls/library/ccm.c index cf6520935e..804eaf80f1 100644 --- a/thirdparty/mbedtls/library/ccm.c +++ b/thirdparty/mbedtls/library/ccm.c @@ -152,8 +152,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, * Check length requirements: SP800-38C A.1 * Additional requirement: a < 2^16 - 2^8 to simplify the code. * 'length' checked later (when writing it to the first block) + * + * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). */ - if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) + if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 ) return( MBEDTLS_ERR_CCM_BAD_INPUT ); /* Also implies q is within bounds */ @@ -302,7 +304,7 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, /* * Authenticated encryption */ -int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, @@ -312,10 +314,23 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, add, add_len, input, output, tag, tag_len ) ); } +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} + /* * Authenticated decryption */ -int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, @@ -346,6 +361,18 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, return( 0 ); } +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} #endif /* !MBEDTLS_CCM_ALT */ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) diff --git a/thirdparty/mbedtls/library/chacha20.c b/thirdparty/mbedtls/library/chacha20.c new file mode 100644 index 0000000000..d14a51e044 --- /dev/null +++ b/thirdparty/mbedtls/library/chacha20.c @@ -0,0 +1,570 @@ +/** + * \file chacha20.c + * + * \brief ChaCha20 cipher. + * + * \author Daniel King <damaki.gh@gmail.com> + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CHACHA20_C) + +#include "mbedtls/chacha20.h" +#include "mbedtls/platform_util.h" + +#include <stddef.h> +#include <string.h> + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdio.h> +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHA20_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define BYTES_TO_U32_LE( data, offset ) \ + ( (uint32_t) data[offset] \ + | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \ + ) + +#define ROTL32( value, amount ) \ + ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) ) + +#define CHACHA20_CTR_INDEX ( 12U ) + +#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U ) + +/** + * \brief ChaCha20 quarter round operation. + * + * The quarter round is defined as follows (from RFC 7539): + * 1. a += b; d ^= a; d <<<= 16; + * 2. c += d; b ^= c; b <<<= 12; + * 3. a += b; d ^= a; d <<<= 8; + * 4. c += d; b ^= c; b <<<= 7; + * + * \param state ChaCha20 state to modify. + * \param a The index of 'a' in the state. + * \param b The index of 'b' in the state. + * \param c The index of 'c' in the state. + * \param d The index of 'd' in the state. + */ +static inline void chacha20_quarter_round( uint32_t state[16], + size_t a, + size_t b, + size_t c, + size_t d ) +{ + /* a += b; d ^= a; d <<<= 16; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 16 ); + + /* c += d; b ^= c; b <<<= 12 */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 12 ); + + /* a += b; d ^= a; d <<<= 8; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 8 ); + + /* c += d; b ^= c; b <<<= 7; */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 7 ); +} + +/** + * \brief Perform the ChaCha20 inner block operation. + * + * This function performs two rounds: the column round and the + * diagonal round. + * + * \param state The ChaCha20 state to update. + */ +static void chacha20_inner_block( uint32_t state[16] ) +{ + chacha20_quarter_round( state, 0, 4, 8, 12 ); + chacha20_quarter_round( state, 1, 5, 9, 13 ); + chacha20_quarter_round( state, 2, 6, 10, 14 ); + chacha20_quarter_round( state, 3, 7, 11, 15 ); + + chacha20_quarter_round( state, 0, 5, 10, 15 ); + chacha20_quarter_round( state, 1, 6, 11, 12 ); + chacha20_quarter_round( state, 2, 7, 8, 13 ); + chacha20_quarter_round( state, 3, 4, 9, 14 ); +} + +/** + * \brief Generates a keystream block. + * + * \param initial_state The initial ChaCha20 state (key, nonce, counter). + * \param keystream Generated keystream bytes are written to this buffer. + */ +static void chacha20_block( const uint32_t initial_state[16], + unsigned char keystream[64] ) +{ + uint32_t working_state[16]; + size_t i; + + memcpy( working_state, + initial_state, + CHACHA20_BLOCK_SIZE_BYTES ); + + for( i = 0U; i < 10U; i++ ) + chacha20_inner_block( working_state ); + + working_state[ 0] += initial_state[ 0]; + working_state[ 1] += initial_state[ 1]; + working_state[ 2] += initial_state[ 2]; + working_state[ 3] += initial_state[ 3]; + working_state[ 4] += initial_state[ 4]; + working_state[ 5] += initial_state[ 5]; + working_state[ 6] += initial_state[ 6]; + working_state[ 7] += initial_state[ 7]; + working_state[ 8] += initial_state[ 8]; + working_state[ 9] += initial_state[ 9]; + working_state[10] += initial_state[10]; + working_state[11] += initial_state[11]; + working_state[12] += initial_state[12]; + working_state[13] += initial_state[13]; + working_state[14] += initial_state[14]; + working_state[15] += initial_state[15]; + + for( i = 0U; i < 16; i++ ) + { + size_t offset = i * 4U; + + keystream[offset ] = (unsigned char)( working_state[i] ); + keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 ); + keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 ); + keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 ); + } + + mbedtls_platform_zeroize( working_state, sizeof( working_state ) ); +} + +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; + } +} + +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) ); + } +} + +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ) +{ + if( ( ctx == NULL ) || ( key == NULL ) ) + { + return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); + } + + /* ChaCha20 constants - the string "expand 32-byte k" */ + ctx->state[0] = 0x61707865; + ctx->state[1] = 0x3320646e; + ctx->state[2] = 0x79622d32; + ctx->state[3] = 0x6b206574; + + /* Set key */ + ctx->state[4] = BYTES_TO_U32_LE( key, 0 ); + ctx->state[5] = BYTES_TO_U32_LE( key, 4 ); + ctx->state[6] = BYTES_TO_U32_LE( key, 8 ); + ctx->state[7] = BYTES_TO_U32_LE( key, 12 ); + ctx->state[8] = BYTES_TO_U32_LE( key, 16 ); + ctx->state[9] = BYTES_TO_U32_LE( key, 20 ); + ctx->state[10] = BYTES_TO_U32_LE( key, 24 ); + ctx->state[11] = BYTES_TO_U32_LE( key, 28 ); + + return( 0 ); +} + +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ) +{ + if( ( ctx == NULL ) || ( nonce == NULL ) ) + { + return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); + } + + /* Counter */ + ctx->state[12] = counter; + + /* Nonce */ + ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 ); + ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 ); + ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 ); + + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; + + return( 0 ); +} + +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ) +{ + size_t offset = 0U; + size_t i; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); + } + else if( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) ) + { + /* input and output pointers are allowed to be NULL only if size == 0 */ + return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); + } + + /* Use leftover keystream bytes, if available */ + while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) + { + output[offset] = input[offset] + ^ ctx->keystream8[ctx->keystream_bytes_used]; + + ctx->keystream_bytes_used++; + offset++; + size--; + } + + /* Process full blocks */ + while( size >= CHACHA20_BLOCK_SIZE_BYTES ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < 64U; i += 8U ) + { + output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ]; + output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1]; + output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2]; + output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3]; + output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4]; + output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5]; + output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6]; + output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7]; + } + + offset += CHACHA20_BLOCK_SIZE_BYTES; + size -= CHACHA20_BLOCK_SIZE_BYTES; + } + + /* Last (partial) block */ + if( size > 0U ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < size; i++) + { + output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; + } + + ctx->keystream_bytes_used = size; + + } + + return( 0 ); +} + +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t data_len, + const unsigned char* input, + unsigned char* output ) +{ + mbedtls_chacha20_context ctx; + int ret; + + mbedtls_chacha20_init( &ctx ); + + ret = mbedtls_chacha20_setkey( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_starts( &ctx, nonce, counter ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_update( &ctx, data_len, input, output ); + +cleanup: + mbedtls_chacha20_free( &ctx ); + return( ret ); +} + +#endif /* !MBEDTLS_CHACHA20_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + } +}; + +static const unsigned char test_nonces[2][12] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02 + } +}; + +static const uint32_t test_counters[2] = +{ + 0U, + 1U +}; + +static const unsigned char test_input[2][375] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f + } +}; + +static const unsigned char test_output[2][375] = +{ + { + 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, + 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, + 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, + 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, + 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, + 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, + 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, + 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 + }, + { + 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, + 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, + 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, + 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, + 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, + 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, + 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, + 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, + 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, + 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, + 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, + 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, + 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, + 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, + 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, + 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, + 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, + 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, + 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, + 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, + 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, + 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, + 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, + 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, + 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, + 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, + 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, + 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, + 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, + 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, + 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, + 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, + 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, + 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, + 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, + 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, + 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, + 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, + 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, + 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, + 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, + 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, + 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, + 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, + 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, + 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, + 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 + } +}; + +static const size_t test_lengths[2] = +{ + 64U, + 375U +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chacha20_self_test( int verbose ) +{ + unsigned char output[381]; + unsigned i; + int ret; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20 test %u ", i ); + + ret = mbedtls_chacha20_crypt( test_keys[i], + test_nonces[i], + test_counters[i], + test_lengths[i], + test_input[i], + output ); + + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ), + ( "failed (output)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_CHACHA20_C */ diff --git a/thirdparty/mbedtls/library/chachapoly.c b/thirdparty/mbedtls/library/chachapoly.c new file mode 100644 index 0000000000..860f877653 --- /dev/null +++ b/thirdparty/mbedtls/library/chachapoly.c @@ -0,0 +1,547 @@ +/** + * \file chachapoly.c + * + * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + +#include "mbedtls/chachapoly.h" +#include "mbedtls/platform_util.h" + +#include <string.h> + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdio.h> +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#define CHACHAPOLY_STATE_INIT ( 0 ) +#define CHACHAPOLY_STATE_AAD ( 1 ) +#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ +#define CHACHAPOLY_STATE_FINISHED ( 3 ) + +/** + * \brief Adds nul bytes to pad the AAD for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +/** + * \brief Adds nul bytes to pad the ciphertext for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_chacha20_init( &ctx->chacha20_ctx ); + mbedtls_poly1305_init( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; + } +} + +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_chacha20_free( &ctx->chacha20_ctx ); + mbedtls_poly1305_free( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; + } +} + +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ) +{ + int ret; + + if( ( ctx == NULL ) || ( key == NULL ) ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + + ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); + + return( ret ); +} + +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ) +{ + int ret; + unsigned char poly1305_key[64]; + + if( ( ctx == NULL ) || ( nonce == NULL ) ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + + /* Set counter = 0, will be update to 1 when generating Poly1305 key */ + ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); + if( ret != 0 ) + goto cleanup; + + /* Generate the Poly1305 key by getting the ChaCha20 keystream output with + * counter = 0. This is the same as encrypting a buffer of zeroes. + * Only the first 256-bits (32 bytes) of the key is used for Poly1305. + * The other 256 bits are discarded. + */ + memset( poly1305_key, 0, sizeof( poly1305_key ) ); + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ), + poly1305_key, poly1305_key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key ); + + if( ret == 0 ) + { + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_AAD; + ctx->mode = mode; + } + +cleanup: + mbedtls_platform_zeroize( poly1305_key, 64U ); + return( ret ); +} + +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ) +{ + if( ctx == NULL ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ( aad_len > 0U ) && ( aad == NULL ) ) + { + /* aad pointer is allowed to be NULL if aad_len == 0 */ + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ctx->state != CHACHAPOLY_STATE_AAD ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + ctx->aad_len += aad_len; + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) ); +} + +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) ) + { + /* input and output pointers are allowed to be NULL if len == 0 */ + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && + ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; + + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->ciphertext_len += len; + + if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT ) + { + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len ); + if( ret != 0 ) + return( ret ); + } + else /* DECRYPT */ + { + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + } + + return( 0 ); +} + +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ) +{ + int ret; + unsigned char len_block[16]; + + if( ( ctx == NULL ) || ( mac == NULL ) ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ctx->state == CHACHAPOLY_STATE_INIT ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT ) + { + ret = chachapoly_pad_ciphertext( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->state = CHACHAPOLY_STATE_FINISHED; + + /* The lengths of the AAD and ciphertext are processed by + * Poly1305 as the final 128-bit block, encoded as little-endian integers. + */ + len_block[ 0] = (unsigned char)( ctx->aad_len ); + len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 ); + len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 ); + len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 ); + len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 ); + len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 ); + len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 ); + len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 ); + len_block[ 8] = (unsigned char)( ctx->ciphertext_len ); + len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 ); + len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 ); + len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 ); + len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 ); + len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 ); + len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 ); + len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac ); + + return( ret ); +} + +static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx, + mbedtls_chachapoly_mode_t mode, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + int ret; + + ret = mbedtls_chachapoly_starts( ctx, nonce, mode ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update( ctx, length, input, output ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_finish( ctx, tag ); + +cleanup: + return( ret ); +} + +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, + length, nonce, aad, aad_len, + input, output, tag ) ); +} + +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + + if( tag == NULL ) + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + + if( ( ret = chachapoly_crypt_and_tag( ctx, + MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, + aad, aad_len, input, output, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < sizeof( check_tag ); i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_CHACHAPOLY_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_key[1][32] = +{ + { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f + } +}; + +static const unsigned char test_nonce[1][12] = +{ + { + 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ + } +}; + +static const unsigned char test_aad[1][12] = +{ + { + 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7 + } +}; + +static const size_t test_aad_len[1] = +{ + 12U +}; + +static const unsigned char test_input[1][114] = +{ + { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, + 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e + } +}; + +static const unsigned char test_output[1][114] = +{ + { + 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, + 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, + 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, + 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, + 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, + 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, + 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, + 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, + 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, + 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, + 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, + 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, + 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, + 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, + 0x61, 0x16 + } +}; + +static const size_t test_input_len[1] = +{ + 114U +}; + +static const unsigned char test_mac[1][16] = +{ + { + 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, + 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 + } +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chachapoly_self_test( int verbose ) +{ + mbedtls_chachapoly_context ctx; + unsigned i; + int ret; + unsigned char output[200]; + unsigned char mac[16]; + + for( i = 0U; i < 1U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20-Poly1305 test %u ", i ); + + mbedtls_chachapoly_init( &ctx ); + + ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] ); + ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) ); + + ret = mbedtls_chachapoly_encrypt_and_tag( &ctx, + test_input_len[i], + test_nonce[i], + test_aad[i], + test_aad_len[i], + test_input[i], + output, + mac ); + + ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ), + ( "failure (wrong output)\n" ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), + ( "failure (wrong MAC)\n" ) ); + + mbedtls_chachapoly_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CHACHAPOLY_C */ diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c index a5cd61cdf3..7ae6c4ac5d 100644 --- a/thirdparty/mbedtls/library/cipher.c +++ b/thirdparty/mbedtls/library/cipher.c @@ -38,6 +38,10 @@ #include <stdlib.h> #include <string.h> +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif @@ -46,6 +50,10 @@ #include "mbedtls/ccm.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + #if defined(MBEDTLS_CMAC_C) #include "mbedtls/cmac.h" #endif @@ -57,9 +65,25 @@ #define mbedtls_free free #endif -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) -#define MBEDTLS_CIPHER_MODE_STREAM -#endif +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/* Compare the contents of two buffers in constant time. + * Returns 0 if the contents are bitwise identical, otherwise returns + * a non-zero value. + * This is currently only used by GCM and ChaCha20+Poly1305. + */ +static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len ) +{ + const unsigned char *p1 = (const unsigned char*) v1; + const unsigned char *p2 = (const unsigned char*) v2; + size_t i; + unsigned char diff; + + for( diff = 0, i = 0; i < len; i++ ) + diff |= p1[i] ^ p2[i]; + + return (int)diff; +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ static int supported_init = 0; @@ -191,10 +215,11 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k ctx->operation = operation; /* - * For CFB and CTR mode always use the encryption key schedule + * For OFB, CFB and CTR mode always use the encryption key schedule */ if( MBEDTLS_ENCRYPT == operation || MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) { return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, @@ -231,6 +256,18 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } +#if defined(MBEDTLS_CHACHA20_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) + { + if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, + iv, + 0U ) ) /* Initial counter value */ + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + } +#endif + memcpy( ctx->iv, iv, actual_iv_size ); ctx->iv_size = actual_iv_size; @@ -247,22 +284,45 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) return( 0 ); } -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len ) { if( NULL == ctx || NULL == ctx->cipher_info ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, ctx->iv, ctx->iv_size, ad, ad_len ); } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int result; + mbedtls_chachapoly_mode_t mode; + + mode = ( ctx->operation == MBEDTLS_ENCRYPT ) + ? MBEDTLS_CHACHAPOLY_ENCRYPT + : MBEDTLS_CHACHAPOLY_DECRYPT; + + result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ctx->iv, + mode ); + if ( result != 0 ) + return( result ); + + return mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ad, ad_len ); + } +#endif return( 0 ); } -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ) @@ -303,6 +363,15 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } #endif +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) + { + *olen = ilen; + return mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ilen, input, output ); + } +#endif + if ( 0 == block_size ) { return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; @@ -424,6 +493,21 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) { @@ -440,6 +524,27 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) + { + if( ctx->unprocessed_len > 0 ) { + /* We can only process an entire data unit at a time. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ); + if( ret != 0 ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_CIPHER_MODE_STREAM) if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) { @@ -639,13 +744,21 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, *olen = 0; if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || MBEDTLS_MODE_CTR == ctx->cipher_info->mode || MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_XTS == ctx->cipher_info->mode || MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) { return( 0 ); } + if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || + ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) + { + return( 0 ); + } + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) { if( ctx->unprocessed_len != 0 ) @@ -757,7 +870,7 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len ) { @@ -767,8 +880,22 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, if( MBEDTLS_ENCRYPT != ctx->operation ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != 16U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + tag ); + } +#endif return( 0 ); } @@ -776,6 +903,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len ) { + unsigned char check_tag[16]; int ret; if( NULL == ctx || NULL == ctx->cipher_info || @@ -784,12 +912,9 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } +#if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { - unsigned char check_tag[16]; - size_t i; - int diff; - if( tag_len > sizeof( check_tag ) ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); @@ -800,18 +925,38 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, } /* Check the tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - if( diff != 0 ) + ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + check_tag ); + if ( ret != 0 ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); return( 0 ); } +#endif /* MBEDTLS_CHACHAPOLY_C */ return( 0 ); } -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /* * Packet-oriented wrapper for non-AEAD modes @@ -870,6 +1015,21 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, tag, tag_len ) ); } #endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, + ilen, iv, ad, ad_len, input, output, tag ) ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } @@ -916,6 +1076,28 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, return( ret ); } #endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int ret; + + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, + iv, ad, ad_len, tag, input, output ); + + if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } diff --git a/thirdparty/mbedtls/library/cipher_wrap.c b/thirdparty/mbedtls/library/cipher_wrap.c index a9ef8195ca..893490acc8 100644 --- a/thirdparty/mbedtls/library/cipher_wrap.c +++ b/thirdparty/mbedtls/library/cipher_wrap.c @@ -33,6 +33,10 @@ #include "mbedtls/cipher_internal.h" +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + #if defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #endif @@ -57,6 +61,10 @@ #include "mbedtls/blowfish.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif @@ -142,6 +150,15 @@ static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, } #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off, + iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, @@ -152,6 +169,33 @@ static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, } #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + int mode; + + switch( operation ) + { + case MBEDTLS_ENCRYPT: + mode = MBEDTLS_AES_ENCRYPT; + break; + case MBEDTLS_DECRYPT: + mode = MBEDTLS_AES_DECRYPT; + break; + default: + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + + return mbedtls_aes_crypt_xts( xts_ctx, mode, length, + data_unit, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_bitlen ) { @@ -191,9 +235,15 @@ static const mbedtls_cipher_base_t aes_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) aes_crypt_cfb128_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + aes_crypt_ofb_wrap, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) aes_crypt_ctr_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -306,6 +356,41 @@ static const mbedtls_cipher_info_t aes_256_cfb128_info = { }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static const mbedtls_cipher_info_t aes_128_ofb_info = { + MBEDTLS_CIPHER_AES_128_OFB, + MBEDTLS_MODE_OFB, + 128, + "AES-128-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ofb_info = { + MBEDTLS_CIPHER_AES_192_OFB, + MBEDTLS_MODE_OFB, + 192, + "AES-192-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ofb_info = { + MBEDTLS_CIPHER_AES_256_OFB, + MBEDTLS_MODE_OFB, + 256, + "AES-256-OFB", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t aes_128_ctr_info = { MBEDTLS_CIPHER_AES_128_CTR, @@ -341,6 +426,92 @@ static const mbedtls_cipher_info_t aes_256_ctr_info = { }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) ); +} + +static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) ); +} + +static void *xts_aes_ctx_alloc( void ) +{ + mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) ); + + if( xts_ctx != NULL ) + mbedtls_aes_xts_init( xts_ctx ); + + return( xts_ctx ); +} + +static void xts_aes_ctx_free( void *ctx ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + + if( xts_ctx == NULL ) + return; + + mbedtls_aes_xts_free( xts_ctx ); + mbedtls_free( xts_ctx ); +} + +static const mbedtls_cipher_base_t xts_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + aes_crypt_xts_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + xts_aes_setkey_enc_wrap, + xts_aes_setkey_dec_wrap, + xts_aes_ctx_alloc, + xts_aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_xts_info = { + MBEDTLS_CIPHER_AES_128_XTS, + MBEDTLS_MODE_XTS, + 256, + "AES-128-XTS", + 16, + 0, + 16, + &xts_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_xts_info = { + MBEDTLS_CIPHER_AES_256_XTS, + MBEDTLS_MODE_XTS, + 512, + "AES-256-XTS", + 16, + 0, + 16, + &xts_aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_GCM_C) static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_bitlen ) @@ -358,9 +529,15 @@ static const mbedtls_cipher_base_t gcm_aes_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -421,9 +598,15 @@ static const mbedtls_cipher_base_t ccm_aes_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -548,9 +731,15 @@ static const mbedtls_cipher_base_t camellia_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) camellia_crypt_cfb128_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) camellia_crypt_ctr_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -715,9 +904,15 @@ static const mbedtls_cipher_base_t gcm_camellia_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -778,9 +973,15 @@ static const mbedtls_cipher_base_t ccm_camellia_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -906,9 +1107,15 @@ static const mbedtls_cipher_base_t aria_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) aria_crypt_cfb128_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) aria_crypt_ctr_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1073,9 +1280,15 @@ static const mbedtls_cipher_base_t gcm_aria_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1136,9 +1349,15 @@ static const mbedtls_cipher_base_t ccm_aria_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1312,9 +1531,15 @@ static const mbedtls_cipher_base_t des_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1357,9 +1582,15 @@ static const mbedtls_cipher_base_t des_ede_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1402,9 +1633,15 @@ static const mbedtls_cipher_base_t des_ede3_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1511,9 +1748,15 @@ static const mbedtls_cipher_base_t blowfish_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) blowfish_crypt_cfb64_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) blowfish_crypt_ctr_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1621,9 +1864,15 @@ static const mbedtls_cipher_base_t arc4_base_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) arc4_crypt_stream_wrap, #endif @@ -1645,6 +1894,162 @@ static const mbedtls_cipher_info_t arc4_128_info = { }; #endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_CHACHA20_C) + +static int chacha20_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static int chacha20_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + + ret = mbedtls_chacha20_update( ctx, length, input, output ); + if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( ret ); +} + +static void * chacha20_ctx_alloc( void ) +{ + mbedtls_chacha20_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chacha20_init( ctx ); + + return( ctx ); +} + +static void chacha20_ctx_free( void *ctx ) +{ + mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chacha20_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + chacha20_stream_wrap, +#endif + chacha20_setkey_wrap, + chacha20_setkey_wrap, + chacha20_ctx_alloc, + chacha20_ctx_free +}; +static const mbedtls_cipher_info_t chacha20_info = { + MBEDTLS_CIPHER_CHACHA20, + MBEDTLS_MODE_STREAM, + 256, + "CHACHA20", + 12, + 0, + 1, + &chacha20_base_info +}; +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + +static int chachapoly_setkey_wrap( void *ctx, + const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static void * chachapoly_ctx_alloc( void ) +{ + mbedtls_chachapoly_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chachapoly_init( ctx ); + + return( ctx ); +} + +static void chachapoly_ctx_free( void *ctx ) +{ + mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chachapoly_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + chachapoly_setkey_wrap, + chachapoly_setkey_wrap, + chachapoly_ctx_alloc, + chachapoly_ctx_free +}; +static const mbedtls_cipher_info_t chachapoly_info = { + MBEDTLS_CIPHER_CHACHA20_POLY1305, + MBEDTLS_MODE_CHACHAPOLY, + 256, + "CHACHA20-POLY1305", + 12, + 0, + 1, + &chachapoly_base_info +}; +#endif /* MBEDTLS_CHACHAPOLY_C */ + #if defined(MBEDTLS_CIPHER_NULL_CIPHER) static int null_crypt_stream( void *ctx, size_t length, const unsigned char *input, @@ -1684,9 +2089,15 @@ static const mbedtls_cipher_base_t null_base_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) null_crypt_stream, #endif @@ -1724,11 +2135,20 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, + { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, + { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, + { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, +#endif #if defined(MBEDTLS_GCM_C) { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, @@ -1831,6 +2251,14 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = #endif #endif /* MBEDTLS_DES_C */ +#if defined(MBEDTLS_CHACHA20_C) + { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, +#endif + #if defined(MBEDTLS_CIPHER_NULL_CIPHER) { MBEDTLS_CIPHER_NULL, &null_cipher_info }, #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ diff --git a/thirdparty/mbedtls/library/cmac.c b/thirdparty/mbedtls/library/cmac.c index 4d7a1f1693..5d101e1c7d 100644 --- a/thirdparty/mbedtls/library/cmac.c +++ b/thirdparty/mbedtls/library/cmac.c @@ -828,6 +828,7 @@ static int cmac_test_subkeys( int verbose, mbedtls_cipher_free( &ctx ); } + ret = 0; goto exit; cleanup: @@ -883,6 +884,7 @@ static int cmac_test_wth_cipher( int verbose, if( verbose != 0 ) mbedtls_printf( "passed\n" ); } + ret = 0; exit: return( ret ); diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c index cefe882d2a..f44a753f4d 100644 --- a/thirdparty/mbedtls/library/entropy_poll.c +++ b/thirdparty/mbedtls/library/entropy_poll.c @@ -19,19 +19,25 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +#if defined(__linux__) +/* Ensure that syscall() is available even when compiling with -std=c99 */ +#define _GNU_SOURCE +#endif + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif +#include <string.h> + #if defined(MBEDTLS_ENTROPY_C) #include "mbedtls/entropy.h" #include "mbedtls/entropy_poll.h" #if defined(MBEDTLS_TIMING_C) -#include <string.h> #include "mbedtls/timing.h" #endif #if defined(MBEDTLS_HAVEGE_C) @@ -44,7 +50,8 @@ #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) #error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" #endif diff --git a/thirdparty/mbedtls/library/entropy_poll.c.orig b/thirdparty/mbedtls/library/entropy_poll.c.orig new file mode 100644 index 0000000000..040aa117dc --- /dev/null +++ b/thirdparty/mbedtls/library/entropy_poll.c.orig @@ -0,0 +1,275 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if defined(__linux__) +/* Ensure that syscall() is available even when compiling with -std=c99 */ +#define _GNU_SOURCE +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include <string.h> + +#if defined(MBEDTLS_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#if defined(MBEDTLS_TIMING_C) +#include "mbedtls/timing.h" +#endif +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) +#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include <windows.h> +#include <wincrypt.h> + +int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + { + CryptReleaseContext( provider, 0 ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if defined(__linux__) && defined(__GLIBC__) +#include <unistd.h> +#include <sys/syscall.h> +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM + +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + /* MemSan cannot understand that the syscall writes to the buffer */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset( buf, 0, buflen ); +#endif +#endif + + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} + +#include <sys/utsname.h> +/* Check if version is at least 3.17.0 */ +static int check_version_3_17_plus( void ) +{ + int minor; + struct utsname un; + const char *ver; + + /* Get version information */ + uname(&un); + ver = un.release; + + /* Check major version; assume a single digit */ + if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) + return( -1 ); + + if( ver[0] - '0' > 3 ) + return( 0 ); + + /* Ok, so now we know major == 3, check minor. + * Assume 1 or 2 digits. */ + if( ver[2] < '0' || ver[2] > '9' ) + return( -1 ); + + minor = ver[2] - '0'; + + if( ver[3] >= '0' && ver[3] <= '9' ) + minor = 10 * minor + ver[3] - '0'; + else if( ver [3] != '.' ) + return( -1 ); + + if( minor < 17 ) + return( -1 ); + + return( 0 ); +} +static int has_getrandom = -1; +#endif /* SYS_getrandom */ +#endif /* __linux__ */ + +#include <stdio.h> + +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t read_len; + ((void) data); + +#if defined(HAVE_GETRANDOM) + if( has_getrandom == -1 ) + has_getrandom = ( check_version_3_17_plus() == 0 ); + + if( has_getrandom ) + { + int ret; + + if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = ret; + return( 0 ); + } +#endif /* HAVE_GETRANDOM */ + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + read_len = fread( output, 1, len, file ); + if( read_len != len ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + ((void) data); + ((void) output); + *olen = 0; + + if( len < sizeof(unsigned char) ) + return( 0 ); + + *olen = sizeof(unsigned char); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_TIMING_C) +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = mbedtls_timing_hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} +#endif /* MBEDTLS_TIMING_C */ + +#if defined(MBEDTLS_HAVEGE_C) +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + mbedtls_havege_state *hs = (mbedtls_havege_state *) data; + *olen = 0; + + if( mbedtls_havege_random( hs, output, len ) != 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* MBEDTLS_HAVEGE_C */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + ((void) data); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + if( len < use_len ) + use_len = len; + + memcpy( output, buf, use_len ); + *olen = use_len; + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/thirdparty/mbedtls/library/error.c b/thirdparty/mbedtls/library/error.c index 8818054c56..774244b454 100644 --- a/thirdparty/mbedtls/library/error.c +++ b/thirdparty/mbedtls/library/error.c @@ -73,6 +73,14 @@ #include "mbedtls/ccm.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif @@ -105,6 +113,10 @@ #include "mbedtls/gcm.h" #endif +#if defined(MBEDTLS_HKDF_C) +#include "mbedtls/hkdf.h" +#endif + #if defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" #endif @@ -153,6 +165,10 @@ #include "mbedtls/pkcs5.h" #endif +#if defined(MBEDTLS_POLY1305_C) +#include "mbedtls/poly1305.h" +#endif + #if defined(MBEDTLS_RIPEMD160_C) #include "mbedtls/ripemd160.h" #endif @@ -497,6 +513,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) ) mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) @@ -670,6 +688,22 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" ); #endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHA20_C) + if( use_ret == -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Invalid input parameter(s)" ); + if( use_ret == -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Feature not available. For example, s part of the API is not implemented" ); + if( use_ret == -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Chacha20 hardware accelerator failed" ); +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE) ) + mbedtls_snprintf( buf, buflen, "CHACHAPOLY - The requested operation is not permitted in the current state" ); + if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); +#endif /* MBEDTLS_CHACHAPOLY_C */ + #if defined(MBEDTLS_CMAC_C) if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" ); @@ -715,6 +749,11 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); #endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_HKDF_C) + if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "HKDF - Bad input parameters to function" ); +#endif /* MBEDTLS_HKDF_C */ + #if defined(MBEDTLS_HMAC_DRBG_C) if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); @@ -782,6 +821,15 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); #endif /* MBEDTLS_PADLOCK_C */ +#if defined(MBEDTLS_POLY1305_C) + if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" ); + if( use_ret == -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Feature not available. For example, s part of the API is not implemented" ); + if( use_ret == -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Poly1305 hardware accelerator failed" ); +#endif /* MBEDTLS_POLY1305_C */ + #if defined(MBEDTLS_RIPEMD160_C) if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); diff --git a/thirdparty/mbedtls/library/hkdf.c b/thirdparty/mbedtls/library/hkdf.c new file mode 100644 index 0000000000..82d8a429f4 --- /dev/null +++ b/thirdparty/mbedtls/library/hkdf.c @@ -0,0 +1,192 @@ +/* + * HKDF implementation -- RFC 5869 + * + * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HKDF_C) + +#include <string.h> +#include "mbedtls/hkdf.h" +#include "mbedtls/platform_util.h" + +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ) +{ + int ret; + unsigned char prk[MBEDTLS_MD_MAX_SIZE]; + + ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk ); + + if( ret == 0 ) + { + ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ), + info, info_len, okm, okm_len ); + } + + mbedtls_platform_zeroize( prk, sizeof( prk ) ); + + return( ret ); +} + +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ) +{ + unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; + + if( salt == NULL ) + { + size_t hash_len; + + if( salt_len != 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + hash_len = mbedtls_md_get_size( md ); + + if( hash_len == 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + salt = null_salt; + salt_len = hash_len; + } + + return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) ); +} + +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ) +{ + size_t hash_len; + size_t where = 0; + size_t n; + size_t t_len = 0; + size_t i; + int ret = 0; + mbedtls_md_context_t ctx; + unsigned char t[MBEDTLS_MD_MAX_SIZE]; + + if( okm == NULL ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + hash_len = mbedtls_md_get_size( md ); + + if( prk_len < hash_len || hash_len == 0 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + if( info == NULL ) + { + info = (const unsigned char *) ""; + info_len = 0; + } + + n = okm_len / hash_len; + + if( (okm_len % hash_len) != 0 ) + { + n++; + } + + /* + * Per RFC 5869 Section 2.3, okm_len must not exceed + * 255 times the hash length + */ + if( n > 255 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + mbedtls_md_init( &ctx ); + + if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 ) + { + goto exit; + } + + /* + * Compute T = T(1) | T(2) | T(3) | ... | T(N) + * Where T(N) is defined in RFC 5869 Section 2.3 + */ + for( i = 1; i <= n; i++ ) + { + size_t num_to_copy; + unsigned char c = i & 0xff; + + ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, t, t_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, info, info_len ); + if( ret != 0 ) + { + goto exit; + } + + /* The constant concatenated to the end of each T(n) is a single octet. + * */ + ret = mbedtls_md_hmac_update( &ctx, &c, 1 ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_finish( &ctx, t ); + if( ret != 0 ) + { + goto exit; + } + + num_to_copy = i != n ? hash_len : okm_len - where; + memcpy( okm + where, t, num_to_copy ); + where += hash_len; + t_len = hash_len; + } + +exit: + mbedtls_md_free( &ctx ); + mbedtls_platform_zeroize( t, sizeof( t ) ); + + return( ret ); +} + +#endif /* MBEDTLS_HKDF_C */ diff --git a/thirdparty/mbedtls/library/md5.c b/thirdparty/mbedtls/library/md5.c index 8238c2b81a..2a740cda81 100644 --- a/thirdparty/mbedtls/library/md5.c +++ b/thirdparty/mbedtls/library/md5.c @@ -309,14 +309,6 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, } #endif -static const unsigned char md5_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - /* * MD5 final digest */ @@ -324,26 +316,48 @@ int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, unsigned char output[16] ) { int ret; - uint32_t last, padn; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; - PUT_UINT32_LE( low, msglen, 0 ); - PUT_UINT32_LE( high, msglen, 4 ); + ctx->buffer[used++] = 0x80; - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); - if( ( ret = mbedtls_md5_update_ret( ctx, md5_padding, padn ) ) != 0 ) + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) return( ret ); - if( ( ret = mbedtls_md5_update_ret( ctx, msglen, 8 ) ) != 0 ) - return( ret ); + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, ctx->buffer, 56 ); + PUT_UINT32_LE( high, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + /* + * Output final state + */ PUT_UINT32_LE( ctx->state[0], output, 0 ); PUT_UINT32_LE( ctx->state[1], output, 4 ); PUT_UINT32_LE( ctx->state[2], output, 8 ); diff --git a/thirdparty/mbedtls/library/memory_buffer_alloc.c b/thirdparty/mbedtls/library/memory_buffer_alloc.c index ceaeda1e73..51ea7c41d7 100644 --- a/thirdparty/mbedtls/library/memory_buffer_alloc.c +++ b/thirdparty/mbedtls/library/memory_buffer_alloc.c @@ -518,7 +518,9 @@ void mbedtls_memory_buffer_alloc_status( void ) heap.alloc_count, heap.free_count ); if( heap.first->next == NULL ) + { mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + } else { mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c index 9b0a375fb7..816b1303df 100644 --- a/thirdparty/mbedtls/library/net_sockets.c +++ b/thirdparty/mbedtls/library/net_sockets.c @@ -19,6 +19,11 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must + * be set before config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#define _POSIX_C_SOURCE 200112L + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -28,7 +33,8 @@ #if defined(MBEDTLS_NET_C) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" #endif @@ -47,13 +53,11 @@ #define IS_EINTR( ret ) ( ( ret ) == WSAEINTR ) -/* GODOT ADDITION */ #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501) #undef _WIN32_WINNT /* Enables getaddrinfo() & Co */ #define _WIN32_WINNT 0x0501 #endif -/* END GODOT ADDITION */ #include <ws2tcpip.h> diff --git a/thirdparty/mbedtls/library/nist_kw.c b/thirdparty/mbedtls/library/nist_kw.c new file mode 100644 index 0000000000..176af9fe08 --- /dev/null +++ b/thirdparty/mbedtls/library/nist_kw.c @@ -0,0 +1,755 @@ +/* + * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes + * only + * + * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +/* + * Definition of Key Wrapping: + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" + * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" + * + * Note: RFC 3394 defines different methodology for intermediate operations for + * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_NIST_KW_C) + +#include "mbedtls/nist_kw.h" +#include "mbedtls/platform_util.h" + +#include <stdint.h> +#include <string.h> + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdio.h> +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_NIST_KW_ALT) + +#define KW_SEMIBLOCK_LENGTH 8 +#define MIN_SEMIBLOCKS_COUNT 3 + +/* constant-time buffer comparison */ +static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return( diff ); +} + +/*! The 64-bit default integrity check value (ICV) for KW mode. */ +static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}; +/*! The 32-bit default integrity check value (ICV) for KWP mode. */ +static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6}; + +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +/* + * Initialize context + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) ); +} + +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, + keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* + * SP 800-38F currently defines AES cipher as the only block cipher allowed: + * "For KW and KWP, the underlying block cipher shall be approved, and the + * block size shall be 128 bits. Currently, the AES block cipher, with key + * lengths of 128, 192, or 256 bits, is the only block cipher that fits + * this profile." + * Currently we don't support other 128 bit block ciphers for key wrapping, + * such as Camellia and Aria. + */ + if( cipher != MBEDTLS_CIPHER_ID_AES ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + is_wrap ? MBEDTLS_ENCRYPT : + MBEDTLS_DECRYPT ) + ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) ); +} + +/* + * Helper function for Xoring the uint64_t "t" with the encrypted A. + * Defined in NIST SP 800-38F section 6.1 + */ +static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t ) +{ + size_t i = 0; + for( i = 0; i < sizeof( t ); i++ ) + { + A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff; + } +} + +/* + * KW-AE as defined in SP 800-38F section 6.2 + * KWP-AE as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t semiblocks = 0; + size_t s; + size_t olen, padlen = 0; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; + unsigned char *A = output; + + *out_len = 0; + /* + * Generate the String to work on + */ + if( mode == MBEDTLS_KW_MODE_KW ) + { + if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KW + * must be between 2 to 2^54-1 semiblocks inclusive. + */ + if( in_len < 16 || +#if SIZE_MAX > 0x1FFFFFFFFFFFFF8 + in_len > 0x1FFFFFFFFFFFFF8 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); + memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + } + else + { + if( in_len % 8 != 0 ) + { + padlen = ( 8 - ( in_len % 8 ) ); + } + + if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KWP + * must be between 1 and 2^32-1 octets inclusive. + */ + if( in_len < 1 +#if SIZE_MAX > 0xFFFFFFFF + || in_len > 0xFFFFFFFF +#endif + ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); + PUT_UINT32_BE( ( in_len & 0xffffffff ), output, + KW_SEMIBLOCK_LENGTH / 2 ); + + memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); + } + semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; + + s = 6 * ( semiblocks - 1 ); + + if( mode == MBEDTLS_KW_MODE_KWP + && in_len <= KW_SEMIBLOCK_LENGTH ) + { + memcpy( inbuff, output, 16 ); + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, output, &olen ); + if( ret != 0 ) + goto cleanup; + } + else + { + /* + * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 + */ + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + goto cleanup; + } + + /* Calculate intermediate values */ + for( t = 1; t <= s; t++ ) + { + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + calc_a_xor_t( A, t ); + + memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + R2 += KW_SEMIBLOCK_LENGTH; + if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) + R2 = output + KW_SEMIBLOCK_LENGTH; + } + } + + *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; + +cleanup: + + if( ret != 0) + { + memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); + } + mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); + mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); + mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen ); + return( ret ); +} + +/* + * W-1 function as defined in RFC 3394 section 2.2.2 + * This function assumes the following: + * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. + * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. + * 3. Minimal number of semiblocks is 3. + * 4. A is a buffer to hold the first semiblock of the input buffer. + */ +static int unwrap( mbedtls_nist_kw_context *ctx, + const unsigned char *input, size_t semiblocks, + unsigned char A[KW_SEMIBLOCK_LENGTH], + unsigned char *output, size_t* out_len ) +{ + int ret = 0; + const size_t s = 6 * ( semiblocks - 1 ); + size_t olen; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + *out_len = 0; + + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( A, input, KW_SEMIBLOCK_LENGTH ); + memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + + /* Calculate intermediate values */ + for( t = s; t >= 1; t-- ) + { + calc_a_xor_t( A, t ); + + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + + /* Set R as LSB64 of outbuff */ + memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + + if( R == output ) + R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + else + R -= KW_SEMIBLOCK_LENGTH; + } + + *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH; + +cleanup: + if( ret != 0) + memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + + return( ret ); +} + +/* + * KW-AD as defined in SP 800-38F section 6.2 + * KWP-AD as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t i, olen; + unsigned char A[KW_SEMIBLOCK_LENGTH]; + unsigned char diff, bad_padding = 0; + + *out_len = 0; + if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( mode == MBEDTLS_KW_MODE_KW ) + { + /* + * According to SP 800-38F Table 1, the ciphertext length for KW + * must be between 3 to 2^54 semiblocks inclusive. + */ + if( in_len < 24 || +#if SIZE_MAX > 0x200000000000000 + in_len > 0x200000000000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + + /* Check ICV in "constant-time" */ + diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto cleanup; + } + + } + else if( mode == MBEDTLS_KW_MODE_KWP ) + { + size_t padlen = 0; + uint32_t Plen; + /* + * According to SP 800-38F Table 1, the ciphertext length for KWP + * must be between 2 to 2^29 semiblocks inclusive. + */ + if( in_len < KW_SEMIBLOCK_LENGTH * 2 || +#if SIZE_MAX > 0x100000000 + in_len > 0x100000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) + { + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + input, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + *out_len = KW_SEMIBLOCK_LENGTH; + } + else + { + /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + } + + /* Check ICV in "constant-time" */ + diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 ); + + /* + * Plen is the length of the plaintext, when the input is valid. + * If Plen is larger than the plaintext and padding, padlen will be + * larger than 8, because of the type wrap around. + */ + padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; + if ( padlen > 7 ) + { + padlen &= 7; + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + /* Check padding in "constant-time" */ + for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) + { + if( i >= KW_SEMIBLOCK_LENGTH - padlen ) + diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + else + bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + } + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + if( ret != 0 ) + { + goto cleanup; + } + memset( output + Plen, 0, padlen ); + *out_len = Plen; + } + else + { + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto cleanup; + } + +cleanup: + if( ret != 0 ) + { + memset( output, 0, *out_len ); + *out_len = 0; + } + + mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); + mbedtls_platform_zeroize( &diff, sizeof( diff ) ); + mbedtls_platform_zeroize( A, sizeof( A ) ); + mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen ); + return( ret ); +} + +#endif /* !MBEDTLS_NIST_KW_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) + +#define KW_TESTS 3 + +/* + * Test vectors taken from NIST + * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW + */ +static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; + +static const unsigned char kw_key[KW_TESTS][32] = { + { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, + 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, + { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, + 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, + 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, + { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, + 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, + 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, + 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } +}; + +static const unsigned char kw_msg[KW_TESTS][40] = { + { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, + 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, + { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, + 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, + 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, + 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, + 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, + { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, + 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, + 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } +}; + +static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; +static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; +static const unsigned char kw_res[KW_TESTS][48] = { + { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, + 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, + 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, + { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, + 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, + 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, + 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, + 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, + 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, + { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, + 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, + 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, + 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } +}; + +static const unsigned char kwp_key[KW_TESTS][32] = { + { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, + 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, + { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, + 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, + 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, + { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, + 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, + 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, + 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } +}; + +static const unsigned char kwp_msg[KW_TESTS][31] = { + { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, + 0x96 }, + { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, + 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, + 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, + 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, + { 0xd1 } +}; +static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; + +static const unsigned char kwp_res[KW_TESTS][48] = { + { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, + 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, + 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, + { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, + 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, + 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, + 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, + 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, + { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, + 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } +}; +static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; + +int mbedtls_nist_kw_self_test( int verbose ) +{ + mbedtls_nist_kw_context ctx; + unsigned char out[48]; + size_t olen; + int i; + int ret = 0; + mbedtls_nist_kw_init( &ctx ); + + for( i = 0; i < KW_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed " ); + + goto end; + } + + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], + kw_msg_len[i], out, &olen, sizeof( out ) ); + if( ret != 0 || kw_out_len[i] != olen || + memcmp( out, kw_res[i], kw_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW, + out, olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kw_msg_len[i] || + memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } + + for( i = 0; i < KW_TESTS; i++ ) + { + olen = sizeof( out ); + if( verbose != 0 ) + mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], + key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed " ); + + goto end; + } + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], + kwp_msg_len[i], out, &olen, sizeof( out ) ); + + if( ret != 0 || kwp_out_len[i] != olen || + memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kwp_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out, + olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kwp_msg_len[i] || + memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } +end: + mbedtls_nist_kw_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_NIST_KW_C */ diff --git a/thirdparty/mbedtls/library/pkcs5.c b/thirdparty/mbedtls/library/pkcs5.c index 440a174b5b..f04f0ab25e 100644 --- a/thirdparty/mbedtls/library/pkcs5.c +++ b/thirdparty/mbedtls/library/pkcs5.c @@ -249,8 +249,10 @@ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *p memset( counter, 0, 4 ); counter[3] = 1; +#if UINT_MAX > 0xFFFFFFFF if( iteration_count > 0xFFFFFFFF ) return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); +#endif while( key_length ) { diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c index ccb7f5409d..d6ac987e23 100644 --- a/thirdparty/mbedtls/library/pkparse.c +++ b/thirdparty/mbedtls/library/pkparse.c @@ -1261,7 +1261,6 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, return( ret ); #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ #else - ((void) ret); ((void) pwd); ((void) pwdlen); #endif /* MBEDTLS_PEM_PARSE_C */ diff --git a/thirdparty/mbedtls/library/platform.c b/thirdparty/mbedtls/library/platform.c index 9e992875d9..b24b2fa652 100644 --- a/thirdparty/mbedtls/library/platform.c +++ b/thirdparty/mbedtls/library/platform.c @@ -51,14 +51,24 @@ static void platform_free_uninit( void *ptr ) #define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit #endif /* !MBEDTLS_PLATFORM_STD_FREE */ -void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; -void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE; +static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +void * mbedtls_calloc( size_t nmemb, size_t size ) +{ + return (*mbedtls_calloc_func)( nmemb, size ); +} + +void mbedtls_free( void * ptr ) +{ + (*mbedtls_free_func)( ptr ); +} int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), void (*free_func)( void * ) ) { - mbedtls_calloc = calloc_func; - mbedtls_free = free_func; + mbedtls_calloc_func = calloc_func; + mbedtls_free_func = free_func; return( 0 ); } #endif /* MBEDTLS_PLATFORM_MEMORY */ diff --git a/thirdparty/mbedtls/library/poly1305.c b/thirdparty/mbedtls/library/poly1305.c new file mode 100644 index 0000000000..e22d3afb68 --- /dev/null +++ b/thirdparty/mbedtls/library/poly1305.c @@ -0,0 +1,563 @@ +/** + * \file poly1305.c + * + * \brief Poly1305 authentication algorithm. + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_POLY1305_C) + +#include "mbedtls/poly1305.h" +#include "mbedtls/platform_util.h" + +#include <string.h> + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdio.h> +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_POLY1305_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define POLY1305_BLOCK_SIZE_BYTES ( 16U ) + +#define BYTES_TO_U32_LE( data, offset ) \ + ( (uint32_t) data[offset] \ + | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \ + ) + +/* + * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. + * However we provided an alternative for platforms without such a multiplier. + */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) +static uint64_t mul64( uint32_t a, uint32_t b ) +{ + /* a = al + 2**16 ah, b = bl + 2**16 bh */ + const uint16_t al = (uint16_t) a; + const uint16_t bl = (uint16_t) b; + const uint16_t ah = a >> 16; + const uint16_t bh = b >> 16; + + /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ + const uint32_t lo = (uint32_t) al * bl; + const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh; + const uint32_t hi = (uint32_t) ah * bh; + + return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) ); +} +#else +static inline uint64_t mul64( uint32_t a, uint32_t b ) +{ + return( (uint64_t) a * b ); +} +#endif + + +/** + * \brief Process blocks with Poly1305. + * + * \param ctx The Poly1305 context. + * \param nblocks Number of blocks to process. Note that this + * function only processes full blocks. + * \param input Buffer containing the input block(s). + * \param needs_padding Set to 0 if the padding bit has already been + * applied to the input data before calling this + * function. Otherwise, set this parameter to 1. + */ +static void poly1305_process( mbedtls_poly1305_context *ctx, + size_t nblocks, + const unsigned char *input, + uint32_t needs_padding ) +{ + uint64_t d0, d1, d2, d3; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t r0, r1, r2, r3; + uint32_t rs1, rs2, rs3; + size_t offset = 0U; + size_t i; + + r0 = ctx->r[0]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; + r3 = ctx->r[3]; + + rs1 = r1 + ( r1 >> 2U ); + rs2 = r2 + ( r2 >> 2U ); + rs3 = r3 + ( r3 >> 2U ); + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Process full blocks */ + for( i = 0U; i < nblocks; i++ ) + { + /* The input block is treated as a 128-bit little-endian integer */ + d0 = BYTES_TO_U32_LE( input, offset + 0 ); + d1 = BYTES_TO_U32_LE( input, offset + 4 ); + d2 = BYTES_TO_U32_LE( input, offset + 8 ); + d3 = BYTES_TO_U32_LE( input, offset + 12 ); + + /* Compute: acc += (padded) block as a 130-bit integer */ + d0 += (uint64_t) acc0; + d1 += (uint64_t) acc1 + ( d0 >> 32U ); + d2 += (uint64_t) acc2 + ( d1 >> 32U ); + d3 += (uint64_t) acc3 + ( d2 >> 32U ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding; + + /* Compute: acc *= r */ + d0 = mul64( acc0, r0 ) + + mul64( acc1, rs3 ) + + mul64( acc2, rs2 ) + + mul64( acc3, rs1 ); + d1 = mul64( acc0, r1 ) + + mul64( acc1, r0 ) + + mul64( acc2, rs3 ) + + mul64( acc3, rs2 ) + + mul64( acc4, rs1 ); + d2 = mul64( acc0, r2 ) + + mul64( acc1, r1 ) + + mul64( acc2, r0 ) + + mul64( acc3, rs3 ) + + mul64( acc4, rs2 ); + d3 = mul64( acc0, r3 ) + + mul64( acc1, r2 ) + + mul64( acc2, r1 ) + + mul64( acc3, r0 ) + + mul64( acc4, rs3 ); + acc4 *= r0; + + /* Compute: acc %= (2^130 - 5) (partial remainder) */ + d1 += ( d0 >> 32 ); + d2 += ( d1 >> 32 ); + d3 += ( d2 >> 32 ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 = (uint32_t) ( d3 >> 32 ) + acc4; + + d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU ); + acc4 &= 3U; + acc0 = (uint32_t) d0; + d0 = (uint64_t) acc1 + ( d0 >> 32U ); + acc1 = (uint32_t) d0; + d0 = (uint64_t) acc2 + ( d0 >> 32U ); + acc2 = (uint32_t) d0; + d0 = (uint64_t) acc3 + ( d0 >> 32U ); + acc3 = (uint32_t) d0; + d0 = (uint64_t) acc4 + ( d0 >> 32U ); + acc4 = (uint32_t) d0; + + offset += POLY1305_BLOCK_SIZE_BYTES; + } + + ctx->acc[0] = acc0; + ctx->acc[1] = acc1; + ctx->acc[2] = acc2; + ctx->acc[3] = acc3; + ctx->acc[4] = acc4; +} + +/** + * \brief Compute the Poly1305 MAC + * + * \param ctx The Poly1305 context. + * \param mac The buffer to where the MAC is written. Must be + * big enough to contain the 16-byte MAC. + */ +static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + uint64_t d; + uint32_t g0, g1, g2, g3, g4; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t mask; + uint32_t mask_inv; + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. + * We do this by calculating acc - (2^130 - 5), then checking if + * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) + */ + + /* Calculate acc + -(2^130 - 5) */ + d = ( (uint64_t) acc0 + 5U ); + g0 = (uint32_t) d; + d = ( (uint64_t) acc1 + ( d >> 32 ) ); + g1 = (uint32_t) d; + d = ( (uint64_t) acc2 + ( d >> 32 ) ); + g2 = (uint32_t) d; + d = ( (uint64_t) acc3 + ( d >> 32 ) ); + g3 = (uint32_t) d; + g4 = acc4 + (uint32_t) ( d >> 32U ); + + /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ + mask = (uint32_t) 0U - ( g4 >> 2U ); + mask_inv = ~mask; + + /* If 131st bit is set then acc=g, otherwise, acc is unmodified */ + acc0 = ( acc0 & mask_inv ) | ( g0 & mask ); + acc1 = ( acc1 & mask_inv ) | ( g1 & mask ); + acc2 = ( acc2 & mask_inv ) | ( g2 & mask ); + acc3 = ( acc3 & mask_inv ) | ( g3 & mask ); + + /* Add 's' */ + d = (uint64_t) acc0 + ctx->s[0]; + acc0 = (uint32_t) d; + d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U ); + acc1 = (uint32_t) d; + d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U ); + acc2 = (uint32_t) d; + acc3 += ctx->s[3] + (uint32_t) ( d >> 32U ); + + /* Compute MAC (128 least significant bits of the accumulator) */ + mac[ 0] = (unsigned char)( acc0 ); + mac[ 1] = (unsigned char)( acc0 >> 8 ); + mac[ 2] = (unsigned char)( acc0 >> 16 ); + mac[ 3] = (unsigned char)( acc0 >> 24 ); + mac[ 4] = (unsigned char)( acc1 ); + mac[ 5] = (unsigned char)( acc1 >> 8 ); + mac[ 6] = (unsigned char)( acc1 >> 16 ); + mac[ 7] = (unsigned char)( acc1 >> 24 ); + mac[ 8] = (unsigned char)( acc2 ); + mac[ 9] = (unsigned char)( acc2 >> 8 ); + mac[10] = (unsigned char)( acc2 >> 16 ); + mac[11] = (unsigned char)( acc2 >> 24 ); + mac[12] = (unsigned char)( acc3 ); + mac[13] = (unsigned char)( acc3 >> 8 ); + mac[14] = (unsigned char)( acc3 >> 16 ); + mac[15] = (unsigned char)( acc3 >> 24 ); +} + +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); + } +} + +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); + } +} + +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ) +{ + if( ctx == NULL || key == NULL ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + + /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ + ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU; + ctx->r[1] = BYTES_TO_U32_LE( key, 4 ) & 0x0FFFFFFCU; + ctx->r[2] = BYTES_TO_U32_LE( key, 8 ) & 0x0FFFFFFCU; + ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU; + + ctx->s[0] = BYTES_TO_U32_LE( key, 16 ); + ctx->s[1] = BYTES_TO_U32_LE( key, 20 ); + ctx->s[2] = BYTES_TO_U32_LE( key, 24 ); + ctx->s[3] = BYTES_TO_U32_LE( key, 28 ); + + /* Initial accumulator state */ + ctx->acc[0] = 0U; + ctx->acc[1] = 0U; + ctx->acc[2] = 0U; + ctx->acc[3] = 0U; + ctx->acc[4] = 0U; + + /* Queue initially empty */ + mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) ); + ctx->queue_len = 0U; + + return( 0 ); +} + +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + size_t offset = 0U; + size_t remaining = ilen; + size_t queue_free_len; + size_t nblocks; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ( ilen > 0U ) && ( input == NULL ) ) + { + /* input pointer is allowed to be NULL only if ilen == 0 */ + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + + if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) ) + { + queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + if( ilen < queue_free_len ) + { + /* Not enough data to complete the block. + * Store this data with the other leftovers. + */ + memcpy( &ctx->queue[ctx->queue_len], + input, + ilen ); + + ctx->queue_len += ilen; + + remaining = 0U; + } + else + { + /* Enough data to produce a complete block */ + memcpy( &ctx->queue[ctx->queue_len], + input, + queue_free_len ); + + ctx->queue_len = 0U; + + poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */ + + offset += queue_free_len; + remaining -= queue_free_len; + } + } + + if( remaining >= POLY1305_BLOCK_SIZE_BYTES ) + { + nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; + + poly1305_process( ctx, nblocks, &input[offset], 1U ); + + offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; + remaining %= POLY1305_BLOCK_SIZE_BYTES; + } + + if( remaining > 0U ) + { + /* Store partial block */ + ctx->queue_len = remaining; + memcpy( ctx->queue, &input[offset], remaining ); + } + + return( 0 ); +} + +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + if( ( ctx == NULL ) || ( mac == NULL ) ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + + /* Process any leftover data */ + if( ctx->queue_len > 0U ) + { + /* Add padding bit */ + ctx->queue[ctx->queue_len] = 1U; + ctx->queue_len++; + + /* Pad with zeroes */ + memset( &ctx->queue[ctx->queue_len], + 0, + POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + poly1305_process( ctx, 1U, /* Process 1 block */ + ctx->queue, 0U ); /* Already padded above */ + } + + poly1305_compute_mac( ctx, mac ); + + return( 0 ); +} + +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ) +{ + mbedtls_poly1305_context ctx; + int ret; + + mbedtls_poly1305_init( &ctx ); + + ret = mbedtls_poly1305_starts( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_update( &ctx, input, ilen ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_finish( &ctx, mac ); + +cleanup: + mbedtls_poly1305_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_POLY1305_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, + 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, + 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, + 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b + }, + { + 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, + 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, + 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, + 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 + } +}; + +static const unsigned char test_data[2][127] = +{ + { + 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, + 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, + 0x75, 0x70 + }, + { + 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, + 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, + 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, + 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, + 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, + 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, + 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, + 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, + 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, + 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e + } +}; + +static const size_t test_data_len[2] = +{ + 34U, + 127U +}; + +static const unsigned char test_mac[2][16] = +{ + { + 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, + 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 + }, + { + 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, + 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 + } +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_poly1305_self_test( int verbose ) +{ + unsigned char mac[16]; + unsigned i; + int ret; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " Poly1305 test %u ", i ); + + ret = mbedtls_poly1305_mac( test_keys[i], + test_data[i], + test_data_len[i], + mac ); + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_POLY1305_C */ diff --git a/thirdparty/mbedtls/library/sha1.c b/thirdparty/mbedtls/library/sha1.c index 1587de4805..bab6087c4e 100644 --- a/thirdparty/mbedtls/library/sha1.c +++ b/thirdparty/mbedtls/library/sha1.c @@ -342,14 +342,6 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, } #endif -static const unsigned char sha1_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - /* * SHA-1 final digest */ @@ -357,25 +349,48 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, unsigned char output[20] ) { int ret; - uint32_t last, padn; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); - if( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 ) - return( ret ); - if( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 ) + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) return( ret ); + /* + * Output final state + */ PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[2], output, 8 ); diff --git a/thirdparty/mbedtls/library/sha256.c b/thirdparty/mbedtls/library/sha256.c index 695485d847..dbb4a89861 100644 --- a/thirdparty/mbedtls/library/sha256.c +++ b/thirdparty/mbedtls/library/sha256.c @@ -311,14 +311,6 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, } #endif -static const unsigned char sha256_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - /* * SHA-256 final digest */ @@ -326,26 +318,48 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, unsigned char output[32] ) { int ret; - uint32_t last, padn; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - if( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 ) - return( ret ); + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); - if( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 ) + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) return( ret ); + /* + * Output final state + */ PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[2], output, 8 ); diff --git a/thirdparty/mbedtls/library/sha512.c b/thirdparty/mbedtls/library/sha512.c index 6de94e99b4..a9440e8af5 100644 --- a/thirdparty/mbedtls/library/sha512.c +++ b/thirdparty/mbedtls/library/sha512.c @@ -341,18 +341,6 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, } #endif -static const unsigned char sha512_padding[128] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - /* * SHA-512 final digest */ @@ -360,26 +348,48 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, unsigned char output[64] ) { int ret; - size_t last, padn; + unsigned used; uint64_t high, low; - unsigned char msglen[16]; - high = ( ctx->total[0] >> 61 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; - PUT_UINT64_BE( high, msglen, 0 ); - PUT_UINT64_BE( low, msglen, 8 ); + ctx->buffer[used++] = 0x80; - last = (size_t)( ctx->total[0] & 0x7F ); - padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); - if( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 ) + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) return( ret ); - if( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 ) - return( ret ); + memset( ctx->buffer, 0, 112 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, ctx->buffer, 112 ); + PUT_UINT64_BE( low, ctx->buffer, 120 ); + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ PUT_UINT64_BE( ctx->state[0], output, 0 ); PUT_UINT64_BE( ctx->state[1], output, 8 ); PUT_UINT64_BE( ctx->state[2], output, 16 ); diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c index 2e9a0fd792..59cdc7a806 100644 --- a/thirdparty/mbedtls/library/ssl_ciphersuites.c +++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c @@ -47,7 +47,7 @@ * 1. By key exchange: * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK * 2. By key length and cipher: - * AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 > 3DES + * ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 > 3DES * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 * 4. By hash function used when relevant * 5. By key exchange/auth again: EC > non-EC @@ -57,6 +57,11 @@ static const int ciphersuite_preference[] = #if defined(MBEDTLS_SSL_CIPHERSUITES) MBEDTLS_SSL_CIPHERSUITES, #else + /* Chacha-Poly ephemeral suites */ + MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + /* All AES-256 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, @@ -127,6 +132,8 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* The PSK ephemeral suites */ + MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, @@ -227,6 +234,7 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* The RSA PSK suites */ + MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, @@ -246,6 +254,7 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CCM, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, @@ -312,6 +321,75 @@ static const int ciphersuite_preference[] = static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = { +#if defined(MBEDTLS_CHACHAPOLY_C) && \ + defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#endif /* MBEDTLS_CHACHAPOLY_C && + MBEDTLS_SHA256_C && + MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #if defined(MBEDTLS_AES_C) #if defined(MBEDTLS_SHA1_C) diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c index 7455e99d2e..ba59c48989 100644 --- a/thirdparty/mbedtls/library/ssl_cli.c +++ b/thirdparty/mbedtls/library/ssl_cli.c @@ -57,7 +57,7 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t hostname_len; *olen = 0; @@ -127,7 +127,7 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -171,7 +171,7 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t sig_alg_len = 0; const int *md; #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) @@ -256,7 +256,7 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; unsigned char *elliptic_curve_list = p + 6; size_t elliptic_curve_len = 0; const mbedtls_ecp_curve_info *info; @@ -329,7 +329,7 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -362,7 +362,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, { int ret; unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t kkpp_len; *olen = 0; @@ -439,7 +439,7 @@ static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -472,7 +472,7 @@ static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -504,7 +504,7 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -538,7 +538,7 @@ static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -572,7 +572,7 @@ static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t tlen = ssl->session_negotiate->ticket_len; *olen = 0; @@ -616,7 +616,7 @@ static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t alpnlen = 0; const char **cur; @@ -1247,14 +1247,14 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, size_t list_size; const unsigned char *p; - list_size = buf[0]; - if( list_size + 1 != len ) + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } + list_size = buf[0]; p = buf + 1; while( list_size > 0 ) @@ -2117,7 +2117,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; unsigned char *p = ssl->handshake->premaster + pms_offset; - if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); @@ -2160,7 +2160,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, p, ssl->handshake->pmslen, ssl->out_msg + offset + len_bytes, olen, - MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes, + MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); @@ -2544,10 +2544,9 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) defined(MBEDTLS_SSL_PROTO_TLS1_2) if( md_alg != MBEDTLS_MD_NONE ) { - /* Info from md_alg will be used instead */ - hashlen = 0; - ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, params, - params_len, md_alg ); + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + params, params_len, + md_alg ); if( ret != 0 ) return( ret ); } @@ -2559,8 +2558,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : - (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); if( ssl->session_negotiate->peer_cert == NULL ) { @@ -2711,7 +2709,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) * therefore the buffer length at this point must be greater than that * regardless of the actual code path. */ - if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, @@ -2928,7 +2926,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) i = 4; n = ssl->conf->psk_identity_len; - if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or " "SSL buffer too short" ) ); @@ -2964,7 +2962,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) */ n = ssl->handshake->dhm_ctx.len; - if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long" " or SSL buffer too short" ) ); @@ -2993,7 +2991,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) * ClientECDiffieHellmanPublic public; */ ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, - &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i, + &ssl->out_msg[i], MBEDTLS_SSL_OUT_CONTENT_LEN - i, ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { @@ -3034,7 +3032,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) i = 4; ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, - ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n, + ssl->out_msg + i, MBEDTLS_SSL_OUT_CONTENT_LEN - i, &n, ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { diff --git a/thirdparty/mbedtls/library/ssl_srv.c b/thirdparty/mbedtls/library/ssl_srv.c index 09b7a3fed3..52087ae6e1 100644 --- a/thirdparty/mbedtls/library/ssl_srv.c +++ b/thirdparty/mbedtls/library/ssl_srv.c @@ -91,6 +91,13 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + if( len < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( servername_list_size + 2 != len ) { @@ -101,7 +108,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, } p = buf + 2; - while( servername_list_size > 0 ) + while( servername_list_size > 2 ) { hostname_len = ( ( p[1] << 8 ) | p[2] ); if( hostname_len + 3 > servername_list_size ) @@ -205,6 +212,12 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, mbedtls_md_type_t md_cur; mbedtls_pk_type_t sig_cur; + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( sig_alg_list_size + 2 != len || sig_alg_list_size % 2 != 0 ) @@ -273,6 +286,12 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, const unsigned char *p; const mbedtls_ecp_curve_info *curve_info, **curves; + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( list_size + 2 != len || list_size % 2 != 0 ) @@ -332,14 +351,14 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, size_t list_size; const unsigned char *p; - list_size = buf[0]; - if( list_size + 1 != len ) + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } + list_size = buf[0]; p = buf + 1; while( list_size > 0 ) @@ -709,7 +728,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", cur->cert ); - if( ! mbedtls_pk_can_do( cur->key, pk_alg ) ) + if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); continue; @@ -733,7 +752,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_ECDSA_C) if( pk_alg == MBEDTLS_PK_ECDSA && - ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 ) + ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); continue; @@ -1303,7 +1322,7 @@ read_record_header: else #endif { - if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); @@ -1656,10 +1675,16 @@ read_record_header: while( ext_len != 0 ) { - unsigned int ext_id = ( ( ext[0] << 8 ) - | ( ext[1] ) ); - unsigned int ext_size = ( ( ext[2] << 8 ) - | ( ext[3] ) ); + unsigned int ext_id; + unsigned int ext_size; + if ( ext_len < 4 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) ); + ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) ); if( ext_size + 4 > ext_len ) { @@ -2235,7 +2260,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, { int ret; unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t kkpp_len; *olen = 0; @@ -2342,7 +2367,7 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) cookie_len_byte = p++; if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, - &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN, + &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN, ssl->cli_id, ssl->cli_id_len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); @@ -2638,7 +2663,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) size_t dn_size, total_dn_size; /* excluding length bytes */ size_t ct_len, sa_len; /* including length bytes */ unsigned char *buf, *p; - const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; const mbedtls_x509_crt *crt; int authmode; @@ -2828,54 +2853,56 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2; + size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN + - sig_start ); + int ret = ssl->conf->f_async_resume( ssl, + sig_start, signature_len, sig_max_len ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret ); + return( ret ); +} +#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + +/* Prepare the ServerKeyExchange message, up to and including + * calculating the signature if any, but excluding formatting the + * signature and sending the message. */ +static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) { - int ret; - size_t n = 0; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - #if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) - unsigned char *p = ssl->out_msg + 4; - size_t len; #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - unsigned char *dig_signed = p; - size_t dig_signed_len = 0; + unsigned char *dig_signed = NULL; #endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); - - /* - * - * Part 1: Extract static ECDH parameters and abort - * if ServerKeyExchange not needed. - * - */ - - /* For suites involving ECDH, extract DH parameters - * from certificate at this point. */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) - if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) - { - ssl_get_ecdh_params_from_cert( ssl ); - } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + (void) ciphersuite_info; /* unused in some configurations */ +#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + (void) signature_len; +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ - /* Key exchanges not involving ephemeral keys don't use - * ServerKeyExchange, so end here. */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) - if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); - ssl->state++; - return( 0 ); - } -#endif /* MBEDTLS_KEY_EXCHANGE__NON_PFS__ENABLED */ + ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ /* * - * Part 2: Provide key exchange parameters for chosen ciphersuite. + * Part 1: Provide key exchange parameters for chosen ciphersuite. * */ @@ -2885,18 +2912,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) { - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + int ret; + size_t len = 0; - ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, - p, end - p, &len, ssl->conf->f_rng, ssl->conf->p_rng ); + ret = mbedtls_ecjpake_write_round_two( + &ssl->handshake->ecjpake_ctx, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); return( ret ); } - p += len; - n += len; + ssl->out_msglen += len; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ @@ -2910,10 +2940,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) { - *(p++) = 0x00; - *(p++) = 0x00; - - n += 2; + ssl->out_msg[ssl->out_msglen++] = 0x00; + ssl->out_msg[ssl->out_msglen++] = 0x00; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ @@ -2924,6 +2952,9 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) { + int ret; + size_t len = 0; + if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); @@ -2947,21 +2978,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) return( ret ); } - if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), - p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + if( ( ret = mbedtls_dhm_make_params( + &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + ssl->out_msg + ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); return( ret ); } #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - dig_signed = p; - dig_signed_len = len; + dig_signed = ssl->out_msg + ssl->out_msglen; #endif - p += len; - n += len; + ssl->out_msglen += len; MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); @@ -2986,6 +3017,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) */ const mbedtls_ecp_curve_info **curve = NULL; const mbedtls_ecp_group_id *gid; + int ret; + size_t len = 0; /* Match our preference list against the offered curves */ for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) @@ -3009,21 +3042,21 @@ curve_matching_done: return( ret ); } - if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, - p, MBEDTLS_SSL_MAX_CONTENT_LEN - n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + if( ( ret = mbedtls_ecdh_make_params( + &ssl->handshake->ecdh_ctx, &len, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); return( ret ); } #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - dig_signed = p; - dig_signed_len = len; + dig_signed = ssl->out_msg + ssl->out_msglen; #endif - p += len; - n += len; + ssl->out_msglen += len; MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); } @@ -3031,19 +3064,20 @@ curve_matching_done: /* * - * Part 3: For key exchanges involving the server signing the + * Part 2: For key exchanges involving the server signing the * exchange parameters, compute and add the signature here. * */ #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) { - size_t signature_len = 0; - unsigned int hashlen = 0; - unsigned char hash[64]; + size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; + size_t hashlen = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + int ret; /* - * 3.1: Choose hash algorithm: + * 2.1: Choose hash algorithm: * A: For TLS 1.2, obey signature-hash-algorithm extension * to choose appropriate hash. * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 @@ -3090,7 +3124,7 @@ curve_matching_done: MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) ); /* - * 3.2: Compute the hash to be signed + * 2.2: Compute the hash to be signed */ #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) @@ -3110,9 +3144,7 @@ curve_matching_done: defined(MBEDTLS_SSL_PROTO_TLS1_2) if( md_alg != MBEDTLS_MD_NONE ) { - /* Info from md_alg will be used instead */ - hashlen = 0; - ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, dig_signed, dig_signed_len, md_alg ); @@ -3127,18 +3159,11 @@ curve_matching_done: return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : - (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); /* - * 3.3: Compute and add the signature + * 2.3: Compute and add the signature */ - if( mbedtls_ssl_own_key( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { @@ -3158,33 +3183,150 @@ curve_matching_done: * */ - *(p++) = mbedtls_ssl_hash_from_md_alg( md_alg ); - *(p++) = mbedtls_ssl_sig_from_pk_alg( sig_alg ); - - n += 2; + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_hash_from_md_alg( md_alg ); + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_sig_from_pk_alg( sig_alg ); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen, - p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_sign_start != NULL ) + { + ret = ssl->conf->f_async_sign_start( ssl, + mbedtls_ssl_own_cert( ssl ), + md_alg, hash, hashlen ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_sign was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_server_key_exchange( ssl, signature_len ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), + md_alg, hash, hashlen, + ssl->out_msg + ssl->out_msglen + 2, + signature_len, + ssl->conf->f_rng, + ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); return( ret ); } + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + + return( 0 ); +} + +/* Prepare the ServerKeyExchange message and send it. For ciphersuites + * that do not include a ServerKeyExchange message, do nothing. Either + * way, if successful, move on to the next step in the SSL state + * machine. */ +static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t signature_len = 0; +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) + /* Extract static ECDH parameters and abort if ServerKeyExchange + * is not needed. */ + if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) + { + /* For suites involving ECDH, extract DH parameters + * from certificate at this point. */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) + { + ssl_get_ecdh_params_from_cert( ssl ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ - *(p++) = (unsigned char)( signature_len >> 8 ); - *(p++) = (unsigned char)( signature_len ); - n += 2; + /* Key exchanges not involving ephemeral keys don't use + * ServerKeyExchange, so end here. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ - MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already prepared the message and there is an ongoing + * signature operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) ); + ret = ssl_resume_server_key_exchange( ssl, &signature_len ); + } + else +#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + { + /* ServerKeyExchange is needed. Prepare the message. */ + ret = ssl_prepare_server_key_exchange( ssl, &signature_len ); + } - n += signature_len; + if( ret != 0 ) + { + /* If we're starting to write a new message, set ssl->out_msglen + * to 0. But if we're resuming after an asynchronous message, + * out_msglen is the amount of data written so far and mst be + * preserved. */ + if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) ); + else + ssl->out_msglen = 0; + return( ret ); } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ - /* Done with actual work; add header and send. */ + /* If there is a signature, write its length. + * ssl_prepare_server_key_exchange already wrote the signature + * itself at its proper place in the output buffer. */ +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( signature_len != 0 ) + { + ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 ); + ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len ); - ssl->out_msglen = 4 + n; + MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", + ssl->out_msg + ssl->out_msglen, + signature_len ); + + /* Skip over the already-written signature */ + ssl->out_msglen += signature_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + + /* Add header and send. */ ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; @@ -3197,7 +3339,6 @@ curve_matching_done: } MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); - return( 0 ); } @@ -3272,33 +3413,59 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char * #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, - const unsigned char *p, - const unsigned char *end, - size_t pms_offset ) + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret = ssl->conf->f_async_resume( ssl, + peer_pms, peer_pmslen, peer_pmssize ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret ); + return( ret ); +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) { int ret; - size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) ); - unsigned char *pms = ssl->handshake->premaster + pms_offset; - unsigned char ver[2]; - unsigned char fake_pms[48], peer_pms[48]; - unsigned char mask; - size_t i, peer_pmslen; - unsigned int diff; + mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl ); + mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk; + size_t len = mbedtls_pk_get_len( public_key ); - if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already started decoding the message and there is an ongoing + * decryption operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) ); + return( ssl_resume_decrypt_pms( ssl, + peer_pms, peer_pmslen, peer_pmssize ) ); } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ /* - * Decrypt the premaster using own private RSA key + * Prepare to decrypt the premaster using own private RSA key */ #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) { + if ( p + 2 > end ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } if( *p++ != ( ( len >> 8 ) & 0xFF ) || *p++ != ( ( len ) & 0xFF ) ) { @@ -3314,30 +3481,120 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); } + /* + * Decrypt the premaster secret + */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_decrypt_start != NULL ) + { + ret = ssl->conf->f_async_decrypt_start( ssl, + mbedtls_ssl_own_cert( ssl ), + p, len ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_decrypt_start was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_decrypt_pms( ssl, + peer_pms, + peer_pmslen, + peer_pmssize ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + ret = mbedtls_pk_decrypt( private_key, p, len, + peer_pms, peer_pmslen, peer_pmssize, + ssl->conf->f_rng, ssl->conf->p_rng ); + return( ret ); +} + +static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret; + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char ver[2]; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, peer_pmslen; + unsigned int diff; + + /* In case of a failure in decryption, the decryption may write less than + * 2 bytes of output, but we always read the first two bytes. It doesn't + * matter in the end because diff will be nonzero in that case due to + * peer_pmslen being less than 48, and we only care whether diff is 0. + * But do initialize peer_pms for robustness anyway. This also makes + * memory analyzers happy (don't access uninitialized memory, even + * if it's an unsigned char). */ + peer_pms[0] = peer_pms[1] = ~0; + + ret = ssl_decrypt_encrypted_pms( ssl, p, end, + peer_pms, + &peer_pmslen, + sizeof( peer_pms ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + return( ret ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + mbedtls_ssl_write_version( ssl->handshake->max_major_ver, - ssl->handshake->max_minor_ver, - ssl->conf->transport, ver ); + ssl->handshake->max_minor_ver, + ssl->conf->transport, ver ); + + /* Avoid data-dependent branches while checking for invalid + * padding, to protect against timing-based Bleichenbacher-type + * attacks. */ + diff = (unsigned int) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ver[0]; + diff |= peer_pms[1] ^ ver[1]; + + /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif /* * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding * must not cause the connection to end immediately; instead, send a * bad_record_mac later in the handshake. - * Also, avoid data-dependant branches here to protect against - * timing-based variants. + * To protect against timing-based variants of the attack, we must + * not have any branch that depends on whether the decryption was + * successful. In particular, always generate the fake premaster secret, + * regardless of whether it will ultimately influence the output or not. */ ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); if( ret != 0 ) + { + /* It's ok to abort on an RNG failure, since this does not reveal + * anything about the RSA decryption. */ return( ret ); - - ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len, - peer_pms, &peer_pmslen, - sizeof( peer_pms ), - ssl->conf->f_rng, ssl->conf->p_rng ); - - diff = (unsigned int) ret; - diff |= peer_pmslen ^ 48; - diff |= peer_pms[0] ^ ver[0]; - diff |= peer_pms[1] ^ ver[1]; + } #if defined(MBEDTLS_SSL_DEBUG_ALL) if( diff != 0 ) @@ -3352,18 +3609,8 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, } ssl->handshake->pmslen = 48; - /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ - /* MSVC has a warning about unary minus on unsigned, but this is - * well-defined and precisely what we want to do here */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif - + /* Set pms to either the true or the fake PMS, without + * data-dependent branches. */ for( i = 0; i < ssl->handshake->pmslen; i++ ) pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); @@ -3445,6 +3692,20 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) ) + if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) && + ( ssl->handshake->async_in_progress != 0 ) ) + { + /* We've already read a record and there is an asynchronous + * operation in progress to decrypt it. So skip reading the + * record. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) ); + } + else +#endif if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); @@ -3557,6 +3818,19 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) { +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ssl->handshake->async_in_progress != 0 ) + { + /* There is an asynchronous operation in progress to + * decrypt the encrypted premaster secret, so skip + * directly to resuming this operation. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) ); + /* Update p to skip the PSK identity. ssl_parse_encrypted_pms + * won't actually use it, but maintain p anyway for robustness. */ + p += ssl->conf->psk_identity_len + 2; + } + else +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); @@ -3926,7 +4200,7 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, ssl->session_negotiate, ssl->out_msg + 10, - ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, &tlen, &lifetime ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c index e8e0cd854b..91f96c8ab6 100644 --- a/thirdparty/mbedtls/library/ssl_tls.c +++ b/thirdparty/mbedtls/library/ssl_tls.c @@ -141,14 +141,24 @@ static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) * } MaxFragmentLength; * and we add 0 -> extension unused */ -static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] = +static unsigned int ssl_mfl_code_to_length( int mfl ) { - MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */ - 512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */ - 1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */ - 2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */ - 4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */ -}; + switch( mfl ) + { + case MBEDTLS_SSL_MAX_FRAG_LEN_NONE: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + case MBEDTLS_SSL_MAX_FRAG_LEN_512: + return 512; + case MBEDTLS_SSL_MAX_FRAG_LEN_1024: + return 1024; + case MBEDTLS_SSL_MAX_FRAG_LEN_2048: + return 2048; + case MBEDTLS_SSL_MAX_FRAG_LEN_4096: + return 4096; + default: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + } +} #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_CLI_C) @@ -688,18 +698,32 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) transform->keylen = cipher_info->key_bitlen / 8; if( cipher_info->mode == MBEDTLS_MODE_GCM || - cipher_info->mode == MBEDTLS_MODE_CCM ) + cipher_info->mode == MBEDTLS_MODE_CCM || + cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) { + size_t taglen, explicit_ivlen; + transform->maclen = 0; mac_key_len = 0; + /* All modes haves 96-bit IVs; + * GCM and CCM has 4 implicit and 8 explicit bytes + * ChachaPoly has all 12 bytes implicit + */ transform->ivlen = 12; - transform->fixed_ivlen = 4; + if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) + transform->fixed_ivlen = 12; + else + transform->fixed_ivlen = 4; + + /* All modes have 128-bit tags, except CCM_8 (ciphersuite flag) */ + taglen = transform->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; - /* Minimum length is expicit IV + tag */ - transform->minlen = transform->ivlen - transform->fixed_ivlen - + ( transform->ciphersuite_info->flags & - MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); + + /* Minimum length of encrypted record */ + explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + transform->minlen = explicit_ivlen + taglen; } else { @@ -956,11 +980,11 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) if( ssl->compress_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); - ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN ); + ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); if( ssl->compress_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", - MBEDTLS_SSL_BUFFER_LEN ) ); + MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } } @@ -1151,6 +1175,9 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch * other_secret already set by the ClientKeyExchange message, * and is 48 bytes long */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + *p++ = 0; *p++ = 48; p += 48; @@ -1276,6 +1303,27 @@ static void ssl_mac( mbedtls_md_context_t *md_ctx, #define SSL_SOME_MODES_USE_MAC #endif +/* The function below is only used in the Lucky 13 counter-measure in + * ssl_decrypt_buf(). These are the defines that guard the call site. */ +#if defined(SSL_SOME_MODES_USE_MAC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) ) +/* This function makes sure every byte in the memory region is accessed + * (in ascending addresses order) */ +static void ssl_read_memory( unsigned char *p, size_t len ) +{ + unsigned char acc = 0; + volatile unsigned char force; + + for( ; len != 0; p++, len-- ) + acc ^= *p; + + force = acc; + (void) force; +} +#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */ + /* * Encryption/decryption functions */ @@ -1297,11 +1345,11 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", ssl->out_msg, ssl->out_msglen ); - if( ssl->out_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d", (unsigned) ssl->out_msglen, - MBEDTLS_SSL_MAX_CONTENT_LEN ) ); + MBEDTLS_SSL_OUT_CONTENT_LEN ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -1394,17 +1442,26 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM ) + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) { int ret; size_t enc_msglen, olen; unsigned char *enc_msg; unsigned char add_data[13]; - unsigned char taglen = ssl->transform_out->ciphersuite_info->flags & + unsigned char iv[12]; + mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned char taglen = transform->ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + size_t explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + /* + * Prepare additional authenticated data + */ memcpy( add_data, ssl->out_ctr, 8 ); add_data[8] = ssl->out_msgtype; mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, @@ -1412,44 +1469,57 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; add_data[12] = ssl->out_msglen & 0xFF; - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 ); /* * Generate IV */ - if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 ) + if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) + { + /* GCM and CCM: fixed || explicit (=seqnum) */ + memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); + memcpy( iv + transform->fixed_ivlen, ssl->out_ctr, 8 ); + memcpy( ssl->out_iv, ssl->out_ctr, 8 ); + + } + else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) + { + /* ChachaPoly: fixed XOR sequence number */ + unsigned char i; + + memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); + + for( i = 0; i < 8; i++ ) + iv[i+4] ^= ssl->out_ctr[i]; + } + else { /* Reminder if we ever add an AEAD mode with a different size */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, - ssl->out_ctr, 8 ); - memcpy( ssl->out_iv, ssl->out_ctr, 8 ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, - ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)", + iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)", + ssl->out_iv, explicit_ivlen ); /* - * Fix pointer positions and message length with added IV + * Fix message length with added IV */ enc_msg = ssl->out_msg; enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->transform_out->ivlen - - ssl->transform_out->fixed_ivlen; + ssl->out_msglen += explicit_ivlen; MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - ssl->out_msglen, 0 ) ); + "including 0 bytes of padding", + ssl->out_msglen ) ); /* * Encrypt and authenticate */ - if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, + if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc, + iv, transform->ivlen, add_data, 13, enc_msg, enc_msglen, enc_msg, &olen, @@ -1609,7 +1679,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) { - size_t i; mbedtls_cipher_mode_t mode; int auth_done = 0; #if defined(SSL_SOME_MODES_USE_MAC) @@ -1659,20 +1728,27 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM ) + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) { int ret; size_t dec_msglen, olen; unsigned char *dec_msg; unsigned char *dec_msg_result; unsigned char add_data[13]; - unsigned char taglen = ssl->transform_in->ciphersuite_info->flags & + unsigned char iv[12]; + mbedtls_ssl_transform *transform = ssl->transform_in; + unsigned char taglen = transform->ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; - size_t explicit_iv_len = ssl->transform_in->ivlen - - ssl->transform_in->fixed_ivlen; + size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen; + /* + * Compute and update sizes + */ if( ssl->in_msglen < explicit_iv_len + taglen ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " @@ -1686,6 +1762,9 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) dec_msg_result = ssl->in_msg; ssl->in_msglen = dec_msglen; + /* + * Prepare additional authenticated data + */ memcpy( add_data, ssl->in_ctr, 8 ); add_data[8] = ssl->in_msgtype; mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, @@ -1693,23 +1772,43 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; add_data[12] = ssl->in_msglen & 0xFF; - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 ); - memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, - ssl->in_iv, - ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); + /* + * Prepare IV + */ + if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) + { + /* GCM and CCM: fixed || explicit (transmitted) */ + memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); + memcpy( iv + transform->fixed_ivlen, ssl->in_iv, 8 ); - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, - ssl->transform_in->ivlen ); + } + else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) + { + /* ChachaPoly: fixed XOR sequence number */ + unsigned char i; + + memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); + + for( i = 0; i < 8; i++ ) + iv[i+4] ^= ssl->in_ctr[i]; + } + else + { + /* Reminder if we ever add an AEAD mode with a different size */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen ); MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); /* * Decrypt and authenticate */ if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, + iv, transform->ivlen, add_data, 13, dec_msg, dec_msglen, dec_msg_result, &olen, @@ -1827,6 +1926,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) */ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) { + unsigned char i; dec_msglen -= ssl->transform_in->ivlen; ssl->in_msglen -= ssl->transform_in->ivlen; @@ -1900,27 +2000,28 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) * and fake check up to 256 bytes of padding */ size_t pad_count = 0, real_count = 1; - size_t padding_idx = ssl->in_msglen - padlen - 1; + size_t padding_idx = ssl->in_msglen - padlen; + size_t i; /* * Padding is guaranteed to be incorrect if: - * 1. padlen >= ssl->in_msglen + * 1. padlen > ssl->in_msglen * - * 2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN + + * 2. padding_idx > MBEDTLS_SSL_IN_CONTENT_LEN + * ssl->transform_in->maclen * * In both cases we reset padding_idx to a safe value (0) to * prevent out-of-buffer reads. */ - correct &= ( ssl->in_msglen >= padlen + 1 ); - correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN + + correct &= ( padlen <= ssl->in_msglen ); + correct &= ( padding_idx <= MBEDTLS_SSL_IN_CONTENT_LEN + ssl->transform_in->maclen ); padding_idx *= correct; - for( i = 1; i <= 256; i++ ) + for( i = 0; i < 256; i++ ) { - real_count &= ( i <= padlen ); + real_count &= ( i < padlen ); pad_count += real_count * ( ssl->in_msg[padding_idx + i] == padlen - 1 ); } @@ -1951,8 +2052,10 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } +#if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", ssl->in_msg, ssl->in_msglen ); +#endif /* * Authenticate if not done yet. @@ -1985,20 +2088,69 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) { /* * Process MAC and always update for padlen afterwards to make - * total time independent of padlen - * - * extra_run compensates MAC check for padlen + * total time independent of padlen. * * Known timing attacks: * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) * - * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values - * correctly. (We round down instead of up, so -56 is the correct - * value for our calculations instead of -55) + * To compensate for different timings for the MAC calculation + * depending on how much padding was removed (which is determined + * by padlen), process extra_run more blocks through the hash + * function. + * + * The formula in the paper is + * extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 ) + * where L1 is the size of the header plus the decrypted message + * plus CBC padding and L2 is the size of the header plus the + * decrypted message. This is for an underlying hash function + * with 64-byte blocks. + * We use ( (Lx+8) / 64 ) to handle 'negative Lx' values + * correctly. We round down instead of up, so -56 is the correct + * value for our calculations instead of -55. + * + * Repeat the formula rather than defining a block_size variable. + * This avoids requiring division by a variable at runtime + * (which would be marginally less efficient and would require + * linking an extra division function in some builds). */ size_t j, extra_run = 0; - extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - - ( 13 + ssl->in_msglen + 8 ) / 64; + + /* + * The next two sizes are the minimum and maximum values of + * in_msglen over all padlen values. + * + * They're independent of padlen, since we previously did + * in_msglen -= padlen. + * + * Note that max_len + maclen is never more than the buffer + * length, as we previously did in_msglen -= maclen too. + */ + const size_t max_len = ssl->in_msglen + padlen; + const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; + + switch( ssl->transform_in->ciphersuite_info->mac ) + { +#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \ + defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_MD5: + case MBEDTLS_MD_SHA1: + case MBEDTLS_MD_SHA256: + /* 8 bytes of message size, 64-byte compression blocks */ + extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - + ( 13 + ssl->in_msglen + 8 ) / 64; + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + /* 16 bytes of message size, 128-byte compression blocks */ + extra_run = ( 13 + ssl->in_msglen + padlen + 16 ) / 128 - + ( 13 + ssl->in_msglen + 16 ) / 128; + break; +#endif + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } extra_run &= correct * 0xFF; @@ -2007,12 +2159,25 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 ); mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, ssl->in_msglen ); + /* Make sure we access everything even when padlen > 0. This + * makes the synchronisation requirements for just-in-time + * Prime+Probe attacks much tighter and hopefully impractical. */ + ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen ); mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); - /* Call mbedtls_md_process at least once due to cache attacks */ + + /* Call mbedtls_md_process at least once due to cache attacks + * that observe whether md_process() was called of not */ for( j = 0; j < extra_run + 1; j++ ) mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + + /* Make sure we access all the memory that could contain the MAC, + * before we check it in the next code block. This makes the + * synchronisation requirements for just-in-time Prime+Probe + * attacks much tighter and hopefully impractical. */ + ssl_read_memory( ssl->in_msg + min_len, + max_len - min_len + ssl->transform_in->maclen ); } else #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ @@ -2022,9 +2187,11 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } +#if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen ); MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); +#endif if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect, ssl->transform_in->maclen ) != 0 ) @@ -2053,6 +2220,16 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) if( ssl->in_msglen == 0 ) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 + && ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + ssl->nb_zero++; /* @@ -2077,6 +2254,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) else #endif { + unsigned char i; for( i = 8; i > ssl_ep_len( ssl ); i-- ) if( ++ssl->in_ctr[i - 1] != 0 ) break; @@ -2126,7 +2304,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl ) ssl->transform_out->ctx_deflate.next_in = msg_pre; ssl->transform_out->ctx_deflate.avail_in = len_pre; ssl->transform_out->ctx_deflate.next_out = msg_post; - ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN - bytes_written; + ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written; ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); if( ret != Z_OK ) @@ -2135,7 +2313,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); } - ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN - + ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN - ssl->transform_out->ctx_deflate.avail_out - bytes_written; MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", @@ -2173,7 +2351,7 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) ssl->transform_in->ctx_inflate.next_in = msg_pre; ssl->transform_in->ctx_inflate.avail_in = len_pre; ssl->transform_in->ctx_inflate.next_out = msg_post; - ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_BUFFER_LEN - + ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN - header_bytes; ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); @@ -2183,7 +2361,7 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); } - ssl->in_msglen = MBEDTLS_SSL_BUFFER_LEN - + ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN - ssl->transform_in->ctx_inflate.avail_out - header_bytes; MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", @@ -2258,7 +2436,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } - if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); @@ -2344,7 +2522,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) } else { - len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); + len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) timeout = ssl->handshake->retransmit_timeout; @@ -2798,12 +2976,12 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) { /* Make room for the additional DTLS fields */ - if( MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen < 8 ) + if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " "size %u, maximum %u", (unsigned) ( ssl->in_hslen - 4 ), - (unsigned) ( MBEDTLS_SSL_MAX_CONTENT_LEN - 12 ) ) ); + (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -3016,7 +3194,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", msg_len ) ); - if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( ssl->in_hslen > MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); @@ -3120,7 +3298,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) ssl->next_record_offset = new_remain - ssl->in_hdr; ssl->in_left = ssl->next_record_offset + remain_len; - if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN - + if( ssl->in_left > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); @@ -3496,7 +3674,7 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) ssl->conf->p_cookie, ssl->cli_id, ssl->cli_id_len, ssl->in_buf, ssl->in_left, - ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len ); + ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); @@ -3593,7 +3771,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) } /* Check length against the size of our buffer */ - if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN + if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_msg - ssl->in_buf ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); @@ -3687,7 +3865,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) if( ssl->transform_in == NULL ) { if( ssl->in_msglen < 1 || - ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); @@ -3703,7 +3881,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_PROTO_SSL3) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN ) + ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); @@ -3716,7 +3894,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) */ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && ssl->in_msglen > ssl->transform_in->minlen + - MBEDTLS_SSL_MAX_CONTENT_LEN + 256 ) + MBEDTLS_SSL_IN_CONTENT_LEN + 256 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); @@ -3764,7 +3942,7 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", ssl->in_msg, ssl->in_msglen ); - if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); @@ -4096,6 +4274,16 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) { + if( ssl->in_msglen != 2 ) + { + /* Note: Standard allows for more than one 2 byte alert + to be packed in a single message, but Mbed TLS doesn't + currently support this. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", ssl->in_msg[0], ssl->in_msg[1] ) ); @@ -4325,10 +4513,10 @@ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) while( crt != NULL ) { n = crt->raw.len; - if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i ) + if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", - i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) ); + i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) ); return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); } @@ -4528,6 +4716,12 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) while( i < ssl->in_hslen ) { + if ( i + 3 > ssl->in_hslen ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } if( ssl->in_msg[i] != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); @@ -5202,7 +5396,7 @@ static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) /* * Free our handshake params */ - mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_handshake_free( ssl ); mbedtls_free( ssl->handshake ); ssl->handshake = NULL; @@ -5557,7 +5751,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl ) if( ssl->session_negotiate ) mbedtls_ssl_session_free( ssl->session_negotiate ); if( ssl->handshake ) - mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_handshake_free( ssl ); /* * Either the pointers are now NULL or cleared properly and can be freed. @@ -5662,17 +5856,23 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf ) { int ret; - const size_t len = MBEDTLS_SSL_BUFFER_LEN; ssl->conf = conf; /* * Prepare base structures */ - if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL || - ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL ) + ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN ); + if( ssl->in_buf == NULL ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN ); + if( ssl->out_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) ); mbedtls_free( ssl->in_buf ); ssl->in_buf = NULL; return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); @@ -5773,9 +5973,9 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->transform_in = NULL; ssl->transform_out = NULL; - memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN ); if( partial == 0 ) - memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN ); #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_reset != NULL ) @@ -5995,27 +6195,27 @@ static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, mbedtls_x509_crt *cert, mbedtls_pk_context *key ) { - mbedtls_ssl_key_cert *new; + mbedtls_ssl_key_cert *new_cert; - new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); - if( new == NULL ) + new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new_cert == NULL ) return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - new->cert = cert; - new->key = key; - new->next = NULL; + new_cert->cert = cert; + new_cert->key = key; + new_cert->next = NULL; /* Update head is the list was null, else add to the end */ if( *head == NULL ) { - *head = new; + *head = new_cert; } else { mbedtls_ssl_key_cert *cur = *head; while( cur->next != NULL ) cur = cur->next; - cur->next = new; + cur->next = new_cert; } return( 0 ); @@ -6100,7 +6300,7 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, /* Identity len will be encoded on two bytes */ if( ( psk_identity_len >> 16 ) != 0 || - psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -6401,7 +6601,7 @@ void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) { if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || - mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN ) + ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -6480,6 +6680,43 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, } #endif +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +void mbedtls_ssl_conf_async_private_cb( + mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *async_config_data ) +{ + conf->f_async_sign_start = f_async_sign; + conf->f_async_decrypt_start = f_async_decrypt; + conf->f_async_resume = f_async_resume; + conf->f_async_cancel = f_async_cancel; + conf->p_async_config_data = async_config_data; +} + +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ) +{ + return( conf->p_async_config_data ); +} + +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ) +{ + if( ssl->handshake == NULL ) + return( NULL ); + else + return( ssl->handshake->user_async_ctx ); +} + +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ) +{ + if( ssl->handshake != NULL ) + ssl->handshake->user_async_ctx = ctx; +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + /* * SSL get accessors */ @@ -6642,15 +6879,15 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) /* * Assume mfl_code is correct since it was checked when set */ - max_len = mfl_code_to_length[ssl->conf->mfl_code]; + max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code ); /* * Check if a smaller max length was negotiated */ if( ssl->session_out != NULL && - mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) + ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len ) { - max_len = mfl_code_to_length[ssl->session_out->mfl_code]; + max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); } return max_len; @@ -7194,8 +7431,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) } /* - * Send application data to be encrypted by the SSL layer, - * taking care of max fragment length and buffer size + * Send application data to be encrypted by the SSL layer, taking care of max + * fragment length and buffer size. + * + * According to RFC 5246 Section 6.2.1: + * + * Zero-length fragments of Application data MAY be sent as they are + * potentially useful as a traffic analysis countermeasure. + * + * Therefore, it is possible that the input message length is 0 and the + * corresponding return code is 0 on success. */ static int ssl_write_real( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -7204,7 +7449,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); #else - size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ if( len > max_len ) { @@ -7223,6 +7468,12 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, if( ssl->out_left != 0 ) { + /* + * The user has previously tried to send the data and + * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially + * written. In this case, we expect the high-level write function + * (e.g. mbedtls_ssl_write()) to be called with the same parameters + */ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); @@ -7231,6 +7482,11 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, } else { + /* + * The user is trying to send a message the first time, so we need to + * copy the data into the internal buffers and setup the data structure + * to keep track of partial writes + */ ssl->out_msglen = len; ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; memcpy( ssl->out_msg, buf, len ); @@ -7387,11 +7643,21 @@ static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) } #endif /* MBEDTLS_X509_CRT_PARSE_C */ -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) { + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + if( handshake == NULL ) return; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 ) + { + ssl->conf->f_async_cancel( ssl ); + handshake->async_in_progress = 0; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) mbedtls_md5_free( &handshake->fin_md5 ); @@ -7496,20 +7762,20 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) if( ssl->out_buf != NULL ) { - mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN ); mbedtls_free( ssl->out_buf ); } if( ssl->in_buf != NULL ) { - mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN ); mbedtls_free( ssl->in_buf ); } #if defined(MBEDTLS_ZLIB_SUPPORT) if( ssl->compress_buf != NULL ) { - mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); mbedtls_free( ssl->compress_buf ); } #endif @@ -7522,7 +7788,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) if( ssl->handshake ) { - mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_handshake_free( ssl ); mbedtls_ssl_transform_free( ssl->transform_negotiate ); mbedtls_ssl_session_free( ssl->session_negotiate ); @@ -8289,13 +8555,14 @@ exit: #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_2) int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, - unsigned char *output, - unsigned char *data, size_t data_len, - mbedtls_md_type_t md_alg ) + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) { int ret = 0; mbedtls_md_context_t ctx; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + *hashlen = mbedtls_md_get_size( md_info ); mbedtls_md_init( &ctx ); @@ -8326,7 +8593,7 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); goto exit; } - if( ( ret = mbedtls_md_finish( &ctx, output ) ) != 0 ) + if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret ); goto exit; diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c index f1c37245c7..7a32e672c7 100644 --- a/thirdparty/mbedtls/library/threading.c +++ b/thirdparty/mbedtls/library/threading.c @@ -114,9 +114,6 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * #if defined(MBEDTLS_FS_IO) mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); #endif -#if defined(MBEDTLS_HAVE_TIME_DATE) - mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); -#endif } /* @@ -127,9 +124,6 @@ void mbedtls_threading_free_alt( void ) #if defined(MBEDTLS_FS_IO) mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); #endif -#if defined(MBEDTLS_HAVE_TIME_DATE) - mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); -#endif } #endif /* MBEDTLS_THREADING_ALT */ @@ -142,8 +136,5 @@ void mbedtls_threading_free_alt( void ) #if defined(MBEDTLS_FS_IO) mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; #endif -#if defined(MBEDTLS_HAVE_TIME_DATE) -mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; -#endif #endif /* MBEDTLS_THREADING_C */ diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c index 6a30e51259..3e8139f1f9 100644 --- a/thirdparty/mbedtls/library/timing.c +++ b/thirdparty/mbedtls/library/timing.c @@ -39,7 +39,8 @@ #if !defined(MBEDTLS_TIMING_ALT) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) #error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" #endif diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c index e8e448f6f8..777b6034c4 100644 --- a/thirdparty/mbedtls/library/version_features.c +++ b/thirdparty/mbedtls/library/version_features.c @@ -39,6 +39,9 @@ static const char *features[] = { #if defined(MBEDTLS_NO_UDBL_DIVISION) "MBEDTLS_NO_UDBL_DIVISION", #endif /* MBEDTLS_NO_UDBL_DIVISION */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) + "MBEDTLS_NO_64BIT_MULTIPLICATION", +#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ #if defined(MBEDTLS_HAVE_SSE2) "MBEDTLS_HAVE_SSE2", #endif /* MBEDTLS_HAVE_SSE2 */ @@ -102,6 +105,12 @@ static const char *features[] = { #if defined(MBEDTLS_CCM_ALT) "MBEDTLS_CCM_ALT", #endif /* MBEDTLS_CCM_ALT */ +#if defined(MBEDTLS_CHACHA20_ALT) + "MBEDTLS_CHACHA20_ALT", +#endif /* MBEDTLS_CHACHA20_ALT */ +#if defined(MBEDTLS_CHACHAPOLY_ALT) + "MBEDTLS_CHACHAPOLY_ALT", +#endif /* MBEDTLS_CHACHAPOLY_ALT */ #if defined(MBEDTLS_CMAC_ALT) "MBEDTLS_CMAC_ALT", #endif /* MBEDTLS_CMAC_ALT */ @@ -117,6 +126,9 @@ static const char *features[] = { #if defined(MBEDTLS_GCM_ALT) "MBEDTLS_GCM_ALT", #endif /* MBEDTLS_GCM_ALT */ +#if defined(MBEDTLS_NIST_KW_ALT) + "MBEDTLS_NIST_KW_ALT", +#endif /* MBEDTLS_NIST_KW_ALT */ #if defined(MBEDTLS_MD2_ALT) "MBEDTLS_MD2_ALT", #endif /* MBEDTLS_MD2_ALT */ @@ -126,6 +138,9 @@ static const char *features[] = { #if defined(MBEDTLS_MD5_ALT) "MBEDTLS_MD5_ALT", #endif /* MBEDTLS_MD5_ALT */ +#if defined(MBEDTLS_POLY1305_ALT) + "MBEDTLS_POLY1305_ALT", +#endif /* MBEDTLS_POLY1305_ALT */ #if defined(MBEDTLS_RIPEMD160_ALT) "MBEDTLS_RIPEMD160_ALT", #endif /* MBEDTLS_RIPEMD160_ALT */ @@ -255,6 +270,12 @@ static const char *features[] = { #if defined(MBEDTLS_CIPHER_MODE_CTR) "MBEDTLS_CIPHER_MODE_CTR", #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + "MBEDTLS_CIPHER_MODE_OFB", +#endif /* MBEDTLS_CIPHER_MODE_OFB */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + "MBEDTLS_CIPHER_MODE_XTS", +#endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) "MBEDTLS_CIPHER_NULL_CIPHER", #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ @@ -405,6 +426,9 @@ static const char *features[] = { #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) "MBEDTLS_SSL_ALL_ALERT_MESSAGES", #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + "MBEDTLS_SSL_ASYNC_PRIVATE", +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_DEBUG_ALL) "MBEDTLS_SSL_DEBUG_ALL", #endif /* MBEDTLS_SSL_DEBUG_ALL */ @@ -543,6 +567,12 @@ static const char *features[] = { #if defined(MBEDTLS_CERTS_C) "MBEDTLS_CERTS_C", #endif /* MBEDTLS_CERTS_C */ +#if defined(MBEDTLS_CHACHA20_C) + "MBEDTLS_CHACHA20_C", +#endif /* MBEDTLS_CHACHA20_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + "MBEDTLS_CHACHAPOLY_C", +#endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CIPHER_C) "MBEDTLS_CIPHER_C", #endif /* MBEDTLS_CIPHER_C */ @@ -585,9 +615,15 @@ static const char *features[] = { #if defined(MBEDTLS_HAVEGE_C) "MBEDTLS_HAVEGE_C", #endif /* MBEDTLS_HAVEGE_C */ +#if defined(MBEDTLS_HKDF_C) + "MBEDTLS_HKDF_C", +#endif /* MBEDTLS_HKDF_C */ #if defined(MBEDTLS_HMAC_DRBG_C) "MBEDTLS_HMAC_DRBG_C", #endif /* MBEDTLS_HMAC_DRBG_C */ +#if defined(MBEDTLS_NIST_KW_C) + "MBEDTLS_NIST_KW_C", +#endif /* MBEDTLS_NIST_KW_C */ #if defined(MBEDTLS_MD_C) "MBEDTLS_MD_C", #endif /* MBEDTLS_MD_C */ @@ -639,6 +675,9 @@ static const char *features[] = { #if defined(MBEDTLS_PLATFORM_C) "MBEDTLS_PLATFORM_C", #endif /* MBEDTLS_PLATFORM_C */ +#if defined(MBEDTLS_POLY1305_C) + "MBEDTLS_POLY1305_C", +#endif /* MBEDTLS_POLY1305_C */ #if defined(MBEDTLS_RIPEMD160_C) "MBEDTLS_RIPEMD160_C", #endif /* MBEDTLS_RIPEMD160_C */ diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c index 371d6da1dc..2e6795f750 100644 --- a/thirdparty/mbedtls/library/x509.c +++ b/thirdparty/mbedtls/library/x509.c @@ -29,6 +29,10 @@ * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ +/* Ensure gmtime_r is available even with -std=c99; must be included before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. */ +#define _POSIX_C_SOURCE 200112L + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -59,26 +63,13 @@ #define mbedtls_snprintf snprintf #endif - #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#include <windows.h> -#else +#if defined(MBEDTLS_HAVE_TIME_DATE) #include <time.h> #endif -#if defined(MBEDTLS_FS_IO) -#include <stdio.h> -#if !defined(_WIN32) -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#endif -#endif - #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } @@ -903,36 +894,18 @@ int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) * Set the time structure to the current time. * Return 0 on success, non-zero on failure. */ -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -static int x509_get_current_time( mbedtls_x509_time *now ) -{ - SYSTEMTIME st; - - GetSystemTime( &st ); - - now->year = st.wYear; - now->mon = st.wMonth; - now->day = st.wDay; - now->hour = st.wHour; - now->min = st.wMinute; - now->sec = st.wSecond; - - return( 0 ); -} -#else static int x509_get_current_time( mbedtls_x509_time *now ) { - struct tm *lt; + struct tm *lt, tm_buf; mbedtls_time_t tt; int ret = 0; -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - tt = mbedtls_time( NULL ); - lt = gmtime( &tt ); +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + lt = gmtime_s( &tm_buf, &tt ) == 0 ? &tm_buf : NULL; +#else + lt = gmtime_r( &tt, &tm_buf ); +#endif if( lt == NULL ) ret = -1; @@ -946,14 +919,8 @@ static int x509_get_current_time( mbedtls_x509_time *now ) now->sec = lt->tm_sec; } -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - return( ret ); } -#endif /* _WIN32 && !EFIX64 && !EFI32 */ /* * Return 0 if before <= after, 1 otherwise diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c index 038eae0257..3cf1743821 100644 --- a/thirdparty/mbedtls/library/x509_crt.c +++ b/thirdparty/mbedtls/library/x509_crt.c @@ -1139,7 +1139,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) char filename[MAX_PATH]; char *p; size_t len = strlen( path ); - int lengthAsInt = 0; + int length_as_int = 0; WIN32_FIND_DATAW file_data; HANDLE hFind; @@ -1154,7 +1154,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) p = filename + len; filename[len++] = '*'; - if ( FAILED ( SizeTToInt( len, &lengthAsInt ) ) ) + if ( FAILED ( SizeTToInt( len, &length_as_int ) ) ) return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); /* @@ -1165,7 +1165,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) * incoming string are less than MAX_PATH to avoid a buffer overrun with * MultiByteToWideChar(). */ - w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir, + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, length_as_int, szDir, MAX_PATH - 3 ); if( w_ret == 0 ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); @@ -1182,11 +1182,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) continue; - if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &lengthAsInt ) ) ) + if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &length_as_int ) ) ) return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, - lengthAsInt, + length_as_int, p, (int) len - 1, NULL, NULL ); if( w_ret == 0 ) diff --git a/thirdparty/mbedtls/library/x509_csr.c b/thirdparty/mbedtls/library/x509_csr.c index 3e8e8fbc6a..f84425728a 100644 --- a/thirdparty/mbedtls/library/x509_csr.c +++ b/thirdparty/mbedtls/library/x509_csr.c @@ -274,34 +274,25 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); #if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_init( &pem ); - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( buf[buflen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else + if( buf[buflen - 1] == '\0' ) + { + mbedtls_pem_init( &pem ); ret = mbedtls_pem_read_buffer( &pem, "-----BEGIN CERTIFICATE REQUEST-----", "-----END CERTIFICATE REQUEST-----", buf, NULL, 0, &use_len ); - if( ret == 0 ) - { - /* - * Was PEM encoded, parse the result - */ - if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) - return( ret ); + if( ret == 0 ) + /* + * Was PEM encoded, parse the result + */ + ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ); mbedtls_pem_free( &pem ); - return( 0 ); - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - mbedtls_pem_free( &pem ); - return( ret ); + if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); } - else #endif /* MBEDTLS_PEM_PARSE_C */ return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); } diff --git a/thirdparty/misc/triangulator.h b/thirdparty/misc/triangulator.h index b6dd7e8236..d1538cfae5 100644 --- a/thirdparty/misc/triangulator.h +++ b/thirdparty/misc/triangulator.h @@ -21,9 +21,9 @@ #ifndef TRIANGULATOR_H #define TRIANGULATOR_H -#include "math_2d.h" #include "list.h" #include "set.h" +#include "vector2.h" //2D point structure diff --git a/thirdparty/squish/config.h b/thirdparty/squish/config.h index 92edefe966..05f8d72598 100644 --- a/thirdparty/squish/config.h +++ b/thirdparty/squish/config.h @@ -32,6 +32,26 @@ #endif // Set to 1 or 2 when building squish to use SSE or SSE2 instructions. +// -- GODOT start -- +#ifdef _MSC_VER + #if defined(_M_IX86_FP) + #if _M_IX86_FP >= 2 + #define SQUISH_USE_SSE 2 + #elif _M_IX86_FP >= 1 + #define SQUISH_USE_SSE 1 + #endif + #elif defined(_M_X64) + #define SQUISH_USE_SSE 2 + #endif +#else + #if defined(__SSE2__) + #define SQUISH_USE_SSE 2 + #elif defined(__SSE__) + #define SQUISH_USE_SSE 1 + #endif +#endif +// -- GODOT end -- + #ifndef SQUISH_USE_SSE #define SQUISH_USE_SSE 0 #endif diff --git a/thirdparty/thekla_atlas/nvcore/nvcore.h b/thirdparty/thekla_atlas/nvcore/nvcore.h index a3deb66be2..5ef69668d9 100644 --- a/thirdparty/thekla_atlas/nvcore/nvcore.h +++ b/thirdparty/thekla_atlas/nvcore/nvcore.h @@ -44,6 +44,9 @@ #elif defined POSH_OS_FREEBSD # define NV_OS_FREEBSD 1 # define NV_OS_UNIX 1 +#elif defined POSH_OS_HAIKU +# define NV_OS_HAIKU 1 +# define NV_OS_UNIX 1 #elif defined POSH_OS_OPENBSD # define NV_OS_OPENBSD 1 # define NV_OS_UNIX 1 @@ -341,7 +344,7 @@ template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N]; #elif NV_CC_GNUC # if NV_OS_LINUX # include "DefsGnucLinux.h" -# elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD +# elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_HAIKU # include "DefsGnucDarwin.h" # elif NV_OS_ORBIS # include "DefsOrbis.h" diff --git a/thirdparty/thekla_atlas/nvmath/nvmath.h b/thirdparty/thekla_atlas/nvmath/nvmath.h index f2b69426e1..a697f9293d 100644 --- a/thirdparty/thekla_atlas/nvmath/nvmath.h +++ b/thirdparty/thekla_atlas/nvmath/nvmath.h @@ -181,10 +181,8 @@ namespace nv { #if NV_OS_WIN32 || NV_OS_XBOX || NV_OS_DURANGO return _finite(f) != 0; -#elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_ORBIS +#elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_ORBIS || NV_OS_LINUX return isfinite(f); -#elif NV_OS_LINUX - return finitef(f); #else # error "isFinite not supported" #endif @@ -196,10 +194,8 @@ namespace nv { #if NV_OS_WIN32 || NV_OS_XBOX || NV_OS_DURANGO return _isnan(f) != 0; -#elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_ORBIS +#elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_ORBIS || NV_OS_LINUX return isnan(f); -#elif NV_OS_LINUX - return isnanf(f); #else # error "isNan not supported" #endif diff --git a/thirdparty/thekla_atlas/poshlib/posh.h b/thirdparty/thekla_atlas/poshlib/posh.h index 3038297b39..72acd20ce0 100644 --- a/thirdparty/thekla_atlas/poshlib/posh.h +++ b/thirdparty/thekla_atlas/poshlib/posh.h @@ -298,6 +298,11 @@ Metrowerks: # define POSH_OS_STRING "Linux" #endif +#if defined __HAIKU__ +# define POSH_OS_HAIKU 1 +# define POSH_OS_STRING "Haiku" +#endif + #if defined __FreeBSD__ # define POSH_OS_FREEBSD 1 # define POSH_OS_STRING "FreeBSD" |