blitz-research 9 rokov pred
rodič
commit
7f31bf9e58
100 zmenil súbory, kde vykonal 24451 pridanie a 0 odobranie
  1. 37 0
      .gitignore
  2. 14 0
      LICENSE.TXT
  3. 762 0
      Monkey2-quick-reference.html
  4. 43 0
      bin/env_linux.txt
  5. 52 0
      bin/env_macos.txt
  6. 59 0
      bin/env_windows.txt
  7. BIN
      bin/mx2cc_linux
  8. BIN
      bin/mx2cc_macos
  9. BIN
      bin/mx2cc_windows.exe
  10. 1 0
      devtools/.gitignore
  11. 4 0
      hello-world.monkey2
  12. 0 0
      modules/gles20/angle/angle.monkey2
  13. BIN
      modules/gles20/angle/bin/d3dcompiler_47.dll
  14. BIN
      modules/gles20/angle/bin/libEGL.a
  15. BIN
      modules/gles20/angle/bin/libEGL.dll
  16. BIN
      modules/gles20/angle/bin/libGLESv2.dll
  17. 303 0
      modules/gles20/angle/include/EGL/egl.h
  18. 774 0
      modules/gles20/angle/include/EGL/eglext.h
  19. 139 0
      modules/gles20/angle/include/EGL/eglplatform.h
  20. 620 0
      modules/gles20/angle/include/GLES2/gl2.h
  21. 2013 0
      modules/gles20/angle/include/GLES2/gl2ext.h
  22. 30 0
      modules/gles20/angle/include/GLES2/gl2platform.h
  23. 282 0
      modules/gles20/angle/include/KHR/khrplatform.h
  24. BIN
      modules/gles20/angle/lib/libEGL.a
  25. BIN
      modules/gles20/angle/lib/libEGL.lib
  26. BIN
      modules/gles20/angle/lib/libGLESv2.a
  27. BIN
      modules/gles20/angle/lib/libGLESv2.lib
  28. 597 0
      modules/gles20/gles20.monkey2
  29. 187 0
      modules/gles20/makegles20.monkey
  30. 621 0
      modules/gles20/native/gles20.h
  31. 8 0
      modules/gles20/native/gles20_linux.h
  32. 107 0
      modules/gles20/native/gles20_windows.c
  33. 307 0
      modules/gles20/native/gles20_windows.h
  34. 195 0
      modules/hoedown/hoedown.json
  35. 112 0
      modules/hoedown/hoedown.monkey2
  36. 15 0
      modules/hoedown/hoedown/LICENSE
  37. 104 0
      modules/hoedown/hoedown/README.md
  38. 281 0
      modules/hoedown/hoedown/src/autolink.c
  39. 46 0
      modules/hoedown/hoedown/src/autolink.h
  40. 308 0
      modules/hoedown/hoedown/src/buffer.c
  41. 134 0
      modules/hoedown/hoedown/src/buffer.h
  42. 2994 0
      modules/hoedown/hoedown/src/document.c
  43. 172 0
      modules/hoedown/hoedown/src/document.h
  44. 188 0
      modules/hoedown/hoedown/src/escape.c
  45. 28 0
      modules/hoedown/hoedown/src/escape.h
  46. 754 0
      modules/hoedown/hoedown/src/html.c
  47. 84 0
      modules/hoedown/hoedown/src/html.h
  48. 240 0
      modules/hoedown/hoedown/src/html_blocks.c
  49. 435 0
      modules/hoedown/hoedown/src/html_smartypants.c
  50. 79 0
      modules/hoedown/hoedown/src/stack.c
  51. 52 0
      modules/hoedown/hoedown/src/stack.h
  52. 9 0
      modules/hoedown/hoedown/src/version.c
  53. 33 0
      modules/hoedown/hoedown/src/version.h
  54. 98 0
      modules/libc/libc.monkey2
  55. 57 0
      modules/libc/native/libc.cpp
  56. 25 0
      modules/libc/native/libc.h
  57. 93 0
      modules/miniz/miniz.monkey2
  58. 4916 0
      modules/miniz/native/miniz.c
  59. 770 0
      modules/miniz/native/miniz.h
  60. 18 0
      modules/monkey/debug.monkey2
  61. 6 0
      modules/monkey/gc.monkey2
  62. 109 0
      modules/monkey/math.monkey2
  63. 209 0
      modules/monkey/monkey.json
  64. 17 0
      modules/monkey/monkey.monkey2
  65. 2 0
      modules/monkey/native/bbarray.cpp
  66. 360 0
      modules/monkey/native/bbarray.h
  67. 2 0
      modules/monkey/native/bbdebug.cpp
  68. 31 0
      modules/monkey/native/bbdebug.h
  69. 2 0
      modules/monkey/native/bbfunction.cpp
  70. 260 0
      modules/monkey/native/bbfunction.h
  71. 247 0
      modules/monkey/native/bbgc.cpp
  72. 258 0
      modules/monkey/native/bbgc.h
  73. 12 0
      modules/monkey/native/bbinit.cpp
  74. 17 0
      modules/monkey/native/bbinit.h
  75. 66 0
      modules/monkey/native/bbmemory.cpp
  76. 13 0
      modules/monkey/native/bbmemory.h
  77. 123 0
      modules/monkey/native/bbmonkey.cpp
  78. 24 0
      modules/monkey/native/bbmonkey.h
  79. 2 0
      modules/monkey/native/bbobject.cpp
  80. 43 0
      modules/monkey/native/bbobject.h
  81. 14 0
      modules/monkey/native/bbstd.h
  82. 173 0
      modules/monkey/native/bbstring.cpp
  83. 577 0
      modules/monkey/native/bbstring.h
  84. 2 0
      modules/monkey/native/bbtypes.cpp
  85. 25 0
      modules/monkey/native/bbtypes.h
  86. 50 0
      modules/monkey/native/bbvariant.h
  87. 168 0
      modules/monkey/types.monkey2
  88. 20 0
      modules/sdl2/SDL/COPYING.txt
  89. 53 0
      modules/sdl2/SDL/CREDITS.txt
  90. 8 0
      modules/sdl2/SDL/TWEAKS.txt
  91. 132 0
      modules/sdl2/SDL/include/SDL.h
  92. 289 0
      modules/sdl2/SDL/include/SDL_assert.h
  93. 268 0
      modules/sdl2/SDL/include/SDL_atomic.h
  94. 605 0
      modules/sdl2/SDL/include/SDL_audio.h
  95. 97 0
      modules/sdl2/SDL/include/SDL_bits.h
  96. 63 0
      modules/sdl2/SDL/include/SDL_blendmode.h
  97. 71 0
      modules/sdl2/SDL/include/SDL_clipboard.h
  98. 55 0
      modules/sdl2/SDL/include/SDL_config.h
  99. 419 0
      modules/sdl2/SDL/include/SDL_config.h.cmake
  100. 359 0
      modules/sdl2/SDL/include/SDL_config.h.in

+ 37 - 0
.gitignore

@@ -0,0 +1,37 @@
+
+*.buildv*
+
+/*.txt
+!/README.TXT
+!/LICENSE.TXT
+
+/desktop.ini
+
+/bananas
+
+/bin/*.dll
+/bin/assets
+
+/devtools/*
+!/devtools/.gitignore
+
+/help
+
+/modules/*
+!/modules/monkey
+!/modules/libc
+!/modules/miniz
+!/modules/hoedown
+!/modules/stb-image
+!/modules/std
+!/modules/gles20
+!/modules/sdl2
+
+/src/createrelease
+/src/launcher
+/src/ted2
+
+/src/*.save
+
+/tmp/*
+!/tmp/.gitignore

+ 14 - 0
LICENSE.TXT

@@ -0,0 +1,14 @@
+
+The zlib/libpng License
+
+Copyright (c) 2015 Mark Sibly
+
+This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.

+ 762 - 0
Monkey2-quick-reference.html

@@ -0,0 +1,762 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Monkey2-quick-reference</title>
+<link rel="stylesheet" href="https://stackedit.io/res-min/themes/base.css" />
+<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
+</head>
+<body><div class="container"><h3 id="primitive-types">Primitive types</h3>
+
+<table>
+<thead>
+<tr>
+  <th align="left">Name</th>
+  <th align="left">Description</th>
+</tr>
+</thead>
+<tbody><tr>
+  <td align="left"><code>Void</code></td>
+  <td align="left">No type</td>
+</tr>
+<tr>
+  <td align="left"><code>Bool</code></td>
+  <td align="left">Boolean</td>
+</tr>
+<tr>
+  <td align="left"><code>Byte</code></td>
+  <td align="left">8 bit signed integer</td>
+</tr>
+<tr>
+  <td align="left"><code>UByte</code></td>
+  <td align="left">8 bit unsigned integer</td>
+</tr>
+<tr>
+  <td align="left"><code>Short</code></td>
+  <td align="left">16 bit signed integer</td>
+</tr>
+<tr>
+  <td align="left"><code>UShort</code></td>
+  <td align="left">16 bit unsigned integer</td>
+</tr>
+<tr>
+  <td align="left"><code>Int</code></td>
+  <td align="left">32 bit signed integer</td>
+</tr>
+<tr>
+  <td align="left"><code>UInt</code></td>
+  <td align="left">32 bit unsigned integer</td>
+</tr>
+<tr>
+  <td align="left"><code>Long</code></td>
+  <td align="left">64 bit signed integer</td>
+</tr>
+<tr>
+  <td align="left"><code>ULong</code></td>
+  <td align="left">64 bit unsigned integer</td>
+</tr>
+<tr>
+  <td align="left"><code>Float</code></td>
+  <td align="left">32 bit float</td>
+</tr>
+<tr>
+  <td align="left"><code>Double</code></td>
+  <td align="left">64 bit float</td>
+</tr>
+<tr>
+  <td align="left"><code>String</code></td>
+  <td align="left">Character string</td>
+</tr>
+<tr>
+  <td align="left"><code>Object</code></td>
+  <td align="left">Class instance</td>
+</tr>
+</tbody></table>
+
+
+
+
+<h3 id="derived-types">Derived types</h3>
+
+<table>
+<thead>
+<tr>
+  <th align="left">Syntax</th>
+  <th align="left">Derived type</th>
+</tr>
+</thead>
+<tbody><tr>
+  <td align="left">type <code>[ ]</code></td>
+  <td align="left">Array type</td>
+</tr>
+<tr>
+  <td align="left">type <code>(</code> types <code>)</code></td>
+  <td align="left">Function type</td>
+</tr>
+<tr>
+  <td align="left">type <code>&lt;</code> types <code>&gt;</code></td>
+  <td align="left">Generic instance type</td>
+</tr>
+<tr>
+  <td align="left">type <code>Ptr</code></td>
+  <td align="left">Pointer type</td>
+</tr>
+</tbody></table>
+
+
+
+
+<h3 id="native-wrapper-types">Native wrapper types</h3>
+
+<table>
+<thead>
+<tr>
+  <th align="left">Name</th>
+  <th align="left">Description</th>
+</tr>
+</thead>
+<tbody><tr>
+  <td align="left"><code>CString</code></td>
+  <td align="left">Null terminated C/C++ <code>const char *</code></td>
+</tr>
+<tr>
+  <td align="left"><code>WString</code></td>
+  <td align="left">Null terminated C/C++ <code>wchar_t *</code></td>
+</tr>
+<tr>
+  <td align="left"><code>Utf8String</code></td>
+  <td align="left">Null terminated C/C++ <code>const unsigned char *</code> in utf8 encoding.</td>
+</tr>
+</tbody></table>
+
+
+<p><code>CString</code>, <code>WString</code> and <code>Utf8String</code> should only be used when declaring parameters for extern functions.</p>
+
+
+
+<h3 id="implicit-conversions">Implicit conversions</h3>
+
+<p>These conversions are performed automatically:</p>
+
+<table>
+<thead>
+<tr>
+  <th align="left">Source type</th>
+  <th align="left">Destination type</th>
+</tr>
+</thead>
+<tbody><tr>
+  <td align="left">Any non-void type</td>
+  <td align="left"><code>Bool</code></td>
+</tr>
+<tr>
+  <td align="left">Any numeric type</td>
+  <td align="left">Any numeric type, <code>String</code></td>
+</tr>
+<tr>
+  <td align="left"><code>String</code></td>
+  <td align="left"><code>CString</code>, <code>WString</code>, <code>Utf8String</code></td>
+</tr>
+<tr>
+  <td align="left">Any pointer type</td>
+  <td align="left"><code>Void Ptr</code></td>
+</tr>
+<tr>
+  <td align="left">Any enum type</td>
+  <td align="left"><code>Int</code></td>
+</tr>
+<tr>
+  <td align="left">Derived class</td>
+  <td align="left">Base class</td>
+</tr>
+</tbody></table>
+
+
+
+
+<h3 id="explicit-conversions">Explicit conversions</h3>
+
+<p>The <code>Cast</code> <code>&lt;</code> <em>dest-type</em> <code>&gt;</code> <code>:</code> <em>dest-type</em> <code>(</code> <em>expression</em> <code>)</code> operator must be used for these conversions:</p>
+
+<table>
+<thead>
+<tr>
+  <th align="left">Source type</th>
+  <th align="left">Destination type</th>
+</tr>
+</thead>
+<tbody><tr>
+  <td align="left"><code>Bool</code></td>
+  <td align="left">Any numeric type</td>
+</tr>
+<tr>
+  <td align="left"><code>String</code></td>
+  <td align="left">Any numeric type</td>
+</tr>
+<tr>
+  <td align="left">Any pointer type</td>
+  <td align="left">Any pointer type</td>
+</tr>
+<tr>
+  <td align="left"><code>Int</code></td>
+  <td align="left">Any enum type</td>
+</tr>
+<tr>
+  <td align="left">Base class</td>
+  <td align="left">Derived class</td>
+</tr>
+</tbody></table>
+
+
+
+
+<h3 id="operators">Operators</h3>
+
+<table>
+<thead>
+<tr>
+  <th align="left">Operator</th>
+  <th align="left">Description</th>
+  <th align="center">Precedence</th>
+</tr>
+</thead>
+<tbody><tr>
+  <td align="left"><code>New</code></td>
+  <td align="left">New object or array</td>
+  <td align="center">1</td>
+</tr>
+<tr>
+  <td align="left"><code>Null</code></td>
+  <td align="left">Null value</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>Self</code></td>
+  <td align="left">Self instance</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>Super</code></td>
+  <td align="left">Super instance</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>True</code></td>
+  <td align="left">Boolean true</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>False</code></td>
+  <td align="left">Boolean false</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>Cast</code></td>
+  <td align="left">Cast operator</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>Lambda</code></td>
+  <td align="left">Lambda function</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><em>identifier</em></td>
+  <td align="left">Identifier</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><em>literal</em></td>
+  <td align="left">Literal value</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>.</code></td>
+  <td align="left">Postfix member acccess</td>
+  <td align="center">2</td>
+</tr>
+<tr>
+  <td align="left"><code>( )</code></td>
+  <td align="left">Postfix Invoke</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>[ ]</code></td>
+  <td align="left">Postfix Index</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>&lt; &gt;</code></td>
+  <td align="left">Postfix Generic instance</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>Varptr</code></td>
+  <td align="left">Unary variable address</td>
+  <td align="center">3</td>
+</tr>
+<tr>
+  <td align="left"><code>-</code></td>
+  <td align="left">Unary numeric negate</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>~</code></td>
+  <td align="left">Unary integer complement</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>Not</code></td>
+  <td align="left">Unary boolean invert</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>*</code></td>
+  <td align="left">Numeric multiplication</td>
+  <td align="center">4</td>
+</tr>
+<tr>
+  <td align="left"><code>/</code></td>
+  <td align="left">Numeric division</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>Mod</code></td>
+  <td align="left">Numeric modulo</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>+</code></td>
+  <td align="left">Numeric addition</td>
+  <td align="center">5</td>
+</tr>
+<tr>
+  <td align="left"><code>-</code></td>
+  <td align="left">Numeric subtraction</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>Shl</code></td>
+  <td align="left">Integer shift left</td>
+  <td align="center">6</td>
+</tr>
+<tr>
+  <td align="left"><code>Shr</code></td>
+  <td align="left">Integer shift right</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>&amp;</code></td>
+  <td align="left">Integer and</td>
+  <td align="center">7</td>
+</tr>
+<tr>
+  <td align="left"><code>~</code></td>
+  <td align="left">Integer xor</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>|</code></td>
+  <td align="left">Integer or</td>
+  <td align="center">8</td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>&lt;=&gt;</code></td>
+  <td align="left">Compare</td>
+  <td align="center">9</td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>&lt;</code></td>
+  <td align="left">Less than</td>
+  <td align="center">10</td>
+</tr>
+<tr>
+  <td align="left"><code>&gt;</code></td>
+  <td align="left">Greater than</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>&lt;=</code></td>
+  <td align="left">Less than or equal</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>&gt;=</code></td>
+  <td align="left">Greater than or equal</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>=</code></td>
+  <td align="left">Equal</td>
+  <td align="center">11</td>
+</tr>
+<tr>
+  <td align="left"><code>&lt;&gt;</code></td>
+  <td align="left">Not equal</td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>And</code></td>
+  <td align="left">Boolean and</td>
+  <td align="center">12</td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>Or</code></td>
+  <td align="left">Boolean or</td>
+  <td align="center">13</td>
+</tr>
+<tr>
+  <td align="left"></td>
+  <td align="left"></td>
+  <td align="center"></td>
+</tr>
+<tr>
+  <td align="left"><code>?</code> <code>Else</code></td>
+  <td align="left">If-then-else</td>
+  <td align="center">14</td>
+</tr>
+</tbody></table>
+
+
+
+
+<h3 id="string-members">String members</h3>
+
+<table>
+<thead>
+<tr>
+  <th align="left">Member</th>
+</tr>
+</thead>
+<tbody><tr>
+  <td align="left">Property Length:Int</td>
+</tr>
+<tr>
+  <td align="left">Property Utf8Length:Int</td>
+</tr>
+<tr>
+  <td align="left">Method Find:Int( str:String,from:Int=0 )</td>
+</tr>
+<tr>
+  <td align="left">Method FindLast:Int( str:String,from:Int=0 )</td>
+</tr>
+<tr>
+  <td align="left">Method Contains:Bool( str:String )</td>
+</tr>
+<tr>
+  <td align="left">Method StartsWith:Bool( str:String )</td>
+</tr>
+<tr>
+  <td align="left">Method EndsWith:Bool( str:String )</td>
+</tr>
+<tr>
+  <td align="left">Method Slice:String( from:Int )</td>
+</tr>
+<tr>
+  <td align="left">Method Slice:String( from:Int,tail:Int )</td>
+</tr>
+<tr>
+  <td align="left">Method ToUpper:String()</td>
+</tr>
+<tr>
+  <td align="left">Method ToLower:String()</td>
+</tr>
+<tr>
+  <td align="left">Method Capitalize:String()</td>
+</tr>
+<tr>
+  <td align="left">Method Trim:String()</td>
+</tr>
+<tr>
+  <td align="left">Method Replace:String( find:String,replace:String )</td>
+</tr>
+<tr>
+  <td align="left">Method Split:String<a></a></td>
+</tr>
+<tr>
+  <td align="left">Method Join:String( bits:String[] )</td>
+</tr>
+<tr>
+  <td align="left">Method ToUtf8String:Int( buf:Void Ptr,size:Int )</td>
+</tr>
+<tr>
+  <td align="left">Function FromChar:String( chr:Int )</td>
+</tr>
+<tr>
+  <td align="left">Function FromCString:String( data:Void Ptr )</td>
+</tr>
+<tr>
+  <td align="left">Function FromWString:String( data:Void Ptr )</td>
+</tr>
+<tr>
+  <td align="left">Function FromUtf8String:String( data:Void Ptr )</td>
+</tr>
+<tr>
+  <td align="left">Function FromUtf8String:String( data:Void Ptr,size:Int )</td>
+</tr>
+</tbody></table>
+
+
+
+
+<h3 id="array-members">Array members</h3>
+
+<table>
+<thead>
+<tr>
+  <th align="left">Member</th>
+</tr>
+</thead>
+<tbody><tr>
+  <td align="left">Property Length:Int</td>
+</tr>
+</tbody></table>
+
+
+
+
+<h3 id="creating-arrays">Creating arrays</h3>
+
+<ul>
+<li><p><code>New</code> <em>element-type</em> <code>[</code> <em>length-expression</em> <code>]</code></p></li>
+<li><p><code>New</code> <em>element-type</em> <code>[]</code> <code>(</code> <em>element-expressions</em> <code>)</code></p></li>
+</ul>
+
+
+
+<h3 id="variable-declarations">Variable declarations</h3>
+
+<p>Local variables</p>
+
+<ul>
+<li><p><code>Local</code> <em>identifier</em> <code>:</code> <em>type</em> [ <code>=</code> <em>expression</em> ]</p></li>
+<li><p><code>Local</code> <em>identifier</em> <code>:=</code> <em>expression</em></p></li>
+</ul>
+
+<p>Field variables:</p>
+
+<ul>
+<li><p><code>Field</code> <em>identifier</em> <code>:</code> <em>type</em> [ <code>=</code> <em>expression</em> ]</p></li>
+<li><p><code>Field</code> <em>identifier</em> <code>:=</code> <em>expression</em></p></li>
+<li><p><code>Field</code> <em>identifier</em> <code>:</code> <em>type</em> <code>=</code> <em>extern-symbol</em></p></li>
+</ul>
+
+<p>Global variables:</p>
+
+<ul>
+<li><p><code>Global</code> <em>identifier</em> <code>:</code> <em>type</em> [ <code>=</code> <em>expression</em> ]</p></li>
+<li><p><code>Global</code> <em>identifier</em> <code>:=</code> <em>expression</em></p></li>
+<li><p><code>Global</code> <em>identifier</em> <code>:</code> <em>type</em> <code>=</code> <em>extern-symbol</em></p></li>
+</ul>
+
+
+
+<h3 id="constant-declarations">Constant declarations</h3>
+
+<ul>
+<li><p><code>Const</code> <em>identifier</em> <code>:</code> <em>type</em> <code>=</code> <em>expression</em></p></li>
+<li><p><code>Const</code> <em>identifier</em> <code>:=</code> <em>expression</em></p></li>
+<li><p><code>Const</code> <em>identifier</em> <code>:</code> <em>type</em> <code>=</code> <em>extern-symbol</em></p></li>
+</ul>
+
+
+
+<h3 id="method-declarations">Method declarations</h3>
+
+<ul>
+<li><code>Method</code> <em>identifier</em> <code>:</code> <em>return-type</em> <code>(</code> <em>param-decls</em> <code>)</code> [ <code>Abstract</code> | <code>Virtual</code> | <code>Override</code> | <code>Final</code> | <code>Override Final</code> ] [ <code>=</code><em>extern-symbol</em> ] <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> <br>
+<code>End</code> | <code>End Method</code></li>
+</ul>
+
+
+
+<h3 id="function-declarations">Function declarations</h3>
+
+<ul>
+<li><code>Function</code> <em>identifier</em> <code>:</code> <em>return-type</em> <code>(</code> <em>param-decls</em><code>)</code> [ <code>=</code><em>extern-symbol</em> ] <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> <br>
+<code>End</code> | <code>End Method</code></li>
+</ul>
+
+
+
+<h3 id="if-statement">If statement</h3>
+
+<ul>
+<li><p><code>If</code> <em>expression</em> [ <code>Then</code> ] <em>simple-statements</em> { <code>ElseIf</code> <em>expression</em> [ <code>Then</code> ] <em>simple-statements</em> } [ <code>Else</code> <em>simple-statements</em> ]</p></li>
+<li><p><code>If</code> <em>expression</em> [ <code>Then</code> ] <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> <br>
+{ <code>ElseIf</code> expression  <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> }  <br>
+[ <code>Else</code>  <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> ]  <br>
+<code>End</code> | <code>End If</code> | <code>EndIf</code></p></li>
+</ul>
+
+
+
+<h3 id="while-statement">While statement</h3>
+
+<ul>
+<li><code>While</code> <em>expression</em> <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> <br>
+<code>End</code> | <code>End While</code> | <code>Wend</code></li>
+</ul>
+
+
+
+<h3 id="repeat-statement">Repeat statement</h3>
+
+<ul>
+<li><p><code>Repeat</code> <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> <br>
+<code>Until</code> <em>expression</em></p></li>
+<li><p><code>Repeat</code> <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> <br>
+<code>Forever</code></p></li>
+</ul>
+
+
+
+<h3 id="for-statement">For statement</h3>
+
+<ul>
+<li><p><code>For</code> <em>variable-expression</em> <code>=</code> <em>expression</em> <code>To</code> | <code>Until</code> <em>expression</em> [ <code>Step</code> <em>expression</em> ] <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> <br>
+<code>End</code> | <code>End For</code> | <code>Next</code></p></li>
+<li><p><code>For</code> <em>variable-expression</em> <code>= Eachin</code> <em>expression</em> <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> <br>
+<code>End</code> | <code>End For</code> | <code>Next</code></p></li>
+</ul>
+
+
+
+<h3 id="select-statement">Select statement</h3>
+
+<ul>
+<li><code>Select</code> <em>expression</em> <br>
+{ <code>Case</code> <em>expression</em> { <code>,</code> expression } <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> } <br>
+[ <code>Default</code> <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> ] <br>
+<code>End</code> | <code>End Select</code></li>
+</ul>
+
+
+
+<h3 id="try-statement">Try statement</h3>
+
+<ul>
+<li><code>Try</code> <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> <br>
+<code>Catch</code> ident <code>:</code> type <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> <br>
+{ <code>Catch</code> ident <code>:</code> type <br>
+&nbsp;&nbsp;&nbsp;&nbsp;    <em>statement-block</em> } <br>
+<code>End</code> | <code>End Try</code></li>
+</ul>
+
+
+
+<h3 id="return-statement">Return statement</h3>
+
+<ul>
+<li><code>Return</code> [ <em>expression</em> ]</li>
+</ul>
+
+
+
+<h3 id="throw-statement">Throw statement</h3>
+
+<ul>
+<li><code>Throw</code> [ <em>expression</em> ]</li>
+</ul>
+
+
+
+<h3 id="continue-statement">Continue statement</h3>
+
+<ul>
+<li><code>Continue</code></li>
+</ul>
+
+
+
+<h3 id="exit-statement">Exit statement</h3>
+
+<ul>
+<li><code>Exit</code></li>
+</ul>
+
+
+
+<h3 id="keywords">Keywords</h3>
+
+<p><code>Namespace Using Import Extern Public Private Protected Void Bool Byte UByte Short UShort Int UInt Long ULong Float Double String Object New Self Super Eachin True False Null Where Alias Const Local Global Field Method Function Property Getter Setter Operator Lambda Enum Class Interface Struct Extends Implements Virtual Override Abstract Final Inline Varptr Ptr Not Mod And Or Shl Shr End If Then Else Elseif Endif While Wend Repeat Until Forever For To Step Next Select Case Default Try Catch Throw Throwable Continue Exit Return Print Cast</code></p>
+
+<p>These keywords are currently unused but reserved for future use:</p>
+
+<p><code>Extension Protocol Delete Var Friend Static</code></p></div></body>
+</html>

+ 43 - 0
bin/env_linux.txt

@@ -0,0 +1,43 @@
+
+'***** COMMON *****
+
+MX2_BUILD_VERBOSE=0
+
+'***** DESKTOP *****
+
+MX2_BUILD_DIR_DESKTOP_DEBUG=desktop_debug_linux
+MX2_BUILD_DIR_DESKTOP_RELEASE=desktop_release_linux
+
+'LD options
+MX2_LD_OPTS_DESKTOP=
+MX2_LD_OPTS_DESKTOP_DEBUG=-O0 '-g
+MX2_LD_OPTS_DESKTOP_RELEASE=-O3 -s
+
+'C compiler options
+MX2_CC_OPTS_DESKTOP=-std=gnu99
+MX2_CC_OPTS_DESKTOP_DEBUG=-O0 '-g
+MX2_CC_OPTS_DESKTOP_RELEASE=-O3 -DNDEBUG
+
+'C++ compiler options
+MX2_CPP_OPTS_DESKTOP=-std=c++11
+MX2_CPP_OPTS_DESKTOP_DEBUG=-O0 '-g
+MX2_CPP_OPTS_DESKTOP_RELEASE=-O3 -DNDEBUG
+
+'***** EMSCRIPTEN *****
+
+MX2_BUILD_DIR_EMSCRIPTEN_DEBUG=emscripten_debug
+MX2_BUILD_DIR_EMSCRIPTEN_RELEASE=emscripten_release
+
+MX2_MSERVER="${MX2_HOME}/devtools/MonkeyXFree86c/bin/mserver_linux"
+
+MX2_LD_OPTS_EMSCRIPTEN=-s TOTAL_MEMORY=33554432 -s DISABLE_EXCEPTION_CATCHING=0
+MX2_LD_OPTS_EMSCRIPTEN_DEBUG=-O2
+MX2_LD_OPTS_EMSCRIPTEN_RELEASE=-O3
+
+MX2_CC_OPTS_EMSCRIPTEN=-std=gnu99 -Wno-undefined-bool-conversion -s TOTAL_MEMORY=33554432 -s DISABLE_EXCEPTION_CATCHING=0
+MX2_CC_OPTS_EMSCRIPTEN_DEBUG=-O2
+MX2_CC_OPTS_EMSCRIPTEN_RELEASE=-O3
+
+MX2_CPP_OPTS_EMSCRIPTEN=-std=c++11 -Wno-undefined-bool-conversion -s TOTAL_MEMORY=33554432 -s DISABLE_EXCEPTION_CATCHING=0
+MX2_CPP_OPTS_EMSCRIPTEN_DEBUG=-O2
+MX2_CPP_OPTS_EMSCRIPTEN_RELEASE=-O3

+ 52 - 0
bin/env_macos.txt

@@ -0,0 +1,52 @@
+
+'***** COMMON *****
+
+MX2_BUILD_VERBOSE=0
+
+'***** DESKTOP *****
+
+MX2_BUILD_DIR_DESKTOP_DEBUG=desktop_debug_macos
+MX2_BUILD_DIR_DESKTOP_RELEASE=desktop_release_macos
+
+'LD options
+MX2_LD_OPTS_DESKTOP=
+MX2_LD_OPTS_DESKTOP_DEBUG=-O0 '-g
+MX2_LD_OPTS_DESKTOP_RELEASE=-O3
+
+'C compiler options
+MX2_CC_OPTS_DESKTOP=-std=gnu99 -Wno-deprecated-declarations -Wno-tautological-pointer-compare -Wno-undefined-bool-conversion -Wno-int-to-void-pointer-cast -Wno-inconsistent-missing-override -Wno-logical-op-parentheses
+MX2_CC_OPTS_DESKTOP_DEBUG=-O0 '-g
+MX2_CC_OPTS_DESKTOP_RELEASE=-O3 -DNDEBUG
+
+'C++ compiler options
+MX2_CPP_OPTS_DESKTOP=-std=c++11 -Wno-deprecated-declarations -Wno-tautological-pointer-compare -Wno-undefined-bool-conversion -Wno-int-to-void-pointer-cast -Wno-inconsistent-missing-override -Wno-logical-op-parentheses
+MX2_CPP_OPTS_DESKTOP_DEBUG=-O0 '-g
+MX2_CPP_OPTS_DESKTOP_RELEASE=-O3 -DNDEBUG
+
+'***** EMSCRIPTEN *****
+
+EMSCRIPTEN=${HOME}/emsdk/emscripten/1.35.0
+PATH=${HOME}/emsdk:${HOME}/emsdk/clang/e1.35.0_64bit:${HOME}/emsdk/node/0.12.2_64bit/bin:${HOME}/emsdk/emscripten/1.35.0:${PATH}
+
+MX2_MSERVER=open "${MX2_HOME}/devtools/MonkeyXFree86c/bin/mserver_macos.app"
+
+'El Capitan broke my python...
+PATH=/usr/local/bin:${PATH}
+
+MX2_BUILD_DIR_EMSCRIPTEN_DEBUG=emscripten_debug
+MX2_BUILD_DIR_EMSCRIPTEN_RELEASE=emscripten_release
+
+'LD options
+MX2_LD_OPTS_EMSCRIPTEN=-s TOTAL_MEMORY=33554432 -s DISABLE_EXCEPTION_CATCHING=0 -s USE_PTHREADS=1
+MX2_LD_OPTS_EMSCRIPTEN_DEBUG=-O2
+MX2_LD_OPTS_EMSCRIPTEN_RELEASE=-O3
+
+'C compiler options
+MX2_CC_OPTS_EMSCRIPTEN=-std=gnu99 -s TOTAL_MEMORY=33554432 -s DISABLE_EXCEPTION_CATCHING=0 -s USE_PTHREADS=1 -Wno-undefined-bool-conversion -Wno-inconsistent-missing-override -Wno-logical-op-parentheses -Wno-warn-absolute-paths
+MX2_CC_OPTS_EMSCRIPTEN_DEBUG=-O2
+MX2_CC_OPTS_EMSCRIPTEN_RELEASE=-O3
+
+'C++ compiler options
+MX2_CPP_OPTS_EMSCRIPTEN=-std=c++11 -s TOTAL_MEMORY=33554432 -s DISABLE_EXCEPTION_CATCHING=0 -s USE_PTHREADS=1 -Wno-undefined-bool-conversion -Wno-inconsistent-missing-override -Wno-logical-op-parentheses -Wno-warn-absolute-paths
+MX2_CPP_OPTS_EMSCRIPTEN_DEBUG=-O2
+MX2_CPP_OPTS_EMSCRIPTEN_RELEASE=-O3

+ 59 - 0
bin/env_windows.txt

@@ -0,0 +1,59 @@
+
+'***** COMMON ******
+
+MX2_BUILD_VERBOSE=0
+
+'***** DESKTOP *****
+
+GCC_EXEC_PREFIX=
+PATH=${MX2_HOME}\devtools\TDM-GCC-64-4.9.2\bin;${PATH}
+
+MX2_BUILD_DIR_DESKTOP_DEBUG=desktop_debug_windows
+MX2_BUILD_DIR_DESKTOP_RELEASE=desktop_release_windows
+
+MX2_LD_OPTS_DESKTOP=-m32	'-mwindows
+MX2_LD_OPTS_DESKTOP_DEBUG=
+MX2_LD_OPTS_DESKTOP_RELEASE=-O3 -s
+
+MX2_CC_OPTS_DESKTOP=-std=gnu99 -m32
+MX2_CC_OPTS_DESKTOP_DEBUG=-g
+MX2_CC_OPTS_DESKTOP_RELEASE=-O3
+
+MX2_CPP_OPTS_DESKTOP=-std=c++11 -m32
+MX2_CPP_OPTS_DESKTOP_DEBUG=-g
+MX2_CPP_OPTS_DESKTOP_RELEASE=-O3
+
+'***** EMSCRIPTEN *****
+
+'PATH=${MX2_HOME}\devtools\Emscripten\clang\e1.35.0_64bit;${PATH}
+'PATH=${MX2_HOME}\devtools\Emscripten\emscripten\1.35.0;${PATH}
+'PATH=${MX2_HOME}\devtools\Emscripten\python\2.7.5.3_64bit;${PATH}
+
+EM_CONFIG=C:\Users\Mark Sibly\.emscripten
+EMSCRIPTEN=D:\devtools\Emscripten\emscripten\incoming
+
+PATH=D:\devtools\Emscripten;${PATH}
+PATH=D:\devtools\Emscripten\spidermonkey\37.0.1_64bit;${PATH}
+PATH=D:\devtools\Emscripten\crunch\1.03;${PATH}
+PATH=D:\devtools\Emscripten\clang\fastcomp\build_incoming_vs2013_64\RelWithDebInfo\bin;${PATH}
+PATH=D:\devtools\Emscripten\node\4.1.1_64bit\bin;${PATH}
+PATH=D:\devtools\Emscripten\python\2.7.5.3_64bit;${PATH}
+PATH=D:\devtools\Emscripten\java\7.45_64bit\bin;${PATH}
+PATH=D:\devtools\Emscripten\emscripten\incoming;${PATH}
+
+MX2_MSERVER="${MX2_HOME}\devtools\MonkeyXFree86c\bin\mserver_winnt"
+
+MX2_BUILD_DIR_EMSCRIPTEN_DEBUG=emscripten_debug
+MX2_BUILD_DIR_EMSCRIPTEN_RELEASE=emscripten_release
+
+MX2_LD_OPTS_EMSCRIPTEN=-s TOTAL_MEMORY=33554432 -s DISABLE_EXCEPTION_CATCHING=1 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=1
+MX2_LD_OPTS_EMSCRIPTEN_DEBUG=-O2
+MX2_LD_OPTS_EMSCRIPTEN_RELEASE=-O3
+
+MX2_CC_OPTS_EMSCRIPTEN=-std=gnu99 -s TOTAL_MEMORY=33554432 -s DISABLE_EXCEPTION_CATCHING=1 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=1 -Wno-undefined-bool-conversion -Wno-inconsistent-missing-override -Wno-logical-op-parentheses -Wno-warn-absolute-paths
+MX2_CC_OPTS_EMSCRIPTEN_DEBUG=-O2
+MX2_CC_OPTS_EMSCRIPTEN_RELEASE=-O3
+
+MX2_CPP_OPTS_EMSCRIPTEN=-std=c++11 -s TOTAL_MEMORY=33554432 -s DISABLE_EXCEPTION_CATCHING=1 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=1 -Wno-undefined-bool-conversion
+MX2_CPP_OPTS_EMSCRIPTEN_DEBUG=-O2
+MX2_CPP_OPTS_EMSCRIPTEN_RELEASE=-O3

BIN
bin/mx2cc_linux


BIN
bin/mx2cc_macos


BIN
bin/mx2cc_windows.exe


+ 1 - 0
devtools/.gitignore

@@ -0,0 +1 @@
+!.gitignore

+ 4 - 0
hello-world.monkey2

@@ -0,0 +1,4 @@
+
+Function Main()
+	Print "Hello World!"
+End

+ 0 - 0
modules/gles20/angle/angle.monkey2


BIN
modules/gles20/angle/bin/d3dcompiler_47.dll


BIN
modules/gles20/angle/bin/libEGL.a


BIN
modules/gles20/angle/bin/libEGL.dll


BIN
modules/gles20/angle/bin/libGLESv2.dll


+ 303 - 0
modules/gles20/angle/include/EGL/egl.h

@@ -0,0 +1,303 @@
+#ifndef __egl_h_
+#define __egl_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/
+**
+** Khronos $Revision: 29318 $ on $Date: 2015-01-02 03:16:10 -0800 (Fri, 02 Jan 2015) $
+*/
+
+#include <EGL/eglplatform.h>
+
+/* Generated on date 20150102 */
+
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_VERSION_1_0
+#define EGL_VERSION_1_0 1
+typedef unsigned int EGLBoolean;
+typedef void *EGLDisplay;
+#include <KHR/khrplatform.h>
+#include <EGL/eglplatform.h>
+typedef void *EGLConfig;
+typedef void *EGLSurface;
+typedef void *EGLContext;
+typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+#define EGL_ALPHA_SIZE                    0x3021
+#define EGL_BAD_ACCESS                    0x3002
+#define EGL_BAD_ALLOC                     0x3003
+#define EGL_BAD_ATTRIBUTE                 0x3004
+#define EGL_BAD_CONFIG                    0x3005
+#define EGL_BAD_CONTEXT                   0x3006
+#define EGL_BAD_CURRENT_SURFACE           0x3007
+#define EGL_BAD_DISPLAY                   0x3008
+#define EGL_BAD_MATCH                     0x3009
+#define EGL_BAD_NATIVE_PIXMAP             0x300A
+#define EGL_BAD_NATIVE_WINDOW             0x300B
+#define EGL_BAD_PARAMETER                 0x300C
+#define EGL_BAD_SURFACE                   0x300D
+#define EGL_BLUE_SIZE                     0x3022
+#define EGL_BUFFER_SIZE                   0x3020
+#define EGL_CONFIG_CAVEAT                 0x3027
+#define EGL_CONFIG_ID                     0x3028
+#define EGL_CORE_NATIVE_ENGINE            0x305B
+#define EGL_DEPTH_SIZE                    0x3025
+#define EGL_DONT_CARE                     ((EGLint)-1)
+#define EGL_DRAW                          0x3059
+#define EGL_EXTENSIONS                    0x3055
+#define EGL_FALSE                         0
+#define EGL_GREEN_SIZE                    0x3023
+#define EGL_HEIGHT                        0x3056
+#define EGL_LARGEST_PBUFFER               0x3058
+#define EGL_LEVEL                         0x3029
+#define EGL_MAX_PBUFFER_HEIGHT            0x302A
+#define EGL_MAX_PBUFFER_PIXELS            0x302B
+#define EGL_MAX_PBUFFER_WIDTH             0x302C
+#define EGL_NATIVE_RENDERABLE             0x302D
+#define EGL_NATIVE_VISUAL_ID              0x302E
+#define EGL_NATIVE_VISUAL_TYPE            0x302F
+#define EGL_NONE                          0x3038
+#define EGL_NON_CONFORMANT_CONFIG         0x3051
+#define EGL_NOT_INITIALIZED               0x3001
+#define EGL_NO_CONTEXT                    ((EGLContext)0)
+#define EGL_NO_DISPLAY                    ((EGLDisplay)0)
+#define EGL_NO_SURFACE                    ((EGLSurface)0)
+#define EGL_PBUFFER_BIT                   0x0001
+#define EGL_PIXMAP_BIT                    0x0002
+#define EGL_READ                          0x305A
+#define EGL_RED_SIZE                      0x3024
+#define EGL_SAMPLES                       0x3031
+#define EGL_SAMPLE_BUFFERS                0x3032
+#define EGL_SLOW_CONFIG                   0x3050
+#define EGL_STENCIL_SIZE                  0x3026
+#define EGL_SUCCESS                       0x3000
+#define EGL_SURFACE_TYPE                  0x3033
+#define EGL_TRANSPARENT_BLUE_VALUE        0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE       0x3036
+#define EGL_TRANSPARENT_RED_VALUE         0x3037
+#define EGL_TRANSPARENT_RGB               0x3052
+#define EGL_TRANSPARENT_TYPE              0x3034
+#define EGL_TRUE                          1
+#define EGL_VENDOR                        0x3053
+#define EGL_VERSION                       0x3054
+#define EGL_WIDTH                         0x3057
+#define EGL_WINDOW_BIT                    0x0004
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void);
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id);
+EGLAPI EGLint EGLAPIENTRY eglGetError (void);
+EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname);
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine);
+#endif /* EGL_VERSION_1_0 */
+
+#ifndef EGL_VERSION_1_1
+#define EGL_VERSION_1_1 1
+#define EGL_BACK_BUFFER                   0x3084
+#define EGL_BIND_TO_TEXTURE_RGB           0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA          0x303A
+#define EGL_CONTEXT_LOST                  0x300E
+#define EGL_MIN_SWAP_INTERVAL             0x303B
+#define EGL_MAX_SWAP_INTERVAL             0x303C
+#define EGL_MIPMAP_TEXTURE                0x3082
+#define EGL_MIPMAP_LEVEL                  0x3083
+#define EGL_NO_TEXTURE                    0x305C
+#define EGL_TEXTURE_2D                    0x305F
+#define EGL_TEXTURE_FORMAT                0x3080
+#define EGL_TEXTURE_RGB                   0x305D
+#define EGL_TEXTURE_RGBA                  0x305E
+#define EGL_TEXTURE_TARGET                0x3081
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval);
+#endif /* EGL_VERSION_1_1 */
+
+#ifndef EGL_VERSION_1_2
+#define EGL_VERSION_1_2 1
+typedef unsigned int EGLenum;
+typedef void *EGLClientBuffer;
+#define EGL_ALPHA_FORMAT                  0x3088
+#define EGL_ALPHA_FORMAT_NONPRE           0x308B
+#define EGL_ALPHA_FORMAT_PRE              0x308C
+#define EGL_ALPHA_MASK_SIZE               0x303E
+#define EGL_BUFFER_PRESERVED              0x3094
+#define EGL_BUFFER_DESTROYED              0x3095
+#define EGL_CLIENT_APIS                   0x308D
+#define EGL_COLORSPACE                    0x3087
+#define EGL_COLORSPACE_sRGB               0x3089
+#define EGL_COLORSPACE_LINEAR             0x308A
+#define EGL_COLOR_BUFFER_TYPE             0x303F
+#define EGL_CONTEXT_CLIENT_TYPE           0x3097
+#define EGL_DISPLAY_SCALING               10000
+#define EGL_HORIZONTAL_RESOLUTION         0x3090
+#define EGL_LUMINANCE_BUFFER              0x308F
+#define EGL_LUMINANCE_SIZE                0x303D
+#define EGL_OPENGL_ES_BIT                 0x0001
+#define EGL_OPENVG_BIT                    0x0002
+#define EGL_OPENGL_ES_API                 0x30A0
+#define EGL_OPENVG_API                    0x30A1
+#define EGL_OPENVG_IMAGE                  0x3096
+#define EGL_PIXEL_ASPECT_RATIO            0x3092
+#define EGL_RENDERABLE_TYPE               0x3040
+#define EGL_RENDER_BUFFER                 0x3086
+#define EGL_RGB_BUFFER                    0x308E
+#define EGL_SINGLE_BUFFER                 0x3085
+#define EGL_SWAP_BEHAVIOR                 0x3093
+#define EGL_UNKNOWN                       ((EGLint)-1)
+#define EGL_VERTICAL_RESOLUTION           0x3091
+EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api);
+EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void);
+#endif /* EGL_VERSION_1_2 */
+
+#ifndef EGL_VERSION_1_3
+#define EGL_VERSION_1_3 1
+#define EGL_CONFORMANT                    0x3042
+#define EGL_CONTEXT_CLIENT_VERSION        0x3098
+#define EGL_MATCH_NATIVE_PIXMAP           0x3041
+#define EGL_OPENGL_ES2_BIT                0x0004
+#define EGL_VG_ALPHA_FORMAT               0x3088
+#define EGL_VG_ALPHA_FORMAT_NONPRE        0x308B
+#define EGL_VG_ALPHA_FORMAT_PRE           0x308C
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT       0x0040
+#define EGL_VG_COLORSPACE                 0x3087
+#define EGL_VG_COLORSPACE_sRGB            0x3089
+#define EGL_VG_COLORSPACE_LINEAR          0x308A
+#define EGL_VG_COLORSPACE_LINEAR_BIT      0x0020
+#endif /* EGL_VERSION_1_3 */
+
+#ifndef EGL_VERSION_1_4
+#define EGL_VERSION_1_4 1
+#define EGL_DEFAULT_DISPLAY               ((EGLNativeDisplayType)0)
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT   0x0200
+#define EGL_MULTISAMPLE_RESOLVE           0x3099
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT   0x309A
+#define EGL_MULTISAMPLE_RESOLVE_BOX       0x309B
+#define EGL_OPENGL_API                    0x30A2
+#define EGL_OPENGL_BIT                    0x0008
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT   0x0400
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
+#endif /* EGL_VERSION_1_4 */
+
+#ifndef EGL_VERSION_1_5
+#define EGL_VERSION_1_5 1
+typedef void *EGLSync;
+typedef intptr_t EGLAttrib;
+typedef khronos_utime_nanoseconds_t EGLTime;
+typedef void *EGLImage;
+#define EGL_CONTEXT_MAJOR_VERSION         0x3098
+#define EGL_CONTEXT_MINOR_VERSION         0x30FB
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK   0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
+#define EGL_NO_RESET_NOTIFICATION         0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET         0x31BF
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define EGL_CONTEXT_OPENGL_DEBUG          0x31B0
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS  0x31B2
+#define EGL_OPENGL_ES3_BIT                0x00000040
+#define EGL_CL_EVENT_HANDLE               0x309C
+#define EGL_SYNC_CL_EVENT                 0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE        0x30FF
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE  0x30F0
+#define EGL_SYNC_TYPE                     0x30F7
+#define EGL_SYNC_STATUS                   0x30F1
+#define EGL_SYNC_CONDITION                0x30F8
+#define EGL_SIGNALED                      0x30F2
+#define EGL_UNSIGNALED                    0x30F3
+#define EGL_SYNC_FLUSH_COMMANDS_BIT       0x0001
+#define EGL_FOREVER                       0xFFFFFFFFFFFFFFFFull
+#define EGL_TIMEOUT_EXPIRED               0x30F5
+#define EGL_CONDITION_SATISFIED           0x30F6
+#define EGL_NO_SYNC                       ((EGLSync)0)
+#define EGL_SYNC_FENCE                    0x30F9
+#define EGL_GL_COLORSPACE                 0x309D
+#define EGL_GL_COLORSPACE_SRGB            0x3089
+#define EGL_GL_COLORSPACE_LINEAR          0x308A
+#define EGL_GL_RENDERBUFFER               0x30B9
+#define EGL_GL_TEXTURE_2D                 0x30B1
+#define EGL_GL_TEXTURE_LEVEL              0x30BC
+#define EGL_GL_TEXTURE_3D                 0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET            0x30BD
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
+#define EGL_IMAGE_PRESERVED               0x30D2
+#define EGL_NO_IMAGE                      ((EGLImage)0)
+EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags);
+#endif /* EGL_VERSION_1_5 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 774 - 0
modules/gles20/angle/include/EGL/eglext.h

@@ -0,0 +1,774 @@
+#ifndef __eglext_h_
+#define __eglext_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/
+**
+** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $
+*/
+
+#include <EGL/eglplatform.h>
+
+#define EGL_EGLEXT_VERSION 20140610
+
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: _nomatch_^
+ * Default extensions included: egl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_KHR_cl_event
+#define EGL_KHR_cl_event 1
+#define EGL_CL_EVENT_HANDLE_KHR           0x309C
+#define EGL_SYNC_CL_EVENT_KHR             0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE_KHR    0x30FF
+#endif /* EGL_KHR_cl_event */
+
+#ifndef EGL_KHR_cl_event2
+#define EGL_KHR_cl_event2 1
+typedef void *EGLSyncKHR;
+typedef intptr_t EGLAttribKHR;
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#endif
+#endif /* EGL_KHR_cl_event2 */
+
+#ifndef EGL_KHR_client_get_all_proc_addresses
+#define EGL_KHR_client_get_all_proc_addresses 1
+#endif /* EGL_KHR_client_get_all_proc_addresses */
+
+#ifndef EGL_KHR_config_attribs
+#define EGL_KHR_config_attribs 1
+#define EGL_CONFORMANT_KHR                0x3042
+#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR  0x0020
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR   0x0040
+#endif /* EGL_KHR_config_attribs */
+
+#ifndef EGL_KHR_create_context
+#define EGL_KHR_create_context 1
+#define EGL_CONTEXT_MAJOR_VERSION_KHR     0x3098
+#define EGL_CONTEXT_MINOR_VERSION_KHR     0x30FB
+#define EGL_CONTEXT_FLAGS_KHR             0x30FC
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
+#define EGL_NO_RESET_NOTIFICATION_KHR     0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_KHR     0x31BF
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR  0x00000001
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#define EGL_OPENGL_ES3_BIT_KHR            0x00000040
+#endif /* EGL_KHR_create_context */
+
+#ifndef EGL_KHR_fence_sync
+#define EGL_KHR_fence_sync 1
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
+#define EGL_SYNC_CONDITION_KHR            0x30F8
+#define EGL_SYNC_FENCE_KHR                0x30F9
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_fence_sync */
+
+#ifndef EGL_KHR_get_all_proc_addresses
+#define EGL_KHR_get_all_proc_addresses 1
+#endif /* EGL_KHR_get_all_proc_addresses */
+
+#ifndef EGL_KHR_gl_colorspace
+#define EGL_KHR_gl_colorspace 1
+#define EGL_GL_COLORSPACE_KHR             0x309D
+#define EGL_GL_COLORSPACE_SRGB_KHR        0x3089
+#define EGL_GL_COLORSPACE_LINEAR_KHR      0x308A
+#endif /* EGL_KHR_gl_colorspace */
+
+#ifndef EGL_KHR_gl_renderbuffer_image
+#define EGL_KHR_gl_renderbuffer_image 1
+#define EGL_GL_RENDERBUFFER_KHR           0x30B9
+#endif /* EGL_KHR_gl_renderbuffer_image */
+
+#ifndef EGL_KHR_gl_texture_2D_image
+#define EGL_KHR_gl_texture_2D_image 1
+#define EGL_GL_TEXTURE_2D_KHR             0x30B1
+#define EGL_GL_TEXTURE_LEVEL_KHR          0x30BC
+#endif /* EGL_KHR_gl_texture_2D_image */
+
+#ifndef EGL_KHR_gl_texture_3D_image
+#define EGL_KHR_gl_texture_3D_image 1
+#define EGL_GL_TEXTURE_3D_KHR             0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET_KHR        0x30BD
+#endif /* EGL_KHR_gl_texture_3D_image */
+
+#ifndef EGL_KHR_gl_texture_cubemap_image
+#define EGL_KHR_gl_texture_cubemap_image 1
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8
+#endif /* EGL_KHR_gl_texture_cubemap_image */
+
+#ifndef EGL_KHR_image
+#define EGL_KHR_image 1
+typedef void *EGLImageKHR;
+#define EGL_NATIVE_PIXMAP_KHR             0x30B0
+#define EGL_NO_IMAGE_KHR                  ((EGLImageKHR)0)
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
+#endif
+#endif /* EGL_KHR_image */
+
+#ifndef EGL_KHR_image_base
+#define EGL_KHR_image_base 1
+#define EGL_IMAGE_PRESERVED_KHR           0x30D2
+#endif /* EGL_KHR_image_base */
+
+#ifndef EGL_KHR_image_pixmap
+#define EGL_KHR_image_pixmap 1
+#endif /* EGL_KHR_image_pixmap */
+
+#ifndef EGL_KHR_lock_surface
+#define EGL_KHR_lock_surface 1
+#define EGL_READ_SURFACE_BIT_KHR          0x0001
+#define EGL_WRITE_SURFACE_BIT_KHR         0x0002
+#define EGL_LOCK_SURFACE_BIT_KHR          0x0080
+#define EGL_OPTIMAL_FORMAT_BIT_KHR        0x0100
+#define EGL_MATCH_FORMAT_KHR              0x3043
+#define EGL_FORMAT_RGB_565_EXACT_KHR      0x30C0
+#define EGL_FORMAT_RGB_565_KHR            0x30C1
+#define EGL_FORMAT_RGBA_8888_EXACT_KHR    0x30C2
+#define EGL_FORMAT_RGBA_8888_KHR          0x30C3
+#define EGL_MAP_PRESERVE_PIXELS_KHR       0x30C4
+#define EGL_LOCK_USAGE_HINT_KHR           0x30C5
+#define EGL_BITMAP_POINTER_KHR            0x30C6
+#define EGL_BITMAP_PITCH_KHR              0x30C7
+#define EGL_BITMAP_ORIGIN_KHR             0x30C8
+#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR   0x30C9
+#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA
+#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR  0x30CB
+#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC
+#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD
+#define EGL_LOWER_LEFT_KHR                0x30CE
+#define EGL_UPPER_LEFT_KHR                0x30CF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface);
+#endif
+#endif /* EGL_KHR_lock_surface */
+
+#ifndef EGL_KHR_lock_surface2
+#define EGL_KHR_lock_surface2 1
+#define EGL_BITMAP_PIXEL_SIZE_KHR         0x3110
+#endif /* EGL_KHR_lock_surface2 */
+
+#ifndef EGL_KHR_lock_surface3
+#define EGL_KHR_lock_surface3 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
+#endif
+#endif /* EGL_KHR_lock_surface3 */
+
+#ifndef EGL_KHR_platform_android
+#define EGL_KHR_platform_android 1
+#define EGL_PLATFORM_ANDROID_KHR          0x3141
+#endif /* EGL_KHR_platform_android */
+
+#ifndef EGL_KHR_platform_gbm
+#define EGL_KHR_platform_gbm 1
+#define EGL_PLATFORM_GBM_KHR              0x31D7
+#endif /* EGL_KHR_platform_gbm */
+
+#ifndef EGL_KHR_platform_wayland
+#define EGL_KHR_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_KHR          0x31D8
+#endif /* EGL_KHR_platform_wayland */
+
+#ifndef EGL_KHR_platform_x11
+#define EGL_KHR_platform_x11 1
+#define EGL_PLATFORM_X11_KHR              0x31D5
+#define EGL_PLATFORM_X11_SCREEN_KHR       0x31D6
+#endif /* EGL_KHR_platform_x11 */
+
+#ifndef EGL_KHR_reusable_sync
+#define EGL_KHR_reusable_sync 1
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_STATUS_KHR               0x30F1
+#define EGL_SIGNALED_KHR                  0x30F2
+#define EGL_UNSIGNALED_KHR                0x30F3
+#define EGL_TIMEOUT_EXPIRED_KHR           0x30F5
+#define EGL_CONDITION_SATISFIED_KHR       0x30F6
+#define EGL_SYNC_TYPE_KHR                 0x30F7
+#define EGL_SYNC_REUSABLE_KHR             0x30FA
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR   0x0001
+#define EGL_FOREVER_KHR                   0xFFFFFFFFFFFFFFFFull
+#define EGL_NO_SYNC_KHR                   ((EGLSyncKHR)0)
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_reusable_sync */
+
+#ifndef EGL_KHR_stream
+#define EGL_KHR_stream 1
+typedef void *EGLStreamKHR;
+typedef khronos_uint64_t EGLuint64KHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_NO_STREAM_KHR                 ((EGLStreamKHR)0)
+#define EGL_CONSUMER_LATENCY_USEC_KHR     0x3210
+#define EGL_PRODUCER_FRAME_KHR            0x3212
+#define EGL_CONSUMER_FRAME_KHR            0x3213
+#define EGL_STREAM_STATE_KHR              0x3214
+#define EGL_STREAM_STATE_CREATED_KHR      0x3215
+#define EGL_STREAM_STATE_CONNECTING_KHR   0x3216
+#define EGL_STREAM_STATE_EMPTY_KHR        0x3217
+#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
+#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
+#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
+#define EGL_BAD_STREAM_KHR                0x321B
+#define EGL_BAD_STATE_KHR                 0x321C
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_stream */
+
+#ifndef EGL_KHR_stream_consumer_gltexture
+#define EGL_KHR_stream_consumer_gltexture 1
+#ifdef EGL_KHR_stream
+#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_consumer_gltexture */
+
+#ifndef EGL_KHR_stream_cross_process_fd
+#define EGL_KHR_stream_cross_process_fd 1
+typedef int EGLNativeFileDescriptorKHR;
+#ifdef EGL_KHR_stream
+#define EGL_NO_FILE_DESCRIPTOR_KHR        ((EGLNativeFileDescriptorKHR)(-1))
+typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_cross_process_fd */
+
+#ifndef EGL_KHR_stream_fifo
+#define EGL_KHR_stream_fifo 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_FIFO_LENGTH_KHR        0x31FC
+#define EGL_STREAM_TIME_NOW_KHR           0x31FD
+#define EGL_STREAM_TIME_CONSUMER_KHR      0x31FE
+#define EGL_STREAM_TIME_PRODUCER_KHR      0x31FF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_fifo */
+
+#ifndef EGL_KHR_stream_producer_aldatalocator
+#define EGL_KHR_stream_producer_aldatalocator 1
+#ifdef EGL_KHR_stream
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_aldatalocator */
+
+#ifndef EGL_KHR_stream_producer_eglsurface
+#define EGL_KHR_stream_producer_eglsurface 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_BIT_KHR                0x0800
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_eglsurface */
+
+#ifndef EGL_KHR_surfaceless_context
+#define EGL_KHR_surfaceless_context 1
+#endif /* EGL_KHR_surfaceless_context */
+
+#ifndef EGL_KHR_vg_parent_image
+#define EGL_KHR_vg_parent_image 1
+#define EGL_VG_PARENT_IMAGE_KHR           0x30BA
+#endif /* EGL_KHR_vg_parent_image */
+
+#ifndef EGL_KHR_wait_sync
+#define EGL_KHR_wait_sync 1
+typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#endif
+#endif /* EGL_KHR_wait_sync */
+
+#ifndef EGL_ANDROID_blob_cache
+#define EGL_ANDROID_blob_cache 1
+typedef khronos_ssize_t EGLsizeiANDROID;
+typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize);
+typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize);
+typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+#endif
+#endif /* EGL_ANDROID_blob_cache */
+
+#ifndef EGL_ANDROID_framebuffer_target
+#define EGL_ANDROID_framebuffer_target 1
+#define EGL_FRAMEBUFFER_TARGET_ANDROID    0x3147
+#endif /* EGL_ANDROID_framebuffer_target */
+
+#ifndef EGL_ANDROID_image_native_buffer
+#define EGL_ANDROID_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_ANDROID         0x3140
+#endif /* EGL_ANDROID_image_native_buffer */
+
+#ifndef EGL_ANDROID_native_fence_sync
+#define EGL_ANDROID_native_fence_sync 1
+#define EGL_SYNC_NATIVE_FENCE_ANDROID     0x3144
+#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID  0x3145
+#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
+#define EGL_NO_NATIVE_FENCE_FD_ANDROID    -1
+typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync);
+#endif
+#endif /* EGL_ANDROID_native_fence_sync */
+
+#ifndef EGL_ANDROID_recordable
+#define EGL_ANDROID_recordable 1
+#define EGL_RECORDABLE_ANDROID            0x3142
+#endif /* EGL_ANDROID_recordable */
+
+#ifndef EGL_ANGLE_d3d_share_handle_client_buffer
+#define EGL_ANGLE_d3d_share_handle_client_buffer 1
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
+#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
+
+#ifndef EGL_ANGLE_window_fixed_size
+#define EGL_ANGLE_window_fixed_size 1
+#define EGL_FIXED_SIZE_ANGLE        0x3201
+#endif /* EGL_ANGLE_window_fixed_size */
+
+#ifndef EGL_ANGLE_query_surface_pointer
+#define EGL_ANGLE_query_surface_pointer 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+#endif /* EGL_ANGLE_query_surface_pointer */
+
+#ifndef EGL_ANGLE_software_display
+#define EGL_ANGLE_software_display 1
+#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
+#endif /* EGL_ANGLE_software_display */
+
+#ifndef EGL_ANGLE_direct3d_display
+#define EGL_ANGLE_direct3d_display 1
+#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
+#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
+#endif /* EGL_ANGLE_direct3d_display */
+
+#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
+#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+
+#ifndef EGL_ANGLE_platform_angle
+#define EGL_ANGLE_platform_angle 1
+#define EGL_PLATFORM_ANGLE_ANGLE          0x3202
+#define EGL_PLATFORM_ANGLE_TYPE_ANGLE     0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
+#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
+#endif /* EGL_ANGLE_platform_angle */
+
+#ifndef EGL_ANGLE_platform_angle_d3d
+#define EGL_ANGLE_platform_angle_d3d 1
+#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C
+#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
+#endif /* EGL_ANGLE_platform_angle_d3d */
+
+#ifndef EGL_ANGLE_platform_angle_opengl
+#define EGL_ANGLE_platform_angle_opengl 1
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
+#endif /* EGL_ANGLE_platform_angle_opengl */
+
+#ifndef EGL_ANGLE_device_d3d
+#define EGL_ANGLE_device_d3d 1
+#define EGL_D3D9_DEVICE_ANGLE             0x33A0
+#define EGL_D3D11_DEVICE_ANGLE            0x33A1
+#endif /* EGL_ANGLE_device_d3d */
+
+#ifndef EGL_ARM_pixmap_multisample_discard
+#define EGL_ARM_pixmap_multisample_discard 1
+#define EGL_DISCARD_SAMPLES_ARM           0x3286
+#endif /* EGL_ARM_pixmap_multisample_discard */
+
+#ifndef EGL_EXT_buffer_age
+#define EGL_EXT_buffer_age 1
+#define EGL_BUFFER_AGE_EXT                0x313D
+#endif /* EGL_EXT_buffer_age */
+
+#ifndef EGL_EXT_client_extensions
+#define EGL_EXT_client_extensions 1
+#endif /* EGL_EXT_client_extensions */
+
+#ifndef EGL_EXT_create_context_robustness
+#define EGL_EXT_create_context_robustness 1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define EGL_NO_RESET_NOTIFICATION_EXT     0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_EXT     0x31BF
+#endif /* EGL_EXT_create_context_robustness */
+
+#ifndef EGL_EXT_device_base
+#define EGL_EXT_device_base 1
+typedef void *EGLDeviceEXT;
+#define EGL_NO_DEVICE_EXT                 ((EGLDeviceEXT)(0))
+#define EGL_BAD_DEVICE_EXT                0x322B
+#define EGL_DEVICE_EXT                    0x322C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#endif
+#endif /* EGL_EXT_device_base */
+
+#ifndef EGL_EXT_device_query
+#define EGL_EXT_device_query 1
+#endif /* EGL_EXT_device_query */
+
+#ifndef EGL_EXT_image_dma_buf_import
+#define EGL_EXT_image_dma_buf_import 1
+#define EGL_LINUX_DMA_BUF_EXT             0x3270
+#define EGL_LINUX_DRM_FOURCC_EXT          0x3271
+#define EGL_DMA_BUF_PLANE0_FD_EXT         0x3272
+#define EGL_DMA_BUF_PLANE0_OFFSET_EXT     0x3273
+#define EGL_DMA_BUF_PLANE0_PITCH_EXT      0x3274
+#define EGL_DMA_BUF_PLANE1_FD_EXT         0x3275
+#define EGL_DMA_BUF_PLANE1_OFFSET_EXT     0x3276
+#define EGL_DMA_BUF_PLANE1_PITCH_EXT      0x3277
+#define EGL_DMA_BUF_PLANE2_FD_EXT         0x3278
+#define EGL_DMA_BUF_PLANE2_OFFSET_EXT     0x3279
+#define EGL_DMA_BUF_PLANE2_PITCH_EXT      0x327A
+#define EGL_YUV_COLOR_SPACE_HINT_EXT      0x327B
+#define EGL_SAMPLE_RANGE_HINT_EXT         0x327C
+#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
+#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
+#define EGL_ITU_REC601_EXT                0x327F
+#define EGL_ITU_REC709_EXT                0x3280
+#define EGL_ITU_REC2020_EXT               0x3281
+#define EGL_YUV_FULL_RANGE_EXT            0x3282
+#define EGL_YUV_NARROW_RANGE_EXT          0x3283
+#define EGL_YUV_CHROMA_SITING_0_EXT       0x3284
+#define EGL_YUV_CHROMA_SITING_0_5_EXT     0x3285
+#endif /* EGL_EXT_image_dma_buf_import */
+
+#ifndef EGL_EXT_multiview_window
+#define EGL_EXT_multiview_window 1
+#define EGL_MULTIVIEW_VIEW_COUNT_EXT      0x3134
+#endif /* EGL_EXT_multiview_window */
+
+#ifndef EGL_EXT_platform_base
+#define EGL_EXT_platform_base 1
+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#endif
+#endif /* EGL_EXT_platform_base */
+
+#ifndef EGL_EXT_platform_device
+#define EGL_EXT_platform_device 1
+#define EGL_PLATFORM_DEVICE_EXT           0x313F
+#endif /* EGL_EXT_platform_device */
+
+#ifndef EGL_EXT_platform_wayland
+#define EGL_EXT_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_EXT          0x31D8
+#endif /* EGL_EXT_platform_wayland */
+
+#ifndef EGL_EXT_platform_x11
+#define EGL_EXT_platform_x11 1
+#define EGL_PLATFORM_X11_EXT              0x31D5
+#define EGL_PLATFORM_X11_SCREEN_EXT       0x31D6
+#endif /* EGL_EXT_platform_x11 */
+
+#ifndef EGL_EXT_protected_surface
+#define EGL_EXT_protected_surface 1
+#define EGL_PROTECTED_CONTENT_EXT         0x32C0
+#endif /* EGL_EXT_protected_surface */
+
+#ifndef EGL_EXT_swap_buffers_with_damage
+#define EGL_EXT_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_EXT_swap_buffers_with_damage */
+
+#ifndef EGL_HI_clientpixmap
+#define EGL_HI_clientpixmap 1
+struct EGLClientPixmapHI {
+    void  *pData;
+    EGLint iWidth;
+    EGLint iHeight;
+    EGLint iStride;
+};
+#define EGL_CLIENT_PIXMAP_POINTER_HI      0x8F74
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#endif
+#endif /* EGL_HI_clientpixmap */
+
+#ifndef EGL_HI_colorformats
+#define EGL_HI_colorformats 1
+#define EGL_COLOR_FORMAT_HI               0x8F70
+#define EGL_COLOR_RGB_HI                  0x8F71
+#define EGL_COLOR_RGBA_HI                 0x8F72
+#define EGL_COLOR_ARGB_HI                 0x8F73
+#endif /* EGL_HI_colorformats */
+
+#ifndef EGL_IMG_context_priority
+#define EGL_IMG_context_priority 1
+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG    0x3100
+#define EGL_CONTEXT_PRIORITY_HIGH_IMG     0x3101
+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG   0x3102
+#define EGL_CONTEXT_PRIORITY_LOW_IMG      0x3103
+#endif /* EGL_IMG_context_priority */
+
+#ifndef EGL_MESA_drm_image
+#define EGL_MESA_drm_image 1
+#define EGL_DRM_BUFFER_FORMAT_MESA        0x31D0
+#define EGL_DRM_BUFFER_USE_MESA           0x31D1
+#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
+#define EGL_DRM_BUFFER_MESA               0x31D3
+#define EGL_DRM_BUFFER_STRIDE_MESA        0x31D4
+#define EGL_DRM_BUFFER_USE_SCANOUT_MESA   0x00000001
+#define EGL_DRM_BUFFER_USE_SHARE_MESA     0x00000002
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+#endif /* EGL_MESA_drm_image */
+
+#ifndef EGL_MESA_platform_gbm
+#define EGL_MESA_platform_gbm 1
+#define EGL_PLATFORM_GBM_MESA             0x31D7
+#endif /* EGL_MESA_platform_gbm */
+
+#ifndef EGL_NOK_swap_region
+#define EGL_NOK_swap_region 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region */
+
+#ifndef EGL_NOK_swap_region2
+#define EGL_NOK_swap_region2 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region2 */
+
+#ifndef EGL_NOK_texture_from_pixmap
+#define EGL_NOK_texture_from_pixmap 1
+#define EGL_Y_INVERTED_NOK                0x307F
+#endif /* EGL_NOK_texture_from_pixmap */
+
+#ifndef EGL_NV_3dvision_surface
+#define EGL_NV_3dvision_surface 1
+#define EGL_AUTO_STEREO_NV                0x3136
+#endif /* EGL_NV_3dvision_surface */
+
+#ifndef EGL_NV_coverage_sample
+#define EGL_NV_coverage_sample 1
+#define EGL_COVERAGE_BUFFERS_NV           0x30E0
+#define EGL_COVERAGE_SAMPLES_NV           0x30E1
+#endif /* EGL_NV_coverage_sample */
+
+#ifndef EGL_NV_coverage_sample_resolve
+#define EGL_NV_coverage_sample_resolve 1
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NV    0x3131
+#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
+#endif /* EGL_NV_coverage_sample_resolve */
+
+#ifndef EGL_NV_depth_nonlinear
+#define EGL_NV_depth_nonlinear 1
+#define EGL_DEPTH_ENCODING_NV             0x30E2
+#define EGL_DEPTH_ENCODING_NONE_NV        0
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV   0x30E3
+#endif /* EGL_NV_depth_nonlinear */
+
+#ifndef EGL_NV_native_query
+#define EGL_NV_native_query 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#endif
+#endif /* EGL_NV_native_query */
+
+#ifndef EGL_NV_post_convert_rounding
+#define EGL_NV_post_convert_rounding 1
+#endif /* EGL_NV_post_convert_rounding */
+
+#ifndef EGL_NV_post_sub_buffer
+#define EGL_NV_post_sub_buffer 1
+#define EGL_POST_SUB_BUFFER_SUPPORTED_NV  0x30BE
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#endif
+#endif /* EGL_NV_post_sub_buffer */
+
+#ifndef EGL_NV_stream_sync
+#define EGL_NV_stream_sync 1
+#define EGL_SYNC_NEW_FRAME_NV             0x321F
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#endif
+#endif /* EGL_NV_stream_sync */
+
+#ifndef EGL_NV_sync
+#define EGL_NV_sync 1
+typedef void *EGLSyncNV;
+typedef khronos_utime_nanoseconds_t EGLTimeNV;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
+#define EGL_SYNC_STATUS_NV                0x30E7
+#define EGL_SIGNALED_NV                   0x30E8
+#define EGL_UNSIGNALED_NV                 0x30E9
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV    0x0001
+#define EGL_FOREVER_NV                    0xFFFFFFFFFFFFFFFFull
+#define EGL_ALREADY_SIGNALED_NV           0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV            0x30EB
+#define EGL_CONDITION_SATISFIED_NV        0x30EC
+#define EGL_SYNC_TYPE_NV                  0x30ED
+#define EGL_SYNC_CONDITION_NV             0x30EE
+#define EGL_SYNC_FENCE_NV                 0x30EF
+#define EGL_NO_SYNC_NV                    ((EGLSyncNV)0)
+typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync);
+EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_sync */
+
+#ifndef EGL_NV_system_time
+#define EGL_NV_system_time 1
+typedef khronos_utime_nanoseconds_t EGLuint64NV;
+#ifdef KHRONOS_SUPPORT_INT64
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void);
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_system_time */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 139 - 0
modules/gles20/angle/include/EGL/eglplatform.h

@@ -0,0 +1,139 @@
+#ifndef __eglplatform_h_
+#define __eglplatform_h_
+
+/*
+** Copyright (c) 2007-2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Platform-specific types and definitions for egl.h
+ * $Revision: 23432 $ on $Date: 2013-10-09 00:57:24 -0700 (Wed, 09 Oct 2013) $
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "EGL" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+/* Macros used in EGL function prototype declarations.
+ *
+ * EGL functions should be prototyped as:
+ *
+ * EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
+ * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
+ *
+ * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
+ */
+
+#ifndef EGLAPI
+#define EGLAPI KHRONOS_APICALL
+#endif
+
+#ifndef EGLAPIENTRY
+#define EGLAPIENTRY  KHRONOS_APIENTRY
+#endif
+#define EGLAPIENTRYP EGLAPIENTRY*
+
+/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
+ * are aliases of window-system-dependent types, such as X Display * or
+ * Windows Device Context. They must be defined in platform-specific
+ * code below. The EGL-prefixed versions of Native*Type are the same
+ * types, renamed in EGL 1.3 so all types in the API start with "EGL".
+ *
+ * Khronos STRONGLY RECOMMENDS that you use the default definitions
+ * provided below, since these changes affect both binary and source
+ * portability of applications using EGL running on different EGL
+ * implementations.
+ */
+
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+
+typedef HDC     EGLNativeDisplayType;
+typedef HBITMAP EGLNativePixmapType;
+
+#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) /* Windows Desktop */
+typedef HWND    EGLNativeWindowType;
+#else /* Windows Store */
+#include <inspectable.h>
+typedef IInspectable* EGLNativeWindowType;
+#endif
+
+#elif defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */
+
+typedef int   EGLNativeDisplayType;
+typedef void *EGLNativeWindowType;
+typedef void *EGLNativePixmapType;
+
+#elif defined(__ANDROID__) || defined(ANDROID)
+
+#include <android/native_window.h>
+
+struct egl_native_pixmap_t;
+
+typedef struct ANativeWindow*           EGLNativeWindowType;
+typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
+typedef void*                           EGLNativeDisplayType;
+
+#elif defined(__unix__)
+
+/* X11 (tentative)  */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap   EGLNativePixmapType;
+typedef Window   EGLNativeWindowType;
+
+#elif defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) )
+
+// TODO(jmadill): native implementation for OSX
+
+typedef void *EGLNativeDisplayType;
+typedef void *EGLNativePixmapType;
+typedef void *EGLNativeWindowType;
+
+#else
+#error "Platform not recognized"
+#endif
+
+/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
+typedef EGLNativeDisplayType NativeDisplayType;
+typedef EGLNativePixmapType  NativePixmapType;
+typedef EGLNativeWindowType  NativeWindowType;
+
+
+/* Define EGLint. This must be a signed integral type large enough to contain
+ * all legal attribute names and values passed into and out of EGL, whether
+ * their type is boolean, bitmask, enumerant (symbolic constant), integer,
+ * handle, or other.  While in general a 32-bit integer will suffice, if
+ * handles are 64 bit types, then EGLint should be defined as a signed 64-bit
+ * integer type.
+ */
+typedef khronos_int32_t EGLint;
+
+#endif /* __eglplatform_h */

+ 620 - 0
modules/gles20/angle/include/GLES2/gl2.h

@@ -0,0 +1,620 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 20555 $ on $Date:: 2013-02-12 14:32:47 -0800 #$ */
+
+#include <GLES2/gl2platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void             GLvoid;
+typedef char             GLchar;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef khronos_int8_t   GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef khronos_uint8_t  GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef khronos_float_t  GLfloat;
+typedef khronos_float_t  GLclampf;
+typedef khronos_int32_t  GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t  GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0                 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+
+/* Boolean */
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+
+/* BeginMode */
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+
+/* BlendingFactorSrc */
+/*      GL_ZERO */
+/*      GL_ONE */
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+/*      GL_SRC_ALPHA */
+/*      GL_ONE_MINUS_SRC_ALPHA */
+/*      GL_DST_ALPHA */
+/*      GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009    /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+
+/* CullFaceMode */
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+
+/* DepthFunction */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+
+/* FrontFaceDirection */
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+/*      GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+/*      GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+
+/* GetTextureParameter */
+/*      GL_TEXTURE_MAG_FILTER */
+/*      GL_TEXTURE_MIN_FILTER */
+/*      GL_TEXTURE_WRAP_S */
+/*      GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT            0x8192
+
+/* DataType */
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+
+/* PixelType */
+/*      GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER                  0x8B30
+#define GL_VERTEX_SHADER                    0x8B31
+#define GL_MAX_VERTEX_ATTRIBS               0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
+#define GL_MAX_VARYING_VECTORS              0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS   0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS          0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
+#define GL_SHADER_TYPE                      0x8B4F
+#define GL_DELETE_STATUS                    0x8B80
+#define GL_LINK_STATUS                      0x8B82
+#define GL_VALIDATE_STATUS                  0x8B83
+#define GL_ATTACHED_SHADERS                 0x8B85
+#define GL_ACTIVE_UNIFORMS                  0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH        0x8B87
+#define GL_ACTIVE_ATTRIBUTES                0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH      0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION         0x8B8C
+#define GL_CURRENT_PROGRAM                  0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+
+/* StencilOp */
+/*      GL_ZERO */
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+
+/* StringName */
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+
+/* TextureMinFilter */
+/*      GL_NEAREST */
+/*      GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+
+/* TextureTarget */
+/*      GL_TEXTURE_2D */
+#define GL_TEXTURE                        0x1702
+
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED        0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE           0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE         0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE           0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED     0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER        0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE   0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX8                 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE           0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME           0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+
+#define GL_NONE                           0
+
+#define GL_FRAMEBUFFER_COMPLETE                      0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT         0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS         0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED                   0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void         GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void         GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void         GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void         GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void         GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void         GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void         GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void         GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void         GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void         GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+GL_APICALL GLenum       GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void         GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void         GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void         GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void         GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void         GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void         GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void         GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void         GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint       GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint       GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void         GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void         GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void         GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void         GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void         GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void         GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void         GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glFinish (void);
+GL_APICALL void         GL_APIENTRY glFlush (void);
+GL_APICALL void         GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void         GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void         GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void         GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL GLint        GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void         GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum       GL_APIENTRY glGetError (void);
+GL_APICALL void         GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void         GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void         GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void         GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void         GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL GLint        GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
+GL_APICALL void         GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean    GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean    GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean    GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean    GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void         GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void         GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void         GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void         GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void         GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void         GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
+GL_APICALL void         GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void         GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void         GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void         GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void         GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void         GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void         GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void         GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void         GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+GL_APICALL void         GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */

+ 2013 - 0
modules/gles20/angle/include/GLES2/gl2ext.h

@@ -0,0 +1,2013 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_
+
+/* $Revision: 20795 $ on $Date:: 2013-03-07 01:01:58 -0800 #$ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+#ifndef GL_APIENTRYP
+#   define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/*------------------------------------------------------------------------*
+ * OES extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_ETC1_RGB8_OES                                        0x8D64
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_PALETTE4_RGB8_OES                                    0x8B90
+#define GL_PALETTE4_RGBA8_OES                                   0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES                                0x8B92
+#define GL_PALETTE4_RGBA4_OES                                   0x8B93
+#define GL_PALETTE4_RGB5_A1_OES                                 0x8B94
+#define GL_PALETTE8_RGB8_OES                                    0x8B95
+#define GL_PALETTE8_RGBA8_OES                                   0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES                                0x8B97
+#define GL_PALETTE8_RGBA4_OES                                   0x8B98
+#define GL_PALETTE8_RGB5_A1_OES                                 0x8B99
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_DEPTH_COMPONENT24_OES                                0x81A6
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_DEPTH_COMPONENT32_OES                                0x81A7
+#endif
+
+/* GL_OES_depth_texture */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+/* GLeglImageOES defined in GL_OES_EGL_image already. */
+#define GL_TEXTURE_EXTERNAL_OES                                 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES                                 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES                         0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES                     0x8D68
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_UNSIGNED_INT                                         0x1405
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_PROGRAM_BINARY_LENGTH_OES                            0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES                       0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES                           0x87FF
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_WRITE_ONLY_OES                                       0x88B9
+#define GL_BUFFER_ACCESS_OES                                    0x88BB
+#define GL_BUFFER_MAPPED_OES                                    0x88BC
+#define GL_BUFFER_MAP_POINTER_OES                               0x88BD
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_DEPTH_STENCIL_OES                                    0x84F9
+#define GL_UNSIGNED_INT_24_8_OES                                0x84FA
+#define GL_DEPTH24_STENCIL8_OES                                 0x88F0
+#endif
+
+/* GL_OES_required_internalformat */
+#ifndef GL_OES_required_internalformat 
+#define GL_ALPHA8_OES                                           0x803C
+#define GL_DEPTH_COMPONENT16_OES                                0x81A5
+/* reuse GL_DEPTH_COMPONENT24_OES */                            
+/* reuse GL_DEPTH24_STENCIL8_OES */                             
+/* reuse GL_DEPTH_COMPONENT32_OES */                            
+#define GL_LUMINANCE4_ALPHA4_OES                                0x8043
+#define GL_LUMINANCE8_ALPHA8_OES                                0x8045
+#define GL_LUMINANCE8_OES                                       0x8040
+#define GL_RGBA4_OES                                            0x8056
+#define GL_RGB5_A1_OES                                          0x8057
+#define GL_RGB565_OES                                           0x8D62
+/* reuse GL_RGB8_OES */                              
+/* reuse GL_RGBA8_OES */  
+/* reuse GL_RGB10_EXT */
+/* reuse GL_RGB10_A2_EXT */
+#endif 
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_RGB8_OES                                             0x8051
+#define GL_RGBA8_OES                                            0x8058
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES                  0x8B8B
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_STENCIL_INDEX1_OES                                   0x8D46
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_STENCIL_INDEX4_OES                                   0x8D47
+#endif
+
+#ifndef GL_OES_surfaceless_context
+#define GL_FRAMEBUFFER_UNDEFINED_OES                            0x8219
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_TEXTURE_WRAP_R_OES                                   0x8072
+#define GL_TEXTURE_3D_OES                                       0x806F
+#define GL_TEXTURE_BINDING_3D_OES                               0x806A
+#define GL_MAX_3D_TEXTURE_SIZE_OES                              0x8073
+#define GL_SAMPLER_3D_OES                                       0x8B5F
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES        0x8CD4
+#endif
+
+/* GL_OES_texture_float */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_HALF_FLOAT_OES                                       0x8D61
+#endif
+
+/* GL_OES_texture_half_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_npot */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_OES                             0x85B5
+#endif
+
+/* GL_OES_vertex_half_float */
+/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_UNSIGNED_INT_10_10_10_2_OES                          0x8DF6
+#define GL_INT_10_10_10_2_OES                                   0x8DF7
+#endif
+
+/*------------------------------------------------------------------------*
+ * KHR extension tokens
+ *------------------------------------------------------------------------*/
+
+#ifndef GL_KHR_debug
+typedef void (GL_APIENTRYP GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS                             0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH                     0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION                              0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM                            0x8245
+#define GL_DEBUG_SOURCE_API                                     0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM                           0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER                         0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY                             0x8249
+#define GL_DEBUG_SOURCE_APPLICATION                             0x824A
+#define GL_DEBUG_SOURCE_OTHER                                   0x824B
+#define GL_DEBUG_TYPE_ERROR                                     0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR                       0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR                        0x824E
+#define GL_DEBUG_TYPE_PORTABILITY                               0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE                               0x8250
+#define GL_DEBUG_TYPE_OTHER                                     0x8251
+#define GL_DEBUG_TYPE_MARKER                                    0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP                                0x8269
+#define GL_DEBUG_TYPE_POP_GROUP                                 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION                          0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH                          0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH                              0x826D
+#define GL_BUFFER                                               0x82E0
+#define GL_SHADER                                               0x82E1
+#define GL_PROGRAM                                              0x82E2
+#define GL_QUERY                                                0x82E3
+/* PROGRAM_PIPELINE only in GL */                               
+#define GL_SAMPLER                                              0x82E6
+/* DISPLAY_LIST only in GL */                                   
+#define GL_MAX_LABEL_LENGTH                                     0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH                             0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES                            0x9144
+#define GL_DEBUG_LOGGED_MESSAGES                                0x9145
+#define GL_DEBUG_SEVERITY_HIGH                                  0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM                                0x9147
+#define GL_DEBUG_SEVERITY_LOW                                   0x9148
+#define GL_DEBUG_OUTPUT                                         0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT                               0x00000002
+#define GL_STACK_OVERFLOW                                       0x0503
+#define GL_STACK_UNDERFLOW                                      0x0504
+#endif
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR                         0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR                         0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR                         0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR                         0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR                         0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR                         0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR                         0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR                         0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR                        0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR                        0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR                        0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR                       0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR                       0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR                       0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR                 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR                 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR                 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR                 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR                 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR                 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR                 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR                 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR                0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR                0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR                0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR               0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR               0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR               0x93DD
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_3DC_X_AMD                                            0x87F9
+#define GL_3DC_XY_AMD                                           0x87FA
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_ATC_RGB_AMD                                          0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      0x87EE
+#endif
+
+/* GL_AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_COUNTER_TYPE_AMD                                     0x8BC0
+#define GL_COUNTER_RANGE_AMD                                    0x8BC1
+#define GL_UNSIGNED_INT64_AMD                                   0x8BC2
+#define GL_PERCENTAGE_AMD                                       0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD                         0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD                              0x8BC5
+#define GL_PERFMON_RESULT_AMD                                   0x8BC6
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_Z400_BINARY_AMD                                      0x8740
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_depth_texture */
+#ifndef GL_ANGLE_depth_texture
+#define GL_DEPTH_COMPONENT                                      0x1902
+#define GL_DEPTH_STENCIL_OES                                    0x84F9
+#define GL_UNSIGNED_SHORT                                       0x1403
+#define GL_UNSIGNED_INT                                         0x1405
+#define GL_UNSIGNED_INT_24_8_OES                                0x84FA
+#define GL_DEPTH_COMPONENT16                                    0x81A5
+#define GL_DEPTH_COMPONENT32_OES                                0x81A7
+#define GL_DEPTH24_STENCIL8_OES                                 0x88F0
+#endif
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_ANGLE                               0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE                               0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE                       0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE                       0x8CAA
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_ANGLE                           0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE             0x8D56
+#define GL_MAX_SAMPLES_ANGLE                                    0x8D57
+#endif
+
+/* GL_ANGLE_instanced_arrays */
+#ifndef GL_ANGLE_instanced_arrays 
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE                    0x88FE
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order 
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE                         0x93A4
+#endif
+
+/* GL_ANGLE_program_binary */
+#ifndef GL_ANGLE_program_binary
+#define GL_PROGRAM_BINARY_ANGLE                                 0x93A6
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3 
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE                      0x83F2
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5 
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE                      0x83F3
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage 
+#define GL_TEXTURE_USAGE_ANGLE                                  0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE                         0x93A3
+#endif
+
+/* GL_ANGLE_translated_shader_source */
+#ifndef GL_ANGLE_translated_shader_source 
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE                0x93A0
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_copy_texture_levels */
+/* No new tokens introduced by this extension. */
+    
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_APPLE                           0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE             0x8D56
+#define GL_MAX_SAMPLES_APPLE                                    0x8D57
+#define GL_READ_FRAMEBUFFER_APPLE                               0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE                               0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE                       0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE                       0x8CAA
+#endif
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_RGB_422_APPLE                                        0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE                             0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE                         0x85BB
+#endif
+
+/* GL_APPLE_sync */
+#ifndef GL_APPLE_sync
+
+#ifndef __gl3_h_
+/* These types are defined with reference to <inttypes.h>
+ * in the Apple extension spec, but here we use the Khronos
+ * portable types in khrplatform.h, and assume those types 
+ * are always defined.
+ * If any other extensions using these types are defined, 
+ * the typedefs must move out of this block and be shared.
+ */
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+#endif
+
+#define GL_SYNC_OBJECT_APPLE                                    0x8A53
+#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE                        0x9111
+#define GL_OBJECT_TYPE_APPLE                                    0x9112
+#define GL_SYNC_CONDITION_APPLE                                 0x9113
+#define GL_SYNC_STATUS_APPLE                                    0x9114
+#define GL_SYNC_FLAGS_APPLE                                     0x9115
+#define GL_SYNC_FENCE_APPLE                                     0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE                     0x9117
+#define GL_UNSIGNALED_APPLE                                     0x9118
+#define GL_SIGNALED_APPLE                                       0x9119
+#define GL_ALREADY_SIGNALED_APPLE                               0x911A
+#define GL_TIMEOUT_EXPIRED_APPLE                                0x911B
+#define GL_CONDITION_SATISFIED_APPLE                            0x911C
+#define GL_WAIT_FAILED_APPLE                                    0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE                        0x00000001
+#define GL_TIMEOUT_IGNORED_APPLE                                0xFFFFFFFFFFFFFFFFull
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_BGRA_EXT                                             0x80E1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_TEXTURE_MAX_LEVEL_APPLE                              0x813D
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_program_binary */
+#ifndef GL_ARM_mali_program_binary
+#define GL_MALI_PROGRAM_BINARY_ARM                              0x8F61
+#endif
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_MALI_SHADER_BINARY_ARM                               0x8F60
+#endif
+
+/* GL_ARM_rgba8 */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * EXT extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_MIN_EXT                                              0x8007
+#define GL_MAX_EXT                                              0x8008
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_RGBA16F_EXT                                          0x881A
+#define GL_RGB16F_EXT                                           0x881B
+#define GL_RG16F_EXT                                            0x822F
+#define GL_R16F_EXT                                             0x822D
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT            0x8211
+#define GL_UNSIGNED_NORMALIZED_EXT                              0x8C17
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT                          0x8A4F
+#define GL_PROGRAM_OBJECT_EXT                                   0x8B40
+#define GL_SHADER_OBJECT_EXT                                    0x8B48
+#define GL_BUFFER_OBJECT_EXT                                    0x9151
+#define GL_QUERY_OBJECT_EXT                                     0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT                              0x9154
+#endif
+
+/* GL_EXT_debug_marker */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_COLOR_EXT                                            0x1800
+#define GL_DEPTH_EXT                                            0x1801
+#define GL_STENCIL_EXT                                          0x1802
+#endif
+
+/* GL_EXT_map_buffer_range */
+#ifndef GL_EXT_map_buffer_range
+#define GL_MAP_READ_BIT_EXT                                     0x0001
+#define GL_MAP_WRITE_BIT_EXT                                    0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT                         0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT                        0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT                           0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT                           0x0020
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT           0x8D6C
+/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */ 
+#define GL_RENDERBUFFER_SAMPLES_EXT                             0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT               0x8D56
+#define GL_MAX_SAMPLES_EXT                                      0x8D57
+#endif
+
+/* GL_EXT_multiview_draw_buffers */
+#ifndef GL_EXT_multiview_draw_buffers
+#define GL_COLOR_ATTACHMENT_EXT                                 0x90F0
+#define GL_MULTIVIEW_EXT                                        0x90F1
+#define GL_DRAW_BUFFER_EXT                                      0x0C01
+#define GL_READ_BUFFER_EXT                                      0x0C02
+#define GL_MAX_MULTIVIEW_BUFFERS_EXT                            0x90F2
+#endif
+
+/* GL_EXT_multi_draw_arrays */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_ANY_SAMPLES_PASSED_EXT                               0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT                  0x8D6A
+#define GL_CURRENT_QUERY_EXT                                    0x8865
+#define GL_QUERY_RESULT_EXT                                     0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT                           0x8867
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_BGRA_EXT                                             0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT                       0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT                       0x8366
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+/* reuse GL_NO_ERROR */
+#define GL_GUILTY_CONTEXT_RESET_EXT                             0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT                           0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT                            0x8255
+#define GL_CONTEXT_ROBUST_ACCESS_EXT                            0x90F3
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT                      0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_EXT                            0x8252
+#define GL_NO_RESET_NOTIFICATION_EXT                            0x8261
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_VERTEX_SHADER_BIT_EXT                                0x00000001
+#define GL_FRAGMENT_SHADER_BIT_EXT                              0x00000002
+#define GL_ALL_SHADER_BITS_EXT                                  0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE_EXT                                0x8258
+#define GL_ACTIVE_PROGRAM_EXT                                   0x8259
+#define GL_PROGRAM_PIPELINE_BINDING_EXT                         0x825A
+#endif
+
+/* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT                 0x8A52
+#endif
+
+/* GL_EXT_shader_texture_lod */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_TEXTURE_COMPARE_MODE_EXT                             0x884C
+#define GL_TEXTURE_COMPARE_FUNC_EXT                             0x884D
+#define GL_COMPARE_REF_TO_TEXTURE_EXT                           0x884E
+#define GL_SAMPLER_2D_SHADOW_EXT                                0x8B62
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_SRGB_EXT                                             0x8C40
+#define GL_SRGB_ALPHA_EXT                                       0x8C42
+#define GL_SRGB8_ALPHA8_EXT                                     0x8C43
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT            0x8210
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT                         0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT                        0x83F1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT                           0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       0x84FF
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA_EXT                                             0x80E1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_RED_EXT                                              0x1903
+#define GL_RG_EXT                                               0x8227
+#define GL_R8_EXT                                               0x8229
+#define GL_RG8_EXT                                              0x822B
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT                         0x912F
+#define GL_ALPHA8_EXT                                           0x803C  
+#define GL_LUMINANCE8_EXT                                       0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT                                0x8045
+#define GL_RGBA32F_EXT                                          0x8814  
+#define GL_RGB32F_EXT                                           0x8815
+#define GL_ALPHA32F_EXT                                         0x8816
+#define GL_LUMINANCE32F_EXT                                     0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT                               0x8819
+/* reuse GL_RGBA16F_EXT */
+/* reuse GL_RGB16F_EXT */
+#define GL_ALPHA16F_EXT                                         0x881C
+#define GL_LUMINANCE16F_EXT                                     0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT                               0x881F
+#define GL_RGB10_A2_EXT                                         0x8059  
+#define GL_RGB10_EXT                                            0x8052
+#define GL_BGRA8_EXT                                            0x93A1
+#define GL_R8_EXT                                               0x8229
+#define GL_RG8_EXT                                              0x822B
+#define GL_R32F_EXT                                             0x822E  
+#define GL_RG32F_EXT                                            0x8230
+#define GL_R16F_EXT                                             0x822D
+#define GL_RG16F_EXT                                            0x822F
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT                      0x8368
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_UNPACK_ROW_LENGTH_EXT                                0x0CF2
+#define GL_UNPACK_SKIP_ROWS_EXT                                 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS_EXT                               0x0CF4
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_SHADER_BINARY_DMP                                    0x9250
+#endif
+
+/*------------------------------------------------------------------------*
+ * FJ extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_GCCSO_SHADER_BINARY_F                                0x9260
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_SGX_PROGRAM_BINARY_IMG                               0x9130
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_BGRA_IMG                                             0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG                       0x8365
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_SGX_BINARY_IMG                                       0x8C0A
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG                      0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG                     0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG                     0x8C03
+#endif
+
+/* GL_IMG_texture_compression_pvrtc2 */
+#ifndef GL_IMG_texture_compression_pvrtc2
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG                     0x9137
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG                     0x9138
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_RENDERBUFFER_SAMPLES_IMG                             0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG               0x9134
+#define GL_MAX_SAMPLES_IMG                                      0x9135
+#define GL_TEXTURE_SAMPLES_IMG                                  0x9136
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_COVERAGE_COMPONENT_NV                                0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV                               0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV                               0x8ED2
+#define GL_COVERAGE_BUFFERS_NV                                  0x8ED3
+#define GL_COVERAGE_SAMPLES_NV                                  0x8ED4
+#define GL_COVERAGE_ALL_FRAGMENTS_NV                            0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV                           0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV                                0x8ED7
+#define GL_COVERAGE_BUFFER_BIT_NV                               0x8000
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV                       0x8E2C
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_NV                                  0x8824
+#define GL_DRAW_BUFFER0_NV                                      0x8825
+#define GL_DRAW_BUFFER1_NV                                      0x8826
+#define GL_DRAW_BUFFER2_NV                                      0x8827
+#define GL_DRAW_BUFFER3_NV                                      0x8828
+#define GL_DRAW_BUFFER4_NV                                      0x8829
+#define GL_DRAW_BUFFER5_NV                                      0x882A
+#define GL_DRAW_BUFFER6_NV                                      0x882B
+#define GL_DRAW_BUFFER7_NV                                      0x882C
+#define GL_DRAW_BUFFER8_NV                                      0x882D
+#define GL_DRAW_BUFFER9_NV                                      0x882E
+#define GL_DRAW_BUFFER10_NV                                     0x882F
+#define GL_DRAW_BUFFER11_NV                                     0x8830
+#define GL_DRAW_BUFFER12_NV                                     0x8831
+#define GL_DRAW_BUFFER13_NV                                     0x8832
+#define GL_DRAW_BUFFER14_NV                                     0x8833
+#define GL_DRAW_BUFFER15_NV                                     0x8834
+#define GL_COLOR_ATTACHMENT0_NV                                 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV                                 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV                                 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV                                 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV                                 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV                                 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV                                 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV                                 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV                                 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV                                 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV                                0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV                                0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV                                0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV                                0x8CED
+#define GL_COLOR_ATTACHMENT14_NV                                0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV                                0x8CEF
+#endif
+
+/* GL_EXT_draw_buffers */
+#ifndef GL_EXT_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_EXT                                  0x8824
+#define GL_DRAW_BUFFER0_EXT                                      0x8825
+#define GL_DRAW_BUFFER1_EXT                                      0x8826
+#define GL_DRAW_BUFFER2_EXT                                      0x8827
+#define GL_DRAW_BUFFER3_EXT                                      0x8828
+#define GL_DRAW_BUFFER4_EXT                                      0x8829
+#define GL_DRAW_BUFFER5_EXT                                      0x882A
+#define GL_DRAW_BUFFER6_EXT                                      0x882B
+#define GL_DRAW_BUFFER7_EXT                                      0x882C
+#define GL_DRAW_BUFFER8_EXT                                      0x882D
+#define GL_DRAW_BUFFER9_EXT                                      0x882E
+#define GL_DRAW_BUFFER10_EXT                                     0x882F
+#define GL_DRAW_BUFFER11_EXT                                     0x8830
+#define GL_DRAW_BUFFER12_EXT                                     0x8831
+#define GL_DRAW_BUFFER13_EXT                                     0x8832
+#define GL_DRAW_BUFFER14_EXT                                     0x8833
+#define GL_DRAW_BUFFER15_EXT                                     0x8834
+#define GL_COLOR_ATTACHMENT0_EXT                                 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT                                 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT                                 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT                                 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT                                 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT                                 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT                                 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT                                 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT                                 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT                                 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT                                0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT                                0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT                                0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT                                0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT                                0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT                                0x8CEF
+#define GL_MAX_COLOR_ATTACHMENTS_EXT                             0x8CDF
+#endif
+
+/* GL_NV_draw_instanced */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_MAX_COLOR_ATTACHMENTS_NV                             0x8CDF
+/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV                                     0x84F2
+#define GL_FENCE_STATUS_NV                                      0x84F3
+#define GL_FENCE_CONDITION_NV                                   0x84F4
+#endif
+
+/* GL_NV_framebuffer_blit */
+#ifndef GL_NV_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_NV                                  0x8CA8
+#define GL_DRAW_FRAMEBUFFER_NV                                  0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_NV                          0x8CA6 
+#define GL_READ_FRAMEBUFFER_BINDING_NV                          0x8CAA
+#endif
+
+/* GL_NV_framebuffer_multisample */
+#ifndef GL_NV_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_NV                              0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV                0x8D56
+#define GL_MAX_SAMPLES_NV                                       0x8D57
+#endif
+
+/* GL_NV_generate_mipmap_sRGB */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_instanced_arrays */
+#ifndef GL_NV_instanced_arrays
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV                       0x88FE
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_READ_BUFFER_NV                                       0x0C02
+#endif
+
+/* GL_NV_read_buffer_front */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_shadow_samplers_array */
+#ifndef GL_NV_shadow_samplers_array
+#define GL_SAMPLER_2D_ARRAY_SHADOW_NV                           0x8DC4
+#endif                                             
+                                                   
+/* GL_NV_shadow_samplers_cube */
+#ifndef GL_NV_shadow_samplers_cube                 
+#define GL_SAMPLER_CUBE_SHADOW_NV                               0x8DC5
+#endif
+
+/* GL_NV_sRGB_formats */
+#ifndef GL_NV_sRGB_formats
+#define GL_SLUMINANCE_NV                                        0x8C46
+#define GL_SLUMINANCE_ALPHA_NV                                  0x8C44
+#define GL_SRGB8_NV                                             0x8C41
+#define GL_SLUMINANCE8_NV                                       0x8C47
+#define GL_SLUMINANCE8_ALPHA8_NV                                0x8C45
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV                         0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV                   0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV                   0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV                   0x8C4F
+#define GL_ETC1_SRGB8_NV                                        0x88EE
+#endif
+
+/* GL_NV_texture_border_clamp */
+#ifndef GL_NV_texture_border_clamp
+#define GL_TEXTURE_BORDER_COLOR_NV                              0x1004
+#define GL_CLAMP_TO_BORDER_NV                                   0x812D
+#endif
+
+/* GL_NV_texture_compression_s3tc_update */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_texture_npot_2D_mipmap */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_ALPHA_TEST_QCOM                                      0x0BC0
+#define GL_ALPHA_TEST_FUNC_QCOM                                 0x0BC1
+#define GL_ALPHA_TEST_REF_QCOM                                  0x0BC2
+#endif
+
+/* GL_QCOM_binning_control */
+#ifndef GL_QCOM_binning_control
+#define GL_BINNING_CONTROL_HINT_QCOM                            0x8FB0
+#define GL_CPU_OPTIMIZED_QCOM                                   0x8FB1
+#define GL_GPU_OPTIMIZED_QCOM                                   0x8FB2
+#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM                    0x8FB3
+#endif
+
+/* GL_QCOM_driver_control */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_TEXTURE_WIDTH_QCOM                                   0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM                                  0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM                                   0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM                         0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM                                  0x8BD6
+#define GL_TEXTURE_TYPE_QCOM                                    0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM                             0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM                              0x8BD9
+#define GL_TEXTURE_TARGET_QCOM                                  0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM                            0x8BDB
+#define GL_STATE_RESTORE                                        0x8BDC
+#endif
+
+/* GL_QCOM_extended_get2 */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_PERFMON_GLOBAL_MODE_QCOM                             0x8FA0
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_WRITEONLY_RENDERING_QCOM                             0x8823
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_COLOR_BUFFER_BIT0_QCOM                               0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM                               0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM                               0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM                               0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM                               0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM                               0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM                               0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM                               0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM                               0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM                               0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM                               0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM                               0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM                               0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM                               0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM                               0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM                               0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM                             0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM                             0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM                             0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM                             0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM                             0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM                             0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM                             0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM                             0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM                         0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM                         0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM                         0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM                         0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM                         0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM                         0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM                         0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM                         0x80000000
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_SHADER_BINARY_VIV                                    0x8FC4
+#endif
+
+/*------------------------------------------------------------------------*
+ * End of extension tokens, start of corresponding extension functions
+ *------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*
+ * OES extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_OES_depth24 1
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_OES_depth32 1
+#endif
+
+/* GL_OES_depth_texture */
+#ifndef GL_OES_depth_texture
+#define GL_OES_depth_texture 1
+#endif
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+#define GL_OES_EGL_image_external 1
+/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_OES_element_index_uint 1
+#endif
+
+/* GL_OES_fbo_render_mipmap */
+#ifndef GL_OES_fbo_render_mipmap
+#define GL_OES_fbo_render_mipmap 1
+#endif
+
+/* GL_OES_fragment_precision_high */
+#ifndef GL_OES_fragment_precision_high
+#define GL_OES_fragment_precision_high 1
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_OES_get_program_binary 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_OES_mapbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid** params);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid** params);
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_OES_packed_depth_stencil 1
+#endif
+
+/* GL_OES_required_internalformat */
+#ifndef GL_OES_required_internalformat
+#define GL_OES_required_internalformat 1
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_OES_rgb8_rgba8 1
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_OES_standard_derivatives 1
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_OES_stencil1 1
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_OES_stencil4 1
+#endif
+
+#ifndef GL_OES_surfaceless_context
+#define GL_OES_surfaceless_context 1
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_OES_texture_3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+
+/* GL_OES_texture_float */
+#ifndef GL_OES_texture_float
+#define GL_OES_texture_float 1
+#endif
+
+/* GL_OES_texture_float_linear */
+#ifndef GL_OES_texture_float_linear
+#define GL_OES_texture_float_linear 1
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_OES_texture_half_float 1
+#endif
+
+/* GL_OES_texture_half_float_linear */
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif
+
+/* GL_OES_texture_npot */
+#ifndef GL_OES_texture_npot
+#define GL_OES_texture_npot 1
+#endif
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_OES_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
+#endif
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+#endif
+
+/* GL_OES_vertex_half_float */
+#ifndef GL_OES_vertex_half_float
+#define GL_OES_vertex_half_float 1
+#endif
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_OES_vertex_type_10_10_10_2 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * KHR extension functions
+ *------------------------------------------------------------------------*/
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GL_APICALL void GL_APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GL_APICALL void GL_APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GL_APICALL void GL_APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GL_APICALL void GL_APIENTRY glPopDebugGroup (void);
+GL_APICALL void GL_APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glGetPointerv (GLenum pname, void **params);
+#endif 
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, void **params);
+#endif
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif
+
+
+/*------------------------------------------------------------------------*
+ * AMD extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_AMD_compressed_3DC_texture 1
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_AMD_compressed_ATC_texture 1
+#endif
+
+/* AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_depth_texture */
+#ifndef GL_ANGLE_depth_texture
+#define GL_ANGLE_depth_texture 1
+#endif
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_ANGLE_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_ANGLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_ANGLE_instanced_arrays 
+#define GL_ANGLE_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order 
+#define GL_ANGLE_pack_reverse_row_order 1
+#endif
+
+/* GL_ANGLE_program_binary */
+#ifndef GL_ANGLE_program_binary
+#define GL_ANGLE_program_binary 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3 
+#define GL_ANGLE_texture_compression_dxt3 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5 
+#define GL_ANGLE_texture_compression_dxt5 1
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage 
+#define GL_ANGLE_texture_usage 1
+#endif
+
+#ifndef GL_ANGLE_translated_shader_source 
+#define GL_ANGLE_translated_shader_source 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_copy_texture_levels */
+#ifndef GL_APPLE_copy_texture_levels
+#define GL_APPLE_copy_texture_levels 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#endif
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_APPLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+#endif
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#endif
+
+/* GL_APPLE_sync */
+#ifndef GL_APPLE_sync
+#define GL_APPLE_sync 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_APPLE_texture_format_BGRA8888 1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_APPLE_texture_max_level 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_program_binary */
+#ifndef GL_ARM_mali_program_binary
+#define GL_ARM_mali_program_binary 1
+#endif
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_ARM_mali_shader_binary 1
+#endif
+
+/* GL_ARM_rgba8 */
+#ifndef GL_ARM_rgba8
+#define GL_ARM_rgba8 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * EXT extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_EXT_color_buffer_half_float 1
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_EXT_debug_label 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+
+/* GL_EXT_debug_marker */
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void);
+#endif
+typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_EXT_discard_framebuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+
+/* GL_EXT_map_buffer_range */
+#ifndef GL_EXT_map_buffer_range
+#define GL_EXT_map_buffer_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_EXT_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/* GL_EXT_multiview_draw_buffers */
+#ifndef GL_EXT_multiview_draw_buffers
+#define GL_EXT_multiview_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index);
+GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices);
+GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data);
+#endif
+typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum, const GLint *, const GLsizei *, GLsizei);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_EXT_occlusion_query_boolean 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params);
+#endif
+typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_EXT_read_format_bgra 1
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+#define GL_EXT_robustness 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, float *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, float *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+
+/* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_EXT_shader_framebuffer_fetch 1
+#endif
+
+/* GL_EXT_shader_texture_lod */
+#ifndef GL_EXT_shader_texture_lod
+#define GL_EXT_shader_texture_lod 1
+#endif
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_EXT_shadow_samplers 1
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_EXT_sRGB 1
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_EXT_texture_rg 1
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_EXT_texture_storage 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_EXT_unpack_subimage 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_DMP_shader_binary 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * FJ extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_FJ_shader_binary_GCCSO 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_IMG_program_binary 1
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_IMG_shader_binary 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc2 */
+#ifndef GL_IMG_texture_compression_pvrtc2
+#define GL_IMG_texture_compression_pvrtc2 1
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_IMG_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_NV_coverage_sample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask);
+GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_NV_depth_nonlinear 1
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_NV_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+/* GL_EXT_draw_buffers */
+#ifndef GL_EXT_draw_buffers
+#define GL_EXT_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+/* GL_NV_draw_instanced */
+#ifndef GL_NV_draw_instanced
+#define GL_NV_draw_instanced 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+typedef void (GL_APIENTRYP PFNDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_NV_fbo_color_attachments 1
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei, GLuint *);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint, GLenum);
+#endif
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+/* GL_NV_framebuffer_blit */
+#ifndef GL_NV_framebuffer_blit
+#define GL_NV_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferNV (int srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (GL_APIENTRYP PFNBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+/* GL_NV_framebuffer_multisample */
+#ifndef GL_NV_framebuffer_multisample
+#define GL_NV_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (GL_APIENTRYP PFNRENDERBUFFERSTORAGEMULTISAMPLENVPROC) ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+/* GL_NV_generate_mipmap_sRGB */
+#ifndef GL_NV_generate_mipmap_sRGB
+#define GL_NV_generate_mipmap_sRGB 1
+#endif
+
+/* GL_NV_instanced_arrays */
+#ifndef GL_NV_instanced_arrays
+#define GL_NV_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor);
+#endif
+typedef void (GL_APIENTRYP PFNVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor);
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_NV_read_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode);
+#endif
+typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode);
+#endif
+
+/* GL_NV_read_buffer_front */
+#ifndef GL_NV_read_buffer_front
+#define GL_NV_read_buffer_front 1
+#endif
+
+/* GL_NV_read_depth */
+#ifndef GL_NV_read_depth
+#define GL_NV_read_depth 1
+#endif
+
+/* GL_NV_read_depth_stencil */
+#ifndef GL_NV_read_depth_stencil
+#define GL_NV_read_depth_stencil 1
+#endif
+
+/* GL_NV_read_stencil */
+#ifndef GL_NV_read_stencil
+#define GL_NV_read_stencil 1
+#endif
+
+/* GL_NV_shadow_samplers_array */
+#ifndef GL_NV_shadow_samplers_array
+#define GL_NV_shadow_samplers_array 1
+#endif
+
+/* GL_NV_shadow_samplers_cube */
+#ifndef GL_NV_shadow_samplers_cube
+#define GL_NV_shadow_samplers_cube 1
+#endif
+
+/* GL_NV_sRGB_formats */
+#ifndef GL_NV_sRGB_formats
+#define GL_NV_sRGB_formats 1
+#endif
+
+/* GL_NV_texture_border_clamp */
+#ifndef GL_NV_texture_border_clamp
+#define GL_NV_texture_border_clamp 1
+#endif
+
+/* GL_NV_texture_compression_s3tc_update */
+#ifndef GL_NV_texture_compression_s3tc_update
+#define GL_NV_texture_compression_s3tc_update 1
+#endif
+
+/* GL_NV_texture_npot_2D_mipmap */
+#ifndef GL_NV_texture_npot_2D_mipmap
+#define GL_NV_texture_npot_2D_mipmap 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_QCOM_alpha_test 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref);
+#endif
+typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
+#endif
+
+/* GL_QCOM_binning_control */
+#ifndef GL_QCOM_binning_control
+#define GL_QCOM_binning_control 1
+#endif
+
+/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
+GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#endif
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_QCOM_extended_get 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
+GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params);
+#endif
+
+/* GL_QCOM_extended_get2 */
+#ifndef GL_QCOM_extended_get2
+#define GL_QCOM_extended_get2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
+GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_QCOM_perfmon_global_mode 1
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_QCOM_tiled_rendering 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
+#endif
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_VIV_shader_binary 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2ext_h_ */

+ 30 - 0
modules/gles20/angle/include/GLES2/gl2platform.h

@@ -0,0 +1,30 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X  gl2.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL  KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl2platform_h_ */

+ 282 - 0
modules/gles20/angle/include/KHR/khrplatform.h

@@ -0,0 +1,282 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by sending them to the public Khronos Bugzilla
+ * (http://khronos.org/bugzilla) by filing a bug against product
+ * "Khronos (general)" component "Registry".
+ *
+ * A predefined template which fills in some of the bug fields can be
+ * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+ * must create a Bugzilla login first.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ *    http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ *        #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ *    khronos_int8_t              signed   8  bit
+ *    khronos_uint8_t             unsigned 8  bit
+ *    khronos_int16_t             signed   16 bit
+ *    khronos_uint16_t            unsigned 16 bit
+ *    khronos_int32_t             signed   32 bit
+ *    khronos_uint32_t            unsigned 32 bit
+ *    khronos_int64_t             signed   64 bit
+ *    khronos_uint64_t            unsigned 64 bit
+ *    khronos_intptr_t            signed   same number of bits as a pointer
+ *    khronos_uintptr_t           unsigned same number of bits as a pointer
+ *    khronos_ssize_t             signed   size
+ *    khronos_usize_t             unsigned size
+ *    khronos_float_t             signed   32 bit floating point
+ *    khronos_time_ns_t           unsigned 64 bit time in nanoseconds
+ *    khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ *                                         nanoseconds
+ *    khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ *    khronos_boolean_enum_t      enumerated boolean type. This should
+ *      only be used as a base type when a client API's boolean type is
+ *      an enum. Client APIs which use an integer or other type for
+ *      booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ *    KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ *    KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ *    KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ *    KHRONOS_APICALL
+ *    KHRONOS_APIENTRY
+ *    KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ *      KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ *                                  int arg1,
+ *                                  int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+#   define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+#   define KHRONOS_APICALL IMPORT_C
+#else
+#   define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function  and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+    /* Win32 but not WinCE */
+#   define KHRONOS_APIENTRY __stdcall
+#else
+#   define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32                 khronos_int32_t;
+typedef unsigned __int32        khronos_uint32_t;
+typedef __int64                 khronos_int64_t;
+typedef unsigned __int64        khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int                     khronos_int32_t;
+typedef unsigned int            khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int                khronos_int64_t;
+typedef unsigned long int       khronos_uint64_t;
+#else
+typedef long long int           khronos_int64_t;
+typedef unsigned long long int  khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int                     khronos_int32_t;
+typedef unsigned int            khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64   0
+#define KHRONOS_SUPPORT_FLOAT   0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed   char          khronos_int8_t;
+typedef unsigned char          khronos_uint8_t;
+typedef signed   short int     khronos_int16_t;
+typedef unsigned short int     khronos_uint16_t;
+
+/*
+ * Types that differ between LLP64 and LP64 architectures - in LLP64, 
+ * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+ * to be the only LLP64 architecture in current use.
+ */
+#ifdef _WIN64
+typedef signed   long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+typedef signed   long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed   long  int     khronos_intptr_t;
+typedef unsigned long  int     khronos_uintptr_t;
+typedef signed   long  int     khronos_ssize_t;
+typedef unsigned long  int     khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef          float         khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time.  Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted).  The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years.  Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t       khronos_utime_nanoseconds_t;
+typedef khronos_int64_t        khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true.  Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+    KHRONOS_FALSE = 0,
+    KHRONOS_TRUE  = 1,
+    KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */

BIN
modules/gles20/angle/lib/libEGL.a


BIN
modules/gles20/angle/lib/libEGL.lib


BIN
modules/gles20/angle/lib/libGLESv2.a


BIN
modules/gles20/angle/lib/libGLESv2.lib


+ 597 - 0
modules/gles20/gles20.monkey2

@@ -0,0 +1,597 @@
+
+Namespace gles20
+
+#Import "<libc.monkey2>"
+
+Using monkey
+
+#If __TARGET__="desktop"
+
+	#If __HOSTOS__="windows"
+	
+		'USE ANGLE!
+		#Import "angle/include/*.h"
+		#Import "<GLES2/gl2.h>"
+
+'		#Import "angle/lib/*.lib"
+'		#Import "<libEGL.lib>"
+'		#Import "<libGLESv2.lib>"
+		
+		'mingw 5.1.0 doesn't like linking lib files! Use 4.9.2!
+		#Import "angle/lib/libEGL.lib"
+		#Import "angle/lib/libGLESv2.lib"
+		
+		#Import "angle/bin/libEGL.dll"
+		#Import "angle/bin/libGLESv2.dll"
+		#Import "angle/bin/d3dcompiler_47.dll"
+		
+		'#Import "native/gles20_windows.c"
+		'#Import "native/gles20_windows.h"
+		'#Import "<libopengl32.a>"
+		
+	#Else If __HOSTOS__="macos"
+	
+		#Import "<OpenGL/gl.h>"
+		#Import "<OpenGL.framework>"
+		
+	#Else If __HOSTOS__="linux"
+	
+		#Import "native/gles20_linux.h"
+		#Import "<libGL.a>"
+		
+	#Endif
+	
+#Else If __TARGET__="emscripten"
+
+	#Import "<GLES2/gl2.h>"	
+	
+#Endif
+
+#rem
+typedef void             GLvoid;
+typedef char             GLchar;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef khronos_int8_t   GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef khronos_uint8_t  GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef khronos_float_t  GLfloat;
+typedef khronos_float_t  GLclampf;
+typedef khronos_int32_t  GLfixed;
+
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t  GLsizeiptr;
+#end
+
+'Not quite right, but less annoying...
+Alias GLvoid:Void
+Alias GLenum:Int
+Alias GLboolean:Bool
+Alias GLbitfield:Int
+Alias GLshort:Short
+Alias GLint:Int
+Alias GLsizei:Int
+Alias GLubyte:UByte
+Alias GLushort:UShort
+Alias GLuint:UInt
+Alias GLfloat:Float
+Alias GLfixed:Int
+Alias GLclampf:Float
+Alias GLintptr:Int
+Alias GLsizeiptr:Int
+
+Extern
+
+Struct GLchar="char"
+End
+
+Struct GLcchar="const char"
+End
+
+'${CONSTS}
+Const GL_ES_VERSION_2_0:Int
+Const GL_DEPTH_BUFFER_BIT:Int
+Const GL_STENCIL_BUFFER_BIT:Int
+Const GL_COLOR_BUFFER_BIT:Int
+Const GL_FALSE:Int
+Const GL_TRUE:Int
+Const GL_POINTS:Int
+Const GL_LINES:Int
+Const GL_LINE_LOOP:Int
+Const GL_LINE_STRIP:Int
+Const GL_TRIANGLES:Int
+Const GL_TRIANGLE_STRIP:Int
+Const GL_TRIANGLE_FAN:Int
+Const GL_ZERO:Int
+Const GL_ONE:Int
+Const GL_SRC_COLOR:Int
+Const GL_ONE_MINUS_SRC_COLOR:Int
+Const GL_SRC_ALPHA:Int
+Const GL_ONE_MINUS_SRC_ALPHA:Int
+Const GL_DST_ALPHA:Int
+Const GL_ONE_MINUS_DST_ALPHA:Int
+Const GL_DST_COLOR:Int
+Const GL_ONE_MINUS_DST_COLOR:Int
+Const GL_SRC_ALPHA_SATURATE:Int
+Const GL_FUNC_ADD:Int
+Const GL_BLEND_EQUATION:Int
+Const GL_BLEND_EQUATION_RGB:Int
+Const GL_BLEND_EQUATION_ALPHA:Int
+Const GL_FUNC_SUBTRACT:Int
+Const GL_FUNC_REVERSE_SUBTRACT:Int
+Const GL_BLEND_DST_RGB:Int
+Const GL_BLEND_SRC_RGB:Int
+Const GL_BLEND_DST_ALPHA:Int
+Const GL_BLEND_SRC_ALPHA:Int
+Const GL_CONSTANT_COLOR:Int
+Const GL_ONE_MINUS_CONSTANT_COLOR:Int
+Const GL_CONSTANT_ALPHA:Int
+Const GL_ONE_MINUS_CONSTANT_ALPHA:Int
+Const GL_BLEND_COLOR:Int
+Const GL_ARRAY_BUFFER:Int
+Const GL_ELEMENT_ARRAY_BUFFER:Int
+Const GL_ARRAY_BUFFER_BINDING:Int
+Const GL_ELEMENT_ARRAY_BUFFER_BINDING:Int
+Const GL_STREAM_DRAW:Int
+Const GL_STATIC_DRAW:Int
+Const GL_DYNAMIC_DRAW:Int
+Const GL_BUFFER_SIZE:Int
+Const GL_BUFFER_USAGE:Int
+Const GL_CURRENT_VERTEX_ATTRIB:Int
+Const GL_FRONT:Int
+Const GL_BACK:Int
+Const GL_FRONT_AND_BACK:Int
+Const GL_TEXTURE_2D:Int
+Const GL_CULL_FACE:Int
+Const GL_BLEND:Int
+Const GL_DITHER:Int
+Const GL_STENCIL_TEST:Int
+Const GL_DEPTH_TEST:Int
+Const GL_SCISSOR_TEST:Int
+Const GL_POLYGON_OFFSET_FILL:Int
+Const GL_SAMPLE_ALPHA_TO_COVERAGE:Int
+Const GL_SAMPLE_COVERAGE:Int
+Const GL_NO_ERROR:Int
+Const GL_INVALID_ENUM:Int
+Const GL_INVALID_VALUE:Int
+Const GL_INVALID_OPERATION:Int
+Const GL_OUT_OF_MEMORY:Int
+Const GL_CW:Int
+Const GL_CCW:Int
+Const GL_LINE_WIDTH:Int
+Const GL_ALIASED_POINT_SIZE_RANGE:Int
+Const GL_ALIASED_LINE_WIDTH_RANGE:Int
+Const GL_CULL_FACE_MODE:Int
+Const GL_FRONT_FACE:Int
+Const GL_DEPTH_RANGE:Int
+Const GL_DEPTH_WRITEMASK:Int
+Const GL_DEPTH_CLEAR_VALUE:Int
+Const GL_DEPTH_FUNC:Int
+Const GL_STENCIL_CLEAR_VALUE:Int
+Const GL_STENCIL_FUNC:Int
+Const GL_STENCIL_FAIL:Int
+Const GL_STENCIL_PASS_DEPTH_FAIL:Int
+Const GL_STENCIL_PASS_DEPTH_PASS:Int
+Const GL_STENCIL_REF:Int
+Const GL_STENCIL_VALUE_MASK:Int
+Const GL_STENCIL_WRITEMASK:Int
+Const GL_STENCIL_BACK_FUNC:Int
+Const GL_STENCIL_BACK_FAIL:Int
+Const GL_STENCIL_BACK_PASS_DEPTH_FAIL:Int
+Const GL_STENCIL_BACK_PASS_DEPTH_PASS:Int
+Const GL_STENCIL_BACK_REF:Int
+Const GL_STENCIL_BACK_VALUE_MASK:Int
+Const GL_STENCIL_BACK_WRITEMASK:Int
+Const GL_VIEWPORT:Int
+Const GL_SCISSOR_BOX:Int
+Const GL_COLOR_CLEAR_VALUE:Int
+Const GL_COLOR_WRITEMASK:Int
+Const GL_UNPACK_ALIGNMENT:Int
+Const GL_PACK_ALIGNMENT:Int
+Const GL_MAX_TEXTURE_SIZE:Int
+Const GL_MAX_VIEWPORT_DIMS:Int
+Const GL_SUBPIXEL_BITS:Int
+Const GL_RED_BITS:Int
+Const GL_GREEN_BITS:Int
+Const GL_BLUE_BITS:Int
+Const GL_ALPHA_BITS:Int
+Const GL_DEPTH_BITS:Int
+Const GL_STENCIL_BITS:Int
+Const GL_POLYGON_OFFSET_UNITS:Int
+Const GL_POLYGON_OFFSET_FACTOR:Int
+Const GL_TEXTURE_BINDING_2D:Int
+Const GL_SAMPLE_BUFFERS:Int
+Const GL_SAMPLES:Int
+Const GL_SAMPLE_COVERAGE_VALUE:Int
+Const GL_SAMPLE_COVERAGE_INVERT:Int
+Const GL_NUM_COMPRESSED_TEXTURE_FORMATS:Int
+Const GL_COMPRESSED_TEXTURE_FORMATS:Int
+Const GL_DONT_CARE:Int
+Const GL_FASTEST:Int
+Const GL_NICEST:Int
+Const GL_GENERATE_MIPMAP_HINT:Int
+Const GL_BYTE:Int
+Const GL_UNSIGNED_BYTE:Int
+Const GL_SHORT:Int
+Const GL_UNSIGNED_SHORT:Int
+Const GL_INT:Int
+Const GL_UNSIGNED_INT:Int
+Const GL_FLOAT:Int
+Const GL_FIXED:Int
+Const GL_DEPTH_COMPONENT:Int
+Const GL_ALPHA:Int
+Const GL_RGB:Int
+Const GL_RGBA:Int
+Const GL_LUMINANCE:Int
+Const GL_LUMINANCE_ALPHA:Int
+Const GL_UNSIGNED_SHORT_4_4_4_4:Int
+Const GL_UNSIGNED_SHORT_5_5_5_1:Int
+Const GL_UNSIGNED_SHORT_5_6_5:Int
+Const GL_FRAGMENT_SHADER:Int
+Const GL_VERTEX_SHADER:Int
+Const GL_MAX_VERTEX_ATTRIBS:Int
+Const GL_MAX_VERTEX_UNIFORM_VECTORS:Int
+Const GL_MAX_VARYING_VECTORS:Int
+Const GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:Int
+Const GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:Int
+Const GL_MAX_TEXTURE_IMAGE_UNITS:Int
+Const GL_MAX_FRAGMENT_UNIFORM_VECTORS:Int
+Const GL_SHADER_TYPE:Int
+Const GL_DELETE_STATUS:Int
+Const GL_LINK_STATUS:Int
+Const GL_VALIDATE_STATUS:Int
+Const GL_ATTACHED_SHADERS:Int
+Const GL_ACTIVE_UNIFORMS:Int
+Const GL_ACTIVE_UNIFORM_MAX_LENGTH:Int
+Const GL_ACTIVE_ATTRIBUTES:Int
+Const GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:Int
+Const GL_SHADING_LANGUAGE_VERSION:Int
+Const GL_CURRENT_PROGRAM:Int
+Const GL_NEVER:Int
+Const GL_LESS:Int
+Const GL_EQUAL:Int
+Const GL_LEQUAL:Int
+Const GL_GREATER:Int
+Const GL_NOTEQUAL:Int
+Const GL_GEQUAL:Int
+Const GL_ALWAYS:Int
+Const GL_KEEP:Int
+Const GL_REPLACE:Int
+Const GL_INCR:Int
+Const GL_DECR:Int
+Const GL_INVERT:Int
+Const GL_INCR_WRAP:Int
+Const GL_DECR_WRAP:Int
+Const GL_VENDOR:Int
+Const GL_RENDERER:Int
+Const GL_VERSION:Int
+Const GL_EXTENSIONS:Int
+Const GL_NEAREST:Int
+Const GL_LINEAR:Int
+Const GL_NEAREST_MIPMAP_NEAREST:Int
+Const GL_LINEAR_MIPMAP_NEAREST:Int
+Const GL_NEAREST_MIPMAP_LINEAR:Int
+Const GL_LINEAR_MIPMAP_LINEAR:Int
+Const GL_TEXTURE_MAG_FILTER:Int
+Const GL_TEXTURE_MIN_FILTER:Int
+Const GL_TEXTURE_WRAP_S:Int
+Const GL_TEXTURE_WRAP_T:Int
+Const GL_TEXTURE:Int
+Const GL_TEXTURE_CUBE_MAP:Int
+Const GL_TEXTURE_BINDING_CUBE_MAP:Int
+Const GL_TEXTURE_CUBE_MAP_POSITIVE_X:Int
+Const GL_TEXTURE_CUBE_MAP_NEGATIVE_X:Int
+Const GL_TEXTURE_CUBE_MAP_POSITIVE_Y:Int
+Const GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:Int
+Const GL_TEXTURE_CUBE_MAP_POSITIVE_Z:Int
+Const GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:Int
+Const GL_MAX_CUBE_MAP_TEXTURE_SIZE:Int
+Const GL_TEXTURE0:Int
+Const GL_TEXTURE1:Int
+Const GL_TEXTURE2:Int
+Const GL_TEXTURE3:Int
+Const GL_TEXTURE4:Int
+Const GL_TEXTURE5:Int
+Const GL_TEXTURE6:Int
+Const GL_TEXTURE7:Int
+Const GL_TEXTURE8:Int
+Const GL_TEXTURE9:Int
+Const GL_TEXTURE10:Int
+Const GL_TEXTURE11:Int
+Const GL_TEXTURE12:Int
+Const GL_TEXTURE13:Int
+Const GL_TEXTURE14:Int
+Const GL_TEXTURE15:Int
+Const GL_TEXTURE16:Int
+Const GL_TEXTURE17:Int
+Const GL_TEXTURE18:Int
+Const GL_TEXTURE19:Int
+Const GL_TEXTURE20:Int
+Const GL_TEXTURE21:Int
+Const GL_TEXTURE22:Int
+Const GL_TEXTURE23:Int
+Const GL_TEXTURE24:Int
+Const GL_TEXTURE25:Int
+Const GL_TEXTURE26:Int
+Const GL_TEXTURE27:Int
+Const GL_TEXTURE28:Int
+Const GL_TEXTURE29:Int
+Const GL_TEXTURE30:Int
+Const GL_TEXTURE31:Int
+Const GL_ACTIVE_TEXTURE:Int
+Const GL_REPEAT:Int
+Const GL_CLAMP_TO_EDGE:Int
+Const GL_MIRRORED_REPEAT:Int
+Const GL_FLOAT_VEC2:Int
+Const GL_FLOAT_VEC3:Int
+Const GL_FLOAT_VEC4:Int
+Const GL_INT_VEC2:Int
+Const GL_INT_VEC3:Int
+Const GL_INT_VEC4:Int
+Const GL_BOOL:Int
+Const GL_BOOL_VEC2:Int
+Const GL_BOOL_VEC3:Int
+Const GL_BOOL_VEC4:Int
+Const GL_FLOAT_MAT2:Int
+Const GL_FLOAT_MAT3:Int
+Const GL_FLOAT_MAT4:Int
+Const GL_SAMPLER_2D:Int
+Const GL_SAMPLER_CUBE:Int
+Const GL_VERTEX_ATTRIB_ARRAY_ENABLED:Int
+Const GL_VERTEX_ATTRIB_ARRAY_SIZE:Int
+Const GL_VERTEX_ATTRIB_ARRAY_STRIDE:Int
+Const GL_VERTEX_ATTRIB_ARRAY_TYPE:Int
+Const GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:Int
+Const GL_VERTEX_ATTRIB_ARRAY_POINTER:Int
+Const GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:Int
+Const GL_IMPLEMENTATION_COLOR_READ_TYPE:Int
+Const GL_IMPLEMENTATION_COLOR_READ_FORMAT:Int
+Const GL_COMPILE_STATUS:Int
+Const GL_INFO_LOG_LENGTH:Int
+Const GL_SHADER_SOURCE_LENGTH:Int
+Const GL_SHADER_COMPILER:Int
+Const GL_SHADER_BINARY_FORMATS:Int
+Const GL_NUM_SHADER_BINARY_FORMATS:Int
+Const GL_LOW_FLOAT:Int
+Const GL_MEDIUM_FLOAT:Int
+Const GL_HIGH_FLOAT:Int
+Const GL_LOW_INT:Int
+Const GL_MEDIUM_INT:Int
+Const GL_HIGH_INT:Int
+Const GL_FRAMEBUFFER:Int
+Const GL_RENDERBUFFER:Int
+Const GL_RGBA4:Int
+Const GL_RGB5_A1:Int
+Const GL_RGB565:Int
+Const GL_DEPTH_COMPONENT16:Int
+Const GL_STENCIL_INDEX:Int
+Const GL_STENCIL_INDEX8:Int
+Const GL_RENDERBUFFER_WIDTH:Int
+Const GL_RENDERBUFFER_HEIGHT:Int
+Const GL_RENDERBUFFER_INTERNAL_FORMAT:Int
+Const GL_RENDERBUFFER_RED_SIZE:Int
+Const GL_RENDERBUFFER_GREEN_SIZE:Int
+Const GL_RENDERBUFFER_BLUE_SIZE:Int
+Const GL_RENDERBUFFER_ALPHA_SIZE:Int
+Const GL_RENDERBUFFER_DEPTH_SIZE:Int
+Const GL_RENDERBUFFER_STENCIL_SIZE:Int
+Const GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:Int
+Const GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:Int
+Const GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:Int
+Const GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:Int
+Const GL_COLOR_ATTACHMENT0:Int
+Const GL_DEPTH_ATTACHMENT:Int
+Const GL_STENCIL_ATTACHMENT:Int
+Const GL_NONE:Int
+Const GL_FRAMEBUFFER_COMPLETE:Int
+Const GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:Int
+Const GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:Int
+Const GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:Int
+Const GL_FRAMEBUFFER_UNSUPPORTED:Int
+Const GL_FRAMEBUFFER_BINDING:Int
+Const GL_RENDERBUFFER_BINDING:Int
+Const GL_MAX_RENDERBUFFER_SIZE:Int
+Const GL_INVALID_FRAMEBUFFER_OPERATION:Int
+'${END}
+
+'${FUNCTIONS}
+Function glActiveTexture:Void(texture_:GLenum)
+Function glAttachShader:Void(program_:GLuint,shader_:GLuint)
+Function glBindAttribLocation:Void(program_:GLuint,index_:GLuint,name_:CString)
+Function glBindBuffer:Void(target_:GLenum,buffer_:GLuint)
+Function glBindFramebuffer:Void(target_:GLenum,framebuffer_:GLuint)
+Function glBindRenderbuffer:Void(target_:GLenum,renderbuffer_:GLuint)
+Function glBindTexture:Void(target_:GLenum,texture_:GLuint)
+Function glBlendColor:Void(red_:GLclampf,green_:GLclampf,blue_:GLclampf,alpha_:GLclampf)
+Function glBlendEquation:Void(mode_:GLenum)
+Function glBlendEquationSeparate:Void(modeRGB_:GLenum,modeAlpha_:GLenum)
+Function glBlendFunc:Void(sfactor_:GLenum,dfactor_:GLenum)
+Function glBlendFuncSeparate:Void(srcRGB_:GLenum,dstRGB_:GLenum,srcAlpha_:GLenum,dstAlpha_:GLenum)
+Function glBufferData:Void(target_:GLenum,size_:GLsizeiptr,data_:GLvoid Ptr,usage_:GLenum)
+Function glBufferSubData:Void(target_:GLenum,offset_:GLintptr,size_:GLsizeiptr,data_:GLvoid Ptr)
+Function glCheckFramebufferStatus:GLenum(target_:GLenum)
+Function glClear:Void(mask_:GLbitfield)
+Function glClearColor:Void(red_:GLclampf,green_:GLclampf,blue_:GLclampf,alpha_:GLclampf)
+Function glClearDepthf:Void(depth_:GLclampf)
+Function glClearStencil:Void(s_:GLint)
+Function glColorMask:Void(red_:GLboolean,green_:GLboolean,blue_:GLboolean,alpha_:GLboolean)
+Function glCompileShader:Void(shader_:GLuint)
+Function glCompressedTexImage2D:Void(target_:GLenum,level_:GLint,internalformat_:GLenum,width_:GLsizei,height_:GLsizei,border_:GLint,imageSize_:GLsizei,data_:GLvoid Ptr)
+Function glCompressedTexSubImage2D:Void(target_:GLenum,level_:GLint,xoffset_:GLint,yoffset_:GLint,width_:GLsizei,height_:GLsizei,format_:GLenum,imageSize_:GLsizei,data_:GLvoid Ptr)
+Function glCopyTexImage2D:Void(target_:GLenum,level_:GLint,internalformat_:GLenum,x_:GLint,y_:GLint,width_:GLsizei,height_:GLsizei,border_:GLint)
+Function glCopyTexSubImage2D:Void(target_:GLenum,level_:GLint,xoffset_:GLint,yoffset_:GLint,x_:GLint,y_:GLint,width_:GLsizei,height_:GLsizei)
+Function glCreateProgram:GLuint()
+Function glCreateShader:GLuint(type_:GLenum)
+Function glCullFace:Void(mode_:GLenum)
+Function glDeleteBuffers:Void(n_:GLsizei,buffers_:GLuint Ptr)
+Function glDeleteFramebuffers:Void(n_:GLsizei,framebuffers_:GLuint Ptr)
+Function glDeleteProgram:Void(program_:GLuint)
+Function glDeleteRenderbuffers:Void(n_:GLsizei,renderbuffers_:GLuint Ptr)
+Function glDeleteShader:Void(shader_:GLuint)
+Function glDeleteTextures:Void(n_:GLsizei,textures_:GLuint Ptr)
+Function glDepthFunc:Void(func_:GLenum)
+Function glDepthMask:Void(flag_:GLboolean)
+Function glDepthRangef:Void(zNear_:GLclampf,zFar_:GLclampf)
+Function glDetachShader:Void(program_:GLuint,shader_:GLuint)
+Function glDisable:Void(cap_:GLenum)
+Function glDisableVertexAttribArray:Void(index_:GLuint)
+Function glDrawArrays:Void(mode_:GLenum,first_:GLint,count_:GLsizei)
+Function glDrawElements:Void(mode_:GLenum,count_:GLsizei,type_:GLenum,indices_:GLvoid Ptr)
+Function glEnable:Void(cap_:GLenum)
+Function glEnableVertexAttribArray:Void(index_:GLuint)
+Function glFinish:Void()
+Function glFlush:Void()
+Function glFramebufferRenderbuffer:Void(target_:GLenum,attachment_:GLenum,renderbuffertarget_:GLenum,renderbuffer_:GLuint)
+Function glFramebufferTexture2D:Void(target_:GLenum,attachment_:GLenum,textarget_:GLenum,texture_:GLuint,level_:GLint)
+Function glFrontFace:Void(mode_:GLenum)
+Function glGenBuffers:Void(n_:GLsizei,buffers_:GLuint Ptr)
+Function glGenerateMipmap:Void(target_:GLenum)
+Function glGenFramebuffers:Void(n_:GLsizei,framebuffers_:GLuint Ptr)
+Function glGenRenderbuffers:Void(n_:GLsizei,renderbuffers_:GLuint Ptr)
+Function glGenTextures:Void(n_:GLsizei,textures_:GLuint Ptr)
+Function glGetActiveAttrib:Void(program_:GLuint,index_:GLuint,bufsize_:GLsizei,length_:GLsizei Ptr,size_:GLint Ptr,type_:GLenum Ptr,name_:GLchar Ptr)
+
+Function glGetActiveUniform:Void(program_:GLuint,index_:GLuint,bufsize_:GLsizei,length_:GLsizei Ptr,size_:GLint Ptr,type_:UInt Ptr,name_:GLchar Ptr)
+
+Function glGetAttachedShaders:Void(program_:GLuint,maxcount_:GLsizei,count_:GLsizei Ptr,shaders_:GLuint Ptr)
+Function glGetAttribLocation:int(program_:GLuint,name_:CString)
+Function glGetBooleanv:Void(pname_:GLenum,params_:GLboolean Ptr)
+Function glGetBufferParameteriv:Void(target_:GLenum,pname_:GLenum,params_:GLint Ptr)
+Function glGetError:GLenum()
+Function glGetFloatv:Void(pname_:GLenum,params_:GLfloat Ptr)
+Function glGetFramebufferAttachmentParameteriv:Void(target_:GLenum,attachment_:GLenum,pname_:GLenum,params_:GLint Ptr)
+Function glGetIntegerv:Void(pname_:GLenum,params_:GLint Ptr)
+Function glGetProgramiv:Void(program_:GLuint,pname_:GLenum,params_:GLint Ptr)
+Function glGetProgramInfoLog:Void(program_:GLuint,bufsize_:GLsizei,length_:GLsizei Ptr,infolog_:GLchar Ptr )
+Function glGetRenderbufferParameteriv:Void(target_:GLenum,pname_:GLenum,params_:GLint Ptr)
+Function glGetShaderiv:Void(shader_:GLuint,pname_:GLenum,params_:GLint Ptr)
+Function glGetShaderInfoLog:Void(shader_:GLuint,bufsize_:GLsizei,length_:GLsizei Ptr,infolog_:GLchar Ptr )
+Function glGetShaderPrecisionFormat:Void(shadertype_:GLenum,precisiontype_:GLenum,range_:GLint Ptr,precision_:GLint Ptr)
+Function glGetShaderSource:Void(shader_:GLuint,bufsize_:GLsizei,length_:GLsizei Ptr,source_:CString)
+Function glGetString:GLubyte Ptr(name_:GLenum)
+Function glGetTexParameterfv:Void(target_:GLenum,pname_:GLenum,params_:GLfloat Ptr)
+Function glGetTexParameteriv:Void(target_:GLenum,pname_:GLenum,params_:GLint Ptr)
+Function glGetUniformfv:Void(program_:GLuint,location_:GLint,params_:GLfloat Ptr)
+Function glGetUniformiv:Void(program_:GLuint,location_:GLint,params_:GLint Ptr)
+Function glGetUniformLocation:Int(program_:GLuint,name_:CString)
+Function glGetVertexAttribfv:Void(index_:GLuint,pname_:GLenum,params_:GLfloat Ptr)
+Function glGetVertexAttribiv:Void(index_:GLuint,pname_:GLenum,params_:GLint Ptr)
+Function glGetVertexAttribPointerv:Void(index_:GLuint,pname_:GLenum,pointer_:GLvoid Ptr Ptr)
+Function glHint:Void(target_:GLenum,mode_:GLenum)
+Function glIsBuffer:GLboolean(buffer_:GLuint)
+Function glIsEnabled:GLboolean(cap_:GLenum)
+Function glIsFramebuffer:GLboolean(framebuffer_:GLuint)
+Function glIsProgram:GLboolean(program_:GLuint)
+Function glIsRenderbuffer:GLboolean(renderbuffer_:GLuint)
+Function glIsShader:GLboolean(shader_:GLuint)
+Function glIsTexture:GLboolean(texture_:GLuint)
+Function glLineWidth:Void(width_:GLfloat)
+Function glLinkProgram:Void(program_:GLuint)
+Function glPixelStorei:Void(pname_:GLenum,param_:GLint)
+Function glPolygonOffset:Void(factor_:GLfloat,units_:GLfloat)
+Function glReadPixels:Void(x_:GLint,y_:GLint,width_:GLsizei,height_:GLsizei,format_:GLenum,type_:GLenum,pixels_:GLvoid Ptr)
+Function glReleaseShaderCompiler:Void()
+Function glRenderbufferStorage:Void(target_:GLenum,internalformat_:GLenum,width_:GLsizei,height_:GLsizei)
+Function glSampleCoverage:Void(value_:GLclampf,invert_:GLboolean)
+Function glScissor:Void(x_:GLint,y_:GLint,width_:GLsizei,height_:GLsizei)
+Function glShaderBinary:Void(n_:GLsizei,shaders_:GLuint Ptr,binaryformat_:GLenum,binary_:GLvoid Ptr,length_:GLsizei)
+Function glShaderSource:Void(shader_:GLuint,count_:GLsizei,string_:GLcchar Ptr Ptr,length_:GLint Ptr)
+Function glStencilFunc:Void(func_:GLenum,ref_:GLint,mask_:GLuint)
+Function glStencilFuncSeparate:Void(face_:GLenum,func_:GLenum,ref_:GLint,mask_:GLuint)
+Function glStencilMask:Void(mask_:GLuint)
+Function glStencilMaskSeparate:Void(face_:GLenum,mask_:GLuint)
+Function glStencilOp:Void(fail_:GLenum,zfail_:GLenum,zpass_:GLenum)
+Function glStencilOpSeparate:Void(face_:GLenum,fail_:GLenum,zfail_:GLenum,zpass_:GLenum)
+Function glTexImage2D:Void(target_:GLenum,level_:GLint,internalformat_:GLint,width_:GLsizei,height_:GLsizei,border_:GLint,format_:GLenum,type_:GLenum,pixels_:GLvoid Ptr)
+Function glTexParameterf:Void(target_:GLenum,pname_:GLenum,param_:GLfloat)
+Function glTexParameterfv:Void(target_:GLenum,pname_:GLenum,params_:GLfloat Ptr)
+Function glTexParameteri:Void(target_:GLenum,pname_:GLenum,param_:GLint)
+Function glTexParameteriv:Void(target_:GLenum,pname_:GLenum,params_:GLint Ptr)
+Function glTexSubImage2D:Void(target_:GLenum,level_:GLint,xoffset_:GLint,yoffset_:GLint,width_:GLsizei,height_:GLsizei,format_:GLenum,type_:GLenum,pixels_:GLvoid Ptr)
+Function glUniform1f:Void(location_:GLint,x_:GLfloat)
+Function glUniform1fv:Void(location_:GLint,count_:GLsizei,v_:GLfloat Ptr)
+Function glUniform1i:Void(location_:GLint,x_:GLint)
+Function glUniform1iv:Void(location_:GLint,count_:GLsizei,v_:GLint Ptr)
+Function glUniform2f:Void(location_:GLint,x_:GLfloat,y_:GLfloat)
+Function glUniform2fv:Void(location_:GLint,count_:GLsizei,v_:GLfloat Ptr)
+Function glUniform2i:Void(location_:GLint,x_:GLint,y_:GLint)
+Function glUniform2iv:Void(location_:GLint,count_:GLsizei,v_:GLint Ptr)
+Function glUniform3f:Void(location_:GLint,x_:GLfloat,y_:GLfloat,z_:GLfloat)
+Function glUniform3fv:Void(location_:GLint,count_:GLsizei,v_:GLfloat Ptr)
+Function glUniform3i:Void(location_:GLint,x_:GLint,y_:GLint,z_:GLint)
+Function glUniform3iv:Void(location_:GLint,count_:GLsizei,v_:GLint Ptr)
+Function glUniform4f:Void(location_:GLint,x_:GLfloat,y_:GLfloat,z_:GLfloat,w_:GLfloat)
+Function glUniform4fv:Void(location_:GLint,count_:GLsizei,v_:GLfloat Ptr)
+Function glUniform4i:Void(location_:GLint,x_:GLint,y_:GLint,z_:GLint,w_:GLint)
+Function glUniform4iv:Void(location_:GLint,count_:GLsizei,v_:GLint Ptr)
+Function glUniformMatrix2fv:Void(location_:GLint,count_:GLsizei,transpose_:GLboolean,value_:GLfloat Ptr)
+Function glUniformMatrix3fv:Void(location_:GLint,count_:GLsizei,transpose_:GLboolean,value_:GLfloat Ptr)
+Function glUniformMatrix4fv:Void(location_:GLint,count_:GLsizei,transpose_:GLboolean,value_:GLfloat Ptr)
+Function glUseProgram:Void(program_:GLuint)
+Function glValidateProgram:Void(program_:GLuint)
+Function glVertexAttrib1f:Void(indx_:GLuint,x_:GLfloat)
+Function glVertexAttrib1fv:Void(indx_:GLuint,values_:GLfloat Ptr)
+Function glVertexAttrib2f:Void(indx_:GLuint,x_:GLfloat,y_:GLfloat)
+Function glVertexAttrib2fv:Void(indx_:GLuint,values_:GLfloat Ptr)
+Function glVertexAttrib3f:Void(indx_:GLuint,x_:GLfloat,y_:GLfloat,z_:GLfloat)
+Function glVertexAttrib3fv:Void(indx_:GLuint,values_:GLfloat Ptr)
+Function glVertexAttrib4f:Void(indx_:GLuint,x_:GLfloat,y_:GLfloat,z_:GLfloat,w_:GLfloat)
+Function glVertexAttrib4fv:Void(indx_:GLuint,values_:GLfloat Ptr)
+Function glVertexAttribPointer:Void(indx_:GLuint,size_:GLint,type_:GLenum,normalized_:GLboolean,stride_:GLsizei,ptr_:GLvoid Ptr)
+Function glViewport:Void(x_:GLint,y_:GLint,width_:GLsizei,height_:GLsizei)
+'${END}
+
+#If __TARGET__="desktop" And __HOSTOS__="windows"
+Function bb_gles20_windows_init()
+#Endif
+
+Public
+
+'Must call this after creating context...
+'
+Function glInitEx()
+	#If __TARGET__="desktop" And __HOSTOS__="windows"
+'		bb_gles20_windows_init()
+	#Endif
+End
+
+'Saner versions of some string functions...
+'
+Function glShaderSourceEx:Void( shader:GLuint,source:String )
+
+	Local n:=source.Length
+	Local buf:=Cast<Byte Ptr>( libc.malloc( n+1 ) )
+	For Local i:=0 Until n
+		buf[i]=source[i]
+	Next
+	buf[n]=0
+	
+	Local p:=Cast<GLcchar Ptr>( buf )
+	
+	glShaderSource( shader,1,Varptr p,Null )
+	
+	libc.free( buf )
+End
+
+Function glGetShaderInfoLogEx:String( shader:GLuint )
+
+	Local buf:=New Byte[1024],length:GLsizei
+	
+	glGetShaderInfoLog( shader,buf.Length,Varptr length,Cast<GLchar Ptr>( Varptr buf[0] ) )
+	
+	Return String.FromCString( Varptr buf[0] )
+End
+
+Function glGetProgramInfoLogEx:String( program:GLuint )
+
+	Local buf:=New Byte[1024],length:GLsizei
+	
+	glGetProgramInfoLog( program,buf.Length,Varptr length,Cast<GLchar Ptr>( Varptr buf[0] ) )
+	
+	Return String.FromCString( Varptr buf[0] )
+End

+ 187 - 0
modules/gles20/makegles20.monkey

@@ -0,0 +1,187 @@
+
+Import brl.filesystem
+Import brl.process
+Import brl.filepath
+Import brl.filestream
+
+Global pos:=0
+Global tokes:String[]
+
+Function LoadString:String( path:String )
+	Local stream:=FileStream.Open( path,"r" )
+	If Not stream Return ""
+	Local str:=stream.ReadString()
+	stream.Close
+	Return str
+End
+
+Function SaveString:Void( str:String,path:String )
+	Local stream:=FileStream.Open( path,"w" )
+	stream.WriteString str
+	stream.Close
+End
+
+Function GetTokes:Void( text:String )
+
+	Local pos:=0
+	Local buf:=New StringStack
+	
+	Repeat
+	
+		While pos<text.Length And text[pos]<=32
+			pos+=1
+		Wend
+		
+		If pos=text.Length 
+			.pos=0
+			.tokes=buf.ToArray()
+			Return
+		Endif
+		
+		Local start:=pos
+		Local chr:=text[pos]
+		pos+=1
+		
+		If (chr>=65 And chr<65+26) Or (chr>=97 And chr<97+26) Or chr=95
+			While pos<text.Length
+				chr=text[pos]
+				If (chr>=65 And chr<65+26) Or (chr>=97 And chr<97+26) Or( chr>=48 And chr<58) Or chr=95
+					pos+=1
+					Continue
+				Endif
+				Exit
+			Wend
+		Else If chr>=48 And chr<58
+			If pos<text.Length And text[pos]="x"[0]
+				pos+=1
+				While pos<text.Length
+					chr=text[pos]
+					If (chr>=48 And chr<58) Or (chr>=65 And chr<70) Or (chr>=97 And chr<102)
+						pos+=1
+						Continue
+					Endif
+					Exit
+				Wend
+			Else
+				While pos<text.Length
+					chr=text[pos]
+					If chr>=48 And chr<58
+						pos+=1
+						Continue
+					Endif
+					Exit
+				Wend
+			Endif
+		Endif
+		
+		buf.Push text[start..pos]
+		
+	Forever
+End
+
+Function Parse:String()
+	If pos=tokes.Length Return ""
+	Local toke:=tokes[pos]
+	pos+=1
+	Return toke
+End
+
+Function CParse:Bool( toke:String )
+	If pos=tokes.Length Or tokes[pos]<>toke Return False
+	pos+=1
+	Return True
+End
+
+Function Parse:Void( toke:String )
+	If Not CParse( toke ) DebugStop
+End
+
+Function ParseType:String()
+
+	Local isconst:=CParse( "const" )
+
+	Local ty:=Parse()
+	
+	If ty="void" ty="Void"
+	
+	If CParse( "*" ) ty+=" Ptr"
+	If CParse( "*" ) ty+=" Ptr"
+	
+	If isconst And ty="GLchar Ptr" ty="String"
+	
+	Return ty
+End
+
+Function Main()
+
+	While FileType( "gles20.h" )=FILETYPE_NONE
+		ChangeDir( ".." )
+	Wend
+	
+	Local file:=LoadString( "gles20.h" )
+	Local lines:=file.Split( "~n" )
+	
+	Local consts:=New StringStack
+	Local functions:=New StringStack
+	
+	For Local line:=Eachin lines
+
+		GetTokes( line )
+		
+		If CParse( "#" ) And CParse( "define" )
+		
+			Local id:=Parse()
+			
+			If id.StartsWith( "GL_" )
+				Local ty:="Int"
+				consts.Push( "Const "+id+":"+ty )
+			Endif
+			
+		Else If CParse( "GL_APICALL" )
+		
+			Local retTy:=ParseType()
+			
+			Parse( "GL_APIENTRY" )
+			Local id:=Parse()
+			Parse( "(" )
+			
+			Local argTys:=""
+			
+			If Not CParse( ")" )
+				Repeat
+					Local ty:=ParseType()
+					If ty="Void" Exit
+					Local id:=Parse()+"_"
+					If argTys argTys+=","
+					argTys+=id+":"+ty
+				Until Not CParse( "," )
+				Parse( ")" )
+			Endif
+		
+			functions.Push( "Function "+id+":"+retTy+"("+argTys+")" )
+
+		Endif
+		
+	Next
+	
+	Local gles20:=LoadString( "gles20.monkey2" )
+	
+	Local i0:Int,i1:Int,i2:Int
+	
+	i0=gles20.Find( "~n'${CONSTS}" ) ; If i0=-1 DebugStop
+	i1=gles20.Find( "~n",i0+1 ) ; If i1=-1 DebugStop
+	i2=gles20.Find( "~n'${END}",i1 ) ; If i2=-1 DebugStop
+	
+	gles20=gles20[..i1+1]+consts.Join( "~n" )+gles20[i2..]
+	
+	i0=gles20.Find( "~n'${FUNCTIONS}" ) ; If i0=-1 DebugStop
+	i1=gles20.Find( "~n",i0+1 ) ; If i1=-1 DebugStop
+	i2=gles20.Find( "~n'${END}",i1 ) ; If i2=-1 DebugStop
+
+	gles20=gles20[..i1+1]+functions.Join( "~n" )+gles20[i2..]
+	
+	SaveString( gles20,"gles20.monkey2" )
+	
+	Print "Done!"
+
+End

+ 621 - 0
modules/gles20/native/gles20.h

@@ -0,0 +1,621 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+#include <GLES2/gl2platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void             GLvoid;
+typedef char             GLchar;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef khronos_int8_t   GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef khronos_uint8_t  GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef khronos_float_t  GLfloat;
+typedef khronos_float_t  GLclampf;
+typedef khronos_int32_t  GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t  GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0                 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+
+/* Boolean */
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+
+/* BeginMode */
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+
+/* BlendingFactorSrc */
+/*      GL_ZERO */
+/*      GL_ONE */
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+/*      GL_SRC_ALPHA */
+/*      GL_ONE_MINUS_SRC_ALPHA */
+/*      GL_DST_ALPHA */
+/*      GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009    /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+
+/* CullFaceMode */
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+
+/* DepthFunction */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+
+/* FrontFaceDirection */
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+/*      GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+/*      GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+
+/* GetTextureParameter */
+/*      GL_TEXTURE_MAG_FILTER */
+/*      GL_TEXTURE_MIN_FILTER */
+/*      GL_TEXTURE_WRAP_S */
+/*      GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT            0x8192
+
+/* DataType */
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+
+/* PixelType */
+/*      GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER                  0x8B30
+#define GL_VERTEX_SHADER                    0x8B31
+#define GL_MAX_VERTEX_ATTRIBS               0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
+#define GL_MAX_VARYING_VECTORS              0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS   0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS          0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
+#define GL_SHADER_TYPE                      0x8B4F
+#define GL_DELETE_STATUS                    0x8B80
+#define GL_LINK_STATUS                      0x8B82
+#define GL_VALIDATE_STATUS                  0x8B83
+#define GL_ATTACHED_SHADERS                 0x8B85
+#define GL_ACTIVE_UNIFORMS                  0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH        0x8B87
+#define GL_ACTIVE_ATTRIBUTES                0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH      0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION         0x8B8C
+#define GL_CURRENT_PROGRAM                  0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+
+/* StencilOp */
+/*      GL_ZERO */
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+
+/* StringName */
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+
+/* TextureMinFilter */
+/*      GL_NEAREST */
+/*      GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+
+/* TextureTarget */
+/*      GL_TEXTURE_2D */
+#define GL_TEXTURE                        0x1702
+
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED        0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE           0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE         0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE           0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED     0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER        0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE   0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX                  0x1901
+#define GL_STENCIL_INDEX8                 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE           0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME           0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+
+#define GL_NONE                           0
+
+#define GL_FRAMEBUFFER_COMPLETE                      0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT         0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS         0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED                   0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void         GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void         GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void         GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void         GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void         GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void         GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void         GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void         GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void         GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void         GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+GL_APICALL GLenum       GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void         GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void         GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void         GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void         GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void         GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void         GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void         GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void         GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint       GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint       GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void         GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void         GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void         GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void         GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void         GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void         GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void         GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glFinish (void);
+GL_APICALL void         GL_APIENTRY glFlush (void);
+GL_APICALL void         GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void         GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void         GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void         GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL int          GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void         GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum       GL_APIENTRY glGetError (void);
+GL_APICALL void         GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void         GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void         GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void         GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void         GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL int          GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
+GL_APICALL void         GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean    GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean    GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean    GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean    GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void         GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void         GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void         GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void         GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void         GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void         GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
+GL_APICALL void         GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void         GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void         GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void         GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void         GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void         GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void         GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void         GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void         GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+GL_APICALL void         GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */

+ 8 - 0
modules/gles20/native/gles20_linux.h

@@ -0,0 +1,8 @@
+
+#ifndef BB_GLES20_LINUX_H
+#define BB_GLES20_LINUX_H
+
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>	
+
+#endif

+ 107 - 0
modules/gles20/native/gles20_windows.c

@@ -0,0 +1,107 @@
+
+#define BB_GL_EXTERN
+
+#include "gles20_windows.h"
+
+//for wglGetProcAddress
+#include <windows.h>
+
+void bb_gles20_windows_init(){
+	glActiveTexture=(void*)wglGetProcAddress("glActiveTexture");
+	glAttachShader=(void*)wglGetProcAddress("glAttachShader");
+	glBindAttribLocation=(void*)wglGetProcAddress("glBindAttribLocation");
+	glBindBuffer=(void*)wglGetProcAddress("glBindBuffer");
+	glBindFramebuffer=(void*)wglGetProcAddress("glBindFramebuffer");
+	glBindRenderbuffer=(void*)wglGetProcAddress("glBindRenderbuffer");
+	glBlendColor=(void*)wglGetProcAddress("glBlendColor");
+	glBlendEquation=(void*)wglGetProcAddress("glBlendEquation");
+	glBlendEquationSeparate=(void*)wglGetProcAddress("glBlendEquationSeparate");
+	glBlendFuncSeparate=(void*)wglGetProcAddress("glBlendFuncSeparate");
+	glBufferData=(void*)wglGetProcAddress("glBufferData");
+	glBufferSubData=(void*)wglGetProcAddress("glBufferSubData");
+	glCheckFramebufferStatus=(void*)wglGetProcAddress("glCheckFramebufferStatus");
+	glClearDepthf=(void*)wglGetProcAddress("glClearDepthf");
+	glCompileShader=(void*)wglGetProcAddress("glCompileShader");
+	glCompressedTexImage2D=(void*)wglGetProcAddress("glCompressedTexImage2D");
+	glCompressedTexSubImage2D=(void*)wglGetProcAddress("glCompressedTexSubImage2D");
+	glCreateProgram=(void*)wglGetProcAddress("glCreateProgram");
+	glCreateShader=(void*)wglGetProcAddress("glCreateShader");
+	glDeleteBuffers=(void*)wglGetProcAddress("glDeleteBuffers");
+	glDeleteFramebuffers=(void*)wglGetProcAddress("glDeleteFramebuffers");
+	glDeleteProgram=(void*)wglGetProcAddress("glDeleteProgram");
+	glDeleteRenderbuffers=(void*)wglGetProcAddress("glDeleteRenderbuffers");
+	glDeleteShader=(void*)wglGetProcAddress("glDeleteShader");
+	glDepthRangef=(void*)wglGetProcAddress("glDepthRangef");
+	glDetachShader=(void*)wglGetProcAddress("glDetachShader");
+	glDisableVertexAttribArray=(void*)wglGetProcAddress("glDisableVertexAttribArray");
+	glEnableVertexAttribArray=(void*)wglGetProcAddress("glEnableVertexAttribArray");
+	glFramebufferRenderbuffer=(void*)wglGetProcAddress("glFramebufferRenderbuffer");
+	glFramebufferTexture2D=(void*)wglGetProcAddress("glFramebufferTexture2D");
+	glGenBuffers=(void*)wglGetProcAddress("glGenBuffers");
+	glGenerateMipmap=(void*)wglGetProcAddress("glGenerateMipmap");
+	glGenFramebuffers=(void*)wglGetProcAddress("glGenFramebuffers");
+	glGenRenderbuffers=(void*)wglGetProcAddress("glGenRenderbuffers");
+	glGetActiveAttrib=(void*)wglGetProcAddress("glGetActiveAttrib");
+	glGetActiveUniform=(void*)wglGetProcAddress("glGetActiveUniform");
+	glGetAttachedShaders=(void*)wglGetProcAddress("glGetAttachedShaders");
+	glGetAttribLocation=(void*)wglGetProcAddress("glGetAttribLocation");
+	glGetBufferParameteriv=(void*)wglGetProcAddress("glGetBufferParameteriv");
+	glGetFramebufferAttachmentParameteriv=(void*)wglGetProcAddress("glGetFramebufferAttachmentParameteriv");
+	glGetProgramiv=(void*)wglGetProcAddress("glGetProgramiv");
+	glGetProgramInfoLog=(void*)wglGetProcAddress("glGetProgramInfoLog");
+	glGetRenderbufferParameteriv=(void*)wglGetProcAddress("glGetRenderbufferParameteriv");
+	glGetShaderiv=(void*)wglGetProcAddress("glGetShaderiv");
+	glGetShaderInfoLog=(void*)wglGetProcAddress("glGetShaderInfoLog");
+	glGetShaderPrecisionFormat=(void*)wglGetProcAddress("glGetShaderPrecisionFormat");
+	glGetShaderSource=(void*)wglGetProcAddress("glGetShaderSource");
+	glGetUniformfv=(void*)wglGetProcAddress("glGetUniformfv");
+	glGetUniformiv=(void*)wglGetProcAddress("glGetUniformiv");
+	glGetUniformLocation=(void*)wglGetProcAddress("glGetUniformLocation");
+	glGetVertexAttribfv=(void*)wglGetProcAddress("glGetVertexAttribfv");
+	glGetVertexAttribiv=(void*)wglGetProcAddress("glGetVertexAttribiv");
+	glGetVertexAttribPointerv=(void*)wglGetProcAddress("glGetVertexAttribPointerv");
+	glIsBuffer=(void*)wglGetProcAddress("glIsBuffer");
+	glIsFramebuffer=(void*)wglGetProcAddress("glIsFramebuffer");
+	glIsProgram=(void*)wglGetProcAddress("glIsProgram");
+	glIsRenderbuffer=(void*)wglGetProcAddress("glIsRenderbuffer");
+	glIsShader=(void*)wglGetProcAddress("glIsShader");
+	glLinkProgram=(void*)wglGetProcAddress("glLinkProgram");
+	glReleaseShaderCompiler=(void*)wglGetProcAddress("glReleaseShaderCompiler");
+	glRenderbufferStorage=(void*)wglGetProcAddress("glRenderbufferStorage");
+	glSampleCoverage=(void*)wglGetProcAddress("glSampleCoverage");
+	glShaderBinary=(void*)wglGetProcAddress("glShaderBinary");
+	glShaderSource=(void*)wglGetProcAddress("glShaderSource");
+	glStencilFuncSeparate=(void*)wglGetProcAddress("glStencilFuncSeparate");
+	glStencilMaskSeparate=(void*)wglGetProcAddress("glStencilMaskSeparate");
+	glStencilOpSeparate=(void*)wglGetProcAddress("glStencilOpSeparate");
+	glUniform1f=(void*)wglGetProcAddress("glUniform1f");
+	glUniform1fv=(void*)wglGetProcAddress("glUniform1fv");
+	glUniform1i=(void*)wglGetProcAddress("glUniform1i");
+	glUniform1iv=(void*)wglGetProcAddress("glUniform1iv");
+	glUniform2f=(void*)wglGetProcAddress("glUniform2f");
+	glUniform2fv=(void*)wglGetProcAddress("glUniform2fv");
+	glUniform2i=(void*)wglGetProcAddress("glUniform2i");
+	glUniform2iv=(void*)wglGetProcAddress("glUniform2iv");
+	glUniform3f=(void*)wglGetProcAddress("glUniform3f");
+	glUniform3fv=(void*)wglGetProcAddress("glUniform3fv");
+	glUniform3i=(void*)wglGetProcAddress("glUniform3i");
+	glUniform3iv=(void*)wglGetProcAddress("glUniform3iv");
+	glUniform4f=(void*)wglGetProcAddress("glUniform4f");
+	glUniform4fv=(void*)wglGetProcAddress("glUniform4fv");
+	glUniform4i=(void*)wglGetProcAddress("glUniform4i");
+	glUniform4iv=(void*)wglGetProcAddress("glUniform4iv");
+	glUniformMatrix2fv=(void*)wglGetProcAddress("glUniformMatrix2fv");
+	glUniformMatrix3fv=(void*)wglGetProcAddress("glUniformMatrix3fv");
+	glUniformMatrix4fv=(void*)wglGetProcAddress("glUniformMatrix4fv");
+	glUseProgram=(void*)wglGetProcAddress("glUseProgram");
+	glValidateProgram=(void*)wglGetProcAddress("glValidateProgram");
+	glVertexAttrib1f=(void*)wglGetProcAddress("glVertexAttrib1f");
+	glVertexAttrib1fv=(void*)wglGetProcAddress("glVertexAttrib1fv");
+	glVertexAttrib2f=(void*)wglGetProcAddress("glVertexAttrib2f");
+	glVertexAttrib2fv=(void*)wglGetProcAddress("glVertexAttrib2fv");
+	glVertexAttrib3f=(void*)wglGetProcAddress("glVertexAttrib3f");
+	glVertexAttrib3fv=(void*)wglGetProcAddress("glVertexAttrib3fv");
+	glVertexAttrib4f=(void*)wglGetProcAddress("glVertexAttrib4f");
+	glVertexAttrib4fv=(void*)wglGetProcAddress("glVertexAttrib4fv");
+	glVertexAttribPointer=(void*)wglGetProcAddress("glVertexAttribPointer");
+}

+ 307 - 0
modules/gles20/native/gles20_windows.h

@@ -0,0 +1,307 @@
+
+#ifndef BB_GLES20_WINDOWS_H
+#define BB_GLES20_WINDOWS_H
+
+#include <GL/gl.h>
+
+#include <stdlib.h>
+
+#ifndef BB_GL_EXTERN
+#define BB_GL_EXTERN extern
+#endif
+
+typedef char GLchar;
+typedef size_t GLintptr;
+typedef size_t GLsizeiptr;
+
+#define __gl2_h_
+
+#define GL_ES_VERSION_2_0 1
+
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_FIXED 0x140C
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_DELETE_STATUS 0x8B80
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#ifndef GL_CLAMP_TO_EDGE
+#define GL_CLAMP_TO_EDGE 0x812F
+#endif
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RGB565 0x8D62
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+
+BB_GL_EXTERN void(__stdcall*glActiveTexture)(GLenum texture);
+BB_GL_EXTERN void(__stdcall*glAttachShader)(GLuint program, GLuint shader);
+BB_GL_EXTERN void(__stdcall*glBindAttribLocation)(GLuint program, GLuint index, const GLchar* name);
+BB_GL_EXTERN void(__stdcall*glBindBuffer)(GLenum target, GLuint buffer);
+BB_GL_EXTERN void(__stdcall*glBindFramebuffer)(GLenum target, GLuint framebuffer);
+BB_GL_EXTERN void(__stdcall*glBindRenderbuffer)(GLenum target, GLuint renderbuffer);
+BB_GL_EXTERN void(__stdcall*glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+BB_GL_EXTERN void(__stdcall*glBlendEquation)( GLenum mode );
+BB_GL_EXTERN void(__stdcall*glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha);
+BB_GL_EXTERN void(__stdcall*glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+BB_GL_EXTERN void(__stdcall*glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+BB_GL_EXTERN void(__stdcall*glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+BB_GL_EXTERN GLenum(__stdcall*glCheckFramebufferStatus)(GLenum target);
+BB_GL_EXTERN void(__stdcall*glClearDepthf)(GLclampf depth);
+BB_GL_EXTERN void(__stdcall*glCompileShader)(GLuint shader);
+BB_GL_EXTERN void(__stdcall*glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+BB_GL_EXTERN void(__stdcall*glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+BB_GL_EXTERN GLuint(__stdcall*glCreateProgram)(void);
+BB_GL_EXTERN GLuint(__stdcall*glCreateShader)(GLenum type);
+BB_GL_EXTERN void(__stdcall*glDeleteBuffers)(GLsizei n, const GLuint* buffers);
+BB_GL_EXTERN void(__stdcall*glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers);
+BB_GL_EXTERN void(__stdcall*glDeleteProgram)(GLuint program);
+BB_GL_EXTERN void(__stdcall*glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers);
+BB_GL_EXTERN void(__stdcall*glDeleteShader)(GLuint shader);
+BB_GL_EXTERN void(__stdcall*glDepthRangef)(GLclampf zNear, GLclampf zFar);
+BB_GL_EXTERN void(__stdcall*glDetachShader)(GLuint program, GLuint shader);
+BB_GL_EXTERN void(__stdcall*glDisableVertexAttribArray)(GLuint index);
+BB_GL_EXTERN void(__stdcall*glEnableVertexAttribArray)(GLuint index);
+BB_GL_EXTERN void(__stdcall*glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+BB_GL_EXTERN void(__stdcall*glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+BB_GL_EXTERN void(__stdcall*glGenBuffers)(GLsizei n, GLuint* buffers);
+BB_GL_EXTERN void(__stdcall*glGenerateMipmap)(GLenum target);
+BB_GL_EXTERN void(__stdcall*glGenFramebuffers)(GLsizei n, GLuint* framebuffers);
+BB_GL_EXTERN void(__stdcall*glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers);
+BB_GL_EXTERN void(__stdcall*glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+BB_GL_EXTERN void(__stdcall*glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+BB_GL_EXTERN void(__stdcall*glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+BB_GL_EXTERN int(__stdcall*glGetAttribLocation)(GLuint program, const GLchar* name);
+BB_GL_EXTERN void(__stdcall*glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params);
+BB_GL_EXTERN void(__stdcall*glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params);
+BB_GL_EXTERN void(__stdcall*glGetProgramiv)(GLuint program, GLenum pname, GLint* params);
+BB_GL_EXTERN void(__stdcall*glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+BB_GL_EXTERN void(__stdcall*glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params);
+BB_GL_EXTERN void(__stdcall*glGetShaderiv)(GLuint shader, GLenum pname, GLint* params);
+BB_GL_EXTERN void(__stdcall*glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+BB_GL_EXTERN void(__stdcall*glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+BB_GL_EXTERN void(__stdcall*glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+BB_GL_EXTERN void(__stdcall*glGetUniformfv)(GLuint program, GLint location, GLfloat* params);
+BB_GL_EXTERN void(__stdcall*glGetUniformiv)(GLuint program, GLint location, GLint* params);
+BB_GL_EXTERN int(__stdcall*glGetUniformLocation)(GLuint program, const GLchar* name);
+BB_GL_EXTERN void(__stdcall*glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params);
+BB_GL_EXTERN void(__stdcall*glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params);
+BB_GL_EXTERN void(__stdcall*glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer);
+BB_GL_EXTERN GLboolean(__stdcall*glIsBuffer)(GLuint buffer);
+BB_GL_EXTERN GLboolean(__stdcall*glIsFramebuffer)(GLuint framebuffer);
+BB_GL_EXTERN GLboolean(__stdcall*glIsProgram)(GLuint program);
+BB_GL_EXTERN GLboolean(__stdcall*glIsRenderbuffer)(GLuint renderbuffer);
+BB_GL_EXTERN GLboolean(__stdcall*glIsShader)(GLuint shader);
+BB_GL_EXTERN void(__stdcall*glLinkProgram)(GLuint program);
+BB_GL_EXTERN void(__stdcall*glReleaseShaderCompiler)(void);
+BB_GL_EXTERN void(__stdcall*glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+BB_GL_EXTERN void(__stdcall*glSampleCoverage)(GLclampf value, GLboolean invert);
+BB_GL_EXTERN void(__stdcall*glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+BB_GL_EXTERN void(__stdcall*glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
+BB_GL_EXTERN void(__stdcall*glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask);
+BB_GL_EXTERN void(__stdcall*glStencilMaskSeparate)(GLenum face, GLuint mask);
+BB_GL_EXTERN void(__stdcall*glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+BB_GL_EXTERN void(__stdcall*glUniform1f)(GLint location, GLfloat x);
+BB_GL_EXTERN void(__stdcall*glUniform1fv)(GLint location, GLsizei count, const GLfloat* v);
+BB_GL_EXTERN void(__stdcall*glUniform1i)(GLint location, GLint x);
+BB_GL_EXTERN void(__stdcall*glUniform1iv)(GLint location, GLsizei count, const GLint* v);
+BB_GL_EXTERN void(__stdcall*glUniform2f)(GLint location, GLfloat x, GLfloat y);
+BB_GL_EXTERN void(__stdcall*glUniform2fv)(GLint location, GLsizei count, const GLfloat* v);
+BB_GL_EXTERN void(__stdcall*glUniform2i)(GLint location, GLint x, GLint y);
+BB_GL_EXTERN void(__stdcall*glUniform2iv)(GLint location, GLsizei count, const GLint* v);
+BB_GL_EXTERN void(__stdcall*glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z);
+BB_GL_EXTERN void(__stdcall*glUniform3fv)(GLint location, GLsizei count, const GLfloat* v);
+BB_GL_EXTERN void(__stdcall*glUniform3i)(GLint location, GLint x, GLint y, GLint z);
+BB_GL_EXTERN void(__stdcall*glUniform3iv)(GLint location, GLsizei count, const GLint* v);
+BB_GL_EXTERN void(__stdcall*glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+BB_GL_EXTERN void(__stdcall*glUniform4fv)(GLint location, GLsizei count, const GLfloat* v);
+BB_GL_EXTERN void(__stdcall*glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w);
+BB_GL_EXTERN void(__stdcall*glUniform4iv)(GLint location, GLsizei count, const GLint* v);
+BB_GL_EXTERN void(__stdcall*glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+BB_GL_EXTERN void(__stdcall*glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+BB_GL_EXTERN void(__stdcall*glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+BB_GL_EXTERN void(__stdcall*glUseProgram)(GLuint program);
+BB_GL_EXTERN void(__stdcall*glValidateProgram)(GLuint program);
+BB_GL_EXTERN void(__stdcall*glVertexAttrib1f)(GLuint indx, GLfloat x);
+BB_GL_EXTERN void(__stdcall*glVertexAttrib1fv)(GLuint indx, const GLfloat* values);
+BB_GL_EXTERN void(__stdcall*glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y);
+BB_GL_EXTERN void(__stdcall*glVertexAttrib2fv)(GLuint indx, const GLfloat* values);
+BB_GL_EXTERN void(__stdcall*glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+BB_GL_EXTERN void(__stdcall*glVertexAttrib3fv)(GLuint indx, const GLfloat* values);
+BB_GL_EXTERN void(__stdcall*glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+BB_GL_EXTERN void(__stdcall*glVertexAttrib4fv)(GLuint indx, const GLfloat* values);
+BB_GL_EXTERN void(__stdcall*glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+
+#ifdef __cplusplus
+extern "C" void bb_gles20_windows_init();
+#else
+void bb_gles20_windows_init();
+#endif
+
+#endif

+ 195 - 0
modules/hoedown/hoedown.json

@@ -0,0 +1,195 @@
+{
+  "module":{
+    "name":"hoedown"
+    ,"namespaces":[
+      {
+        "ident":"hoedown"
+        ,"enums":[
+          {
+            "ident":"hoedown_extensions"
+            ,"flags":129
+          }
+          ,{
+            "ident":"hoedown_html_flags"
+            ,"flags":129
+          }
+        ]
+        ,"constants":[
+          {
+            "ident":"HOEDOWN_EXT_AUTOLINK"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_DISABLE_INDENTED_CODE"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_FENCED_CODE"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_FOOTNOTES"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_HIGHLIGHT"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_MATH"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_MATH_EXPLICIT"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_NONE"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_NO_INTRA_EMPHASIS"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_QUOTE"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_SPACE_HEADERS"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_STRIKETHROUGH"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_SUPERSCRIPT"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_TABLES"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_EXT_UNDERLINE"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_extensions"
+          }
+          ,{
+            "ident":"HOEDOWN_HTML_ESCAPE"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_html_flags"
+          }
+          ,{
+            "ident":"HOEDOWN_HTML_HARD_WRAP"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_html_flags"
+          }
+          ,{
+            "ident":"HOEDOWN_HTML_NONE"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_html_flags"
+          }
+          ,{
+            "ident":"HOEDOWN_HTML_SKIP_HTML"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_html_flags"
+          }
+          ,{
+            "ident":"HOEDOWN_HTML_USE_XHTML"
+            ,"flags":129
+            ,"type":"hoedown.hoedown_html_flags"
+          }
+        ]
+        ,"functions":[
+          {
+            "ident":"hoedown_buffer_cstr"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"monkey.CChar Ptr"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"hoedown_buffer_free"
+          }
+          ,{
+            "ident":"hoedown_buffer_new"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"hoedown.hoedown_buffer Ptr"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"hoedown_buffer_put"
+          }
+          ,{
+            "ident":"hoedown_buffer_reset"
+          }
+          ,{
+            "ident":"hoedown_document_free"
+          }
+          ,{
+            "ident":"hoedown_document_new"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"hoedown.hoedown_document Ptr"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"hoedown_document_render"
+          }
+          ,{
+            "ident":"hoedown_document_render_inline"
+          }
+          ,{
+            "ident":"hoedown_html_renderer_free"
+          }
+          ,{
+            "ident":"hoedown_html_renderer_new"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"hoedown.hoedown_renderer Ptr"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"hoedown_html_toc_renderer_new"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"hoedown.hoedown_renderer Ptr"
+                }
+              }
+            ]
+          }
+        ]
+      }
+    ]
+  }
+}

+ 112 - 0
modules/hoedown/hoedown.monkey2

@@ -0,0 +1,112 @@
+
+Namespace hoedown
+
+#Import "hoedown/src/document.h"
+#Import "hoedown/src/html.h"
+
+#Import "hoedown/src/autolink.c"
+#Import "hoedown/src/buffer.c"
+#Import "hoedown/src/document.c"
+#Import "hoedown/src/escape.c"
+#Import "hoedown/src/html_blocks.c"
+#Import "hoedown/src/html_smartypants.c"
+#Import "hoedown/src/html.c"
+#Import "hoedown/src/stack.c"
+#Import "hoedown/src/version.c"
+
+Extern
+
+'buffer
+
+Struct hoedown_buffer
+End
+
+Function hoedown_buffer_new:hoedown_buffer Ptr( unit:Int )
+
+Function hoedown_buffer_reset( buf:hoedown_buffer Ptr )
+
+Function hoedown_buffer_free( buf:hoedown_buffer Ptr )
+
+Function hoedown_buffer_put( buf:hoedown_buffer Ptr,data:UByte Ptr,size:Int )
+
+Function hoedown_buffer_cstr:CString( buf:hoedown_buffer Ptr )
+
+'renderer
+
+Struct hoedown_renderer
+End
+
+Enum hoedown_html_flags
+End
+
+Const HOEDOWN_HTML_NONE:hoedown_html_flags="(hoedown_html_flags)0"
+
+Const HOEDOWN_HTML_SKIP_HTML:hoedown_html_flags
+Const HOEDOWN_HTML_ESCAPE:hoedown_html_flags
+Const HOEDOWN_HTML_HARD_WRAP:hoedown_html_flags
+Const HOEDOWN_HTML_USE_XHTML:hoedown_html_flags
+
+Function hoedown_html_renderer_new:hoedown_renderer Ptr( render_flags:hoedown_html_flags,nesting_level:Int )
+
+Function hoedown_html_toc_renderer_new:hoedown_renderer Ptr( nesting_level:Int )
+
+Function hoedown_html_renderer_free( renderer:hoedown_renderer Ptr )
+
+'document
+
+Struct hoedown_document
+End
+
+Enum hoedown_extensions
+End
+
+Const HOEDOWN_EXT_NONE:hoedown_extensions="(hoedown_extensions)0"
+
+Const HOEDOWN_EXT_TABLES:hoedown_extensions
+Const HOEDOWN_EXT_FENCED_CODE:hoedown_extensions
+Const HOEDOWN_EXT_FOOTNOTES:hoedown_extensions
+
+Const HOEDOWN_EXT_AUTOLINK:hoedown_extensions
+Const HOEDOWN_EXT_STRIKETHROUGH:hoedown_extensions
+Const HOEDOWN_EXT_UNDERLINE:hoedown_extensions
+Const HOEDOWN_EXT_HIGHLIGHT:hoedown_extensions
+Const HOEDOWN_EXT_QUOTE:hoedown_extensions
+Const HOEDOWN_EXT_SUPERSCRIPT:hoedown_extensions
+Const HOEDOWN_EXT_MATH:hoedown_extensions
+
+Const HOEDOWN_EXT_NO_INTRA_EMPHASIS:hoedown_extensions
+Const HOEDOWN_EXT_SPACE_HEADERS:hoedown_extensions
+Const HOEDOWN_EXT_MATH_EXPLICIT:hoedown_extensions
+
+Const HOEDOWN_EXT_DISABLE_INDENTED_CODE:hoedown_extensions
+
+#rem
+Enum hoedown_extensions
+
+	HOEDOWN_EXT_TABLES
+	HOEDOWN_EXT_FENCED_CODE
+	HOEDOWN_EXT_FOOTNOTES
+	
+	HOEDOWN_EXT_AUTOLINK
+	HOEDOWN_EXT_STRIKETHROUGH
+	HOEDOWN_EXT_UNDERLINE
+	HOEDOWN_EXT_HIGHLIGHT
+	HOEDOWN_EXT_QUOTE
+	HOEDOWN_EXT_SUPERSCRIPT
+	HOEDOWN_EXT_MATH
+	
+	HOEDOWN_EXT_NO_INTRA_EMPHASIS
+	HOEDOWN_EXT_SPACE_HEADERS
+	HOEDOWN_EXT_MATH_EXPLICIT
+	
+	HOEDOWN_EXT_DISABLE_INDENTED_CODE
+End
+#end
+
+Function hoedown_document_new:hoedown_document Ptr( renderer:hoedown_renderer Ptr,extensions:hoedown_extensions,max_nesting:Int )
+
+Function hoedown_document_render( doc:hoedown_document Ptr,ob:hoedown_buffer Ptr,data:Utf8String,size:Int )
+
+Function hoedown_document_render_inline( doc:hoedown_document Ptr,ob:hoedown_buffer Ptr,data:Utf8String,size:Int )
+
+Function hoedown_document_free( doc:hoedown_document Ptr )

+ 15 - 0
modules/hoedown/hoedown/LICENSE

@@ -0,0 +1,15 @@
+Copyright (c) 2008, Natacha Porté
+Copyright (c) 2011, Vicent Martí
+Copyright (c) 2014, Xavier Mendez, Devin Torres and the Hoedown authors
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+ 104 - 0
modules/hoedown/hoedown/README.md

@@ -0,0 +1,104 @@
+Hoedown
+=======
+
+[![Build Status](https://travis-ci.org/hoedown/hoedown.png?branch=master)](https://travis-ci.org/hoedown/hoedown)
+
+`Hoedown` is a revived fork of [Sundown](https://github.com/vmg/sundown),
+the Markdown parser based on the original code of the
+[Upskirt library](http://fossil.instinctive.eu/libupskirt/index)
+by Natacha Porté.
+
+Features
+--------
+
+*	**Fully standards compliant**
+
+	`Hoedown` passes out of the box the official Markdown v1.0.0 and v1.0.3
+	test suites, and has been extensively tested with additional corner cases
+	to make sure its output is as sane as possible at all times.
+
+*	**Massive extension support**
+
+	`Hoedown` has optional support for several (unofficial) Markdown extensions,
+	such as non-strict emphasis, fenced code blocks, tables, autolinks,
+	strikethrough and more.
+
+*	**UTF-8 aware**
+
+	`Hoedown` is fully UTF-8 aware, both when parsing the source document and when
+	generating the resulting (X)HTML code.
+
+*	**Tested & Ready to be used on production**
+
+	`Hoedown` has been extensively security audited, and includes protection against
+	all possible DOS attacks (stack overflows, out of memory situations, malformed
+	Markdown syntax...).
+
+	We've worked very hard to make `Hoedown` never leak or crash under *any* input.
+
+	**Warning**: `Hoedown` doesn't validate or post-process the HTML in Markdown documents.
+	Unless you use `HTML_ESCAPE` or `HTML_SKIP`, you should strongly consider using a
+	good post-processor in conjunction with Hoedown to prevent client-side attacks.
+
+*	**Customizable renderers**
+
+	`Hoedown` is not stuck with XHTML output: the Markdown parser of the library
+	is decoupled from the renderer, so it's trivial to extend the library with
+	custom renderers. A fully functional (X)HTML renderer is included.
+
+*	**Optimized for speed**
+
+	`Hoedown` is written in C, with a special emphasis on performance. When wrapped
+	on a dynamic language such as Python or Ruby, it has shown to be up to 40
+	times faster than other native alternatives.
+
+*	**Zero-dependency**
+
+	`Hoedown` is a zero-dependency library composed of some `.c` files and their
+	headers. No dependencies, no bullshit. Only standard C99 that builds everywhere.
+
+*	**Additional features**
+
+	`Hoedown` comes with a fully functional implementation of SmartyPants,
+	a separate autolinker, escaping utilities, buffers and stacks.
+
+Bindings
+--------
+
+You can see a community-maintained list of `Hoedown` bindings at
+[the wiki](https://github.com/hoedown/hoedown/wiki/Bindings). There is also a
+[migration guide](https://github.com/hoedown/hoedown/wiki/Migration-Guide)
+available for authors of Sundown bindings.
+
+Help us
+-------
+
+`Hoedown` is all about security. If you find a (potential) security vulnerability in the
+library, or a way to make it crash through malicious input, please report it to us by
+emailing the private [Hoedown Security](mailto:[email protected])
+mailing list. The `Hoedown` security team will review the vulnerability and work with you
+to reproduce and resolve it.
+
+Unicode character handling
+--------------------------
+
+Given that the Markdown spec makes no provision for Unicode character handling, `Hoedown`
+takes a conservative approach towards deciding which extended characters trigger Markdown
+features:
+
+*	Punctuation characters outside of the U+007F codepoint are not handled as punctuation.
+	They are considered as normal, in-word characters for word-boundary checks.
+
+*	Whitespace characters outside of the U+007F codepoint are not considered as
+	whitespace. They are considered as normal, in-word characters for word-boundary checks.
+
+Install
+-------
+
+Just typing `make` will build `Hoedown` into a dynamic library and create the `hoedown`
+and `smartypants` executables, which are command-line tools to render Markdown to HTML
+and perform SmartyPants, respectively.
+
+If you are using [CocoaPods](http://cocoapods.org), just add the line `pod 'hoedown'` to your Podfile and call `pod install`.
+
+Or, if you prefer, you can just throw the files at `src` into your project.

+ 281 - 0
modules/hoedown/hoedown/src/autolink.c

@@ -0,0 +1,281 @@
+#include "autolink.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#ifndef _MSC_VER
+#include <strings.h>
+#else
+#define strncasecmp	_strnicmp
+#endif
+
+int
+hoedown_autolink_is_safe(const uint8_t *data, size_t size)
+{
+	static const size_t valid_uris_count = 6;
+	static const char *valid_uris[] = {
+		"http://", "https://", "/", "#", "ftp://", "mailto:"
+	};
+	static const size_t valid_uris_size[] = { 7, 8, 1, 1, 6, 7 };
+	size_t i;
+
+	for (i = 0; i < valid_uris_count; ++i) {
+		size_t len = valid_uris_size[i];
+
+		if (size > len &&
+			strncasecmp((char *)data, valid_uris[i], len) == 0 &&
+			isalnum(data[len]))
+			return 1;
+	}
+
+	return 0;
+}
+
+static size_t
+autolink_delim(uint8_t *data, size_t link_end, size_t max_rewind, size_t size)
+{
+	uint8_t cclose, copen = 0;
+	size_t i;
+
+	for (i = 0; i < link_end; ++i)
+		if (data[i] == '<') {
+			link_end = i;
+			break;
+		}
+
+	while (link_end > 0) {
+		if (strchr("?!.,:", data[link_end - 1]) != NULL)
+			link_end--;
+
+		else if (data[link_end - 1] == ';') {
+			size_t new_end = link_end - 2;
+
+			while (new_end > 0 && isalpha(data[new_end]))
+				new_end--;
+
+			if (new_end < link_end - 2 && data[new_end] == '&')
+				link_end = new_end;
+			else
+				link_end--;
+		}
+		else break;
+	}
+
+	if (link_end == 0)
+		return 0;
+
+	cclose = data[link_end - 1];
+
+	switch (cclose) {
+	case '"':	copen = '"'; break;
+	case '\'':	copen = '\''; break;
+	case ')':	copen = '('; break;
+	case ']':	copen = '['; break;
+	case '}':	copen = '{'; break;
+	}
+
+	if (copen != 0) {
+		size_t closing = 0;
+		size_t opening = 0;
+		size_t i = 0;
+
+		/* Try to close the final punctuation sign in this same line;
+		 * if we managed to close it outside of the URL, that means that it's
+		 * not part of the URL. If it closes inside the URL, that means it
+		 * is part of the URL.
+		 *
+		 * Examples:
+		 *
+		 *	foo http://www.pokemon.com/Pikachu_(Electric) bar
+		 *		=> http://www.pokemon.com/Pikachu_(Electric)
+		 *
+		 *	foo (http://www.pokemon.com/Pikachu_(Electric)) bar
+		 *		=> http://www.pokemon.com/Pikachu_(Electric)
+		 *
+		 *	foo http://www.pokemon.com/Pikachu_(Electric)) bar
+		 *		=> http://www.pokemon.com/Pikachu_(Electric))
+		 *
+		 *	(foo http://www.pokemon.com/Pikachu_(Electric)) bar
+		 *		=> foo http://www.pokemon.com/Pikachu_(Electric)
+		 */
+
+		while (i < link_end) {
+			if (data[i] == copen)
+				opening++;
+			else if (data[i] == cclose)
+				closing++;
+
+			i++;
+		}
+
+		if (closing != opening)
+			link_end--;
+	}
+
+	return link_end;
+}
+
+static size_t
+check_domain(uint8_t *data, size_t size, int allow_short)
+{
+	size_t i, np = 0;
+
+	if (!isalnum(data[0]))
+		return 0;
+
+	for (i = 1; i < size - 1; ++i) {
+		if (strchr(".:", data[i]) != NULL) np++;
+		else if (!isalnum(data[i]) && data[i] != '-') break;
+	}
+
+	if (allow_short) {
+		/* We don't need a valid domain in the strict sense (with
+		 * least one dot; so just make sure it's composed of valid
+		 * domain characters and return the length of the the valid
+		 * sequence. */
+		return i;
+	} else {
+		/* a valid domain needs to have at least a dot.
+		 * that's as far as we get */
+		return np ? i : 0;
+	}
+}
+
+size_t
+hoedown_autolink__www(
+	size_t *rewind_p,
+	hoedown_buffer *link,
+	uint8_t *data,
+	size_t max_rewind,
+	size_t size,
+	unsigned int flags)
+{
+	size_t link_end;
+
+	if (max_rewind > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
+		return 0;
+
+	if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
+		return 0;
+
+	link_end = check_domain(data, size, 0);
+
+	if (link_end == 0)
+		return 0;
+
+	while (link_end < size && !isspace(data[link_end]))
+		link_end++;
+
+	link_end = autolink_delim(data, link_end, max_rewind, size);
+
+	if (link_end == 0)
+		return 0;
+
+	hoedown_buffer_put(link, data, link_end);
+	*rewind_p = 0;
+
+	return (int)link_end;
+}
+
+size_t
+hoedown_autolink__email(
+	size_t *rewind_p,
+	hoedown_buffer *link,
+	uint8_t *data,
+	size_t max_rewind,
+	size_t size,
+	unsigned int flags)
+{
+	size_t link_end, rewind;
+	int nb = 0, np = 0;
+
+	for (rewind = 0; rewind < max_rewind; ++rewind) {
+		uint8_t c = data[-1 - rewind];
+
+		if (isalnum(c))
+			continue;
+
+		if (strchr(".+-_", c) != NULL)
+			continue;
+
+		break;
+	}
+
+	if (rewind == 0)
+		return 0;
+
+	for (link_end = 0; link_end < size; ++link_end) {
+		uint8_t c = data[link_end];
+
+		if (isalnum(c))
+			continue;
+
+		if (c == '@')
+			nb++;
+		else if (c == '.' && link_end < size - 1)
+			np++;
+		else if (c != '-' && c != '_')
+			break;
+	}
+
+	if (link_end < 2 || nb != 1 || np == 0 ||
+		!isalpha(data[link_end - 1]))
+		return 0;
+
+	link_end = autolink_delim(data, link_end, max_rewind, size);
+
+	if (link_end == 0)
+		return 0;
+
+	hoedown_buffer_put(link, data - rewind, link_end + rewind);
+	*rewind_p = rewind;
+
+	return link_end;
+}
+
+size_t
+hoedown_autolink__url(
+	size_t *rewind_p,
+	hoedown_buffer *link,
+	uint8_t *data,
+	size_t max_rewind,
+	size_t size,
+	unsigned int flags)
+{
+	size_t link_end, rewind = 0, domain_len;
+
+	if (size < 4 || data[1] != '/' || data[2] != '/')
+		return 0;
+
+	while (rewind < max_rewind && isalpha(data[-1 - rewind]))
+		rewind++;
+
+	if (!hoedown_autolink_is_safe(data - rewind, size + rewind))
+		return 0;
+
+	link_end = strlen("://");
+
+	domain_len = check_domain(
+		data + link_end,
+		size - link_end,
+		flags & HOEDOWN_AUTOLINK_SHORT_DOMAINS);
+
+	if (domain_len == 0)
+		return 0;
+
+	link_end += domain_len;
+	while (link_end < size && !isspace(data[link_end]))
+		link_end++;
+
+	link_end = autolink_delim(data, link_end, max_rewind, size);
+
+	if (link_end == 0)
+		return 0;
+
+	hoedown_buffer_put(link, data - rewind, link_end + rewind);
+	*rewind_p = rewind;
+
+	return link_end;
+}

+ 46 - 0
modules/hoedown/hoedown/src/autolink.h

@@ -0,0 +1,46 @@
+/* autolink.h - versatile autolinker */
+
+#ifndef HOEDOWN_AUTOLINK_H
+#define HOEDOWN_AUTOLINK_H
+
+#include "buffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************
+ * CONSTANTS *
+ *************/
+
+typedef enum hoedown_autolink_flags {
+	HOEDOWN_AUTOLINK_SHORT_DOMAINS = (1 << 0)
+} hoedown_autolink_flags;
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_autolink_is_safe: verify that a URL has a safe protocol */
+int hoedown_autolink_is_safe(const uint8_t *data, size_t size);
+
+/* hoedown_autolink__www: search for the next www link in data */
+size_t hoedown_autolink__www(size_t *rewind_p, hoedown_buffer *link,
+	uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
+
+/* hoedown_autolink__email: search for the next email in data */
+size_t hoedown_autolink__email(size_t *rewind_p, hoedown_buffer *link,
+	uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
+
+/* hoedown_autolink__url: search for the next URL in data */
+size_t hoedown_autolink__url(size_t *rewind_p, hoedown_buffer *link,
+	uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_AUTOLINK_H **/

+ 308 - 0
modules/hoedown/hoedown/src/buffer.c

@@ -0,0 +1,308 @@
+#include "buffer.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+void *
+hoedown_malloc(size_t size)
+{
+	void *ret = malloc(size);
+
+	if (!ret) {
+		fprintf(stderr, "Allocation failed.\n");
+		abort();
+	}
+
+	return ret;
+}
+
+void *
+hoedown_calloc(size_t nmemb, size_t size)
+{
+	void *ret = calloc(nmemb, size);
+
+	if (!ret) {
+		fprintf(stderr, "Allocation failed.\n");
+		abort();
+	}
+
+	return ret;
+}
+
+void *
+hoedown_realloc(void *ptr, size_t size)
+{
+	void *ret = realloc(ptr, size);
+
+	if (!ret) {
+		fprintf(stderr, "Allocation failed.\n");
+		abort();
+	}
+
+	return ret;
+}
+
+void
+hoedown_buffer_init(
+	hoedown_buffer *buf,
+	size_t unit,
+	hoedown_realloc_callback data_realloc,
+	hoedown_free_callback data_free,
+	hoedown_free_callback buffer_free)
+{
+	assert(buf);
+
+	buf->data = NULL;
+	buf->size = buf->asize = 0;
+	buf->unit = unit;
+	buf->data_realloc = data_realloc;
+	buf->data_free = data_free;
+	buf->buffer_free = buffer_free;
+}
+
+void
+hoedown_buffer_uninit(hoedown_buffer *buf)
+{
+	assert(buf && buf->unit);
+	buf->data_free(buf->data);
+}
+
+hoedown_buffer *
+hoedown_buffer_new(size_t unit)
+{
+	hoedown_buffer *ret = hoedown_malloc(sizeof (hoedown_buffer));
+	hoedown_buffer_init(ret, unit, hoedown_realloc, free, free);
+	return ret;
+}
+
+void
+hoedown_buffer_free(hoedown_buffer *buf)
+{
+	if (!buf) return;
+	assert(buf && buf->unit);
+
+	buf->data_free(buf->data);
+
+	if (buf->buffer_free)
+		buf->buffer_free(buf);
+}
+
+void
+hoedown_buffer_reset(hoedown_buffer *buf)
+{
+	assert(buf && buf->unit);
+
+	buf->data_free(buf->data);
+	buf->data = NULL;
+	buf->size = buf->asize = 0;
+}
+
+void
+hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz)
+{
+	size_t neoasz;
+	assert(buf && buf->unit);
+
+	if (buf->asize >= neosz)
+		return;
+
+	neoasz = buf->asize + buf->unit;
+	while (neoasz < neosz)
+		neoasz += buf->unit;
+
+	buf->data = buf->data_realloc(buf->data, neoasz);
+	buf->asize = neoasz;
+}
+
+void
+hoedown_buffer_put(hoedown_buffer *buf, const uint8_t *data, size_t size)
+{
+	assert(buf && buf->unit);
+
+	if (buf->size + size > buf->asize)
+		hoedown_buffer_grow(buf, buf->size + size);
+
+	memcpy(buf->data + buf->size, data, size);
+	buf->size += size;
+}
+
+void
+hoedown_buffer_puts(hoedown_buffer *buf, const char *str)
+{
+	hoedown_buffer_put(buf, (const uint8_t *)str, strlen(str));
+}
+
+void
+hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c)
+{
+	assert(buf && buf->unit);
+
+	if (buf->size >= buf->asize)
+		hoedown_buffer_grow(buf, buf->size + 1);
+
+	buf->data[buf->size] = c;
+	buf->size += 1;
+}
+
+int
+hoedown_buffer_putf(hoedown_buffer *buf, FILE *file)
+{
+	assert(buf && buf->unit);
+
+	while (!(feof(file) || ferror(file))) {
+		hoedown_buffer_grow(buf, buf->size + buf->unit);
+		buf->size += fread(buf->data + buf->size, 1, buf->unit, file);
+	}
+
+	return ferror(file);
+}
+
+void
+hoedown_buffer_set(hoedown_buffer *buf, const uint8_t *data, size_t size)
+{
+	assert(buf && buf->unit);
+
+	if (size > buf->asize)
+		hoedown_buffer_grow(buf, size);
+
+	memcpy(buf->data, data, size);
+	buf->size = size;
+}
+
+void
+hoedown_buffer_sets(hoedown_buffer *buf, const char *str)
+{
+	hoedown_buffer_set(buf, (const uint8_t *)str, strlen(str));
+}
+
+int
+hoedown_buffer_eq(const hoedown_buffer *buf, const uint8_t *data, size_t size)
+{
+	if (buf->size != size) return 0;
+	return memcmp(buf->data, data, size) == 0;
+}
+
+int
+hoedown_buffer_eqs(const hoedown_buffer *buf, const char *str)
+{
+	return hoedown_buffer_eq(buf, (const uint8_t *)str, strlen(str));
+}
+
+int
+hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix)
+{
+	size_t i;
+
+	for (i = 0; i < buf->size; ++i) {
+		if (prefix[i] == 0)
+			return 0;
+
+		if (buf->data[i] != prefix[i])
+			return buf->data[i] - prefix[i];
+	}
+
+	return 0;
+}
+
+void
+hoedown_buffer_slurp(hoedown_buffer *buf, size_t size)
+{
+	assert(buf && buf->unit);
+
+	if (size >= buf->size) {
+		buf->size = 0;
+		return;
+	}
+
+	buf->size -= size;
+	memmove(buf->data, buf->data + size, buf->size);
+}
+
+const char *
+hoedown_buffer_cstr(hoedown_buffer *buf)
+{
+	assert(buf && buf->unit);
+
+	if (buf->size < buf->asize && buf->data[buf->size] == 0)
+		return (char *)buf->data;
+
+	hoedown_buffer_grow(buf, buf->size + 1);
+	buf->data[buf->size] = 0;
+
+	return (char *)buf->data;
+}
+
+void
+hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...)
+{
+	va_list ap;
+	int n;
+
+	assert(buf && buf->unit);
+
+	if (buf->size >= buf->asize)
+		hoedown_buffer_grow(buf, buf->size + 1);
+
+	va_start(ap, fmt);
+	n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
+	va_end(ap);
+
+	if (n < 0) {
+#ifndef _MSC_VER
+		return;
+#else
+		va_start(ap, fmt);
+		n = _vscprintf(fmt, ap);
+		va_end(ap);
+#endif
+	}
+
+	if ((size_t)n >= buf->asize - buf->size) {
+		hoedown_buffer_grow(buf, buf->size + n + 1);
+
+		va_start(ap, fmt);
+		n = vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
+		va_end(ap);
+	}
+
+	if (n < 0)
+		return;
+
+	buf->size += n;
+}
+
+void hoedown_buffer_put_utf8(hoedown_buffer *buf, unsigned int c) {
+	unsigned char unichar[4];
+
+	assert(buf && buf->unit);
+
+	if (c < 0x80) {
+		hoedown_buffer_putc(buf, c);
+	}
+	else if (c < 0x800) {
+		unichar[0] = 192 + (c / 64);
+		unichar[1] = 128 + (c % 64);
+		hoedown_buffer_put(buf, unichar, 2);
+	}
+	else if (c - 0xd800u < 0x800) {
+		HOEDOWN_BUFPUTSL(buf, "\xef\xbf\xbd");
+	}
+	else if (c < 0x10000) {
+		unichar[0] = 224 + (c / 4096);
+		unichar[1] = 128 + (c / 64) % 64;
+		unichar[2] = 128 + (c % 64);
+		hoedown_buffer_put(buf, unichar, 3);
+	}
+	else if (c < 0x110000) {
+		unichar[0] = 240 + (c / 262144);
+		unichar[1] = 128 + (c / 4096) % 64;
+		unichar[2] = 128 + (c / 64) % 64;
+		unichar[3] = 128 + (c % 64);
+		hoedown_buffer_put(buf, unichar, 4);
+	}
+	else {
+		HOEDOWN_BUFPUTSL(buf, "\xef\xbf\xbd");
+	}
+}

+ 134 - 0
modules/hoedown/hoedown/src/buffer.h

@@ -0,0 +1,134 @@
+/* buffer.h - simple, fast buffers */
+
+#ifndef HOEDOWN_BUFFER_H
+#define HOEDOWN_BUFFER_H
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_MSC_VER)
+#define __attribute__(x)
+#define inline __inline
+#define __builtin_expect(x,n) x
+#endif
+
+
+/*********
+ * TYPES *
+ *********/
+
+typedef void *(*hoedown_realloc_callback)(void *, size_t);
+typedef void (*hoedown_free_callback)(void *);
+
+struct hoedown_buffer {
+	uint8_t *data;	/* actual character data */
+	size_t size;	/* size of the string */
+	size_t asize;	/* allocated size (0 = volatile buffer) */
+	size_t unit;	/* reallocation unit size (0 = read-only buffer) */
+
+	hoedown_realloc_callback data_realloc;
+	hoedown_free_callback data_free;
+	hoedown_free_callback buffer_free;
+};
+
+typedef struct hoedown_buffer hoedown_buffer;
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* allocation wrappers */
+void *hoedown_malloc(size_t size) __attribute__ ((malloc));
+void *hoedown_calloc(size_t nmemb, size_t size) __attribute__ ((malloc));
+void *hoedown_realloc(void *ptr, size_t size) __attribute__ ((malloc));
+
+/* hoedown_buffer_init: initialize a buffer with custom allocators */
+void hoedown_buffer_init(
+	hoedown_buffer *buffer,
+	size_t unit,
+	hoedown_realloc_callback data_realloc,
+	hoedown_free_callback data_free,
+	hoedown_free_callback buffer_free
+);
+
+/* hoedown_buffer_uninit: uninitialize an existing buffer */
+void hoedown_buffer_uninit(hoedown_buffer *buf);
+
+/* hoedown_buffer_new: allocate a new buffer */
+hoedown_buffer *hoedown_buffer_new(size_t unit) __attribute__ ((malloc));
+
+/* hoedown_buffer_reset: free internal data of the buffer */
+void hoedown_buffer_reset(hoedown_buffer *buf);
+
+/* hoedown_buffer_grow: increase the allocated size to the given value */
+void hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz);
+
+/* hoedown_buffer_put: append raw data to a buffer */
+void hoedown_buffer_put(hoedown_buffer *buf, const uint8_t *data, size_t size);
+
+/* hoedown_buffer_puts: append a NUL-terminated string to a buffer */
+void hoedown_buffer_puts(hoedown_buffer *buf, const char *str);
+
+/* hoedown_buffer_putc: append a single char to a buffer */
+void hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c);
+
+/* hoedown_buffer_putf: read from a file and append to a buffer, until EOF or error */
+int hoedown_buffer_putf(hoedown_buffer *buf, FILE* file);
+
+/* hoedown_buffer_set: replace the buffer's contents with raw data */
+void hoedown_buffer_set(hoedown_buffer *buf, const uint8_t *data, size_t size);
+
+/* hoedown_buffer_sets: replace the buffer's contents with a NUL-terminated string */
+void hoedown_buffer_sets(hoedown_buffer *buf, const char *str);
+
+/* hoedown_buffer_eq: compare a buffer's data with other data for equality */
+int hoedown_buffer_eq(const hoedown_buffer *buf, const uint8_t *data, size_t size);
+
+/* hoedown_buffer_eq: compare a buffer's data with NUL-terminated string for equality */
+int hoedown_buffer_eqs(const hoedown_buffer *buf, const char *str);
+
+/* hoedown_buffer_prefix: compare the beginning of a buffer with a string */
+int hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix);
+
+/* hoedown_buffer_slurp: remove a given number of bytes from the head of the buffer */
+void hoedown_buffer_slurp(hoedown_buffer *buf, size_t size);
+
+/* hoedown_buffer_cstr: NUL-termination of the string array (making a C-string) */
+const char *hoedown_buffer_cstr(hoedown_buffer *buf);
+
+/* hoedown_buffer_printf: formatted printing to a buffer */
+void hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
+/* hoedown_buffer_put_utf8: put a Unicode character encoded as UTF-8 */
+void hoedown_buffer_put_utf8(hoedown_buffer *buf, unsigned int codepoint);
+
+/* hoedown_buffer_free: free the buffer */
+void hoedown_buffer_free(hoedown_buffer *buf);
+
+
+/* HOEDOWN_BUFPUTSL: optimized hoedown_buffer_puts of a string literal */
+#define HOEDOWN_BUFPUTSL(output, literal) \
+	hoedown_buffer_put(output, (const uint8_t *)literal, sizeof(literal) - 1)
+
+/* HOEDOWN_BUFSETSL: optimized hoedown_buffer_sets of a string literal */
+#define HOEDOWN_BUFSETSL(output, literal) \
+	hoedown_buffer_set(output, (const uint8_t *)literal, sizeof(literal) - 1)
+
+/* HOEDOWN_BUFEQSL: optimized hoedown_buffer_eqs of a string literal */
+#define HOEDOWN_BUFEQSL(output, literal) \
+	hoedown_buffer_eq(output, (const uint8_t *)literal, sizeof(literal) - 1)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_BUFFER_H **/

+ 2994 - 0
modules/hoedown/hoedown/src/document.c

@@ -0,0 +1,2994 @@
+#include "document.h"
+
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include "stack.h"
+
+#ifndef _MSC_VER
+#include <strings.h>
+#else
+#define strncasecmp	_strnicmp
+#endif
+
+#define REF_TABLE_SIZE 8
+
+#define BUFFER_BLOCK 0
+#define BUFFER_SPAN 1
+
+#define HOEDOWN_LI_END 8	/* internal list flag */
+
+const char *hoedown_find_block_tag(const char *str, unsigned int len);
+
+/***************
+ * LOCAL TYPES *
+ ***************/
+
+/* link_ref: reference to a link */
+struct link_ref {
+	unsigned int id;
+
+	hoedown_buffer *link;
+	hoedown_buffer *title;
+
+	struct link_ref *next;
+};
+
+/* footnote_ref: reference to a footnote */
+struct footnote_ref {
+	unsigned int id;
+
+	int is_used;
+	unsigned int num;
+
+	hoedown_buffer *contents;
+};
+
+/* footnote_item: an item in a footnote_list */
+struct footnote_item {
+	struct footnote_ref *ref;
+	struct footnote_item *next;
+};
+
+/* footnote_list: linked list of footnote_item */
+struct footnote_list {
+	unsigned int count;
+	struct footnote_item *head;
+	struct footnote_item *tail;
+};
+
+/* char_trigger: function pointer to render active chars */
+/*   returns the number of chars taken care of */
+/*   data is the pointer of the beginning of the span */
+/*   offset is the number of valid chars before data */
+typedef size_t
+(*char_trigger)(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+
+static size_t char_emphasis(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_autolink_url(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_autolink_www(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+static size_t char_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size);
+
+enum markdown_char_t {
+	MD_CHAR_NONE = 0,
+	MD_CHAR_EMPHASIS,
+	MD_CHAR_CODESPAN,
+	MD_CHAR_LINEBREAK,
+	MD_CHAR_LINK,
+	MD_CHAR_LANGLE,
+	MD_CHAR_ESCAPE,
+	MD_CHAR_ENTITY,
+	MD_CHAR_AUTOLINK_URL,
+	MD_CHAR_AUTOLINK_EMAIL,
+	MD_CHAR_AUTOLINK_WWW,
+	MD_CHAR_SUPERSCRIPT,
+	MD_CHAR_QUOTE,
+	MD_CHAR_MATH
+};
+
+static char_trigger markdown_char_ptrs[] = {
+	NULL,
+	&char_emphasis,
+	&char_codespan,
+	&char_linebreak,
+	&char_link,
+	&char_langle_tag,
+	&char_escape,
+	&char_entity,
+	&char_autolink_url,
+	&char_autolink_email,
+	&char_autolink_www,
+	&char_superscript,
+	&char_quote,
+	&char_math
+};
+
+struct hoedown_document {
+	hoedown_renderer md;
+	hoedown_renderer_data data;
+
+	struct link_ref *refs[REF_TABLE_SIZE];
+	struct footnote_list footnotes_found;
+	struct footnote_list footnotes_used;
+	uint8_t active_char[256];
+	hoedown_stack work_bufs[2];
+	hoedown_extensions ext_flags;
+	size_t max_nesting;
+	int in_link_body;
+};
+
+/***************************
+ * HELPER FUNCTIONS *
+ ***************************/
+
+static hoedown_buffer *
+newbuf(hoedown_document *doc, int type)
+{
+	static const size_t buf_size[2] = {256, 64};
+	hoedown_buffer *work = NULL;
+	hoedown_stack *pool = &doc->work_bufs[type];
+
+	if (pool->size < pool->asize &&
+		pool->item[pool->size] != NULL) {
+		work = pool->item[pool->size++];
+		work->size = 0;
+	} else {
+		work = hoedown_buffer_new(buf_size[type]);
+		hoedown_stack_push(pool, work);
+	}
+
+	return work;
+}
+
+static void
+popbuf(hoedown_document *doc, int type)
+{
+	doc->work_bufs[type].size--;
+}
+
+static void
+unscape_text(hoedown_buffer *ob, hoedown_buffer *src)
+{
+	size_t i = 0, org;
+	while (i < src->size) {
+		org = i;
+		while (i < src->size && src->data[i] != '\\')
+			i++;
+
+		if (i > org)
+			hoedown_buffer_put(ob, src->data + org, i - org);
+
+		if (i + 1 >= src->size)
+			break;
+
+		hoedown_buffer_putc(ob, src->data[i + 1]);
+		i += 2;
+	}
+}
+
+static unsigned int
+hash_link_ref(const uint8_t *link_ref, size_t length)
+{
+	size_t i;
+	unsigned int hash = 0;
+
+	for (i = 0; i < length; ++i)
+		hash = tolower(link_ref[i]) + (hash << 6) + (hash << 16) - hash;
+
+	return hash;
+}
+
+static struct link_ref *
+add_link_ref(
+	struct link_ref **references,
+	const uint8_t *name, size_t name_size)
+{
+	struct link_ref *ref = hoedown_calloc(1, sizeof(struct link_ref));
+
+	ref->id = hash_link_ref(name, name_size);
+	ref->next = references[ref->id % REF_TABLE_SIZE];
+
+	references[ref->id % REF_TABLE_SIZE] = ref;
+	return ref;
+}
+
+static struct link_ref *
+find_link_ref(struct link_ref **references, uint8_t *name, size_t length)
+{
+	unsigned int hash = hash_link_ref(name, length);
+	struct link_ref *ref = NULL;
+
+	ref = references[hash % REF_TABLE_SIZE];
+
+	while (ref != NULL) {
+		if (ref->id == hash)
+			return ref;
+
+		ref = ref->next;
+	}
+
+	return NULL;
+}
+
+static void
+free_link_refs(struct link_ref **references)
+{
+	size_t i;
+
+	for (i = 0; i < REF_TABLE_SIZE; ++i) {
+		struct link_ref *r = references[i];
+		struct link_ref *next;
+
+		while (r) {
+			next = r->next;
+			hoedown_buffer_free(r->link);
+			hoedown_buffer_free(r->title);
+			free(r);
+			r = next;
+		}
+	}
+}
+
+static struct footnote_ref *
+create_footnote_ref(struct footnote_list *list, const uint8_t *name, size_t name_size)
+{
+	struct footnote_ref *ref = hoedown_calloc(1, sizeof(struct footnote_ref));
+
+	ref->id = hash_link_ref(name, name_size);
+
+	return ref;
+}
+
+static int
+add_footnote_ref(struct footnote_list *list, struct footnote_ref *ref)
+{
+	struct footnote_item *item = hoedown_calloc(1, sizeof(struct footnote_item));
+	if (!item)
+		return 0;
+	item->ref = ref;
+
+	if (list->head == NULL) {
+		list->head = list->tail = item;
+	} else {
+		list->tail->next = item;
+		list->tail = item;
+	}
+	list->count++;
+
+	return 1;
+}
+
+static struct footnote_ref *
+find_footnote_ref(struct footnote_list *list, uint8_t *name, size_t length)
+{
+	unsigned int hash = hash_link_ref(name, length);
+	struct footnote_item *item = NULL;
+
+	item = list->head;
+
+	while (item != NULL) {
+		if (item->ref->id == hash)
+			return item->ref;
+		item = item->next;
+	}
+
+	return NULL;
+}
+
+static void
+free_footnote_ref(struct footnote_ref *ref)
+{
+	hoedown_buffer_free(ref->contents);
+	free(ref);
+}
+
+static void
+free_footnote_list(struct footnote_list *list, int free_refs)
+{
+	struct footnote_item *item = list->head;
+	struct footnote_item *next;
+
+	while (item) {
+		next = item->next;
+		if (free_refs)
+			free_footnote_ref(item->ref);
+		free(item);
+		item = next;
+	}
+}
+
+
+/*
+ * Check whether a char is a Markdown spacing char.
+
+ * Right now we only consider spaces the actual
+ * space and a newline: tabs and carriage returns
+ * are filtered out during the preprocessing phase.
+ *
+ * If we wanted to actually be UTF-8 compliant, we
+ * should instead extract an Unicode codepoint from
+ * this character and check for space properties.
+ */
+static int
+_isspace(int c)
+{
+	return c == ' ' || c == '\n';
+}
+
+/* is_empty_all: verify that all the data is spacing */
+static int
+is_empty_all(const uint8_t *data, size_t size)
+{
+	size_t i = 0;
+	while (i < size && _isspace(data[i])) i++;
+	return i == size;
+}
+
+/*
+ * Replace all spacing characters in data with spaces. As a special
+ * case, this collapses a newline with the previous space, if possible.
+ */
+static void
+replace_spacing(hoedown_buffer *ob, const uint8_t *data, size_t size)
+{
+	size_t i = 0, mark;
+	hoedown_buffer_grow(ob, size);
+	while (1) {
+		mark = i;
+		while (i < size && data[i] != '\n') i++;
+		hoedown_buffer_put(ob, data + mark, i - mark);
+
+		if (i >= size) break;
+
+		if (!(i > 0 && data[i-1] == ' '))
+			hoedown_buffer_putc(ob, ' ');
+		i++;
+	}
+}
+
+/****************************
+ * INLINE PARSING FUNCTIONS *
+ ****************************/
+
+/* is_mail_autolink • looks for the address part of a mail autolink and '>' */
+/* this is less strict than the original markdown e-mail address matching */
+static size_t
+is_mail_autolink(uint8_t *data, size_t size)
+{
+	size_t i = 0, nb = 0;
+
+	/* address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@' */
+	for (i = 0; i < size; ++i) {
+		if (isalnum(data[i]))
+			continue;
+
+		switch (data[i]) {
+			case '@':
+				nb++;
+
+			case '-':
+			case '.':
+			case '_':
+				break;
+
+			case '>':
+				return (nb == 1) ? i + 1 : 0;
+
+			default:
+				return 0;
+		}
+	}
+
+	return 0;
+}
+
+/* tag_length • returns the length of the given tag, or 0 is it's not valid */
+static size_t
+tag_length(uint8_t *data, size_t size, hoedown_autolink_type *autolink)
+{
+	size_t i, j;
+
+	/* a valid tag can't be shorter than 3 chars */
+	if (size < 3) return 0;
+
+	if (data[0] != '<') return 0;
+
+        /* HTML comment, laxist form */
+        if (size > 5 && data[1] == '!' && data[2] == '-' && data[3] == '-') {
+		i = 5;
+
+		while (i < size && !(data[i - 2] == '-' && data[i - 1] == '-' && data[i] == '>'))
+			i++;
+
+		i++;
+
+		if (i <= size)
+			return i;
+        }
+
+	/* begins with a '<' optionally followed by '/', followed by letter or number */
+        i = (data[1] == '/') ? 2 : 1;
+
+	if (!isalnum(data[i]))
+		return 0;
+
+	/* scheme test */
+	*autolink = HOEDOWN_AUTOLINK_NONE;
+
+	/* try to find the beginning of an URI */
+	while (i < size && (isalnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-'))
+		i++;
+
+	if (i > 1 && data[i] == '@') {
+		if ((j = is_mail_autolink(data + i, size - i)) != 0) {
+			*autolink = HOEDOWN_AUTOLINK_EMAIL;
+			return i + j;
+		}
+	}
+
+	if (i > 2 && data[i] == ':') {
+		*autolink = HOEDOWN_AUTOLINK_NORMAL;
+		i++;
+	}
+
+	/* completing autolink test: no spacing or ' or " */
+	if (i >= size)
+		*autolink = HOEDOWN_AUTOLINK_NONE;
+
+	else if (*autolink) {
+		j = i;
+
+		while (i < size) {
+			if (data[i] == '\\') i += 2;
+			else if (data[i] == '>' || data[i] == '\'' ||
+					data[i] == '"' || data[i] == ' ' || data[i] == '\n')
+					break;
+			else i++;
+		}
+
+		if (i >= size) return 0;
+		if (i > j && data[i] == '>') return i + 1;
+		/* one of the forbidden chars has been found */
+		*autolink = HOEDOWN_AUTOLINK_NONE;
+	}
+
+	/* looking for something looking like a tag end */
+	while (i < size && data[i] != '>') i++;
+	if (i >= size) return 0;
+	return i + 1;
+}
+
+/* parse_inline • parses inline markdown elements */
+static void
+parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
+{
+	size_t i = 0, end = 0, consumed = 0;
+	hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
+	uint8_t *active_char = doc->active_char;
+
+	if (doc->work_bufs[BUFFER_SPAN].size +
+		doc->work_bufs[BUFFER_BLOCK].size > doc->max_nesting)
+		return;
+
+	while (i < size) {
+		/* copying inactive chars into the output */
+		while (end < size && active_char[data[end]] == 0)
+			end++;
+
+		if (doc->md.normal_text) {
+			work.data = data + i;
+			work.size = end - i;
+			doc->md.normal_text(ob, &work, &doc->data);
+		}
+		else
+			hoedown_buffer_put(ob, data + i, end - i);
+
+		if (end >= size) break;
+		i = end;
+
+		end = markdown_char_ptrs[ (int)active_char[data[end]] ](ob, doc, data + i, i - consumed, size - i);
+		if (!end) /* no action from the callback */
+			end = i + 1;
+		else {
+			i += end;
+			end = i;
+			consumed = i;
+		}
+	}
+}
+
+/* is_escaped • returns whether special char at data[loc] is escaped by '\\' */
+static int
+is_escaped(uint8_t *data, size_t loc)
+{
+	size_t i = loc;
+	while (i >= 1 && data[i - 1] == '\\')
+		i--;
+
+	/* odd numbers of backslashes escapes data[loc] */
+	return (loc - i) % 2;
+}
+
+/* find_emph_char • looks for the next emph uint8_t, skipping other constructs */
+static size_t
+find_emph_char(uint8_t *data, size_t size, uint8_t c)
+{
+	size_t i = 0;
+
+	while (i < size) {
+		while (i < size && data[i] != c && data[i] != '[' && data[i] != '`')
+			i++;
+
+		if (i == size)
+			return 0;
+
+		/* not counting escaped chars */
+		if (is_escaped(data, i)) {
+			i++; continue;
+		}
+
+		if (data[i] == c)
+			return i;
+
+		/* skipping a codespan */
+		if (data[i] == '`') {
+			size_t span_nb = 0, bt;
+			size_t tmp_i = 0;
+
+			/* counting the number of opening backticks */
+			while (i < size && data[i] == '`') {
+				i++; span_nb++;
+			}
+
+			if (i >= size) return 0;
+
+			/* finding the matching closing sequence */
+			bt = 0;
+			while (i < size && bt < span_nb) {
+				if (!tmp_i && data[i] == c) tmp_i = i;
+				if (data[i] == '`') bt++;
+				else bt = 0;
+				i++;
+			}
+
+			/* not a well-formed codespan; use found matching emph char */
+			if (bt < span_nb && i >= size) return tmp_i;
+		}
+		/* skipping a link */
+		else if (data[i] == '[') {
+			size_t tmp_i = 0;
+			uint8_t cc;
+
+			i++;
+			while (i < size && data[i] != ']') {
+				if (!tmp_i && data[i] == c) tmp_i = i;
+				i++;
+			}
+
+			i++;
+			while (i < size && _isspace(data[i]))
+				i++;
+
+			if (i >= size)
+				return tmp_i;
+
+			switch (data[i]) {
+			case '[':
+				cc = ']'; break;
+
+			case '(':
+				cc = ')'; break;
+
+			default:
+				if (tmp_i)
+					return tmp_i;
+				else
+					continue;
+			}
+
+			i++;
+			while (i < size && data[i] != cc) {
+				if (!tmp_i && data[i] == c) tmp_i = i;
+				i++;
+			}
+
+			if (i >= size)
+				return tmp_i;
+
+			i++;
+		}
+	}
+
+	return 0;
+}
+
+/* parse_emph1 • parsing single emphase */
+/* closed by a symbol not preceded by spacing and not followed by symbol */
+static size_t
+parse_emph1(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c)
+{
+	size_t i = 0, len;
+	hoedown_buffer *work = 0;
+	int r;
+
+	/* skipping one symbol if coming from emph3 */
+	if (size > 1 && data[0] == c && data[1] == c) i = 1;
+
+	while (i < size) {
+		len = find_emph_char(data + i, size - i, c);
+		if (!len) return 0;
+		i += len;
+		if (i >= size) return 0;
+
+		if (data[i] == c && !_isspace(data[i - 1])) {
+
+			if (doc->ext_flags & HOEDOWN_EXT_NO_INTRA_EMPHASIS) {
+				if (i + 1 < size && isalnum(data[i + 1]))
+					continue;
+			}
+
+			work = newbuf(doc, BUFFER_SPAN);
+			parse_inline(work, doc, data, i);
+
+			if (doc->ext_flags & HOEDOWN_EXT_UNDERLINE && c == '_')
+				r = doc->md.underline(ob, work, &doc->data);
+			else
+				r = doc->md.emphasis(ob, work, &doc->data);
+
+			popbuf(doc, BUFFER_SPAN);
+			return r ? i + 1 : 0;
+		}
+	}
+
+	return 0;
+}
+
+/* parse_emph2 • parsing single emphase */
+static size_t
+parse_emph2(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c)
+{
+	size_t i = 0, len;
+	hoedown_buffer *work = 0;
+	int r;
+
+	while (i < size) {
+		len = find_emph_char(data + i, size - i, c);
+		if (!len) return 0;
+		i += len;
+
+		if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !_isspace(data[i - 1])) {
+			work = newbuf(doc, BUFFER_SPAN);
+			parse_inline(work, doc, data, i);
+
+			if (c == '~')
+				r = doc->md.strikethrough(ob, work, &doc->data);
+			else if (c == '=')
+				r = doc->md.highlight(ob, work, &doc->data);
+			else
+				r = doc->md.double_emphasis(ob, work, &doc->data);
+
+			popbuf(doc, BUFFER_SPAN);
+			return r ? i + 2 : 0;
+		}
+		i++;
+	}
+	return 0;
+}
+
+/* parse_emph3 • parsing single emphase */
+/* finds the first closing tag, and delegates to the other emph */
+static size_t
+parse_emph3(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c)
+{
+	size_t i = 0, len;
+	int r;
+
+	while (i < size) {
+		len = find_emph_char(data + i, size - i, c);
+		if (!len) return 0;
+		i += len;
+
+		/* skip spacing preceded symbols */
+		if (data[i] != c || _isspace(data[i - 1]))
+			continue;
+
+		if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && doc->md.triple_emphasis) {
+			/* triple symbol found */
+			hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
+
+			parse_inline(work, doc, data, i);
+			r = doc->md.triple_emphasis(ob, work, &doc->data);
+			popbuf(doc, BUFFER_SPAN);
+			return r ? i + 3 : 0;
+
+		} else if (i + 1 < size && data[i + 1] == c) {
+			/* double symbol found, handing over to emph1 */
+			len = parse_emph1(ob, doc, data - 2, size + 2, c);
+			if (!len) return 0;
+			else return len - 2;
+
+		} else {
+			/* single symbol found, handing over to emph2 */
+			len = parse_emph2(ob, doc, data - 1, size + 1, c);
+			if (!len) return 0;
+			else return len - 1;
+		}
+	}
+	return 0;
+}
+
+/* parse_math • parses a math span until the given ending delimiter */
+static size_t
+parse_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, const char *end, size_t delimsz, int displaymode)
+{
+	hoedown_buffer text = { NULL, 0, 0, 0, NULL, NULL, NULL };
+	size_t i = delimsz;
+
+	if (!doc->md.math)
+		return 0;
+
+	/* find ending delimiter */
+	while (1) {
+		while (i < size && data[i] != (uint8_t)end[0])
+			i++;
+
+		if (i >= size)
+			return 0;
+
+		if (!is_escaped(data, i) && !(i + delimsz > size)
+			&& memcmp(data + i, end, delimsz) == 0)
+			break;
+
+		i++;
+	}
+
+	/* prepare buffers */
+	text.data = data + delimsz;
+	text.size = i - delimsz;
+
+	/* if this is a $$ and MATH_EXPLICIT is not active,
+	 * guess whether displaymode should be enabled from the context */
+	i += delimsz;
+	if (delimsz == 2 && !(doc->ext_flags & HOEDOWN_EXT_MATH_EXPLICIT))
+		displaymode = is_empty_all(data - offset, offset) && is_empty_all(data + i, size - i);
+
+	/* call callback */
+	if (doc->md.math(ob, &text, displaymode, &doc->data))
+		return i;
+
+	return 0;
+}
+
+/* char_emphasis • single and double emphasis parsing */
+static size_t
+char_emphasis(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	uint8_t c = data[0];
+	size_t ret;
+
+	if (doc->ext_flags & HOEDOWN_EXT_NO_INTRA_EMPHASIS) {
+		if (offset > 0 && !_isspace(data[-1]) && data[-1] != '>' && data[-1] != '(')
+			return 0;
+	}
+
+	if (size > 2 && data[1] != c) {
+		/* spacing cannot follow an opening emphasis;
+		 * strikethrough and highlight only takes two characters '~~' */
+		if (c == '~' || c == '=' || _isspace(data[1]) || (ret = parse_emph1(ob, doc, data + 1, size - 1, c)) == 0)
+			return 0;
+
+		return ret + 1;
+	}
+
+	if (size > 3 && data[1] == c && data[2] != c) {
+		if (_isspace(data[2]) || (ret = parse_emph2(ob, doc, data + 2, size - 2, c)) == 0)
+			return 0;
+
+		return ret + 2;
+	}
+
+	if (size > 4 && data[1] == c && data[2] == c && data[3] != c) {
+		if (c == '~' || c == '=' || _isspace(data[3]) || (ret = parse_emph3(ob, doc, data + 3, size - 3, c)) == 0)
+			return 0;
+
+		return ret + 3;
+	}
+
+	return 0;
+}
+
+
+/* char_linebreak • '\n' preceded by two spaces (assuming linebreak != 0) */
+static size_t
+char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	if (offset < 2 || data[-1] != ' ' || data[-2] != ' ')
+		return 0;
+
+	/* removing the last space from ob and rendering */
+	while (ob->size && ob->data[ob->size - 1] == ' ')
+		ob->size--;
+
+	return doc->md.linebreak(ob, &doc->data) ? 1 : 0;
+}
+
+
+/* char_codespan • '`' parsing a code span (assuming codespan != 0) */
+static size_t
+char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
+	size_t end, nb = 0, i, f_begin, f_end;
+
+	/* counting the number of backticks in the delimiter */
+	while (nb < size && data[nb] == '`')
+		nb++;
+
+	/* finding the next delimiter */
+	i = 0;
+	for (end = nb; end < size && i < nb; end++) {
+		if (data[end] == '`') i++;
+		else i = 0;
+	}
+
+	if (i < nb && end >= size)
+		return 0; /* no matching delimiter */
+
+	/* trimming outside spaces */
+	f_begin = nb;
+	while (f_begin < end && data[f_begin] == ' ')
+		f_begin++;
+
+	f_end = end - nb;
+	while (f_end > nb && data[f_end-1] == ' ')
+		f_end--;
+
+	/* real code span */
+	if (f_begin < f_end) {
+		work.data = data + f_begin;
+		work.size = f_end - f_begin;
+
+		if (!doc->md.codespan(ob, &work, &doc->data))
+			end = 0;
+	} else {
+		if (!doc->md.codespan(ob, 0, &doc->data))
+			end = 0;
+	}
+
+	return end;
+}
+
+/* char_quote • '"' parsing a quote */
+static size_t
+char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	size_t end, nq = 0, i, f_begin, f_end;
+
+	/* counting the number of quotes in the delimiter */
+	while (nq < size && data[nq] == '"')
+		nq++;
+
+	/* finding the next delimiter */
+	end = nq;
+	while (1) {
+		i = end;
+		end += find_emph_char(data + end, size - end, '"');
+		if (end == i) return 0;		/* no matching delimiter */
+		i = end;
+		while (end < size && data[end] == '"' && end - i < nq) end++;
+		if (end - i >= nq) break;
+	}
+
+	/* trimming outside spaces */
+	f_begin = nq;
+	while (f_begin < end && data[f_begin] == ' ')
+		f_begin++;
+
+	f_end = end - nq;
+	while (f_end > nq && data[f_end-1] == ' ')
+		f_end--;
+
+	/* real quote */
+	if (f_begin < f_end) {
+		hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
+		parse_inline(work, doc, data + f_begin, f_end - f_begin);
+
+		if (!doc->md.quote(ob, work, &doc->data))
+			end = 0;
+		popbuf(doc, BUFFER_SPAN);
+	} else {
+		if (!doc->md.quote(ob, 0, &doc->data))
+			end = 0;
+	}
+
+	return end;
+}
+
+
+/* char_escape • '\\' backslash escape */
+static size_t
+char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>^~=\"$";
+	hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
+	size_t w;
+
+	if (size > 1) {
+		if (data[1] == '\\' && (doc->ext_flags & HOEDOWN_EXT_MATH) &&
+			size > 2 && (data[2] == '(' || data[2] == '[')) {
+			const char *end = (data[2] == '[') ? "\\\\]" : "\\\\)";
+			w = parse_math(ob, doc, data, offset, size, end, 3, data[2] == '[');
+			if (w) return w;
+		}
+
+		if (strchr(escape_chars, data[1]) == NULL)
+			return 0;
+
+		if (doc->md.normal_text) {
+			work.data = data + 1;
+			work.size = 1;
+			doc->md.normal_text(ob, &work, &doc->data);
+		}
+		else hoedown_buffer_putc(ob, data[1]);
+	} else if (size == 1) {
+		hoedown_buffer_putc(ob, data[0]);
+	}
+
+	return 2;
+}
+
+/* char_entity • '&' escaped when it doesn't belong to an entity */
+/* valid entities are assumed to be anything matching &#?[A-Za-z0-9]+; */
+static size_t
+char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	size_t end = 1;
+	hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL };
+
+	if (end < size && data[end] == '#')
+		end++;
+
+	while (end < size && isalnum(data[end]))
+		end++;
+
+	if (end < size && data[end] == ';')
+		end++; /* real entity */
+	else
+		return 0; /* lone '&' */
+
+	if (doc->md.entity) {
+		work.data = data;
+		work.size = end;
+		doc->md.entity(ob, &work, &doc->data);
+	}
+	else hoedown_buffer_put(ob, data, end);
+
+	return end;
+}
+
+/* char_langle_tag • '<' when tags or autolinks are allowed */
+static size_t
+char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
+	hoedown_autolink_type altype = HOEDOWN_AUTOLINK_NONE;
+	size_t end = tag_length(data, size, &altype);
+	int ret = 0;
+
+	work.data = data;
+	work.size = end;
+
+	if (end > 2) {
+		if (doc->md.autolink && altype != HOEDOWN_AUTOLINK_NONE) {
+			hoedown_buffer *u_link = newbuf(doc, BUFFER_SPAN);
+			work.data = data + 1;
+			work.size = end - 2;
+			unscape_text(u_link, &work);
+			ret = doc->md.autolink(ob, u_link, altype, &doc->data);
+			popbuf(doc, BUFFER_SPAN);
+		}
+		else if (doc->md.raw_html)
+			ret = doc->md.raw_html(ob, &work, &doc->data);
+	}
+
+	if (!ret) return 0;
+	else return end;
+}
+
+static size_t
+char_autolink_www(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	hoedown_buffer *link, *link_url, *link_text;
+	size_t link_len, rewind;
+
+	if (!doc->md.link || doc->in_link_body)
+		return 0;
+
+	link = newbuf(doc, BUFFER_SPAN);
+
+	if ((link_len = hoedown_autolink__www(&rewind, link, data, offset, size, HOEDOWN_AUTOLINK_SHORT_DOMAINS)) > 0) {
+		link_url = newbuf(doc, BUFFER_SPAN);
+		HOEDOWN_BUFPUTSL(link_url, "http://");
+		hoedown_buffer_put(link_url, link->data, link->size);
+
+		if (ob->size > rewind)
+			ob->size -= rewind;
+		else
+			ob->size = 0;
+
+		if (doc->md.normal_text) {
+			link_text = newbuf(doc, BUFFER_SPAN);
+			doc->md.normal_text(link_text, link, &doc->data);
+			doc->md.link(ob, link_text, link_url, NULL, &doc->data);
+			popbuf(doc, BUFFER_SPAN);
+		} else {
+			doc->md.link(ob, link, link_url, NULL, &doc->data);
+		}
+		popbuf(doc, BUFFER_SPAN);
+	}
+
+	popbuf(doc, BUFFER_SPAN);
+	return link_len;
+}
+
+static size_t
+char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	hoedown_buffer *link;
+	size_t link_len, rewind;
+
+	if (!doc->md.autolink || doc->in_link_body)
+		return 0;
+
+	link = newbuf(doc, BUFFER_SPAN);
+
+	if ((link_len = hoedown_autolink__email(&rewind, link, data, offset, size, 0)) > 0) {
+		if (ob->size > rewind)
+			ob->size -= rewind;
+		else
+			ob->size = 0;
+
+		doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_EMAIL, &doc->data);
+	}
+
+	popbuf(doc, BUFFER_SPAN);
+	return link_len;
+}
+
+static size_t
+char_autolink_url(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	hoedown_buffer *link;
+	size_t link_len, rewind;
+
+	if (!doc->md.autolink || doc->in_link_body)
+		return 0;
+
+	link = newbuf(doc, BUFFER_SPAN);
+
+	if ((link_len = hoedown_autolink__url(&rewind, link, data, offset, size, 0)) > 0) {
+		if (ob->size > rewind)
+			ob->size -= rewind;
+		else
+			ob->size = 0;
+
+		doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_NORMAL, &doc->data);
+	}
+
+	popbuf(doc, BUFFER_SPAN);
+	return link_len;
+}
+
+/* char_link • '[': parsing a link, a footnote or an image */
+static size_t
+char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	int is_img = (offset && data[-1] == '!' && !is_escaped(data - offset, offset - 1));
+	int is_footnote = (doc->ext_flags & HOEDOWN_EXT_FOOTNOTES && data[1] == '^');
+	size_t i = 1, txt_e, link_b = 0, link_e = 0, title_b = 0, title_e = 0;
+	hoedown_buffer *content = NULL;
+	hoedown_buffer *link = NULL;
+	hoedown_buffer *title = NULL;
+	hoedown_buffer *u_link = NULL;
+	size_t org_work_size = doc->work_bufs[BUFFER_SPAN].size;
+	int ret = 0, in_title = 0, qtype = 0;
+
+	/* checking whether the correct renderer exists */
+	if ((is_footnote && !doc->md.footnote_ref) || (is_img && !doc->md.image)
+		|| (!is_img && !is_footnote && !doc->md.link))
+		goto cleanup;
+
+	/* looking for the matching closing bracket */
+	i += find_emph_char(data + i, size - i, ']');
+	txt_e = i;
+
+	if (i < size && data[i] == ']') i++;
+	else goto cleanup;
+
+	/* footnote link */
+	if (is_footnote) {
+		hoedown_buffer id = { NULL, 0, 0, 0, NULL, NULL, NULL };
+		struct footnote_ref *fr;
+
+		if (txt_e < 3)
+			goto cleanup;
+
+		id.data = data + 2;
+		id.size = txt_e - 2;
+
+		fr = find_footnote_ref(&doc->footnotes_found, id.data, id.size);
+
+		/* mark footnote used */
+		if (fr && !fr->is_used) {
+			if(!add_footnote_ref(&doc->footnotes_used, fr))
+				goto cleanup;
+			fr->is_used = 1;
+			fr->num = doc->footnotes_used.count;
+
+			/* render */
+			if (doc->md.footnote_ref)
+				ret = doc->md.footnote_ref(ob, fr->num, &doc->data);
+		}
+
+		goto cleanup;
+	}
+
+	/* skip any amount of spacing */
+	/* (this is much more laxist than original markdown syntax) */
+	while (i < size && _isspace(data[i]))
+		i++;
+
+	/* inline style link */
+	if (i < size && data[i] == '(') {
+		size_t nb_p;
+
+		/* skipping initial spacing */
+		i++;
+
+		while (i < size && _isspace(data[i]))
+			i++;
+
+		link_b = i;
+
+		/* looking for link end: ' " ) */
+		/* Count the number of open parenthesis */
+		nb_p = 0;
+
+		while (i < size) {
+			if (data[i] == '\\') i += 2;
+			else if (data[i] == '(' && i != 0) {
+				nb_p++; i++;
+			}
+			else if (data[i] == ')') {
+				if (nb_p == 0) break;
+				else nb_p--; i++;
+			} else if (i >= 1 && _isspace(data[i-1]) && (data[i] == '\'' || data[i] == '"')) break;
+			else i++;
+		}
+
+		if (i >= size) goto cleanup;
+		link_e = i;
+
+		/* looking for title end if present */
+		if (data[i] == '\'' || data[i] == '"') {
+			qtype = data[i];
+			in_title = 1;
+			i++;
+			title_b = i;
+
+			while (i < size) {
+				if (data[i] == '\\') i += 2;
+				else if (data[i] == qtype) {in_title = 0; i++;}
+				else if ((data[i] == ')') && !in_title) break;
+				else i++;
+			}
+
+			if (i >= size) goto cleanup;
+
+			/* skipping spacing after title */
+			title_e = i - 1;
+			while (title_e > title_b && _isspace(data[title_e]))
+				title_e--;
+
+			/* checking for closing quote presence */
+			if (data[title_e] != '\'' &&  data[title_e] != '"') {
+				title_b = title_e = 0;
+				link_e = i;
+			}
+		}
+
+		/* remove spacing at the end of the link */
+		while (link_e > link_b && _isspace(data[link_e - 1]))
+			link_e--;
+
+		/* remove optional angle brackets around the link */
+		if (data[link_b] == '<' && data[link_e - 1] == '>') {
+			link_b++;
+			link_e--;
+		}
+
+		/* building escaped link and title */
+		if (link_e > link_b) {
+			link = newbuf(doc, BUFFER_SPAN);
+			hoedown_buffer_put(link, data + link_b, link_e - link_b);
+		}
+
+		if (title_e > title_b) {
+			title = newbuf(doc, BUFFER_SPAN);
+			hoedown_buffer_put(title, data + title_b, title_e - title_b);
+		}
+
+		i++;
+	}
+
+	/* reference style link */
+	else if (i < size && data[i] == '[') {
+		hoedown_buffer *id = newbuf(doc, BUFFER_SPAN);
+		struct link_ref *lr;
+
+		/* looking for the id */
+		i++;
+		link_b = i;
+		while (i < size && data[i] != ']') i++;
+		if (i >= size) goto cleanup;
+		link_e = i;
+
+		/* finding the link_ref */
+		if (link_b == link_e)
+			replace_spacing(id, data + 1, txt_e - 1);
+		else
+			hoedown_buffer_put(id, data + link_b, link_e - link_b);
+
+		lr = find_link_ref(doc->refs, id->data, id->size);
+		if (!lr)
+			goto cleanup;
+
+		/* keeping link and title from link_ref */
+		link = lr->link;
+		title = lr->title;
+		i++;
+	}
+
+	/* shortcut reference style link */
+	else {
+		hoedown_buffer *id = newbuf(doc, BUFFER_SPAN);
+		struct link_ref *lr;
+
+		/* crafting the id */
+		replace_spacing(id, data + 1, txt_e - 1);
+
+		/* finding the link_ref */
+		lr = find_link_ref(doc->refs, id->data, id->size);
+		if (!lr)
+			goto cleanup;
+
+		/* keeping link and title from link_ref */
+		link = lr->link;
+		title = lr->title;
+
+		/* rewinding the spacing */
+		i = txt_e + 1;
+	}
+
+	/* building content: img alt is kept, only link content is parsed */
+	if (txt_e > 1) {
+		content = newbuf(doc, BUFFER_SPAN);
+		if (is_img) {
+			hoedown_buffer_put(content, data + 1, txt_e - 1);
+		} else {
+			/* disable autolinking when parsing inline the
+			 * content of a link */
+			doc->in_link_body = 1;
+			parse_inline(content, doc, data + 1, txt_e - 1);
+			doc->in_link_body = 0;
+		}
+	}
+
+	if (link) {
+		u_link = newbuf(doc, BUFFER_SPAN);
+		unscape_text(u_link, link);
+	}
+
+	/* calling the relevant rendering function */
+	if (is_img) {
+		if (ob->size && ob->data[ob->size - 1] == '!')
+			ob->size -= 1;
+
+		ret = doc->md.image(ob, u_link, title, content, &doc->data);
+	} else {
+		ret = doc->md.link(ob, content, u_link, title, &doc->data);
+	}
+
+	/* cleanup */
+cleanup:
+	doc->work_bufs[BUFFER_SPAN].size = (int)org_work_size;
+	return ret ? i : 0;
+}
+
+static size_t
+char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	size_t sup_start, sup_len;
+	hoedown_buffer *sup;
+
+	if (!doc->md.superscript)
+		return 0;
+
+	if (size < 2)
+		return 0;
+
+	if (data[1] == '(') {
+		sup_start = 2;
+		sup_len = find_emph_char(data + 2, size - 2, ')') + 2;
+
+		if (sup_len == size)
+			return 0;
+	} else {
+		sup_start = sup_len = 1;
+
+		while (sup_len < size && !_isspace(data[sup_len]))
+			sup_len++;
+	}
+
+	if (sup_len - sup_start == 0)
+		return (sup_start == 2) ? 3 : 0;
+
+	sup = newbuf(doc, BUFFER_SPAN);
+	parse_inline(sup, doc, data + sup_start, sup_len - sup_start);
+	doc->md.superscript(ob, sup, &doc->data);
+	popbuf(doc, BUFFER_SPAN);
+
+	return (sup_start == 2) ? sup_len + 1 : sup_len;
+}
+
+static size_t
+char_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size)
+{
+	/* double dollar */
+	if (size > 1 && data[1] == '$')
+		return parse_math(ob, doc, data, offset, size, "$$", 2, 1);
+
+	/* single dollar allowed only with MATH_EXPLICIT flag */
+	if (doc->ext_flags & HOEDOWN_EXT_MATH_EXPLICIT)
+		return parse_math(ob, doc, data, offset, size, "$", 1, 0);
+
+	return 0;
+}
+
+/*********************************
+ * BLOCK-LEVEL PARSING FUNCTIONS *
+ *********************************/
+
+/* is_empty • returns the line length when it is empty, 0 otherwise */
+static size_t
+is_empty(const uint8_t *data, size_t size)
+{
+	size_t i;
+
+	for (i = 0; i < size && data[i] != '\n'; i++)
+		if (data[i] != ' ')
+			return 0;
+
+	return i + 1;
+}
+
+/* is_hrule • returns whether a line is a horizontal rule */
+static int
+is_hrule(uint8_t *data, size_t size)
+{
+	size_t i = 0, n = 0;
+	uint8_t c;
+
+	/* skipping initial spaces */
+	if (size < 3) return 0;
+	if (data[0] == ' ') { i++;
+	if (data[1] == ' ') { i++;
+	if (data[2] == ' ') { i++; } } }
+
+	/* looking at the hrule uint8_t */
+	if (i + 2 >= size
+	|| (data[i] != '*' && data[i] != '-' && data[i] != '_'))
+		return 0;
+	c = data[i];
+
+	/* the whole line must be the char or space */
+	while (i < size && data[i] != '\n') {
+		if (data[i] == c) n++;
+		else if (data[i] != ' ')
+			return 0;
+
+		i++;
+	}
+
+	return n >= 3;
+}
+
+/* check if a line is a code fence; return the
+ * end of the code fence. if passed, width of
+ * the fence rule and character will be returned */
+static size_t
+is_codefence(uint8_t *data, size_t size, size_t *width, uint8_t *chr)
+{
+	size_t i = 0, n = 1;
+	uint8_t c;
+
+	/* skipping initial spaces */
+	if (size < 3)
+		return 0;
+
+	if (data[0] == ' ') { i++;
+	if (data[1] == ' ') { i++;
+	if (data[2] == ' ') { i++; } } }
+
+	/* looking at the hrule uint8_t */
+	c = data[i];
+	if (i + 2 >= size || !(c=='~' || c=='`'))
+		return 0;
+
+	/* the fence must be that same character */
+	while (++i < size && data[i] == c)
+		++n;
+
+	if (n < 3)
+		return 0;
+
+	if (width) *width = n;
+	if (chr) *chr = c;
+	return i;
+}
+
+/* expects single line, checks if it's a codefence and extracts language */
+static size_t
+parse_codefence(uint8_t *data, size_t size, hoedown_buffer *lang, size_t *width, uint8_t *chr)
+{
+	size_t i, w, lang_start;
+
+	i = w = is_codefence(data, size, width, chr);
+	if (i == 0)
+		return 0;
+
+	while (i < size && _isspace(data[i]))
+		i++;
+
+	lang_start = i;
+
+	while (i < size && !_isspace(data[i]))
+		i++;
+
+	lang->data = data + lang_start;
+	lang->size = i - lang_start;
+
+	/* Avoid parsing a codespan as a fence */
+	i = lang_start + 2;
+	while (i < size && !(data[i] == *chr && data[i-1] == *chr && data[i-2] == *chr)) i++;
+	if (i < size) return 0;
+
+	return w;
+}
+
+/* is_atxheader • returns whether the line is a hash-prefixed header */
+static int
+is_atxheader(hoedown_document *doc, uint8_t *data, size_t size)
+{
+	if (data[0] != '#')
+		return 0;
+
+	if (doc->ext_flags & HOEDOWN_EXT_SPACE_HEADERS) {
+		size_t level = 0;
+
+		while (level < size && level < 6 && data[level] == '#')
+			level++;
+
+		if (level < size && data[level] != ' ')
+			return 0;
+	}
+
+	return 1;
+}
+
+/* is_headerline • returns whether the line is a setext-style hdr underline */
+static int
+is_headerline(uint8_t *data, size_t size)
+{
+	size_t i = 0;
+
+	/* test of level 1 header */
+	if (data[i] == '=') {
+		for (i = 1; i < size && data[i] == '='; i++);
+		while (i < size && data[i] == ' ') i++;
+		return (i >= size || data[i] == '\n') ? 1 : 0; }
+
+	/* test of level 2 header */
+	if (data[i] == '-') {
+		for (i = 1; i < size && data[i] == '-'; i++);
+		while (i < size && data[i] == ' ') i++;
+		return (i >= size || data[i] == '\n') ? 2 : 0; }
+
+	return 0;
+}
+
+static int
+is_next_headerline(uint8_t *data, size_t size)
+{
+	size_t i = 0;
+
+	while (i < size && data[i] != '\n')
+		i++;
+
+	if (++i >= size)
+		return 0;
+
+	return is_headerline(data + i, size - i);
+}
+
+/* prefix_quote • returns blockquote prefix length */
+static size_t
+prefix_quote(uint8_t *data, size_t size)
+{
+	size_t i = 0;
+	if (i < size && data[i] == ' ') i++;
+	if (i < size && data[i] == ' ') i++;
+	if (i < size && data[i] == ' ') i++;
+
+	if (i < size && data[i] == '>') {
+		if (i + 1 < size && data[i + 1] == ' ')
+			return i + 2;
+
+		return i + 1;
+	}
+
+	return 0;
+}
+
+/* prefix_code • returns prefix length for block code*/
+static size_t
+prefix_code(uint8_t *data, size_t size)
+{
+	if (size > 3 && data[0] == ' ' && data[1] == ' '
+		&& data[2] == ' ' && data[3] == ' ') return 4;
+
+	return 0;
+}
+
+/* prefix_oli • returns ordered list item prefix */
+static size_t
+prefix_oli(uint8_t *data, size_t size)
+{
+	size_t i = 0;
+
+	if (i < size && data[i] == ' ') i++;
+	if (i < size && data[i] == ' ') i++;
+	if (i < size && data[i] == ' ') i++;
+
+	if (i >= size || data[i] < '0' || data[i] > '9')
+		return 0;
+
+	while (i < size && data[i] >= '0' && data[i] <= '9')
+		i++;
+
+	if (i + 1 >= size || data[i] != '.' || data[i + 1] != ' ')
+		return 0;
+
+	if (is_next_headerline(data + i, size - i))
+		return 0;
+
+	return i + 2;
+}
+
+/* prefix_uli • returns ordered list item prefix */
+static size_t
+prefix_uli(uint8_t *data, size_t size)
+{
+	size_t i = 0;
+
+	if (i < size && data[i] == ' ') i++;
+	if (i < size && data[i] == ' ') i++;
+	if (i < size && data[i] == ' ') i++;
+
+	if (i + 1 >= size ||
+		(data[i] != '*' && data[i] != '+' && data[i] != '-') ||
+		data[i + 1] != ' ')
+		return 0;
+
+	if (is_next_headerline(data + i, size - i))
+		return 0;
+
+	return i + 2;
+}
+
+
+/* parse_block • parsing of one block, returning next uint8_t to parse */
+static void parse_block(hoedown_buffer *ob, hoedown_document *doc,
+			uint8_t *data, size_t size);
+
+
+/* parse_blockquote • handles parsing of a blockquote fragment */
+static size_t
+parse_blockquote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
+{
+	size_t beg, end = 0, pre, work_size = 0;
+	uint8_t *work_data = 0;
+	hoedown_buffer *out = 0;
+
+	out = newbuf(doc, BUFFER_BLOCK);
+	beg = 0;
+	while (beg < size) {
+		for (end = beg + 1; end < size && data[end - 1] != '\n'; end++);
+
+		pre = prefix_quote(data + beg, end - beg);
+
+		if (pre)
+			beg += pre; /* skipping prefix */
+
+		/* empty line followed by non-quote line */
+		else if (is_empty(data + beg, end - beg) &&
+				(end >= size || (prefix_quote(data + end, size - end) == 0 &&
+				!is_empty(data + end, size - end))))
+			break;
+
+		if (beg < end) { /* copy into the in-place working buffer */
+			/* hoedown_buffer_put(work, data + beg, end - beg); */
+			if (!work_data)
+				work_data = data + beg;
+			else if (data + beg != work_data + work_size)
+				memmove(work_data + work_size, data + beg, end - beg);
+			work_size += end - beg;
+		}
+		beg = end;
+	}
+
+	parse_block(out, doc, work_data, work_size);
+	if (doc->md.blockquote)
+		doc->md.blockquote(ob, out, &doc->data);
+	popbuf(doc, BUFFER_BLOCK);
+	return end;
+}
+
+static size_t
+parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, int do_render);
+
+/* parse_blockquote • handles parsing of a regular paragraph */
+static size_t
+parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
+{
+	hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
+	size_t i = 0, end = 0;
+	int level = 0;
+
+	work.data = data;
+
+	while (i < size) {
+		for (end = i + 1; end < size && data[end - 1] != '\n'; end++) /* empty */;
+
+		if (is_empty(data + i, size - i))
+			break;
+
+		if ((level = is_headerline(data + i, size - i)) != 0)
+			break;
+
+		if (is_atxheader(doc, data + i, size - i) ||
+			is_hrule(data + i, size - i) ||
+			prefix_quote(data + i, size - i)) {
+			end = i;
+			break;
+		}
+
+		i = end;
+	}
+
+	work.size = i;
+	while (work.size && data[work.size - 1] == '\n')
+		work.size--;
+
+	if (!level) {
+		hoedown_buffer *tmp = newbuf(doc, BUFFER_BLOCK);
+		parse_inline(tmp, doc, work.data, work.size);
+		if (doc->md.paragraph)
+			doc->md.paragraph(ob, tmp, &doc->data);
+		popbuf(doc, BUFFER_BLOCK);
+	} else {
+		hoedown_buffer *header_work;
+
+		if (work.size) {
+			size_t beg;
+			i = work.size;
+			work.size -= 1;
+
+			while (work.size && data[work.size] != '\n')
+				work.size -= 1;
+
+			beg = work.size + 1;
+			while (work.size && data[work.size - 1] == '\n')
+				work.size -= 1;
+
+			if (work.size > 0) {
+				hoedown_buffer *tmp = newbuf(doc, BUFFER_BLOCK);
+				parse_inline(tmp, doc, work.data, work.size);
+
+				if (doc->md.paragraph)
+					doc->md.paragraph(ob, tmp, &doc->data);
+
+				popbuf(doc, BUFFER_BLOCK);
+				work.data += beg;
+				work.size = i - beg;
+			}
+			else work.size = i;
+		}
+
+		header_work = newbuf(doc, BUFFER_SPAN);
+		parse_inline(header_work, doc, work.data, work.size);
+
+		if (doc->md.header)
+			doc->md.header(ob, header_work, (int)level, &doc->data);
+
+		popbuf(doc, BUFFER_SPAN);
+	}
+
+	return end;
+}
+
+/* parse_fencedcode • handles parsing of a block-level code fragment */
+static size_t
+parse_fencedcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
+{
+	hoedown_buffer text = { 0, 0, 0, 0, NULL, NULL, NULL };
+	hoedown_buffer lang = { 0, 0, 0, 0, NULL, NULL, NULL };
+	size_t i = 0, text_start, line_start;
+	size_t w, w2;
+	size_t width, width2;
+	uint8_t chr, chr2;
+
+	/* parse codefence line */
+	while (i < size && data[i] != '\n')
+		i++;
+
+	w = parse_codefence(data, i, &lang, &width, &chr);
+	if (!w)
+		return 0;
+
+	/* search for end */
+	i++;
+	text_start = i;
+	while ((line_start = i) < size) {
+		while (i < size && data[i] != '\n')
+			i++;
+
+		w2 = is_codefence(data + line_start, i - line_start, &width2, &chr2);
+		if (w == w2 && width == width2 && chr == chr2 &&
+		    is_empty(data + (line_start+w), i - (line_start+w)))
+			break;
+
+		i++;
+	}
+
+	text.data = data + text_start;
+	text.size = line_start - text_start;
+
+	if (doc->md.blockcode)
+		doc->md.blockcode(ob, text.size ? &text : NULL, lang.size ? &lang : NULL, &doc->data);
+
+	return i;
+}
+
+static size_t
+parse_blockcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
+{
+	size_t beg, end, pre;
+	hoedown_buffer *work = 0;
+
+	work = newbuf(doc, BUFFER_BLOCK);
+
+	beg = 0;
+	while (beg < size) {
+		for (end = beg + 1; end < size && data[end - 1] != '\n'; end++) {};
+		pre = prefix_code(data + beg, end - beg);
+
+		if (pre)
+			beg += pre; /* skipping prefix */
+		else if (!is_empty(data + beg, end - beg))
+			/* non-empty non-prefixed line breaks the pre */
+			break;
+
+		if (beg < end) {
+			/* verbatim copy to the working buffer,
+				escaping entities */
+			if (is_empty(data + beg, end - beg))
+				hoedown_buffer_putc(work, '\n');
+			else hoedown_buffer_put(work, data + beg, end - beg);
+		}
+		beg = end;
+	}
+
+	while (work->size && work->data[work->size - 1] == '\n')
+		work->size -= 1;
+
+	hoedown_buffer_putc(work, '\n');
+
+	if (doc->md.blockcode)
+		doc->md.blockcode(ob, work, NULL, &doc->data);
+
+	popbuf(doc, BUFFER_BLOCK);
+	return beg;
+}
+
+/* parse_listitem • parsing of a single list item */
+/*	assuming initial prefix is already removed */
+static size_t
+parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_list_flags *flags)
+{
+	hoedown_buffer *work = 0, *inter = 0;
+	size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i;
+	int in_empty = 0, has_inside_empty = 0, in_fence = 0;
+
+	/* keeping track of the first indentation prefix */
+	while (orgpre < 3 && orgpre < size && data[orgpre] == ' ')
+		orgpre++;
+
+	beg = prefix_uli(data, size);
+	if (!beg)
+		beg = prefix_oli(data, size);
+
+	if (!beg)
+		return 0;
+
+	/* skipping to the beginning of the following line */
+	end = beg;
+	while (end < size && data[end - 1] != '\n')
+		end++;
+
+	/* getting working buffers */
+	work = newbuf(doc, BUFFER_SPAN);
+	inter = newbuf(doc, BUFFER_SPAN);
+
+	/* putting the first line into the working buffer */
+	hoedown_buffer_put(work, data + beg, end - beg);
+	beg = end;
+
+	/* process the following lines */
+	while (beg < size) {
+		size_t has_next_uli = 0, has_next_oli = 0;
+
+		end++;
+
+		while (end < size && data[end - 1] != '\n')
+			end++;
+
+		/* process an empty line */
+		if (is_empty(data + beg, end - beg)) {
+			in_empty = 1;
+			beg = end;
+			continue;
+		}
+
+		/* calculating the indentation */
+		i = 0;
+		while (i < 4 && beg + i < end && data[beg + i] == ' ')
+			i++;
+
+		pre = i;
+
+		if (doc->ext_flags & HOEDOWN_EXT_FENCED_CODE) {
+			if (is_codefence(data + beg + i, end - beg - i, NULL, NULL))
+				in_fence = !in_fence;
+		}
+
+		/* Only check for new list items if we are **not** inside
+		 * a fenced code block */
+		if (!in_fence) {
+			has_next_uli = prefix_uli(data + beg + i, end - beg - i);
+			has_next_oli = prefix_oli(data + beg + i, end - beg - i);
+		}
+
+		/* checking for a new item */
+		if ((has_next_uli && !is_hrule(data + beg + i, end - beg - i)) || has_next_oli) {
+			if (in_empty)
+				has_inside_empty = 1;
+
+			/* the following item must have the same (or less) indentation */
+			if (pre <= orgpre) {
+				/* if the following item has different list type, we end this list */
+				if (in_empty && (
+					((*flags & HOEDOWN_LIST_ORDERED) && has_next_uli) ||
+					(!(*flags & HOEDOWN_LIST_ORDERED) && has_next_oli)))
+					*flags |= HOEDOWN_LI_END;
+
+				break;
+			}
+
+			if (!sublist)
+				sublist = work->size;
+		}
+		/* joining only indented stuff after empty lines;
+		 * note that now we only require 1 space of indentation
+		 * to continue a list */
+		else if (in_empty && pre == 0) {
+			*flags |= HOEDOWN_LI_END;
+			break;
+		}
+
+		if (in_empty) {
+			hoedown_buffer_putc(work, '\n');
+			has_inside_empty = 1;
+			in_empty = 0;
+		}
+
+		/* adding the line without prefix into the working buffer */
+		hoedown_buffer_put(work, data + beg + i, end - beg - i);
+		beg = end;
+	}
+
+	/* render of li contents */
+	if (has_inside_empty)
+		*flags |= HOEDOWN_LI_BLOCK;
+
+	if (*flags & HOEDOWN_LI_BLOCK) {
+		/* intermediate render of block li */
+		if (sublist && sublist < work->size) {
+			parse_block(inter, doc, work->data, sublist);
+			parse_block(inter, doc, work->data + sublist, work->size - sublist);
+		}
+		else
+			parse_block(inter, doc, work->data, work->size);
+	} else {
+		/* intermediate render of inline li */
+		if (sublist && sublist < work->size) {
+			parse_inline(inter, doc, work->data, sublist);
+			parse_block(inter, doc, work->data + sublist, work->size - sublist);
+		}
+		else
+			parse_inline(inter, doc, work->data, work->size);
+	}
+
+	/* render of li itself */
+	if (doc->md.listitem)
+		doc->md.listitem(ob, inter, *flags, &doc->data);
+
+	popbuf(doc, BUFFER_SPAN);
+	popbuf(doc, BUFFER_SPAN);
+	return beg;
+}
+
+
+/* parse_list • parsing ordered or unordered list block */
+static size_t
+parse_list(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_list_flags flags)
+{
+	hoedown_buffer *work = 0;
+	size_t i = 0, j;
+
+	work = newbuf(doc, BUFFER_BLOCK);
+
+	while (i < size) {
+		j = parse_listitem(work, doc, data + i, size - i, &flags);
+		i += j;
+
+		if (!j || (flags & HOEDOWN_LI_END))
+			break;
+	}
+
+	if (doc->md.list)
+		doc->md.list(ob, work, flags, &doc->data);
+	popbuf(doc, BUFFER_BLOCK);
+	return i;
+}
+
+/* parse_atxheader • parsing of atx-style headers */
+static size_t
+parse_atxheader(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
+{
+	size_t level = 0;
+	size_t i, end, skip;
+
+	while (level < size && level < 6 && data[level] == '#')
+		level++;
+
+	for (i = level; i < size && data[i] == ' '; i++);
+
+	for (end = i; end < size && data[end] != '\n'; end++);
+	skip = end;
+
+	while (end && data[end - 1] == '#')
+		end--;
+
+	while (end && data[end - 1] == ' ')
+		end--;
+
+	if (end > i) {
+		hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
+
+		parse_inline(work, doc, data + i, end - i);
+
+		if (doc->md.header)
+			doc->md.header(ob, work, (int)level, &doc->data);
+
+		popbuf(doc, BUFFER_SPAN);
+	}
+
+	return skip;
+}
+
+/* parse_footnote_def • parse a single footnote definition */
+static void
+parse_footnote_def(hoedown_buffer *ob, hoedown_document *doc, unsigned int num, uint8_t *data, size_t size)
+{
+	hoedown_buffer *work = 0;
+	work = newbuf(doc, BUFFER_SPAN);
+
+	parse_block(work, doc, data, size);
+
+	if (doc->md.footnote_def)
+	doc->md.footnote_def(ob, work, num, &doc->data);
+	popbuf(doc, BUFFER_SPAN);
+}
+
+/* parse_footnote_list • render the contents of the footnotes */
+static void
+parse_footnote_list(hoedown_buffer *ob, hoedown_document *doc, struct footnote_list *footnotes)
+{
+	hoedown_buffer *work = 0;
+	struct footnote_item *item;
+	struct footnote_ref *ref;
+
+	if (footnotes->count == 0)
+		return;
+
+	work = newbuf(doc, BUFFER_BLOCK);
+
+	item = footnotes->head;
+	while (item) {
+		ref = item->ref;
+		parse_footnote_def(work, doc, ref->num, ref->contents->data, ref->contents->size);
+		item = item->next;
+	}
+
+	if (doc->md.footnotes)
+		doc->md.footnotes(ob, work, &doc->data);
+	popbuf(doc, BUFFER_BLOCK);
+}
+
+/* htmlblock_is_end • check for end of HTML block : </tag>( *)\n */
+/*	returns tag length on match, 0 otherwise */
+/*	assumes data starts with "<" */
+static size_t
+htmlblock_is_end(
+	const char *tag,
+	size_t tag_len,
+	hoedown_document *doc,
+	uint8_t *data,
+	size_t size)
+{
+	size_t i = tag_len + 3, w;
+
+	/* try to match the end tag */
+	/* note: we're not considering tags like "</tag >" which are still valid */
+	if (i > size ||
+		data[1] != '/' ||
+		strncasecmp((char *)data + 2, tag, tag_len) != 0 ||
+		data[tag_len + 2] != '>')
+		return 0;
+
+	/* rest of the line must be empty */
+	if ((w = is_empty(data + i, size - i)) == 0 && i < size)
+		return 0;
+
+	return i + w;
+}
+
+/* htmlblock_find_end • try to find HTML block ending tag */
+/*	returns the length on match, 0 otherwise */
+static size_t
+htmlblock_find_end(
+	const char *tag,
+	size_t tag_len,
+	hoedown_document *doc,
+	uint8_t *data,
+	size_t size)
+{
+	size_t i = 0, w;
+
+	while (1) {
+		while (i < size && data[i] != '<') i++;
+		if (i >= size) return 0;
+
+		w = htmlblock_is_end(tag, tag_len, doc, data + i, size - i);
+		if (w) return i + w;
+		i++;
+	}
+}
+
+/* htmlblock_find_end_strict • try to find end of HTML block in strict mode */
+/*	(it must be an unindented line, and have a blank line afterwads) */
+/*	returns the length on match, 0 otherwise */
+static size_t
+htmlblock_find_end_strict(
+	const char *tag,
+	size_t tag_len,
+	hoedown_document *doc,
+	uint8_t *data,
+	size_t size)
+{
+	size_t i = 0, mark;
+
+	while (1) {
+		mark = i;
+		while (i < size && data[i] != '\n') i++;
+		if (i < size) i++;
+		if (i == mark) return 0;
+
+		if (data[mark] == ' ' && mark > 0) continue;
+		mark += htmlblock_find_end(tag, tag_len, doc, data + mark, i - mark);
+		if (mark == i && (is_empty(data + i, size - i) || i >= size)) break;
+	}
+
+	return i;
+}
+
+/* parse_htmlblock • parsing of inline HTML block */
+static size_t
+parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, int do_render)
+{
+	hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL };
+	size_t i, j = 0, tag_len, tag_end;
+	const char *curtag = NULL;
+
+	work.data = data;
+
+	/* identification of the opening tag */
+	if (size < 2 || data[0] != '<')
+		return 0;
+
+	i = 1;
+	while (i < size && data[i] != '>' && data[i] != ' ')
+		i++;
+
+	if (i < size)
+		curtag = hoedown_find_block_tag((char *)data + 1, (int)i - 1);
+
+	/* handling of special cases */
+	if (!curtag) {
+
+		/* HTML comment, laxist form */
+		if (size > 5 && data[1] == '!' && data[2] == '-' && data[3] == '-') {
+			i = 5;
+
+			while (i < size && !(data[i - 2] == '-' && data[i - 1] == '-' && data[i] == '>'))
+				i++;
+
+			i++;
+
+			if (i < size)
+				j = is_empty(data + i, size - i);
+
+			if (j) {
+				work.size = i + j;
+				if (do_render && doc->md.blockhtml)
+					doc->md.blockhtml(ob, &work, &doc->data);
+				return work.size;
+			}
+		}
+
+		/* HR, which is the only self-closing block tag considered */
+		if (size > 4 && (data[1] == 'h' || data[1] == 'H') && (data[2] == 'r' || data[2] == 'R')) {
+			i = 3;
+			while (i < size && data[i] != '>')
+				i++;
+
+			if (i + 1 < size) {
+				i++;
+				j = is_empty(data + i, size - i);
+				if (j) {
+					work.size = i + j;
+					if (do_render && doc->md.blockhtml)
+						doc->md.blockhtml(ob, &work, &doc->data);
+					return work.size;
+				}
+			}
+		}
+
+		/* no special case recognised */
+		return 0;
+	}
+
+	/* looking for a matching closing tag in strict mode */
+	tag_len = strlen(curtag);
+	tag_end = htmlblock_find_end_strict(curtag, tag_len, doc, data, size);
+
+	/* if not found, trying a second pass looking for indented match */
+	/* but not if tag is "ins" or "del" (following original Markdown.pl) */
+	if (!tag_end && strcmp(curtag, "ins") != 0 && strcmp(curtag, "del") != 0)
+		tag_end = htmlblock_find_end(curtag, tag_len, doc, data, size);
+
+	if (!tag_end)
+		return 0;
+
+	/* the end of the block has been found */
+	work.size = tag_end;
+	if (do_render && doc->md.blockhtml)
+		doc->md.blockhtml(ob, &work, &doc->data);
+
+	return tag_end;
+}
+
+static void
+parse_table_row(
+	hoedown_buffer *ob,
+	hoedown_document *doc,
+	uint8_t *data,
+	size_t size,
+	size_t columns,
+	hoedown_table_flags *col_data,
+	hoedown_table_flags header_flag)
+{
+	size_t i = 0, col, len;
+	hoedown_buffer *row_work = 0;
+
+	if (!doc->md.table_cell || !doc->md.table_row)
+		return;
+
+	row_work = newbuf(doc, BUFFER_SPAN);
+
+	if (i < size && data[i] == '|')
+		i++;
+
+	for (col = 0; col < columns && i < size; ++col) {
+		size_t cell_start, cell_end;
+		hoedown_buffer *cell_work;
+
+		cell_work = newbuf(doc, BUFFER_SPAN);
+
+		while (i < size && _isspace(data[i]))
+			i++;
+
+		cell_start = i;
+
+		len = find_emph_char(data + i, size - i, '|');
+
+		/* Two possibilities for len == 0:
+		   1) No more pipe char found in the current line.
+		   2) The next pipe is right after the current one, i.e. empty cell.
+		   For case 1, we skip to the end of line; for case 2 we just continue.
+		*/
+		if (len == 0 && i < size && data[i] != '|')
+			len = size - i;
+		i += len;
+
+		cell_end = i - 1;
+
+		while (cell_end > cell_start && _isspace(data[cell_end]))
+			cell_end--;
+
+		parse_inline(cell_work, doc, data + cell_start, 1 + cell_end - cell_start);
+		doc->md.table_cell(row_work, cell_work, col_data[col] | header_flag, &doc->data);
+
+		popbuf(doc, BUFFER_SPAN);
+		i++;
+	}
+
+	for (; col < columns; ++col) {
+		hoedown_buffer empty_cell = { 0, 0, 0, 0, NULL, NULL, NULL };
+		doc->md.table_cell(row_work, &empty_cell, col_data[col] | header_flag, &doc->data);
+	}
+
+	doc->md.table_row(ob, row_work, &doc->data);
+
+	popbuf(doc, BUFFER_SPAN);
+}
+
+static size_t
+parse_table_header(
+	hoedown_buffer *ob,
+	hoedown_document *doc,
+	uint8_t *data,
+	size_t size,
+	size_t *columns,
+	hoedown_table_flags **column_data)
+{
+	int pipes;
+	size_t i = 0, col, header_end, under_end;
+
+	pipes = 0;
+	while (i < size && data[i] != '\n')
+		if (data[i++] == '|')
+			pipes++;
+
+	if (i == size || pipes == 0)
+		return 0;
+
+	header_end = i;
+
+	while (header_end > 0 && _isspace(data[header_end - 1]))
+		header_end--;
+
+	if (data[0] == '|')
+		pipes--;
+
+	if (header_end && data[header_end - 1] == '|')
+		pipes--;
+
+	if (pipes < 0)
+		return 0;
+
+	*columns = pipes + 1;
+	*column_data = hoedown_calloc(*columns, sizeof(hoedown_table_flags));
+
+	/* Parse the header underline */
+	i++;
+	if (i < size && data[i] == '|')
+		i++;
+
+	under_end = i;
+	while (under_end < size && data[under_end] != '\n')
+		under_end++;
+
+	for (col = 0; col < *columns && i < under_end; ++col) {
+		size_t dashes = 0;
+
+		while (i < under_end && data[i] == ' ')
+			i++;
+
+		if (data[i] == ':') {
+			i++; (*column_data)[col] |= HOEDOWN_TABLE_ALIGN_LEFT;
+			dashes++;
+		}
+
+		while (i < under_end && data[i] == '-') {
+			i++; dashes++;
+		}
+
+		if (i < under_end && data[i] == ':') {
+			i++; (*column_data)[col] |= HOEDOWN_TABLE_ALIGN_RIGHT;
+			dashes++;
+		}
+
+		while (i < under_end && data[i] == ' ')
+			i++;
+
+		if (i < under_end && data[i] != '|' && data[i] != '+')
+			break;
+
+		if (dashes < 3)
+			break;
+
+		i++;
+	}
+
+	if (col < *columns)
+		return 0;
+
+	parse_table_row(
+		ob, doc, data,
+		header_end,
+		*columns,
+		*column_data,
+		HOEDOWN_TABLE_HEADER
+	);
+
+	return under_end + 1;
+}
+
+static size_t
+parse_table(
+	hoedown_buffer *ob,
+	hoedown_document *doc,
+	uint8_t *data,
+	size_t size)
+{
+	size_t i;
+
+	hoedown_buffer *work = 0;
+	hoedown_buffer *header_work = 0;
+	hoedown_buffer *body_work = 0;
+
+	size_t columns;
+	hoedown_table_flags *col_data = NULL;
+
+	work = newbuf(doc, BUFFER_BLOCK);
+	header_work = newbuf(doc, BUFFER_SPAN);
+	body_work = newbuf(doc, BUFFER_BLOCK);
+
+	i = parse_table_header(header_work, doc, data, size, &columns, &col_data);
+	if (i > 0) {
+
+		while (i < size) {
+			size_t row_start;
+			int pipes = 0;
+
+			row_start = i;
+
+			while (i < size && data[i] != '\n')
+				if (data[i++] == '|')
+					pipes++;
+
+			if (pipes == 0 || i == size) {
+				i = row_start;
+				break;
+			}
+
+			parse_table_row(
+				body_work,
+				doc,
+				data + row_start,
+				i - row_start,
+				columns,
+				col_data, 0
+			);
+
+			i++;
+		}
+
+        if (doc->md.table_header)
+            doc->md.table_header(work, header_work, &doc->data);
+
+        if (doc->md.table_body)
+            doc->md.table_body(work, body_work, &doc->data);
+
+		if (doc->md.table)
+			doc->md.table(ob, work, &doc->data);
+	}
+
+	free(col_data);
+	popbuf(doc, BUFFER_SPAN);
+	popbuf(doc, BUFFER_BLOCK);
+	popbuf(doc, BUFFER_BLOCK);
+	return i;
+}
+
+/* parse_block • parsing of one block, returning next uint8_t to parse */
+static void
+parse_block(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size)
+{
+	size_t beg, end, i;
+	uint8_t *txt_data;
+	beg = 0;
+
+	if (doc->work_bufs[BUFFER_SPAN].size +
+		doc->work_bufs[BUFFER_BLOCK].size > doc->max_nesting)
+		return;
+
+	while (beg < size) {
+		txt_data = data + beg;
+		end = size - beg;
+
+		if (is_atxheader(doc, txt_data, end))
+			beg += parse_atxheader(ob, doc, txt_data, end);
+
+		else if (data[beg] == '<' && doc->md.blockhtml &&
+				(i = parse_htmlblock(ob, doc, txt_data, end, 1)) != 0)
+			beg += i;
+
+		else if ((i = is_empty(txt_data, end)) != 0)
+			beg += i;
+
+		else if (is_hrule(txt_data, end)) {
+			if (doc->md.hrule)
+				doc->md.hrule(ob, &doc->data);
+
+			while (beg < size && data[beg] != '\n')
+				beg++;
+
+			beg++;
+		}
+
+		else if ((doc->ext_flags & HOEDOWN_EXT_FENCED_CODE) != 0 &&
+			(i = parse_fencedcode(ob, doc, txt_data, end)) != 0)
+			beg += i;
+
+		else if ((doc->ext_flags & HOEDOWN_EXT_TABLES) != 0 &&
+			(i = parse_table(ob, doc, txt_data, end)) != 0)
+			beg += i;
+
+		else if (prefix_quote(txt_data, end))
+			beg += parse_blockquote(ob, doc, txt_data, end);
+
+		else if (!(doc->ext_flags & HOEDOWN_EXT_DISABLE_INDENTED_CODE) && prefix_code(txt_data, end))
+			beg += parse_blockcode(ob, doc, txt_data, end);
+
+		else if (prefix_uli(txt_data, end))
+			beg += parse_list(ob, doc, txt_data, end, 0);
+
+		else if (prefix_oli(txt_data, end))
+			beg += parse_list(ob, doc, txt_data, end, HOEDOWN_LIST_ORDERED);
+
+		else
+			beg += parse_paragraph(ob, doc, txt_data, end);
+	}
+}
+
+
+
+/*********************
+ * REFERENCE PARSING *
+ *********************/
+
+/* is_footnote • returns whether a line is a footnote definition or not */
+static int
+is_footnote(const uint8_t *data, size_t beg, size_t end, size_t *last, struct footnote_list *list)
+{
+	size_t i = 0;
+	hoedown_buffer *contents = 0;
+	size_t ind = 0;
+	int in_empty = 0;
+	size_t start = 0;
+
+	size_t id_offset, id_end;
+
+	/* up to 3 optional leading spaces */
+	if (beg + 3 >= end) return 0;
+	if (data[beg] == ' ') { i = 1;
+	if (data[beg + 1] == ' ') { i = 2;
+	if (data[beg + 2] == ' ') { i = 3;
+	if (data[beg + 3] == ' ') return 0; } } }
+	i += beg;
+
+	/* id part: caret followed by anything between brackets */
+	if (data[i] != '[') return 0;
+	i++;
+	if (i >= end || data[i] != '^') return 0;
+	i++;
+	id_offset = i;
+	while (i < end && data[i] != '\n' && data[i] != '\r' && data[i] != ']')
+		i++;
+	if (i >= end || data[i] != ']') return 0;
+	id_end = i;
+
+	/* spacer: colon (space | tab)* newline? (space | tab)* */
+	i++;
+	if (i >= end || data[i] != ':') return 0;
+	i++;
+
+	/* getting content buffer */
+	contents = hoedown_buffer_new(64);
+
+	start = i;
+
+	/* process lines similar to a list item */
+	while (i < end) {
+		while (i < end && data[i] != '\n' && data[i] != '\r') i++;
+
+		/* process an empty line */
+		if (is_empty(data + start, i - start)) {
+			in_empty = 1;
+			if (i < end && (data[i] == '\n' || data[i] == '\r')) {
+				i++;
+				if (i < end && data[i] == '\n' && data[i - 1] == '\r') i++;
+			}
+			start = i;
+			continue;
+		}
+
+		/* calculating the indentation */
+		ind = 0;
+		while (ind < 4 && start + ind < end && data[start + ind] == ' ')
+			ind++;
+
+		/* joining only indented stuff after empty lines;
+		 * note that now we only require 1 space of indentation
+		 * to continue, just like lists */
+		if (ind == 0) {
+			if (start == id_end + 2 && data[start] == '\t') {}
+			else break;
+		}
+		else if (in_empty) {
+			hoedown_buffer_putc(contents, '\n');
+		}
+
+		in_empty = 0;
+
+		/* adding the line into the content buffer */
+		hoedown_buffer_put(contents, data + start + ind, i - start - ind);
+		/* add carriage return */
+		if (i < end) {
+			hoedown_buffer_putc(contents, '\n');
+			if (i < end && (data[i] == '\n' || data[i] == '\r')) {
+				i++;
+				if (i < end && data[i] == '\n' && data[i - 1] == '\r') i++;
+			}
+		}
+		start = i;
+	}
+
+	if (last)
+		*last = start;
+
+	if (list) {
+		struct footnote_ref *ref;
+		ref = create_footnote_ref(list, data + id_offset, id_end - id_offset);
+		if (!ref)
+			return 0;
+		if (!add_footnote_ref(list, ref)) {
+			free_footnote_ref(ref);
+			return 0;
+		}
+		ref->contents = contents;
+	}
+
+	return 1;
+}
+
+/* is_ref • returns whether a line is a reference or not */
+static int
+is_ref(const uint8_t *data, size_t beg, size_t end, size_t *last, struct link_ref **refs)
+{
+/*	int n; */
+	size_t i = 0;
+	size_t id_offset, id_end;
+	size_t link_offset, link_end;
+	size_t title_offset, title_end;
+	size_t line_end;
+
+	/* up to 3 optional leading spaces */
+	if (beg + 3 >= end) return 0;
+	if (data[beg] == ' ') { i = 1;
+	if (data[beg + 1] == ' ') { i = 2;
+	if (data[beg + 2] == ' ') { i = 3;
+	if (data[beg + 3] == ' ') return 0; } } }
+	i += beg;
+
+	/* id part: anything but a newline between brackets */
+	if (data[i] != '[') return 0;
+	i++;
+	id_offset = i;
+	while (i < end && data[i] != '\n' && data[i] != '\r' && data[i] != ']')
+		i++;
+	if (i >= end || data[i] != ']') return 0;
+	id_end = i;
+
+	/* spacer: colon (space | tab)* newline? (space | tab)* */
+	i++;
+	if (i >= end || data[i] != ':') return 0;
+	i++;
+	while (i < end && data[i] == ' ') i++;
+	if (i < end && (data[i] == '\n' || data[i] == '\r')) {
+		i++;
+		if (i < end && data[i] == '\r' && data[i - 1] == '\n') i++; }
+	while (i < end && data[i] == ' ') i++;
+	if (i >= end) return 0;
+
+	/* link: spacing-free sequence, optionally between angle brackets */
+	if (data[i] == '<')
+		i++;
+
+	link_offset = i;
+
+	while (i < end && data[i] != ' ' && data[i] != '\n' && data[i] != '\r')
+		i++;
+
+	if (data[i - 1] == '>') link_end = i - 1;
+	else link_end = i;
+
+	/* optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) */
+	while (i < end && data[i] == ' ') i++;
+	if (i < end && data[i] != '\n' && data[i] != '\r'
+			&& data[i] != '\'' && data[i] != '"' && data[i] != '(')
+		return 0;
+	line_end = 0;
+	/* computing end-of-line */
+	if (i >= end || data[i] == '\r' || data[i] == '\n') line_end = i;
+	if (i + 1 < end && data[i] == '\n' && data[i + 1] == '\r')
+		line_end = i + 1;
+
+	/* optional (space|tab)* spacer after a newline */
+	if (line_end) {
+		i = line_end + 1;
+		while (i < end && data[i] == ' ') i++; }
+
+	/* optional title: any non-newline sequence enclosed in '"()
+					alone on its line */
+	title_offset = title_end = 0;
+	if (i + 1 < end
+	&& (data[i] == '\'' || data[i] == '"' || data[i] == '(')) {
+		i++;
+		title_offset = i;
+		/* looking for EOL */
+		while (i < end && data[i] != '\n' && data[i] != '\r') i++;
+		if (i + 1 < end && data[i] == '\n' && data[i + 1] == '\r')
+			title_end = i + 1;
+		else	title_end = i;
+		/* stepping back */
+		i -= 1;
+		while (i > title_offset && data[i] == ' ')
+			i -= 1;
+		if (i > title_offset
+		&& (data[i] == '\'' || data[i] == '"' || data[i] == ')')) {
+			line_end = title_end;
+			title_end = i; } }
+
+	if (!line_end || link_end == link_offset)
+		return 0; /* garbage after the link empty link */
+
+	/* a valid ref has been found, filling-in return structures */
+	if (last)
+		*last = line_end;
+
+	if (refs) {
+		struct link_ref *ref;
+
+		ref = add_link_ref(refs, data + id_offset, id_end - id_offset);
+		if (!ref)
+			return 0;
+
+		ref->link = hoedown_buffer_new(link_end - link_offset);
+		hoedown_buffer_put(ref->link, data + link_offset, link_end - link_offset);
+
+		if (title_end > title_offset) {
+			ref->title = hoedown_buffer_new(title_end - title_offset);
+			hoedown_buffer_put(ref->title, data + title_offset, title_end - title_offset);
+		}
+	}
+
+	return 1;
+}
+
+static void expand_tabs(hoedown_buffer *ob, const uint8_t *line, size_t size)
+{
+	/* This code makes two assumptions:
+	 * - Input is valid UTF-8.  (Any byte with top two bits 10 is skipped,
+	 *   whether or not it is a valid UTF-8 continuation byte.)
+	 * - Input contains no combining characters.  (Combining characters
+	 *   should be skipped but are not.)
+	 */
+	size_t  i = 0, tab = 0;
+
+	while (i < size) {
+		size_t org = i;
+
+		while (i < size && line[i] != '\t') {
+			/* ignore UTF-8 continuation bytes */
+			if ((line[i] & 0xc0) != 0x80)
+				tab++;
+			i++;
+		}
+
+		if (i > org)
+			hoedown_buffer_put(ob, line + org, i - org);
+
+		if (i >= size)
+			break;
+
+		do {
+			hoedown_buffer_putc(ob, ' '); tab++;
+		} while (tab % 4);
+
+		i++;
+	}
+}
+
+/**********************
+ * EXPORTED FUNCTIONS *
+ **********************/
+
+hoedown_document *
+hoedown_document_new(
+	const hoedown_renderer *renderer,
+	hoedown_extensions extensions,
+	size_t max_nesting)
+{
+	hoedown_document *doc = NULL;
+
+	assert(max_nesting > 0 && renderer);
+
+	doc = hoedown_malloc(sizeof(hoedown_document));
+	memcpy(&doc->md, renderer, sizeof(hoedown_renderer));
+
+	doc->data.opaque = renderer->opaque;
+
+	hoedown_stack_init(&doc->work_bufs[BUFFER_BLOCK], 4);
+	hoedown_stack_init(&doc->work_bufs[BUFFER_SPAN], 8);
+
+	memset(doc->active_char, 0x0, 256);
+
+	if (extensions & HOEDOWN_EXT_UNDERLINE && doc->md.underline) {
+		doc->active_char['_'] = MD_CHAR_EMPHASIS;
+	}
+
+	if (doc->md.emphasis || doc->md.double_emphasis || doc->md.triple_emphasis) {
+		doc->active_char['*'] = MD_CHAR_EMPHASIS;
+		doc->active_char['_'] = MD_CHAR_EMPHASIS;
+		if (extensions & HOEDOWN_EXT_STRIKETHROUGH)
+			doc->active_char['~'] = MD_CHAR_EMPHASIS;
+		if (extensions & HOEDOWN_EXT_HIGHLIGHT)
+			doc->active_char['='] = MD_CHAR_EMPHASIS;
+	}
+
+	if (doc->md.codespan)
+		doc->active_char['`'] = MD_CHAR_CODESPAN;
+
+	if (doc->md.linebreak)
+		doc->active_char['\n'] = MD_CHAR_LINEBREAK;
+
+	if (doc->md.image || doc->md.link || doc->md.footnotes || doc->md.footnote_ref)
+		doc->active_char['['] = MD_CHAR_LINK;
+
+	doc->active_char['<'] = MD_CHAR_LANGLE;
+	doc->active_char['\\'] = MD_CHAR_ESCAPE;
+	doc->active_char['&'] = MD_CHAR_ENTITY;
+
+	if (extensions & HOEDOWN_EXT_AUTOLINK) {
+		doc->active_char[':'] = MD_CHAR_AUTOLINK_URL;
+		doc->active_char['@'] = MD_CHAR_AUTOLINK_EMAIL;
+		doc->active_char['w'] = MD_CHAR_AUTOLINK_WWW;
+	}
+
+	if (extensions & HOEDOWN_EXT_SUPERSCRIPT)
+		doc->active_char['^'] = MD_CHAR_SUPERSCRIPT;
+
+	if (extensions & HOEDOWN_EXT_QUOTE)
+		doc->active_char['"'] = MD_CHAR_QUOTE;
+
+	if (extensions & HOEDOWN_EXT_MATH)
+		doc->active_char['$'] = MD_CHAR_MATH;
+
+	/* Extension data */
+	doc->ext_flags = extensions;
+	doc->max_nesting = max_nesting;
+	doc->in_link_body = 0;
+
+	return doc;
+}
+
+void
+hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size)
+{
+	static const uint8_t UTF8_BOM[] = {0xEF, 0xBB, 0xBF};
+
+	hoedown_buffer *text;
+	size_t beg, end;
+
+	int footnotes_enabled;
+
+	text = hoedown_buffer_new(64);
+
+	/* Preallocate enough space for our buffer to avoid expanding while copying */
+	hoedown_buffer_grow(text, size);
+
+	/* reset the references table */
+	memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
+
+	footnotes_enabled = doc->ext_flags & HOEDOWN_EXT_FOOTNOTES;
+
+	/* reset the footnotes lists */
+	if (footnotes_enabled) {
+		memset(&doc->footnotes_found, 0x0, sizeof(doc->footnotes_found));
+		memset(&doc->footnotes_used, 0x0, sizeof(doc->footnotes_used));
+	}
+
+	/* first pass: looking for references, copying everything else */
+	beg = 0;
+
+	/* Skip a possible UTF-8 BOM, even though the Unicode standard
+	 * discourages having these in UTF-8 documents */
+	if (size >= 3 && memcmp(data, UTF8_BOM, 3) == 0)
+		beg += 3;
+
+	while (beg < size) /* iterating over lines */
+		if (footnotes_enabled && is_footnote(data, beg, size, &end, &doc->footnotes_found))
+			beg = end;
+		else if (is_ref(data, beg, size, &end, doc->refs))
+			beg = end;
+		else { /* skipping to the next line */
+			end = beg;
+			while (end < size && data[end] != '\n' && data[end] != '\r')
+				end++;
+
+			/* adding the line body if present */
+			if (end > beg)
+				expand_tabs(text, data + beg, end - beg);
+
+			while (end < size && (data[end] == '\n' || data[end] == '\r')) {
+				/* add one \n per newline */
+				if (data[end] == '\n' || (end + 1 < size && data[end + 1] != '\n'))
+					hoedown_buffer_putc(text, '\n');
+				end++;
+			}
+
+			beg = end;
+		}
+
+	/* pre-grow the output buffer to minimize allocations */
+	hoedown_buffer_grow(ob, text->size + (text->size >> 1));
+
+	/* second pass: actual rendering */
+	if (doc->md.doc_header)
+		doc->md.doc_header(ob, 0, &doc->data);
+
+	if (text->size) {
+		/* adding a final newline if not already present */
+		if (text->data[text->size - 1] != '\n' &&  text->data[text->size - 1] != '\r')
+			hoedown_buffer_putc(text, '\n');
+
+		parse_block(ob, doc, text->data, text->size);
+	}
+
+	/* footnotes */
+	if (footnotes_enabled)
+		parse_footnote_list(ob, doc, &doc->footnotes_used);
+
+	if (doc->md.doc_footer)
+		doc->md.doc_footer(ob, 0, &doc->data);
+
+	/* clean-up */
+	hoedown_buffer_free(text);
+	free_link_refs(doc->refs);
+	if (footnotes_enabled) {
+		free_footnote_list(&doc->footnotes_found, 1);
+		free_footnote_list(&doc->footnotes_used, 0);
+	}
+
+	assert(doc->work_bufs[BUFFER_SPAN].size == 0);
+	assert(doc->work_bufs[BUFFER_BLOCK].size == 0);
+}
+
+void
+hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size)
+{
+	size_t i = 0, mark;
+	hoedown_buffer *text = hoedown_buffer_new(64);
+
+	/* reset the references table */
+	memset(&doc->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
+
+	/* first pass: expand tabs and process newlines */
+	hoedown_buffer_grow(text, size);
+	while (1) {
+		mark = i;
+		while (i < size && data[i] != '\n' && data[i] != '\r')
+			i++;
+
+		expand_tabs(text, data + mark, i - mark);
+
+		if (i >= size)
+			break;
+
+		while (i < size && (data[i] == '\n' || data[i] == '\r')) {
+			/* add one \n per newline */
+			if (data[i] == '\n' || (i + 1 < size && data[i + 1] != '\n'))
+				hoedown_buffer_putc(text, '\n');
+			i++;
+		}
+	}
+
+	/* second pass: actual rendering */
+	hoedown_buffer_grow(ob, text->size + (text->size >> 1));
+
+	if (doc->md.doc_header)
+		doc->md.doc_header(ob, 1, &doc->data);
+
+	parse_inline(ob, doc, text->data, text->size);
+
+	if (doc->md.doc_footer)
+		doc->md.doc_footer(ob, 1, &doc->data);
+
+	/* clean-up */
+	hoedown_buffer_free(text);
+
+	assert(doc->work_bufs[BUFFER_SPAN].size == 0);
+	assert(doc->work_bufs[BUFFER_BLOCK].size == 0);
+}
+
+void
+hoedown_document_free(hoedown_document *doc)
+{
+	size_t i;
+
+	for (i = 0; i < (size_t)doc->work_bufs[BUFFER_SPAN].asize; ++i)
+		hoedown_buffer_free(doc->work_bufs[BUFFER_SPAN].item[i]);
+
+	for (i = 0; i < (size_t)doc->work_bufs[BUFFER_BLOCK].asize; ++i)
+		hoedown_buffer_free(doc->work_bufs[BUFFER_BLOCK].item[i]);
+
+	hoedown_stack_uninit(&doc->work_bufs[BUFFER_SPAN]);
+	hoedown_stack_uninit(&doc->work_bufs[BUFFER_BLOCK]);
+
+	free(doc);
+}

+ 172 - 0
modules/hoedown/hoedown/src/document.h

@@ -0,0 +1,172 @@
+/* document.h - generic markdown parser */
+
+#ifndef HOEDOWN_DOCUMENT_H
+#define HOEDOWN_DOCUMENT_H
+
+#include "buffer.h"
+#include "autolink.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************
+ * CONSTANTS *
+ *************/
+
+typedef enum hoedown_extensions {
+	/* block-level extensions */
+	HOEDOWN_EXT_TABLES = (1 << 0),
+	HOEDOWN_EXT_FENCED_CODE = (1 << 1),
+	HOEDOWN_EXT_FOOTNOTES = (1 << 2),
+
+	/* span-level extensions */
+	HOEDOWN_EXT_AUTOLINK = (1 << 3),
+	HOEDOWN_EXT_STRIKETHROUGH = (1 << 4),
+	HOEDOWN_EXT_UNDERLINE = (1 << 5),
+	HOEDOWN_EXT_HIGHLIGHT = (1 << 6),
+	HOEDOWN_EXT_QUOTE = (1 << 7),
+	HOEDOWN_EXT_SUPERSCRIPT = (1 << 8),
+	HOEDOWN_EXT_MATH = (1 << 9),
+
+	/* other flags */
+	HOEDOWN_EXT_NO_INTRA_EMPHASIS = (1 << 11),
+	HOEDOWN_EXT_SPACE_HEADERS = (1 << 12),
+	HOEDOWN_EXT_MATH_EXPLICIT = (1 << 13),
+
+	/* negative flags */
+	HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 14)
+} hoedown_extensions;
+
+#define HOEDOWN_EXT_BLOCK (\
+	HOEDOWN_EXT_TABLES |\
+	HOEDOWN_EXT_FENCED_CODE |\
+	HOEDOWN_EXT_FOOTNOTES )
+
+#define HOEDOWN_EXT_SPAN (\
+	HOEDOWN_EXT_AUTOLINK |\
+	HOEDOWN_EXT_STRIKETHROUGH |\
+	HOEDOWN_EXT_UNDERLINE |\
+	HOEDOWN_EXT_HIGHLIGHT |\
+	HOEDOWN_EXT_QUOTE |\
+	HOEDOWN_EXT_SUPERSCRIPT |\
+	HOEDOWN_EXT_MATH )
+
+#define HOEDOWN_EXT_FLAGS (\
+	HOEDOWN_EXT_NO_INTRA_EMPHASIS |\
+	HOEDOWN_EXT_SPACE_HEADERS |\
+	HOEDOWN_EXT_MATH_EXPLICIT )
+
+#define HOEDOWN_EXT_NEGATIVE (\
+	HOEDOWN_EXT_DISABLE_INDENTED_CODE )
+
+typedef enum hoedown_list_flags {
+	HOEDOWN_LIST_ORDERED = (1 << 0),
+	HOEDOWN_LI_BLOCK = (1 << 1)	/* <li> containing block data */
+} hoedown_list_flags;
+
+typedef enum hoedown_table_flags {
+	HOEDOWN_TABLE_ALIGN_LEFT = 1,
+	HOEDOWN_TABLE_ALIGN_RIGHT = 2,
+	HOEDOWN_TABLE_ALIGN_CENTER = 3,
+	HOEDOWN_TABLE_ALIGNMASK = 3,
+	HOEDOWN_TABLE_HEADER = 4
+} hoedown_table_flags;
+
+typedef enum hoedown_autolink_type {
+	HOEDOWN_AUTOLINK_NONE,		/* used internally when it is not an autolink*/
+	HOEDOWN_AUTOLINK_NORMAL,	/* normal http/http/ftp/mailto/etc link */
+	HOEDOWN_AUTOLINK_EMAIL		/* e-mail link without explit mailto: */
+} hoedown_autolink_type;
+
+
+/*********
+ * TYPES *
+ *********/
+
+struct hoedown_document;
+typedef struct hoedown_document hoedown_document;
+
+struct hoedown_renderer_data {
+	void *opaque;
+};
+typedef struct hoedown_renderer_data hoedown_renderer_data;
+
+/* hoedown_renderer - functions for rendering parsed data */
+struct hoedown_renderer {
+	/* state object */
+	void *opaque;
+
+	/* block level callbacks - NULL skips the block */
+	void (*blockcode)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data);
+	void (*blockquote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	void (*header)(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data);
+	void (*hrule)(hoedown_buffer *ob, const hoedown_renderer_data *data);
+	void (*list)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data);
+	void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data);
+	void (*paragraph)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	void (*table)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	void (*table_header)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	void (*table_body)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	void (*table_row)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data);
+	void (*footnotes)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	void (*footnote_def)(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data);
+	void (*blockhtml)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+
+	/* span level callbacks - NULL or return 0 prints the span verbatim */
+	int (*autolink)(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data);
+	int (*codespan)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+	int (*double_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	int (*emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	int (*underline)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	int (*highlight)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	int (*quote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	int (*image)(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data);
+	int (*linebreak)(hoedown_buffer *ob, const hoedown_renderer_data *data);
+	int (*link)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data);
+	int (*triple_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	int (*strikethrough)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	int (*superscript)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+	int (*footnote_ref)(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data);
+	int (*math)(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data);
+	int (*raw_html)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+
+	/* low level callbacks - NULL copies input directly into the output */
+	void (*entity)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+	void (*normal_text)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+
+	/* miscellaneous callbacks */
+	void (*doc_header)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data);
+	void (*doc_footer)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data);
+};
+typedef struct hoedown_renderer hoedown_renderer;
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_document_new: allocate a new document processor instance */
+hoedown_document *hoedown_document_new(
+	const hoedown_renderer *renderer,
+	hoedown_extensions extensions,
+	size_t max_nesting
+) __attribute__ ((malloc));
+
+/* hoedown_document_render: render regular Markdown using the document processor */
+void hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size);
+
+/* hoedown_document_render_inline: render inline Markdown using the document processor */
+void hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size);
+
+/* hoedown_document_free: deallocate a document processor instance */
+void hoedown_document_free(hoedown_document *doc);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_DOCUMENT_H **/

+ 188 - 0
modules/hoedown/hoedown/src/escape.c

@@ -0,0 +1,188 @@
+#include "escape.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#define likely(x)       __builtin_expect((x),1)
+#define unlikely(x)     __builtin_expect((x),0)
+
+
+/*
+ * The following characters will not be escaped:
+ *
+ *		-_.+!*'(),%#@?=;:/,+&$ alphanum
+ *
+ * Note that this character set is the addition of:
+ *
+ *	- The characters which are safe to be in an URL
+ *	- The characters which are *not* safe to be in
+ *	an URL because they are RESERVED characters.
+ *
+ * We assume (lazily) that any RESERVED char that
+ * appears inside an URL is actually meant to
+ * have its native function (i.e. as an URL
+ * component/separator) and hence needs no escaping.
+ *
+ * There are two exceptions: the chacters & (amp)
+ * and ' (single quote) do not appear in the table.
+ * They are meant to appear in the URL as components,
+ * yet they require special HTML-entity escaping
+ * to generate valid HTML markup.
+ *
+ * All other characters will be escaped to %XX.
+ *
+ */
+static const uint8_t HREF_SAFE[UINT8_MAX+1] = {
+	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, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 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, 0, 0, 0, 0, 1,
+	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, 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, 0, 0, 0, 0, 0, 0,
+};
+
+void
+hoedown_escape_href(hoedown_buffer *ob, const uint8_t *data, size_t size)
+{
+	static const char hex_chars[] = "0123456789ABCDEF";
+	size_t  i = 0, mark;
+	char hex_str[3];
+
+	hex_str[0] = '%';
+
+	while (i < size) {
+		mark = i;
+		while (i < size && HREF_SAFE[data[i]]) i++;
+
+		/* Optimization for cases where there's nothing to escape */
+		if (mark == 0 && i >= size) {
+			hoedown_buffer_put(ob, data, size);
+			return;
+		}
+
+		if (likely(i > mark)) {
+			hoedown_buffer_put(ob, data + mark, i - mark);
+		}
+
+		/* escaping */
+		if (i >= size)
+			break;
+
+		switch (data[i]) {
+		/* amp appears all the time in URLs, but needs
+		 * HTML-entity escaping to be inside an href */
+		case '&':
+			HOEDOWN_BUFPUTSL(ob, "&amp;");
+			break;
+
+		/* the single quote is a valid URL character
+		 * according to the standard; it needs HTML
+		 * entity escaping too */
+		case '\'':
+			HOEDOWN_BUFPUTSL(ob, "&#x27;");
+			break;
+
+		/* the space can be escaped to %20 or a plus
+		 * sign. we're going with the generic escape
+		 * for now. the plus thing is more commonly seen
+		 * when building GET strings */
+#if 0
+		case ' ':
+			hoedown_buffer_putc(ob, '+');
+			break;
+#endif
+
+		/* every other character goes with a %XX escaping */
+		default:
+			hex_str[1] = hex_chars[(data[i] >> 4) & 0xF];
+			hex_str[2] = hex_chars[data[i] & 0xF];
+			hoedown_buffer_put(ob, (uint8_t *)hex_str, 3);
+		}
+
+		i++;
+	}
+}
+
+
+/**
+ * According to the OWASP rules:
+ *
+ * & --> &amp;
+ * < --> &lt;
+ * > --> &gt;
+ * " --> &quot;
+ * ' --> &#x27;     &apos; is not recommended
+ * / --> &#x2F;     forward slash is included as it helps end an HTML entity
+ *
+ */
+static const uint8_t HTML_ESCAPE_TABLE[UINT8_MAX+1] = {
+	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, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 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, 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,
+};
+
+static const char *HTML_ESCAPES[] = {
+        "",
+        "&quot;",
+        "&amp;",
+        "&#39;",
+        "&#47;",
+        "&lt;",
+        "&gt;"
+};
+
+void
+hoedown_escape_html(hoedown_buffer *ob, const uint8_t *data, size_t size, int secure)
+{
+	size_t i = 0, mark;
+
+	while (1) {
+		mark = i;
+		while (i < size && HTML_ESCAPE_TABLE[data[i]] == 0) i++;
+
+		/* Optimization for cases where there's nothing to escape */
+		if (mark == 0 && i >= size) {
+			hoedown_buffer_put(ob, data, size);
+			return;
+		}
+
+		if (likely(i > mark))
+			hoedown_buffer_put(ob, data + mark, i - mark);
+
+		if (i >= size) break;
+
+		/* The forward slash is only escaped in secure mode */
+		if (!secure && data[i] == '/') {
+			hoedown_buffer_putc(ob, '/');
+		} else {
+			hoedown_buffer_puts(ob, HTML_ESCAPES[HTML_ESCAPE_TABLE[data[i]]]);
+		}
+
+		i++;
+	}
+}

+ 28 - 0
modules/hoedown/hoedown/src/escape.h

@@ -0,0 +1,28 @@
+/* escape.h - escape utilities */
+
+#ifndef HOEDOWN_ESCAPE_H
+#define HOEDOWN_ESCAPE_H
+
+#include "buffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_escape_href: escape (part of) a URL inside HTML */
+void hoedown_escape_href(hoedown_buffer *ob, const uint8_t *data, size_t size);
+
+/* hoedown_escape_html: escape HTML */
+void hoedown_escape_html(hoedown_buffer *ob, const uint8_t *data, size_t size, int secure);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_ESCAPE_H **/

+ 754 - 0
modules/hoedown/hoedown/src/html.c

@@ -0,0 +1,754 @@
+#include "html.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "escape.h"
+
+#define USE_XHTML(opt) (opt->flags & HOEDOWN_HTML_USE_XHTML)
+
+hoedown_html_tag
+hoedown_html_is_tag(const uint8_t *data, size_t size, const char *tagname)
+{
+	size_t i;
+	int closed = 0;
+
+	if (size < 3 || data[0] != '<')
+		return HOEDOWN_HTML_TAG_NONE;
+
+	i = 1;
+
+	if (data[i] == '/') {
+		closed = 1;
+		i++;
+	}
+
+	for (; i < size; ++i, ++tagname) {
+		if (*tagname == 0)
+			break;
+
+		if (data[i] != *tagname)
+			return HOEDOWN_HTML_TAG_NONE;
+	}
+
+	if (i == size)
+		return HOEDOWN_HTML_TAG_NONE;
+
+	if (isspace(data[i]) || data[i] == '>')
+		return closed ? HOEDOWN_HTML_TAG_CLOSE : HOEDOWN_HTML_TAG_OPEN;
+
+	return HOEDOWN_HTML_TAG_NONE;
+}
+
+static void escape_html(hoedown_buffer *ob, const uint8_t *source, size_t length)
+{
+	hoedown_escape_html(ob, source, length, 0);
+}
+
+static void escape_href(hoedown_buffer *ob, const uint8_t *source, size_t length)
+{
+	hoedown_escape_href(ob, source, length);
+}
+
+/********************
+ * GENERIC RENDERER *
+ ********************/
+static int
+rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state = data->opaque;
+
+	if (!link || !link->size)
+		return 0;
+
+	HOEDOWN_BUFPUTSL(ob, "<a href=\"");
+	if (type == HOEDOWN_AUTOLINK_EMAIL)
+		HOEDOWN_BUFPUTSL(ob, "mailto:");
+	escape_href(ob, link->data, link->size);
+
+	if (state->link_attributes) {
+		hoedown_buffer_putc(ob, '\"');
+		state->link_attributes(ob, link, data);
+		hoedown_buffer_putc(ob, '>');
+	} else {
+		HOEDOWN_BUFPUTSL(ob, "\">");
+	}
+
+	/*
+	 * Pretty printing: if we get an email address as
+	 * an actual URI, e.g. `mailto:[email protected]`, we don't
+	 * want to print the `mailto:` prefix
+	 */
+	if (hoedown_buffer_prefix(link, "mailto:") == 0) {
+		escape_html(ob, link->data + 7, link->size - 7);
+	} else {
+		escape_html(ob, link->data, link->size);
+	}
+
+	HOEDOWN_BUFPUTSL(ob, "</a>");
+
+	return 1;
+}
+
+static void
+rndr_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data)
+{
+	if (ob->size) hoedown_buffer_putc(ob, '\n');
+
+	if (lang) {
+		HOEDOWN_BUFPUTSL(ob, "<pre><code class=\"language-");
+		escape_html(ob, lang->data, lang->size);
+		HOEDOWN_BUFPUTSL(ob, "\">");
+	} else {
+		HOEDOWN_BUFPUTSL(ob, "<pre><code>");
+	}
+
+	if (text)
+		escape_html(ob, text->data, text->size);
+
+	HOEDOWN_BUFPUTSL(ob, "</code></pre>\n");
+}
+
+static void
+rndr_blockquote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	if (ob->size) hoedown_buffer_putc(ob, '\n');
+	HOEDOWN_BUFPUTSL(ob, "<blockquote>\n");
+	if (content) hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</blockquote>\n");
+}
+
+static int
+rndr_codespan(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)
+{
+	HOEDOWN_BUFPUTSL(ob, "<code>");
+	if (text) escape_html(ob, text->data, text->size);
+	HOEDOWN_BUFPUTSL(ob, "</code>");
+	return 1;
+}
+
+static int
+rndr_strikethrough(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	if (!content || !content->size)
+		return 0;
+
+	HOEDOWN_BUFPUTSL(ob, "<del>");
+	hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</del>");
+	return 1;
+}
+
+static int
+rndr_double_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	if (!content || !content->size)
+		return 0;
+
+	HOEDOWN_BUFPUTSL(ob, "<strong>");
+	hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</strong>");
+
+	return 1;
+}
+
+static int
+rndr_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	if (!content || !content->size) return 0;
+	HOEDOWN_BUFPUTSL(ob, "<em>");
+	if (content) hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</em>");
+	return 1;
+}
+
+static int
+rndr_underline(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	if (!content || !content->size)
+		return 0;
+
+	HOEDOWN_BUFPUTSL(ob, "<u>");
+	hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</u>");
+
+	return 1;
+}
+
+static int
+rndr_highlight(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	if (!content || !content->size)
+		return 0;
+
+	HOEDOWN_BUFPUTSL(ob, "<mark>");
+	hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</mark>");
+
+	return 1;
+}
+
+static int
+rndr_quote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	if (!content || !content->size)
+		return 0;
+
+	HOEDOWN_BUFPUTSL(ob, "<q>");
+	hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</q>");
+
+	return 1;
+}
+
+static int
+rndr_linebreak(hoedown_buffer *ob, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state = data->opaque;
+	hoedown_buffer_puts(ob, USE_XHTML(state) ? "<br/>\n" : "<br>\n");
+	return 1;
+}
+
+static void
+rndr_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state = data->opaque;
+
+	if (ob->size)
+		hoedown_buffer_putc(ob, '\n');
+
+	if (level <= state->toc_data.nesting_level)
+		hoedown_buffer_printf(ob, "<h%d id=\"toc_%d\">", level, state->toc_data.header_count++);
+	else
+		hoedown_buffer_printf(ob, "<h%d>", level);
+
+	if (content) hoedown_buffer_put(ob, content->data, content->size);
+	hoedown_buffer_printf(ob, "</h%d>\n", level);
+}
+
+static int
+rndr_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state = data->opaque;
+
+	HOEDOWN_BUFPUTSL(ob, "<a href=\"");
+
+	if (link && link->size)
+		escape_href(ob, link->data, link->size);
+
+	if (title && title->size) {
+		HOEDOWN_BUFPUTSL(ob, "\" title=\"");
+		escape_html(ob, title->data, title->size);
+	}
+
+	if (state->link_attributes) {
+		hoedown_buffer_putc(ob, '\"');
+		state->link_attributes(ob, link, data);
+		hoedown_buffer_putc(ob, '>');
+	} else {
+		HOEDOWN_BUFPUTSL(ob, "\">");
+	}
+
+	if (content && content->size) hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</a>");
+	return 1;
+}
+
+static void
+rndr_list(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data)
+{
+	if (ob->size) hoedown_buffer_putc(ob, '\n');
+	hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "<ol>\n" : "<ul>\n"), 5);
+	if (content) hoedown_buffer_put(ob, content->data, content->size);
+	hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "</ol>\n" : "</ul>\n"), 6);
+}
+
+static void
+rndr_listitem(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data)
+{
+	HOEDOWN_BUFPUTSL(ob, "<li>");
+	if (content) {
+		size_t size = content->size;
+		while (size && content->data[size - 1] == '\n')
+			size--;
+
+		hoedown_buffer_put(ob, content->data, size);
+	}
+	HOEDOWN_BUFPUTSL(ob, "</li>\n");
+}
+
+static void
+rndr_paragraph(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state = data->opaque;
+	size_t i = 0;
+
+	if (ob->size) hoedown_buffer_putc(ob, '\n');
+
+	if (!content || !content->size)
+		return;
+
+	while (i < content->size && isspace(content->data[i])) i++;
+
+	if (i == content->size)
+		return;
+
+	HOEDOWN_BUFPUTSL(ob, "<p>");
+	if (state->flags & HOEDOWN_HTML_HARD_WRAP) {
+		size_t org;
+		while (i < content->size) {
+			org = i;
+			while (i < content->size && content->data[i] != '\n')
+				i++;
+
+			if (i > org)
+				hoedown_buffer_put(ob, content->data + org, i - org);
+
+			/*
+			 * do not insert a line break if this newline
+			 * is the last character on the paragraph
+			 */
+			if (i >= content->size - 1)
+				break;
+
+			rndr_linebreak(ob, data);
+			i++;
+		}
+	} else {
+		hoedown_buffer_put(ob, content->data + i, content->size - i);
+	}
+	HOEDOWN_BUFPUTSL(ob, "</p>\n");
+}
+
+static void
+rndr_raw_block(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)
+{
+	size_t org, sz;
+
+	if (!text)
+		return;
+
+	/* FIXME: Do we *really* need to trim the HTML? How does that make a difference? */
+	sz = text->size;
+	while (sz > 0 && text->data[sz - 1] == '\n')
+		sz--;
+
+	org = 0;
+	while (org < sz && text->data[org] == '\n')
+		org++;
+
+	if (org >= sz)
+		return;
+
+	if (ob->size)
+		hoedown_buffer_putc(ob, '\n');
+
+	hoedown_buffer_put(ob, text->data + org, sz - org);
+	hoedown_buffer_putc(ob, '\n');
+}
+
+static int
+rndr_triple_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	if (!content || !content->size) return 0;
+	HOEDOWN_BUFPUTSL(ob, "<strong><em>");
+	hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</em></strong>");
+	return 1;
+}
+
+static void
+rndr_hrule(hoedown_buffer *ob, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state = data->opaque;
+	if (ob->size) hoedown_buffer_putc(ob, '\n');
+	hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
+}
+
+static int
+rndr_image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state = data->opaque;
+	if (!link || !link->size) return 0;
+
+	HOEDOWN_BUFPUTSL(ob, "<img src=\"");
+	escape_href(ob, link->data, link->size);
+	HOEDOWN_BUFPUTSL(ob, "\" alt=\"");
+
+	if (alt && alt->size)
+		escape_html(ob, alt->data, alt->size);
+
+	if (title && title->size) {
+		HOEDOWN_BUFPUTSL(ob, "\" title=\"");
+		escape_html(ob, title->data, title->size); }
+
+	hoedown_buffer_puts(ob, USE_XHTML(state) ? "\"/>" : "\">");
+	return 1;
+}
+
+static int
+rndr_raw_html(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state = data->opaque;
+
+	/* ESCAPE overrides SKIP_HTML. It doesn't look to see if
+	 * there are any valid tags, just escapes all of them. */
+	if((state->flags & HOEDOWN_HTML_ESCAPE) != 0) {
+		escape_html(ob, text->data, text->size);
+		return 1;
+	}
+
+	if ((state->flags & HOEDOWN_HTML_SKIP_HTML) != 0)
+		return 1;
+
+	hoedown_buffer_put(ob, text->data, text->size);
+	return 1;
+}
+
+static void
+rndr_table(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+    if (ob->size) hoedown_buffer_putc(ob, '\n');
+    HOEDOWN_BUFPUTSL(ob, "<table>\n");
+    hoedown_buffer_put(ob, content->data, content->size);
+    HOEDOWN_BUFPUTSL(ob, "</table>\n");
+}
+
+static void
+rndr_table_header(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+    if (ob->size) hoedown_buffer_putc(ob, '\n');
+    HOEDOWN_BUFPUTSL(ob, "<thead>\n");
+    hoedown_buffer_put(ob, content->data, content->size);
+    HOEDOWN_BUFPUTSL(ob, "</thead>\n");
+}
+
+static void
+rndr_table_body(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+    if (ob->size) hoedown_buffer_putc(ob, '\n');
+    HOEDOWN_BUFPUTSL(ob, "<tbody>\n");
+    hoedown_buffer_put(ob, content->data, content->size);
+    HOEDOWN_BUFPUTSL(ob, "</tbody>\n");
+}
+
+static void
+rndr_tablerow(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	HOEDOWN_BUFPUTSL(ob, "<tr>\n");
+	if (content) hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</tr>\n");
+}
+
+static void
+rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data)
+{
+	if (flags & HOEDOWN_TABLE_HEADER) {
+		HOEDOWN_BUFPUTSL(ob, "<th");
+	} else {
+		HOEDOWN_BUFPUTSL(ob, "<td");
+	}
+
+	switch (flags & HOEDOWN_TABLE_ALIGNMASK) {
+	case HOEDOWN_TABLE_ALIGN_CENTER:
+		HOEDOWN_BUFPUTSL(ob, " style=\"text-align: center\">");
+		break;
+
+	case HOEDOWN_TABLE_ALIGN_LEFT:
+		HOEDOWN_BUFPUTSL(ob, " style=\"text-align: left\">");
+		break;
+
+	case HOEDOWN_TABLE_ALIGN_RIGHT:
+		HOEDOWN_BUFPUTSL(ob, " style=\"text-align: right\">");
+		break;
+
+	default:
+		HOEDOWN_BUFPUTSL(ob, ">");
+	}
+
+	if (content)
+		hoedown_buffer_put(ob, content->data, content->size);
+
+	if (flags & HOEDOWN_TABLE_HEADER) {
+		HOEDOWN_BUFPUTSL(ob, "</th>\n");
+	} else {
+		HOEDOWN_BUFPUTSL(ob, "</td>\n");
+	}
+}
+
+static int
+rndr_superscript(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	if (!content || !content->size) return 0;
+	HOEDOWN_BUFPUTSL(ob, "<sup>");
+	hoedown_buffer_put(ob, content->data, content->size);
+	HOEDOWN_BUFPUTSL(ob, "</sup>");
+	return 1;
+}
+
+static void
+rndr_normal_text(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	if (content)
+		escape_html(ob, content->data, content->size);
+}
+
+static void
+rndr_footnotes(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state = data->opaque;
+
+	if (ob->size) hoedown_buffer_putc(ob, '\n');
+	HOEDOWN_BUFPUTSL(ob, "<div class=\"footnotes\">\n");
+	hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
+	HOEDOWN_BUFPUTSL(ob, "<ol>\n");
+
+	if (content) hoedown_buffer_put(ob, content->data, content->size);
+
+	HOEDOWN_BUFPUTSL(ob, "\n</ol>\n</div>\n");
+}
+
+static void
+rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data)
+{
+	size_t i = 0;
+	int pfound = 0;
+
+	/* insert anchor at the end of first paragraph block */
+	if (content) {
+		while ((i+3) < content->size) {
+			if (content->data[i++] != '<') continue;
+			if (content->data[i++] != '/') continue;
+			if (content->data[i++] != 'p' && content->data[i] != 'P') continue;
+			if (content->data[i] != '>') continue;
+			i -= 3;
+			pfound = 1;
+			break;
+		}
+	}
+
+	hoedown_buffer_printf(ob, "\n<li id=\"fn%d\">\n", num);
+	if (pfound) {
+		hoedown_buffer_put(ob, content->data, i);
+		hoedown_buffer_printf(ob, "&nbsp;<a href=\"#fnref%d\" rev=\"footnote\">&#8617;</a>", num);
+		hoedown_buffer_put(ob, content->data + i, content->size - i);
+	} else if (content) {
+		hoedown_buffer_put(ob, content->data, content->size);
+	}
+	HOEDOWN_BUFPUTSL(ob, "</li>\n");
+}
+
+static int
+rndr_footnote_ref(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data)
+{
+	hoedown_buffer_printf(ob, "<sup id=\"fnref%d\"><a href=\"#fn%d\" rel=\"footnote\">%d</a></sup>", num, num, num);
+	return 1;
+}
+
+static int
+rndr_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data)
+{
+	hoedown_buffer_put(ob, (const uint8_t *)(displaymode ? "\\[" : "\\("), 2);
+	escape_html(ob, text->data, text->size);
+	hoedown_buffer_put(ob, (const uint8_t *)(displaymode ? "\\]" : "\\)"), 2);
+	return 1;
+}
+
+static void
+toc_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state = data->opaque;
+
+	if (level <= state->toc_data.nesting_level) {
+		/* set the level offset if this is the first header
+		 * we're parsing for the document */
+		if (state->toc_data.current_level == 0)
+			state->toc_data.level_offset = level - 1;
+
+		level -= state->toc_data.level_offset;
+
+		if (level > state->toc_data.current_level) {
+			while (level > state->toc_data.current_level) {
+				HOEDOWN_BUFPUTSL(ob, "<ul>\n<li>\n");
+				state->toc_data.current_level++;
+			}
+		} else if (level < state->toc_data.current_level) {
+			HOEDOWN_BUFPUTSL(ob, "</li>\n");
+			while (level < state->toc_data.current_level) {
+				HOEDOWN_BUFPUTSL(ob, "</ul>\n</li>\n");
+				state->toc_data.current_level--;
+			}
+			HOEDOWN_BUFPUTSL(ob,"<li>\n");
+		} else {
+			HOEDOWN_BUFPUTSL(ob,"</li>\n<li>\n");
+		}
+
+		hoedown_buffer_printf(ob, "<a href=\"#toc_%d\">", state->toc_data.header_count++);
+		if (content) hoedown_buffer_put(ob, content->data, content->size);
+		HOEDOWN_BUFPUTSL(ob, "</a>\n");
+	}
+}
+
+static int
+toc_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data)
+{
+	if (content && content->size) hoedown_buffer_put(ob, content->data, content->size);
+	return 1;
+}
+
+static void
+toc_finalize(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data)
+{
+	hoedown_html_renderer_state *state;
+
+	if (inline_render)
+		return;
+
+	state = data->opaque;
+
+	while (state->toc_data.current_level > 0) {
+		HOEDOWN_BUFPUTSL(ob, "</li>\n</ul>\n");
+		state->toc_data.current_level--;
+	}
+
+	state->toc_data.header_count = 0;
+}
+
+hoedown_renderer *
+hoedown_html_toc_renderer_new(int nesting_level)
+{
+	static const hoedown_renderer cb_default = {
+		NULL,
+
+		NULL,
+		NULL,
+		toc_header,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+
+		NULL,
+		rndr_codespan,
+		rndr_double_emphasis,
+		rndr_emphasis,
+		rndr_underline,
+		rndr_highlight,
+		rndr_quote,
+		NULL,
+		NULL,
+		toc_link,
+		rndr_triple_emphasis,
+		rndr_strikethrough,
+		rndr_superscript,
+		NULL,
+		NULL,
+		NULL,
+
+		NULL,
+		rndr_normal_text,
+
+		NULL,
+		toc_finalize
+	};
+
+	hoedown_html_renderer_state *state;
+	hoedown_renderer *renderer;
+
+	/* Prepare the state pointer */
+	state = hoedown_malloc(sizeof(hoedown_html_renderer_state));
+	memset(state, 0x0, sizeof(hoedown_html_renderer_state));
+
+	state->toc_data.nesting_level = nesting_level;
+
+	/* Prepare the renderer */
+	renderer = hoedown_malloc(sizeof(hoedown_renderer));
+	memcpy(renderer, &cb_default, sizeof(hoedown_renderer));
+
+	renderer->opaque = state;
+	return renderer;
+}
+
+hoedown_renderer *
+hoedown_html_renderer_new(hoedown_html_flags render_flags, int nesting_level)
+{
+	static const hoedown_renderer cb_default = {
+		NULL,
+
+		rndr_blockcode,
+		rndr_blockquote,
+		rndr_header,
+		rndr_hrule,
+		rndr_list,
+		rndr_listitem,
+		rndr_paragraph,
+		rndr_table,
+		rndr_table_header,
+		rndr_table_body,
+		rndr_tablerow,
+		rndr_tablecell,
+		rndr_footnotes,
+		rndr_footnote_def,
+		rndr_raw_block,
+
+		rndr_autolink,
+		rndr_codespan,
+		rndr_double_emphasis,
+		rndr_emphasis,
+		rndr_underline,
+		rndr_highlight,
+		rndr_quote,
+		rndr_image,
+		rndr_linebreak,
+		rndr_link,
+		rndr_triple_emphasis,
+		rndr_strikethrough,
+		rndr_superscript,
+		rndr_footnote_ref,
+		rndr_math,
+		rndr_raw_html,
+
+		NULL,
+		rndr_normal_text,
+
+		NULL,
+		NULL
+	};
+
+	hoedown_html_renderer_state *state;
+	hoedown_renderer *renderer;
+
+	/* Prepare the state pointer */
+	state = hoedown_malloc(sizeof(hoedown_html_renderer_state));
+	memset(state, 0x0, sizeof(hoedown_html_renderer_state));
+
+	state->flags = render_flags;
+	state->toc_data.nesting_level = nesting_level;
+
+	/* Prepare the renderer */
+	renderer = hoedown_malloc(sizeof(hoedown_renderer));
+	memcpy(renderer, &cb_default, sizeof(hoedown_renderer));
+
+	if (render_flags & HOEDOWN_HTML_SKIP_HTML || render_flags & HOEDOWN_HTML_ESCAPE)
+		renderer->blockhtml = NULL;
+
+	renderer->opaque = state;
+	return renderer;
+}
+
+void
+hoedown_html_renderer_free(hoedown_renderer *renderer)
+{
+	free(renderer->opaque);
+	free(renderer);
+}

+ 84 - 0
modules/hoedown/hoedown/src/html.h

@@ -0,0 +1,84 @@
+/* html.h - HTML renderer and utilities */
+
+#ifndef HOEDOWN_HTML_H
+#define HOEDOWN_HTML_H
+
+#include "document.h"
+#include "buffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************
+ * CONSTANTS *
+ *************/
+
+typedef enum hoedown_html_flags {
+	HOEDOWN_HTML_SKIP_HTML = (1 << 0),
+	HOEDOWN_HTML_ESCAPE = (1 << 1),
+	HOEDOWN_HTML_HARD_WRAP = (1 << 2),
+	HOEDOWN_HTML_USE_XHTML = (1 << 3)
+} hoedown_html_flags;
+
+typedef enum hoedown_html_tag {
+	HOEDOWN_HTML_TAG_NONE = 0,
+	HOEDOWN_HTML_TAG_OPEN,
+	HOEDOWN_HTML_TAG_CLOSE
+} hoedown_html_tag;
+
+
+/*********
+ * TYPES *
+ *********/
+
+struct hoedown_html_renderer_state {
+	void *opaque;
+
+	struct {
+		int header_count;
+		int current_level;
+		int level_offset;
+		int nesting_level;
+	} toc_data;
+
+	hoedown_html_flags flags;
+
+	/* extra callbacks */
+	void (*link_attributes)(hoedown_buffer *ob, const hoedown_buffer *url, const hoedown_renderer_data *data);
+};
+typedef struct hoedown_html_renderer_state hoedown_html_renderer_state;
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_html_smartypants: process an HTML snippet using SmartyPants for smart punctuation */
+void hoedown_html_smartypants(hoedown_buffer *ob, const uint8_t *data, size_t size);
+
+/* hoedown_html_is_tag: checks if data starts with a specific tag, returns the tag type or NONE */
+hoedown_html_tag hoedown_html_is_tag(const uint8_t *data, size_t size, const char *tagname);
+
+
+/* hoedown_html_renderer_new: allocates a regular HTML renderer */
+hoedown_renderer *hoedown_html_renderer_new(
+	hoedown_html_flags render_flags,
+	int nesting_level
+) __attribute__ ((malloc));
+
+/* hoedown_html_toc_renderer_new: like hoedown_html_renderer_new, but the returned renderer produces the Table of Contents */
+hoedown_renderer *hoedown_html_toc_renderer_new(
+	int nesting_level
+) __attribute__ ((malloc));
+
+/* hoedown_html_renderer_free: deallocate an HTML renderer */
+void hoedown_html_renderer_free(hoedown_renderer *renderer);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_HTML_H **/

+ 240 - 0
modules/hoedown/hoedown/src/html_blocks.c

@@ -0,0 +1,240 @@
+/* ANSI-C code produced by gperf version 3.0.3 */
+/* Command-line: gperf -L ANSI-C -N hoedown_find_block_tag -c -C -E -S 1 --ignore-case -m100 html_block_names.gperf  */
+/* Computed positions: -k'1-2' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646.  */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <[email protected]>."
+#endif
+
+/* maximum key range = 24, duplicates = 0 */
+
+#ifndef GPERF_DOWNCASE
+#define GPERF_DOWNCASE 1
+static unsigned char gperf_downcase[256] =
+  {
+      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,  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,  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, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+    255
+  };
+#endif
+
+#ifndef GPERF_CASE_STRNCMP
+#define GPERF_CASE_STRNCMP 1
+static int
+gperf_case_strncmp (register const char *s1, register const char *s2, register unsigned int n)
+{
+  for (; n > 0;)
+    {
+      unsigned char c1 = gperf_downcase[(unsigned char)*s1++];
+      unsigned char c2 = gperf_downcase[(unsigned char)*s2++];
+      if (c1 != 0 && c1 == c2)
+        {
+          n--;
+          continue;
+        }
+      return (int)c1 - (int)c2;
+    }
+  return 0;
+}
+#endif
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash (register const char *str, register unsigned int len)
+{
+  static const unsigned char asso_values[] =
+    {
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      22, 21, 19, 18, 16,  0, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25,  1, 25,  0, 25,
+       1,  0,  0, 13,  0, 25, 25, 11,  2,  1,
+       0, 25, 25,  5,  0,  2, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25,  1, 25,
+       0, 25,  1,  0,  0, 13,  0, 25, 25, 11,
+       2,  1,  0, 25, 25,  5,  0,  2, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+      25, 25, 25, 25, 25, 25, 25
+    };
+  register int hval = (int)len;
+
+  switch (hval)
+    {
+      default:
+        hval += asso_values[(unsigned char)str[1]+1];
+      /*FALLTHROUGH*/
+      case 1:
+        hval += asso_values[(unsigned char)str[0]];
+        break;
+    }
+  return hval;
+}
+
+#ifdef __GNUC__
+__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const char *
+hoedown_find_block_tag (register const char *str, register unsigned int len)
+{
+  enum
+    {
+      TOTAL_KEYWORDS = 24,
+      MIN_WORD_LENGTH = 1,
+      MAX_WORD_LENGTH = 10,
+      MIN_HASH_VALUE = 1,
+      MAX_HASH_VALUE = 24
+    };
+
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
+        {
+          register const char *resword;
+
+          switch (key - 1)
+            {
+              case 0:
+                resword = "p";
+                goto compare;
+              case 1:
+                resword = "h6";
+                goto compare;
+              case 2:
+                resword = "div";
+                goto compare;
+              case 3:
+                resword = "del";
+                goto compare;
+              case 4:
+                resword = "form";
+                goto compare;
+              case 5:
+                resword = "table";
+                goto compare;
+              case 6:
+                resword = "figure";
+                goto compare;
+              case 7:
+                resword = "pre";
+                goto compare;
+              case 8:
+                resword = "fieldset";
+                goto compare;
+              case 9:
+                resword = "noscript";
+                goto compare;
+              case 10:
+                resword = "script";
+                goto compare;
+              case 11:
+                resword = "style";
+                goto compare;
+              case 12:
+                resword = "dl";
+                goto compare;
+              case 13:
+                resword = "ol";
+                goto compare;
+              case 14:
+                resword = "ul";
+                goto compare;
+              case 15:
+                resword = "math";
+                goto compare;
+              case 16:
+                resword = "ins";
+                goto compare;
+              case 17:
+                resword = "h5";
+                goto compare;
+              case 18:
+                resword = "iframe";
+                goto compare;
+              case 19:
+                resword = "h4";
+                goto compare;
+              case 20:
+                resword = "h3";
+                goto compare;
+              case 21:
+                resword = "blockquote";
+                goto compare;
+              case 22:
+                resword = "h2";
+                goto compare;
+              case 23:
+                resword = "h1";
+                goto compare;
+            }
+          return 0;
+        compare:
+          if ((((unsigned char)*str ^ (unsigned char)*resword) & ~32) == 0 && !gperf_case_strncmp (str, resword, len) && resword[len] == '\0')
+            return resword;
+        }
+    }
+  return 0;
+}

+ 435 - 0
modules/hoedown/hoedown/src/html_smartypants.c

@@ -0,0 +1,435 @@
+#include "html.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+struct smartypants_data {
+	int in_squote;
+	int in_dquote;
+};
+
+static size_t smartypants_cb__ltag(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
+static size_t smartypants_cb__dquote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
+static size_t smartypants_cb__amp(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
+static size_t smartypants_cb__period(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
+static size_t smartypants_cb__number(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
+static size_t smartypants_cb__dash(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
+static size_t smartypants_cb__parens(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
+static size_t smartypants_cb__squote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
+static size_t smartypants_cb__backtick(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
+static size_t smartypants_cb__escape(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
+
+static size_t (*smartypants_cb_ptrs[])
+	(hoedown_buffer *, struct smartypants_data *, uint8_t, const uint8_t *, size_t) =
+{
+	NULL,					/* 0 */
+	smartypants_cb__dash,	/* 1 */
+	smartypants_cb__parens,	/* 2 */
+	smartypants_cb__squote, /* 3 */
+	smartypants_cb__dquote, /* 4 */
+	smartypants_cb__amp,	/* 5 */
+	smartypants_cb__period,	/* 6 */
+	smartypants_cb__number,	/* 7 */
+	smartypants_cb__ltag,	/* 8 */
+	smartypants_cb__backtick, /* 9 */
+	smartypants_cb__escape, /* 10 */
+};
+
+static const uint8_t smartypants_cb_chars[UINT8_MAX+1] = {
+	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, 4, 0, 0, 0, 5, 3, 2, 0, 0, 0, 0, 1, 6, 0,
+	0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 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, 10, 0, 0, 0,
+	9, 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,
+	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,
+};
+
+static int
+word_boundary(uint8_t c)
+{
+	return c == 0 || isspace(c) || ispunct(c);
+}
+
+/*
+	If 'text' begins with any kind of single quote (e.g. "'" or "&apos;" etc.),
+	returns the length of the sequence of characters that makes up the single-
+	quote.  Otherwise, returns zero.
+*/
+static size_t
+squote_len(const uint8_t *text, size_t size)
+{
+	static char* single_quote_list[] = { "'", "&#39;", "&#x27;", "&apos;", NULL };
+	char** p;
+
+	for (p = single_quote_list; *p; ++p) {
+		size_t len = strlen(*p);
+		if (size >= len && memcmp(text, *p, len) == 0) {
+			return len;
+		}
+	}
+
+	return 0;
+}
+
+/* Converts " or ' at very beginning or end of a word to left or right quote */
+static int
+smartypants_quotes(hoedown_buffer *ob, uint8_t previous_char, uint8_t next_char, uint8_t quote, int *is_open)
+{
+	char ent[8];
+
+	if (*is_open && !word_boundary(next_char))
+		return 0;
+
+	if (!(*is_open) && !word_boundary(previous_char))
+		return 0;
+
+	snprintf(ent, sizeof(ent), "&%c%cquo;", (*is_open) ? 'r' : 'l', quote);
+	*is_open = !(*is_open);
+	hoedown_buffer_puts(ob, ent);
+	return 1;
+}
+
+/*
+	Converts ' to left or right single quote; but the initial ' might be in
+	different forms, e.g. &apos; or &#39; or &#x27;.
+	'squote_text' points to the original single quote, and 'squote_size' is its length.
+	'text' points at the last character of the single-quote, e.g. ' or ;
+*/
+static size_t
+smartypants_squote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size,
+				   const uint8_t *squote_text, size_t squote_size)
+{
+	if (size >= 2) {
+		uint8_t t1 = tolower(text[1]);
+		size_t next_squote_len = squote_len(text+1, size-1);
+
+		/* convert '' to &ldquo; or &rdquo; */
+		if (next_squote_len > 0) {
+			uint8_t next_char = (size > 1+next_squote_len) ? text[1+next_squote_len] : 0;
+			if (smartypants_quotes(ob, previous_char, next_char, 'd', &smrt->in_dquote))
+				return next_squote_len;
+		}
+
+		/* Tom's, isn't, I'm, I'd */
+		if ((t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') &&
+			(size == 3 || word_boundary(text[2]))) {
+			HOEDOWN_BUFPUTSL(ob, "&rsquo;");
+			return 0;
+		}
+
+		/* you're, you'll, you've */
+		if (size >= 3) {
+			uint8_t t2 = tolower(text[2]);
+
+			if (((t1 == 'r' && t2 == 'e') ||
+				(t1 == 'l' && t2 == 'l') ||
+				(t1 == 'v' && t2 == 'e')) &&
+				(size == 4 || word_boundary(text[3]))) {
+				HOEDOWN_BUFPUTSL(ob, "&rsquo;");
+				return 0;
+			}
+		}
+	}
+
+	if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
+		return 0;
+
+	hoedown_buffer_put(ob, squote_text, squote_size);
+	return 0;
+}
+
+/* Converts ' to left or right single quote. */
+static size_t
+smartypants_cb__squote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
+{
+	return smartypants_squote(ob, smrt, previous_char, text, size, text, 1);
+}
+
+/* Converts (c), (r), (tm) */
+static size_t
+smartypants_cb__parens(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
+{
+	if (size >= 3) {
+		uint8_t t1 = tolower(text[1]);
+		uint8_t t2 = tolower(text[2]);
+
+		if (t1 == 'c' && t2 == ')') {
+			HOEDOWN_BUFPUTSL(ob, "&copy;");
+			return 2;
+		}
+
+		if (t1 == 'r' && t2 == ')') {
+			HOEDOWN_BUFPUTSL(ob, "&reg;");
+			return 2;
+		}
+
+		if (size >= 4 && t1 == 't' && t2 == 'm' && text[3] == ')') {
+			HOEDOWN_BUFPUTSL(ob, "&trade;");
+			return 3;
+		}
+	}
+
+	hoedown_buffer_putc(ob, text[0]);
+	return 0;
+}
+
+/* Converts "--" to em-dash, etc. */
+static size_t
+smartypants_cb__dash(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
+{
+	if (size >= 3 && text[1] == '-' && text[2] == '-') {
+		HOEDOWN_BUFPUTSL(ob, "&mdash;");
+		return 2;
+	}
+
+	if (size >= 2 && text[1] == '-') {
+		HOEDOWN_BUFPUTSL(ob, "&ndash;");
+		return 1;
+	}
+
+	hoedown_buffer_putc(ob, text[0]);
+	return 0;
+}
+
+/* Converts &quot; etc. */
+static size_t
+smartypants_cb__amp(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
+{
+	size_t len;
+	if (size >= 6 && memcmp(text, "&quot;", 6) == 0) {
+		if (smartypants_quotes(ob, previous_char, size >= 7 ? text[6] : 0, 'd', &smrt->in_dquote))
+			return 5;
+	}
+
+	len = squote_len(text, size);
+	if (len > 0) {
+		return (len-1) + smartypants_squote(ob, smrt, previous_char, text+(len-1), size-(len-1), text, len);
+	}
+
+	if (size >= 4 && memcmp(text, "&#0;", 4) == 0)
+		return 3;
+
+	hoedown_buffer_putc(ob, '&');
+	return 0;
+}
+
+/* Converts "..." to ellipsis */
+static size_t
+smartypants_cb__period(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
+{
+	if (size >= 3 && text[1] == '.' && text[2] == '.') {
+		HOEDOWN_BUFPUTSL(ob, "&hellip;");
+		return 2;
+	}
+
+	if (size >= 5 && text[1] == ' ' && text[2] == '.' && text[3] == ' ' && text[4] == '.') {
+		HOEDOWN_BUFPUTSL(ob, "&hellip;");
+		return 4;
+	}
+
+	hoedown_buffer_putc(ob, text[0]);
+	return 0;
+}
+
+/* Converts `` to opening double quote */
+static size_t
+smartypants_cb__backtick(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
+{
+	if (size >= 2 && text[1] == '`') {
+		if (smartypants_quotes(ob, previous_char, size >= 3 ? text[2] : 0, 'd', &smrt->in_dquote))
+			return 1;
+	}
+
+	hoedown_buffer_putc(ob, text[0]);
+	return 0;
+}
+
+/* Converts 1/2, 1/4, 3/4 */
+static size_t
+smartypants_cb__number(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
+{
+	if (word_boundary(previous_char) && size >= 3) {
+		if (text[0] == '1' && text[1] == '/' && text[2] == '2') {
+			if (size == 3 || word_boundary(text[3])) {
+				HOEDOWN_BUFPUTSL(ob, "&frac12;");
+				return 2;
+			}
+		}
+
+		if (text[0] == '1' && text[1] == '/' && text[2] == '4') {
+			if (size == 3 || word_boundary(text[3]) ||
+				(size >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h')) {
+				HOEDOWN_BUFPUTSL(ob, "&frac14;");
+				return 2;
+			}
+		}
+
+		if (text[0] == '3' && text[1] == '/' && text[2] == '4') {
+			if (size == 3 || word_boundary(text[3]) ||
+				(size >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's')) {
+				HOEDOWN_BUFPUTSL(ob, "&frac34;");
+				return 2;
+			}
+		}
+	}
+
+	hoedown_buffer_putc(ob, text[0]);
+	return 0;
+}
+
+/* Converts " to left or right double quote */
+static size_t
+smartypants_cb__dquote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
+{
+	if (!smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 'd', &smrt->in_dquote))
+		HOEDOWN_BUFPUTSL(ob, "&quot;");
+
+	return 0;
+}
+
+static size_t
+smartypants_cb__ltag(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
+{
+	static const char *skip_tags[] = {
+	  "pre", "code", "var", "samp", "kbd", "math", "script", "style"
+	};
+	static const size_t skip_tags_count = 8;
+
+	size_t tag, i = 0;
+
+	/* This is a comment. Copy everything verbatim until --> or EOF is seen. */
+	if (i + 4 < size && memcmp(text + i, "<!--", 4) == 0) {
+		i += 4;
+		while (i + 3 < size && memcmp(text + i, "-->",  3) != 0)
+			i++;
+		i += 3;
+		hoedown_buffer_put(ob, text, i + 1);
+		return i;
+	}
+
+	while (i < size && text[i] != '>')
+		i++;
+
+	for (tag = 0; tag < skip_tags_count; ++tag) {
+		if (hoedown_html_is_tag(text, size, skip_tags[tag]) == HOEDOWN_HTML_TAG_OPEN)
+			break;
+	}
+
+	if (tag < skip_tags_count) {
+		for (;;) {
+			while (i < size && text[i] != '<')
+				i++;
+
+			if (i == size)
+				break;
+
+			if (hoedown_html_is_tag(text + i, size - i, skip_tags[tag]) == HOEDOWN_HTML_TAG_CLOSE)
+				break;
+
+			i++;
+		}
+
+		while (i < size && text[i] != '>')
+			i++;
+	}
+
+	hoedown_buffer_put(ob, text, i + 1);
+	return i;
+}
+
+static size_t
+smartypants_cb__escape(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
+{
+	if (size < 2)
+		return 0;
+
+	switch (text[1]) {
+	case '\\':
+	case '"':
+	case '\'':
+	case '.':
+	case '-':
+	case '`':
+		hoedown_buffer_putc(ob, text[1]);
+		return 1;
+
+	default:
+		hoedown_buffer_putc(ob, '\\');
+		return 0;
+	}
+}
+
+#if 0
+static struct {
+    uint8_t c0;
+    const uint8_t *pattern;
+    const uint8_t *entity;
+    int skip;
+} smartypants_subs[] = {
+    { '\'', "'s>",      "&rsquo;",  0 },
+    { '\'', "'t>",      "&rsquo;",  0 },
+    { '\'', "'re>",     "&rsquo;",  0 },
+    { '\'', "'ll>",     "&rsquo;",  0 },
+    { '\'', "'ve>",     "&rsquo;",  0 },
+    { '\'', "'m>",      "&rsquo;",  0 },
+    { '\'', "'d>",      "&rsquo;",  0 },
+    { '-',  "--",       "&mdash;",  1 },
+    { '-',  "<->",      "&ndash;",  0 },
+    { '.',  "...",      "&hellip;", 2 },
+    { '.',  ". . .",    "&hellip;", 4 },
+    { '(',  "(c)",      "&copy;",   2 },
+    { '(',  "(r)",      "&reg;",    2 },
+    { '(',  "(tm)",     "&trade;",  3 },
+    { '3',  "<3/4>",    "&frac34;", 2 },
+    { '3',  "<3/4ths>", "&frac34;", 2 },
+    { '1',  "<1/2>",    "&frac12;", 2 },
+    { '1',  "<1/4>",    "&frac14;", 2 },
+    { '1',  "<1/4th>",  "&frac14;", 2 },
+    { '&',  "&#0;",      0,       3 },
+};
+#endif
+
+void
+hoedown_html_smartypants(hoedown_buffer *ob, const uint8_t *text, size_t size)
+{
+	size_t i;
+	struct smartypants_data smrt = {0, 0};
+
+	if (!text)
+		return;
+
+	hoedown_buffer_grow(ob, size);
+
+	for (i = 0; i < size; ++i) {
+		size_t org;
+		uint8_t action = 0;
+
+		org = i;
+		while (i < size && (action = smartypants_cb_chars[text[i]]) == 0)
+			i++;
+
+		if (i > org)
+			hoedown_buffer_put(ob, text + org, i - org);
+
+		if (i < size) {
+			i += smartypants_cb_ptrs[(int)action]
+				(ob, &smrt, i ? text[i - 1] : 0, text + i, size - i);
+		}
+	}
+}

+ 79 - 0
modules/hoedown/hoedown/src/stack.c

@@ -0,0 +1,79 @@
+#include "stack.h"
+
+#include "buffer.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+void
+hoedown_stack_init(hoedown_stack *st, size_t initial_size)
+{
+	assert(st);
+
+	st->item = NULL;
+	st->size = st->asize = 0;
+
+	if (!initial_size)
+		initial_size = 8;
+
+	hoedown_stack_grow(st, initial_size);
+}
+
+void
+hoedown_stack_uninit(hoedown_stack *st)
+{
+	assert(st);
+
+	free(st->item);
+}
+
+void
+hoedown_stack_grow(hoedown_stack *st, size_t neosz)
+{
+	assert(st);
+
+	if (st->asize >= neosz)
+		return;
+
+	st->item = hoedown_realloc(st->item, neosz * sizeof(void *));
+	memset(st->item + st->asize, 0x0, (neosz - st->asize) * sizeof(void *));
+
+	st->asize = neosz;
+
+	if (st->size > neosz)
+		st->size = neosz;
+}
+
+void
+hoedown_stack_push(hoedown_stack *st, void *item)
+{
+	assert(st);
+
+	if (st->size >= st->asize)
+		hoedown_stack_grow(st, st->size * 2);
+
+	st->item[st->size++] = item;
+}
+
+void *
+hoedown_stack_pop(hoedown_stack *st)
+{
+	assert(st);
+
+	if (!st->size)
+		return NULL;
+
+	return st->item[--st->size];
+}
+
+void *
+hoedown_stack_top(const hoedown_stack *st)
+{
+	assert(st);
+
+	if (!st->size)
+		return NULL;
+
+	return st->item[st->size - 1];
+}

+ 52 - 0
modules/hoedown/hoedown/src/stack.h

@@ -0,0 +1,52 @@
+/* stack.h - simple stacking */
+
+#ifndef HOEDOWN_STACK_H
+#define HOEDOWN_STACK_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*********
+ * TYPES *
+ *********/
+
+struct hoedown_stack {
+	void **item;
+	size_t size;
+	size_t asize;
+};
+typedef struct hoedown_stack hoedown_stack;
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_stack_init: initialize a stack */
+void hoedown_stack_init(hoedown_stack *st, size_t initial_size);
+
+/* hoedown_stack_uninit: free internal data of the stack */
+void hoedown_stack_uninit(hoedown_stack *st);
+
+/* hoedown_stack_grow: increase the allocated size to the given value */
+void hoedown_stack_grow(hoedown_stack *st, size_t neosz);
+
+/* hoedown_stack_push: push an item to the top of the stack */
+void hoedown_stack_push(hoedown_stack *st, void *item);
+
+/* hoedown_stack_pop: retrieve and remove the item at the top of the stack */
+void *hoedown_stack_pop(hoedown_stack *st);
+
+/* hoedown_stack_top: retrieve the item at the top of the stack */
+void *hoedown_stack_top(const hoedown_stack *st);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_STACK_H **/

+ 9 - 0
modules/hoedown/hoedown/src/version.c

@@ -0,0 +1,9 @@
+#include "version.h"
+
+void
+hoedown_version(int *major, int *minor, int *revision)
+{
+	*major = HOEDOWN_VERSION_MAJOR;
+	*minor = HOEDOWN_VERSION_MINOR;
+	*revision = HOEDOWN_VERSION_REVISION;
+}

+ 33 - 0
modules/hoedown/hoedown/src/version.h

@@ -0,0 +1,33 @@
+/* version.h - holds Hoedown's version */
+
+#ifndef HOEDOWN_VERSION_H
+#define HOEDOWN_VERSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************
+ * CONSTANTS *
+ *************/
+
+#define HOEDOWN_VERSION "3.0.6"
+#define HOEDOWN_VERSION_MAJOR 3
+#define HOEDOWN_VERSION_MINOR 0
+#define HOEDOWN_VERSION_REVISION 6
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_version: retrieve Hoedown's version numbers */
+void hoedown_version(int *major, int *minor, int *revision);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_VERSION_H **/

+ 98 - 0
modules/libc/libc.monkey2

@@ -0,0 +1,98 @@
+
+Namespace libc
+
+#Import "native/libc.cpp"
+#Import "native/libc.h"
+
+Extern
+
+Struct size_t
+End
+
+Function sizeof<T>:Int( t:T )="(int)sizeof"
+
+'***** stdio.h *****
+
+Struct FILE
+End
+
+Const SEEK_SET:Int
+Const SEEK_CUR:Int
+Const SEEK_END:Int
+
+Function fopen:FILE Ptr( path:CString,mode:CString )
+
+Function rewind:Void( stream:FILE )
+Function ftell:Int( stream:FILE Ptr )
+Function fseek:Int( stream:FILE Ptr,offset:Int,whence:Int )
+
+Function fread:Int( buf:Void Ptr,size:Int,count:Int,stream:FILE Ptr )
+Function fwrite:Int( buf:Void Ptr,size:Int,count:Int,stream:FILE Ptr )
+Function fclose:Int( stream:FILE Ptr )
+
+Function remove:Int( path:CString )
+
+'***** stdlib.h *****
+
+Function malloc:Void Ptr( size:Int )
+Function free:Void( mem:Void Ptr )
+
+Function system:Int( cmd:CString )="system_"
+Function setenv:Int( name:CString,value:CString,overwrite:Int )="setenv_"
+Function getenv:CChar Ptr( name:CString )
+
+Function exit_:Void( status:Int )="exit"
+Function abort:Void()
+
+'***** string.h *****
+
+Function strlen:Int( str:CString )
+
+Function memset:Void Ptr( dst:Void Ptr,value:Int,count:Int )
+Function memcpy:Void Ptr( dst:Void Ptr,src:Void Ptr,length:Int )
+Function memmove:Void Ptr( dst:Void Ptr,src:Void Ptr,length:Int )
+
+'***** time.h *****
+
+Alias time_t:Long
+
+'***** unistd.h *****
+
+Function getcwd:CChar Ptr( buf:CChar Ptr,size:Int )
+Function chdir:Int( path:CString )
+Function rmdir:Int( path:CString )
+
+'***** sys/stat.h *****
+
+Enum mode_t
+End
+
+Const S_IFMT:mode_t	'$f000
+Const S_IFIFO:mode_t	'$1000
+Const S_IFCHR:mode_t	'$2000
+Const S_IFBLK:mode_t	'$3000
+Const S_IFDIR:mode_t	'$4000
+Const S_IFREG:mode_t	'$8000
+
+Struct stat_t
+	Field st_mode:mode_t
+	Field st_atime:time_t	'last access
+	Field st_mtime:time_t	'last modification
+	Field st_ctime:time_t	'status change
+End
+
+Function stat:Int( path:CString,buf:stat_t Ptr )
+Function mkdir:Int( path:CString,mode:Int )="mkdir_"
+
+'***** dirent.h *****
+
+Struct DIR
+End
+
+Struct dirent
+	Field d_name:Void Ptr
+End
+
+Function opendir:DIR Ptr( path:CString )
+Function readdir:dirent Ptr( dir:DIR Ptr )
+Function closedir( dir:DIR Ptr )

+ 57 - 0
modules/libc/native/libc.cpp

@@ -0,0 +1,57 @@
+
+#include "libc.h"
+
+#if _WIN32
+#include <windows.h>
+#include <bbstring.h>
+#endif
+
+void setenv_( const char *name,const char *value,int overwrite ){
+
+#if _WIN32
+
+	if( !overwrite && getenv( name ) ) return;
+
+	bbString tmp=bbString( name )+BB_T( "=" )+bbString( value );
+	putenv( tmp.toCString() );
+
+#else
+	setenv( name,value,overwrite );
+#endif
+}
+
+int system_( const char *cmd ){
+
+#if _WIN32
+
+	bbString tmp=BB_T( "cmd /S /C\"" )+BB_T( cmd )+BB_T( "\"" );
+
+	PROCESS_INFORMATION pi={0};
+	STARTUPINFOA si={sizeof(si)};
+	
+	if( !CreateProcessA( 0,(LPSTR)tmp.toCString(),0,0,1,CREATE_DEFAULT_ERROR_MODE,0,0,&si,&pi ) ) return -1;
+
+	WaitForSingleObject( pi.hProcess,INFINITE );
+	
+	int res=GetExitCodeProcess( pi.hProcess,(DWORD*)&res ) ? res : -1;
+
+	CloseHandle( pi.hProcess );
+	CloseHandle( pi.hThread );
+
+	return res;
+
+#else
+
+	return system( cmd );
+
+#endif
+
+}
+
+int mkdir_( const char *path,int mode ){
+#if _WIN32
+	return mkdir( path );
+#else
+	return mkdir( path,0777 );
+#endif
+}

+ 25 - 0
modules/libc/native/libc.h

@@ -0,0 +1,25 @@
+
+//Libc fudge, mainly for windows.
+
+#ifndef BB_LIB_C_H
+#define BB_LIB_C_H
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#if _WIN32
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+
+typedef struct stat stat_t;
+
+int system_( const char *command );
+void setenv_( const char *name,const char *value,int overwrite );
+int mkdir_( const char *path,int mode );
+
+#endif

+ 93 - 0
modules/miniz/miniz.monkey2

@@ -0,0 +1,93 @@
+
+Namespace miniz
+
+#Import "<libc.monkey2>"
+
+#Import "native/miniz.c"
+#Import "native/miniz.h"
+
+Using libc
+
+Extern
+
+Enum mz_zip_mode
+End
+
+Const MZ_ZIP_MODE_INVALID:mz_zip_mode
+Const MZ_ZIP_MODE_READING:mz_zip_mode
+Const MZ_ZIP_MODE_WRITING:mz_zip_mode
+Const MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED:mz_zip_mode
+
+Alias mz_alloc_func:Void Ptr( opaque:Void Ptr,items:size_t,size:size_t )
+Alias mz_free_func:Void( opaque:Void Ptr,address:Void Ptr )
+Alias mz_realloc_func:Void Ptr( opaque:Void Ptr,address:Void Ptr,items:size_t,size:size_t )
+
+Alias mz_file_read_func:size_t( pOpaque:Void Ptr,file_ofs:ULong,buf:Void Ptr,n:size_t )
+Alias mz_file_write_func:size_t( pOpaque:Byte Ptr,file_ofs:ULong,buf:Void Ptr,n:size_t )
+
+Struct mz_zip_archive
+
+	Field m_archive_size:ULong
+	Field m_central_directory_file_ofs:ULong
+	Field m_total_files:UInt
+	
+	Field m_file_offset_alignment:UInt
+	
+	Field m_pAlloc:mz_alloc_func
+	Field m_pFree:mz_free_func
+	Field m_pRealloc:mz_realloc_func
+	Field m_pAlloc_opaque:Void Ptr
+	
+	Field m_pRead:mz_file_read_func
+	Field m_pWrite:mz_file_write_func
+	Field m_pIO_opaque:Void Ptr
+	
+	Field m_pState:Void Ptr
+End
+
+Struct mz_zip_archive_file_stat
+	Field m_file_index:UInt
+	Field m_central_dir_ofs:UInt
+	Field m_version_made_by:UShort
+	Field m_version_needed:UShort
+	Field m_bit_flag:UShort
+	Field m_method:UShort
+	Field m_crc32:UInt
+	Field m_comp_size:ULong
+	Field m_uncomp_size:ULong
+	Field m_internal_attr:UShort
+	Field m_external_attr:UInt
+	Field m_local_header_ofs:ULong
+	Field m_comment_size:UInt
+	Field m_filename:CChar Ptr
+	Field m_comment:CChar Ptr
+End
+
+Function mz_free:Void( address:Void Ptr )
+
+'Inits a ZIP archive reader.
+'These functions read and validate the archive's central directory.
+Function mz_zip_reader_init:Int( pZip:mz_zip_archive Ptr,size:Int,flags:Int )
+Function mz_zip_reader_init_mem:Int( pZip:mz_zip_archive Ptr,pMem:Void Ptr,size:Int,flags:Int )
+
+'Ends archive reading, freeing all allocations, and closing the input archive file If mz_zip_reader_init_file() was used.
+Function mz_zip_reader_end:Int( pZip:mz_zip_archive Ptr )
+
+'Returns the total number of files in the archive.
+Function mz_zip_reader_get_num_files:Int( pZip:mz_zip_archive Ptr )
+
+'Attempts to locates a file in the archive's central directory.
+'Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
+'Returns -1 If the file cannot be found.
+Function mz_zip_reader_locate_file:Int( pZip:mz_zip_archive Ptr,pName:CString,pComment:CString,flags:Int )
+
+'Returns detailed information about an archive file entry.
+Function mz_zip_reader_file_stat:Int( pZip:mz_zip_archive Ptr,file_index:Int,pStat:mz_zip_archive_file_stat Ptr )
+
+'Extracts a archive file to a memory buffer.
+Function mz_zip_reader_extract_to_mem:Int( pZip:mz_zip_archive Ptr,file_index:Int,pBuf:Void Ptr,buf_size:Int,flags:Int )
+Function mz_zip_reader_extract_file_to_mem:Int( pZip:mz_zip_archive Ptr,pFilename:CString,pBuf:Void Ptr,buf_size:Int,flags:Int )
+
+'Extracts a archive file to a dynamically allocated heap buffer.
+Function mz_zip_reader_extract_to_heap:Void Ptr( pZip:mz_zip_archive Ptr,file_index:Int,pSize:size_t Ptr,flags:Int )
+Function mz_zip_reader_extract_file_to_heap:Void Ptr( pZip:mz_zip_archive Ptr,pFilename:CString,pSize:size_t Ptr,flags:Int )

+ 4916 - 0
modules/miniz/native/miniz.c

@@ -0,0 +1,4916 @@
+/* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
+   See "unlicense" statement at the end of this file.
+   Rich Geldreich <[email protected]>, last updated Oct. 13, 2013
+   Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
+
+   Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define
+   MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).
+
+   * Change History
+     10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major release with Zip64 support (almost there!):
+       - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks [email protected]) which could cause locate files to not find files. This bug
+        would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place()
+        (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag).
+       - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size
+       - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries.
+         Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice).
+       - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes
+       - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
+       - Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6.
+       - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
+       - Merged MZ_FORCEINLINE fix from hdeanclark
+       - Fix <time.h> include before config #ifdef, thanks emil.brink
+       - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can
+        set it to 1 for real-time compression).
+       - Merged in some compiler fixes from paulharris's github repro.
+       - Retested this build under Windows (VS 2010, including static analysis), tcc  0.9.26, gcc v4.6 and clang v3.3.
+       - Added example6.c, which dumps an image of the mandelbrot set to a PNG file.
+       - Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
+       - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled
+		 - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch
+     5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).
+     5/19/12 v1.13 - From [email protected] and [email protected] - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
+       - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files.
+       - Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
+       - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly
+        "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning).
+       - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64.
+       - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test.
+       - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives.
+       - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)
+       - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself).
+     4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's.
+      level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <[email protected]> for the feedback/bug report.
+     5/28/11 v1.11 - Added statement from unlicense.org
+     5/27/11 v1.10 - Substantial compressor optimizations:
+      - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a
+      - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86).
+      - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types.
+      - Refactored the compression code for better readability and maintainability.
+      - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large
+       drop in throughput on some files).
+     5/15/11 v1.09 - Initial stable release.
+
+   * Low-level Deflate/Inflate implementation notes:
+
+     Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or
+     greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses
+     approximately as well as zlib.
+
+     Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function
+     coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory
+     block large enough to hold the entire file.
+
+     The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation.
+
+   * zlib-style API notes:
+
+     miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in
+     zlib replacement in many apps:
+        The z_stream struct, optional memory allocation callbacks
+        deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
+        inflateInit/inflateInit2/inflate/inflateEnd
+        compress, compress2, compressBound, uncompress
+        CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines.
+        Supports raw deflate streams or standard zlib streams with adler-32 checking.
+
+     Limitations:
+      The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries.
+      I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but
+      there are no guarantees that miniz.c pulls this off perfectly.
+
+   * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by
+     Alex Evans. Supports 1-4 bytes/pixel images.
+
+   * ZIP archive API notes:
+
+     The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to
+     get the job done with minimal fuss. There are simple API's to retrieve file information, read files from
+     existing archives, create new archives, append new files to existing archives, or clone archive data from
+     one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h),
+     or you can specify custom file read/write callbacks.
+
+     - Archive reading: Just call this function to read a single file from a disk archive:
+
+      void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name,
+        size_t *pSize, mz_uint zip_flags);
+
+     For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central
+     directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files.
+
+     - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file:
+
+     int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
+
+     The locate operation can optionally check file comments too, which (as one example) can be used to identify
+     multiple versions of the same file in an archive. This function uses a simple linear search through the central
+     directory, so it's not very fast.
+
+     Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and
+     retrieve detailed info on each file by calling mz_zip_reader_file_stat().
+
+     - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data
+     to disk and builds an exact image of the central directory in memory. The central directory image is written
+     all at once at the end of the archive file when the archive is finalized.
+
+     The archive writer can optionally align each file's local header and file data to any power of 2 alignment,
+     which can be useful when the archive will be read from optical media. Also, the writer supports placing
+     arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still
+     readable by any ZIP tool.
+
+     - Archive appending: The simple way to add a single file to an archive is to call this function:
+
+      mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name,
+        const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
+
+     The archive will be created if it doesn't already exist, otherwise it'll be appended to.
+     Note the appending is done in-place and is not an atomic operation, so if something goes wrong
+     during the operation it's possible the archive could be left without a central directory (although the local
+     file headers and file data will be fine, so the archive will be recoverable).
+
+     For more complex archive modification scenarios:
+     1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to
+     preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the
+     compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and
+     you're done. This is safe but requires a bunch of temporary disk space or heap memory.
+
+     2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(),
+     append new files as needed, then finalize the archive which will write an updated central directory to the
+     original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a
+     possibility that the archive's central directory could be lost with this method if anything goes wrong, though.
+
+     - ZIP archive support limitations:
+     No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files.
+     Requires streams capable of seeking.
+
+   * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the
+     below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.
+
+   * Important: For best perf. be sure to customize the below macros for your target platform:
+     #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
+     #define MINIZ_LITTLE_ENDIAN 1
+     #define MINIZ_HAS_64BIT_REGISTERS 1
+
+   * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz
+     uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files
+     (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
+*/
+
+#ifndef MINIZ_HEADER_INCLUDED
+#define MINIZ_HEADER_INCLUDED
+
+#include <stdlib.h>
+
+// Defines to completely disable specific portions of miniz.c:
+// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl.
+
+// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O.
+//#define MINIZ_NO_STDIO
+
+// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or
+// get/set file times, and the C run-time funcs that get/set times won't be called.
+// The current downside is the times written to your archives will be from 1979.
+//#define MINIZ_NO_TIME
+
+// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
+//#define MINIZ_NO_ARCHIVE_APIS
+
+// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's.
+//#define MINIZ_NO_ARCHIVE_WRITING_APIS
+
+// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's.
+//#define MINIZ_NO_ZLIB_APIS
+
+// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib.
+//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+
+// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
+// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc
+// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user
+// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
+//#define MINIZ_NO_MALLOC
+
+#if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
+  // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux
+  #define MINIZ_NO_TIME
+#endif
+
+#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
+  #include <time.h>
+#endif
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__)
+// MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
+#define MINIZ_X86_OR_X64_CPU 1
+#endif
+
+#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
+// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
+#define MINIZ_LITTLE_ENDIAN 1
+#endif
+
+#if MINIZ_X86_OR_X64_CPU
+// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses.
+#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
+#endif
+
+#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)
+// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions).
+#define MINIZ_HAS_64BIT_REGISTERS 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ------------------- zlib-style API Definitions.
+
+// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
+typedef unsigned long mz_ulong;
+
+// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap.
+void mz_free(void *p);
+
+#define MZ_ADLER32_INIT (1)
+// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL.
+mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
+
+#define MZ_CRC32_INIT (0)
+// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL.
+mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
+
+// Compression strategies.
+enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 };
+
+// Method
+#define MZ_DEFLATED 8
+
+#ifndef MINIZ_NO_ZLIB_APIS
+
+// Heap allocation callbacks.
+// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long.
+typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
+typedef void (*mz_free_func)(void *opaque, void *address);
+typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);
+
+#define MZ_VERSION          "9.1.15"
+#define MZ_VERNUM           0x91F0
+#define MZ_VER_MAJOR        9
+#define MZ_VER_MINOR        1
+#define MZ_VER_REVISION     15
+#define MZ_VER_SUBREVISION  0
+
+// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs).
+enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 };
+
+// Return status codes. MZ_PARAM_ERROR is non-standard.
+enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };
+
+// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
+enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 };
+
+// Window bits
+#define MZ_DEFAULT_WINDOW_BITS 15
+
+struct mz_internal_state;
+
+// Compression/decompression stream struct.
+typedef struct mz_stream_s
+{
+  const unsigned char *next_in;     // pointer to next byte to read
+  unsigned int avail_in;            // number of bytes available at next_in
+  mz_ulong total_in;                // total number of bytes consumed so far
+
+  unsigned char *next_out;          // pointer to next byte to write
+  unsigned int avail_out;           // number of bytes that can be written to next_out
+  mz_ulong total_out;               // total number of bytes produced so far
+
+  char *msg;                        // error msg (unused)
+  struct mz_internal_state *state;  // internal state, allocated by zalloc/zfree
+
+  mz_alloc_func zalloc;             // optional heap allocation function (defaults to malloc)
+  mz_free_func zfree;               // optional heap free function (defaults to free)
+  void *opaque;                     // heap alloc function user pointer
+
+  int data_type;                    // data_type (unused)
+  mz_ulong adler;                   // adler32 of the source or uncompressed data
+  mz_ulong reserved;                // not used
+} mz_stream;
+
+typedef mz_stream *mz_streamp;
+
+// Returns the version string of miniz.c.
+const char *mz_version(void);
+
+// mz_deflateInit() initializes a compressor with default options:
+// Parameters:
+//  pStream must point to an initialized mz_stream struct.
+//  level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
+//  level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio.
+//  (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
+// Return values:
+//  MZ_OK on success.
+//  MZ_STREAM_ERROR if the stream is bogus.
+//  MZ_PARAM_ERROR if the input parameters are bogus.
+//  MZ_MEM_ERROR on out of memory.
+int mz_deflateInit(mz_streamp pStream, int level);
+
+// mz_deflateInit2() is like mz_deflate(), except with more control:
+// Additional parameters:
+//   method must be MZ_DEFLATED
+//   window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer)
+//   mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
+int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);
+
+// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
+int mz_deflateReset(mz_streamp pStream);
+
+// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible.
+// Parameters:
+//   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
+//   flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
+// Return values:
+//   MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full).
+//   MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore.
+//   MZ_STREAM_ERROR if the stream is bogus.
+//   MZ_PARAM_ERROR if one of the parameters is invalid.
+//   MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.)
+int mz_deflate(mz_streamp pStream, int flush);
+
+// mz_deflateEnd() deinitializes a compressor:
+// Return values:
+//  MZ_OK on success.
+//  MZ_STREAM_ERROR if the stream is bogus.
+int mz_deflateEnd(mz_streamp pStream);
+
+// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH.
+mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
+
+// Single-call compression functions mz_compress() and mz_compress2():
+// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure.
+int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
+int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
+
+// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress().
+mz_ulong mz_compressBound(mz_ulong source_len);
+
+// Initializes a decompressor.
+int mz_inflateInit(mz_streamp pStream);
+
+// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer:
+// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
+int mz_inflateInit2(mz_streamp pStream, int window_bits);
+
+// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible.
+// Parameters:
+//   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
+//   flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
+//   On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster).
+//   MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data.
+// Return values:
+//   MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full.
+//   MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified.
+//   MZ_STREAM_ERROR if the stream is bogus.
+//   MZ_DATA_ERROR if the deflate stream is invalid.
+//   MZ_PARAM_ERROR if one of the parameters is invalid.
+//   MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again
+//   with more input data, or with more room in the output buffer (except when using single call decompression, described above).
+int mz_inflate(mz_streamp pStream, int flush);
+
+// Deinitializes a decompressor.
+int mz_inflateEnd(mz_streamp pStream);
+
+// Single-call decompression.
+// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure.
+int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
+
+// Returns a string description of the specified error code, or NULL if the error code is invalid.
+const char *mz_error(int err);
+
+// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports.
+// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project.
+#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+  typedef unsigned char Byte;
+  typedef unsigned int uInt;
+  typedef mz_ulong uLong;
+  typedef Byte Bytef;
+  typedef uInt uIntf;
+  typedef char charf;
+  typedef int intf;
+  typedef void *voidpf;
+  typedef uLong uLongf;
+  typedef void *voidp;
+  typedef void *const voidpc;
+  #define Z_NULL                0
+  #define Z_NO_FLUSH            MZ_NO_FLUSH
+  #define Z_PARTIAL_FLUSH       MZ_PARTIAL_FLUSH
+  #define Z_SYNC_FLUSH          MZ_SYNC_FLUSH
+  #define Z_FULL_FLUSH          MZ_FULL_FLUSH
+  #define Z_FINISH              MZ_FINISH
+  #define Z_BLOCK               MZ_BLOCK
+  #define Z_OK                  MZ_OK
+  #define Z_STREAM_END          MZ_STREAM_END
+  #define Z_NEED_DICT           MZ_NEED_DICT
+  #define Z_ERRNO               MZ_ERRNO
+  #define Z_STREAM_ERROR        MZ_STREAM_ERROR
+  #define Z_DATA_ERROR          MZ_DATA_ERROR
+  #define Z_MEM_ERROR           MZ_MEM_ERROR
+  #define Z_BUF_ERROR           MZ_BUF_ERROR
+  #define Z_VERSION_ERROR       MZ_VERSION_ERROR
+  #define Z_PARAM_ERROR         MZ_PARAM_ERROR
+  #define Z_NO_COMPRESSION      MZ_NO_COMPRESSION
+  #define Z_BEST_SPEED          MZ_BEST_SPEED
+  #define Z_BEST_COMPRESSION    MZ_BEST_COMPRESSION
+  #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
+  #define Z_DEFAULT_STRATEGY    MZ_DEFAULT_STRATEGY
+  #define Z_FILTERED            MZ_FILTERED
+  #define Z_HUFFMAN_ONLY        MZ_HUFFMAN_ONLY
+  #define Z_RLE                 MZ_RLE
+  #define Z_FIXED               MZ_FIXED
+  #define Z_DEFLATED            MZ_DEFLATED
+  #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
+  #define alloc_func            mz_alloc_func
+  #define free_func             mz_free_func
+  #define internal_state        mz_internal_state
+  #define z_stream              mz_stream
+  #define deflateInit           mz_deflateInit
+  #define deflateInit2          mz_deflateInit2
+  #define deflateReset          mz_deflateReset
+  #define deflate               mz_deflate
+  #define deflateEnd            mz_deflateEnd
+  #define deflateBound          mz_deflateBound
+  #define compress              mz_compress
+  #define compress2             mz_compress2
+  #define compressBound         mz_compressBound
+  #define inflateInit           mz_inflateInit
+  #define inflateInit2          mz_inflateInit2
+  #define inflate               mz_inflate
+  #define inflateEnd            mz_inflateEnd
+  #define uncompress            mz_uncompress
+  #define crc32                 mz_crc32
+  #define adler32               mz_adler32
+  #define MAX_WBITS             15
+  #define MAX_MEM_LEVEL         9
+  #define zError                mz_error
+  #define ZLIB_VERSION          MZ_VERSION
+  #define ZLIB_VERNUM           MZ_VERNUM
+  #define ZLIB_VER_MAJOR        MZ_VER_MAJOR
+  #define ZLIB_VER_MINOR        MZ_VER_MINOR
+  #define ZLIB_VER_REVISION     MZ_VER_REVISION
+  #define ZLIB_VER_SUBREVISION  MZ_VER_SUBREVISION
+  #define zlibVersion           mz_version
+  #define zlib_version          mz_version()
+#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+
+#endif // MINIZ_NO_ZLIB_APIS
+
+// ------------------- Types and macros
+
+typedef unsigned char mz_uint8;
+typedef signed short mz_int16;
+typedef unsigned short mz_uint16;
+typedef unsigned int mz_uint32;
+typedef unsigned int mz_uint;
+typedef long long mz_int64;
+typedef unsigned long long mz_uint64;
+typedef int mz_bool;
+
+#define MZ_FALSE (0)
+#define MZ_TRUE (1)
+
+// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message.
+#ifdef _MSC_VER
+   #define MZ_MACRO_END while (0, 0)
+#else
+   #define MZ_MACRO_END while (0)
+#endif
+
+// ------------------- ZIP archive reading/writing
+
+#ifndef MINIZ_NO_ARCHIVE_APIS
+
+enum
+{
+  MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024,
+  MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
+  MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
+};
+
+typedef struct
+{
+  mz_uint32 m_file_index;
+  mz_uint32 m_central_dir_ofs;
+  mz_uint16 m_version_made_by;
+  mz_uint16 m_version_needed;
+  mz_uint16 m_bit_flag;
+  mz_uint16 m_method;
+#ifndef MINIZ_NO_TIME
+  time_t m_time;
+#endif
+  mz_uint32 m_crc32;
+  mz_uint64 m_comp_size;
+  mz_uint64 m_uncomp_size;
+  mz_uint16 m_internal_attr;
+  mz_uint32 m_external_attr;
+  mz_uint64 m_local_header_ofs;
+  mz_uint32 m_comment_size;
+  char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
+  char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
+} mz_zip_archive_file_stat;
+
+typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);
+typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n);
+
+struct mz_zip_internal_state_tag;
+typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
+
+typedef enum
+{
+  MZ_ZIP_MODE_INVALID = 0,
+  MZ_ZIP_MODE_READING = 1,
+  MZ_ZIP_MODE_WRITING = 2,
+  MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
+} mz_zip_mode;
+
+typedef struct mz_zip_archive_tag
+{
+  mz_uint64 m_archive_size;
+  mz_uint64 m_central_directory_file_ofs;
+  mz_uint m_total_files;
+  mz_zip_mode m_zip_mode;
+
+  mz_uint m_file_offset_alignment;
+
+  mz_alloc_func m_pAlloc;
+  mz_free_func m_pFree;
+  mz_realloc_func m_pRealloc;
+  void *m_pAlloc_opaque;
+
+  mz_file_read_func m_pRead;
+  mz_file_write_func m_pWrite;
+  void *m_pIO_opaque;
+
+  mz_zip_internal_state *m_pState;
+
+} mz_zip_archive;
+
+typedef enum
+{
+  MZ_ZIP_FLAG_CASE_SENSITIVE                = 0x0100,
+  MZ_ZIP_FLAG_IGNORE_PATH                   = 0x0200,
+  MZ_ZIP_FLAG_COMPRESSED_DATA               = 0x0400,
+  MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
+} mz_zip_flags;
+
+// ZIP archive reading
+
+// Inits a ZIP archive reader.
+// These functions read and validate the archive's central directory.
+mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags);
+mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags);
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);
+#endif
+
+// Returns the total number of files in the archive.
+mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
+
+// Returns detailed information about an archive file entry.
+mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
+
+// Determines if an archive file entry is a directory entry.
+mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
+mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);
+
+// Retrieves the filename of an archive file entry.
+// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename.
+mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);
+
+// Attempts to locates a file in the archive's central directory.
+// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
+// Returns -1 if the file cannot be found.
+int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
+
+// Extracts a archive file to a memory buffer using no memory allocation.
+mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
+mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
+
+// Extracts a archive file to a memory buffer.
+mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
+mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);
+
+// Extracts a archive file to a dynamically allocated heap buffer.
+void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
+void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);
+
+// Extracts a archive file using a callback function to output the file's data.
+mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
+mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
+
+#ifndef MINIZ_NO_STDIO
+// Extracts a archive file to a disk file and sets its last accessed and modified times.
+// This function only extracts files, not archive directory records.
+mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);
+mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);
+#endif
+
+// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used.
+mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
+
+// ZIP archive writing
+
+#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
+
+// Inits a ZIP archive writer.
+mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
+mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);
+#endif
+
+// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive.
+// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called.
+// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it).
+// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL.
+// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before
+// the archive is finalized the file's central directory will be hosed.
+mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);
+
+// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive.
+// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer.
+// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
+mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
+mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
+
+#ifndef MINIZ_NO_STDIO
+// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive.
+// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
+mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
+#endif
+
+// Adds a file to an archive by fully cloning the data from another archive.
+// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields.
+mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index);
+
+// Finalizes the archive by writing the central directory records followed by the end of central directory record.
+// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end().
+// An archive must be manually finalized by calling this function for it to be valid.
+mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
+mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize);
+
+// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used.
+// Note for the archive to be valid, it must have been finalized before ending.
+mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
+
+// Misc. high-level helper functions:
+
+// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive.
+// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
+mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
+
+// Reads a single file from an archive into a heap block.
+// Returns NULL on failure.
+void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags);
+
+#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
+
+#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
+
+// ------------------- Low-level Decompression API Definitions
+
+// Decompression flags used by tinfl_decompress().
+// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
+// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
+// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
+// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
+enum
+{
+  TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
+  TINFL_FLAG_HAS_MORE_INPUT = 2,
+  TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
+  TINFL_FLAG_COMPUTE_ADLER32 = 8
+};
+
+// High level decompression functions:
+// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
+// On entry:
+//  pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
+// On return:
+//  Function returns a pointer to the decompressed data, or NULL on failure.
+//  *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
+//  The caller must call mz_free() on the returned block when it's no longer needed.
+void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
+
+// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
+// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
+#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
+size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
+
+// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
+// Returns 1 on success or 0 on failure.
+typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
+int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
+
+// Max size of LZ dictionary.
+#define TINFL_LZ_DICT_SIZE 32768
+
+// Return status.
+typedef enum
+{
+  TINFL_STATUS_BAD_PARAM = -3,
+  TINFL_STATUS_ADLER32_MISMATCH = -2,
+  TINFL_STATUS_FAILED = -1,
+  TINFL_STATUS_DONE = 0,
+  TINFL_STATUS_NEEDS_MORE_INPUT = 1,
+  TINFL_STATUS_HAS_MORE_OUTPUT = 2
+} tinfl_status;
+
+// Initializes the decompressor to its initial state.
+#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
+#define tinfl_get_adler32(r) (r)->m_check_adler32
+
+// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
+// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
+tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
+
+// Internal/private bits follow.
+enum
+{
+  TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
+  TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
+};
+
+typedef struct
+{
+  mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
+  mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
+} tinfl_huff_table;
+
+#if MINIZ_HAS_64BIT_REGISTERS
+  #define TINFL_USE_64BIT_BITBUF 1
+#endif
+
+#if TINFL_USE_64BIT_BITBUF
+  typedef mz_uint64 tinfl_bit_buf_t;
+  #define TINFL_BITBUF_SIZE (64)
+#else
+  typedef mz_uint32 tinfl_bit_buf_t;
+  #define TINFL_BITBUF_SIZE (32)
+#endif
+
+struct tinfl_decompressor_tag
+{
+  mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
+  tinfl_bit_buf_t m_bit_buf;
+  size_t m_dist_from_out_buf_start;
+  tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
+  mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
+};
+
+// ------------------- Low-level Compression API Definitions
+
+// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently).
+#define TDEFL_LESS_MEMORY 0
+
+// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search):
+// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression).
+enum
+{
+  TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF
+};
+
+// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data.
+// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers).
+// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing.
+// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory).
+// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
+// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
+// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
+// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
+// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK).
+enum
+{
+  TDEFL_WRITE_ZLIB_HEADER             = 0x01000,
+  TDEFL_COMPUTE_ADLER32               = 0x02000,
+  TDEFL_GREEDY_PARSING_FLAG           = 0x04000,
+  TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
+  TDEFL_RLE_MATCHES                   = 0x10000,
+  TDEFL_FILTER_MATCHES                = 0x20000,
+  TDEFL_FORCE_ALL_STATIC_BLOCKS       = 0x40000,
+  TDEFL_FORCE_ALL_RAW_BLOCKS          = 0x80000
+};
+
+// High level compression functions:
+// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc().
+// On entry:
+//  pSrc_buf, src_buf_len: Pointer and size of source block to compress.
+//  flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression.
+// On return:
+//  Function returns a pointer to the compressed data, or NULL on failure.
+//  *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data.
+//  The caller must free() the returned block when it's no longer needed.
+void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
+
+// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory.
+// Returns 0 on failure.
+size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
+
+// Compresses an image to a compressed PNG file in memory.
+// On entry:
+//  pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. 
+//  The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory.
+//  level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
+//  If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps).
+// On return:
+//  Function returns a pointer to the compressed data, or NULL on failure.
+//  *pLen_out will be set to the size of the PNG image file.
+//  The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed.
+void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);
+void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);
+
+// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
+typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
+
+// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally.
+mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 };
+
+// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes).
+#if TDEFL_LESS_MEMORY
+enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
+#else
+enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
+#endif
+
+// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions.
+typedef enum
+{
+  TDEFL_STATUS_BAD_PARAM = -2,
+  TDEFL_STATUS_PUT_BUF_FAILED = -1,
+  TDEFL_STATUS_OKAY = 0,
+  TDEFL_STATUS_DONE = 1,
+} tdefl_status;
+
+// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
+typedef enum
+{
+  TDEFL_NO_FLUSH = 0,
+  TDEFL_SYNC_FLUSH = 2,
+  TDEFL_FULL_FLUSH = 3,
+  TDEFL_FINISH = 4
+} tdefl_flush;
+
+// tdefl's compression state structure.
+typedef struct
+{
+  tdefl_put_buf_func_ptr m_pPut_buf_func;
+  void *m_pPut_buf_user;
+  mz_uint m_flags, m_max_probes[2];
+  int m_greedy_parsing;
+  mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
+  mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
+  mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
+  mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
+  tdefl_status m_prev_return_status;
+  const void *m_pIn_buf;
+  void *m_pOut_buf;
+  size_t *m_pIn_buf_size, *m_pOut_buf_size;
+  tdefl_flush m_flush;
+  const mz_uint8 *m_pSrc;
+  size_t m_src_buf_left, m_out_buf_ofs;
+  mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
+  mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+  mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+  mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+  mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
+  mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
+  mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
+  mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
+} tdefl_compressor;
+
+// Initializes the compressor.
+// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory.
+// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression.
+// If pBut_buf_func is NULL the user should always call the tdefl_compress() API.
+// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
+tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible.
+tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
+
+// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr.
+// tdefl_compress_buffer() always consumes the entire input buffer.
+tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
+
+tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
+mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
+
+// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros.
+#ifndef MINIZ_NO_ZLIB_APIS
+// Create tdefl_compress() flags given zlib-style compression parameters.
+// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files)
+// window_bits may be -15 (raw deflate) or 15 (zlib)
+// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED
+mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
+#endif // #ifndef MINIZ_NO_ZLIB_APIS
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MINIZ_HEADER_INCLUDED
+
+// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.)
+
+#ifndef MINIZ_HEADER_FILE_ONLY
+
+typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1];
+typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1];
+typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1];
+
+#include <string.h>
+#include <assert.h>
+
+#define MZ_ASSERT(x) assert(x)
+
+#ifdef MINIZ_NO_MALLOC
+  #define MZ_MALLOC(x) NULL
+  #define MZ_FREE(x) (void)x, ((void)0)
+  #define MZ_REALLOC(p, x) NULL
+#else
+  #define MZ_MALLOC(x) malloc(x)
+  #define MZ_FREE(x) free(x)
+  #define MZ_REALLOC(p, x) realloc(p, x)
+#endif
+
+#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
+#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
+#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
+
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
+  #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
+  #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
+#else
+  #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
+  #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
+#endif
+
+#ifdef _MSC_VER
+  #define MZ_FORCEINLINE __forceinline
+#elif defined(__GNUC__)
+  #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
+#else
+  #define MZ_FORCEINLINE inline
+#endif
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+// ------------------- zlib-style API's
+
+mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
+{
+  mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552;
+  if (!ptr) return MZ_ADLER32_INIT;
+  while (buf_len) {
+    for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
+      s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
+      s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
+    }
+    for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
+    s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
+  }
+  return (s2 << 16) + s1;
+}
+
+// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/
+mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
+{
+  static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
+  mz_uint32 crcu32 = (mz_uint32)crc;
+  if (!ptr) return MZ_CRC32_INIT;
+  crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; }
+  return ~crcu32;
+}
+
+void mz_free(void *p)
+{
+  MZ_FREE(p);
+}
+
+#ifndef MINIZ_NO_ZLIB_APIS
+
+static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); }
+static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); }
+static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); }
+
+const char *mz_version(void)
+{
+  return MZ_VERSION;
+}
+
+int mz_deflateInit(mz_streamp pStream, int level)
+{
+  return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
+}
+
+int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
+{
+  tdefl_compressor *pComp;
+  mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
+
+  if (!pStream) return MZ_STREAM_ERROR;
+  if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR;
+
+  pStream->data_type = 0;
+  pStream->adler = MZ_ADLER32_INIT;
+  pStream->msg = NULL;
+  pStream->reserved = 0;
+  pStream->total_in = 0;
+  pStream->total_out = 0;
+  if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
+  if (!pStream->zfree) pStream->zfree = def_free_func;
+
+  pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
+  if (!pComp)
+    return MZ_MEM_ERROR;
+
+  pStream->state = (struct mz_internal_state *)pComp;
+
+  if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
+  {
+    mz_deflateEnd(pStream);
+    return MZ_PARAM_ERROR;
+  }
+
+  return MZ_OK;
+}
+
+int mz_deflateReset(mz_streamp pStream)
+{
+  if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR;
+  pStream->total_in = pStream->total_out = 0;
+  tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags);
+  return MZ_OK;
+}
+
+int mz_deflate(mz_streamp pStream, int flush)
+{
+  size_t in_bytes, out_bytes;
+  mz_ulong orig_total_in, orig_total_out;
+  int mz_status = MZ_OK;
+
+  if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR;
+  if (!pStream->avail_out) return MZ_BUF_ERROR;
+
+  if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
+
+  if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
+    return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
+
+  orig_total_in = pStream->total_in; orig_total_out = pStream->total_out;
+  for ( ; ; )
+  {
+    tdefl_status defl_status;
+    in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
+
+    defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
+    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
+    pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state);
+
+    pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes;
+    pStream->total_out += (mz_uint)out_bytes;
+
+    if (defl_status < 0)
+    {
+      mz_status = MZ_STREAM_ERROR;
+      break;
+    }
+    else if (defl_status == TDEFL_STATUS_DONE)
+    {
+      mz_status = MZ_STREAM_END;
+      break;
+    }
+    else if (!pStream->avail_out)
+      break;
+    else if ((!pStream->avail_in) && (flush != MZ_FINISH))
+    {
+      if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
+        break;
+      return MZ_BUF_ERROR; // Can't make forward progress without some input.
+    }
+  }
+  return mz_status;
+}
+
+int mz_deflateEnd(mz_streamp pStream)
+{
+  if (!pStream) return MZ_STREAM_ERROR;
+  if (pStream->state)
+  {
+    pStream->zfree(pStream->opaque, pStream->state);
+    pStream->state = NULL;
+  }
+  return MZ_OK;
+}
+
+mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
+{
+  (void)pStream;
+  // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.)
+  return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
+}
+
+int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
+{
+  int status;
+  mz_stream stream;
+  memset(&stream, 0, sizeof(stream));
+
+  // In case mz_ulong is 64-bits (argh I hate longs).
+  if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
+
+  stream.next_in = pSource;
+  stream.avail_in = (mz_uint32)source_len;
+  stream.next_out = pDest;
+  stream.avail_out = (mz_uint32)*pDest_len;
+
+  status = mz_deflateInit(&stream, level);
+  if (status != MZ_OK) return status;
+
+  status = mz_deflate(&stream, MZ_FINISH);
+  if (status != MZ_STREAM_END)
+  {
+    mz_deflateEnd(&stream);
+    return (status == MZ_OK) ? MZ_BUF_ERROR : status;
+  }
+
+  *pDest_len = stream.total_out;
+  return mz_deflateEnd(&stream);
+}
+
+int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
+{
+  return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
+}
+
+mz_ulong mz_compressBound(mz_ulong source_len)
+{
+  return mz_deflateBound(NULL, source_len);
+}
+
+typedef struct
+{
+  tinfl_decompressor m_decomp;
+  mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits;
+  mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
+  tinfl_status m_last_status;
+} inflate_state;
+
+int mz_inflateInit2(mz_streamp pStream, int window_bits)
+{
+  inflate_state *pDecomp;
+  if (!pStream) return MZ_STREAM_ERROR;
+  if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR;
+
+  pStream->data_type = 0;
+  pStream->adler = 0;
+  pStream->msg = NULL;
+  pStream->total_in = 0;
+  pStream->total_out = 0;
+  pStream->reserved = 0;
+  if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
+  if (!pStream->zfree) pStream->zfree = def_free_func;
+
+  pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
+  if (!pDecomp) return MZ_MEM_ERROR;
+
+  pStream->state = (struct mz_internal_state *)pDecomp;
+
+  tinfl_init(&pDecomp->m_decomp);
+  pDecomp->m_dict_ofs = 0;
+  pDecomp->m_dict_avail = 0;
+  pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
+  pDecomp->m_first_call = 1;
+  pDecomp->m_has_flushed = 0;
+  pDecomp->m_window_bits = window_bits;
+
+  return MZ_OK;
+}
+
+int mz_inflateInit(mz_streamp pStream)
+{
+   return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
+}
+
+int mz_inflate(mz_streamp pStream, int flush)
+{
+  inflate_state* pState;
+  mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
+  size_t in_bytes, out_bytes, orig_avail_in;
+  tinfl_status status;
+
+  if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
+  if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
+  if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
+
+  pState = (inflate_state*)pStream->state;
+  if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
+  orig_avail_in = pStream->avail_in;
+
+  first_call = pState->m_first_call; pState->m_first_call = 0;
+  if (pState->m_last_status < 0) return MZ_DATA_ERROR;
+
+  if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
+  pState->m_has_flushed |= (flush == MZ_FINISH);
+
+  if ((flush == MZ_FINISH) && (first_call))
+  {
+    // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file.
+    decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
+    in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
+    status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
+    pState->m_last_status = status;
+    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes;
+    pStream->adler = tinfl_get_adler32(&pState->m_decomp);
+    pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes;
+
+    if (status < 0)
+      return MZ_DATA_ERROR;
+    else if (status != TINFL_STATUS_DONE)
+    {
+      pState->m_last_status = TINFL_STATUS_FAILED;
+      return MZ_BUF_ERROR;
+    }
+    return MZ_STREAM_END;
+  }
+  // flush != MZ_FINISH then we must assume there's more input.
+  if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
+
+  if (pState->m_dict_avail)
+  {
+    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
+    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
+    pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
+    pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
+    return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
+  }
+
+  for ( ; ; )
+  {
+    in_bytes = pStream->avail_in;
+    out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
+
+    status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
+    pState->m_last_status = status;
+
+    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
+    pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp);
+
+    pState->m_dict_avail = (mz_uint)out_bytes;
+
+    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
+    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
+    pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
+    pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
+
+    if (status < 0)
+       return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
+    else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
+      return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH.
+    else if (flush == MZ_FINISH)
+    {
+       // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH.
+       if (status == TINFL_STATUS_DONE)
+          return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
+       // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong.
+       else if (!pStream->avail_out)
+          return MZ_BUF_ERROR;
+    }
+    else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
+      break;
+  }
+
+  return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
+}
+
+int mz_inflateEnd(mz_streamp pStream)
+{
+  if (!pStream)
+    return MZ_STREAM_ERROR;
+  if (pStream->state)
+  {
+    pStream->zfree(pStream->opaque, pStream->state);
+    pStream->state = NULL;
+  }
+  return MZ_OK;
+}
+
+int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
+{
+  mz_stream stream;
+  int status;
+  memset(&stream, 0, sizeof(stream));
+
+  // In case mz_ulong is 64-bits (argh I hate longs).
+  if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
+
+  stream.next_in = pSource;
+  stream.avail_in = (mz_uint32)source_len;
+  stream.next_out = pDest;
+  stream.avail_out = (mz_uint32)*pDest_len;
+
+  status = mz_inflateInit(&stream);
+  if (status != MZ_OK)
+    return status;
+
+  status = mz_inflate(&stream, MZ_FINISH);
+  if (status != MZ_STREAM_END)
+  {
+    mz_inflateEnd(&stream);
+    return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
+  }
+  *pDest_len = stream.total_out;
+
+  return mz_inflateEnd(&stream);
+}
+
+const char *mz_error(int err)
+{
+  static struct { int m_err; const char *m_pDesc; } s_error_descs[] =
+  {
+    { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" },
+    { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
+  };
+  mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc;
+  return NULL;
+}
+
+#endif //MINIZ_NO_ZLIB_APIS
+
+// ------------------- Low-level Decompression (completely independent from all compression API's)
+
+#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
+#define TINFL_MEMSET(p, c, l) memset(p, c, l)
+
+#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
+#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
+#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
+#define TINFL_CR_FINISH }
+
+// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never
+// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
+#define TINFL_GET_BYTE(state_index, c) do { \
+  if (pIn_buf_cur >= pIn_buf_end) { \
+    for ( ; ; ) { \
+      if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
+        TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
+        if (pIn_buf_cur < pIn_buf_end) { \
+          c = *pIn_buf_cur++; \
+          break; \
+        } \
+      } else { \
+        c = 0; \
+        break; \
+      } \
+    } \
+  } else c = *pIn_buf_cur++; } MZ_MACRO_END
+
+#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
+#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
+#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
+
+// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
+// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a
+// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the
+// bit buffer contains >=15 bits (deflate's max. Huffman code size).
+#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
+  do { \
+    temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
+    if (temp >= 0) { \
+      code_len = temp >> 9; \
+      if ((code_len) && (num_bits >= code_len)) \
+      break; \
+    } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
+       code_len = TINFL_FAST_LOOKUP_BITS; \
+       do { \
+          temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
+       } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
+    } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
+  } while (num_bits < 15);
+
+// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read
+// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully
+// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32.
+// The slow path is only executed at the very end of the input buffer.
+#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
+  int temp; mz_uint code_len, c; \
+  if (num_bits < 15) { \
+    if ((pIn_buf_end - pIn_buf_cur) < 2) { \
+       TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
+    } else { \
+       bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
+    } \
+  } \
+  if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
+    code_len = temp >> 9, temp &= 511; \
+  else { \
+    code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
+  } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
+
+tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
+{
+  static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 };
+  static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
+  static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
+  static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+  static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
+  static const int s_min_table_sizes[3] = { 257, 1, 4 };
+
+  tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
+  const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
+  mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
+  size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
+
+  // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter).
+  if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }
+
+  num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
+  TINFL_CR_BEGIN
+
+  bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
+  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
+  {
+    TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
+    counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
+    if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
+    if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
+  }
+
+  do
+  {
+    TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
+    if (r->m_type == 0)
+    {
+      TINFL_SKIP_BITS(5, num_bits & 7);
+      for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
+      if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
+      while ((counter) && (num_bits))
+      {
+        TINFL_GET_BITS(51, dist, 8);
+        while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
+        *pOut_buf_cur++ = (mz_uint8)dist;
+        counter--;
+      }
+      while (counter)
+      {
+        size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
+        while (pIn_buf_cur >= pIn_buf_end)
+        {
+          if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
+          {
+            TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
+          }
+          else
+          {
+            TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
+          }
+        }
+        n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
+        TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
+      }
+    }
+    else if (r->m_type == 3)
+    {
+      TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
+    }
+    else
+    {
+      if (r->m_type == 1)
+      {
+        mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
+        r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
+        for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
+      }
+      else
+      {
+        for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
+        MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
+        r->m_table_sizes[2] = 19;
+      }
+      for ( ; (int)r->m_type >= 0; r->m_type--)
+      {
+        int tree_next, tree_cur; tinfl_huff_table *pTable;
+        mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
+        for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
+        used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
+        for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
+        if ((65536 != total) && (used_syms > 1))
+        {
+          TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
+        }
+        for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
+        {
+          mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
+          cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
+          if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
+          if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
+          rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
+          for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
+          {
+            tree_cur -= ((rev_code >>= 1) & 1);
+            if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
+          }
+          tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
+        }
+        if (r->m_type == 2)
+        {
+          for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
+          {
+            mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
+            if ((dist == 16) && (!counter))
+            {
+              TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
+            }
+            num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
+            TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
+          }
+          if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
+          {
+            TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
+          }
+          TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
+        }
+      }
+      for ( ; ; )
+      {
+        mz_uint8 *pSrc;
+        for ( ; ; )
+        {
+          if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
+          {
+            TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
+            if (counter >= 256)
+              break;
+            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
+            *pOut_buf_cur++ = (mz_uint8)counter;
+          }
+          else
+          {
+            int sym2; mz_uint code_len;
+#if TINFL_USE_64BIT_BITBUF
+            if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; }
+#else
+            if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
+#endif
+            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
+              code_len = sym2 >> 9;
+            else
+            {
+              code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
+            }
+            counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
+            if (counter & 256)
+              break;
+
+#if !TINFL_USE_64BIT_BITBUF
+            if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
+#endif
+            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
+              code_len = sym2 >> 9;
+            else
+            {
+              code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
+            }
+            bit_buf >>= code_len; num_bits -= code_len;
+
+            pOut_buf_cur[0] = (mz_uint8)counter;
+            if (sym2 & 256)
+            {
+              pOut_buf_cur++;
+              counter = sym2;
+              break;
+            }
+            pOut_buf_cur[1] = (mz_uint8)sym2;
+            pOut_buf_cur += 2;
+          }
+        }
+        if ((counter &= 511) == 256) break;
+
+        num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
+        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
+
+        TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
+        num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
+        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
+
+        dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
+        if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
+        {
+          TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
+        }
+
+        pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
+
+        if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
+        {
+          while (counter--)
+          {
+            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
+            *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
+          }
+          continue;
+        }
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
+        else if ((counter >= 9) && (counter <= dist))
+        {
+          const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
+          do
+          {
+            ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
+            ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
+            pOut_buf_cur += 8;
+          } while ((pSrc += 8) < pSrc_end);
+          if ((counter &= 7) < 3)
+          {
+            if (counter)
+            {
+              pOut_buf_cur[0] = pSrc[0];
+              if (counter > 1)
+                pOut_buf_cur[1] = pSrc[1];
+              pOut_buf_cur += counter;
+            }
+            continue;
+          }
+        }
+#endif
+        do
+        {
+          pOut_buf_cur[0] = pSrc[0];
+          pOut_buf_cur[1] = pSrc[1];
+          pOut_buf_cur[2] = pSrc[2];
+          pOut_buf_cur += 3; pSrc += 3;
+        } while ((int)(counter -= 3) > 2);
+        if ((int)counter > 0)
+        {
+          pOut_buf_cur[0] = pSrc[0];
+          if ((int)counter > 1)
+            pOut_buf_cur[1] = pSrc[1];
+          pOut_buf_cur += counter;
+        }
+      }
+    }
+  } while (!(r->m_final & 1));
+  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
+  {
+    TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
+  }
+  TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
+  TINFL_CR_FINISH
+
+common_exit:
+  r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
+  *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
+  if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
+  {
+    const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
+    mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
+    while (buf_len)
+    {
+      for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
+      {
+        s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
+        s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
+      }
+      for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
+      s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
+    }
+    r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
+  }
+  return status;
+}
+
+// Higher level helper functions.
+void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
+{
+  tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
+  *pOut_len = 0;
+  tinfl_init(&decomp);
+  for ( ; ; )
+  {
+    size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
+    tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size,
+      (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
+    if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
+    {
+      MZ_FREE(pBuf); *pOut_len = 0; return NULL;
+    }
+    src_buf_ofs += src_buf_size;
+    *pOut_len += dst_buf_size;
+    if (status == TINFL_STATUS_DONE) break;
+    new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
+    pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
+    if (!pNew_buf)
+    {
+      MZ_FREE(pBuf); *pOut_len = 0; return NULL;
+    }
+    pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
+  }
+  return pBuf;
+}
+
+size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
+{
+  tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
+  status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
+  return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
+}
+
+int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
+{
+  int result = 0;
+  tinfl_decompressor decomp;
+  mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
+  if (!pDict)
+    return TINFL_STATUS_FAILED;
+  tinfl_init(&decomp);
+  for ( ; ; )
+  {
+    size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
+    tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
+      (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
+    in_buf_ofs += in_buf_size;
+    if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
+      break;
+    if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
+    {
+      result = (status == TINFL_STATUS_DONE);
+      break;
+    }
+    dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
+  }
+  MZ_FREE(pDict);
+  *pIn_buf_size = in_buf_ofs;
+  return result;
+}
+
+// ------------------- Low-level Compression (independent from all decompression API's)
+
+// Purposely making these tables static for faster init and thread safety.
+static const mz_uint16 s_tdefl_len_sym[256] = {
+  257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272,
+  273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276,
+  277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
+  279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
+  281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,
+  282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,
+  283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,
+  284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 };
+
+static const mz_uint8 s_tdefl_len_extra[256] = {
+  0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 };
+
+static const mz_uint8 s_tdefl_small_dist_sym[512] = {
+  0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,
+  11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,
+  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,
+  14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
+  14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+  15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,
+  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 };
+
+static const mz_uint8 s_tdefl_small_dist_extra[512] = {
+  0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,
+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7 };
+
+static const mz_uint8 s_tdefl_large_dist_sym[128] = {
+  0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,
+  26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
+  28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 };
+
+static const mz_uint8 s_tdefl_large_dist_extra[128] = {
+  0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
+  12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 };
+
+// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values.
+typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
+static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1)
+{
+  mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist);
+  for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; }
+  while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
+  for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
+  {
+    const mz_uint32* pHist = &hist[pass << 8];
+    mz_uint offsets[256], cur_ofs = 0;
+    for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
+    for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
+    { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; }
+  }
+  return pCur_syms;
+}
+
+// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, [email protected], Jyrki Katajainen, [email protected], November 1996.
+static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
+{
+  int root, leaf, next, avbl, used, dpth;
+  if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
+  A[0].m_key += A[1].m_key; root = 0; leaf = 2;
+  for (next=1; next < n-1; next++)
+  {
+    if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = (mz_uint16)next; } else A[next].m_key = A[leaf++].m_key;
+    if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); A[root++].m_key = (mz_uint16)next; } else A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
+  }
+  A[n-2].m_key = 0; for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1;
+  avbl = 1; used = dpth = 0; root = n-2; next = n-1;
+  while (avbl>0)
+  {
+    while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
+    while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; }
+    avbl = 2*used; dpth++; used = 0;
+  }
+}
+
+// Limits canonical Huffman code table's max code size.
+enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
+static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
+{
+  int i; mz_uint32 total = 0; if (code_list_len <= 1) return;
+  for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
+  for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
+  while (total != (1UL << max_code_size))
+  {
+    pNum_codes[max_code_size]--;
+    for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
+    total--;
+  }
+}
+
+static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
+{
+  int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes);
+  if (static_table)
+  {
+    for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++;
+  }
+  else
+  {
+    tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
+    int num_used_syms = 0;
+    const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
+    for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; }
+
+    pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
+
+    for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
+
+    tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
+
+    MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
+    for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
+      for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
+  }
+
+  next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1);
+
+  for (i = 0; i < table_len; i++)
+  {
+    mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
+    code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
+    d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
+  }
+}
+
+#define TDEFL_PUT_BITS(b, l) do { \
+  mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \
+  d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \
+  while (d->m_bits_in >= 8) { \
+    if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
+      *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
+      d->m_bit_buffer >>= 8; \
+      d->m_bits_in -= 8; \
+  } \
+} MZ_MACRO_END
+
+#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \
+  if (rle_repeat_count < 3) { \
+    d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
+    while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
+  } else { \
+    d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
+} rle_repeat_count = 0; } }
+
+#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \
+  if (rle_z_count < 3) { \
+    d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \
+  } else if (rle_z_count <= 10) { \
+    d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
+  } else { \
+    d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
+} rle_z_count = 0; } }
+
+static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
+
+static void tdefl_start_dynamic_block(tdefl_compressor *d)
+{
+  int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
+  mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
+
+  d->m_huff_count[0][256] = 1;
+
+  tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
+  tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
+
+  for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
+  for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;
+
+  memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
+  memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
+  total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0;
+
+  memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
+  for (i = 0; i < total_code_sizes_to_pack; i++)
+  {
+    mz_uint8 code_size = code_sizes_to_pack[i];
+    if (!code_size)
+    {
+      TDEFL_RLE_PREV_CODE_SIZE();
+      if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); }
+    }
+    else
+    {
+      TDEFL_RLE_ZERO_CODE_SIZE();
+      if (code_size != prev_code_size)
+      {
+        TDEFL_RLE_PREV_CODE_SIZE();
+        d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size;
+      }
+      else if (++rle_repeat_count == 6)
+      {
+        TDEFL_RLE_PREV_CODE_SIZE();
+      }
+    }
+    prev_code_size = code_size;
+  }
+  if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); }
+
+  tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
+
+  TDEFL_PUT_BITS(2, 2);
+
+  TDEFL_PUT_BITS(num_lit_codes - 257, 5);
+  TDEFL_PUT_BITS(num_dist_codes - 1, 5);
+
+  for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break;
+  num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
+  for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
+
+  for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; )
+  {
+    mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
+    TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
+    if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
+  }
+}
+
+static void tdefl_start_static_block(tdefl_compressor *d)
+{
+  mz_uint i;
+  mz_uint8 *p = &d->m_huff_code_sizes[0][0];
+
+  for (i = 0; i <= 143; ++i) *p++ = 8;
+  for ( ; i <= 255; ++i) *p++ = 9;
+  for ( ; i <= 279; ++i) *p++ = 7;
+  for ( ; i <= 287; ++i) *p++ = 8;
+
+  memset(d->m_huff_code_sizes[1], 5, 32);
+
+  tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
+  tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
+
+  TDEFL_PUT_BITS(1, 2);
+}
+
+static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
+static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
+{
+  mz_uint flags;
+  mz_uint8 *pLZ_codes;
+  mz_uint8 *pOutput_buf = d->m_pOutput_buf;
+  mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
+  mz_uint64 bit_buffer = d->m_bit_buffer;
+  mz_uint bits_in = d->m_bits_in;
+
+#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); }
+
+  flags = 1;
+  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
+  {
+    if (flags == 1)
+      flags = *pLZ_codes++ | 0x100;
+
+    if (flags & 1)
+    {
+      mz_uint s0, s1, n0, n1, sym, num_extra_bits;
+      mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3;
+
+      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
+      TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
+      TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
+
+      // This sequence coaxes MSVC into using cmov's vs. jmp's.
+      s0 = s_tdefl_small_dist_sym[match_dist & 511];
+      n0 = s_tdefl_small_dist_extra[match_dist & 511];
+      s1 = s_tdefl_large_dist_sym[match_dist >> 8];
+      n1 = s_tdefl_large_dist_extra[match_dist >> 8];
+      sym = (match_dist < 512) ? s0 : s1;
+      num_extra_bits = (match_dist < 512) ? n0 : n1;
+
+      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
+      TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
+      TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
+    }
+    else
+    {
+      mz_uint lit = *pLZ_codes++;
+      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
+      TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
+
+      if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
+      {
+        flags >>= 1;
+        lit = *pLZ_codes++;
+        MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
+        TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
+
+        if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
+        {
+          flags >>= 1;
+          lit = *pLZ_codes++;
+          MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
+          TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
+        }
+      }
+    }
+
+    if (pOutput_buf >= d->m_pOutput_buf_end)
+      return MZ_FALSE;
+
+    *(mz_uint64*)pOutput_buf = bit_buffer;
+    pOutput_buf += (bits_in >> 3);
+    bit_buffer >>= (bits_in & ~7);
+    bits_in &= 7;
+  }
+
+#undef TDEFL_PUT_BITS_FAST
+
+  d->m_pOutput_buf = pOutput_buf;
+  d->m_bits_in = 0;
+  d->m_bit_buffer = 0;
+
+  while (bits_in)
+  {
+    mz_uint32 n = MZ_MIN(bits_in, 16);
+    TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
+    bit_buffer >>= n;
+    bits_in -= n;
+  }
+
+  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
+
+  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
+}
+#else
+static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
+{
+  mz_uint flags;
+  mz_uint8 *pLZ_codes;
+
+  flags = 1;
+  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
+  {
+    if (flags == 1)
+      flags = *pLZ_codes++ | 0x100;
+    if (flags & 1)
+    {
+      mz_uint sym, num_extra_bits;
+      mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3;
+
+      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
+      TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
+      TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
+
+      if (match_dist < 512)
+      {
+        sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist];
+      }
+      else
+      {
+        sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
+      }
+      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
+      TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
+      TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
+    }
+    else
+    {
+      mz_uint lit = *pLZ_codes++;
+      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
+      TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
+    }
+  }
+
+  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
+
+  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
+}
+#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
+
+static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
+{
+  if (static_block)
+    tdefl_start_static_block(d);
+  else
+    tdefl_start_dynamic_block(d);
+  return tdefl_compress_lz_codes(d);
+}
+
+static int tdefl_flush_block(tdefl_compressor *d, int flush)
+{
+  mz_uint saved_bit_buf, saved_bits_in;
+  mz_uint8 *pSaved_output_buf;
+  mz_bool comp_block_succeeded = MZ_FALSE;
+  int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
+  mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
+
+  d->m_pOutput_buf = pOutput_buf_start;
+  d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
+
+  MZ_ASSERT(!d->m_output_flush_remaining);
+  d->m_output_flush_ofs = 0;
+  d->m_output_flush_remaining = 0;
+
+  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
+  d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
+
+  if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
+  {
+    TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8);
+  }
+
+  TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
+
+  pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in;
+
+  if (!use_raw_block)
+    comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
+
+  // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead.
+  if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
+       ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) )
+  {
+    mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
+    TDEFL_PUT_BITS(0, 2);
+    if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
+    for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
+    {
+      TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
+    }
+    for (i = 0; i < d->m_total_lz_bytes; ++i)
+    {
+      TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
+    }
+  }
+  // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes.
+  else if (!comp_block_succeeded)
+  {
+    d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
+    tdefl_compress_block(d, MZ_TRUE);
+  }
+
+  if (flush)
+  {
+    if (flush == TDEFL_FINISH)
+    {
+      if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
+      if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } }
+    }
+    else
+    {
+      mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); }
+    }
+  }
+
+  MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
+
+  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
+  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
+
+  d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++;
+
+  if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
+  {
+    if (d->m_pPut_buf_func)
+    {
+      *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
+      if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
+        return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
+    }
+    else if (pOutput_buf_start == d->m_output_buf)
+    {
+      int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
+      memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
+      d->m_out_buf_ofs += bytes_to_copy;
+      if ((n -= bytes_to_copy) != 0)
+      {
+        d->m_output_flush_ofs = bytes_to_copy;
+        d->m_output_flush_remaining = n;
+      }
+    }
+    else
+    {
+      d->m_out_buf_ofs += n;
+    }
+  }
+
+  return d->m_output_flush_remaining;
+}
+
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
+#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p)
+static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
+{
+  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
+  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
+  const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q;
+  mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s);
+  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
+  for ( ; ; )
+  {
+    for ( ; ; )
+    {
+      if (--num_probes_left == 0) return;
+      #define TDEFL_PROBE \
+        next_probe_pos = d->m_next[probe_pos]; \
+        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
+        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
+        if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break;
+      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
+    }
+    if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32;
+    do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
+                   (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
+    if (!probe_len)
+    {
+      *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break;
+    }
+    else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len)
+    {
+      *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break;
+      c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
+    }
+  }
+}
+#else
+static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
+{
+  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
+  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
+  const mz_uint8 *s = d->m_dict + pos, *p, *q;
+  mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
+  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
+  for ( ; ; )
+  {
+    for ( ; ; )
+    {
+      if (--num_probes_left == 0) return;
+      #define TDEFL_PROBE \
+        next_probe_pos = d->m_next[probe_pos]; \
+        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
+        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
+        if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break;
+      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
+    }
+    if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
+    if (probe_len > match_len)
+    {
+      *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
+      c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1];
+    }
+  }
+}
+#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
+
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
+static mz_bool tdefl_compress_fast(tdefl_compressor *d)
+{
+  // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio.
+  mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
+  mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
+  mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
+
+  while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
+  {
+    const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
+    mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
+    mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
+    d->m_src_buf_left -= num_bytes_to_process;
+    lookahead_size += num_bytes_to_process;
+
+    while (num_bytes_to_process)
+    {
+      mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
+      memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
+      if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
+        memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
+      d->m_pSrc += n;
+      dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
+      num_bytes_to_process -= n;
+    }
+
+    dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
+    if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break;
+
+    while (lookahead_size >= 4)
+    {
+      mz_uint cur_match_dist, cur_match_len = 1;
+      mz_uint8 *pCur_dict = d->m_dict + cur_pos;
+      mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
+      mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
+      mz_uint probe_pos = d->m_hash[hash];
+      d->m_hash[hash] = (mz_uint16)lookahead_pos;
+
+      if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
+      {
+        const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
+        const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
+        mz_uint32 probe_len = 32;
+        do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
+          (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
+        cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
+        if (!probe_len)
+          cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
+
+        if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)))
+        {
+          cur_match_len = 1;
+          *pLZ_code_buf++ = (mz_uint8)first_trigram;
+          *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
+          d->m_huff_count[0][(mz_uint8)first_trigram]++;
+        }
+        else
+        {
+          mz_uint32 s0, s1;
+          cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
+
+          MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
+
+          cur_match_dist--;
+
+          pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
+          *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
+          pLZ_code_buf += 3;
+          *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
+
+          s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
+          s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
+          d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
+
+          d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
+        }
+      }
+      else
+      {
+        *pLZ_code_buf++ = (mz_uint8)first_trigram;
+        *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
+        d->m_huff_count[0][(mz_uint8)first_trigram]++;
+      }
+
+      if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
+
+      total_lz_bytes += cur_match_len;
+      lookahead_pos += cur_match_len;
+      dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
+      cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
+      MZ_ASSERT(lookahead_size >= cur_match_len);
+      lookahead_size -= cur_match_len;
+
+      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
+      {
+        int n;
+        d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
+        d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
+        if ((n = tdefl_flush_block(d, 0)) != 0)
+          return (n < 0) ? MZ_FALSE : MZ_TRUE;
+        total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
+      }
+    }
+
+    while (lookahead_size)
+    {
+      mz_uint8 lit = d->m_dict[cur_pos];
+
+      total_lz_bytes++;
+      *pLZ_code_buf++ = lit;
+      *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
+      if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
+
+      d->m_huff_count[0][lit]++;
+
+      lookahead_pos++;
+      dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
+      cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
+      lookahead_size--;
+
+      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
+      {
+        int n;
+        d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
+        d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
+        if ((n = tdefl_flush_block(d, 0)) != 0)
+          return (n < 0) ? MZ_FALSE : MZ_TRUE;
+        total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
+      }
+    }
+  }
+
+  d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
+  d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
+  return MZ_TRUE;
+}
+#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
+
+static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
+{
+  d->m_total_lz_bytes++;
+  *d->m_pLZ_code_buf++ = lit;
+  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
+  d->m_huff_count[0][lit]++;
+}
+
+static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
+{
+  mz_uint32 s0, s1;
+
+  MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
+
+  d->m_total_lz_bytes += match_len;
+
+  d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
+
+  match_dist -= 1;
+  d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
+  d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3;
+
+  *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
+
+  s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
+  d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
+
+  if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
+}
+
+static mz_bool tdefl_compress_normal(tdefl_compressor *d)
+{
+  const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left;
+  tdefl_flush flush = d->m_flush;
+
+  while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
+  {
+    mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
+    // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN.
+    if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
+    {
+      mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
+      mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
+      mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
+      const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
+      src_buf_left -= num_bytes_to_process;
+      d->m_lookahead_size += num_bytes_to_process;
+      while (pSrc != pSrc_end)
+      {
+        mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
+        hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
+        d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
+        dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++;
+      }
+    }
+    else
+    {
+      while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
+      {
+        mz_uint8 c = *pSrc++;
+        mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
+        src_buf_left--;
+        d->m_dict[dst_pos] = c;
+        if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
+          d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
+        if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
+        {
+          mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
+          mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
+          d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
+        }
+      }
+    }
+    d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
+    if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
+      break;
+
+    // Simple lazy/greedy parsing state machine.
+    len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
+    if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
+    {
+      if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
+      {
+        mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
+        cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; }
+        if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1;
+      }
+    }
+    else
+    {
+      tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
+    }
+    if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
+    {
+      cur_match_dist = cur_match_len = 0;
+    }
+    if (d->m_saved_match_len)
+    {
+      if (cur_match_len > d->m_saved_match_len)
+      {
+        tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
+        if (cur_match_len >= 128)
+        {
+          tdefl_record_match(d, cur_match_len, cur_match_dist);
+          d->m_saved_match_len = 0; len_to_move = cur_match_len;
+        }
+        else
+        {
+          d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
+        }
+      }
+      else
+      {
+        tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
+        len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0;
+      }
+    }
+    else if (!cur_match_dist)
+      tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
+    else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
+    {
+      tdefl_record_match(d, cur_match_len, cur_match_dist);
+      len_to_move = cur_match_len;
+    }
+    else
+    {
+      d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
+    }
+    // Move the lookahead forward by len_to_move bytes.
+    d->m_lookahead_pos += len_to_move;
+    MZ_ASSERT(d->m_lookahead_size >= len_to_move);
+    d->m_lookahead_size -= len_to_move;
+    d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
+    // Check if it's time to flush the current LZ codes to the internal output buffer.
+    if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
+         ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) )
+    {
+      int n;
+      d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
+      if ((n = tdefl_flush_block(d, 0)) != 0)
+        return (n < 0) ? MZ_FALSE : MZ_TRUE;
+    }
+  }
+
+  d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
+  return MZ_TRUE;
+}
+
+static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
+{
+  if (d->m_pIn_buf_size)
+  {
+    *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
+  }
+
+  if (d->m_pOut_buf_size)
+  {
+    size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
+    memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
+    d->m_output_flush_ofs += (mz_uint)n;
+    d->m_output_flush_remaining -= (mz_uint)n;
+    d->m_out_buf_ofs += n;
+
+    *d->m_pOut_buf_size = d->m_out_buf_ofs;
+  }
+
+  return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
+}
+
+tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
+{
+  if (!d)
+  {
+    if (pIn_buf_size) *pIn_buf_size = 0;
+    if (pOut_buf_size) *pOut_buf_size = 0;
+    return TDEFL_STATUS_BAD_PARAM;
+  }
+
+  d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size;
+  d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size;
+  d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
+  d->m_out_buf_ofs = 0;
+  d->m_flush = flush;
+
+  if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
+        (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) )
+  {
+    if (pIn_buf_size) *pIn_buf_size = 0;
+    if (pOut_buf_size) *pOut_buf_size = 0;
+    return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
+  }
+  d->m_wants_to_finish |= (flush == TDEFL_FINISH);
+
+  if ((d->m_output_flush_remaining) || (d->m_finished))
+    return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
+
+#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
+  if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
+      ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
+      ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
+  {
+    if (!tdefl_compress_fast(d))
+      return d->m_prev_return_status;
+  }
+  else
+#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
+  {
+    if (!tdefl_compress_normal(d))
+      return d->m_prev_return_status;
+  }
+
+  if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
+    d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
+
+  if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
+  {
+    if (tdefl_flush_block(d, flush) < 0)
+      return d->m_prev_return_status;
+    d->m_finished = (flush == TDEFL_FINISH);
+    if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; }
+  }
+
+  return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
+}
+
+tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
+{
+  MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
+}
+
+tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
+{
+  d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user;
+  d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
+  d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
+  if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
+  d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
+  d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
+  d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8;
+  d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY;
+  d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1;
+  d->m_pIn_buf = NULL; d->m_pOut_buf = NULL;
+  d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL;
+  d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0;
+  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
+  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
+  return TDEFL_STATUS_OKAY;
+}
+
+tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
+{
+  return d->m_prev_return_status;
+}
+
+mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
+{
+  return d->m_adler32;
+}
+
+mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
+{
+  tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE;
+  pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE;
+  succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
+  succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
+  MZ_FREE(pComp); return succeeded;
+}
+
+typedef struct
+{
+  size_t m_size, m_capacity;
+  mz_uint8 *m_pBuf;
+  mz_bool m_expandable;
+} tdefl_output_buffer;
+
+static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
+{
+  tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
+  size_t new_size = p->m_size + len;
+  if (new_size > p->m_capacity)
+  {
+    size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE;
+    do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity);
+    pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE;
+    p->m_pBuf = pNew_buf; p->m_capacity = new_capacity;
+  }
+  memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size;
+  return MZ_TRUE;
+}
+
+void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
+{
+  tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
+  if (!pOut_len) return MZ_FALSE; else *pOut_len = 0;
+  out_buf.m_expandable = MZ_TRUE;
+  if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL;
+  *pOut_len = out_buf.m_size; return out_buf.m_pBuf;
+}
+
+size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
+{
+  tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
+  if (!pOut_buf) return 0;
+  out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len;
+  if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0;
+  return out_buf.m_size;
+}
+
+#ifndef MINIZ_NO_ZLIB_APIS
+static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32,  16, 32, 128, 256,  512, 768, 1500 };
+
+// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files).
+mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
+{
+  mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
+  if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
+
+  if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
+  else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES;
+  else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK;
+  else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
+  else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES;
+
+  return comp_flags;
+}
+#endif //MINIZ_NO_ZLIB_APIS
+
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal)
+#endif
+
+// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
+// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
+// This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck.
+void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
+{
+  // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined.
+  static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32,  16, 32, 128, 256,  512, 768, 1500 };
+  tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0;
+  if (!pComp) return NULL;
+  MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; }
+  // write dummy header
+  for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
+  // compress image data
+  tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
+  for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); }
+  if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
+  // write real header
+  *pLen_out = out_buf.m_size-41;
+  {
+    static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
+    mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
+      0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0,
+      (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54};
+    c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24);
+    memcpy(out_buf.m_pBuf, pnghdr, 41);
+  }
+  // write footer (IDAT CRC-32, followed by IEND chunk)
+  if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
+  c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24);
+  // compute final size of file, grab compressed data buffer and return
+  *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf;
+}
+void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
+{
+  // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out)
+  return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
+}
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+// ------------------- .ZIP archive reading
+
+#ifndef MINIZ_NO_ARCHIVE_APIS
+
+#ifdef MINIZ_NO_STDIO
+  #define MZ_FILE void *
+#else
+  #include <stdio.h>
+  #include <sys/stat.h>
+
+  #if defined(_MSC_VER) || defined(__MINGW64__)
+    static FILE *mz_fopen(const char *pFilename, const char *pMode)
+    {
+      FILE* pFile = NULL;
+      fopen_s(&pFile, pFilename, pMode);
+      return pFile;
+    }
+    static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
+    {
+      FILE* pFile = NULL;
+      if (freopen_s(&pFile, pPath, pMode, pStream))
+        return NULL;
+      return pFile;
+    }
+    #ifndef MINIZ_NO_TIME
+      #include <sys/utime.h>
+    #endif
+    #define MZ_FILE FILE
+    #define MZ_FOPEN mz_fopen
+    #define MZ_FCLOSE fclose
+    #define MZ_FREAD fread
+    #define MZ_FWRITE fwrite
+    #define MZ_FTELL64 _ftelli64
+    #define MZ_FSEEK64 _fseeki64
+    #define MZ_FILE_STAT_STRUCT _stat
+    #define MZ_FILE_STAT _stat
+    #define MZ_FFLUSH fflush
+    #define MZ_FREOPEN mz_freopen
+    #define MZ_DELETE_FILE remove
+  #elif defined(__MINGW32__)
+    #ifndef MINIZ_NO_TIME
+      #include <sys/utime.h>
+    #endif
+    #define MZ_FILE FILE
+    #define MZ_FOPEN(f, m) fopen(f, m)
+    #define MZ_FCLOSE fclose
+    #define MZ_FREAD fread
+    #define MZ_FWRITE fwrite
+    #define MZ_FTELL64 ftello64
+    #define MZ_FSEEK64 fseeko64
+    #define MZ_FILE_STAT_STRUCT _stat
+    #define MZ_FILE_STAT _stat
+    #define MZ_FFLUSH fflush
+    #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
+    #define MZ_DELETE_FILE remove
+  #elif defined(__TINYC__)
+    #ifndef MINIZ_NO_TIME
+      #include <sys/utime.h>
+    #endif
+    #define MZ_FILE FILE
+    #define MZ_FOPEN(f, m) fopen(f, m)
+    #define MZ_FCLOSE fclose
+    #define MZ_FREAD fread
+    #define MZ_FWRITE fwrite
+    #define MZ_FTELL64 ftell
+    #define MZ_FSEEK64 fseek
+    #define MZ_FILE_STAT_STRUCT stat
+    #define MZ_FILE_STAT stat
+    #define MZ_FFLUSH fflush
+    #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
+    #define MZ_DELETE_FILE remove
+  #elif defined(__GNUC__) && _LARGEFILE64_SOURCE
+    #ifndef MINIZ_NO_TIME
+      #include <utime.h>
+    #endif
+    #define MZ_FILE FILE
+    #define MZ_FOPEN(f, m) fopen64(f, m)
+    #define MZ_FCLOSE fclose
+    #define MZ_FREAD fread
+    #define MZ_FWRITE fwrite
+    #define MZ_FTELL64 ftello64
+    #define MZ_FSEEK64 fseeko64
+    #define MZ_FILE_STAT_STRUCT stat64
+    #define MZ_FILE_STAT stat64
+    #define MZ_FFLUSH fflush
+    #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
+    #define MZ_DELETE_FILE remove
+  #else
+    #ifndef MINIZ_NO_TIME
+      #include <utime.h>
+    #endif
+    #define MZ_FILE FILE
+    #define MZ_FOPEN(f, m) fopen(f, m)
+    #define MZ_FCLOSE fclose
+    #define MZ_FREAD fread
+    #define MZ_FWRITE fwrite
+    #define MZ_FTELL64 ftello
+    #define MZ_FSEEK64 fseeko
+    #define MZ_FILE_STAT_STRUCT stat
+    #define MZ_FILE_STAT stat
+    #define MZ_FFLUSH fflush
+    #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
+    #define MZ_DELETE_FILE remove
+  #endif // #ifdef _MSC_VER
+#endif // #ifdef MINIZ_NO_STDIO
+
+#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
+
+// Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff.
+enum
+{
+  // ZIP archive identifiers and record sizes
+  MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
+  MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
+  // Central directory header record offsets
+  MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
+  MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16,
+  MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
+  MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
+  // Local directory header offsets
+  MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10,
+  MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
+  MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
+  // End of central directory offsets
+  MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
+  MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
+};
+
+typedef struct
+{
+  void *m_p;
+  size_t m_size, m_capacity;
+  mz_uint m_element_size;
+} mz_zip_array;
+
+struct mz_zip_internal_state_tag
+{
+  mz_zip_array m_central_dir;
+  mz_zip_array m_central_dir_offsets;
+  mz_zip_array m_sorted_central_dir_offsets;
+  MZ_FILE *m_pFile;
+  void *m_pMem;
+  size_t m_mem_size;
+  size_t m_mem_capacity;
+};
+
+#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
+#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
+
+static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
+{
+  pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
+  memset(pArray, 0, sizeof(mz_zip_array));
+}
+
+static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
+{
+  void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE;
+  if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; }
+  if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE;
+  pArray->m_p = pNew_p; pArray->m_capacity = new_capacity;
+  return MZ_TRUE;
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
+{
+  if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; }
+  return MZ_TRUE;
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
+{
+  if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; }
+  pArray->m_size = new_size;
+  return MZ_TRUE;
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
+{
+  return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
+{
+  size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE;
+  memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
+  return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_TIME
+static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date)
+{
+  struct tm tm;
+  memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1;
+  tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31;
+  tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62;
+  return mktime(&tm);
+}
+
+static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
+{
+#ifdef _MSC_VER
+  struct tm tm_struct;
+  struct tm *tm = &tm_struct;
+  errno_t err = localtime_s(tm, &time);
+  if (err)
+  {
+    *pDOS_date = 0; *pDOS_time = 0;
+    return;
+  }
+#else
+  struct tm *tm = localtime(&time);
+#endif
+  *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
+  *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
+}
+#endif
+
+#ifndef MINIZ_NO_STDIO
+static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
+{
+#ifdef MINIZ_NO_TIME
+  (void)pFilename; *pDOS_date = *pDOS_time = 0;
+#else
+  struct MZ_FILE_STAT_STRUCT file_stat;
+  // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh.
+  if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
+    return MZ_FALSE;
+  mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date);
+#endif // #ifdef MINIZ_NO_TIME
+  return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_TIME
+static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time)
+{
+  struct utimbuf t; t.actime = access_time; t.modtime = modified_time;
+  return !utime(pFilename, &t);
+}
+#endif // #ifndef MINIZ_NO_TIME
+#endif // #ifndef MINIZ_NO_STDIO
+
+static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags)
+{
+  (void)flags;
+  if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
+    return MZ_FALSE;
+
+  if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
+  if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
+  if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
+
+  pZip->m_zip_mode = MZ_ZIP_MODE_READING;
+  pZip->m_archive_size = 0;
+  pZip->m_central_directory_file_ofs = 0;
+  pZip->m_total_files = 0;
+
+  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
+    return MZ_FALSE;
+  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
+  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
+  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
+  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
+  return MZ_TRUE;
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
+{
+  const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
+  const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
+  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+  mz_uint8 l = 0, r = 0;
+  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
+  pE = pL + MZ_MIN(l_len, r_len);
+  while (pL < pE)
+  {
+    if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
+      break;
+    pL++; pR++;
+  }
+  return (pL == pE) ? (l_len < r_len) : (l < r);
+}
+
+#define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END
+
+// Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.)
+static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
+{
+  mz_zip_internal_state *pState = pZip->m_pState;
+  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
+  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
+  mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
+  const int size = pZip->m_total_files;
+  int start = (size - 2) >> 1, end;
+  while (start >= 0)
+  {
+    int child, root = start;
+    for ( ; ; )
+    {
+      if ((child = (root << 1) + 1) >= size)
+        break;
+      child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])));
+      if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
+        break;
+      MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
+    }
+    start--;
+  }
+
+  end = size - 1;
+  while (end > 0)
+  {
+    int child, root = 0;
+    MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
+    for ( ; ; )
+    {
+      if ((child = (root << 1) + 1) >= end)
+        break;
+      child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]));
+      if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
+        break;
+      MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
+    }
+    end--;
+  }
+}
+
+static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags)
+{
+  mz_uint cdir_size, num_this_disk, cdir_disk_index;
+  mz_uint64 cdir_ofs;
+  mz_int64 cur_file_ofs;
+  const mz_uint8 *p;
+  mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
+  mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
+  // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there.
+  if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
+    return MZ_FALSE;
+  // Find the end of central directory record by scanning the file from the end towards the beginning.
+  cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
+  for ( ; ; )
+  {
+    int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
+    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
+      return MZ_FALSE;
+    for (i = n - 4; i >= 0; --i)
+      if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
+        break;
+    if (i >= 0)
+    {
+      cur_file_ofs += i;
+      break;
+    }
+    if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
+      return MZ_FALSE;
+    cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
+  }
+  // Read and verify the end of central directory record.
+  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
+    return MZ_FALSE;
+  if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
+      ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
+    return MZ_FALSE;
+
+  num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
+  cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
+  if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
+    return MZ_FALSE;
+
+  if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
+    return MZ_FALSE;
+
+  cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
+  if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
+    return MZ_FALSE;
+
+  pZip->m_central_directory_file_ofs = cdir_ofs;
+
+  if (pZip->m_total_files)
+  {
+     mz_uint i, n;
+
+    // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices.
+    if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
+        (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
+      return MZ_FALSE;
+
+    if (sort_central_dir)
+    {
+      if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
+        return MZ_FALSE;
+    }
+
+    if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
+      return MZ_FALSE;
+
+    // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported).
+    p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
+    for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
+    {
+      mz_uint total_header_size, comp_size, decomp_size, disk_index;
+      if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
+        return MZ_FALSE;
+      MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
+      if (sort_central_dir)
+        MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
+      comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
+      decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
+      if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF))
+        return MZ_FALSE;
+      disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
+      if ((disk_index != num_this_disk) && (disk_index != 1))
+        return MZ_FALSE;
+      if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
+        return MZ_FALSE;
+      if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
+        return MZ_FALSE;
+      n -= total_header_size; p += total_header_size;
+    }
+  }
+
+  if (sort_central_dir)
+    mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
+
+  return MZ_TRUE;
+}
+
+mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags)
+{
+  if ((!pZip) || (!pZip->m_pRead))
+    return MZ_FALSE;
+  if (!mz_zip_reader_init_internal(pZip, flags))
+    return MZ_FALSE;
+  pZip->m_archive_size = size;
+  if (!mz_zip_reader_read_central_dir(pZip, flags))
+  {
+    mz_zip_reader_end(pZip);
+    return MZ_FALSE;
+  }
+  return MZ_TRUE;
+}
+
+static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
+{
+  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
+  size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
+  memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
+  return s;
+}
+
+mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags)
+{
+  if (!mz_zip_reader_init_internal(pZip, flags))
+    return MZ_FALSE;
+  pZip->m_archive_size = size;
+  pZip->m_pRead = mz_zip_mem_read_func;
+  pZip->m_pIO_opaque = pZip;
+#ifdef __cplusplus
+  pZip->m_pState->m_pMem = const_cast<void *>(pMem);
+#else
+  pZip->m_pState->m_pMem = (void *)pMem;
+#endif
+  pZip->m_pState->m_mem_size = size;
+  if (!mz_zip_reader_read_central_dir(pZip, flags))
+  {
+    mz_zip_reader_end(pZip);
+    return MZ_FALSE;
+  }
+  return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_STDIO
+static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
+{
+  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
+  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
+  if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
+    return 0;
+  return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
+}
+
+mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
+{
+  mz_uint64 file_size;
+  MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
+  if (!pFile)
+    return MZ_FALSE;
+  if (MZ_FSEEK64(pFile, 0, SEEK_END))
+  {
+    MZ_FCLOSE(pFile);
+    return MZ_FALSE;
+  }
+  file_size = MZ_FTELL64(pFile);
+  if (!mz_zip_reader_init_internal(pZip, flags))
+  {
+    MZ_FCLOSE(pFile);
+    return MZ_FALSE;
+  }
+  pZip->m_pRead = mz_zip_file_read_func;
+  pZip->m_pIO_opaque = pZip;
+  pZip->m_pState->m_pFile = pFile;
+  pZip->m_archive_size = file_size;
+  if (!mz_zip_reader_read_central_dir(pZip, flags))
+  {
+    mz_zip_reader_end(pZip);
+    return MZ_FALSE;
+  }
+  return MZ_TRUE;
+}
+#endif // #ifndef MINIZ_NO_STDIO
+
+mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
+{
+  return pZip ? pZip->m_total_files : 0;
+}
+
+static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
+{
+  if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
+    return NULL;
+  return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
+}
+
+mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
+{
+  mz_uint m_bit_flag;
+  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
+  if (!p)
+    return MZ_FALSE;
+  m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
+  return (m_bit_flag & 1);
+}
+
+mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
+{
+  mz_uint filename_len, external_attr;
+  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
+  if (!p)
+    return MZ_FALSE;
+
+  // First see if the filename ends with a '/' character.
+  filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+  if (filename_len)
+  {
+    if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
+      return MZ_TRUE;
+  }
+
+  // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct.
+  // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field.
+  // FIXME: Remove this check? Is it necessary - we already check the filename.
+  external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
+  if ((external_attr & 0x10) != 0)
+    return MZ_TRUE;
+
+  return MZ_FALSE;
+}
+
+mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
+{
+  mz_uint n;
+  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
+  if ((!p) || (!pStat))
+    return MZ_FALSE;
+
+  // Unpack the central directory record.
+  pStat->m_file_index = file_index;
+  pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
+  pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
+  pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
+  pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
+  pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
+#ifndef MINIZ_NO_TIME
+  pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
+#endif
+  pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
+  pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
+  pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
+  pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
+  pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
+  pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
+
+  // Copy as much of the filename and comment as possible.
+  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
+  memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0';
+
+  n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
+  pStat->m_comment_size = n;
+  memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0';
+
+  return MZ_TRUE;
+}
+
+mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
+{
+  mz_uint n;
+  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
+  if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; }
+  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+  if (filename_buf_size)
+  {
+    n = MZ_MIN(n, filename_buf_size - 1);
+    memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
+    pFilename[n] = '\0';
+  }
+  return n + 1;
+}
+
+static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
+{
+  mz_uint i;
+  if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
+    return 0 == memcmp(pA, pB, len);
+  for (i = 0; i < len; ++i)
+    if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
+      return MZ_FALSE;
+  return MZ_TRUE;
+}
+
+static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
+{
+  const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
+  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+  mz_uint8 l = 0, r = 0;
+  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
+  pE = pL + MZ_MIN(l_len, r_len);
+  while (pL < pE)
+  {
+    if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
+      break;
+    pL++; pR++;
+  }
+  return (pL == pE) ? (int)(l_len - r_len) : (l - r);
+}
+
+static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename)
+{
+  mz_zip_internal_state *pState = pZip->m_pState;
+  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
+  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
+  mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
+  const int size = pZip->m_total_files;
+  const mz_uint filename_len = (mz_uint)strlen(pFilename);
+  int l = 0, h = size - 1;
+  while (l <= h)
+  {
+    int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
+    if (!comp)
+      return file_index;
+    else if (comp < 0)
+      l = m + 1;
+    else
+      h = m - 1;
+  }
+  return -1;
+}
+
+int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
+{
+  mz_uint file_index; size_t name_len, comment_len;
+  if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
+    return -1;
+  if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
+    return mz_zip_reader_locate_file_binary_search(pZip, pName);
+  name_len = strlen(pName); if (name_len > 0xFFFF) return -1;
+  comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1;
+  for (file_index = 0; file_index < pZip->m_total_files; file_index++)
+  {
+    const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
+    mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
+    const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
+    if (filename_len < name_len)
+      continue;
+    if (comment_len)
+    {
+      mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
+      const char *pFile_comment = pFilename + filename_len + file_extra_len;
+      if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags)))
+        continue;
+    }
+    if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
+    {
+      int ofs = filename_len - 1;
+      do
+      {
+        if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
+          break;
+      } while (--ofs >= 0);
+      ofs++;
+      pFilename += ofs; filename_len -= ofs;
+    }
+    if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
+      return file_index;
+  }
+  return -1;
+}
+
+mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
+{
+  int status = TINFL_STATUS_DONE;
+  mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
+  mz_zip_archive_file_stat file_stat;
+  void *pRead_buf;
+  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
+  tinfl_decompressor inflator;
+
+  if ((buf_size) && (!pBuf))
+    return MZ_FALSE;
+
+  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
+    return MZ_FALSE;
+
+  // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
+  if (!file_stat.m_comp_size)
+    return MZ_TRUE;
+
+  // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
+  // I'm torn how to handle this case - should it fail instead?
+  if (mz_zip_reader_is_file_a_directory(pZip, file_index))
+    return MZ_TRUE;
+
+  // Encryption and patch files are not supported.
+  if (file_stat.m_bit_flag & (1 | 32))
+    return MZ_FALSE;
+
+  // This function only supports stored and deflate.
+  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
+    return MZ_FALSE;
+
+  // Ensure supplied output buffer is large enough.
+  needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
+  if (buf_size < needed_size)
+    return MZ_FALSE;
+
+  // Read and parse the local directory entry.
+  cur_file_ofs = file_stat.m_local_header_ofs;
+  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
+    return MZ_FALSE;
+  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
+    return MZ_FALSE;
+
+  cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
+  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
+    return MZ_FALSE;
+
+  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
+  {
+    // The file is stored or the caller has requested the compressed data.
+    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
+      return MZ_FALSE;
+    return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
+  }
+
+  // Decompress the file either directly from memory or from a file input buffer.
+  tinfl_init(&inflator);
+
+  if (pZip->m_pState->m_pMem)
+  {
+    // Read directly from the archive in memory.
+    pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
+    read_buf_size = read_buf_avail = file_stat.m_comp_size;
+    comp_remaining = 0;
+  }
+  else if (pUser_read_buf)
+  {
+    // Use a user provided read buffer.
+    if (!user_read_buf_size)
+      return MZ_FALSE;
+    pRead_buf = (mz_uint8 *)pUser_read_buf;
+    read_buf_size = user_read_buf_size;
+    read_buf_avail = 0;
+    comp_remaining = file_stat.m_comp_size;
+  }
+  else
+  {
+    // Temporarily allocate a read buffer.
+    read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
+#ifdef _MSC_VER
+    if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
+#else
+    if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
+#endif
+      return MZ_FALSE;
+    if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
+      return MZ_FALSE;
+    read_buf_avail = 0;
+    comp_remaining = file_stat.m_comp_size;
+  }
+
+  do
+  {
+    size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
+    if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
+    {
+      read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
+      if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
+      {
+        status = TINFL_STATUS_FAILED;
+        break;
+      }
+      cur_file_ofs += read_buf_avail;
+      comp_remaining -= read_buf_avail;
+      read_buf_ofs = 0;
+    }
+    in_buf_size = (size_t)read_buf_avail;
+    status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
+    read_buf_avail -= in_buf_size;
+    read_buf_ofs += in_buf_size;
+    out_buf_ofs += out_buf_size;
+  } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
+
+  if (status == TINFL_STATUS_DONE)
+  {
+    // Make sure the entire file was decompressed, and check its CRC.
+    if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
+      status = TINFL_STATUS_FAILED;
+  }
+
+  if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
+    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+
+  return status == TINFL_STATUS_DONE;
+}
+
+mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
+{
+  int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
+  if (file_index < 0)
+    return MZ_FALSE;
+  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
+}
+
+mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
+{
+  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
+}
+
+mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
+{
+  return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
+}
+
+void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
+{
+  mz_uint64 comp_size, uncomp_size, alloc_size;
+  const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
+  void *pBuf;
+
+  if (pSize)
+    *pSize = 0;
+  if (!p)
+    return NULL;
+
+  comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
+  uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
+
+  alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
+#ifdef _MSC_VER
+  if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
+#else
+  if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
+#endif
+    return NULL;
+  if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
+    return NULL;
+
+  if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
+  {
+    pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+    return NULL;
+  }
+
+  if (pSize) *pSize = (size_t)alloc_size;
+  return pBuf;
+}
+
+void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
+{
+  int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
+  if (file_index < 0)
+  {
+    if (pSize) *pSize = 0;
+    return MZ_FALSE;
+  }
+  return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
+}
+
+mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
+{
+  int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT;
+  mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
+  mz_zip_archive_file_stat file_stat;
+  void *pRead_buf = NULL; void *pWrite_buf = NULL;
+  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
+
+  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
+    return MZ_FALSE;
+
+  // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
+  if (!file_stat.m_comp_size)
+    return MZ_TRUE;
+
+  // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
+  // I'm torn how to handle this case - should it fail instead?
+  if (mz_zip_reader_is_file_a_directory(pZip, file_index))
+    return MZ_TRUE;
+
+  // Encryption and patch files are not supported.
+  if (file_stat.m_bit_flag & (1 | 32))
+    return MZ_FALSE;
+
+  // This function only supports stored and deflate.
+  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
+    return MZ_FALSE;
+
+  // Read and parse the local directory entry.
+  cur_file_ofs = file_stat.m_local_header_ofs;
+  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
+    return MZ_FALSE;
+  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
+    return MZ_FALSE;
+
+  cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
+  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
+    return MZ_FALSE;
+
+  // Decompress the file either directly from memory or from a file input buffer.
+  if (pZip->m_pState->m_pMem)
+  {
+    pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
+    read_buf_size = read_buf_avail = file_stat.m_comp_size;
+    comp_remaining = 0;
+  }
+  else
+  {
+    read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
+    if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
+      return MZ_FALSE;
+    read_buf_avail = 0;
+    comp_remaining = file_stat.m_comp_size;
+  }
+
+  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
+  {
+    // The file is stored or the caller has requested the compressed data.
+    if (pZip->m_pState->m_pMem)
+    {
+#ifdef _MSC_VER
+      if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
+#else
+      if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
+#endif
+        return MZ_FALSE;
+      if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
+        status = TINFL_STATUS_FAILED;
+      else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
+        file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
+      cur_file_ofs += file_stat.m_comp_size;
+      out_buf_ofs += file_stat.m_comp_size;
+      comp_remaining = 0;
+    }
+    else
+    {
+      while (comp_remaining)
+      {
+        read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
+        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
+        {
+          status = TINFL_STATUS_FAILED;
+          break;
+        }
+
+        if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
+          file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
+
+        if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
+        {
+          status = TINFL_STATUS_FAILED;
+          break;
+        }
+        cur_file_ofs += read_buf_avail;
+        out_buf_ofs += read_buf_avail;
+        comp_remaining -= read_buf_avail;
+      }
+    }
+  }
+  else
+  {
+    tinfl_decompressor inflator;
+    tinfl_init(&inflator);
+
+    if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
+      status = TINFL_STATUS_FAILED;
+    else
+    {
+      do
+      {
+        mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
+        size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
+        if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
+        {
+          read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
+          if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
+          {
+            status = TINFL_STATUS_FAILED;
+            break;
+          }
+          cur_file_ofs += read_buf_avail;
+          comp_remaining -= read_buf_avail;
+          read_buf_ofs = 0;
+        }
+
+        in_buf_size = (size_t)read_buf_avail;
+        status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
+        read_buf_avail -= in_buf_size;
+        read_buf_ofs += in_buf_size;
+
+        if (out_buf_size)
+        {
+          if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
+          {
+            status = TINFL_STATUS_FAILED;
+            break;
+          }
+          file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
+          if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
+          {
+            status = TINFL_STATUS_FAILED;
+            break;
+          }
+        }
+      } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
+    }
+  }
+
+  if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
+  {
+    // Make sure the entire file was decompressed, and check its CRC.
+    if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32))
+      status = TINFL_STATUS_FAILED;
+  }
+
+  if (!pZip->m_pState->m_pMem)
+    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+  if (pWrite_buf)
+    pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
+
+  return status == TINFL_STATUS_DONE;
+}
+
+mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
+{
+  int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
+  if (file_index < 0)
+    return MZ_FALSE;
+  return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
+}
+
+#ifndef MINIZ_NO_STDIO
+static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
+{
+  (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque);
+}
+
+mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
+{
+  mz_bool status;
+  mz_zip_archive_file_stat file_stat;
+  MZ_FILE *pFile;
+  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
+    return MZ_FALSE;
+  pFile = MZ_FOPEN(pDst_filename, "wb");
+  if (!pFile)
+    return MZ_FALSE;
+  status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
+  if (MZ_FCLOSE(pFile) == EOF)
+    return MZ_FALSE;
+#ifndef MINIZ_NO_TIME
+  if (status)
+    mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
+#endif
+  return status;
+}
+#endif // #ifndef MINIZ_NO_STDIO
+
+mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
+{
+  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
+    return MZ_FALSE;
+
+  if (pZip->m_pState)
+  {
+    mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL;
+    mz_zip_array_clear(pZip, &pState->m_central_dir);
+    mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
+    mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
+
+#ifndef MINIZ_NO_STDIO
+    if (pState->m_pFile)
+    {
+      MZ_FCLOSE(pState->m_pFile);
+      pState->m_pFile = NULL;
+    }
+#endif // #ifndef MINIZ_NO_STDIO
+
+    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
+  }
+  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
+
+  return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
+{
+  int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
+  if (file_index < 0)
+    return MZ_FALSE;
+  return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
+}
+#endif
+
+// ------------------- .ZIP archive writing
+
+#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
+
+static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); }
+static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); }
+#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
+#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
+
+mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
+{
+  if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
+    return MZ_FALSE;
+
+  if (pZip->m_file_offset_alignment)
+  {
+    // Ensure user specified file offset alignment is a power of 2.
+    if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
+      return MZ_FALSE;
+  }
+
+  if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
+  if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
+  if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
+
+  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
+  pZip->m_archive_size = existing_size;
+  pZip->m_central_directory_file_ofs = 0;
+  pZip->m_total_files = 0;
+
+  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
+    return MZ_FALSE;
+  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
+  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
+  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
+  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
+  return MZ_TRUE;
+}
+
+static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
+{
+  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
+  mz_zip_internal_state *pState = pZip->m_pState;
+  mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
+#ifdef _MSC_VER
+  if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
+#else
+  if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
+#endif
+    return 0;
+  if (new_size > pState->m_mem_capacity)
+  {
+    void *pNew_block;
+    size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2;
+    if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
+      return 0;
+    pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity;
+  }
+  memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
+  pState->m_mem_size = (size_t)new_size;
+  return n;
+}
+
+mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
+{
+  pZip->m_pWrite = mz_zip_heap_write_func;
+  pZip->m_pIO_opaque = pZip;
+  if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
+    return MZ_FALSE;
+  if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
+  {
+    if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
+    {
+      mz_zip_writer_end(pZip);
+      return MZ_FALSE;
+    }
+    pZip->m_pState->m_mem_capacity = initial_allocation_size;
+  }
+  return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_STDIO
+static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
+{
+  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
+  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
+  if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
+    return 0;
+  return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
+}
+
+mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
+{
+  MZ_FILE *pFile;
+  pZip->m_pWrite = mz_zip_file_write_func;
+  pZip->m_pIO_opaque = pZip;
+  if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
+    return MZ_FALSE;
+  if (NULL == (pFile = MZ_FOPEN(pFilename, "wb")))
+  {
+    mz_zip_writer_end(pZip);
+    return MZ_FALSE;
+  }
+  pZip->m_pState->m_pFile = pFile;
+  if (size_to_reserve_at_beginning)
+  {
+    mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf);
+    do
+    {
+      size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
+      if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
+      {
+        mz_zip_writer_end(pZip);
+        return MZ_FALSE;
+      }
+      cur_ofs += n; size_to_reserve_at_beginning -= n;
+    } while (size_to_reserve_at_beginning);
+  }
+  return MZ_TRUE;
+}
+#endif // #ifndef MINIZ_NO_STDIO
+
+mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
+{
+  mz_zip_internal_state *pState;
+  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
+    return MZ_FALSE;
+  // No sense in trying to write to an archive that's already at the support max size
+  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
+    return MZ_FALSE;
+
+  pState = pZip->m_pState;
+
+  if (pState->m_pFile)
+  {
+#ifdef MINIZ_NO_STDIO
+    pFilename; return MZ_FALSE;
+#else
+    // Archive is being read from stdio - try to reopen as writable.
+    if (pZip->m_pIO_opaque != pZip)
+      return MZ_FALSE;
+    if (!pFilename)
+      return MZ_FALSE;
+    pZip->m_pWrite = mz_zip_file_write_func;
+    if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
+    {
+      // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it.
+      mz_zip_reader_end(pZip);
+      return MZ_FALSE;
+    }
+#endif // #ifdef MINIZ_NO_STDIO
+  }
+  else if (pState->m_pMem)
+  {
+    // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback.
+    if (pZip->m_pIO_opaque != pZip)
+      return MZ_FALSE;
+    pState->m_mem_capacity = pState->m_mem_size;
+    pZip->m_pWrite = mz_zip_heap_write_func;
+  }
+  // Archive is being read via a user provided read function - make sure the user has specified a write function too.
+  else if (!pZip->m_pWrite)
+    return MZ_FALSE;
+
+  // Start writing new files at the archive's current central directory location.
+  pZip->m_archive_size = pZip->m_central_directory_file_ofs;
+  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
+  pZip->m_central_directory_file_ofs = 0;
+
+  return MZ_TRUE;
+}
+
+mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
+{
+  return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
+}
+
+typedef struct
+{
+  mz_zip_archive *m_pZip;
+  mz_uint64 m_cur_archive_file_ofs;
+  mz_uint64 m_comp_size;
+} mz_zip_writer_add_state;
+
+static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser)
+{
+  mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
+  if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
+    return MZ_FALSE;
+  pState->m_cur_archive_file_ofs += len;
+  pState->m_comp_size += len;
+  return MZ_TRUE;
+}
+
+static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
+{
+  (void)pZip;
+  memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
+  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
+  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
+  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
+  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
+  return MZ_TRUE;
+}
+
+static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
+{
+  (void)pZip;
+  memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
+  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
+  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
+  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
+  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
+  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
+  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
+  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
+  return MZ_TRUE;
+}
+
+static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
+{
+  mz_zip_internal_state *pState = pZip->m_pState;
+  mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
+  size_t orig_central_dir_size = pState->m_central_dir.m_size;
+  mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
+
+  // No zip64 support yet
+  if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF))
+    return MZ_FALSE;
+
+  if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
+    return MZ_FALSE;
+
+  if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
+      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
+      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
+      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
+      (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
+  {
+    // Try to push the central directory array back into its original state.
+    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
+    return MZ_FALSE;
+  }
+
+  return MZ_TRUE;
+}
+
+static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
+{
+  // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes.
+  if (*pArchive_name == '/')
+    return MZ_FALSE;
+  while (*pArchive_name)
+  {
+    if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
+      return MZ_FALSE;
+    pArchive_name++;
+  }
+  return MZ_TRUE;
+}
+
+static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
+{
+  mz_uint32 n;
+  if (!pZip->m_file_offset_alignment)
+    return 0;
+  n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
+  return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1);
+}
+
+static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
+{
+  char buf[4096];
+  memset(buf, 0, MZ_MIN(sizeof(buf), n));
+  while (n)
+  {
+    mz_uint32 s = MZ_MIN(sizeof(buf), n);
+    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
+      return MZ_FALSE;
+    cur_file_ofs += s; n -= s;
+  }
+  return MZ_TRUE;
+}
+
+mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
+{
+  mz_uint16 method = 0, dos_time = 0, dos_date = 0;
+  mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
+  mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
+  size_t archive_name_size;
+  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
+  tdefl_compressor *pComp = NULL;
+  mz_bool store_data_uncompressed;
+  mz_zip_internal_state *pState;
+
+  if ((int)level_and_flags < 0)
+    level_and_flags = MZ_DEFAULT_LEVEL;
+  level = level_and_flags & 0xF;
+  store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
+
+  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
+    return MZ_FALSE;
+
+  pState = pZip->m_pState;
+
+  if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
+    return MZ_FALSE;
+  // No zip64 support yet
+  if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
+    return MZ_FALSE;
+  if (!mz_zip_writer_validate_archive_name(pArchive_name))
+    return MZ_FALSE;
+
+#ifndef MINIZ_NO_TIME
+  {
+    time_t cur_time; time(&cur_time);
+    mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date);
+  }
+#endif // #ifndef MINIZ_NO_TIME
+
+  archive_name_size = strlen(pArchive_name);
+  if (archive_name_size > 0xFFFF)
+    return MZ_FALSE;
+
+  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
+
+  // no zip64 support yet
+  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
+    return MZ_FALSE;
+
+  if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
+  {
+    // Set DOS Subdirectory attribute bit.
+    ext_attributes |= 0x10;
+    // Subdirectories cannot contain data.
+    if ((buf_size) || (uncomp_size))
+      return MZ_FALSE;
+  }
+
+  // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.)
+  if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
+    return MZ_FALSE;
+
+  if ((!store_data_uncompressed) && (buf_size))
+  {
+    if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
+      return MZ_FALSE;
+  }
+
+  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
+  {
+    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+    return MZ_FALSE;
+  }
+  local_dir_header_ofs += num_alignment_padding_bytes;
+  if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
+  cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
+
+  MZ_CLEAR_OBJ(local_dir_header);
+  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
+  {
+    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+    return MZ_FALSE;
+  }
+  cur_archive_file_ofs += archive_name_size;
+
+  if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
+  {
+    uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size);
+    uncomp_size = buf_size;
+    if (uncomp_size <= 3)
+    {
+      level = 0;
+      store_data_uncompressed = MZ_TRUE;
+    }
+  }
+
+  if (store_data_uncompressed)
+  {
+    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
+    {
+      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+      return MZ_FALSE;
+    }
+
+    cur_archive_file_ofs += buf_size;
+    comp_size = buf_size;
+
+    if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
+      method = MZ_DEFLATED;
+  }
+  else if (buf_size)
+  {
+    mz_zip_writer_add_state state;
+
+    state.m_pZip = pZip;
+    state.m_cur_archive_file_ofs = cur_archive_file_ofs;
+    state.m_comp_size = 0;
+
+    if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
+        (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
+    {
+      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+      return MZ_FALSE;
+    }
+
+    comp_size = state.m_comp_size;
+    cur_archive_file_ofs = state.m_cur_archive_file_ofs;
+
+    method = MZ_DEFLATED;
+  }
+
+  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+  pComp = NULL;
+
+  // no zip64 support yet
+  if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
+    return MZ_FALSE;
+
+  if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
+    return MZ_FALSE;
+
+  if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
+    return MZ_FALSE;
+
+  if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
+    return MZ_FALSE;
+
+  pZip->m_total_files++;
+  pZip->m_archive_size = cur_archive_file_ofs;
+
+  return MZ_TRUE;
+}
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
+{
+  mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
+  mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
+  mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0;
+  size_t archive_name_size;
+  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
+  MZ_FILE *pSrc_file = NULL;
+
+  if ((int)level_and_flags < 0)
+    level_and_flags = MZ_DEFAULT_LEVEL;
+  level = level_and_flags & 0xF;
+
+  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
+    return MZ_FALSE;
+  if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
+    return MZ_FALSE;
+  if (!mz_zip_writer_validate_archive_name(pArchive_name))
+    return MZ_FALSE;
+
+  archive_name_size = strlen(pArchive_name);
+  if (archive_name_size > 0xFFFF)
+    return MZ_FALSE;
+
+  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
+
+  // no zip64 support yet
+  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
+    return MZ_FALSE;
+
+  if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date))
+    return MZ_FALSE;
+    
+  pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
+  if (!pSrc_file)
+    return MZ_FALSE;
+  MZ_FSEEK64(pSrc_file, 0, SEEK_END);
+  uncomp_size = MZ_FTELL64(pSrc_file);
+  MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
+
+  if (uncomp_size > 0xFFFFFFFF)
+  {
+    // No zip64 support yet
+    MZ_FCLOSE(pSrc_file);
+    return MZ_FALSE;
+  }
+  if (uncomp_size <= 3)
+    level = 0;
+
+  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
+  {
+    MZ_FCLOSE(pSrc_file);
+    return MZ_FALSE;
+  }
+  local_dir_header_ofs += num_alignment_padding_bytes;
+  if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
+  cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
+
+  MZ_CLEAR_OBJ(local_dir_header);
+  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
+  {
+    MZ_FCLOSE(pSrc_file);
+    return MZ_FALSE;
+  }
+  cur_archive_file_ofs += archive_name_size;
+
+  if (uncomp_size)
+  {
+    mz_uint64 uncomp_remaining = uncomp_size;
+    void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
+    if (!pRead_buf)
+    {
+      MZ_FCLOSE(pSrc_file);
+      return MZ_FALSE;
+    }
+
+    if (!level)
+    {
+      while (uncomp_remaining)
+      {
+        mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
+        if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
+        {
+          pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+          MZ_FCLOSE(pSrc_file);
+          return MZ_FALSE;
+        }
+        uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
+        uncomp_remaining -= n;
+        cur_archive_file_ofs += n;
+      }
+      comp_size = uncomp_size;
+    }
+    else
+    {
+      mz_bool result = MZ_FALSE;
+      mz_zip_writer_add_state state;
+      tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
+      if (!pComp)
+      {
+        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+        MZ_FCLOSE(pSrc_file);
+        return MZ_FALSE;
+      }
+
+      state.m_pZip = pZip;
+      state.m_cur_archive_file_ofs = cur_archive_file_ofs;
+      state.m_comp_size = 0;
+
+      if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
+      {
+        pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+        MZ_FCLOSE(pSrc_file);
+        return MZ_FALSE;
+      }
+
+      for ( ; ; )
+      {
+        size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
+        tdefl_status status;
+
+        if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
+          break;
+
+        uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
+        uncomp_remaining -= in_buf_size;
+
+        status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
+        if (status == TDEFL_STATUS_DONE)
+        {
+          result = MZ_TRUE;
+          break;
+        }
+        else if (status != TDEFL_STATUS_OKAY)
+          break;
+      }
+
+      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
+
+      if (!result)
+      {
+        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+        MZ_FCLOSE(pSrc_file);
+        return MZ_FALSE;
+      }
+
+      comp_size = state.m_comp_size;
+      cur_archive_file_ofs = state.m_cur_archive_file_ofs;
+
+      method = MZ_DEFLATED;
+    }
+
+    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+  }
+
+  MZ_FCLOSE(pSrc_file); pSrc_file = NULL;
+
+  // no zip64 support yet
+  if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
+    return MZ_FALSE;
+
+  if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
+    return MZ_FALSE;
+
+  if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
+    return MZ_FALSE;
+
+  if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
+    return MZ_FALSE;
+
+  pZip->m_total_files++;
+  pZip->m_archive_size = cur_archive_file_ofs;
+
+  return MZ_TRUE;
+}
+#endif // #ifndef MINIZ_NO_STDIO
+
+mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index)
+{
+  mz_uint n, bit_flags, num_alignment_padding_bytes;
+  mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
+  mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
+  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
+  mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
+  size_t orig_central_dir_size;
+  mz_zip_internal_state *pState;
+  void *pBuf; const mz_uint8 *pSrc_central_header;
+
+  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
+    return MZ_FALSE;
+  if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
+    return MZ_FALSE;
+  pState = pZip->m_pState;
+
+  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
+
+  // no zip64 support yet
+  if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
+    return MZ_FALSE;
+
+  cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
+  cur_dst_file_ofs = pZip->m_archive_size;
+
+  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
+    return MZ_FALSE;
+  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
+    return MZ_FALSE;
+  cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
+
+  if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
+    return MZ_FALSE;
+  cur_dst_file_ofs += num_alignment_padding_bytes;
+  local_dir_header_ofs = cur_dst_file_ofs;
+  if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
+
+  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
+    return MZ_FALSE;
+  cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
+
+  n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
+  comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
+
+  if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining)))))
+    return MZ_FALSE;
+
+  while (comp_bytes_remaining)
+  {
+    n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
+    if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
+    {
+      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+      return MZ_FALSE;
+    }
+    cur_src_file_ofs += n;
+
+    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
+    {
+      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+      return MZ_FALSE;
+    }
+    cur_dst_file_ofs += n;
+
+    comp_bytes_remaining -= n;
+  }
+
+  bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
+  if (bit_flags & 8)
+  {
+    // Copy data descriptor
+    if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
+    {
+      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+      return MZ_FALSE;
+    }
+
+    n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
+    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
+    {
+      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+      return MZ_FALSE;
+    }
+
+    cur_src_file_ofs += n;
+    cur_dst_file_ofs += n;
+  }
+  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
+
+  // no zip64 support yet
+  if (cur_dst_file_ofs > 0xFFFFFFFF)
+    return MZ_FALSE;
+
+  orig_central_dir_size = pState->m_central_dir.m_size;
+
+  memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
+  MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
+  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
+    return MZ_FALSE;
+
+  n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
+  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n))
+  {
+    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
+    return MZ_FALSE;
+  }
+
+  if (pState->m_central_dir.m_size > 0xFFFFFFFF)
+    return MZ_FALSE;
+  n = (mz_uint32)orig_central_dir_size;
+  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
+  {
+    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
+    return MZ_FALSE;
+  }
+
+  pZip->m_total_files++;
+  pZip->m_archive_size = cur_dst_file_ofs;
+
+  return MZ_TRUE;
+}
+
+mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
+{
+  mz_zip_internal_state *pState;
+  mz_uint64 central_dir_ofs, central_dir_size;
+  mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
+
+  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
+    return MZ_FALSE;
+
+  pState = pZip->m_pState;
+
+  // no zip64 support yet
+  if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
+    return MZ_FALSE;
+
+  central_dir_ofs = 0;
+  central_dir_size = 0;
+  if (pZip->m_total_files)
+  {
+    // Write central directory
+    central_dir_ofs = pZip->m_archive_size;
+    central_dir_size = pState->m_central_dir.m_size;
+    pZip->m_central_directory_file_ofs = central_dir_ofs;
+    if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
+      return MZ_FALSE;
+    pZip->m_archive_size += central_dir_size;
+  }
+
+  // Write end of central directory record
+  MZ_CLEAR_OBJ(hdr);
+  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
+  MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
+  MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
+  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
+  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
+
+  if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr))
+    return MZ_FALSE;
+#ifndef MINIZ_NO_STDIO
+  if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
+    return MZ_FALSE;
+#endif // #ifndef MINIZ_NO_STDIO
+
+  pZip->m_archive_size += sizeof(hdr);
+
+  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
+  return MZ_TRUE;
+}
+
+mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize)
+{
+  if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
+    return MZ_FALSE;
+  if (pZip->m_pWrite != mz_zip_heap_write_func)
+    return MZ_FALSE;
+  if (!mz_zip_writer_finalize_archive(pZip))
+    return MZ_FALSE;
+
+  *pBuf = pZip->m_pState->m_pMem;
+  *pSize = pZip->m_pState->m_mem_size;
+  pZip->m_pState->m_pMem = NULL;
+  pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
+  return MZ_TRUE;
+}
+
+mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
+{
+  mz_zip_internal_state *pState;
+  mz_bool status = MZ_TRUE;
+  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
+    return MZ_FALSE;
+
+  pState = pZip->m_pState;
+  pZip->m_pState = NULL;
+  mz_zip_array_clear(pZip, &pState->m_central_dir);
+  mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
+  mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
+
+#ifndef MINIZ_NO_STDIO
+  if (pState->m_pFile)
+  {
+    MZ_FCLOSE(pState->m_pFile);
+    pState->m_pFile = NULL;
+  }
+#endif // #ifndef MINIZ_NO_STDIO
+
+  if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
+  {
+    pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
+    pState->m_pMem = NULL;
+  }
+
+  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
+  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
+  return status;
+}
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
+{
+  mz_bool status, created_new_archive = MZ_FALSE;
+  mz_zip_archive zip_archive;
+  struct MZ_FILE_STAT_STRUCT file_stat;
+  MZ_CLEAR_OBJ(zip_archive);
+  if ((int)level_and_flags < 0)
+     level_and_flags = MZ_DEFAULT_LEVEL;
+  if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
+    return MZ_FALSE;
+  if (!mz_zip_writer_validate_archive_name(pArchive_name))
+    return MZ_FALSE;
+  if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
+  {
+    // Create a new archive.
+    if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
+      return MZ_FALSE;
+    created_new_archive = MZ_TRUE;
+  }
+  else
+  {
+    // Append to an existing archive.
+    if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
+      return MZ_FALSE;
+    if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename))
+    {
+      mz_zip_reader_end(&zip_archive);
+      return MZ_FALSE;
+    }
+  }
+  status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
+  // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.)
+  if (!mz_zip_writer_finalize_archive(&zip_archive))
+    status = MZ_FALSE;
+  if (!mz_zip_writer_end(&zip_archive))
+    status = MZ_FALSE;
+  if ((!status) && (created_new_archive))
+  {
+    // It's a new archive and something went wrong, so just delete it.
+    int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
+    (void)ignoredStatus;
+  }
+  return status;
+}
+
+void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
+{
+  int file_index;
+  mz_zip_archive zip_archive;
+  void *p = NULL;
+
+  if (pSize)
+    *pSize = 0;
+
+  if ((!pZip_filename) || (!pArchive_name))
+    return NULL;
+
+  MZ_CLEAR_OBJ(zip_archive);
+  if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
+    return NULL;
+
+  if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0)
+    p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
+
+  mz_zip_reader_end(&zip_archive);
+  return p;
+}
+
+#endif // #ifndef MINIZ_NO_STDIO
+
+#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
+
+#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MINIZ_HEADER_FILE_ONLY
+
+/*
+  This is free and unencumbered software released into the public domain.
+
+  Anyone is free to copy, modify, publish, use, compile, sell, or
+  distribute this software, either in source code form or as a compiled
+  binary, for any purpose, commercial or non-commercial, and by any
+  means.
+
+  In jurisdictions that recognize copyright laws, the author or authors
+  of this software dedicate any and all copyright interest in the
+  software to the public domain. We make this dedication for the benefit
+  of the public at large and to the detriment of our heirs and
+  successors. We intend this dedication to be an overt act of
+  relinquishment in perpetuity of all present and future rights to this
+  software under copyright law.
+
+  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 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.
+
+  For more information, please refer to <http://unlicense.org/>
+*/

+ 770 - 0
modules/miniz/native/miniz.h

@@ -0,0 +1,770 @@
+
+#ifndef MINIZ_HEADER_INCLUDED
+#define MINIZ_HEADER_INCLUDED
+
+#include <stdlib.h>
+
+// Defines to completely disable specific portions of miniz.c:
+// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl.
+
+// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O.
+//#define MINIZ_NO_STDIO
+
+// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or
+// get/set file times, and the C run-time funcs that get/set times won't be called.
+// The current downside is the times written to your archives will be from 1979.
+//#define MINIZ_NO_TIME
+
+// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
+//#define MINIZ_NO_ARCHIVE_APIS
+
+// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's.
+//#define MINIZ_NO_ARCHIVE_WRITING_APIS
+
+// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's.
+//#define MINIZ_NO_ZLIB_APIS
+
+// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib.
+//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+
+// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
+// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc
+// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user
+// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
+//#define MINIZ_NO_MALLOC
+
+#if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
+  // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux
+  #define MINIZ_NO_TIME
+#endif
+
+#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
+  #include <time.h>
+#endif
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__)
+// MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
+#define MINIZ_X86_OR_X64_CPU 1
+#endif
+
+#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
+// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
+#define MINIZ_LITTLE_ENDIAN 1
+#endif
+
+#if MINIZ_X86_OR_X64_CPU
+// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses.
+#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
+#endif
+
+#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)
+// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions).
+#define MINIZ_HAS_64BIT_REGISTERS 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ------------------- zlib-style API Definitions.
+
+// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
+typedef unsigned long mz_ulong;
+
+// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap.
+void mz_free(void *p);
+
+#define MZ_ADLER32_INIT (1)
+// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL.
+mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
+
+#define MZ_CRC32_INIT (0)
+// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL.
+mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
+
+// Compression strategies.
+enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 };
+
+// Method
+#define MZ_DEFLATED 8
+
+#ifndef MINIZ_NO_ZLIB_APIS
+
+// Heap allocation callbacks.
+// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long.
+typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
+typedef void (*mz_free_func)(void *opaque, void *address);
+typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);
+
+#define MZ_VERSION          "9.1.15"
+#define MZ_VERNUM           0x91F0
+#define MZ_VER_MAJOR        9
+#define MZ_VER_MINOR        1
+#define MZ_VER_REVISION     15
+#define MZ_VER_SUBREVISION  0
+
+// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs).
+enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 };
+
+// Return status codes. MZ_PARAM_ERROR is non-standard.
+enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };
+
+// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
+enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 };
+
+// Window bits
+#define MZ_DEFAULT_WINDOW_BITS 15
+
+struct mz_internal_state;
+
+// Compression/decompression stream struct.
+typedef struct mz_stream_s
+{
+  const unsigned char *next_in;     // pointer to next byte to read
+  unsigned int avail_in;            // number of bytes available at next_in
+  mz_ulong total_in;                // total number of bytes consumed so far
+
+  unsigned char *next_out;          // pointer to next byte to write
+  unsigned int avail_out;           // number of bytes that can be written to next_out
+  mz_ulong total_out;               // total number of bytes produced so far
+
+  char *msg;                        // error msg (unused)
+  struct mz_internal_state *state;  // internal state, allocated by zalloc/zfree
+
+  mz_alloc_func zalloc;             // optional heap allocation function (defaults to malloc)
+  mz_free_func zfree;               // optional heap free function (defaults to free)
+  void *opaque;                     // heap alloc function user pointer
+
+  int data_type;                    // data_type (unused)
+  mz_ulong adler;                   // adler32 of the source or uncompressed data
+  mz_ulong reserved;                // not used
+} mz_stream;
+
+typedef mz_stream *mz_streamp;
+
+// Returns the version string of miniz.c.
+const char *mz_version(void);
+
+// mz_deflateInit() initializes a compressor with default options:
+// Parameters:
+//  pStream must point to an initialized mz_stream struct.
+//  level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
+//  level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio.
+//  (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
+// Return values:
+//  MZ_OK on success.
+//  MZ_STREAM_ERROR if the stream is bogus.
+//  MZ_PARAM_ERROR if the input parameters are bogus.
+//  MZ_MEM_ERROR on out of memory.
+int mz_deflateInit(mz_streamp pStream, int level);
+
+// mz_deflateInit2() is like mz_deflate(), except with more control:
+// Additional parameters:
+//   method must be MZ_DEFLATED
+//   window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer)
+//   mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
+int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);
+
+// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
+int mz_deflateReset(mz_streamp pStream);
+
+// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible.
+// Parameters:
+//   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
+//   flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
+// Return values:
+//   MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full).
+//   MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore.
+//   MZ_STREAM_ERROR if the stream is bogus.
+//   MZ_PARAM_ERROR if one of the parameters is invalid.
+//   MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.)
+int mz_deflate(mz_streamp pStream, int flush);
+
+// mz_deflateEnd() deinitializes a compressor:
+// Return values:
+//  MZ_OK on success.
+//  MZ_STREAM_ERROR if the stream is bogus.
+int mz_deflateEnd(mz_streamp pStream);
+
+// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH.
+mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
+
+// Single-call compression functions mz_compress() and mz_compress2():
+// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure.
+int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
+int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
+
+// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress().
+mz_ulong mz_compressBound(mz_ulong source_len);
+
+// Initializes a decompressor.
+int mz_inflateInit(mz_streamp pStream);
+
+// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer:
+// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
+int mz_inflateInit2(mz_streamp pStream, int window_bits);
+
+// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible.
+// Parameters:
+//   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
+//   flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
+//   On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster).
+//   MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data.
+// Return values:
+//   MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full.
+//   MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified.
+//   MZ_STREAM_ERROR if the stream is bogus.
+//   MZ_DATA_ERROR if the deflate stream is invalid.
+//   MZ_PARAM_ERROR if one of the parameters is invalid.
+//   MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again
+//   with more input data, or with more room in the output buffer (except when using single call decompression, described above).
+int mz_inflate(mz_streamp pStream, int flush);
+
+// Deinitializes a decompressor.
+int mz_inflateEnd(mz_streamp pStream);
+
+// Single-call decompression.
+// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure.
+int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
+
+// Returns a string description of the specified error code, or NULL if the error code is invalid.
+const char *mz_error(int err);
+
+// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports.
+// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project.
+#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+  typedef unsigned char Byte;
+  typedef unsigned int uInt;
+  typedef mz_ulong uLong;
+  typedef Byte Bytef;
+  typedef uInt uIntf;
+  typedef char charf;
+  typedef int intf;
+  typedef void *voidpf;
+  typedef uLong uLongf;
+  typedef void *voidp;
+  typedef void *const voidpc;
+  #define Z_NULL                0
+  #define Z_NO_FLUSH            MZ_NO_FLUSH
+  #define Z_PARTIAL_FLUSH       MZ_PARTIAL_FLUSH
+  #define Z_SYNC_FLUSH          MZ_SYNC_FLUSH
+  #define Z_FULL_FLUSH          MZ_FULL_FLUSH
+  #define Z_FINISH              MZ_FINISH
+  #define Z_BLOCK               MZ_BLOCK
+  #define Z_OK                  MZ_OK
+  #define Z_STREAM_END          MZ_STREAM_END
+  #define Z_NEED_DICT           MZ_NEED_DICT
+  #define Z_ERRNO               MZ_ERRNO
+  #define Z_STREAM_ERROR        MZ_STREAM_ERROR
+  #define Z_DATA_ERROR          MZ_DATA_ERROR
+  #define Z_MEM_ERROR           MZ_MEM_ERROR
+  #define Z_BUF_ERROR           MZ_BUF_ERROR
+  #define Z_VERSION_ERROR       MZ_VERSION_ERROR
+  #define Z_PARAM_ERROR         MZ_PARAM_ERROR
+  #define Z_NO_COMPRESSION      MZ_NO_COMPRESSION
+  #define Z_BEST_SPEED          MZ_BEST_SPEED
+  #define Z_BEST_COMPRESSION    MZ_BEST_COMPRESSION
+  #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
+  #define Z_DEFAULT_STRATEGY    MZ_DEFAULT_STRATEGY
+  #define Z_FILTERED            MZ_FILTERED
+  #define Z_HUFFMAN_ONLY        MZ_HUFFMAN_ONLY
+  #define Z_RLE                 MZ_RLE
+  #define Z_FIXED               MZ_FIXED
+  #define Z_DEFLATED            MZ_DEFLATED
+  #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
+  #define alloc_func            mz_alloc_func
+  #define free_func             mz_free_func
+  #define internal_state        mz_internal_state
+  #define z_stream              mz_stream
+  #define deflateInit           mz_deflateInit
+  #define deflateInit2          mz_deflateInit2
+  #define deflateReset          mz_deflateReset
+  #define deflate               mz_deflate
+  #define deflateEnd            mz_deflateEnd
+  #define deflateBound          mz_deflateBound
+  #define compress              mz_compress
+  #define compress2             mz_compress2
+  #define compressBound         mz_compressBound
+  #define inflateInit           mz_inflateInit
+  #define inflateInit2          mz_inflateInit2
+  #define inflate               mz_inflate
+  #define inflateEnd            mz_inflateEnd
+  #define uncompress            mz_uncompress
+  #define crc32                 mz_crc32
+  #define adler32               mz_adler32
+  #define MAX_WBITS             15
+  #define MAX_MEM_LEVEL         9
+  #define zError                mz_error
+  #define ZLIB_VERSION          MZ_VERSION
+  #define ZLIB_VERNUM           MZ_VERNUM
+  #define ZLIB_VER_MAJOR        MZ_VER_MAJOR
+  #define ZLIB_VER_MINOR        MZ_VER_MINOR
+  #define ZLIB_VER_REVISION     MZ_VER_REVISION
+  #define ZLIB_VER_SUBREVISION  MZ_VER_SUBREVISION
+  #define zlibVersion           mz_version
+  #define zlib_version          mz_version()
+#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+
+#endif // MINIZ_NO_ZLIB_APIS
+
+// ------------------- Types and macros
+
+typedef unsigned char mz_uint8;
+typedef signed short mz_int16;
+typedef unsigned short mz_uint16;
+typedef unsigned int mz_uint32;
+typedef unsigned int mz_uint;
+typedef long long mz_int64;
+typedef unsigned long long mz_uint64;
+typedef int mz_bool;
+
+#define MZ_FALSE (0)
+#define MZ_TRUE (1)
+
+// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message.
+#ifdef _MSC_VER
+   #define MZ_MACRO_END while (0, 0)
+#else
+   #define MZ_MACRO_END while (0)
+#endif
+
+// ------------------- ZIP archive reading/writing
+
+#ifndef MINIZ_NO_ARCHIVE_APIS
+
+enum
+{
+  MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024,
+  MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
+  MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
+};
+
+typedef struct
+{
+  mz_uint32 m_file_index;
+  mz_uint32 m_central_dir_ofs;
+  mz_uint16 m_version_made_by;
+  mz_uint16 m_version_needed;
+  mz_uint16 m_bit_flag;
+  mz_uint16 m_method;
+#ifndef MINIZ_NO_TIME
+  time_t m_time;
+#endif
+  mz_uint32 m_crc32;
+  mz_uint64 m_comp_size;
+  mz_uint64 m_uncomp_size;
+  mz_uint16 m_internal_attr;
+  mz_uint32 m_external_attr;
+  mz_uint64 m_local_header_ofs;
+  mz_uint32 m_comment_size;
+  char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
+  char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
+} mz_zip_archive_file_stat;
+
+typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);
+typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n);
+
+struct mz_zip_internal_state_tag;
+typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
+
+typedef enum
+{
+  MZ_ZIP_MODE_INVALID = 0,
+  MZ_ZIP_MODE_READING = 1,
+  MZ_ZIP_MODE_WRITING = 2,
+  MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
+} mz_zip_mode;
+
+typedef struct mz_zip_archive_tag
+{
+  mz_uint64 m_archive_size;
+  mz_uint64 m_central_directory_file_ofs;
+  mz_uint m_total_files;
+  mz_zip_mode m_zip_mode;
+
+  mz_uint m_file_offset_alignment;
+
+  mz_alloc_func m_pAlloc;
+  mz_free_func m_pFree;
+  mz_realloc_func m_pRealloc;
+  void *m_pAlloc_opaque;
+
+  mz_file_read_func m_pRead;
+  mz_file_write_func m_pWrite;
+  void *m_pIO_opaque;
+
+  mz_zip_internal_state *m_pState;
+
+} mz_zip_archive;
+
+typedef enum
+{
+  MZ_ZIP_FLAG_CASE_SENSITIVE                = 0x0100,
+  MZ_ZIP_FLAG_IGNORE_PATH                   = 0x0200,
+  MZ_ZIP_FLAG_COMPRESSED_DATA               = 0x0400,
+  MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
+} mz_zip_flags;
+
+// ZIP archive reading
+
+// Inits a ZIP archive reader.
+// These functions read and validate the archive's central directory.
+mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags);
+mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags);
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);
+#endif
+
+// Returns the total number of files in the archive.
+mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
+
+// Returns detailed information about an archive file entry.
+mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
+
+// Determines if an archive file entry is a directory entry.
+mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
+mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);
+
+// Retrieves the filename of an archive file entry.
+// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename.
+mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);
+
+// Attempts to locates a file in the archive's central directory.
+// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
+// Returns -1 if the file cannot be found.
+int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
+
+// Extracts a archive file to a memory buffer using no memory allocation.
+mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
+mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
+
+// Extracts a archive file to a memory buffer.
+mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
+mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);
+
+// Extracts a archive file to a dynamically allocated heap buffer.
+void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
+void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);
+
+// Extracts a archive file using a callback function to output the file's data.
+mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
+mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
+
+#ifndef MINIZ_NO_STDIO
+// Extracts a archive file to a disk file and sets its last accessed and modified times.
+// This function only extracts files, not archive directory records.
+mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);
+mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);
+#endif
+
+// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used.
+mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
+
+// ZIP archive writing
+
+#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
+
+// Inits a ZIP archive writer.
+mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
+mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);
+
+#ifndef MINIZ_NO_STDIO
+mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);
+#endif
+
+// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive.
+// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called.
+// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it).
+// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL.
+// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before
+// the archive is finalized the file's central directory will be hosed.
+mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);
+
+// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive.
+// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer.
+// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
+mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
+mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
+
+#ifndef MINIZ_NO_STDIO
+// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive.
+// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
+mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
+#endif
+
+// Adds a file to an archive by fully cloning the data from another archive.
+// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields.
+mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index);
+
+// Finalizes the archive by writing the central directory records followed by the end of central directory record.
+// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end().
+// An archive must be manually finalized by calling this function for it to be valid.
+mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
+mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize);
+
+// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used.
+// Note for the archive to be valid, it must have been finalized before ending.
+mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
+
+// Misc. high-level helper functions:
+
+// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive.
+// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
+mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
+
+// Reads a single file from an archive into a heap block.
+// Returns NULL on failure.
+void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags);
+
+#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
+
+#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
+
+// ------------------- Low-level Decompression API Definitions
+
+// Decompression flags used by tinfl_decompress().
+// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
+// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
+// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
+// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
+enum
+{
+  TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
+  TINFL_FLAG_HAS_MORE_INPUT = 2,
+  TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
+  TINFL_FLAG_COMPUTE_ADLER32 = 8
+};
+
+// High level decompression functions:
+// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
+// On entry:
+//  pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
+// On return:
+//  Function returns a pointer to the decompressed data, or NULL on failure.
+//  *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
+//  The caller must call mz_free() on the returned block when it's no longer needed.
+void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
+
+// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
+// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
+#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
+size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
+
+// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
+// Returns 1 on success or 0 on failure.
+typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
+int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
+
+// Max size of LZ dictionary.
+#define TINFL_LZ_DICT_SIZE 32768
+
+// Return status.
+typedef enum
+{
+  TINFL_STATUS_BAD_PARAM = -3,
+  TINFL_STATUS_ADLER32_MISMATCH = -2,
+  TINFL_STATUS_FAILED = -1,
+  TINFL_STATUS_DONE = 0,
+  TINFL_STATUS_NEEDS_MORE_INPUT = 1,
+  TINFL_STATUS_HAS_MORE_OUTPUT = 2
+} tinfl_status;
+
+// Initializes the decompressor to its initial state.
+#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
+#define tinfl_get_adler32(r) (r)->m_check_adler32
+
+// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
+// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
+tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
+
+// Internal/private bits follow.
+enum
+{
+  TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
+  TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
+};
+
+typedef struct
+{
+  mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
+  mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
+} tinfl_huff_table;
+
+#if MINIZ_HAS_64BIT_REGISTERS
+  #define TINFL_USE_64BIT_BITBUF 1
+#endif
+
+#if TINFL_USE_64BIT_BITBUF
+  typedef mz_uint64 tinfl_bit_buf_t;
+  #define TINFL_BITBUF_SIZE (64)
+#else
+  typedef mz_uint32 tinfl_bit_buf_t;
+  #define TINFL_BITBUF_SIZE (32)
+#endif
+
+struct tinfl_decompressor_tag
+{
+  mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
+  tinfl_bit_buf_t m_bit_buf;
+  size_t m_dist_from_out_buf_start;
+  tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
+  mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
+};
+
+// ------------------- Low-level Compression API Definitions
+
+// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently).
+#define TDEFL_LESS_MEMORY 0
+
+// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search):
+// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression).
+enum
+{
+  TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF
+};
+
+// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data.
+// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers).
+// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing.
+// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory).
+// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
+// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
+// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
+// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
+// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK).
+enum
+{
+  TDEFL_WRITE_ZLIB_HEADER             = 0x01000,
+  TDEFL_COMPUTE_ADLER32               = 0x02000,
+  TDEFL_GREEDY_PARSING_FLAG           = 0x04000,
+  TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
+  TDEFL_RLE_MATCHES                   = 0x10000,
+  TDEFL_FILTER_MATCHES                = 0x20000,
+  TDEFL_FORCE_ALL_STATIC_BLOCKS       = 0x40000,
+  TDEFL_FORCE_ALL_RAW_BLOCKS          = 0x80000
+};
+
+// High level compression functions:
+// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc().
+// On entry:
+//  pSrc_buf, src_buf_len: Pointer and size of source block to compress.
+//  flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression.
+// On return:
+//  Function returns a pointer to the compressed data, or NULL on failure.
+//  *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data.
+//  The caller must free() the returned block when it's no longer needed.
+void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
+
+// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory.
+// Returns 0 on failure.
+size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
+
+// Compresses an image to a compressed PNG file in memory.
+// On entry:
+//  pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. 
+//  The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory.
+//  level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
+//  If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps).
+// On return:
+//  Function returns a pointer to the compressed data, or NULL on failure.
+//  *pLen_out will be set to the size of the PNG image file.
+//  The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed.
+void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);
+void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);
+
+// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
+typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
+
+// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally.
+mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 };
+
+// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes).
+#if TDEFL_LESS_MEMORY
+enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
+#else
+enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
+#endif
+
+// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions.
+typedef enum
+{
+  TDEFL_STATUS_BAD_PARAM = -2,
+  TDEFL_STATUS_PUT_BUF_FAILED = -1,
+  TDEFL_STATUS_OKAY = 0,
+  TDEFL_STATUS_DONE = 1,
+} tdefl_status;
+
+// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
+typedef enum
+{
+  TDEFL_NO_FLUSH = 0,
+  TDEFL_SYNC_FLUSH = 2,
+  TDEFL_FULL_FLUSH = 3,
+  TDEFL_FINISH = 4
+} tdefl_flush;
+
+// tdefl's compression state structure.
+typedef struct
+{
+  tdefl_put_buf_func_ptr m_pPut_buf_func;
+  void *m_pPut_buf_user;
+  mz_uint m_flags, m_max_probes[2];
+  int m_greedy_parsing;
+  mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
+  mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
+  mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
+  mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
+  tdefl_status m_prev_return_status;
+  const void *m_pIn_buf;
+  void *m_pOut_buf;
+  size_t *m_pIn_buf_size, *m_pOut_buf_size;
+  tdefl_flush m_flush;
+  const mz_uint8 *m_pSrc;
+  size_t m_src_buf_left, m_out_buf_ofs;
+  mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
+  mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+  mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+  mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
+  mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
+  mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
+  mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
+  mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
+} tdefl_compressor;
+
+// Initializes the compressor.
+// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory.
+// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression.
+// If pBut_buf_func is NULL the user should always call the tdefl_compress() API.
+// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
+tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
+
+// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible.
+tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
+
+// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr.
+// tdefl_compress_buffer() always consumes the entire input buffer.
+tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
+
+tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
+mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
+
+// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros.
+#ifndef MINIZ_NO_ZLIB_APIS
+// Create tdefl_compress() flags given zlib-style compression parameters.
+// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files)
+// window_bits may be -15 (raw deflate) or 15 (zlib)
+// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED
+mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
+#endif // #ifndef MINIZ_NO_ZLIB_APIS
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MINIZ_HEADER_INCLUDED
+

+ 18 - 0
modules/monkey/debug.monkey2

@@ -0,0 +1,18 @@
+
+Namespace monkey
+
+Extern
+
+Class RuntimeError="bbRuntimeError"
+
+	Method New( msg:String )
+
+End
+
+Function Assert( condition:Bool )="bbAssert"
+
+Function Assert( condition:Bool,message:String )="bbAssert"
+
+Function DebugAssert( condition:Bool )="bbDebugAssert"
+
+Function DebugAssert( condition:Bool,message:String )="bbDebugAssert"

+ 6 - 0
modules/monkey/gc.monkey2

@@ -0,0 +1,6 @@
+
+Namespace monkey.gc
+
+Extern
+
+Function Collect:Void()="bbGC::collect"

+ 109 - 0
modules/monkey/math.monkey2

@@ -0,0 +1,109 @@
+
+Namespace monkey
+
+Const Pi:Float=3.14159265359
+
+Extern
+
+'Function Sin:Int( x:Int )="std::sin"
+Function Sin:Float( x:Float )="std::sin"
+Function Sin:Double( x:Double )="std::sin"
+
+'Function Cos:Int( x:Int )="std::cos"
+Function Cos:Float( x:Float )="std::cos"
+Function Cos:Double( x:Double )="std::cos"
+
+'Function Sqrt:Int( x:Int )="std::sqrt"
+Function Sqrt:Float( x:Int )="std::sqrt"
+Function Sqrt:Float( x:Float )="std::sqrt"
+Function Sqrt:Double( x:Double )="std::sqrt"
+
+Function Floor:Float( x:Float )="std::floor"
+Function Floor:Double( x:Double )="std::floor"
+
+Function Ceil:Float( x:Float )="std::ceil"
+Function Ceil:Double( x:Double )="std::ceil"
+
+Function Round:Float( x:Float )="std::round"
+Function Round:Double( x:Double )="std::round"
+
+Public
+
+#rem monkeydoc
+
+Returns the smaller of two values.
+
+@return the smaller of `x` and `y`.
+
+#end
+Function Min<T>:T( x:T,y:T )
+	If x<=y Return x
+	Return y
+End
+
+#rem monkeydoc
+
+Returns the larger of two values.
+
+@return the larger of `x` and `y`.
+
+#end
+Function Max<T>:T( x:T,y:T )
+	If x>=y Return x
+	Return y
+End
+
+#rem monkeydoc
+
+Clamps a value to range.
+
+If `x` is less than `min`, `min` is returned.
+
+If `x` is greater than `max`, `max` is returned.
+
+Otherwise, `x` is returned.
+
+@return `x` clamped to the range [`min`,`max`].
+
+#end
+Function Clamp<T>:T( value:T,min:T,max:T )
+	If value<=min Return min
+	If value>=max Return max
+	Return value
+End
+
+#rem monkeydoc
+
+Returns the absolute value of a number.
+
+If `x` is less than 0, then `-x` is returned.
+
+If `x` is greater than or equal to 0, then `x` is returned.
+
+@return the absolute value of `x`.
+
+#end
+Function Abs<T>:T( x:T )
+	If x>=0 Return x
+	Return -x
+End
+
+#rem monkeydoc
+
+Returns the sign of a number.
+
+If `x` is less than 0, the value -1 is returned.
+
+If `x` is equal to 0, the value 1 is returned.
+
+Otherwise, if `x` is equal to 0, 0 is returned.
+
+@return the sign of `x`.
+
+#end
+Function Sgn<T>:Int( x:T )
+	If x<0 Return -1
+	If x>0 Return 1
+	Return 0
+End
+

+ 209 - 0
modules/monkey/monkey.json

@@ -0,0 +1,209 @@
+{
+  "module":{
+    "name":"monkey"
+    ,"namespaces":[
+      {
+        "ident":"monkey"
+        ,"aliases":[
+          {
+            "ident":"CString"
+            ,"flags":1
+            ,"type":"monkey.CChar Ptr"
+          }
+          ,{
+            "ident":"Utf8String"
+            ,"flags":1
+            ,"type":"monkey.Utf8Char Ptr"
+          }
+          ,{
+            "ident":"WString"
+            ,"flags":1
+            ,"type":"monkey.WChar Ptr"
+          }
+        ]
+        ,"classes":[
+          {
+            "ident":"Object"
+            ,"flags":129
+            ,"methods":[
+              {
+                "ident":"typeName"
+                ,"overloads":[
+                  {
+                    "return":{
+                      "type":"monkey.CChar Ptr"
+                    }
+                  }
+                ]
+              }
+            ]
+          }
+        ]
+        ,"constants":[
+          {
+            "ident":"Pi"
+            ,"flags":1
+            ,"type":"monkey.Float"
+          }
+        ]
+        ,"functions":[
+          {
+            "ident":"Abs"
+            ,"docs":"<p>Returns the absolute value of a number.</p>\n\n<p>If <code>x</code> is less than 0, then <code>-x</code> is returned.</p>\n\n<p>If <code>x</code> is greater than or equal to 0, then <code>x</code> is returned.</p>\n"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"T"
+                  ,"docs":"<p>the absolute value of <code>x</code>.</p>\n"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"Ceil"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"monkey.Float"
+                }
+              }
+              ,{
+                "return":{
+                  "type":"monkey.Double"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"Clamp"
+            ,"docs":"<p>Clamps a value to range.</p>\n\n<p>If <code>x</code> is less than <code>min</code>, <code>min</code> is returned.</p>\n\n<p>If <code>x</code> is greater than <code>max</code>, <code>max</code> is returned.</p>\n\n<p>Otherwise, <code>x</code> is returned.</p>\n"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"T"
+                  ,"docs":"<p><code>x</code> clamped to the range [<code>min</code>,<code>max</code>].</p>\n"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"Cos"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"monkey.Float"
+                }
+              }
+              ,{
+                "return":{
+                  "type":"monkey.Double"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"Floor"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"monkey.Float"
+                }
+              }
+              ,{
+                "return":{
+                  "type":"monkey.Double"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"Max"
+            ,"docs":"<p>Returns the larger of two values.</p>\n"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"T"
+                  ,"docs":"<p>the larger of <code>x</code> and <code>y</code>.</p>\n"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"Min"
+            ,"docs":"<p>Returns the smaller of two values.</p>\n"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"T"
+                  ,"docs":"<p>the smaller of <code>x</code> and <code>y</code>.</p>\n"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"Round"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"monkey.Float"
+                }
+              }
+              ,{
+                "return":{
+                  "type":"monkey.Double"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"Sgn"
+            ,"docs":"<p>Returns the sign of a number.</p>\n\n<p>If <code>x</code> is less than 0, the value -1 is returned.</p>\n\n<p>If <code>x</code> is equal to 0, the value 1 is returned.</p>\n\n<p>Otherwise, if <code>x</code> is equal to 0, 0 is returned.</p>\n"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"monkey.Int"
+                  ,"docs":"<p>the sign of <code>x</code>.</p>\n"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"Sin"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"monkey.Float"
+                }
+              }
+              ,{
+                "return":{
+                  "type":"monkey.Double"
+                }
+              }
+            ]
+          }
+          ,{
+            "ident":"Sqrt"
+            ,"overloads":[
+              {
+                "return":{
+                  "type":"monkey.Float"
+                }
+              }
+              ,{
+                "return":{
+                  "type":"monkey.Float"
+                }
+              }
+              ,{
+                "return":{
+                  "type":"monkey.Double"
+                }
+              }
+            ]
+          }
+        ]
+      }
+    ]
+  }
+}

+ 17 - 0
modules/monkey/monkey.monkey2

@@ -0,0 +1,17 @@
+
+Namespace monkey
+
+#Import "types.monkey2"
+#Import "math.monkey2"
+#Import "debug.monkey2"
+
+#Import "native/bbtypes.cpp"
+#Import "native/bbmemory.cpp"
+#Import "native/bbstring.cpp"
+#Import "native/bbfunction.cpp"
+#Import "native/bbarray.cpp"
+#Import "native/bbmonkey.cpp"
+#Import "native/bbgc.cpp"
+#Import "native/bbobject.cpp"
+#Import "native/bbinit.cpp"
+#Import "native/bbdebug.cpp"

+ 2 - 0
modules/monkey/native/bbarray.cpp

@@ -0,0 +1,2 @@
+
+#include "bbarray.h"

+ 360 - 0
modules/monkey/native/bbarray.h

@@ -0,0 +1,360 @@
+
+#ifndef BB_ARRAY_H
+#define BB_ARRAY_H
+
+#include "bbtypes.h"
+#include "bbgc.h"
+
+template<class T,int D=1> class bbArray : public bbGCNode{
+
+	int _sizes[D];
+	T _data[0];
+		
+	bbArray(){
+		memset( _sizes,0,sizeof(_sizes) );
+	}
+	
+	bbArray( int sizes[] ){
+		bbGC::beginCtor( this );
+		
+		memcpy( _sizes,sizes,D*sizeof(int) );
+		
+		for( int i=0;i<_sizes[D-1];++i ) new( &_data[i] ) T();
+	}
+	
+	~bbArray(){
+		for( int i=0;i<_sizes[D-1];++i ) _data[i].~T();
+	}
+	
+	virtual void gcMark(){
+		for( int i=0;i<_sizes[D-1];++i ) bbGCMark( _data[i] );	
+	}
+	
+	public:
+	
+	const char *typeName(){
+		return "bbArray";
+	}
+	
+	template<class...Args> static bbArray *create( Args...args ){
+	
+		int sizes[]{ args... };
+		for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
+		
+		if( !sizes[D-1] ) return nullptr;
+		
+		bbGCNode *p=bbGC::alloc( sizeof( bbArray )+sizes[D-1]*sizeof(T) );
+		
+		bbArray *r=new( p ) bbArray( sizes );
+		
+		bbGC::endCtor( r );
+		
+		return r;
+	}
+	
+	template<class C,class...Args> static bbArray *create( std::initializer_list<C> init,Args...args ){
+	
+		int sizes[]{ args... };
+		for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
+		
+		if( !sizes[D-1] ) return nullptr;
+		
+		bbGCNode *p=bbGC::alloc( sizeof( bbArray )+sizes[D-1]*sizeof(T) );
+		
+		bbArray *r=new( p ) bbArray( sizes );
+		
+		int i=0;
+		for( auto it=init.begin();it!=init.end();++it ) r->_data[i++]=*it;
+		
+		bbGC::endCtor( r );
+		
+		return r;
+	}
+	
+	T *data(){
+		return _data;
+	}
+	
+	const T *data()const{
+		return _data;
+	}
+	
+	int length()const{
+		return this ? _sizes[D-1] : 0;
+	}
+	
+	int size( int q )const{
+		return this ? (q ? _sizes[q]/_sizes[q-1] : _sizes[0]) : 0;
+	}
+	
+	bbArray<T,1> *slice( int from )const{
+		return slice( from,length() );
+	}
+	
+	bbArray<T,1> *slice( int from,int term )const{
+		int length=this->length();
+		if( from<0 ){
+			from+=length;
+			if( from<0 ) from=0;
+		}else if( from>length ){
+			from=length;
+		}
+		if( term<0 ){
+			term+=length;
+			if( term<from ) term=from;
+		}else if( term<from ){
+			term=from;
+		}else if( term>length ){
+			term=length;
+		}
+		int newlen=term-from;
+		bbArray<T,1> *r=create( newlen );
+		for( int i=0;i<newlen;++i ) r->data()[i]=data()[from+i];
+		return r;
+	}
+	
+	void copyTo( bbArray<T,1> *dst,int offset,int dstOffset,int count )const{
+		int length=this->length();
+		if( offset<0 ){
+			offset=0;
+		}else if( offset>length ){
+			offset=length;
+		}
+		int dstLength=dst->length();
+		if( dstOffset<0 ){
+			dstOffset=0;
+		}else if( dstOffset>dstLength ){
+			dstOffset=dstLength;
+		}
+
+		if( offset+count>length ) count=length-offset;
+		if( dstOffset+count>dstLength) count=dstLength-dstOffset;
+		
+		if( dst==this && dstOffset>offset ){
+			for( int i=count-1;i>=0;--i ) dst->data()[dstOffset+i]=data()[offset+i];
+		}else{
+			for( int i=0;i<count;++i ) dst->data()[dstOffset+i]=data()[offset+i];
+		}
+	}
+	
+	//fast 1D version	
+	T &at( int index )const{
+		if( index<0 || index>=length() ) puts( "Out of range" );
+		return data()[index];
+	}
+	
+	template<class...Args> T &at( Args...args ){
+	
+		//debug only...
+		if( !this ) puts( "Out of range" );
+		
+		int indices[]{args...};
+		int index=indices[0];
+		for( int i=1;i<D;++i ){
+			if( index>=_sizes[i-1] ) puts( "Out of range!" );
+			index+=indices[i]*_sizes[i-1];
+		}
+		if( index>=length() ) puts( "Out of range" );
+		return data()[index];
+	}
+	
+	T &get( int index ){
+		if( index<0 || index>=length() ) puts( "Out of range" );
+		return data()[index];
+	}
+	
+	operator bool()const{
+		return length();
+	}
+};
+
+// ***** OLD *****
+
+/*
+template<class T,int D=1> class bbArray{
+
+	struct Rep : public bbGCNode{
+
+		int _sizes[D];
+		T _data[0];
+		
+		Rep(){
+			memset( _sizes,0,sizeof(_sizes) );
+		}
+		
+		Rep( int sizes[] ){
+			bbGC::beginCtor( this );
+			
+			memcpy( _sizes,sizes,D*sizeof(int) );
+			
+			for( int i=0;i<_sizes[D-1];++i ) new( &_data[i] ) T();
+		}
+		
+		~Rep(){
+			for( int i=0;i<_sizes[D-1];++i ) _data[i].~T();
+		}
+		
+		virtual void gcMark(){
+			for( int i=0;i<_sizes[D-1];++i ) bbGCMark( _data[i] );	
+		}
+		
+		const char *typeName(){
+			return "bbArray";
+		}
+		
+	};
+	
+	Rep *_rep=nullptr;
+	
+	friend void bbGCMark( bbArray &t ){
+
+		bbGC::enqueue( t._rep );
+	}
+	
+	void enqueue(){
+	
+#if BBGC_INCREMENTAL
+		bbGC::enqueue( _rep );
+#endif
+	}
+
+	public:
+	
+	bbArray(){
+	}
+	
+	bbArray( const bbArray &p ):_rep( p._rep ){
+
+		enqueue();
+	}
+	
+	template<class...Args> bbArray( Args...args ){
+	
+		int sizes[]{ args... };
+		for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
+		
+		if( !sizes[D-1] ) return;
+		
+		bbGCNode *p=bbGC::alloc( sizeof( Rep )+sizes[D-1]*sizeof(T) );
+		
+		_rep=new( p ) Rep( sizes );
+		
+		bbGC::endCtor( _rep );
+	}
+	
+	template<class C,class...Args> bbArray( const C *init,Args...args ){
+	
+		int sizes[]{ args... };
+		for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
+		
+		if( !sizes[D-1] ) return;
+		
+		bbGCNode *p=bbGC::alloc( sizeof( Rep )+sizes[D-1]*sizeof(T) );
+		
+		_rep=new( p ) Rep( sizes );
+		
+		for( int i=0;i<sizes[D-1];++i ) _rep->_data[i]=*init++;
+		
+		bbGC::endCtor( _rep );
+	}
+	
+	template<class C,class...Args> bbArray( std::initializer_list<C> init,Args...args ){
+	
+		int sizes[]{ args... };
+		for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
+		
+		if( !sizes[D-1] ) return;
+		
+		bbGCNode *p=bbGC::alloc( sizeof( Rep )+sizes[D-1]*sizeof(T) );
+		
+		_rep=new( p ) Rep( sizes );
+		
+		int i=0;
+		for( auto it=init.begin();it!=init.end();++it ) _rep->_data[i++]=*it;
+		
+		bbGC::endCtor( _rep );
+	}
+	
+	bbArray &operator=( const bbArray &p ){
+		_rep=p._rep;
+		
+		enqueue();
+		
+		return *this;
+	}
+	
+	T *data(){
+		return _rep->_data;
+	}
+	
+	const T *data()const{
+		return _rep->_data;
+	}
+	
+	int length()const{
+		return _rep ? _rep->_sizes[D-1] : 0;
+	}
+	
+	int size( int q )const{
+		return _rep ? (q ? _rep->_sizes[q]/_rep->_sizes[q-1] : _rep->_sizes[0]) : 0;
+	}
+	
+	bbArray<T,1> slice( int from )const{
+		return slice( from,length() );
+	}
+	
+	bbArray<T,1> slice( int from,int term )const{
+		int length=this->length();
+		if( from<0 ){
+			from+=length;
+			if( from<0 ) from=0;
+		}else if( from>length ){
+			from=length;
+		}
+		if( term<0 ){
+			term+=length;
+			if( term<from ) term=from;
+		}else if( term<from ){
+			term=from;
+		}else if( term>length ){
+			term=length;
+		}
+		int newlen=term-from;
+		bbArray<T,1> p( newlen );
+		for( int i=0;i<newlen;++i ) p.data()[i]=data()[from+i];
+		return p;
+	}
+
+	T &operator[]( int index ){
+		if( index<0 || index>=length() ) puts( "OUT OF RANGE" );
+		return data()[index];
+	}
+	
+	const T &operator[]( int index )const{
+		if( index<0 || index>=length() ) puts( "OUT OF RANGE" );
+		return data()[index];
+	}
+	
+	template <class...Args> T &at( Args...args ){
+		int indices[]{args...};
+		int index=indices[0];
+		for( int i=1;i<D;++i ){
+			if( index>=_rep->_sizes[i-1] ) puts( "Out of range!" );
+			index+=indices[i]*_rep->_sizes[i-1];
+		}
+		if( index>=length() ) puts( "Out of range" );
+		return data()[index];
+	}
+	
+	T &get( int index ){
+		if( index<0 || index>=length() ) puts( "Out of range" );
+		return data()[index];
+	}
+	
+	operator bool()const{
+		return length();
+	}
+};
+*/
+
+#endif

+ 2 - 0
modules/monkey/native/bbdebug.cpp

@@ -0,0 +1,2 @@
+
+#include "bbdebug.h"

+ 31 - 0
modules/monkey/native/bbdebug.h

@@ -0,0 +1,31 @@
+
+#ifndef BB_DEBUG_H
+#define BB_DEBUG_H
+
+#include "bbstring.h"
+
+struct bbRuntimeError{
+
+	bbString msg;
+	
+	bbRuntimeError( bbString msg ):msg( msg ){
+	}
+};
+
+inline void bbAssert( bool cond ){
+	if( !cond ) throw new bbRuntimeError( "Assert failed" );
+}
+
+inline void bbAssert( bool cond,bbString msg ){
+	if( !cond ) throw new bbRuntimeError( msg );
+}
+
+inline void bbDebugAssert( bool cond ){
+	if( !cond ) throw new bbRuntimeError( "Assert failed" );
+}
+
+inline void bbDebugAssert( bool cond,bbString msg ){
+	if( !cond ) throw new bbRuntimeError( msg );
+}
+
+#endif

+ 2 - 0
modules/monkey/native/bbfunction.cpp

@@ -0,0 +1,2 @@
+
+#include "bbfunction.h"

+ 260 - 0
modules/monkey/native/bbfunction.h

@@ -0,0 +1,260 @@
+
+#ifndef BB_FUNCTION_H
+#define BB_FUNCTION_H
+
+#include "bbtypes.h"
+#include "bbgc.h"
+
+template<class T> class bbFunction;
+
+template<class R,class...A> struct bbFunction<R(A...)>{
+
+	typedef R(*F)(A...);
+	
+	struct FunctionRep;
+	struct SequenceRep;
+
+	template<class C> struct MethodRep;
+	
+	static R castErr( A... ){
+		puts( "Null Function Error" );
+		exit( -1 );
+		return R();
+	}
+	
+	struct Rep{
+
+		int refs=0;
+
+		virtual ~Rep(){
+		}
+		
+		virtual R invoke( A... ){
+			return R();
+		}
+		
+		virtual bool equals( Rep *rep ){
+			return rep==this;
+		}
+		
+		virtual int compare( Rep *rhs ){
+			if( this<rhs ) return -1;
+			if( this>rhs ) return 1;
+			return 0;
+		}
+		
+		virtual Rep *remove( Rep *rep ){
+			if( equals( rep ) ) return &_nullRep;
+			return this;
+		}
+		
+		virtual void gcMark(){
+		}
+		
+		void *operator new( size_t size ){
+			return bbMalloc( size );
+		}
+		
+		void operator delete( void *p ){
+			bbFree( p );
+		}
+	};
+	
+	struct FunctionRep : public Rep{
+	
+		F p;
+		
+		FunctionRep( F p ):p( p ){
+		}
+		
+		virtual R invoke( A...a ){
+			return p( a... );
+		}
+		
+		virtual bool equals( Rep *rhs ){
+			FunctionRep *t=dynamic_cast<FunctionRep*>( rhs );
+			return t && p==t->p;
+		}
+		
+		virtual int compare( Rep *rhs ){
+			FunctionRep *t=dynamic_cast<FunctionRep*>( rhs );
+			if( t && p==t->p ) return 0;
+			return Rep::compare( rhs );
+		}
+		
+		virtual F Cast(){
+			return p;
+		}
+	};
+	
+	template<class C> struct MethodRep : public Rep{
+	
+		typedef R(C::*T)(A...);
+		C *c;
+		T p;
+		
+		MethodRep( C *c,T p ):c(c),p(p){
+		}
+		
+		virtual R invoke( A...a ){
+			return (c->*p)( a... );
+		}
+		
+		virtual bool equals( Rep *rhs ){
+			MethodRep *t=dynamic_cast<MethodRep*>( rhs );
+			return t && c==t->c && p==t->p;
+		}
+
+		virtual int compare( Rep *rhs ){
+			MethodRep *t=dynamic_cast<MethodRep*>( rhs );
+			if( t && c==t->c && p==t->p ) return 0;
+			return Rep::compare( rhs );
+		}
+		
+		virtual void gcMark(){
+			bbGCMark( c );
+		}
+		
+	};
+	
+	struct SequenceRep : public Rep{
+	
+		bbFunction lhs,rhs;
+		
+		SequenceRep( const bbFunction &lhs,const bbFunction &rhs ):lhs( lhs ),rhs( rhs ){
+		}
+		
+		virtual R invoke( A...a ){
+			lhs( a... );
+			return rhs( a... );
+		}
+		
+		virtual Rep *remove( Rep *rep ){
+		
+			if( rep==this ) return &_nullRep;
+			
+			Rep *lhs2=lhs._rep->remove( rep );
+			Rep *rhs2=rhs._rep->remove( rep );
+			
+			if( lhs2==lhs._rep && rhs2==rhs._rep ) return this;
+			if( lhs2!=&_nullRep && rhs2 !=&_nullRep ) return new SequenceRep( lhs2,rhs2 );
+			if( lhs2!=&_nullRep ) return lhs2;
+			if( rhs2!=&_nullRep ) return rhs2;
+
+			return &_nullRep;
+		}
+		
+		virtual void gcMark(){
+			lhs._rep->gcMark();
+			rhs._rep->gcMark();
+		}
+	};
+	
+	Rep *_rep;
+	
+	static Rep _nullRep;
+	
+	void retain()const{
+		++_rep->refs;
+	}
+	
+	void release(){
+		if( !--_rep->refs && _rep!=&_nullRep ) delete _rep;
+	}
+	
+	bbFunction( Rep *rep ):_rep( rep ){
+		retain();
+	}
+	
+	public:
+	
+	bbFunction():_rep( &_nullRep ){
+	}
+	
+	bbFunction( const bbFunction &p ):_rep( p._rep ){
+		retain();
+	}
+	
+	template<class C> bbFunction( C *c,typename MethodRep<C>::T p ):_rep( new MethodRep<C>(c,p) ){
+		retain();
+	}
+	
+	bbFunction( F p ):_rep( new FunctionRep( p ) ){
+		retain();
+	}
+	
+	~bbFunction(){
+		release();
+	}
+	
+	bbFunction &operator=( const bbFunction &p ){
+		p.retain();
+		release();
+		_rep=p._rep;
+		return *this;
+	}
+	
+	bbFunction operator+( const bbFunction &rhs )const{
+		if( _rep==&_nullRep ) return rhs;
+		if( rhs._rep==&_nullRep ) return *this;
+		return new SequenceRep( *this,rhs );
+	}
+	
+	bbFunction operator-( const bbFunction &rhs )const{
+		return _rep->remove( rhs._rep );
+	}
+	
+	bbFunction &operator+=( const bbFunction &rhs ){
+		*this=*this+rhs;
+		return *this;
+	}
+	
+	bbFunction &operator-=( const bbFunction &rhs ){
+		*this=*this-rhs;
+		return *this;
+	}
+
+	bbBool operator==( const bbFunction &rhs )const{
+		return _rep->equals( rhs._rep );
+	}
+	
+	bbBool operator!=( const bbFunction &rhs )const{
+		return !_rep->equals( rhs._rep );
+	}
+	
+	operator bbBool()const{
+		return _rep==&_nullRep;
+	}
+
+	R operator()( A...a )const{
+		return _rep->invoke( a... );
+	}
+	
+	//cast to simple static function ptr
+	//
+	operator F()const{
+		FunctionRep *t=dynamic_cast<FunctionRep*>( _rep );
+		if( t ) return t->p;
+		return castErr;
+	}
+};
+
+template<class R,class...A> typename bbFunction<R(A...)>::Rep bbFunction<R(A...)>::_nullRep;
+
+template<class C,class R,class...A> bbFunction<R(A...)> bbMethod( C *c,R(C::*p)(A...) ){
+	return bbFunction<R(A...)>( c,p );
+}
+
+template<class C,class R,class...A> bbFunction<R(A...)> bbMethod( const bbGCVar<C> &c,R(C::*p)(A...) ){
+	return bbFunction<R(A...)>( c.get(),p );
+}
+
+template<class R,class...A> void bbGCMark( const bbFunction<R(A...)> &t ){
+	t._rep->gcMark();
+}
+
+template<class R,class...A> int bbCompare( const bbFunction<R(A...)> &x,const bbFunction<R(A...)> &y ){
+	return x._rep->compare( y._rep );
+}
+
+#endif

+ 247 - 0
modules/monkey/native/bbgc.cpp

@@ -0,0 +1,247 @@
+
+//v1001
+
+#include <utility>
+
+#include "bbgc.h"
+
+//For future ref...
+#if BB_THREADED
+
+//fast but unpredictable
+//#define BBGC_LOCK while( bbGC::spinlock.test_and_set( std::memory_order_acquire ) ) std::this_thread::yield();
+//#define BBGC_UNLOCK bbGC::spinlock.clear( std::memory_order_release );
+
+//pretty slow...
+//#define BBGC_LOCK bbGC::mutex.lock();
+//#define BBGC_UNLOCK bbGC::mutex.unlock();
+
+//better...a 'Benaphore' apparently...
+#define BBGC_LOCK \
+	if( ++bbGC::locks>1 ){ \
+		std::unique_lock<std::mutex> lock( bbGC::mutex ); \
+		bbGC::cond_var.wait( lock,[]{ return bbGC::sem_count>0;} ); \
+		--bbGC::sem_count; \
+	}
+
+#define BBGC_UNLOCK \
+	if( --bbGC::locks>0 ){ \
+		std::unique_lock<std::mutex> lock( bbGC::mutex ); \
+		++bbGC::sem_count; \
+		bbGC::cond_var.notify_one(); \
+	}
+	
+	int sem_count;
+	std::mutex mutex;
+	std::atomic_int locks;
+	std::condition_variable cond_var;
+	std::atomic_flag spinlock=ATOMIC_FLAG_INIT;
+	
+#endif
+
+namespace bbGC{
+
+	int markedBit;
+	int unmarkedBit;
+
+	bbGCNode *markQueue;
+	bbGCNode *markedList;
+	bbGCNode *unmarkedList;
+	
+	bbGCRoot *roots;
+	
+	bbGCFiber *fibers;
+	bbGCFiber *currentFiber;
+
+	bbGCNode markLists[2];
+	bbGCNode freeList;
+	
+	size_t markedBytes;
+	size_t unmarkedBytes;
+	size_t allocedBytes;
+	
+	void init(){
+		static bool done;
+		if( done ) return;
+		done=true;
+		
+		markedBit=1;
+		markedList=&markLists[0];
+		markedList->succ=markedList->pred=markedList;
+		
+		unmarkedBit=2;
+		unmarkedList=&markLists[1];
+		unmarkedList->succ=unmarkedList->pred=unmarkedList;
+		
+		freeList.succ=freeList.pred=&freeList;
+		
+		fibers=new bbGCFiber;
+		
+		currentFiber=fibers;
+	}
+	
+	void destroy( bbGCNode *p ){
+	
+//		printf( "destroying: %s %p\n",p->typeName(),p );
+		
+#if BBGC_DEBUG
+
+//		p->~bbGCNode();
+			
+//		size_t sz=(size_t)&((bbGCNode*)0)->flags;
+		
+//		memset( (char*)p+sz,0xaa,size-sz );
+		
+		p->flags=3;
+
+#else
+		p->~bbGCNode();
+			
+		bbFree( p );
+#endif
+	}
+	
+	void reclaim( size_t size=0x7fffffff ){
+	
+		while( freeList.succ!=&freeList ){
+		
+			bbGCNode *p=freeList.succ;
+			size_t psize=p->gcSize();
+			
+			remove( p );
+			destroy( p );
+
+			if( psize>=size ) break;
+			size-=psize;
+		}
+	}
+	
+	void mark( bbGCNode *p ){
+		if( !p || (p->flags&3)==markedBit ) return;
+		
+		remove( p );
+		insert( p,markedList );
+		
+		p->flags=(p->flags & ~3)|markedBit;
+		markedBytes+=p->gcSize();
+
+		p->gcMark();
+	}
+	
+	void markRoots(){
+	
+		for( bbGCRoot *root=roots;root;root=root->succ ){
+		
+			root->gcMark();
+		}
+	}
+	
+	void markFrames(){
+	
+		bbGCFiber *fiber=fibers;
+		
+		for(;;){
+
+			for( bbGCFrame *frame=fiber->frames;frame;frame=frame->succ ){
+			
+				frame->gcMark();
+			}
+			
+			for( bbGCNode *node=fiber->ctoring;node;node=node->succ ){
+			
+				node->gcMark();
+			}
+			
+			fiber=fiber->succ;
+			if( fiber==fibers ) break; 
+		}
+	}
+	
+	void markQueued( size_t tomark=0x7fffffff ){
+	
+		while( markQueue && markedBytes<tomark ){
+
+			bbGCNode *p=markQueue;
+			markQueue=p->succ;
+			
+			insert( p,markedList );
+			markedBytes+=p->gcSize();
+			
+			p->gcMark();
+		}
+	}
+
+	void sweep(){
+	
+//		puts( "bbGC::sweep()" );fflush( stdout );
+	
+		markFrames();
+	
+		markQueued();
+		
+		if( unmarkedList->succ!=unmarkedList ){
+			
+			//append unmarked to end of free queue
+			unmarkedList->succ->pred=freeList.pred;
+			unmarkedList->pred->succ=&freeList;
+			freeList.pred->succ=unmarkedList->succ;
+			freeList.pred=unmarkedList->pred;
+			
+			//clear unmarked
+			unmarkedList->succ=unmarkedList->pred=unmarkedList;
+		}
+		
+		std::swap( markedList,unmarkedList );
+		std::swap( markedBit,unmarkedBit );
+		
+		unmarkedBytes=markedBytes;
+
+		markedBytes=allocedBytes=0;
+		
+		markRoots();
+	}
+
+	bbGCNode *alloc( size_t size ){
+	
+		size=(size+7)&~7;
+		
+		allocedBytes+=size;
+		
+		if( allocedBytes>=BBGC_TRIGGER ){
+		
+			sweep();
+			
+#if BBGC_AGGRESSIVE
+			reclaim();
+#endif
+		}else{
+		
+#if BBGC_INCREMENTAL
+			size_t tomark=double(allocedBytes) / double(BBGC_TRIGGER) * double(unmarkedBytes+allocedBytes);
+
+			markQueued( tomark );
+#endif
+		}
+		
+#if !BBGC_AGGRESSIVE
+		reclaim( size );
+#endif
+
+		bbGCNode *p=(bbGCNode*)bbMalloc( size );
+		
+		*((void**)p)=(void*)0xcafebabe;
+		
+		p->flags=size;
+		
+		return p;
+	}
+	
+	void collect(){
+	
+		sweep();
+
+		reclaim();
+		
+		printf( "GCCollect: in use=%i\n",(int)unmarkedBytes );fflush( stdout );
+	}
+}

+ 258 - 0
modules/monkey/native/bbgc.h

@@ -0,0 +1,258 @@
+
+#ifndef BB_GC_H
+#define BB_GC_H
+
+#include "bbstd.h"
+#include "bbtypes.h"
+#include "bbmemory.h"
+
+//how much to allocate before a sweep occurs
+//#define BBGC_TRIGGER 0
+//#define BBGC_TRIGGER 64
+//#define BBGC_TRIGGER 256
+//#define BBGC_TRIGGER 65536
+//#define BBGC_TRIGGER 1*1024*1024
+#define BBGC_TRIGGER 4*1024*1024
+//#define BBGC_TRIGGER 16*1024*1024
+
+//mark while allocating, slower but smoother...
+#define BBGC_INCREMENTAL 1
+
+//reclaim all memory after a sweep, lumpier...
+//#define BBGC_AGGRESSIVE 1
+
+//check for use of deleted objects, MUCH leakier...
+//#define BBGC_DEBUG 1
+
+#if BBGC_DEBUG
+#define BBGC_VALIDATE( P ) \
+	if( (P) && ((P)->flags&3)==3 ){ \
+		printf( "Attempt to use deleted object %p of type '%s'\n",(P),(P)->typeName() ); \
+		fflush( stdout ); \
+		abort(); \
+	}
+#else
+#define BBGC_VALIDATE( P )
+#endif
+
+struct bbGCNode;
+struct bbGCFiber;
+struct bbGCFrame;
+struct bbGCRoot;
+
+namespace bbGC{
+
+	extern bbGCRoot *roots;
+	
+	extern bbGCNode *markQueue;
+	extern bbGCNode *unmarkedList;
+	
+	extern bbGCFiber *fibers;
+	extern bbGCFiber *currentFiber;
+	
+	extern int markedBit;
+	extern int unmarkedBit;
+	
+	void init();
+	
+	void collect();
+	
+	bbGCNode *alloc( size_t size );
+}
+
+struct bbGCNode{
+	bbGCNode *succ;
+	bbGCNode *pred;
+	size_t flags;		//0=lonely, 1/2=marked/unmarked; 3=destroyed
+
+	bbGCNode(){
+	}
+	
+	virtual ~bbGCNode(){
+	}
+
+	size_t gcSize(){
+		return flags&~7;
+	}
+	
+	virtual void gcMark(){
+	}
+	
+	virtual const char *typeName(){
+		return "bbGCNode";
+	}
+};
+
+struct bbGCFiber{
+
+	bbGCFiber *succ;
+	bbGCFiber *pred;
+	bbGCFrame *frames;
+	bbGCNode *ctoring;
+	
+	bbGCFiber():succ( this ),pred( this ),frames( nullptr ),ctoring( nullptr ){
+	}
+	
+	void link(){
+		succ=bbGC::fibers;
+		pred=bbGC::fibers->pred;
+		bbGC::fibers->pred=this;
+		pred->succ=this;
+	}
+	
+	void unlink(){
+		pred->succ=succ;
+		succ->pred=pred;
+	}
+};
+
+struct bbGCFrame{
+	bbGCFrame *succ;
+	
+	bbGCFrame():succ( bbGC::currentFiber->frames ){
+		bbGC::currentFiber->frames=this;
+	}
+	
+	~bbGCFrame(){
+		bbGC::currentFiber->frames=succ;
+	}
+
+	virtual void gcMark(){
+	}
+};
+
+struct bbGCRoot{
+	bbGCRoot *succ;
+	
+	bbGCRoot():succ( bbGC::roots ){
+		bbGC::roots=this;
+	}
+	
+	virtual void gcMark(){
+	}
+};
+
+namespace bbGC{
+	
+	inline void insert( bbGCNode *p,bbGCNode *succ ){
+		p->succ=succ;
+		p->pred=succ->pred;
+		p->pred->succ=p;
+		succ->pred=p;
+	}
+
+	inline void remove( bbGCNode *p ){	
+		p->pred->succ=p->succ;
+		p->succ->pred=p->pred;
+	}
+
+	inline void enqueue( bbGCNode *p ){
+		BBGC_VALIDATE( p )
+
+		if( !p || (p->flags&3)!=unmarkedBit ) return;
+		
+		remove( p );
+		p->succ=markQueue;
+		markQueue=p;
+		
+		p->flags=(p->flags & ~3)|markedBit;
+	}
+	
+	inline void beginCtor( bbGCNode *p ){
+		p->succ=currentFiber->ctoring;
+		currentFiber->ctoring=p;
+	}
+	
+	inline void endCtor( bbGCNode *p ){
+		currentFiber->ctoring=p->succ;
+#if BBGC_INCREMENTAL
+		p->succ=markQueue;
+		markQueue=p;
+		p->flags|=markedBit;
+#else
+		p->flags|=unmarkedBit;
+		insert( p,unmarkedList );
+#endif
+	}
+}
+
+template<class T> struct bbGCVar{
+	T *_ptr;
+	
+	void enqueue(){
+	
+#if BBGC_INCREMENTAL
+		bbGC::enqueue( dynamic_cast<bbGCNode*>( _ptr ) );
+#endif
+	}
+	
+	public:
+	
+	bbGCVar():_ptr( nullptr ){
+	}
+	
+	bbGCVar( T *p ):_ptr( p ){
+		enqueue();
+	}
+	
+	bbGCVar( const bbGCVar &p ):_ptr( p._ptr ){
+		enqueue();
+	}
+	
+	bbGCVar &operator=( T *p ){
+		_ptr=p;
+		enqueue();
+		return *this;
+	}
+	
+	bbGCVar &operator=( const bbGCVar &p ){
+		_ptr=p._ptr;
+		enqueue();
+		return *this;
+	}
+	
+	T *get()const{
+		return _ptr;
+	}
+	
+	T *operator->()const{
+		return _ptr;
+	}
+	
+	operator T*()const{
+		return _ptr;
+	}
+};
+
+inline void bbGCMark( bbBool ){}
+inline void bbGCMark( bbByte ){}
+inline void bbGCMark( bbUByte ){}
+inline void bbGCMark( bbShort ){}
+inline void bbGCMark( bbUShort ){}
+inline void bbGCMark( bbInt ){}
+inline void bbGCMark( bbUInt ){}
+inline void bbGCMark( bbLong ){}
+inline void bbGCMark( bbULong ){}
+inline void bbGCMark( bbFloat ){}
+inline void bbGCMark( bbDouble ){}
+
+template<class T> void bbGCMark( const T &t ){
+}
+
+template<class T> void bbGCMark( const bbGCVar<T> &v ){
+	bbGC::enqueue( dynamic_cast<bbGCNode*>( v._ptr ) );
+}
+
+template<class T> void bbGCMark( T *p ){
+	bbGC::enqueue( dynamic_cast<bbGCNode*>( p ) );
+}
+
+template<class T,class C> T bb_object_cast( const bbGCVar<C> &p ){
+	return dynamic_cast<T>( p._ptr );
+}
+
+template<class T,class C> T bb_object_cast( C *p ){
+	return dynamic_cast<T>( p );
+}
+
+#endif

+ 12 - 0
modules/monkey/native/bbinit.cpp

@@ -0,0 +1,12 @@
+
+#include "bbinit.h"
+
+#include <stdio.h>
+
+bbInit *bbInit::first;
+
+bbInit::bbInit( const char *ident,void(*init)() ):info( info ),init( init ){
+//	printf( "Registering initializer '%s'\n",info );fflush( stdout );
+	succ=first;
+	first=this;
+}

+ 17 - 0
modules/monkey/native/bbinit.h

@@ -0,0 +1,17 @@
+
+#ifndef BB_INIT_H
+#define BB_INIT_H
+
+//Simple list of stuff to get inited before main is run
+
+struct bbInit{
+	bbInit *succ;
+	const char *info;
+	void (*init)();
+	
+	static bbInit *first;
+	
+	bbInit( const char *info,void(*init)() );
+};
+
+#endif

+ 66 - 0
modules/monkey/native/bbmemory.cpp

@@ -0,0 +1,66 @@
+
+#include "bbmemory.h"
+
+#include <cstring>
+
+static size_t malloced;
+
+static void *pools[256>>3];
+
+void *bbMalloc( size_t size ){
+
+	size+=sizeof(size_t);
+	
+	size=(size+7)&~7;
+	
+	size_t *p;
+/*	
+	if( size<256 && pools[size>>3] ){
+		p=(size_t*)pools[size>>3];
+		pools[size>>3]=*((void**)p);
+	}else{
+		p=(size_t*)malloc( size );
+	}
+*/
+	p=(size_t*)malloc( size );
+	
+	memset( p,0,size );
+	
+	*p=size;
+
+	malloced+=size;
+	
+//	printf( "Malloced:%p, size=%i, total=%i\n",p,size,malloced );
+//	fflush( stdout );
+
+	return p+1;
+}
+
+size_t bbMallocSize( const void *q ){
+	return *((const size_t*)q-1);
+}
+
+void bbFree( void *q ){
+
+	if( !q ) return;
+
+	size_t *p=(size_t*)q-1;
+	
+	size_t size=*p;
+	
+	//free( p );
+	
+	/*
+	if( size<256 ){
+		*((void**)p)=pools[size>>3];
+		pools[size>>3]=p;
+	}else{
+		free( p );
+	}
+	*/
+	
+	malloced-=size;
+	
+//	printf( "Freed:%p, size=%i, total=%i\n",p,size,malloced );
+//	fflush( stdout );
+}

+ 13 - 0
modules/monkey/native/bbmemory.h

@@ -0,0 +1,13 @@
+
+#ifndef BB_MEMORY_H
+#define BB_MEMORY_H
+
+#include "bbtypes.h"
+
+void *bbMalloc( size_t size );
+
+size_t bbMallocSize( const void *p );
+
+void bbFree( void *p );
+
+#endif

+ 123 - 0
modules/monkey/native/bbmonkey.cpp

@@ -0,0 +1,123 @@
+
+#include <signal.h>
+
+#if _WIN32
+
+#include <windows.h>
+
+#elif __APPLE__
+
+#include <execinfo.h>
+#include <dlfcn.h>
+#include <cxxabi.h>
+
+#endif
+
+#include "bbmonkey.h"
+
+namespace{
+
+	void sighandler( int sig  ){
+	
+		const char *err="Unknown signal";
+		switch( sig ){
+		case SIGSEGV:err="Memory access violation";break;
+		case SIGILL:err="Illegal instruction";
+		case SIGFPE:err="Floating point exception";
+	#if !_WIN32
+		case SIGBUS:err="Bus error";
+	#endif	
+		}
+		
+		printf( "Caught signal:%s\n",err );
+		
+#if __APPLE__
+
+		printf( "Stack trace:\n" );	
+		
+		void *stack[128];
+
+		int frames=backtrace( stack,128 );
+		
+		for( int i=0;i<frames;++i ){
+		
+			Dl_info info{};
+			
+			if( dladdr( stack[i],&info ) ){
+			
+				if( info.dli_sname ){
+				
+					char buf[1024];
+					size_t length=1024;
+					int status=0;
+					
+					const char *str=abi::__cxa_demangle( info.dli_sname,buf,&length,&status );
+					
+					if( str ){
+						printf( "%s\n",str );
+					}else{
+						printf( "%s\n",info.dli_sname );
+					}
+				}
+			}
+		}
+#endif
+
+		fflush( stdout );
+		exit( -1 );
+	}
+}
+
+int bb_argc;
+char **bb_argv;
+
+void bbMain();
+
+int main( int argc,char **argv ){
+
+	bb_argc=argc;
+	bb_argv=argv;
+	
+	signal( SIGSEGV,sighandler );
+	signal( SIGILL,sighandler );
+	signal( SIGFPE,sighandler );
+
+#if !_WIN32
+	signal( SIGBUS,sighandler );
+#endif
+
+//	printf( "bbMain() : sizeof(bbBool)=%i sizeof(bbByte)=%i sizeof(bbShort)=%i sizeof(bbInt)=%i, sizeof(bbLong)=%i, sizeof(bbChar)=%i sizeof(void*)=%i, sizeof(size_t)=%i\n",(int)sizeof(bbBool),(int)sizeof(bbByte),(int)sizeof(bbShort),(int)sizeof(bbInt),(int)sizeof(bbLong),(int)sizeof(bbChar),(int)sizeof(void*),(int)sizeof(size_t) );
+//	fflush( stdout );
+	
+	try{
+	
+		bbGC::init();
+		
+		for( bbInit *init=bbInit::first;init;init=init->succ ){
+//			printf( "Executing initializer '%s'\n",init->info );fflush( stdout );
+			init->init();
+		}
+		
+		bbMain();
+		
+	}catch( bbRuntimeError *ex ){
+	
+		printf( "Monkey2 Runtime Error:%s\n",bbCString( ex->msg ).data() );
+
+	}catch(...){
+	
+		printf( "Uncaught exception\n" );fflush( stdout );
+//		throw;
+	}
+	
+	return 0;
+}
+
+/*
+void *operator new( size_t size ){
+}
+
+void operator delete( void *p ){
+	printf( "delete:%p\n",p );
+}
+*/

+ 24 - 0
modules/monkey/native/bbmonkey.h

@@ -0,0 +1,24 @@
+
+#ifndef BB_MONKEY_H
+#define BB_MONKEY_H
+
+#include "bbstd.h"
+#include "bbtypes.h"
+#include "bbmemory.h"
+#include "bbstring.h"
+#include "bbgc.h"
+#include "bbfunction.h"
+#include "bbarray.h"
+#include "bbobject.h"
+#include "bbinit.h"
+#include "bbdebug.h"
+
+extern int bb_argc;
+extern char **bb_argv;
+
+template<class T> int bbCompare( T x,T y ){
+	if( y>x ) return -1;
+	return x>y;
+}
+
+#endif

+ 2 - 0
modules/monkey/native/bbobject.cpp

@@ -0,0 +1,2 @@
+
+#include "bbobject.h"

+ 43 - 0
modules/monkey/native/bbobject.h

@@ -0,0 +1,43 @@
+
+#ifndef BB_OBJECT_H
+#define BB_OBJECT_H
+
+#include "bbgc.h"
+
+class bbObject : public bbGCNode{
+public:
+	bbObject(){
+		bbGC::beginCtor( this );
+	}
+	
+	virtual ~bbObject(){
+	}
+	
+	virtual const char *typeName(){
+		return "monkey.Object";
+	}
+
+	void *operator new( size_t size ){
+		return bbGC::alloc( size );
+	}
+	
+	//NOTE! We need this in case ctor throws an exception. delete never otherwise called...
+	//
+	void operator delete( void *p ){
+		bbGC::endCtor( (bbObject*)(p) );
+	}
+};
+
+class bbInterface{
+public:
+	virtual ~bbInterface(){
+	}
+};
+
+template<class T,class...A> T *bbGCNew( A...a ){
+	T *p=new T( a... );
+	bbGC::endCtor( p );
+	return p;
+}
+
+#endif

+ 14 - 0
modules/monkey/native/bbstd.h

@@ -0,0 +1,14 @@
+
+#ifndef BB_STD_H
+#define BB_STD_H
+
+#include <new>
+#include <initializer_list>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+#include <cmath>
+
+#endif

+ 173 - 0
modules/monkey/native/bbstring.cpp

@@ -0,0 +1,173 @@
+
+#include "bbstring.h"
+
+bbString::Rep bbString::_nullRep;
+
+int bbString::utf8Length()const{
+
+	const bbChar *p=data();
+	const bbChar *e=p+length();
+	
+	int n=0;
+	
+	while( p<e ){
+		bbChar c=*p++;
+		if( c<0x80 ){
+			n+=1;
+		}else if( c<0x800 ){
+			n+=2;
+		}else{
+			n+=3;
+		}
+	}
+
+	return n;
+}
+
+int bbString::toUtf8( void *buf,int size )const{
+
+	char *dst=(char*)buf;
+	char *end=dst+size;
+	
+	const bbChar *p=data();
+	const bbChar *e=p+length();
+	
+	while( p<e && dst<end ){
+		bbChar c=*p++;
+		if( c<0x80 ){
+			*dst++=c;
+		}else if( c<0x800 ){
+			if( dst+2>end ) break;
+			*dst++=0xc0 | (c>>6);
+			*dst++=0x80 | (c & 0x3f);
+		}else{
+			if( dst+3>end ) break;
+			*dst++=0xe0 | (c>>12);
+			*dst++=0x80 | ((c>>6) & 0x3f);
+			*dst++=0x80 | (c & 0x3f);
+		}
+	}
+	
+	int n=dst-(char*)buf;
+
+	if( dst<end ) *dst++=0;
+	
+	return n;
+}
+
+const char *bbString::c_str()const{
+
+	static int _sz;
+	static char *_tmp;
+	
+	int sz=length()+1;
+	if( sz>_sz ){
+		free( _tmp );
+		_tmp=(char*)malloc( _sz=sz );
+	}
+	
+	for( int i=0;i<length();++i ) _tmp[i]=data()[i];
+	_tmp[length()]=0;
+	return _tmp;
+}
+
+bbString bbString::fromChar( int chr ){
+	bbChar buf[]={(bbChar)chr,0};
+	return buf;
+}
+
+bbString bbString::fromCString( const void *data ){
+	return (const char*)data;
+}
+
+bbString bbString::fromWString( const void *data ){
+	return (const wchar_t*)data;
+}
+
+bbString bbString::fromUtf8String( const void *data ){
+	const char *p=(const char*)data;
+	return fromUtf8( p,strlen( p ) );
+}
+
+bbString bbString::fromUtf8String( const void *data,int size ){
+
+	const char *p=(const char*)data;
+	const char *e=p+size;
+	
+	bbChar *tmp=(bbChar*)malloc( size*sizeof(bbChar) );
+	bbChar *put=tmp;
+	
+	while( p<e ){
+		int c=*p++;
+		if( c & 0x80 ){
+			if( (c & 0xe0)==0xc0 ){
+				if( p>=e || (p[0] & 0xc0)!=0x80 ) break;
+				c=((c & 0x1f)<<6) | (p[0] & 0x3f);
+				p+=1;
+			}else if( (c & 0xf0)==0xe0 ){
+				if( p+1>=e || (p[0] & 0xc0)!=0x80 || (p[1] & 0xc0)!=0x80 ) break;
+				c=((c & 0x0f)<<12) | ((p[0] & 0x3f)<<6) | (p[1] & 0x3f);
+				p+=2;
+			}else{
+				break;
+			}
+		}
+		*put++=c;
+	}
+	
+	bbString str( tmp,put-tmp );
+	free( tmp );
+	
+	return str;
+}
+
+bbArray<bbString> *bbString::split( bbString sep )const{
+
+	if( !sep.length() ){
+		bbArray<bbString> *bits=bbArray<bbString>::create( length() );
+		for( int i=0;i<length();++i ){
+			bits->at(i)=bbString( &data()[i],1 );
+		}
+		return bits;
+	}
+	
+	int i=0,i2,n=1;
+	while( (i2=find( sep,i ))!=-1 ){
+		++n;
+		i=i2+sep.length();
+	}
+	bbArray<bbString> *bits=bbArray<bbString>::create( n );
+	if( n==1 ){
+		bits->at(0)=*this;
+		return bits;
+	}
+	i=0;n=0;
+	while( (i2=find( sep,i ))!=-1 ){
+		bits->at(n++)=slice( i,i2 );
+		i=i2+sep.length();
+	}
+	bits->at(n)=slice( i );
+	return bits;
+}
+
+bbString bbString::join( bbArray<bbString> *bits )const{
+
+	if( bits->length()==0 ) return bbString();
+	if( bits->length()==1 ) return bits->at(0);
+	
+	int len=length() * (bits->length()-1);
+	for( int i=0;i<bits->length();++i ) len+=bits->at(i).length();
+	
+	Rep *rep=Rep::alloc( len );
+	bbChar *p=rep->data;
+
+	p=t_memcpy( p,bits->at(0).data(),bits->at(0).length() );
+	
+	for( int i=1;i<bits->length();++i ){
+		p=t_memcpy( p,data(),length() );
+		p=t_memcpy( p,bits->at(i).data(),bits->at(i).length() );
+	}
+	
+	return rep;
+}
+

+ 577 - 0
modules/monkey/native/bbstring.h

@@ -0,0 +1,577 @@
+
+#ifndef BB_STRING_H
+#define BB_STRING_H
+
+#include "bbtypes.h"
+#include "bbmemory.h"
+#include "bbarray.h"
+
+class bbCString;
+
+class bbString{
+
+	struct Rep{
+		int refs;
+		int length;
+		bbChar data[0];
+		
+		static Rep *alloc( int length ){
+			if( !length ) return &_nullRep;
+			Rep *rep=(Rep*)bbMalloc( sizeof(Rep)+length*sizeof(bbChar) );
+			rep->refs=1;
+			rep->length=length;
+			return rep;
+		}
+		
+		template<class C> static Rep *create( const C *p,int length ){
+			Rep *rep=alloc( length );
+			for( int i=0;i<length;++i ) rep->data[i]=p[i];
+			return rep;
+		}
+		
+		template<class C> static Rep *create( const C *p ){
+			const C *e=p;
+			while( *e ) ++e;
+			return create( p,e-p );
+		}
+	};
+	
+	Rep *_rep;
+
+	static Rep _nullRep;
+	
+	void retain()const{
+		++_rep->refs;
+	}
+	
+	void release(){
+		if( !--_rep->refs && _rep!=&_nullRep ) bbFree( _rep );
+	}
+	
+	bbString( Rep *rep ):_rep( rep ){
+	}
+	
+	template<class C> static int t_memcmp( const C *p1,const C *p2,int count ){
+		return memcmp( p1,p2,count*sizeof(C) );
+	}
+
+	//returns END of dst!	
+	template<class C> static C *t_memcpy( C *dst,const C *src,int count ){
+		return (C*)memcpy( dst,src,count*sizeof(C) )+count;
+	}
+	
+	public:
+	
+	const char *c_str()const;
+	
+	bbString():_rep( &_nullRep ){
+	}
+	
+	bbString( const bbString &str ):_rep( str._rep ){
+		retain();
+	}
+	
+	template<class C> bbString( const C *data ):_rep( Rep::create( data ) ){
+	}
+
+	template<class C> bbString( const C *data,int length ):_rep( Rep::create( data,length ) ){
+	}
+	
+	bbString( bbInt n ){
+		char data[64];
+		sprintf( data,"%i",n );
+		_rep=Rep::create( data );
+	}
+	
+	bbString( bbUInt n ){
+		char data[64];
+		sprintf( data,"%u",n );
+		_rep=Rep::create( data );
+	}
+	
+	bbString( bbLong n ){
+		char data[64];
+		sprintf( data,"%lld",n );
+		_rep=Rep::create( data );
+	}
+	
+	bbString( bbULong n ){
+		char data[64];
+		sprintf( data,"%llu",n );
+		_rep=Rep::create( data );
+	}
+	
+	bbString( float n ){
+		char data[64];
+		sprintf( data,"%.9g",n );
+		_rep=Rep::create( data );
+	}
+	
+	bbString( double n ){
+		char data[64];
+		sprintf( data,"%.17g",n );
+		_rep=Rep::create( data );
+	}
+	
+	~bbString(){
+		release();
+	}
+	
+	const bbChar *data()const{
+		return _rep->data;
+	}
+	
+	int length()const{
+		return _rep->length;
+	}
+	
+	bbChar operator[]( int index )const{
+		return data()[index];
+	}
+	
+	bbString operator+()const{
+		return *this;
+	}
+	
+	bbString operator-()const{
+		Rep *rep=Rep::alloc( length() );
+		const bbChar *p=data()+length();
+		for( int i=0;i<rep->length;++i ) rep->data[i]=*--p;
+		return rep;
+	}
+	
+	bbString operator+( const bbString &str ){
+	
+		if( !length() ) return str;
+		if( !str.length() ) return *this;
+		
+		Rep *rep=Rep::alloc( length()+str.length() );
+		t_memcpy( rep->data,data(),length() );
+		t_memcpy( rep->data+length(),str.data(),str.length() );
+
+		return rep;
+	}
+	
+	bbString operator*( int n ){
+		Rep *rep=Rep::alloc( length()*n );
+		bbChar *p=rep->data;
+		for( int j=0;j<n;++j ){
+			for( int i=0;i<_rep->length;++i ) *p++=data()[i];
+		}
+		return rep;
+	}
+	
+	bbString &operator=( const bbString &str ){
+		str.retain();
+		release();
+		_rep=str._rep;
+		return *this;
+	}
+	
+	template<class C> bbString &operator=( const C *data ){
+		release();
+		_rep=Rep::create( data );
+		return *this;
+	}
+	
+	bbString &operator+=( const bbString &str ){
+		*this=*this+str;
+		return *this;
+	}
+	
+	int find( bbString str,int from=0 )const{
+		if( from<0 ) from=0;
+		for( int i=from;i<=length()-str.length();++i ){
+			if( !t_memcmp( data()+i,str.data(),str.length() ) ) return i;
+		}
+		return -1;
+	}
+	
+	int findLast( const bbString &str,int from=0 )const{
+		if( from<0 ) from=0;
+		for( int i=length()-str.length();i>=from;--i ){
+			if( !t_memcmp( data()+i,str.data(),str.length() ) ) return i;
+		}
+		return -1;
+	}
+	
+	bool contains( const bbString &str )const{
+		return find( str )!=-1;
+	}
+	
+	bbString slice( int from )const{
+		int length=this->length();
+		if( from<0 ){
+			from+=length;
+			if( from<0 ) from=0;
+		}else if( from>length ){
+			from=length;
+		}
+		if( !from ) return *this;
+		return bbString( data()+from,length-from );
+	}
+	
+	bbString slice( int from,int term )const{
+		int length=this->length();
+		if( from<0 ){
+			from+=length;
+			if( from<0 ) from=0;
+		}else if( from>length ){
+			from=length;
+		}
+		if( term<0 ){
+			term+=length;
+			if( term<from ) term=from;
+		}else if( term<from ){
+			term=from;
+		}else if( term>length ){
+			term=length;
+		}
+		if( !from && term==length ) return *this;
+		return bbString( data()+from,term-from );
+	}
+
+	bbString left( int count )const{
+		return slice( 0,count );
+	}
+	
+	bbString right( int count )const{
+		return slice( -count );
+	}
+	
+	bbString mid( int from,int count )const{
+		return slice( from,from+count );
+	}
+	
+	bool startsWith( const bbString &str )const{
+		if( str.length()>length() ) return false;
+		return t_memcmp( data(),str.data(),str.length() )==0;
+	}
+	
+	bool endsWith( const bbString &str )const{
+		if( str.length()>length() ) return false;
+		return t_memcmp( data()+(length()-str.length()),str.data(),str.length() )==0;
+	}
+	
+	bbString toUpper()const{
+		Rep *rep=Rep::alloc( length() );
+		for( int i=0;i<length();++i ) rep->data[i]=std::toupper( data()[i] );
+		return rep;
+	}
+	
+	bbString toLower()const{
+		Rep *rep=Rep::alloc( length() );
+		for( int i=0;i<length();++i ) rep->data[i]=std::tolower( data()[i] );
+		return rep;
+	}
+	
+	bbString capitalize()const{
+		if( !length() ) return &_nullRep;
+		Rep *rep=Rep::alloc( length() );
+		rep->data[0]=std::toupper( data()[0] );
+		for( int i=1;i<length();++i ) rep->data[i]=data()[i];
+		return rep;
+	}
+	
+	bbString trim()const{
+		const bbChar *beg=data();
+		const bbChar *end=data()+length();
+		while( beg!=end && *beg<=32 ) ++beg;
+		while( beg!=end && *(end-1)<=32 ) --end;
+		if( end-beg==length() ) return *this;
+		return bbString( beg,end-beg );
+	}
+	
+	bbString replace( const bbString &str,const bbString &repl )const{
+	
+		int n=0;
+		for( int i=0;; ){
+			i=find( str,i );
+			if( i==-1 ) break;
+			i+=str.length();
+			++n;
+		}
+		if( !n ) return *this;
+		
+		Rep *rep=Rep::alloc( length()+n*(repl.length()-str.length()) );
+		
+		bbChar *dst=rep->data;
+		
+		for( int i=0;; ){
+		
+			int i2=find( str,i );
+			if( i2==-1 ){
+				t_memcpy( dst,data()+i,(length()-i) );
+				break;
+			}
+			
+			t_memcpy( dst,data()+i,(i2-i) );
+			dst+=(i2-i);
+			
+			t_memcpy( dst,repl.data(),repl.length() );
+			dst+=repl.length();
+			
+			i=i2+str.length();
+		}
+		return rep;
+	}
+	
+	bbArray<bbString> *split( bbString sep )const;
+	
+	bbString join( bbArray<bbString> *bits )const;
+	
+	int compare( const bbString &t )const{
+		int len=length()<t.length() ? length() : t.length();
+		for( int i=0;i<len;++i ){
+			if( int n=data()[i]-t.data()[i] ) return n;
+		}
+		return length()-t.length();
+	}
+	
+	bool operator<( const bbString &t )const{
+		return compare( t )<0;
+	}
+	
+	bool operator>( const bbString &t )const{
+		return compare( t )>0;
+	}
+	
+	bool operator<=( const bbString &t )const{
+		return compare( t )<=0;
+	}
+	
+	bool operator>=( const bbString &t )const{
+		return compare( t )>=0;
+	}
+	
+	bool operator==( const bbString &t )const{
+		return compare( t )==0;
+	}
+	
+	bool operator!=( const bbString &t )const{
+		return compare( t )!=0;
+	}
+	
+	operator bbBool()const{
+		return length();
+	}
+	
+	operator bbInt()const{
+		return std::atoi( c_str() );
+	}
+	
+	operator bbByte()const{
+		return operator bbInt() & 0xff;
+	}
+	
+	operator bbUByte()const{
+		return operator bbInt() & 0xffu;
+	}
+	
+	operator bbShort()const{
+		return operator bbInt() & 0xffff;
+	}
+	
+	operator bbUShort()const{
+		return operator bbInt() & 0xffffu;
+	}
+	
+	operator bbUInt()const{
+		bbUInt n;
+		sscanf( c_str(),"%u",&n );
+		return n;
+	}
+	
+	operator bbLong()const{
+		bbLong n;
+		sscanf( c_str(),"%lld",&n );
+		return n;
+	}
+	
+	operator bbULong()const{
+		bbULong n;
+		sscanf( c_str(),"%llu",&n );
+		return n;
+	}
+	
+	operator float()const{
+		return std::atof( c_str() );
+	}
+	
+	operator double()const{
+		return std::atof( c_str() );
+	}
+	
+	int utf8Length()const;
+	
+	int toUtf8( void *buf,int size )const;
+	
+	inline bbCString toCString()const;
+	
+	static bbString fromChar( int chr );
+	
+	static bbString fromCString( const void *data );
+	
+	static bbString fromWString( const void *data );
+	
+	static bbString fromUtf8String( const void *data );
+
+	static bbString fromUtf8String( const void *data,int size );
+
+	static bbString fromUtf8( const void *data,int size ){
+		return fromUtf8String( data,size );
+	}
+
+	
+	static bbString fromTString( const void *data ){
+#if _WIN32
+		return fromCString( data );
+#else
+		return fromUtf8String( data );
+#endif
+	}
+
+};
+
+class bbCString{
+	bbString _str;
+	mutable char *_data=nullptr;
+	
+	public:
+	
+	bbCString( const bbString &str ):_str( str ){
+	}
+	
+	bbCString( const bbCString &str ):_str( str._str ){
+	}
+	
+	~bbCString(){
+		free( _data );
+	}
+	
+	bbCString &operator=( const bbCString &str ){
+		free( _data );
+		_data=nullptr;
+		_str=str._str;
+		return *this;
+	}
+	
+	char *data()const{
+		if( _data ) return _data;
+		_data=(char*)malloc( _str.length()+1 );
+		for( int i=0;i<_str.length();++i ) _data[i]=_str.data()[i];
+		_data[_str.length()]=0;
+		return _data;
+	}
+	
+	operator bbString()const{
+		return _str;
+	}
+	
+	operator char*()const{
+		return data();
+	}
+};
+
+class bbWString{
+	bbString _str;
+	mutable wchar_t *_data=nullptr;
+	
+	public:
+	
+	bbWString( const bbString &str ):_str( str ){
+	}
+	
+	bbWString( const bbWString &str ):_str( str._str ){
+	}
+	
+	~bbWString(){
+		free( _data );
+	}
+	
+	bbWString &operator=( const bbWString &str ){
+		free( _data );
+		_data=nullptr;
+		_str=str._str;
+		return *this;
+	}
+	
+	wchar_t *data()const{
+		if( _data ) return _data;
+		_data=(wchar_t*)malloc( (_str.length()+1)*sizeof( wchar_t ) );
+		for( int i=0;i<_str.length();++i ) _data[i]=_str.data()[i];
+		_data[_str.length()]=0;
+		return _data;
+	}
+	
+	operator bbString()const{
+		return _str;
+	}
+	
+	operator wchar_t*()const{
+		return data();
+	}
+};
+
+class bbUtf8String{
+	bbString _str;
+	mutable char *_data=nullptr;
+	
+	public:
+	
+	bbUtf8String( const bbString &str ):_str( str ){
+	}
+	
+	bbUtf8String( const bbUtf8String &str ):_str( str._str ){
+	}
+	
+	~bbUtf8String(){
+		free( _data );
+	}
+	
+	bbUtf8String &operator=( const bbUtf8String &str ){
+		free( _data );
+		_data=nullptr;
+		_str=str._str;
+		return *this;
+	}
+	
+	char *data()const{
+		if( _data ) return _data;
+		int n=_str.utf8Length()+1;
+		_data=(char*)malloc( n );
+		_str.toUtf8( _data,n );
+		return _data;
+	}
+
+	operator bbString()const{
+		return _str;
+	}
+	
+	operator char*()const{
+		return data();
+	}
+};
+
+#if _WIN32
+typedef bbCString bbTString;
+#else
+typedef bbUtf8String bbTString;
+#endif
+
+bbCString bbString::toCString()const{
+	return bbCString( *this );
+}
+
+template<class C> bbString operator+( const C *str,const bbString &str2 ){
+	return bbString( str )+str2;
+}
+
+template<class C> bbString BB_T( const C *p ){
+	return bbString( p );
+}
+
+inline void bbGCMark( const bbString &t ){
+}
+
+#endif

+ 2 - 0
modules/monkey/native/bbtypes.cpp

@@ -0,0 +1,2 @@
+
+#include "bbtypes.h"

+ 25 - 0
modules/monkey/native/bbtypes.h

@@ -0,0 +1,25 @@
+
+#ifndef BB_TYPES_H
+#define BB_TYPES_H
+
+#include "bbstd.h"
+
+typedef bool bbBool;
+typedef signed char bbByte;
+typedef unsigned char bbUByte;
+typedef signed short bbShort;
+typedef unsigned short bbUShort;
+typedef signed int bbInt;
+typedef unsigned int bbUInt;
+typedef signed long long bbLong;
+typedef unsigned long long bbULong;
+typedef float bbFloat;
+typedef double bbDouble;
+
+typedef unsigned short bbChar;
+
+class bbString;
+template<class T> class bbFunction;
+template<class T,int D> class bbArray;
+
+#endif

+ 50 - 0
modules/monkey/native/bbvariant.h

@@ -0,0 +1,50 @@
+
+#ifndef BB_VARIANT_H
+#define BB_VARIANT_H
+
+class bbVariant{
+
+	struct RepBase{
+		virtual ~RepBase(){
+		}
+	};
+	
+	template<class T> struct Rep : public RepBase{
+		T t;
+	};
+	
+	RepBase *_rep;
+	
+	void retain()const{
+		++_rep->refs;
+	}
+	
+	void release(){
+		if( !--_rep->refs ) {}//delete rep;
+	}
+	
+	public:
+	
+	template<class T> bbVariant( const T &t ):_rep( new Rep<T>( t ) ){
+		retain();
+	}
+	
+	bbVariant( const bbVariant &t ):_rep( t._rep ){
+		retain();
+	}
+	
+	bbVariant &operator=( const bbVariant &t ){
+		t.retain();
+		release();
+		_rep=t._rep;
+		return *this;
+	}
+	
+	template<class T> T get()const{
+		Rep<T> *p=dynamic_cast<Rep<T>*>( _rep );
+		return p->t;
+	}
+};
+
+
+#endif

+ 168 - 0
modules/monkey/types.monkey2

@@ -0,0 +1,168 @@
+
+Namespace monkey
+
+Extern
+
+Struct CChar="char"
+End
+
+Struct WChar="wchar_t"
+End
+
+Struct Utf8Char="char"
+End
+
+Struct CString="bbCString"
+End
+
+Struct WString="bbWString"
+End
+
+Struct Utf8String="bbUtf8String"
+End
+
+Interface INumeric
+End
+
+Interface IIntegral Extends INumeric
+End
+
+Interface IReal Extends INumeric
+End
+
+#rem monkeydoc Primitive bool type
+#end
+Struct @Bool Implements IIntegral ="bbBool"
+End
+
+#rem monkeydoc Primitive byte type
+#end
+Struct @Byte Implements IIntegral ="bbByte"
+End
+
+#rem monkeydoc Primitive unsigned byte type
+#end
+Struct @UByte Implements IIntegral ="bbUByte"
+End
+
+#rem monkeydoc Primitive short type
+#end
+Struct @Short Implements IIntegral ="bbShort"
+End
+
+#rem monkeydoc Primitive unsigned short type
+#end
+Struct @UShort Implements IIntegral ="bbUShort"
+End
+
+#rem monkeydoc Primitive int type
+#end
+Struct @Int Implements IIntegral ="bbInt"
+End
+
+#rem monkeydoc Primitive unsigned int type
+#end
+Struct @UInt Implements IIntegral ="bbUInt"
+End
+
+#rem monkeydoc Primitive long type
+#end
+Struct @Long Implements IIntegral ="bbLong"
+End
+
+#rem monkeydoc Primitive unsigned long type
+#end
+Struct @ULong Implements IIntegral ="bbULong"
+End
+
+#rem monkeydoc Primitive float type
+#end
+Struct @Float Implements IReal ="bbFloat"
+End
+
+#rem monkeydoc Primitive double type
+#end
+Struct @Double Implements IReal ="bbDouble"
+End
+
+#rem monkeydoc Primitive string type
+#end
+Struct @String ="bbString"
+
+	Property Length:Int()="length"
+	
+	Property Utf8Length:Int()="utf8Length"
+	
+	Method Find:Int( str:String,from:Int=0 )="find"
+	
+	Method FindLast:Int( str:String,from:Int=0 )="findLast"
+	
+	Method Contains:Bool( str:String )="contains"
+	
+	Method StartsWith:Bool( str:String )="startsWith"
+	
+	Method EndsWith:Bool( str:String )="endsWith"
+	
+	Method Slice:String( from:Int )="slice"
+	
+	Method Slice:String( from:Int,term:Int )="slice"
+	
+	Method Left:String( count:Int )="left"
+	
+	Method Right:String( count:Int )="right"
+	
+	Method Mid:String( from:Int,count:Int )="mid"
+	
+	Method ToUpper:String()="toUpper"
+	
+	Method ToLower:String()="toLower"
+	
+	Method Capitalize:String()="capitalize"
+	
+	Method Trim:String()="trim"
+	
+	Method Replace:String( find:String,replace:String )="replace"
+	
+	Method Split:String[]( separator:String )="split"
+	
+	Method Join:String( bits:String[] )="join"
+	
+	Method ToUtf8:Int( buf:Void Ptr,size:Int )="toUtf8"
+	
+	Method ToCString:CString()="bbString::toCString"
+	
+	Function FromChar:String( chr:Int )="bbString::fromChar"
+	
+	Function FromCString:String( data:Void Ptr )="bbString::fromCString"
+	
+	Function FromWString:String( data:Void Ptr )="bbString::fromWString"
+	
+	Function FromUtf8String:String( data:Void Ptr )="bbString::fromUtf8String"
+	
+	Function FromTString:String( data:Void Ptr )="bbString::fromTString"
+	
+	Function FromUtf8:String( data:Void Ptr,size:Int )="bbString::fromUtf8"
+	
+End
+
+Struct @Array<T>
+
+	Property Data:T Ptr()="data"
+	
+	Property Length:Int()="length"
+	
+	Method Get:T( index:Int )="get"
+	
+	Method Slice:T[]( from:Int )="slice"
+	
+	Method Slice:T[]( from:Int,term:Int )="slice" 
+	
+	Method CopyTo( dstArray:T[],srcOffset:Int,dstOffset:Int,count:Int )="copyTo"
+
+End
+
+Class @Object="bbObject"
+
+	Method typeName:CChar Ptr()="typeName"
+
+End

+ 20 - 0
modules/sdl2/SDL/COPYING.txt

@@ -0,0 +1,20 @@
+
+Simple DirectMedia Layer
+Copyright (C) 1997-2015 Sam Lantinga <[email protected]>
+  
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+  
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required. 
+2. Altered source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+

+ 53 - 0
modules/sdl2/SDL/CREDITS.txt

@@ -0,0 +1,53 @@
+
+Simple DirectMedia Layer CREDITS
+Thanks to everyone who made this possible, including:
+
+* Cliff Matthews, for giving me a reason to start this project. :)
+ -- Executor rocks!  *grin*
+
+* Ryan Gordon for helping everybody out and keeping the dream alive. :)
+
+* Gabriel Jacobo for his work on the Android port and generally helping out all around.
+ 
+* Philipp Wiesemann for his attention to detail reviewing the entire SDL code base and proposes patches.
+
+* Andreas Schiffler for his dedication to unit tests, Visual Studio projects, and managing the Google Summer of Code.
+
+* Mike Sartain for incorporating SDL into Team Fortress 2 and cheering me on at Valve.
+
+* Alfred Reynolds for the game controller API and general (in)sanity
+
+* Jørgen Tjernø for numerous magical Mac OS X fixes.
+
+* Pierre-Loup Griffais for his deep knowledge of OpenGL drivers.
+ 
+* Julian Winter for the SDL 2.0 website.
+
+* Sheena Smith for many months of great work on the SDL wiki creating the API documentation and style guides.
+
+* Paul Hunkin for his port of SDL to Android during the Google Summer of Code 2010.
+
+* Eli Gottlieb for his work on shaped windows during the Google Summer of Code 2010.
+
+* Jim Grandpre for his work on multi-touch and gesture recognition during
+  the Google Summer of Code 2010.
+
+* Edgar "bobbens" Simo for his force feedback API development during the
+  Google Summer of Code 2008.
+
+* Aaron Wishnick for his work on audio resampling and pitch shifting during
+  the Google Summer of Code 2008.
+
+* Holmes Futrell for his port of SDL to the iPhone and iPod Touch during the
+  Google Summer of Code 2008.
+
+* Jon Atkins for SDL_image, SDL_mixer and SDL_net documentation.
+
+* Everybody at Loki Software, Inc. for their great contributions!
+
+ And a big hand to everyone else who has contributed over the years.
+
+THANKS! :)
+
+  -- Sam Lantinga			<[email protected]>
+

+ 8 - 0
modules/sdl2/SDL/TWEAKS.txt

@@ -0,0 +1,8 @@
+
+Added acceptsFirstMouse to SDLView in SDL_cocoawindows.m...
+
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
+{
+    return YES;
+}
+

+ 132 - 0
modules/sdl2/SDL/include/SDL.h

@@ -0,0 +1,132 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ *  \file SDL.h
+ *
+ *  Main include header for the SDL library
+ */
+
+
+#ifndef _SDL_H
+#define _SDL_H
+
+#include "SDL_main.h"
+#include "SDL_stdinc.h"
+#include "SDL_assert.h"
+#include "SDL_atomic.h"
+#include "SDL_audio.h"
+#include "SDL_clipboard.h"
+#include "SDL_cpuinfo.h"
+#include "SDL_endian.h"
+#include "SDL_error.h"
+#include "SDL_events.h"
+#include "SDL_filesystem.h"
+#include "SDL_joystick.h"
+#include "SDL_gamecontroller.h"
+#include "SDL_haptic.h"
+#include "SDL_hints.h"
+#include "SDL_loadso.h"
+#include "SDL_log.h"
+#include "SDL_messagebox.h"
+#include "SDL_mutex.h"
+#include "SDL_power.h"
+#include "SDL_render.h"
+#include "SDL_rwops.h"
+#include "SDL_system.h"
+#include "SDL_thread.h"
+#include "SDL_timer.h"
+#include "SDL_version.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* As of version 0.5, SDL is loaded dynamically into the application */
+
+/**
+ *  \name SDL_INIT_*
+ *
+ *  These are the flags which may be passed to SDL_Init().  You should
+ *  specify the subsystems which you will be using in your application.
+ */
+/* @{ */
+#define SDL_INIT_TIMER          0x00000001
+#define SDL_INIT_AUDIO          0x00000010
+#define SDL_INIT_VIDEO          0x00000020  /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
+#define SDL_INIT_JOYSTICK       0x00000200  /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
+#define SDL_INIT_HAPTIC         0x00001000
+#define SDL_INIT_GAMECONTROLLER 0x00002000  /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
+#define SDL_INIT_EVENTS         0x00004000
+#define SDL_INIT_NOPARACHUTE    0x00100000  /**< compatibility; this flag is ignored. */
+#define SDL_INIT_EVERYTHING ( \
+                SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
+                SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \
+            )
+/* @} */
+
+/**
+ *  This function initializes  the subsystems specified by \c flags
+ */
+extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags);
+
+/**
+ *  This function initializes specific SDL subsystems
+ *
+ *  Subsystem initialization is ref-counted, you must call
+ *  SDL_QuitSubSystem for each SDL_InitSubSystem to correctly
+ *  shutdown a subsystem manually (or call SDL_Quit to force shutdown).
+ *  If a subsystem is already loaded then this call will
+ *  increase the ref-count and return.
+ */
+extern DECLSPEC int SDLCALL SDL_InitSubSystem(Uint32 flags);
+
+/**
+ *  This function cleans up specific SDL subsystems
+ */
+extern DECLSPEC void SDLCALL SDL_QuitSubSystem(Uint32 flags);
+
+/**
+ *  This function returns a mask of the specified subsystems which have
+ *  previously been initialized.
+ *
+ *  If \c flags is 0, it returns a mask of all initialized subsystems.
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_WasInit(Uint32 flags);
+
+/**
+ *  This function cleans up all initialized subsystems. You should
+ *  call it upon all exit conditions.
+ */
+extern DECLSPEC void SDLCALL SDL_Quit(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_H */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 289 - 0
modules/sdl2/SDL/include/SDL_assert.h

@@ -0,0 +1,289 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _SDL_assert_h
+#define _SDL_assert_h
+
+#include "SDL_config.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SDL_ASSERT_LEVEL
+#ifdef SDL_DEFAULT_ASSERT_LEVEL
+#define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL
+#elif defined(_DEBUG) || defined(DEBUG) || \
+      (defined(__GNUC__) && !defined(__OPTIMIZE__))
+#define SDL_ASSERT_LEVEL 2
+#else
+#define SDL_ASSERT_LEVEL 1
+#endif
+#endif /* SDL_ASSERT_LEVEL */
+
+/*
+These are macros and not first class functions so that the debugger breaks
+on the assertion line and not in some random guts of SDL, and so each
+assert can have unique static variables associated with it.
+*/
+
+#if defined(_MSC_VER)
+/* Don't include intrin.h here because it contains C++ code */
+    extern void __cdecl __debugbreak(void);
+    #define SDL_TriggerBreakpoint() __debugbreak()
+#elif (!defined(__NACL__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
+    #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
+#elif defined(HAVE_SIGNAL_H)
+    #include <signal.h>
+    #define SDL_TriggerBreakpoint() raise(SIGTRAP)
+#else
+    /* How do we trigger breakpoints on this platform? */
+    #define SDL_TriggerBreakpoint()
+#endif
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */
+#   define SDL_FUNCTION __func__
+#elif ((__GNUC__ >= 2) || defined(_MSC_VER))
+#   define SDL_FUNCTION __FUNCTION__
+#else
+#   define SDL_FUNCTION "???"
+#endif
+#define SDL_FILE    __FILE__
+#define SDL_LINE    __LINE__
+
+/*
+sizeof (x) makes the compiler still parse the expression even without
+assertions enabled, so the code is always checked at compile time, but
+doesn't actually generate code for it, so there are no side effects or
+expensive checks at run time, just the constant size of what x WOULD be,
+which presumably gets optimized out as unused.
+This also solves the problem of...
+
+    int somevalue = blah();
+    SDL_assert(somevalue == 1);
+
+...which would cause compiles to complain that somevalue is unused if we
+disable assertions.
+*/
+
+/* "while (0,0)" fools Microsoft's compiler's /W4 warning level into thinking
+    this condition isn't constant. And looks like an owl's face! */
+#ifdef _MSC_VER  /* stupid /W4 warnings. */
+#define SDL_NULL_WHILE_LOOP_CONDITION (0,0)
+#else
+#define SDL_NULL_WHILE_LOOP_CONDITION (0)
+#endif
+
+#define SDL_disabled_assert(condition) \
+    do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION)
+
+typedef enum
+{
+    SDL_ASSERTION_RETRY,  /**< Retry the assert immediately. */
+    SDL_ASSERTION_BREAK,  /**< Make the debugger trigger a breakpoint. */
+    SDL_ASSERTION_ABORT,  /**< Terminate the program. */
+    SDL_ASSERTION_IGNORE,  /**< Ignore the assert. */
+    SDL_ASSERTION_ALWAYS_IGNORE  /**< Ignore the assert from now on. */
+} SDL_AssertState;
+
+typedef struct SDL_AssertData
+{
+    int always_ignore;
+    unsigned int trigger_count;
+    const char *condition;
+    const char *filename;
+    int linenum;
+    const char *function;
+    const struct SDL_AssertData *next;
+} SDL_AssertData;
+
+#if (SDL_ASSERT_LEVEL > 0)
+
+/* Never call this directly. Use the SDL_assert* macros. */
+extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *,
+                                                             const char *,
+                                                             const char *, int)
+#if defined(__clang__)
+#if __has_feature(attribute_analyzer_noreturn)
+/* this tells Clang's static analysis that we're a custom assert function,
+   and that the analyzer should assume the condition was always true past this
+   SDL_assert test. */
+   __attribute__((analyzer_noreturn))
+#endif
+#endif
+;
+
+/* the do {} while(0) avoids dangling else problems:
+    if (x) SDL_assert(y); else blah();
+       ... without the do/while, the "else" could attach to this macro's "if".
+   We try to handle just the minimum we need here in a macro...the loop,
+   the static vars, and break points. The heavy lifting is handled in
+   SDL_ReportAssertion(), in SDL_assert.c.
+*/
+#define SDL_enabled_assert(condition) \
+    do { \
+        while ( !(condition) ) { \
+            static struct SDL_AssertData sdl_assert_data = { \
+                0, 0, #condition, 0, 0, 0, 0 \
+            }; \
+            const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
+            if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
+                continue; /* go again. */ \
+            } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \
+                SDL_TriggerBreakpoint(); \
+            } \
+            break; /* not retrying. */ \
+        } \
+    } while (SDL_NULL_WHILE_LOOP_CONDITION)
+
+#endif  /* enabled assertions support code */
+
+/* Enable various levels of assertions. */
+#if SDL_ASSERT_LEVEL == 0   /* assertions disabled */
+#   define SDL_assert(condition) SDL_disabled_assert(condition)
+#   define SDL_assert_release(condition) SDL_disabled_assert(condition)
+#   define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 1  /* release settings. */
+#   define SDL_assert(condition) SDL_disabled_assert(condition)
+#   define SDL_assert_release(condition) SDL_enabled_assert(condition)
+#   define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 2  /* normal settings. */
+#   define SDL_assert(condition) SDL_enabled_assert(condition)
+#   define SDL_assert_release(condition) SDL_enabled_assert(condition)
+#   define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 3  /* paranoid settings. */
+#   define SDL_assert(condition) SDL_enabled_assert(condition)
+#   define SDL_assert_release(condition) SDL_enabled_assert(condition)
+#   define SDL_assert_paranoid(condition) SDL_enabled_assert(condition)
+#else
+#   error Unknown assertion level.
+#endif
+
+/* this assertion is never disabled at any level. */
+#define SDL_assert_always(condition) SDL_enabled_assert(condition)
+
+
+typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)(
+                                 const SDL_AssertData* data, void* userdata);
+
+/**
+ *  \brief Set an application-defined assertion handler.
+ *
+ *  This allows an app to show its own assertion UI and/or force the
+ *  response to an assertion failure. If the app doesn't provide this, SDL
+ *  will try to do the right thing, popping up a system-specific GUI dialog,
+ *  and probably minimizing any fullscreen windows.
+ *
+ *  This callback may fire from any thread, but it runs wrapped in a mutex, so
+ *  it will only fire from one thread at a time.
+ *
+ *  Setting the callback to NULL restores SDL's original internal handler.
+ *
+ *  This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
+ *
+ *  \return SDL_AssertState value of how to handle the assertion failure.
+ *
+ *  \param handler Callback function, called when an assertion fails.
+ *  \param userdata A pointer passed to the callback as-is.
+ */
+extern DECLSPEC void SDLCALL SDL_SetAssertionHandler(
+                                            SDL_AssertionHandler handler,
+                                            void *userdata);
+
+/**
+ *  \brief Get the default assertion handler.
+ *
+ *  This returns the function pointer that is called by default when an
+ *   assertion is triggered. This is an internal function provided by SDL,
+ *   that is used for assertions when SDL_SetAssertionHandler() hasn't been
+ *   used to provide a different function.
+ *
+ *  \return The default SDL_AssertionHandler that is called when an assert triggers.
+ */
+extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void);
+
+/**
+ *  \brief Get the current assertion handler.
+ *
+ *  This returns the function pointer that is called when an assertion is
+ *   triggered. This is either the value last passed to
+ *   SDL_SetAssertionHandler(), or if no application-specified function is
+ *   set, is equivalent to calling SDL_GetDefaultAssertionHandler().
+ *
+ *   \param puserdata Pointer to a void*, which will store the "userdata"
+ *                    pointer that was passed to SDL_SetAssertionHandler().
+ *                    This value will always be NULL for the default handler.
+ *                    If you don't care about this data, it is safe to pass
+ *                    a NULL pointer to this function to ignore it.
+ *  \return The SDL_AssertionHandler that is called when an assert triggers.
+ */
+extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata);
+
+/**
+ *  \brief Get a list of all assertion failures.
+ *
+ *  Get all assertions triggered since last call to SDL_ResetAssertionReport(),
+ *  or the start of the program.
+ *
+ *  The proper way to examine this data looks something like this:
+ *
+ *  <code>
+ *  const SDL_AssertData *item = SDL_GetAssertionReport();
+ *  while (item) {
+ *      printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n",
+ *             item->condition, item->function, item->filename,
+ *             item->linenum, item->trigger_count,
+ *             item->always_ignore ? "yes" : "no");
+ *      item = item->next;
+ *  }
+ *  </code>
+ *
+ *  \return List of all assertions.
+ *  \sa SDL_ResetAssertionReport
+ */
+extern DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void);
+
+/**
+ *  \brief Reset the list of all assertion failures.
+ *
+ *  Reset list of all assertions triggered.
+ *
+ *  \sa SDL_GetAssertionReport
+ */
+extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
+
+
+/* these had wrong naming conventions until 2.0.4. Please update your app! */
+#define SDL_assert_state SDL_AssertState
+#define SDL_assert_data SDL_AssertData
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_assert_h */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 268 - 0
modules/sdl2/SDL/include/SDL_atomic.h

@@ -0,0 +1,268 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_atomic.h
+ *
+ * Atomic operations.
+ *
+ * IMPORTANT:
+ * If you are not an expert in concurrent lockless programming, you should
+ * only be using the atomic lock and reference counting functions in this
+ * file.  In all other cases you should be protecting your data structures
+ * with full mutexes.
+ *
+ * The list of "safe" functions to use are:
+ *  SDL_AtomicLock()
+ *  SDL_AtomicUnlock()
+ *  SDL_AtomicIncRef()
+ *  SDL_AtomicDecRef()
+ *
+ * Seriously, here be dragons!
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * You can find out a little more about lockless programming and the
+ * subtle issues that can arise here:
+ * http://msdn.microsoft.com/en-us/library/ee418650%28v=vs.85%29.aspx
+ *
+ * There's also lots of good information here:
+ * http://www.1024cores.net/home/lock-free-algorithms
+ * http://preshing.com/
+ *
+ * These operations may or may not actually be implemented using
+ * processor specific atomic operations. When possible they are
+ * implemented as true processor specific atomic operations. When that
+ * is not possible the are implemented using locks that *do* use the
+ * available atomic operations.
+ *
+ * All of the atomic operations that modify memory are full memory barriers.
+ */
+
+#ifndef _SDL_atomic_h_
+#define _SDL_atomic_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_platform.h"
+
+#include "begin_code.h"
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name SDL AtomicLock
+ *
+ * The atomic locks are efficient spinlocks using CPU instructions,
+ * but are vulnerable to starvation and can spin forever if a thread
+ * holding a lock has been terminated.  For this reason you should
+ * minimize the code executed inside an atomic lock and never do
+ * expensive things like API or system calls while holding them.
+ *
+ * The atomic locks are not safe to lock recursively.
+ *
+ * Porting Note:
+ * The spin lock functions and type are required and can not be
+ * emulated because they are used in the atomic emulation code.
+ */
+/* @{ */
+
+typedef int SDL_SpinLock;
+
+/**
+ * \brief Try to lock a spin lock by setting it to a non-zero value.
+ *
+ * \param lock Points to the lock.
+ *
+ * \return SDL_TRUE if the lock succeeded, SDL_FALSE if the lock is already held.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock);
+
+/**
+ * \brief Lock a spin lock by setting it to a non-zero value.
+ *
+ * \param lock Points to the lock.
+ */
+extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock);
+
+/**
+ * \brief Unlock a spin lock by setting it to 0. Always returns immediately
+ *
+ * \param lock Points to the lock.
+ */
+extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock);
+
+/* @} *//* SDL AtomicLock */
+
+
+/**
+ * The compiler barrier prevents the compiler from reordering
+ * reads and writes to globally visible variables across the call.
+ */
+#if defined(_MSC_VER) && (_MSC_VER > 1200)
+void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadWriteBarrier)
+#define SDL_CompilerBarrier()   _ReadWriteBarrier()
+#elif (defined(__GNUC__) && !defined(__EMSCRIPTEN__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
+/* This is correct for all CPUs when using GCC or Solaris Studio 12.1+. */
+#define SDL_CompilerBarrier()   __asm__ __volatile__ ("" : : : "memory")
+#else
+#define SDL_CompilerBarrier()   \
+{ SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); }
+#endif
+
+/**
+ * Memory barriers are designed to prevent reads and writes from being
+ * reordered by the compiler and being seen out of order on multi-core CPUs.
+ *
+ * A typical pattern would be for thread A to write some data and a flag,
+ * and for thread B to read the flag and get the data. In this case you
+ * would insert a release barrier between writing the data and the flag,
+ * guaranteeing that the data write completes no later than the flag is
+ * written, and you would insert an acquire barrier between reading the
+ * flag and reading the data, to ensure that all the reads associated
+ * with the flag have completed.
+ *
+ * In this pattern you should always see a release barrier paired with
+ * an acquire barrier and you should gate the data reads/writes with a
+ * single flag variable.
+ *
+ * For more information on these semantics, take a look at the blog post:
+ * http://preshing.com/20120913/acquire-and-release-semantics
+ */
+#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+#define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("lwsync" : : : "memory")
+#define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("lwsync" : : : "memory")
+#elif defined(__GNUC__) && defined(__arm__)
+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
+#define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("dmb ish" : : : "memory")
+#define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("dmb ish" : : : "memory")
+#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
+#ifdef __thumb__
+/* The mcr instruction isn't available in thumb mode, use real functions */
+extern DECLSPEC void SDLCALL SDL_MemoryBarrierRelease();
+extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquire();
+#else
+#define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#endif /* __thumb__ */
+#else
+#define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("" : : : "memory")
+#define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("" : : : "memory")
+#endif /* __GNUC__ && __arm__ */
+#else
+#if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
+/* This is correct for all CPUs on Solaris when using Solaris Studio 12.1+. */
+#include <mbarrier.h>
+#define SDL_MemoryBarrierRelease()  __machine_rel_barrier()
+#define SDL_MemoryBarrierAcquire()  __machine_acq_barrier()
+#else
+/* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */
+#define SDL_MemoryBarrierRelease()  SDL_CompilerBarrier()
+#define SDL_MemoryBarrierAcquire()  SDL_CompilerBarrier()
+#endif
+#endif
+
+/**
+ * \brief A type representing an atomic integer value.  It is a struct
+ *        so people don't accidentally use numeric operations on it.
+ */
+typedef struct { int value; } SDL_atomic_t;
+
+/**
+ * \brief Set an atomic variable to a new value if it is currently an old value.
+ *
+ * \return SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise.
+ *
+ * \note If you don't know what this function is for, you shouldn't use it!
+*/
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval);
+
+/**
+ * \brief Set an atomic variable to a value.
+ *
+ * \return The previous value of the atomic variable.
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicSet(SDL_atomic_t *a, int v);
+
+/**
+ * \brief Get the value of an atomic variable
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicGet(SDL_atomic_t *a);
+
+/**
+ * \brief Add to an atomic variable.
+ *
+ * \return The previous value of the atomic variable.
+ *
+ * \note This same style can be used for any number operation
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicAdd(SDL_atomic_t *a, int v);
+
+/**
+ * \brief Increment an atomic variable used as a reference count.
+ */
+#ifndef SDL_AtomicIncRef
+#define SDL_AtomicIncRef(a)    SDL_AtomicAdd(a, 1)
+#endif
+
+/**
+ * \brief Decrement an atomic variable used as a reference count.
+ *
+ * \return SDL_TRUE if the variable reached zero after decrementing,
+ *         SDL_FALSE otherwise
+ */
+#ifndef SDL_AtomicDecRef
+#define SDL_AtomicDecRef(a)    (SDL_AtomicAdd(a, -1) == 1)
+#endif
+
+/**
+ * \brief Set a pointer to a new value if it is currently an old value.
+ *
+ * \return SDL_TRUE if the pointer was set, SDL_FALSE otherwise.
+ *
+ * \note If you don't know what this function is for, you shouldn't use it!
+*/
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval);
+
+/**
+ * \brief Set a pointer to a value atomically.
+ *
+ * \return The previous value of the pointer.
+ */
+extern DECLSPEC void* SDLCALL SDL_AtomicSetPtr(void **a, void* v);
+
+/**
+ * \brief Get the value of a pointer atomically.
+ */
+extern DECLSPEC void* SDLCALL SDL_AtomicGetPtr(void **a);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+
+#include "close_code.h"
+
+#endif /* _SDL_atomic_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 605 - 0
modules/sdl2/SDL/include/SDL_audio.h

@@ -0,0 +1,605 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ *  \file SDL_audio.h
+ *
+ *  Access to the raw audio mixing buffer for the SDL library.
+ */
+
+#ifndef _SDL_audio_h
+#define _SDL_audio_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_endian.h"
+#include "SDL_mutex.h"
+#include "SDL_thread.h"
+#include "SDL_rwops.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  \brief Audio format flags.
+ *
+ *  These are what the 16 bits in SDL_AudioFormat currently mean...
+ *  (Unspecified bits are always zero).
+ *
+ *  \verbatim
+    ++-----------------------sample is signed if set
+    ||
+    ||       ++-----------sample is bigendian if set
+    ||       ||
+    ||       ||          ++---sample is float if set
+    ||       ||          ||
+    ||       ||          || +---sample bit size---+
+    ||       ||          || |                     |
+    15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+    \endverbatim
+ *
+ *  There are macros in SDL 2.0 and later to query these bits.
+ */
+typedef Uint16 SDL_AudioFormat;
+
+/**
+ *  \name Audio flags
+ */
+/* @{ */
+
+#define SDL_AUDIO_MASK_BITSIZE       (0xFF)
+#define SDL_AUDIO_MASK_DATATYPE      (1<<8)
+#define SDL_AUDIO_MASK_ENDIAN        (1<<12)
+#define SDL_AUDIO_MASK_SIGNED        (1<<15)
+#define SDL_AUDIO_BITSIZE(x)         (x & SDL_AUDIO_MASK_BITSIZE)
+#define SDL_AUDIO_ISFLOAT(x)         (x & SDL_AUDIO_MASK_DATATYPE)
+#define SDL_AUDIO_ISBIGENDIAN(x)     (x & SDL_AUDIO_MASK_ENDIAN)
+#define SDL_AUDIO_ISSIGNED(x)        (x & SDL_AUDIO_MASK_SIGNED)
+#define SDL_AUDIO_ISINT(x)           (!SDL_AUDIO_ISFLOAT(x))
+#define SDL_AUDIO_ISLITTLEENDIAN(x)  (!SDL_AUDIO_ISBIGENDIAN(x))
+#define SDL_AUDIO_ISUNSIGNED(x)      (!SDL_AUDIO_ISSIGNED(x))
+
+/**
+ *  \name Audio format flags
+ *
+ *  Defaults to LSB byte order.
+ */
+/* @{ */
+#define AUDIO_U8        0x0008  /**< Unsigned 8-bit samples */
+#define AUDIO_S8        0x8008  /**< Signed 8-bit samples */
+#define AUDIO_U16LSB    0x0010  /**< Unsigned 16-bit samples */
+#define AUDIO_S16LSB    0x8010  /**< Signed 16-bit samples */
+#define AUDIO_U16MSB    0x1010  /**< As above, but big-endian byte order */
+#define AUDIO_S16MSB    0x9010  /**< As above, but big-endian byte order */
+#define AUDIO_U16       AUDIO_U16LSB
+#define AUDIO_S16       AUDIO_S16LSB
+/* @} */
+
+/**
+ *  \name int32 support
+ */
+/* @{ */
+#define AUDIO_S32LSB    0x8020  /**< 32-bit integer samples */
+#define AUDIO_S32MSB    0x9020  /**< As above, but big-endian byte order */
+#define AUDIO_S32       AUDIO_S32LSB
+/* @} */
+
+/**
+ *  \name float32 support
+ */
+/* @{ */
+#define AUDIO_F32LSB    0x8120  /**< 32-bit floating point samples */
+#define AUDIO_F32MSB    0x9120  /**< As above, but big-endian byte order */
+#define AUDIO_F32       AUDIO_F32LSB
+/* @} */
+
+/**
+ *  \name Native audio byte ordering
+ */
+/* @{ */
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define AUDIO_U16SYS    AUDIO_U16LSB
+#define AUDIO_S16SYS    AUDIO_S16LSB
+#define AUDIO_S32SYS    AUDIO_S32LSB
+#define AUDIO_F32SYS    AUDIO_F32LSB
+#else
+#define AUDIO_U16SYS    AUDIO_U16MSB
+#define AUDIO_S16SYS    AUDIO_S16MSB
+#define AUDIO_S32SYS    AUDIO_S32MSB
+#define AUDIO_F32SYS    AUDIO_F32MSB
+#endif
+/* @} */
+
+/**
+ *  \name Allow change flags
+ *
+ *  Which audio format changes are allowed when opening a device.
+ */
+/* @{ */
+#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE    0x00000001
+#define SDL_AUDIO_ALLOW_FORMAT_CHANGE       0x00000002
+#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE     0x00000004
+#define SDL_AUDIO_ALLOW_ANY_CHANGE          (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE)
+/* @} */
+
+/* @} *//* Audio flags */
+
+/**
+ *  This function is called when the audio device needs more data.
+ *
+ *  \param userdata An application-specific parameter saved in
+ *                  the SDL_AudioSpec structure
+ *  \param stream A pointer to the audio data buffer.
+ *  \param len    The length of that buffer in bytes.
+ *
+ *  Once the callback returns, the buffer will no longer be valid.
+ *  Stereo samples are stored in a LRLRLR ordering.
+ *
+ *  You can choose to avoid callbacks and use SDL_QueueAudio() instead, if
+ *  you like. Just open your audio device with a NULL callback.
+ */
+typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream,
+                                            int len);
+
+/**
+ *  The calculated values in this structure are calculated by SDL_OpenAudio().
+ */
+typedef struct SDL_AudioSpec
+{
+    int freq;                   /**< DSP frequency -- samples per second */
+    SDL_AudioFormat format;     /**< Audio data format */
+    Uint8 channels;             /**< Number of channels: 1 mono, 2 stereo */
+    Uint8 silence;              /**< Audio buffer silence value (calculated) */
+    Uint16 samples;             /**< Audio buffer size in samples (power of 2) */
+    Uint16 padding;             /**< Necessary for some compile environments */
+    Uint32 size;                /**< Audio buffer size in bytes (calculated) */
+    SDL_AudioCallback callback; /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
+    void *userdata;             /**< Userdata passed to callback (ignored for NULL callbacks). */
+} SDL_AudioSpec;
+
+
+struct SDL_AudioCVT;
+typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt,
+                                          SDL_AudioFormat format);
+
+/**
+ *  A structure to hold a set of audio conversion filters and buffers.
+ */
+#ifdef __GNUC__
+/* This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't
+   pad it out to 88 bytes to guarantee ABI compatibility between compilers.
+   vvv
+   The next time we rev the ABI, make sure to size the ints and add padding.
+*/
+#define SDL_AUDIOCVT_PACKED __attribute__((packed))
+#else
+#define SDL_AUDIOCVT_PACKED
+#endif
+/* */
+typedef struct SDL_AudioCVT
+{
+    int needed;                 /**< Set to 1 if conversion possible */
+    SDL_AudioFormat src_format; /**< Source audio format */
+    SDL_AudioFormat dst_format; /**< Target audio format */
+    double rate_incr;           /**< Rate conversion increment */
+    Uint8 *buf;                 /**< Buffer to hold entire audio data */
+    int len;                    /**< Length of original audio buffer */
+    int len_cvt;                /**< Length of converted audio buffer */
+    int len_mult;               /**< buffer must be len*len_mult big */
+    double len_ratio;           /**< Given len, final size is len*len_ratio */
+    SDL_AudioFilter filters[10];        /**< Filter list */
+    int filter_index;           /**< Current audio conversion function */
+} SDL_AUDIOCVT_PACKED SDL_AudioCVT;
+
+
+/* Function prototypes */
+
+/**
+ *  \name Driver discovery functions
+ *
+ *  These functions return the list of built in audio drivers, in the
+ *  order that they are normally initialized by default.
+ */
+/* @{ */
+extern DECLSPEC int SDLCALL SDL_GetNumAudioDrivers(void);
+extern DECLSPEC const char *SDLCALL SDL_GetAudioDriver(int index);
+/* @} */
+
+/**
+ *  \name Initialization and cleanup
+ *
+ *  \internal These functions are used internally, and should not be used unless
+ *            you have a specific need to specify the audio driver you want to
+ *            use.  You should normally use SDL_Init() or SDL_InitSubSystem().
+ */
+/* @{ */
+extern DECLSPEC int SDLCALL SDL_AudioInit(const char *driver_name);
+extern DECLSPEC void SDLCALL SDL_AudioQuit(void);
+/* @} */
+
+/**
+ *  This function returns the name of the current audio driver, or NULL
+ *  if no driver has been initialized.
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void);
+
+/**
+ *  This function opens the audio device with the desired parameters, and
+ *  returns 0 if successful, placing the actual hardware parameters in the
+ *  structure pointed to by \c obtained.  If \c obtained is NULL, the audio
+ *  data passed to the callback function will be guaranteed to be in the
+ *  requested format, and will be automatically converted to the hardware
+ *  audio format if necessary.  This function returns -1 if it failed
+ *  to open the audio device, or couldn't set up the audio thread.
+ *
+ *  When filling in the desired audio spec structure,
+ *    - \c desired->freq should be the desired audio frequency in samples-per-
+ *      second.
+ *    - \c desired->format should be the desired audio format.
+ *    - \c desired->samples is the desired size of the audio buffer, in
+ *      samples.  This number should be a power of two, and may be adjusted by
+ *      the audio driver to a value more suitable for the hardware.  Good values
+ *      seem to range between 512 and 8096 inclusive, depending on the
+ *      application and CPU speed.  Smaller values yield faster response time,
+ *      but can lead to underflow if the application is doing heavy processing
+ *      and cannot fill the audio buffer in time.  A stereo sample consists of
+ *      both right and left channels in LR ordering.
+ *      Note that the number of samples is directly related to time by the
+ *      following formula:  \code ms = (samples*1000)/freq \endcode
+ *    - \c desired->size is the size in bytes of the audio buffer, and is
+ *      calculated by SDL_OpenAudio().
+ *    - \c desired->silence is the value used to set the buffer to silence,
+ *      and is calculated by SDL_OpenAudio().
+ *    - \c desired->callback should be set to a function that will be called
+ *      when the audio device is ready for more data.  It is passed a pointer
+ *      to the audio buffer, and the length in bytes of the audio buffer.
+ *      This function usually runs in a separate thread, and so you should
+ *      protect data structures that it accesses by calling SDL_LockAudio()
+ *      and SDL_UnlockAudio() in your code. Alternately, you may pass a NULL
+ *      pointer here, and call SDL_QueueAudio() with some frequency, to queue
+ *      more audio samples to be played.
+ *    - \c desired->userdata is passed as the first parameter to your callback
+ *      function. If you passed a NULL callback, this value is ignored.
+ *
+ *  The audio device starts out playing silence when it's opened, and should
+ *  be enabled for playing by calling \c SDL_PauseAudio(0) when you are ready
+ *  for your audio callback function to be called.  Since the audio driver
+ *  may modify the requested size of the audio buffer, you should allocate
+ *  any local mixing buffers after you open the audio device.
+ */
+extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired,
+                                          SDL_AudioSpec * obtained);
+
+/**
+ *  SDL Audio Device IDs.
+ *
+ *  A successful call to SDL_OpenAudio() is always device id 1, and legacy
+ *  SDL audio APIs assume you want this device ID. SDL_OpenAudioDevice() calls
+ *  always returns devices >= 2 on success. The legacy calls are good both
+ *  for backwards compatibility and when you don't care about multiple,
+ *  specific, or capture devices.
+ */
+typedef Uint32 SDL_AudioDeviceID;
+
+/**
+ *  Get the number of available devices exposed by the current driver.
+ *  Only valid after a successfully initializing the audio subsystem.
+ *  Returns -1 if an explicit list of devices can't be determined; this is
+ *  not an error. For example, if SDL is set up to talk to a remote audio
+ *  server, it can't list every one available on the Internet, but it will
+ *  still allow a specific host to be specified to SDL_OpenAudioDevice().
+ *
+ *  In many common cases, when this function returns a value <= 0, it can still
+ *  successfully open the default device (NULL for first argument of
+ *  SDL_OpenAudioDevice()).
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumAudioDevices(int iscapture);
+
+/**
+ *  Get the human-readable name of a specific audio device.
+ *  Must be a value between 0 and (number of audio devices-1).
+ *  Only valid after a successfully initializing the audio subsystem.
+ *  The values returned by this function reflect the latest call to
+ *  SDL_GetNumAudioDevices(); recall that function to redetect available
+ *  hardware.
+ *
+ *  The string returned by this function is UTF-8 encoded, read-only, and
+ *  managed internally. You are not to free it. If you need to keep the
+ *  string for any length of time, you should make your own copy of it, as it
+ *  will be invalid next time any of several other SDL functions is called.
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index,
+                                                           int iscapture);
+
+
+/**
+ *  Open a specific audio device. Passing in a device name of NULL requests
+ *  the most reasonable default (and is equivalent to calling SDL_OpenAudio()).
+ *
+ *  The device name is a UTF-8 string reported by SDL_GetAudioDeviceName(), but
+ *  some drivers allow arbitrary and driver-specific strings, such as a
+ *  hostname/IP address for a remote audio server, or a filename in the
+ *  diskaudio driver.
+ *
+ *  \return 0 on error, a valid device ID that is >= 2 on success.
+ *
+ *  SDL_OpenAudio(), unlike this function, always acts on device ID 1.
+ */
+extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(const char
+                                                              *device,
+                                                              int iscapture,
+                                                              const
+                                                              SDL_AudioSpec *
+                                                              desired,
+                                                              SDL_AudioSpec *
+                                                              obtained,
+                                                              int
+                                                              allowed_changes);
+
+
+
+/**
+ *  \name Audio state
+ *
+ *  Get the current audio state.
+ */
+/* @{ */
+typedef enum
+{
+    SDL_AUDIO_STOPPED = 0,
+    SDL_AUDIO_PLAYING,
+    SDL_AUDIO_PAUSED
+} SDL_AudioStatus;
+extern DECLSPEC SDL_AudioStatus SDLCALL SDL_GetAudioStatus(void);
+
+extern DECLSPEC SDL_AudioStatus SDLCALL
+SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev);
+/* @} *//* Audio State */
+
+/**
+ *  \name Pause audio functions
+ *
+ *  These functions pause and unpause the audio callback processing.
+ *  They should be called with a parameter of 0 after opening the audio
+ *  device to start playing sound.  This is so you can safely initialize
+ *  data for your callback function after opening the audio device.
+ *  Silence will be written to the audio device during the pause.
+ */
+/* @{ */
+extern DECLSPEC void SDLCALL SDL_PauseAudio(int pause_on);
+extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev,
+                                                  int pause_on);
+/* @} *//* Pause audio functions */
+
+/**
+ *  This function loads a WAVE from the data source, automatically freeing
+ *  that source if \c freesrc is non-zero.  For example, to load a WAVE file,
+ *  you could do:
+ *  \code
+ *      SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...);
+ *  \endcode
+ *
+ *  If this function succeeds, it returns the given SDL_AudioSpec,
+ *  filled with the audio data format of the wave data, and sets
+ *  \c *audio_buf to a malloc()'d buffer containing the audio data,
+ *  and sets \c *audio_len to the length of that audio buffer, in bytes.
+ *  You need to free the audio buffer with SDL_FreeWAV() when you are
+ *  done with it.
+ *
+ *  This function returns NULL and sets the SDL error message if the
+ *  wave file cannot be opened, uses an unknown data format, or is
+ *  corrupt.  Currently raw and MS-ADPCM WAVE files are supported.
+ */
+extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src,
+                                                      int freesrc,
+                                                      SDL_AudioSpec * spec,
+                                                      Uint8 ** audio_buf,
+                                                      Uint32 * audio_len);
+
+/**
+ *  Loads a WAV from a file.
+ *  Compatibility convenience function.
+ */
+#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \
+    SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len)
+
+/**
+ *  This function frees data previously allocated with SDL_LoadWAV_RW()
+ */
+extern DECLSPEC void SDLCALL SDL_FreeWAV(Uint8 * audio_buf);
+
+/**
+ *  This function takes a source format and rate and a destination format
+ *  and rate, and initializes the \c cvt structure with information needed
+ *  by SDL_ConvertAudio() to convert a buffer of audio data from one format
+ *  to the other.
+ *
+ *  \return -1 if the format conversion is not supported, 0 if there's
+ *  no conversion needed, or 1 if the audio filter is set up.
+ */
+extern DECLSPEC int SDLCALL SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
+                                              SDL_AudioFormat src_format,
+                                              Uint8 src_channels,
+                                              int src_rate,
+                                              SDL_AudioFormat dst_format,
+                                              Uint8 dst_channels,
+                                              int dst_rate);
+
+/**
+ *  Once you have initialized the \c cvt structure using SDL_BuildAudioCVT(),
+ *  created an audio buffer \c cvt->buf, and filled it with \c cvt->len bytes of
+ *  audio data in the source format, this function will convert it in-place
+ *  to the desired format.
+ *
+ *  The data conversion may expand the size of the audio data, so the buffer
+ *  \c cvt->buf should be allocated after the \c cvt structure is initialized by
+ *  SDL_BuildAudioCVT(), and should be \c cvt->len*cvt->len_mult bytes long.
+ */
+extern DECLSPEC int SDLCALL SDL_ConvertAudio(SDL_AudioCVT * cvt);
+
+#define SDL_MIX_MAXVOLUME 128
+/**
+ *  This takes two audio buffers of the playing audio format and mixes
+ *  them, performing addition, volume adjustment, and overflow clipping.
+ *  The volume ranges from 0 - 128, and should be set to ::SDL_MIX_MAXVOLUME
+ *  for full audio volume.  Note this does not change hardware volume.
+ *  This is provided for convenience -- you can mix your own audio data.
+ */
+extern DECLSPEC void SDLCALL SDL_MixAudio(Uint8 * dst, const Uint8 * src,
+                                          Uint32 len, int volume);
+
+/**
+ *  This works like SDL_MixAudio(), but you specify the audio format instead of
+ *  using the format of audio device 1. Thus it can be used when no audio
+ *  device is open at all.
+ */
+extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst,
+                                                const Uint8 * src,
+                                                SDL_AudioFormat format,
+                                                Uint32 len, int volume);
+
+/**
+ *  Queue more audio on non-callback devices.
+ *
+ *  SDL offers two ways to feed audio to the device: you can either supply a
+ *  callback that SDL triggers with some frequency to obtain more audio
+ *  (pull method), or you can supply no callback, and then SDL will expect
+ *  you to supply data at regular intervals (push method) with this function.
+ *
+ *  There are no limits on the amount of data you can queue, short of
+ *  exhaustion of address space. Queued data will drain to the device as
+ *  necessary without further intervention from you. If the device needs
+ *  audio but there is not enough queued, it will play silence to make up
+ *  the difference. This means you will have skips in your audio playback
+ *  if you aren't routinely queueing sufficient data.
+ *
+ *  This function copies the supplied data, so you are safe to free it when
+ *  the function returns. This function is thread-safe, but queueing to the
+ *  same device from two threads at once does not promise which buffer will
+ *  be queued first.
+ *
+ *  You may not queue audio on a device that is using an application-supplied
+ *  callback; doing so returns an error. You have to use the audio callback
+ *  or queue audio with this function, but not both.
+ *
+ *  You should not call SDL_LockAudio() on the device before queueing; SDL
+ *  handles locking internally for this function.
+ *
+ *  \param dev The device ID to which we will queue audio.
+ *  \param data The data to queue to the device for later playback.
+ *  \param len The number of bytes (not samples!) to which (data) points.
+ *  \return zero on success, -1 on error.
+ *
+ *  \sa SDL_GetQueuedAudioSize
+ *  \sa SDL_ClearQueuedAudio
+ */
+extern DECLSPEC int SDLCALL SDL_QueueAudio(SDL_AudioDeviceID dev, const void *data, Uint32 len);
+
+/**
+ *  Get the number of bytes of still-queued audio.
+ *
+ *  This is the number of bytes that have been queued for playback with
+ *  SDL_QueueAudio(), but have not yet been sent to the hardware.
+ *
+ *  Once we've sent it to the hardware, this function can not decide the exact
+ *  byte boundary of what has been played. It's possible that we just gave the
+ *  hardware several kilobytes right before you called this function, but it
+ *  hasn't played any of it yet, or maybe half of it, etc.
+ *
+ *  You may not queue audio on a device that is using an application-supplied
+ *  callback; calling this function on such a device always returns 0.
+ *  You have to use the audio callback or queue audio with SDL_QueueAudio(),
+ *  but not both.
+ *
+ *  You should not call SDL_LockAudio() on the device before querying; SDL
+ *  handles locking internally for this function.
+ *
+ *  \param dev The device ID of which we will query queued audio size.
+ *  \return Number of bytes (not samples!) of queued audio.
+ *
+ *  \sa SDL_QueueAudio
+ *  \sa SDL_ClearQueuedAudio
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetQueuedAudioSize(SDL_AudioDeviceID dev);
+
+/**
+ *  Drop any queued audio data waiting to be sent to the hardware.
+ *
+ *  Immediately after this call, SDL_GetQueuedAudioSize() will return 0 and
+ *  the hardware will start playing silence if more audio isn't queued.
+ *
+ *  This will not prevent playback of queued audio that's already been sent
+ *  to the hardware, as we can not undo that, so expect there to be some
+ *  fraction of a second of audio that might still be heard. This can be
+ *  useful if you want to, say, drop any pending music during a level change
+ *  in your game.
+ *
+ *  You may not queue audio on a device that is using an application-supplied
+ *  callback; calling this function on such a device is always a no-op.
+ *  You have to use the audio callback or queue audio with SDL_QueueAudio(),
+ *  but not both.
+ *
+ *  You should not call SDL_LockAudio() on the device before clearing the
+ *  queue; SDL handles locking internally for this function.
+ *
+ *  This function always succeeds and thus returns void.
+ *
+ *  \param dev The device ID of which to clear the audio queue.
+ *
+ *  \sa SDL_QueueAudio
+ *  \sa SDL_GetQueuedAudioSize
+ */
+extern DECLSPEC void SDLCALL SDL_ClearQueuedAudio(SDL_AudioDeviceID dev);
+
+
+/**
+ *  \name Audio lock functions
+ *
+ *  The lock manipulated by these functions protects the callback function.
+ *  During a SDL_LockAudio()/SDL_UnlockAudio() pair, you can be guaranteed that
+ *  the callback function is not running.  Do not call these from the callback
+ *  function or you will cause deadlock.
+ */
+/* @{ */
+extern DECLSPEC void SDLCALL SDL_LockAudio(void);
+extern DECLSPEC void SDLCALL SDL_LockAudioDevice(SDL_AudioDeviceID dev);
+extern DECLSPEC void SDLCALL SDL_UnlockAudio(void);
+extern DECLSPEC void SDLCALL SDL_UnlockAudioDevice(SDL_AudioDeviceID dev);
+/* @} *//* Audio lock functions */
+
+/**
+ *  This function shuts down audio processing and closes the audio device.
+ */
+extern DECLSPEC void SDLCALL SDL_CloseAudio(void);
+extern DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID dev);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_audio_h */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 97 - 0
modules/sdl2/SDL/include/SDL_bits.h

@@ -0,0 +1,97 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ *  \file SDL_bits.h
+ *
+ *  Functions for fiddling with bits and bitmasks.
+ */
+
+#ifndef _SDL_bits_h
+#define _SDL_bits_h
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  \file SDL_bits.h
+ */
+
+/**
+ *  Get the index of the most significant bit. Result is undefined when called
+ *  with 0. This operation can also be stated as "count leading zeroes" and
+ *  "log base 2".
+ *
+ *  \return Index of the most significant bit, or -1 if the value is 0.
+ */
+SDL_FORCE_INLINE int
+SDL_MostSignificantBitIndex32(Uint32 x)
+{
+#if defined(__GNUC__) && __GNUC__ >= 4
+    /* Count Leading Zeroes builtin in GCC.
+     * http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Other-Builtins.html
+     */
+    if (x == 0) {
+        return -1;
+    }
+    return 31 - __builtin_clz(x);
+#else
+    /* Based off of Bit Twiddling Hacks by Sean Eron Anderson
+     * <[email protected]>, released in the public domain.
+     * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
+     */
+    const Uint32 b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
+    const int    S[] = {1, 2, 4, 8, 16};
+
+    int msbIndex = 0;
+    int i;
+
+    if (x == 0) {
+        return -1;
+    }
+
+    for (i = 4; i >= 0; i--)
+    {
+        if (x & b[i])
+        {
+            x >>= S[i];
+            msbIndex |= S[i];
+        }
+    }
+
+    return msbIndex;
+#endif
+}
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_bits_h */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 63 - 0
modules/sdl2/SDL/include/SDL_blendmode.h

@@ -0,0 +1,63 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ *  \file SDL_blendmode.h
+ *
+ *  Header file declaring the SDL_BlendMode enumeration
+ */
+
+#ifndef _SDL_blendmode_h
+#define _SDL_blendmode_h
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  \brief The blend mode used in SDL_RenderCopy() and drawing operations.
+ */
+typedef enum
+{
+    SDL_BLENDMODE_NONE = 0x00000000,     /**< no blending
+                                              dstRGBA = srcRGBA */
+    SDL_BLENDMODE_BLEND = 0x00000001,    /**< alpha blending
+                                              dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
+                                              dstA = srcA + (dstA * (1-srcA)) */
+    SDL_BLENDMODE_ADD = 0x00000002,      /**< additive blending
+                                              dstRGB = (srcRGB * srcA) + dstRGB
+                                              dstA = dstA */
+    SDL_BLENDMODE_MOD = 0x00000004       /**< color modulate
+                                              dstRGB = srcRGB * dstRGB
+                                              dstA = dstA */
+} SDL_BlendMode;
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_blendmode_h */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 71 - 0
modules/sdl2/SDL/include/SDL_clipboard.h

@@ -0,0 +1,71 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_clipboard.h
+ *
+ * Include file for SDL clipboard handling
+ */
+
+#ifndef _SDL_clipboard_h
+#define _SDL_clipboard_h
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function prototypes */
+
+/**
+ * \brief Put UTF-8 text into the clipboard
+ *
+ * \sa SDL_GetClipboardText()
+ */
+extern DECLSPEC int SDLCALL SDL_SetClipboardText(const char *text);
+
+/**
+ * \brief Get UTF-8 text from the clipboard, which must be freed with SDL_free()
+ *
+ * \sa SDL_SetClipboardText()
+ */
+extern DECLSPEC char * SDLCALL SDL_GetClipboardText(void);
+
+/**
+ * \brief Returns a flag indicating whether the clipboard exists and contains a text string that is non-empty
+ *
+ * \sa SDL_GetClipboardText()
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasClipboardText(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_clipboard_h */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 55 - 0
modules/sdl2/SDL/include/SDL_config.h

@@ -0,0 +1,55 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _SDL_config_h
+#define _SDL_config_h
+
+#include "SDL_platform.h"
+
+/**
+ *  \file SDL_config.h
+ */
+
+/* Add any platform that doesn't build using the configure system. */
+#ifdef USING_PREMAKE_CONFIG_H
+#include "SDL_config_premake.h"
+#elif defined(__WIN32__)
+#include "SDL_config_windows.h"
+#elif defined(__WINRT__)
+#include "SDL_config_winrt.h"
+#elif defined(__MACOSX__)
+#include "SDL_config_macosx.h"
+#elif defined(__IPHONEOS__)
+#include "SDL_config_iphoneos.h"
+#elif defined(__ANDROID__)
+#include "SDL_config_android.h"
+#elif defined(__PSP__)
+#include "SDL_config_psp.h"
+#else
+/* This is a minimal configuration just to get SDL running on new platforms */
+#include "SDL_config_minimal.h"
+#endif /* platform config */
+
+#ifdef USING_GENERATED_CONFIG_H
+#error Wrong SDL_config.h, check your include path?
+#endif
+
+#endif /* _SDL_config_h */

+ 419 - 0
modules/sdl2/SDL/include/SDL_config.h.cmake

@@ -0,0 +1,419 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _SDL_config_h
+#define _SDL_config_h
+
+/**
+ *  \file SDL_config.h.in
+ *
+ *  This is a set of defines to configure the SDL features
+ */
+
+/* General platform specific identifiers */
+#include "SDL_platform.h"
+
+/* C language features */
+#cmakedefine const @HAVE_CONST@
+#cmakedefine inline @HAVE_INLINE@
+#cmakedefine volatile @HAVE_VOLATILE@
+
+/* C datatypes */
+/* Define SIZEOF_VOIDP for 64/32 architectures */
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+
+#cmakedefine HAVE_GCC_ATOMICS @HAVE_GCC_ATOMICS@
+#cmakedefine HAVE_GCC_SYNC_LOCK_TEST_AND_SET @HAVE_GCC_SYNC_LOCK_TEST_AND_SET@
+
+#cmakedefine HAVE_D3D_H @HAVE_D3D_H@
+#cmakedefine HAVE_D3D11_H @HAVE_D3D11_H@
+#cmakedefine HAVE_DDRAW_H @HAVE_DDRAW_H@
+#cmakedefine HAVE_DSOUND_H @HAVE_DSOUND_H@
+#cmakedefine HAVE_DINPUT_H @HAVE_DINPUT_H@
+#cmakedefine HAVE_XAUDIO2_H @HAVE_XAUDIO2_H@
+#cmakedefine HAVE_XINPUT_H @HAVE_XINPUT_H@
+#cmakedefine HAVE_DXGI_H @HAVE_DXGI_H@
+
+/* Comment this if you want to build without any C library requirements */
+#cmakedefine HAVE_LIBC 1
+#if HAVE_LIBC
+
+/* Useful headers */
+#cmakedefine HAVE_ALLOCA_H 1
+#cmakedefine HAVE_SYS_TYPES_H 1
+#cmakedefine HAVE_STDIO_H 1
+#cmakedefine STDC_HEADERS 1
+#cmakedefine HAVE_STDLIB_H 1
+#cmakedefine HAVE_STDARG_H 1
+#cmakedefine HAVE_MALLOC_H 1
+#cmakedefine HAVE_MEMORY_H 1
+#cmakedefine HAVE_STRING_H 1
+#cmakedefine HAVE_STRINGS_H 1
+#cmakedefine HAVE_INTTYPES_H 1
+#cmakedefine HAVE_STDINT_H 1
+#cmakedefine HAVE_CTYPE_H 1
+#cmakedefine HAVE_MATH_H 1
+#cmakedefine HAVE_ICONV_H 1
+#cmakedefine HAVE_SIGNAL_H 1
+#cmakedefine HAVE_ALTIVEC_H 1
+#cmakedefine HAVE_PTHREAD_NP_H 1
+#cmakedefine HAVE_LIBUDEV_H 1
+#cmakedefine HAVE_DBUS_DBUS_H 1
+
+/* C library functions */
+#cmakedefine HAVE_MALLOC 1
+#cmakedefine HAVE_CALLOC 1
+#cmakedefine HAVE_REALLOC 1
+#cmakedefine HAVE_FREE 1
+#cmakedefine HAVE_ALLOCA 1
+#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */
+#cmakedefine HAVE_GETENV 1
+#cmakedefine HAVE_SETENV 1
+#cmakedefine HAVE_PUTENV 1
+#cmakedefine HAVE_UNSETENV 1
+#endif
+#cmakedefine HAVE_QSORT 1
+#cmakedefine HAVE_ABS 1
+#cmakedefine HAVE_BCOPY 1
+#cmakedefine HAVE_MEMSET 1
+#cmakedefine HAVE_MEMCPY 1
+#cmakedefine HAVE_MEMMOVE 1
+#cmakedefine HAVE_MEMCMP 1
+#cmakedefine HAVE_STRLEN 1
+#cmakedefine HAVE_STRLCPY 1
+#cmakedefine HAVE_STRLCAT 1
+#cmakedefine HAVE_STRDUP 1
+#cmakedefine HAVE__STRREV 1
+#cmakedefine HAVE__STRUPR 1
+#cmakedefine HAVE__STRLWR 1
+#cmakedefine HAVE_INDEX 1
+#cmakedefine HAVE_RINDEX 1
+#cmakedefine HAVE_STRCHR 1
+#cmakedefine HAVE_STRRCHR 1
+#cmakedefine HAVE_STRSTR 1
+#cmakedefine HAVE_ITOA 1
+#cmakedefine HAVE__LTOA 1
+#cmakedefine HAVE__UITOA 1
+#cmakedefine HAVE__ULTOA 1
+#cmakedefine HAVE_STRTOL 1
+#cmakedefine HAVE_STRTOUL 1
+#cmakedefine HAVE__I64TOA 1
+#cmakedefine HAVE__UI64TOA 1
+#cmakedefine HAVE_STRTOLL 1
+#cmakedefine HAVE_STRTOULL 1
+#cmakedefine HAVE_STRTOD 1
+#cmakedefine HAVE_ATOI 1
+#cmakedefine HAVE_ATOF 1
+#cmakedefine HAVE_STRCMP 1
+#cmakedefine HAVE_STRNCMP 1
+#cmakedefine HAVE__STRICMP 1
+#cmakedefine HAVE_STRCASECMP 1
+#cmakedefine HAVE__STRNICMP 1
+#cmakedefine HAVE_STRNCASECMP 1
+#cmakedefine HAVE_VSSCANF 1
+#cmakedefine HAVE_VSNPRINTF 1
+#cmakedefine HAVE_M_PI 1
+#cmakedefine HAVE_ATAN 1
+#cmakedefine HAVE_ATAN2 1
+#cmakedefine HAVE_ACOS 1
+#cmakedefine HAVE_ASIN 1
+#cmakedefine HAVE_CEIL 1
+#cmakedefine HAVE_COPYSIGN 1
+#cmakedefine HAVE_COS 1
+#cmakedefine HAVE_COSF 1
+#cmakedefine HAVE_FABS 1
+#cmakedefine HAVE_FLOOR 1
+#cmakedefine HAVE_LOG 1
+#cmakedefine HAVE_POW 1
+#cmakedefine HAVE_SCALBN 1
+#cmakedefine HAVE_SIN 1
+#cmakedefine HAVE_SINF 1
+#cmakedefine HAVE_SQRT 1
+#cmakedefine HAVE_SQRTF 1
+#cmakedefine HAVE_TAN 1
+#cmakedefine HAVE_TANF 1
+#cmakedefine HAVE_FSEEKO 1
+#cmakedefine HAVE_FSEEKO64 1
+#cmakedefine HAVE_SIGACTION 1
+#cmakedefine HAVE_SA_SIGACTION 1
+#cmakedefine HAVE_SETJMP 1
+#cmakedefine HAVE_NANOSLEEP 1
+#cmakedefine HAVE_SYSCONF 1
+#cmakedefine HAVE_SYSCTLBYNAME 1
+#cmakedefine HAVE_CLOCK_GETTIME 1
+#cmakedefine HAVE_GETPAGESIZE 1
+#cmakedefine HAVE_MPROTECT 1
+#cmakedefine HAVE_ICONV 1
+#cmakedefine HAVE_PTHREAD_SETNAME_NP 1
+#cmakedefine HAVE_PTHREAD_SET_NAME_NP 1
+#cmakedefine HAVE_SEM_TIMEDWAIT 1
+#elif __WIN32__
+#cmakedefine HAVE_STDARG_H 1
+#cmakedefine HAVE_STDDEF_H 1
+#else
+/* We may need some replacement for stdarg.h here */
+#include <stdarg.h>
+#endif /* HAVE_LIBC */
+
+/* SDL internal assertion support */
+#cmakedefine SDL_DEFAULT_ASSERT_LEVEL @SDL_DEFAULT_ASSERT_LEVEL@
+
+/* Allow disabling of core subsystems */
+#cmakedefine SDL_ATOMIC_DISABLED @SDL_ATOMIC_DISABLED@
+#cmakedefine SDL_AUDIO_DISABLED @SDL_AUDIO_DISABLED@
+#cmakedefine SDL_CPUINFO_DISABLED @SDL_CPUINFO_DISABLED@
+#cmakedefine SDL_EVENTS_DISABLED @SDL_EVENTS_DISABLED@
+#cmakedefine SDL_FILE_DISABLED @SDL_FILE_DISABLED@
+#cmakedefine SDL_JOYSTICK_DISABLED @SDL_JOYSTICK_DISABLED@
+#cmakedefine SDL_HAPTIC_DISABLED @SDL_HAPTIC_DISABLED@
+#cmakedefine SDL_LOADSO_DISABLED @SDL_LOADSO_DISABLED@
+#cmakedefine SDL_RENDER_DISABLED @SDL_RENDER_DISABLED@
+#cmakedefine SDL_THREADS_DISABLED @SDL_THREADS_DISABLED@
+#cmakedefine SDL_TIMERS_DISABLED @SDL_TIMERS_DISABLED@
+#cmakedefine SDL_VIDEO_DISABLED @SDL_VIDEO_DISABLED@
+#cmakedefine SDL_POWER_DISABLED @SDL_POWER_DISABLED@
+#cmakedefine SDL_FILESYSTEM_DISABLED @SDL_FILESYSTEM_DISABLED@
+
+/* Enable various audio drivers */
+#cmakedefine SDL_AUDIO_DRIVER_ANDROID @SDL_AUDIO_DRIVER_ANDROID@
+#cmakedefine SDL_AUDIO_DRIVER_ALSA @SDL_AUDIO_DRIVER_ALSA@
+#cmakedefine SDL_AUDIO_DRIVER_ALSA_DYNAMIC @SDL_AUDIO_DRIVER_ALSA_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_ARTS @SDL_AUDIO_DRIVER_ARTS@
+#cmakedefine SDL_AUDIO_DRIVER_ARTS_DYNAMIC @SDL_AUDIO_DRIVER_ARTS_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO @SDL_AUDIO_DRIVER_PULSEAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC @SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_HAIKU @SDL_AUDIO_DRIVER_HAIKU@
+#cmakedefine SDL_AUDIO_DRIVER_BSD @SDL_AUDIO_DRIVER_BSD@
+#cmakedefine SDL_AUDIO_DRIVER_COREAUDIO @SDL_AUDIO_DRIVER_COREAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_DISK @SDL_AUDIO_DRIVER_DISK@
+#cmakedefine SDL_AUDIO_DRIVER_DUMMY @SDL_AUDIO_DRIVER_DUMMY@
+#cmakedefine SDL_AUDIO_DRIVER_XAUDIO2 @SDL_AUDIO_DRIVER_XAUDIO2@
+#cmakedefine SDL_AUDIO_DRIVER_DSOUND @SDL_AUDIO_DRIVER_DSOUND@
+#cmakedefine SDL_AUDIO_DRIVER_ESD @SDL_AUDIO_DRIVER_ESD@
+#cmakedefine SDL_AUDIO_DRIVER_ESD_DYNAMIC @SDL_AUDIO_DRIVER_ESD_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_NAS @SDL_AUDIO_DRIVER_NAS@
+#cmakedefine SDL_AUDIO_DRIVER_NAS_DYNAMIC @SDL_AUDIO_DRIVER_NAS_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_SNDIO @SDL_AUDIO_DRIVER_SNDIO@
+#cmakedefine SDL_AUDIO_DRIVER_SNDIO_DYNAMIC @SDL_AUDIO_DRIVER_SNDIO_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_OSS @SDL_AUDIO_DRIVER_OSS@
+#cmakedefine SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H @SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H@
+#cmakedefine SDL_AUDIO_DRIVER_PAUDIO @SDL_AUDIO_DRIVER_PAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_QSA @SDL_AUDIO_DRIVER_QSA@
+#cmakedefine SDL_AUDIO_DRIVER_SUNAUDIO @SDL_AUDIO_DRIVER_SUNAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_WINMM @SDL_AUDIO_DRIVER_WINMM@
+#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND @SDL_AUDIO_DRIVER_FUSIONSOUND@
+#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC @SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_EMSCRIPTEN @SDL_AUDIO_DRIVER_EMSCRIPTEN@
+
+/* Enable various input drivers */
+#cmakedefine SDL_INPUT_LINUXEV @SDL_INPUT_LINUXEV@
+#cmakedefine SDL_INPUT_LINUXKD @SDL_INPUT_LINUXKD@
+#cmakedefine SDL_INPUT_TSLIB @SDL_INPUT_TSLIB@
+#cmakedefine SDL_JOYSTICK_ANDROID @SDL_JOYSTICK_ANDROID@
+#cmakedefine SDL_JOYSTICK_HAIKU @SDL_JOYSTICK_HAIKU@
+#cmakedefine SDL_JOYSTICK_DINPUT @SDL_JOYSTICK_DINPUT@
+#cmakedefine SDL_JOYSTICK_XINPUT @SDL_JOYSTICK_XINPUT@
+#cmakedefine SDL_JOYSTICK_DUMMY @SDL_JOYSTICK_DUMMY@
+#cmakedefine SDL_JOYSTICK_IOKIT @SDL_JOYSTICK_IOKIT@
+#cmakedefine SDL_JOYSTICK_MFI @SDL_JOYSTICK_MFI@
+#cmakedefine SDL_JOYSTICK_LINUX @SDL_JOYSTICK_LINUX@
+#cmakedefine SDL_JOYSTICK_WINMM @SDL_JOYSTICK_WINMM@
+#cmakedefine SDL_JOYSTICK_USBHID @SDL_JOYSTICK_USBHID@
+#cmakedefine SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H @SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H@
+#cmakedefine SDL_JOYSTICK_EMSCRIPTEN @SDL_JOYSTICK_EMSCRIPTEN@
+#cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@
+#cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@
+#cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@
+#cmakedefine SDL_HAPTIC_DINPUT @SDL_HAPTIC_DINPUT@
+#cmakedefine SDL_HAPTIC_XINPUT @SDL_HAPTIC_XINPUT@
+
+/* Enable various shared object loading systems */
+#cmakedefine SDL_LOADSO_HAIKU @SDL_LOADSO_HAIKU@
+#cmakedefine SDL_LOADSO_DLOPEN @SDL_LOADSO_DLOPEN@
+#cmakedefine SDL_LOADSO_DUMMY @SDL_LOADSO_DUMMY@
+#cmakedefine SDL_LOADSO_LDG @SDL_LOADSO_LDG@
+#cmakedefine SDL_LOADSO_WINDOWS @SDL_LOADSO_WINDOWS@
+
+/* Enable various threading systems */
+#cmakedefine SDL_THREAD_PTHREAD @SDL_THREAD_PTHREAD@
+#cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX@
+#cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP@
+#cmakedefine SDL_THREAD_WINDOWS @SDL_THREAD_WINDOWS@
+
+/* Enable various timer systems */
+#cmakedefine SDL_TIMER_HAIKU @SDL_TIMER_HAIKU@
+#cmakedefine SDL_TIMER_DUMMY @SDL_TIMER_DUMMY@
+#cmakedefine SDL_TIMER_UNIX @SDL_TIMER_UNIX@
+#cmakedefine SDL_TIMER_WINDOWS @SDL_TIMER_WINDOWS@
+#cmakedefine SDL_TIMER_WINCE @SDL_TIMER_WINCE@
+
+/* Enable various video drivers */
+#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
+#cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@
+#cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@
+#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
+#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@
+#cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@
+#cmakedefine SDL_VIDEO_DRIVER_RPI @SDL_VIDEO_DRIVER_RPI@
+#cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@
+#cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@
+
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH @SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@
+
+#cmakedefine SDL_VIDEO_DRIVER_MIR @SDL_VIDEO_DRIVER_MIR@
+#cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC @SDL_VIDEO_DRIVER_MIR_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON@
+#cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@
+#cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT @SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS @SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE @SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XCURSOR @SDL_VIDEO_DRIVER_X11_XCURSOR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XDBE @SDL_VIDEO_DRIVER_X11_XDBE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XINERAMA @SDL_VIDEO_DRIVER_X11_XINERAMA@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2 @SDL_VIDEO_DRIVER_X11_XINPUT2@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH @SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XRANDR @SDL_VIDEO_DRIVER_X11_XRANDR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XSCRNSAVER @SDL_VIDEO_DRIVER_X11_XSCRNSAVER@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE @SDL_VIDEO_DRIVER_X11_XSHAPE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XVIDMODE @SDL_VIDEO_DRIVER_X11_XVIDMODE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS @SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS@
+#cmakedefine SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY @SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY@
+#cmakedefine SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM @SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM@
+
+#cmakedefine SDL_VIDEO_RENDER_D3D @SDL_VIDEO_RENDER_D3D@
+#cmakedefine SDL_VIDEO_RENDER_D3D11 @SDL_VIDEO_RENDER_D3D11@
+#cmakedefine SDL_VIDEO_RENDER_OGL @SDL_VIDEO_RENDER_OGL@
+#cmakedefine SDL_VIDEO_RENDER_OGL_ES @SDL_VIDEO_RENDER_OGL_ES@
+#cmakedefine SDL_VIDEO_RENDER_OGL_ES2 @SDL_VIDEO_RENDER_OGL_ES2@
+#cmakedefine SDL_VIDEO_RENDER_DIRECTFB @SDL_VIDEO_RENDER_DIRECTFB@
+
+/* Enable OpenGL support */
+#cmakedefine SDL_VIDEO_OPENGL @SDL_VIDEO_OPENGL@
+#cmakedefine SDL_VIDEO_OPENGL_ES @SDL_VIDEO_OPENGL_ES@
+#cmakedefine SDL_VIDEO_OPENGL_ES2 @SDL_VIDEO_OPENGL_ES2@
+#cmakedefine SDL_VIDEO_OPENGL_BGL @SDL_VIDEO_OPENGL_BGL@
+#cmakedefine SDL_VIDEO_OPENGL_CGL @SDL_VIDEO_OPENGL_CGL@
+#cmakedefine SDL_VIDEO_OPENGL_GLX @SDL_VIDEO_OPENGL_GLX@
+#cmakedefine SDL_VIDEO_OPENGL_WGL @SDL_VIDEO_OPENGL_WGL@
+#cmakedefine SDL_VIDEO_OPENGL_EGL @SDL_VIDEO_OPENGL_EGL@
+#cmakedefine SDL_VIDEO_OPENGL_OSMESA @SDL_VIDEO_OPENGL_OSMESA@
+#cmakedefine SDL_VIDEO_OPENGL_OSMESA_DYNAMIC @SDL_VIDEO_OPENGL_OSMESA_DYNAMIC@
+
+/* Enable system power support */
+#cmakedefine SDL_POWER_ANDROID @SDL_POWER_ANDROID@
+#cmakedefine SDL_POWER_LINUX @SDL_POWER_LINUX@
+#cmakedefine SDL_POWER_WINDOWS @SDL_POWER_WINDOWS@
+#cmakedefine SDL_POWER_MACOSX @SDL_POWER_MACOSX@
+#cmakedefine SDL_POWER_HAIKU @SDL_POWER_HAIKU@
+#cmakedefine SDL_POWER_EMSCRIPTEN @SDL_POWER_EMSCRIPTEN@
+#cmakedefine SDL_POWER_HARDWIRED @SDL_POWER_HARDWIRED@
+
+/* Enable system filesystem support */
+#cmakedefine SDL_FILESYSTEM_ANDROID @SDL_FILESYSTEM_ANDROID@
+#cmakedefine SDL_FILESYSTEM_HAIKU @SDL_FILESYSTEM_HAIKU@
+#cmakedefine SDL_FILESYSTEM_COCOA @SDL_FILESYSTEM_COCOA@
+#cmakedefine SDL_FILESYSTEM_DUMMY @SDL_FILESYSTEM_DUMMY@
+#cmakedefine SDL_FILESYSTEM_UNIX @SDL_FILESYSTEM_UNIX@
+#cmakedefine SDL_FILESYSTEM_WINDOWS @SDL_FILESYSTEM_WINDOWS@
+#cmakedefine SDL_FILESYSTEM_EMSCRIPTEN @SDL_FILESYSTEM_EMSCRIPTEN@
+
+/* Enable assembly routines */
+#cmakedefine SDL_ASSEMBLY_ROUTINES @SDL_ASSEMBLY_ROUTINES@
+#cmakedefine SDL_ALTIVEC_BLITTERS @SDL_ALTIVEC_BLITTERS@
+
+
+/* Platform specific definitions */
+#if !defined(__WIN32__)
+#  if !defined(_STDINT_H_) && !defined(_STDINT_H) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H)
+typedef unsigned int size_t;
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long uintptr_t;
+#  endif /* if (stdint.h isn't available) */
+#else /* __WIN32__ */
+#  if !defined(_STDINT_H_) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H)
+#    if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__)
+#define HAVE_STDINT_H	1
+#    elif defined(_MSC_VER)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#      ifndef _UINTPTR_T_DEFINED
+#        ifdef  _WIN64
+typedef unsigned __int64 uintptr_t;
+#          else
+typedef unsigned int uintptr_t;
+#        endif
+#define _UINTPTR_T_DEFINED
+#      endif
+/* Older Visual C++ headers don't have the Win64-compatible typedefs... */
+#      if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR)))
+#define DWORD_PTR DWORD
+#      endif
+#      if ((_MSC_VER <= 1200) && (!defined(LONG_PTR)))
+#define LONG_PTR LONG
+#      endif
+#    else /* !__GNUC__ && !_MSC_VER */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+#      ifndef _SIZE_T_DEFINED_
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+#      endif
+typedef unsigned int uintptr_t;
+#    endif /* __GNUC__ || _MSC_VER */
+#  endif /* !_STDINT_H_ && !HAVE_STDINT_H */
+#endif /* __WIN32__ */
+
+#endif /* _SDL_config_h */

+ 359 - 0
modules/sdl2/SDL/include/SDL_config.h.in

@@ -0,0 +1,359 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _SDL_config_h
+#define _SDL_config_h
+
+/**
+ *  \file SDL_config.h.in
+ *
+ *  This is a set of defines to configure the SDL features
+ */
+
+/* General platform specific identifiers */
+#include "SDL_platform.h"
+
+/* Make sure that this isn't included by Visual C++ */
+#ifdef _MSC_VER
+#error You should run hg revert SDL_config.h 
+#endif
+
+/* C language features */
+#undef const
+#undef inline
+#undef volatile
+
+/* C datatypes */
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+#undef HAVE_GCC_ATOMICS
+#undef HAVE_GCC_SYNC_LOCK_TEST_AND_SET
+
+#undef HAVE_DDRAW_H
+#undef HAVE_DINPUT_H
+#undef HAVE_DSOUND_H
+#undef HAVE_DXGI_H
+#undef HAVE_XINPUT_H
+
+/* Comment this if you want to build without any C library requirements */
+#undef HAVE_LIBC
+#if HAVE_LIBC
+
+/* Useful headers */
+#undef HAVE_ALLOCA_H
+#undef HAVE_SYS_TYPES_H
+#undef HAVE_STDIO_H
+#undef STDC_HEADERS
+#undef HAVE_STDLIB_H
+#undef HAVE_STDARG_H
+#undef HAVE_MALLOC_H
+#undef HAVE_MEMORY_H
+#undef HAVE_STRING_H
+#undef HAVE_STRINGS_H
+#undef HAVE_INTTYPES_H
+#undef HAVE_STDINT_H
+#undef HAVE_CTYPE_H
+#undef HAVE_MATH_H
+#undef HAVE_ICONV_H
+#undef HAVE_SIGNAL_H
+#undef HAVE_ALTIVEC_H
+#undef HAVE_PTHREAD_NP_H
+#undef HAVE_LIBUDEV_H
+#undef HAVE_DBUS_DBUS_H
+#undef HAVE_IBUS_IBUS_H
+
+/* C library functions */
+#undef HAVE_MALLOC
+#undef HAVE_CALLOC
+#undef HAVE_REALLOC
+#undef HAVE_FREE
+#undef HAVE_ALLOCA
+#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */
+#undef HAVE_GETENV
+#undef HAVE_SETENV
+#undef HAVE_PUTENV
+#undef HAVE_UNSETENV
+#endif
+#undef HAVE_QSORT
+#undef HAVE_ABS
+#undef HAVE_BCOPY
+#undef HAVE_MEMSET
+#undef HAVE_MEMCPY
+#undef HAVE_MEMMOVE
+#undef HAVE_MEMCMP
+#undef HAVE_STRLEN
+#undef HAVE_STRLCPY
+#undef HAVE_STRLCAT
+#undef HAVE_STRDUP
+#undef HAVE__STRREV
+#undef HAVE__STRUPR
+#undef HAVE__STRLWR
+#undef HAVE_INDEX
+#undef HAVE_RINDEX
+#undef HAVE_STRCHR
+#undef HAVE_STRRCHR
+#undef HAVE_STRSTR
+#undef HAVE_ITOA
+#undef HAVE__LTOA
+#undef HAVE__UITOA
+#undef HAVE__ULTOA
+#undef HAVE_STRTOL
+#undef HAVE_STRTOUL
+#undef HAVE__I64TOA
+#undef HAVE__UI64TOA
+#undef HAVE_STRTOLL
+#undef HAVE_STRTOULL
+#undef HAVE_STRTOD
+#undef HAVE_ATOI
+#undef HAVE_ATOF
+#undef HAVE_STRCMP
+#undef HAVE_STRNCMP
+#undef HAVE__STRICMP
+#undef HAVE_STRCASECMP
+#undef HAVE__STRNICMP
+#undef HAVE_STRNCASECMP
+#undef HAVE_SSCANF
+#undef HAVE_VSSCANF
+#undef HAVE_SNPRINTF
+#undef HAVE_VSNPRINTF
+#undef HAVE_M_PI
+#undef HAVE_ATAN
+#undef HAVE_ATAN2
+#undef HAVE_ACOS
+#undef HAVE_ASIN
+#undef HAVE_CEIL
+#undef HAVE_COPYSIGN
+#undef HAVE_COS
+#undef HAVE_COSF
+#undef HAVE_FABS
+#undef HAVE_FLOOR
+#undef HAVE_LOG
+#undef HAVE_POW
+#undef HAVE_SCALBN
+#undef HAVE_SIN
+#undef HAVE_SINF
+#undef HAVE_SQRT
+#undef HAVE_SQRTF
+#undef HAVE_TAN
+#undef HAVE_TANF
+#undef HAVE_FSEEKO
+#undef HAVE_FSEEKO64
+#undef HAVE_SIGACTION
+#undef HAVE_SA_SIGACTION
+#undef HAVE_SETJMP
+#undef HAVE_NANOSLEEP
+#undef HAVE_SYSCONF
+#undef HAVE_SYSCTLBYNAME
+#undef HAVE_CLOCK_GETTIME
+#undef HAVE_GETPAGESIZE
+#undef HAVE_MPROTECT
+#undef HAVE_ICONV
+#undef HAVE_PTHREAD_SETNAME_NP
+#undef HAVE_PTHREAD_SET_NAME_NP
+#undef HAVE_SEM_TIMEDWAIT
+
+#else
+#define HAVE_STDARG_H   1
+#define HAVE_STDDEF_H   1
+#define HAVE_STDINT_H   1
+#endif /* HAVE_LIBC */
+
+/* SDL internal assertion support */
+#undef SDL_DEFAULT_ASSERT_LEVEL
+
+/* Allow disabling of core subsystems */
+#undef SDL_ATOMIC_DISABLED
+#undef SDL_AUDIO_DISABLED
+#undef SDL_CPUINFO_DISABLED
+#undef SDL_EVENTS_DISABLED
+#undef SDL_FILE_DISABLED
+#undef SDL_JOYSTICK_DISABLED
+#undef SDL_HAPTIC_DISABLED
+#undef SDL_LOADSO_DISABLED
+#undef SDL_RENDER_DISABLED
+#undef SDL_THREADS_DISABLED
+#undef SDL_TIMERS_DISABLED
+#undef SDL_VIDEO_DISABLED
+#undef SDL_POWER_DISABLED
+#undef SDL_FILESYSTEM_DISABLED
+
+/* Enable various audio drivers */
+#undef SDL_AUDIO_DRIVER_ALSA
+#undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
+#undef SDL_AUDIO_DRIVER_ARTS
+#undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
+#undef SDL_AUDIO_DRIVER_PULSEAUDIO
+#undef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC
+#undef SDL_AUDIO_DRIVER_HAIKU
+#undef SDL_AUDIO_DRIVER_BSD
+#undef SDL_AUDIO_DRIVER_COREAUDIO
+#undef SDL_AUDIO_DRIVER_DISK
+#undef SDL_AUDIO_DRIVER_DUMMY
+#undef SDL_AUDIO_DRIVER_ANDROID
+#undef SDL_AUDIO_DRIVER_XAUDIO2
+#undef SDL_AUDIO_DRIVER_DSOUND
+#undef SDL_AUDIO_DRIVER_ESD
+#undef SDL_AUDIO_DRIVER_ESD_DYNAMIC
+#undef SDL_AUDIO_DRIVER_NACL
+#undef SDL_AUDIO_DRIVER_NAS
+#undef SDL_AUDIO_DRIVER_NAS_DYNAMIC
+#undef SDL_AUDIO_DRIVER_SNDIO
+#undef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
+#undef SDL_AUDIO_DRIVER_OSS
+#undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H
+#undef SDL_AUDIO_DRIVER_PAUDIO
+#undef SDL_AUDIO_DRIVER_QSA
+#undef SDL_AUDIO_DRIVER_SUNAUDIO
+#undef SDL_AUDIO_DRIVER_WINMM
+#undef SDL_AUDIO_DRIVER_FUSIONSOUND
+#undef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
+#undef SDL_AUDIO_DRIVER_EMSCRIPTEN
+
+/* Enable various input drivers */
+#undef SDL_INPUT_LINUXEV
+#undef SDL_INPUT_LINUXKD
+#undef SDL_INPUT_TSLIB
+#undef SDL_JOYSTICK_HAIKU
+#undef SDL_JOYSTICK_DINPUT
+#undef SDL_JOYSTICK_XINPUT
+#undef SDL_JOYSTICK_DUMMY
+#undef SDL_JOYSTICK_IOKIT
+#undef SDL_JOYSTICK_LINUX
+#undef SDL_JOYSTICK_ANDROID
+#undef SDL_JOYSTICK_WINMM
+#undef SDL_JOYSTICK_USBHID
+#undef SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
+#undef SDL_JOYSTICK_EMSCRIPTEN
+#undef SDL_HAPTIC_DUMMY
+#undef SDL_HAPTIC_LINUX
+#undef SDL_HAPTIC_IOKIT
+#undef SDL_HAPTIC_DINPUT
+#undef SDL_HAPTIC_XINPUT
+
+/* Enable various shared object loading systems */
+#undef SDL_LOADSO_HAIKU
+#undef SDL_LOADSO_DLOPEN
+#undef SDL_LOADSO_DUMMY
+#undef SDL_LOADSO_LDG
+#undef SDL_LOADSO_WINDOWS
+
+/* Enable various threading systems */
+#undef SDL_THREAD_PTHREAD
+#undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX
+#undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP
+#undef SDL_THREAD_WINDOWS
+
+/* Enable various timer systems */
+#undef SDL_TIMER_HAIKU
+#undef SDL_TIMER_DUMMY
+#undef SDL_TIMER_UNIX
+#undef SDL_TIMER_WINDOWS
+
+/* Enable various video drivers */
+#undef SDL_VIDEO_DRIVER_HAIKU
+#undef SDL_VIDEO_DRIVER_COCOA
+#undef SDL_VIDEO_DRIVER_DIRECTFB
+#undef SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC
+#undef SDL_VIDEO_DRIVER_DUMMY
+#undef SDL_VIDEO_DRIVER_WINDOWS
+#undef SDL_VIDEO_DRIVER_WAYLAND
+#undef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
+#undef SDL_VIDEO_DRIVER_MIR
+#undef SDL_VIDEO_DRIVER_MIR_DYNAMIC
+#undef SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON
+#undef SDL_VIDEO_DRIVER_X11
+#undef SDL_VIDEO_DRIVER_RPI
+#undef SDL_VIDEO_DRIVER_ANDROID
+#undef SDL_VIDEO_DRIVER_EMSCRIPTEN
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE
+#undef SDL_VIDEO_DRIVER_X11_XCURSOR
+#undef SDL_VIDEO_DRIVER_X11_XDBE
+#undef SDL_VIDEO_DRIVER_X11_XINERAMA
+#undef SDL_VIDEO_DRIVER_X11_XINPUT2
+#undef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+#undef SDL_VIDEO_DRIVER_X11_XRANDR
+#undef SDL_VIDEO_DRIVER_X11_XSCRNSAVER
+#undef SDL_VIDEO_DRIVER_X11_XSHAPE
+#undef SDL_VIDEO_DRIVER_X11_XVIDMODE
+#undef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
+#undef SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY
+#undef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+#undef SDL_VIDEO_DRIVER_NACL
+#undef SDL_VIDEO_DRIVER_VIVANTE
+#undef SDL_VIDEO_DRIVER_VIVANTE_VDK
+
+#undef SDL_VIDEO_RENDER_D3D
+#undef SDL_VIDEO_RENDER_D3D11
+#undef SDL_VIDEO_RENDER_OGL
+#undef SDL_VIDEO_RENDER_OGL_ES
+#undef SDL_VIDEO_RENDER_OGL_ES2
+#undef SDL_VIDEO_RENDER_DIRECTFB
+
+/* Enable OpenGL support */
+#undef SDL_VIDEO_OPENGL
+#undef SDL_VIDEO_OPENGL_ES
+#undef SDL_VIDEO_OPENGL_ES2
+#undef SDL_VIDEO_OPENGL_BGL
+#undef SDL_VIDEO_OPENGL_CGL
+#undef SDL_VIDEO_OPENGL_EGL
+#undef SDL_VIDEO_OPENGL_GLX
+#undef SDL_VIDEO_OPENGL_WGL
+#undef SDL_VIDEO_OPENGL_OSMESA
+#undef SDL_VIDEO_OPENGL_OSMESA_DYNAMIC
+
+/* Enable system power support */
+#undef SDL_POWER_LINUX
+#undef SDL_POWER_WINDOWS
+#undef SDL_POWER_MACOSX
+#undef SDL_POWER_HAIKU
+#undef SDL_POWER_ANDROID
+#undef SDL_POWER_EMSCRIPTEN
+#undef SDL_POWER_HARDWIRED
+
+/* Enable system filesystem support */
+#undef SDL_FILESYSTEM_HAIKU
+#undef SDL_FILESYSTEM_COCOA
+#undef SDL_FILESYSTEM_DUMMY
+#undef SDL_FILESYSTEM_UNIX
+#undef SDL_FILESYSTEM_WINDOWS
+#undef SDL_FILESYSTEM_NACL
+#undef SDL_FILESYSTEM_ANDROID
+#undef SDL_FILESYSTEM_EMSCRIPTEN
+
+/* Enable assembly routines */
+#undef SDL_ASSEMBLY_ROUTINES
+#undef SDL_ALTIVEC_BLITTERS
+
+#endif /* _SDL_config_h */

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov