packages feed

h-raylib 4.5.0.12 → 4.5.1.0

raw patch · 48 files changed

+13658/−14286 lines, 48 filesdep ~basenew-component:exe:basic-audionew-component:exe:basic-imagesnew-component:exe:basic-models

Dependency ranges changed: base

Files

CHANGELOG.md view
@@ -1,31 +1,38 @@ # h-raylib changelog
 
-## Version 4.5.0.4
-_13 November, 2022_
-- Replaced `CInt` with `CBool` for functions that return booleans
-- Removed `Xext` dependency (it is no longer required for Nix builds)
+## Version 4.5.1.0
+_12 February, 2023_
 
-## Version 4.5.0.5
-_19 November, 2022_
-- Replaced `CInt` with `CBool` in `RayCollision`
-- Updated raylib to the master branch
+- **BREAKING CHANGE**: Changed all types to minimize usage of `Ptr`s
+- **BREAKING CHANGE**: Split the `Raylib` module into six modules: `Raylib.Audio`, `Raylib.Core`, `Raylib.Models`, `Raylib.Shapes`, `Raylib.Text`, and `Raylib.Textures`
+- Added the internal `Freeable` typeclass to prevent memory leaks
 
-## Version 4.5.0.6
-_24 November, 2022_
+\[[#8](https://github.com/Anut-py/h-raylib/issues/8)\]
 
-\[[#6](https://github.com/Anut-py/h-raylib/issues/6)\]
+- Added `Xext` as a dependency again
 
-- Fixed `Font` marshalling
+## Version 4.5.0.12
+_14 January, 2023_
 
-## Version 4.5.0.7
-_26 November, 2022_
+- Removed `ShaderLocationIndex` from some function types
 
-\[[#7](https://github.com/Anut-py/h-raylib/pull/7)\]
+## Version 4.5.0.11
+_14 January, 2023_
 
-- Removed all constants that were enums in the original C API and replaced them with sum types deriving Enum
-- Removed some CInt usage in the main API
-- Removed `Raylib.Constants`
+- Fixed some function types
+- Allowed omitting fragment/vertex shaders in `loadShader` functions
 
+## Version 4.5.0.10
+_5 January, 2023_
+
+- Restructured to make the examples easier to run
+- Updated raylib to the master branch
+
+## Version 4.5.0.9
+_23 December, 2022_
+
+- Changed `setConfigFlags` and `setGesturesEnabled` to use an array of flags
+
 ## Version 4.5.0.8
 _18 December, 2022_
 
@@ -33,24 +40,28 @@ 
 - Fixed an issue on Mac where `clang` failed to detect that `rglfw.c` was using objective-c
 
-## Version 4.5.0.9
-_23 December, 2022_
+## Version 4.5.0.7
+_26 November, 2022_
 
-- Changed `setConfigFlags` and `setGesturesEnabled` to use an array of flags
+\[[#7](https://github.com/Anut-py/h-raylib/pull/7)\]
 
-## Version 4.5.0.10
-_5 January, 2023_
+- Removed all constants that were enums in the original C API and replaced them with sum types deriving `Enum`
+- Removed some `CInt` usage in the main API
+- Removed `Raylib.Constants`
 
-- Restructured to make the examples easier to run
-- Updated raylib to the master branch
+## Version 4.5.0.6
+_24 November, 2022_
 
-## Version 4.5.0.11
-_14 January, 2023_
+\[[#6](https://github.com/Anut-py/h-raylib/issues/6)\]
 
-- Fixed some function types
-- Allowed omitting fragment/vertex shaders in `loadShader` functions
+- Fixed `Font` marshalling
 
-## Version 4.5.0.12
-_14 January, 2023_
+## Version 4.5.0.5
+_19 November, 2022_
+- Replaced `CInt` with `CBool` in `RayCollision`
+- Updated raylib to the master branch
 
-- Removed `ShaderLocationIndex` from some function types
+## Version 4.5.0.4
+_13 November, 2022_
+- Replaced `CInt` with `CBool` for functions that return booleans
+- Removed `Xext` dependency (it is no longer required for Nix builds)
README.md view
@@ -81,6 +81,9 @@ 
 You can run the examples by using `cabal run {example name}` in the project directory.
 
+You can use `run-all-examples.sh` to run all of the examples in one go. In the future I will add an example that uses
+all the major functions for testing if everything is working correctly.
+
 ## License
 
 This project is licensed under the Apache License 2.0. See more in `LICENSE`.
+ examples/basic-audio/src/Main.hs view
@@ -0,0 +1,42 @@+{-# OPTIONS -Wall #-}
+
+module Main where
+
+import Control.Monad (unless)
+import Raylib.Core (changeDirectory, closeWindow, getApplicationDirectory, initWindow, setTargetFPS, beginDrawing, endDrawing, windowShouldClose, clearBackground)
+import Raylib.Types (Music)
+import Raylib.Colors (rayWhite, lightGray)
+import Raylib.Audio (loadMusicStream, playMusicStream, initAudioDevice, closeAudioDevice, updateMusicStream)
+import Raylib.Text (drawText)
+
+musicPath :: String
+musicPath = "../../../../../../../../../examples/basic-audio/assets/mini1111.xm"
+
+main :: IO ()
+main = do
+  initWindow 650 400 "raylib [audio] example - basic audio"
+  initAudioDevice
+
+  setTargetFPS 60
+  _ <- changeDirectory =<< getApplicationDirectory
+
+  music <- loadMusicStream musicPath
+  playMusicStream music
+
+  gameLoop music
+
+  closeAudioDevice
+  closeWindow
+
+gameLoop :: Music -> IO ()
+gameLoop music = do
+  beginDrawing
+
+  clearBackground rayWhite
+  drawText "You should hear music playing!" 20 20 20 lightGray
+
+  endDrawing
+
+  updateMusicStream music
+  shouldClose <- windowShouldClose
+  unless shouldClose $ gameLoop music
+ examples/basic-images/src/Main.hs view
@@ -0,0 +1,66 @@+{-# OPTIONS -Wall #-}
+module Main where
+
+import Control.Monad (unless)
+import Raylib.Colors (black, lightGray, orange, white)
+import Raylib.Core
+  ( beginDrawing,
+    beginTextureMode,
+    changeDirectory,
+    clearBackground,
+    closeWindow,
+    endDrawing,
+    endTextureMode,
+    getApplicationDirectory,
+    initWindow,
+    setTargetFPS,
+    windowShouldClose,
+  )
+import Raylib.Text (drawText)
+import Raylib.Textures
+  ( drawTexture,
+    drawTexturePro,
+    genImagePerlinNoise,
+    loadImage,
+    loadRenderTexture,
+    loadTextureFromImage,
+  )
+import Raylib.Types (Rectangle (Rectangle), RenderTexture (rendertexture'texture), Texture, Vector2 (Vector2))
+
+logoPath :: String
+logoPath = "../../../../../../../../../examples/basic-images/assets/raylib-logo.png"
+
+main :: IO ()
+main = do
+  initWindow 600 450 "raylib [textures] example - basic images"
+  setTargetFPS 60
+  _ <- getApplicationDirectory >>= changeDirectory
+
+  texture <- genImagePerlinNoise 600 450 20 20 2 >>= loadTextureFromImage
+  logo <- loadImage logoPath >>= loadTextureFromImage
+  rt <- loadRenderTexture 200 200
+
+  gameLoop texture logo rt
+
+  closeWindow
+
+gameLoop :: Texture -> Texture -> RenderTexture -> IO ()
+gameLoop texture logo rt = do
+  beginDrawing
+
+  beginTextureMode rt
+
+  clearBackground lightGray
+  drawText "This is scaled up" 10 10 20 black
+
+  endTextureMode
+
+  clearBackground white
+  drawTexture texture 0 0 orange
+  drawTexturePro (rendertexture'texture rt) (Rectangle 0 0 200 (-200)) (Rectangle 50 50 300 300) (Vector2 0 0) 0 white
+  drawTexturePro logo (Rectangle 0 0 256 256) (Rectangle 375 50 175 175) (Vector2 0 0) 0 white
+
+  endDrawing
+
+  shouldClose <- windowShouldClose
+  unless shouldClose $ gameLoop texture logo rt
+ examples/basic-models/src/Main.hs view
@@ -0,0 +1,47 @@+{-# OPTIONS -Wall #-}
+
+module Main where
+
+import Control.Monad (unless)
+import Raylib.Core (changeDirectory, closeWindow, getApplicationDirectory, initWindow, setTargetFPS, beginDrawing, endDrawing, windowShouldClose, clearBackground, beginMode3D, endMode3D, updateCamera, setCameraMode)
+import Raylib.Models (genMeshCube, loadModelFromMesh, drawModel, loadModel, drawGrid)
+import Raylib.Types (Model, Camera3D (Camera3D), Vector3 (Vector3), CameraProjection (CameraPerspective), Camera, CameraMode (CameraModeFirstPerson))
+import Raylib.Colors (white, orange)
+
+modelPath :: String
+modelPath = "../../../../../../../../../examples/basic-models/assets/Model.obj"
+
+main :: IO ()
+main = do
+  initWindow 650 400 "raylib [models] example - basic models"
+  setTargetFPS 60
+  _ <- getApplicationDirectory >>= changeDirectory
+
+  mesh <- genMeshCube 2 3 4
+  cubeModel <- loadModelFromMesh mesh
+  customModel <- loadModel modelPath
+  let camera = Camera3D (Vector3 3 2 3) (Vector3 0 0 0) (Vector3 0 1 0) 70 CameraPerspective
+  setCameraMode camera CameraModeFirstPerson
+
+  gameLoop cubeModel customModel camera
+
+  closeWindow
+
+gameLoop :: Model -> Model -> Camera -> IO ()
+gameLoop cubeModel customModel camera = do
+  beginDrawing
+
+  clearBackground white
+  beginMode3D camera
+
+  drawGrid 20 2.0
+  drawModel cubeModel (Vector3 0 1.5 0) 1 orange
+  drawModel customModel (Vector3 (-5) 1 0) 1 white
+
+  endMode3D
+
+  endDrawing
+
+  newCamera <- updateCamera camera
+  shouldClose <- windowShouldClose
+  unless shouldClose $ gameLoop cubeModel customModel newCamera
examples/basic-window/src/Main.hs view
@@ -2,21 +2,21 @@ module Main where
 
 import Control.Monad (unless)
-import Raylib
+import Raylib.Colors (lightGray, rayWhite)
+import Raylib.Core
   ( beginDrawing,
     clearBackground,
     closeWindow,
-    drawText,
     endDrawing,
     initWindow,
     setTargetFPS,
     windowShouldClose,
   )
-import Raylib.Colors (lightGray, rayWhite)
+import Raylib.Text (drawText)
 
 main :: IO ()
 main = do
-  initWindow 600 450 "raylib example - basic window"
+  initWindow 600 450 "raylib [core] example - basic window"
   setTargetFPS 60
   gameLoop
   closeWindow
examples/camera-ray-collision/src/Main.hs view
@@ -2,27 +2,31 @@ module Main where
 
 import Control.Monad (unless, when)
-import Raylib
+import Raylib.Colors (black, red, white)
+import Raylib.Core
   ( beginDrawing,
     beginMode3D,
     clearBackground,
     closeWindow,
-    drawFPS,
     endDrawing,
     endMode3D,
     initWindow,
     setCameraMode,
     setTargetFPS,
     updateCamera,
-    windowShouldClose, getRayCollisionQuad, drawBoundingBox, drawPoint3D
+    windowShouldClose,
   )
-import Raylib.Colors (black, white, red)
-import Raylib.Types (Camera3D (Camera3D, camera3D'position, camera3D'target), Vector3 (Vector3), Ray (Ray), BoundingBox (BoundingBox), RayCollision (rayCollision'point, rayCollision'hit), CameraProjection (CameraPerspective), CameraMode (CameraModeFirstPerson))
-import Foreign (toBool)
+import Raylib.Models
+  ( drawBoundingBox,
+    drawPoint3D,
+    getRayCollisionQuad,
+  )
+import Raylib.Text (drawFPS)
+import Raylib.Types (BoundingBox (BoundingBox), Camera3D (Camera3D, camera3D'position, camera3D'target), CameraMode (CameraModeFirstPerson), CameraProjection (CameraPerspective), Ray (Ray), RayCollision (rayCollision'hit, rayCollision'point), Vector3 (Vector3))
 
 main :: IO ()
 main = do
-  initWindow 600 450 "raylib example - camera ray collision"
+  initWindow 600 450 "raylib [core] example - camera ray collision"
   let camera = Camera3D (Vector3 0 0 0) (Vector3 2 0 1) (Vector3 0 1 0) 70 CameraPerspective
   setCameraMode camera CameraModeFirstPerson
   setTargetFPS 60
@@ -38,12 +42,12 @@ 
   let ray = Ray (camera3D'position camera) (camera3D'target camera -.- camera3D'position camera)
   let collision = getRayCollisionQuad ray (Vector3 0 0 0) (Vector3 0 2 0) (Vector3 0 2 4) (Vector3 0 0 4)
-  let col = if toBool (rayCollision'hit collision) then red else white
+  let col = if rayCollision'hit collision then red else white
 
   beginMode3D camera
 
   drawBoundingBox (BoundingBox (Vector3 0 0 0) (Vector3 0 2 4)) col
-  when (rayCollision'hit collision > 0) $ drawPoint3D (rayCollision'point collision) red
+  when (rayCollision'hit collision) $ drawPoint3D (rayCollision'point collision) red
 
   endMode3D
 
examples/custom-font-text/src/Main.hs view
@@ -1,26 +1,29 @@ {-# OPTIONS -Wall #-}
 module Main where
 
-import Control.Monad ( unless )
-import Raylib
-    ( beginDrawing,
-      clearBackground,
-      drawTextEx,
-      endDrawing,
-      initWindow,
-      loadFont,
-      setTargetFPS,
-      windowShouldClose, changeDirectory, getApplicationDirectory, unloadFont, isKeyPressed, drawText )
-import Raylib.Types (Vector2 (Vector2), Font, KeyboardKey (KeyUp, KeyDown))
-import Raylib.Colors (rayWhite, black)
+import Control.Monad (unless)
 import Foreign (fromBool)
+import Raylib.Colors (black, rayWhite)
+import Raylib.Core
+  ( beginDrawing,
+    changeDirectory,
+    clearBackground,
+    endDrawing,
+    getApplicationDirectory,
+    initWindow,
+    isKeyPressed,
+    setTargetFPS,
+    windowShouldClose,
+  )
+import Raylib.Text (drawText, drawTextEx, loadFont, unloadFont)
+import Raylib.Types (Font, KeyboardKey (KeyDown, KeyUp), Vector2 (Vector2))
 
 mainFontPath :: String
 mainFontPath = "../../../../../../../../../examples/custom-font-text/assets/Lato-Regular.ttf"
 
 main :: IO ()
 main = do
-  initWindow 800 450 "raylib example - custom font text"
+  initWindow 800 450 "raylib [text] example - custom font text"
   setTargetFPS 60
   _ <- getApplicationDirectory >>= changeDirectory
 
examples/first-person-camera/src/Main.hs view
@@ -2,28 +2,27 @@ module Main where
 
 import Control.Monad (unless)
-import Raylib
+import Raylib.Colors (black, white)
+import Raylib.Core
   ( beginDrawing,
     beginMode3D,
     clearBackground,
     closeWindow,
-    drawCircle3D,
-    drawFPS,
-    drawLine3D,
     endDrawing,
     endMode3D,
     initWindow,
     setCameraMode,
     setTargetFPS,
     updateCamera,
-    windowShouldClose, drawCubeWiresV
+    windowShouldClose,
   )
-import Raylib.Colors (black, white)
-import Raylib.Types (Camera3D (Camera3D), Vector3 (Vector3), CameraProjection (CameraPerspective), CameraMode (CameraModeFirstPerson))
+import Raylib.Models (drawCircle3D, drawCubeWiresV, drawLine3D)
+import Raylib.Text (drawFPS)
+import Raylib.Types (Camera3D (Camera3D), CameraMode (CameraModeFirstPerson), CameraProjection (CameraPerspective), Vector3 (Vector3))
 
 main :: IO ()
 main = do
-  initWindow 600 450 "raylib example - first person camera"
+  initWindow 600 450 "raylib [core] example - first person camera"
   let camera = Camera3D (Vector3 0 0 0) (Vector3 2 0 1) (Vector3 0 1 0) 70 CameraPerspective
   setCameraMode camera CameraModeFirstPerson
   setTargetFPS 60
h-raylib.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4
 name:               h-raylib
-version:            4.5.0.12
+version:            4.5.1.0
 synopsis:           Raylib bindings for Haskell
 category:           graphics
 description:
@@ -69,9 +69,7 @@   default:     False
   manual:      True
 
-executable basic-window
-  hs-source-dirs:   examples/basic-window/src
-  main-is:          Main.hs
+common example-options
   default-language: Haskell2010
 
   if !flag(examples)
@@ -82,55 +80,61 @@       , base
       , h-raylib
 
-executable camera-ray-collision
-  hs-source-dirs:   examples/camera-ray-collision/src
-  main-is:          Main.hs
-  default-language: Haskell2010
-
-  if !flag(examples)
-    buildable: False
+executable basic-window
+  import:         example-options
+  hs-source-dirs: examples/basic-window/src
+  main-is:        Main.hs
 
-  else
-    build-depends:
-      , base
-      , h-raylib
+executable basic-images
+  import:         example-options
+  hs-source-dirs: examples/basic-images/src
+  main-is:        Main.hs
 
-executable custom-font-text
-  hs-source-dirs:   examples/custom-font-text/src
-  main-is:          Main.hs
-  default-language: Haskell2010
+executable basic-models
+  import:         example-options
+  hs-source-dirs: examples/basic-models/src
+  main-is:        Main.hs
 
-  if !flag(examples)
-    buildable: False
+executable basic-audio
+  import:         example-options
+  hs-source-dirs: examples/basic-audio/src
+  main-is:        Main.hs
 
-  else
-    build-depends:
-      , base
-      , h-raylib
+executable custom-font-text
+  import:         example-options
+  hs-source-dirs: examples/custom-font-text/src
+  main-is:        Main.hs
 
 executable first-person-camera
-  hs-source-dirs:   examples/first-person-camera/src
-  main-is:          Main.hs
-  default-language: Haskell2010
-
-  if !flag(examples)
-    buildable: False
+  import:         example-options
+  hs-source-dirs: examples/first-person-camera/src
+  main-is:        Main.hs
 
-  else
-    build-depends:
-      , base
-      , h-raylib
+executable camera-ray-collision
+  import:         example-options
+  hs-source-dirs: examples/camera-ray-collision/src
+  main-is:        Main.hs
 
 library
   exposed-modules:
-    Raylib
+    Raylib.Audio
     Raylib.Colors
+    Raylib.Core
+    Raylib.Models
+    Raylib.Shapes
+    Raylib.Text
+    Raylib.Textures
     Raylib.Types
 
-  other-modules:    Raylib.Util
+  other-modules:
+    Raylib.Native
+    Raylib.Util
+    Raylib.Internal
+
   build-depends:    base >=4.0 && <4.17.0
   hs-source-dirs:   src
   default-language: Haskell2010
+  other-extensions: ForeignFunctionInterface, DeriveAnyClass
 
   if (flag(platform-windows) || (flag(detect-platform) && os(windows)))
     if flag(mingw-cross)
@@ -140,6 +144,7 @@         winmm
         shell32
         gcc
+        gcc_eh
 
     else
       extra-libraries:
@@ -147,8 +152,9 @@         gdi32
         winmm
         shell32
+        gcc_eh
 
-    cc-options: -DPLATFORM_DESKTOP
+    cc-options: -DPLATFORM_DESKTOP -D_ftelli64=ftello64 -D_fseeki64=fseeko64
 
   elif (flag(platform-linux) || (flag(detect-platform) && os(linux)))
     extra-libraries:
@@ -163,6 +169,7 @@       Xcursor
       Xrandr
       Xi
+      Xext
 
     cc-options:      -Wno-unused-result -DPLATFORM_DESKTOP
 
lib/bindings.c view
@@ -87,6 +87,11 @@     return ptr;
 }
 
+bool IsShaderReady_(Shader *a)
+{
+    return IsShaderReady(*a);
+}
+
 int GetShaderLocation_(Shader *a, char *b)
 {
     return GetShaderLocation(*a, b);
@@ -528,6 +533,11 @@     return ptr;
 }
 
+bool IsImageReady_(Image *a)
+{
+    return IsImageReady(*a);
+}
+
 void UnloadImage_(Image *a)
 {
     UnloadImage(*a);
@@ -801,11 +811,19 @@     return ptr;
 }
 
+bool IsTextureReady_(Texture* a) {
+    return IsTextureReady(*a);
+}
+
 void UnloadTexture_(Texture *a)
 {
     UnloadTexture(*a);
 }
 
+bool IsRenderTextureReady_(RenderTexture* a) {
+    return IsRenderTextureReady(*a);
+}
+
 void UnloadRenderTexture_(RenderTexture *a)
 {
     UnloadRenderTexture(*a);
@@ -997,6 +1015,11 @@     return ptr;
 }
 
+bool IsFontReady_(Font *a)
+{
+    return IsFontReady(*a);
+}
+
 void UnloadFont_(Font *a)
 {
     UnloadFont(*a);
@@ -1172,6 +1195,11 @@     return ptr;
 }
 
+bool IsModelReady_(Model *a)
+{
+    return IsModelReady(*a);
+}
+
 void UnloadModel_(Model *a)
 {
     UnloadModel(*a);
@@ -1345,6 +1373,11 @@     return ptr;
 }
 
+bool IsMaterialReady_(Material *a)
+{
+    return IsMaterialReady(*a);
+}
+
 void UnloadMaterial_(Material *a)
 {
     UnloadMaterial(*a);
@@ -1453,11 +1486,19 @@     UpdateSound(*a, b, c);
 }
 
+bool IsWaveReady_(Wave *a) {
+    return IsWaveReady(*a);
+}
+
 void UnloadWave_(Wave *a)
 {
     UnloadWave(*a);
 }
 
+bool IsSoundReady_(Sound *a) {
+    return IsSoundReady(*a);
+}
+
 void UnloadSound_(Sound *a)
 {
     UnloadSound(*a);
@@ -1544,6 +1585,10 @@     return ptr;
 }
 
+bool IsMusicReady_(Music *a) {
+    return IsMusicReady(*a);
+}
+
 void UnloadMusicStream_(Music *a)
 {
     UnloadMusicStream(*a);
@@ -1614,6 +1659,10 @@     AudioStream *ptr = (AudioStream *)malloc(sizeof(AudioStream));
     *ptr = LoadAudioStream(a, b, c);
     return ptr;
+}
+
+bool IsAudioStreamReady_(AudioStream *a) {
+    return IsAudioStreamReady(*a);
 }
 
 void UnloadAudioStream_(AudioStream *a)
lib/bindings.h view
@@ -4,11 +4,11 @@  * @brief Required methods for binding Haskell to Raylib
  *
  * Haskell does not support interfacing with C directly through structs (e.g. Vector2).
- * In order to achieve this, wrapper functions that use pointer need to be written. This
+ * In order to achieve this, wrapper functions that use pointers need to be written. This
  * file contains wrapper functions for all Raylib functions that do not take pointers.
  */
 
-#include "raylib.h"
+#include <raylib.h>
 
 void SetWindowIcon_(Image *a);
 
@@ -38,6 +38,8 @@ 
 Shader *LoadShaderFromMemory_(char *a, char *b);
 
+bool IsShaderReady_(Shader *a);
+
 int GetShaderLocation_(Shader *a, char *b);
 
 int GetShaderLocationAttrib_(Shader *a, char *b);
@@ -196,6 +198,8 @@ 
 Image *LoadImageFromScreen_();
 
+bool IsImageReady_(Image *a);
+
 void UnloadImage_(Image *a);
 
 int ExportImage_(Image *a, char *b);
@@ -290,8 +294,12 @@ 
 RenderTexture *LoadRenderTexture_(int a, int b);
 
+bool IsTextureReady_(Texture* a);
+
 void UnloadTexture_(Texture *a);
 
+bool IsRenderTextureReady_(RenderTexture* a);
+
 void UnloadRenderTexture_(RenderTexture *a);
 
 void UpdateTexture_(Texture *a, const void *b);
@@ -348,6 +356,8 @@ 
 Image *GenImageFontAtlas_(GlyphInfo *a, Rectangle **b, int c, int d, int e, int f);
 
+bool IsFontReady_(Font* a);
+
 void UnloadFont_(Font *a);
 
 int ExportFontAsCode_(Font *a, char *b);
@@ -418,6 +428,8 @@ 
 Model *LoadModelFromMesh_(Mesh *a);
 
+bool IsModelReady_(Model* a);
+
 void UnloadModel_(Model *a);
 
 void UnloadModelKeepMeshes_(Model *a);
@@ -476,6 +488,8 @@ 
 Material *LoadMaterialDefault_();
 
+bool IsMaterialReady_(Material *a);
+
 void UnloadMaterial_(Material *a);
 
 void SetMaterialTexture_(Material *a, int b, Texture *c);
@@ -512,8 +526,12 @@ 
 void UpdateSound_(Sound *a, const void *b, int c);
 
+bool IsWaveReady_(Wave *a);
+
 void UnloadWave_(Wave *a);
 
+bool IsSoundReady_(Sound *a);
+
 void UnloadSound_(Sound *a);
 
 int ExportWave_(Wave *a, char *b);
@@ -546,6 +564,8 @@ 
 Music *LoadMusicStreamFromMemory_(char *a, unsigned char *b, int c);
 
+bool IsMusicReady_(Music *a);
+
 void UnloadMusicStream_(Music *a);
 
 void PlayMusicStream_(Music *a);
@@ -573,6 +593,8 @@ float GetMusicTimePlayed_(Music *a);
 
 AudioStream *LoadAudioStream_(unsigned int a, unsigned int b, unsigned int c);
+
+bool IsAudioStreamReady_(AudioStream *a);
 
 void UnloadAudioStream_(AudioStream *a);
 
raylib/src/config.h view
@@ -25,64 +25,67 @@ *
 **********************************************************************************************/
 
+#ifndef CONFIG_H
+#define CONFIG_H
+
 //------------------------------------------------------------------------------------
 // Module selection - Some modules could be avoided
 // Mandatory modules: rcore, rlgl, utils
 //------------------------------------------------------------------------------------
-#define SUPPORT_MODULE_RSHAPES           1
-#define SUPPORT_MODULE_RTEXTURES         1
-#define SUPPORT_MODULE_RTEXT             1          // WARNING: It requires SUPPORT_MODULE_RTEXTURES to load sprite font textures
-#define SUPPORT_MODULE_RMODELS           1
-#define SUPPORT_MODULE_RAUDIO            1
+#define SUPPORT_MODULE_RSHAPES          1
+#define SUPPORT_MODULE_RTEXTURES        1
+#define SUPPORT_MODULE_RTEXT            1       // WARNING: It requires SUPPORT_MODULE_RTEXTURES to load sprite font textures
+#define SUPPORT_MODULE_RMODELS          1
+#define SUPPORT_MODULE_RAUDIO           1
 
 //------------------------------------------------------------------------------------
 // Module: rcore - Configuration Flags
 //------------------------------------------------------------------------------------
 // Camera module is included (rcamera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital
-#define SUPPORT_CAMERA_SYSTEM       1
+#define SUPPORT_CAMERA_SYSTEM           1
 // Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
-#define SUPPORT_GESTURES_SYSTEM     1
+#define SUPPORT_GESTURES_SYSTEM         1
 // Mouse gestures are directly mapped like touches and processed by gestures system
-#define SUPPORT_MOUSE_GESTURES      1
+#define SUPPORT_MOUSE_GESTURES          1
 // Reconfigure standard input to receive key inputs, works with SSH connection.
-#define SUPPORT_SSH_KEYBOARD_RPI    1
+#define SUPPORT_SSH_KEYBOARD_RPI        1
 // Setting a higher resolution can improve the accuracy of time-out intervals in wait functions.
 // However, it can also reduce overall system performance, because the thread scheduler switches tasks more often.
-#define SUPPORT_WINMM_HIGHRES_TIMER 1
-// Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
-//#define SUPPORT_BUSY_WAIT_LOOP      1
+#define SUPPORT_WINMM_HIGHRES_TIMER     1
+// Use busy wait loop for timing sync, if not defined, a high-resolution timer is set up and used
+//#define SUPPORT_BUSY_WAIT_LOOP          1
 // Use a partial-busy wait loop, in this case frame sleeps for most of the time, but then runs a busy loop at the end for accuracy
 #define SUPPORT_PARTIALBUSY_WAIT_LOOP
 // Wait for events passively (sleeping while no events) instead of polling them actively every frame
-//#define SUPPORT_EVENTS_WAITING      1
+//#define SUPPORT_EVENTS_WAITING          1
 // Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()
-#define SUPPORT_SCREEN_CAPTURE      1
+#define SUPPORT_SCREEN_CAPTURE          1
 // Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()
-#define SUPPORT_GIF_RECORDING       1
+#define SUPPORT_GIF_RECORDING           1
 // Support CompressData() and DecompressData() functions
-#define SUPPORT_COMPRESSION_API     1
+#define SUPPORT_COMPRESSION_API         1
 // Support automatic generated events, loading and recording of those events when required
-//#define SUPPORT_EVENTS_AUTOMATION     1
+//#define SUPPORT_EVENTS_AUTOMATION       1
 // Support custom frame control, only for advance users
-// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timming + PollInputEvents()
+// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
 // Enabling this flag allows manual control of the frame processes, use at your own risk
-//#define SUPPORT_CUSTOM_FRAME_CONTROL   1
+//#define SUPPORT_CUSTOM_FRAME_CONTROL    1
 
 // rcore: Configuration values
 //------------------------------------------------------------------------------------
-#define MAX_FILEPATH_CAPACITY       8192        // Maximum file paths capacity
-#define MAX_FILEPATH_LENGTH         4096        // Maximum length for filepaths (Linux PATH_MAX default value)
+#define MAX_FILEPATH_CAPACITY        8192       // Maximum file paths capacity
+#define MAX_FILEPATH_LENGTH          4096       // Maximum length for filepaths (Linux PATH_MAX default value)
 
-#define MAX_KEYBOARD_KEYS            512        // Maximum number of keyboard keys supported
-#define MAX_MOUSE_BUTTONS              8        // Maximum number of mouse buttons supported
-#define MAX_GAMEPADS                   4        // Maximum number of gamepads supported
-#define MAX_GAMEPAD_AXIS               8        // Maximum number of axis supported (per gamepad)
-#define MAX_GAMEPAD_BUTTONS           32        // Maximum number of buttons supported (per gamepad)
-#define MAX_TOUCH_POINTS               8        // Maximum number of touch points supported
-#define MAX_KEY_PRESSED_QUEUE         16        // Maximum number of keys in the key input queue
-#define MAX_CHAR_PRESSED_QUEUE        16        // Maximum number of characters in the char input queue
+#define MAX_KEYBOARD_KEYS             512       // Maximum number of keyboard keys supported
+#define MAX_MOUSE_BUTTONS               8       // Maximum number of mouse buttons supported
+#define MAX_GAMEPADS                    4       // Maximum number of gamepads supported
+#define MAX_GAMEPAD_AXIS                8       // Maximum number of axis supported (per gamepad)
+#define MAX_GAMEPAD_BUTTONS            32       // Maximum number of buttons supported (per gamepad)
+#define MAX_TOUCH_POINTS                8       // Maximum number of touch points supported
+#define MAX_KEY_PRESSED_QUEUE          16       // Maximum number of keys in the key input queue
+#define MAX_CHAR_PRESSED_QUEUE         16       // Maximum number of characters in the char input queue
 
-#define MAX_DECOMPRESSION_SIZE        64        // Max size allocated for decompression in MB
+#define MAX_DECOMPRESSION_SIZE         64       // Max size allocated for decompression in MB
 
 
 //------------------------------------------------------------------------------------
@@ -109,12 +112,12 @@ 
 // Default shader vertex attribute names to set location points
 // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience
-#define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION     "vertexPosition"    // Binded by default to shader location: 0
-#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD     "vertexTexCoord"    // Binded by default to shader location: 1
-#define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL       "vertexNormal"      // Binded by default to shader location: 2
-#define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR        "vertexColor"       // Binded by default to shader location: 3
-#define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT      "vertexTangent"     // Binded by default to shader location: 4
-#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2    "vertexTexCoord2"   // Binded by default to shader location: 5
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION     "vertexPosition"    // Bound by default to shader location: 0
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD     "vertexTexCoord"    // Bound by default to shader location: 1
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL       "vertexNormal"      // Bound by default to shader location: 2
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR        "vertexColor"       // Bound by default to shader location: 3
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT      "vertexTangent"     // Bound by default to shader location: 4
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2    "vertexTexCoord2"   // Bound by default to shader location: 5
 
 #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP         "mvp"               // model-view-projection matrix
 #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW        "matView"           // view matrix
@@ -132,36 +135,36 @@ //------------------------------------------------------------------------------------
 // Use QUADS instead of TRIANGLES for drawing when possible
 // Some lines-based shapes could still use lines
-#define SUPPORT_QUADS_DRAW_MODE     1
+#define SUPPORT_QUADS_DRAW_MODE         1
 
 
 //------------------------------------------------------------------------------------
 // Module: rtextures - Configuration Flags
 //------------------------------------------------------------------------------------
-// Selecte desired fileformats to be supported for image data loading
-#define SUPPORT_FILEFORMAT_PNG      1
-//#define SUPPORT_FILEFORMAT_BMP      1
-//#define SUPPORT_FILEFORMAT_TGA      1
-//#define SUPPORT_FILEFORMAT_JPG      1
-#define SUPPORT_FILEFORMAT_GIF      1
-#define SUPPORT_FILEFORMAT_QOI      1
-//#define SUPPORT_FILEFORMAT_PSD      1
-#define SUPPORT_FILEFORMAT_DDS      1
-#define SUPPORT_FILEFORMAT_HDR      1
-//#define SUPPORT_FILEFORMAT_PIC      1
-//#define SUPPORT_FILEFORMAT_PNM      1
-//#define SUPPORT_FILEFORMAT_KTX      1
-//#define SUPPORT_FILEFORMAT_ASTC     1
-//#define SUPPORT_FILEFORMAT_PKM      1
-//#define SUPPORT_FILEFORMAT_PVR      1
+// Select the desired fileformats to be supported for image data loading
+#define SUPPORT_FILEFORMAT_PNG          1
+//#define SUPPORT_FILEFORMAT_BMP          1
+//#define SUPPORT_FILEFORMAT_TGA          1
+//#define SUPPORT_FILEFORMAT_JPG          1
+#define SUPPORT_FILEFORMAT_GIF          1
+#define SUPPORT_FILEFORMAT_QOI          1
+//#define SUPPORT_FILEFORMAT_PSD          1
+#define SUPPORT_FILEFORMAT_DDS          1
+#define SUPPORT_FILEFORMAT_HDR          1
+//#define SUPPORT_FILEFORMAT_PIC          1
+//#define SUPPORT_FILEFORMAT_PNM          1
+//#define SUPPORT_FILEFORMAT_KTX          1
+//#define SUPPORT_FILEFORMAT_ASTC         1
+//#define SUPPORT_FILEFORMAT_PKM          1
+//#define SUPPORT_FILEFORMAT_PVR          1
 
 // Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
-#define SUPPORT_IMAGE_EXPORT        1
+#define SUPPORT_IMAGE_EXPORT            1
 // Support procedural image generation functionality (gradient, spot, perlin-noise, cellular)
-#define SUPPORT_IMAGE_GENERATION    1
+#define SUPPORT_IMAGE_GENERATION        1
 // Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop...
 // If not defined, still some functions are supported: ImageFormat(), ImageCrop(), ImageToPOT()
-#define SUPPORT_IMAGE_MANIPULATION  1
+#define SUPPORT_IMAGE_MANIPULATION      1
 
 
 //------------------------------------------------------------------------------------
@@ -169,51 +172,52 @@ //------------------------------------------------------------------------------------
 // Default font is loaded on window initialization to be available for the user to render simple text
 // NOTE: If enabled, uses external module functions to load default raylib font
-#define SUPPORT_DEFAULT_FONT        1
+#define SUPPORT_DEFAULT_FONT            1
 // Selected desired font fileformats to be supported for loading
-#define SUPPORT_FILEFORMAT_FNT      1
-#define SUPPORT_FILEFORMAT_TTF      1
+#define SUPPORT_FILEFORMAT_FNT          1
+#define SUPPORT_FILEFORMAT_TTF          1
 
 // Support text management functions
 // If not defined, still some functions are supported: TextLength(), TextFormat()
-#define SUPPORT_TEXT_MANIPULATION   1
+#define SUPPORT_TEXT_MANIPULATION       1
 
 // rtext: Configuration values
 //------------------------------------------------------------------------------------
-#define MAX_TEXT_BUFFER_LENGTH      1024        // Size of internal static buffers used on some functions:
+#define MAX_TEXT_BUFFER_LENGTH       1024       // Size of internal static buffers used on some functions:
                                                 // TextFormat(), TextSubtext(), TextToUpper(), TextToLower(), TextToPascal(), TextSplit()
-#define MAX_TEXTSPLIT_COUNT          128        // Maximum number of substrings to split: TextSplit()
+#define MAX_TEXTSPLIT_COUNT           128       // Maximum number of substrings to split: TextSplit()
 
 
 //------------------------------------------------------------------------------------
 // Module: rmodels - Configuration Flags
 //------------------------------------------------------------------------------------
 // Selected desired model fileformats to be supported for loading
-#define SUPPORT_FILEFORMAT_OBJ      1
-#define SUPPORT_FILEFORMAT_MTL      1
-#define SUPPORT_FILEFORMAT_IQM      1
-#define SUPPORT_FILEFORMAT_GLTF     1
-#define SUPPORT_FILEFORMAT_VOX      1
-#define SUPPORT_FILEFORMAT_M3D      1
+#define SUPPORT_FILEFORMAT_OBJ          1
+#define SUPPORT_FILEFORMAT_MTL          1
+#define SUPPORT_FILEFORMAT_IQM          1
+#define SUPPORT_FILEFORMAT_GLTF         1
+#define SUPPORT_FILEFORMAT_VOX          1
+#define SUPPORT_FILEFORMAT_M3D          1
 // Support procedural mesh generation functions, uses external par_shapes.h library
 // NOTE: Some generated meshes DO NOT include generated texture coordinates
-#define SUPPORT_MESH_GENERATION     1
+#define SUPPORT_MESH_GENERATION         1
 
 // rmodels: Configuration values
 //------------------------------------------------------------------------------------
-#define MAX_MATERIAL_MAPS               12      // Maximum number of shader maps supported
-#define MAX_MESH_VERTEX_BUFFERS          7      // Maximum vertex buffers (VBO) per mesh
+#define MAX_MATERIAL_MAPS              12       // Maximum number of shader maps supported
+#define MAX_MESH_VERTEX_BUFFERS         7       // Maximum vertex buffers (VBO) per mesh
 
 //------------------------------------------------------------------------------------
 // Module: raudio - Configuration Flags
 //------------------------------------------------------------------------------------
 // Desired audio fileformats to be supported for loading
-#define SUPPORT_FILEFORMAT_WAV      1
-#define SUPPORT_FILEFORMAT_OGG      1
-#define SUPPORT_FILEFORMAT_XM       1
-#define SUPPORT_FILEFORMAT_MOD      1
-#define SUPPORT_FILEFORMAT_MP3      1
-//#define SUPPORT_FILEFORMAT_FLAC     1
+#define SUPPORT_FILEFORMAT_WAV          1
+#define SUPPORT_FILEFORMAT_OGG          1
+#define SUPPORT_FILEFORMAT_MP3          1
+//#define SUPPORT_FILEFORMAT_QOA          1
+//#define SUPPORT_FILEFORMAT_FLAC         1
+#define SUPPORT_FILEFORMAT_XM           1
+#define SUPPORT_FILEFORMAT_MOD          1
 
 // raudio: Configuration values
 //------------------------------------------------------------------------------------
@@ -227,12 +231,14 @@ // Module: utils - Configuration Flags
 //------------------------------------------------------------------------------------
 // Standard file io library (stdio.h) included
-#define SUPPORT_STANDARD_FILEIO
+#define SUPPORT_STANDARD_FILEIO         1
 // Show TRACELOG() output messages
 // NOTE: By default LOG_DEBUG traces not shown
-#define SUPPORT_TRACELOG            1
-//#define SUPPORT_TRACELOG_DEBUG      1
+#define SUPPORT_TRACELOG                1
+//#define SUPPORT_TRACELOG_DEBUG          1
 
 // utils: Configuration values
 //------------------------------------------------------------------------------------
-#define MAX_TRACELOG_MSG_LENGTH          128    // Max length of one trace-log message
+#define MAX_TRACELOG_MSG_LENGTH       128       // Max length of one trace-log message
+
+#endif // CONFIG_H
raylib/src/external/cgltf.h view
@@ -1,7 +1,7 @@ /**
  * cgltf - a single-file glTF 2.0 parser written in C99.
  *
- * Version: 1.12
+ * Version: 1.13
  *
  * Website: https://github.com/jkuhlmann/cgltf
  *
@@ -80,19 +80,16 @@  * `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t
  * and only works with single-component data types.
  *
- * `cgltf_result cgltf_copy_extras_json(const cgltf_data*, const cgltf_extras*,
- * char* dest, cgltf_size* dest_size)` allows users to retrieve the "extras" data that
- * can be attached to many glTF objects (which can be arbitrary JSON data). The
- * `cgltf_extras` struct stores the offsets of the start and end of the extras JSON data
- * as it appears in the complete glTF JSON data. This function copies the extras data
- * into the provided buffer. If `dest` is NULL, the length of the data is written into
- * `dest_size`. You can then parse this data using your own JSON parser
+ * `cgltf_copy_extras_json` allows users to retrieve the "extras" data that can be attached to many
+ * glTF objects (which can be arbitrary JSON data). This is a legacy function, consider using
+ * cgltf_extras::data directly instead. You can parse this data using your own JSON parser
  * or, if you've included the cgltf implementation using the integrated JSMN JSON parser.
  */
 #ifndef CGLTF_H_INCLUDED__
 #define CGLTF_H_INCLUDED__
 
 #include <stddef.h>
+#include <stdint.h> /* For uint8_t, uint32_t */
 
 #ifdef __cplusplus
 extern "C" {
@@ -256,8 +253,10 @@ } cgltf_data_free_method;
 
 typedef struct cgltf_extras {
-	cgltf_size start_offset;
-	cgltf_size end_offset;
+	cgltf_size start_offset; /* this field is deprecated and will be removed in the future; use data instead */
+	cgltf_size end_offset; /* this field is deprecated and will be removed in the future; use data instead */
+
+	char* data;
 } cgltf_extras;
 
 typedef struct cgltf_extension {
@@ -432,8 +431,6 @@ 	cgltf_float base_color_factor[4];
 	cgltf_float metallic_factor;
 	cgltf_float roughness_factor;
-
-	cgltf_extras extras;
 } cgltf_pbr_metallic_roughness;
 
 typedef struct cgltf_pbr_specular_glossiness
@@ -833,6 +830,8 @@ void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix);
 void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix);
 
+const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view);
+
 cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
 cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
 cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
@@ -841,6 +840,7 @@ 
 cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
 
+/* this function is deprecated and will be removed in the future; use cgltf_extras::data instead */
 cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size);
 
 #ifdef __cplusplus
@@ -863,7 +863,6 @@ 
 #ifdef CGLTF_IMPLEMENTATION
 
-#include <stdint.h> /* For uint8_t, uint32_t */
 #include <string.h> /* For strncpy */
 #include <stdio.h>  /* For fopen */
 #include <limits.h> /* For UINT_MAX etc */
@@ -905,15 +904,15 @@ };
 typedef struct {
 	jsmntype_t type;
-	int start;
-	int end;
+	ptrdiff_t start;
+	ptrdiff_t end;
 	int size;
 #ifdef JSMN_PARENT_LINKS
 	int parent;
 #endif
 } jsmntok_t;
 typedef struct {
-	unsigned int pos; /* offset in the JSON string */
+	size_t pos; /* offset in the JSON string */
 	unsigned int toknext; /* next token to allocate */
 	int toksuper; /* superior token node, e.g parent object or array */
 } jsmn_parser;
@@ -924,12 +923,15 @@  */
 
 
+#ifndef CGLTF_CONSTS
 static const cgltf_size GlbHeaderSize = 12;
 static const cgltf_size GlbChunkHeaderSize = 8;
 static const uint32_t GlbVersion = 2;
 static const uint32_t GlbMagic = 0x46546C67;
 static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
 static const uint32_t GlbMagicBinChunk = 0x004E4942;
+#define CGLTF_CONSTS
+#endif
 
 #ifndef CGLTF_MALLOC
 #define CGLTF_MALLOC(size) malloc(size)
@@ -1745,8 +1747,13 @@ 	return cgltf_result_success;
 }
 
-void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions, cgltf_size extensions_count)
+static void cgltf_free_extras(cgltf_data* data, cgltf_extras* extras)
 {
+	data->memory.free_func(data->memory.user_data, extras->data);
+}
+
+static void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions, cgltf_size extensions_count)
+{
 	for (cgltf_size i = 0; i < extensions_count; ++i)
 	{
 		data->memory.free_func(data->memory.user_data, extensions[i].name);
@@ -1755,6 +1762,12 @@ 	data->memory.free_func(data->memory.user_data, extensions);
 }
 
+static void cgltf_free_texture_view(cgltf_data* data, cgltf_texture_view* view)
+{
+	cgltf_free_extensions(data, view->extensions, view->extensions_count);
+	cgltf_free_extras(data, &view->extras);
+}
+
 void cgltf_free(cgltf_data* data)
 {
 	if (!data)
@@ -1770,6 +1783,7 @@ 	data->memory.free_func(data->memory.user_data, data->asset.min_version);
 
 	cgltf_free_extensions(data, data->asset.extensions, data->asset.extensions_count);
+	cgltf_free_extras(data, &data->asset.extras);
 
 	for (cgltf_size i = 0; i < data->accessors_count; ++i)
 	{
@@ -1780,8 +1794,12 @@ 			cgltf_free_extensions(data, data->accessors[i].sparse.extensions, data->accessors[i].sparse.extensions_count);
 			cgltf_free_extensions(data, data->accessors[i].sparse.indices_extensions, data->accessors[i].sparse.indices_extensions_count);
 			cgltf_free_extensions(data, data->accessors[i].sparse.values_extensions, data->accessors[i].sparse.values_extensions_count);
+			cgltf_free_extras(data, &data->accessors[i].sparse.extras);
+			cgltf_free_extras(data, &data->accessors[i].sparse.indices_extras);
+			cgltf_free_extras(data, &data->accessors[i].sparse.values_extras);
 		}
 		cgltf_free_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count);
+		cgltf_free_extras(data, &data->accessors[i].extras);
 	}
 	data->memory.free_func(data->memory.user_data, data->accessors);
 
@@ -1791,6 +1809,7 @@ 		data->memory.free_func(data->memory.user_data, data->buffer_views[i].data);
 
 		cgltf_free_extensions(data, data->buffer_views[i].extensions, data->buffer_views[i].extensions_count);
+		cgltf_free_extras(data, &data->buffer_views[i].extras);
 	}
 	data->memory.free_func(data->memory.user_data, data->buffer_views);
 
@@ -1810,8 +1829,8 @@ 		data->memory.free_func(data->memory.user_data, data->buffers[i].uri);
 
 		cgltf_free_extensions(data, data->buffers[i].extensions, data->buffers[i].extensions_count);
+		cgltf_free_extras(data, &data->buffers[i].extras);
 	}
-
 	data->memory.free_func(data->memory.user_data, data->buffers);
 
 	for (cgltf_size i = 0; i < data->meshes_count; ++i)
@@ -1849,9 +1868,15 @@ 				data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes);
 			}
 
+			for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
+			{
+				cgltf_free_extras(data, &data->meshes[i].primitives[j].mappings[k].extras);
+			}
+
 			data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].mappings);
 
 			cgltf_free_extensions(data, data->meshes[i].primitives[j].extensions, data->meshes[i].primitives[j].extensions_count);
+			cgltf_free_extras(data, &data->meshes[i].primitives[j].extras);
 		}
 
 		data->memory.free_func(data->memory.user_data, data->meshes[i].primitives);
@@ -1863,6 +1888,7 @@ 		}
 
 		cgltf_free_extensions(data, data->meshes[i].extensions, data->meshes[i].extensions_count);
+		cgltf_free_extras(data, &data->meshes[i].extras);
 
 		data->memory.free_func(data->memory.user_data, data->meshes[i].target_names);
 	}
@@ -1875,49 +1901,50 @@ 
 		if(data->materials[i].has_pbr_metallic_roughness)
 		{
-			cgltf_free_extensions(data, data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.extensions, data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.extensions_count);
-			cgltf_free_extensions(data, data->materials[i].pbr_metallic_roughness.base_color_texture.extensions, data->materials[i].pbr_metallic_roughness.base_color_texture.extensions_count);
+			cgltf_free_texture_view(data, &data->materials[i].pbr_metallic_roughness.metallic_roughness_texture);
+			cgltf_free_texture_view(data, &data->materials[i].pbr_metallic_roughness.base_color_texture);
 		}
 		if(data->materials[i].has_pbr_specular_glossiness)
 		{
-			cgltf_free_extensions(data, data->materials[i].pbr_specular_glossiness.diffuse_texture.extensions, data->materials[i].pbr_specular_glossiness.diffuse_texture.extensions_count);
-			cgltf_free_extensions(data, data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.extensions, data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.extensions_count);
+			cgltf_free_texture_view(data, &data->materials[i].pbr_specular_glossiness.diffuse_texture);
+			cgltf_free_texture_view(data, &data->materials[i].pbr_specular_glossiness.specular_glossiness_texture);
 		}
 		if(data->materials[i].has_clearcoat)
 		{
-			cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_texture.extensions, data->materials[i].clearcoat.clearcoat_texture.extensions_count);
-			cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_roughness_texture.extensions, data->materials[i].clearcoat.clearcoat_roughness_texture.extensions_count);
-			cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_normal_texture.extensions, data->materials[i].clearcoat.clearcoat_normal_texture.extensions_count);
+			cgltf_free_texture_view(data, &data->materials[i].clearcoat.clearcoat_texture);
+			cgltf_free_texture_view(data, &data->materials[i].clearcoat.clearcoat_roughness_texture);
+			cgltf_free_texture_view(data, &data->materials[i].clearcoat.clearcoat_normal_texture);
 		}
 		if(data->materials[i].has_specular)
 		{
-			cgltf_free_extensions(data, data->materials[i].specular.specular_texture.extensions, data->materials[i].specular.specular_texture.extensions_count);
-			cgltf_free_extensions(data, data->materials[i].specular.specular_color_texture.extensions, data->materials[i].specular.specular_color_texture.extensions_count);
+			cgltf_free_texture_view(data, &data->materials[i].specular.specular_texture);
+			cgltf_free_texture_view(data, &data->materials[i].specular.specular_color_texture);
 		}
 		if(data->materials[i].has_transmission)
 		{
-			cgltf_free_extensions(data, data->materials[i].transmission.transmission_texture.extensions, data->materials[i].transmission.transmission_texture.extensions_count);
+			cgltf_free_texture_view(data, &data->materials[i].transmission.transmission_texture);
 		}
 		if (data->materials[i].has_volume)
 		{
-			cgltf_free_extensions(data, data->materials[i].volume.thickness_texture.extensions, data->materials[i].volume.thickness_texture.extensions_count);
+			cgltf_free_texture_view(data, &data->materials[i].volume.thickness_texture);
 		}
 		if(data->materials[i].has_sheen)
 		{
-			cgltf_free_extensions(data, data->materials[i].sheen.sheen_color_texture.extensions, data->materials[i].sheen.sheen_color_texture.extensions_count);
-			cgltf_free_extensions(data, data->materials[i].sheen.sheen_roughness_texture.extensions, data->materials[i].sheen.sheen_roughness_texture.extensions_count);
+			cgltf_free_texture_view(data, &data->materials[i].sheen.sheen_color_texture);
+			cgltf_free_texture_view(data, &data->materials[i].sheen.sheen_roughness_texture);
 		}
 		if(data->materials[i].has_iridescence)
 		{
-			cgltf_free_extensions(data, data->materials[i].iridescence.iridescence_texture.extensions, data->materials[i].iridescence.iridescence_texture.extensions_count);
-			cgltf_free_extensions(data, data->materials[i].iridescence.iridescence_thickness_texture.extensions, data->materials[i].iridescence.iridescence_thickness_texture.extensions_count);
+			cgltf_free_texture_view(data, &data->materials[i].iridescence.iridescence_texture);
+			cgltf_free_texture_view(data, &data->materials[i].iridescence.iridescence_thickness_texture);
 		}
 
-		cgltf_free_extensions(data, data->materials[i].normal_texture.extensions, data->materials[i].normal_texture.extensions_count);
-		cgltf_free_extensions(data, data->materials[i].occlusion_texture.extensions, data->materials[i].occlusion_texture.extensions_count);
-		cgltf_free_extensions(data, data->materials[i].emissive_texture.extensions, data->materials[i].emissive_texture.extensions_count);
+		cgltf_free_texture_view(data, &data->materials[i].normal_texture);
+		cgltf_free_texture_view(data, &data->materials[i].occlusion_texture);
+		cgltf_free_texture_view(data, &data->materials[i].emissive_texture);
 
 		cgltf_free_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count);
+		cgltf_free_extras(data, &data->materials[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->materials);
@@ -1929,6 +1956,7 @@ 		data->memory.free_func(data->memory.user_data, data->images[i].mime_type);
 
 		cgltf_free_extensions(data, data->images[i].extensions, data->images[i].extensions_count);
+		cgltf_free_extras(data, &data->images[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->images);
@@ -1936,7 +1964,9 @@ 	for (cgltf_size i = 0; i < data->textures_count; ++i)
 	{
 		data->memory.free_func(data->memory.user_data, data->textures[i].name);
+
 		cgltf_free_extensions(data, data->textures[i].extensions, data->textures[i].extensions_count);
+		cgltf_free_extras(data, &data->textures[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->textures);
@@ -1944,7 +1974,9 @@ 	for (cgltf_size i = 0; i < data->samplers_count; ++i)
 	{
 		data->memory.free_func(data->memory.user_data, data->samplers[i].name);
+
 		cgltf_free_extensions(data, data->samplers[i].extensions, data->samplers[i].extensions_count);
+		cgltf_free_extras(data, &data->samplers[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->samplers);
@@ -1955,6 +1987,7 @@ 		data->memory.free_func(data->memory.user_data, data->skins[i].joints);
 
 		cgltf_free_extensions(data, data->skins[i].extensions, data->skins[i].extensions_count);
+		cgltf_free_extras(data, &data->skins[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->skins);
@@ -1962,7 +1995,18 @@ 	for (cgltf_size i = 0; i < data->cameras_count; ++i)
 	{
 		data->memory.free_func(data->memory.user_data, data->cameras[i].name);
+
+		if (data->cameras[i].type == cgltf_camera_type_perspective)
+		{
+			cgltf_free_extras(data, &data->cameras[i].data.perspective.extras);
+		}
+		else if (data->cameras[i].type == cgltf_camera_type_orthographic)
+		{
+			cgltf_free_extras(data, &data->cameras[i].data.orthographic.extras);
+		}
+
 		cgltf_free_extensions(data, data->cameras[i].extensions, data->cameras[i].extensions_count);
+		cgltf_free_extras(data, &data->cameras[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->cameras);
@@ -1970,6 +2014,8 @@ 	for (cgltf_size i = 0; i < data->lights_count; ++i)
 	{
 		data->memory.free_func(data->memory.user_data, data->lights[i].name);
+
+		cgltf_free_extras(data, &data->lights[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->lights);
@@ -1979,7 +2025,19 @@ 		data->memory.free_func(data->memory.user_data, data->nodes[i].name);
 		data->memory.free_func(data->memory.user_data, data->nodes[i].children);
 		data->memory.free_func(data->memory.user_data, data->nodes[i].weights);
+
+		if (data->nodes[i].has_mesh_gpu_instancing)
+		{
+			for (cgltf_size j = 0; j < data->nodes[i].mesh_gpu_instancing.attributes_count; ++j)
+			{
+				data->memory.free_func(data->memory.user_data, data->nodes[i].mesh_gpu_instancing.attributes[j].name);
+			}
+
+			data->memory.free_func(data->memory.user_data, data->nodes[i].mesh_gpu_instancing.attributes);
+		}
+
 		cgltf_free_extensions(data, data->nodes[i].extensions, data->nodes[i].extensions_count);
+		cgltf_free_extras(data, &data->nodes[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->nodes);
@@ -1990,6 +2048,7 @@ 		data->memory.free_func(data->memory.user_data, data->scenes[i].nodes);
 
 		cgltf_free_extensions(data, data->scenes[i].extensions, data->scenes[i].extensions_count);
+		cgltf_free_extras(data, &data->scenes[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->scenes);
@@ -2000,16 +2059,19 @@ 		for (cgltf_size j = 0; j <  data->animations[i].samplers_count; ++j)
 		{
 			cgltf_free_extensions(data, data->animations[i].samplers[j].extensions, data->animations[i].samplers[j].extensions_count);
+			cgltf_free_extras(data, &data->animations[i].samplers[j].extras);
 		}
 		data->memory.free_func(data->memory.user_data, data->animations[i].samplers);
 
 		for (cgltf_size j = 0; j <  data->animations[i].channels_count; ++j)
 		{
 			cgltf_free_extensions(data, data->animations[i].channels[j].extensions, data->animations[i].channels[j].extensions_count);
+			cgltf_free_extras(data, &data->animations[i].channels[j].extras);
 		}
 		data->memory.free_func(data->memory.user_data, data->animations[i].channels);
 
 		cgltf_free_extensions(data, data->animations[i].extensions, data->animations[i].extensions_count);
+		cgltf_free_extras(data, &data->animations[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->animations);
@@ -2017,11 +2079,14 @@ 	for (cgltf_size i = 0; i < data->variants_count; ++i)
 	{
 		data->memory.free_func(data->memory.user_data, data->variants[i].name);
+
+		cgltf_free_extras(data, &data->variants[i].extras);
 	}
 
 	data->memory.free_func(data->memory.user_data, data->variants);
 
 	cgltf_free_extensions(data, data->data_extensions, data->data_extensions_count);
+	cgltf_free_extras(data, &data->extras);
 
 	for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
 	{
@@ -2440,7 +2505,7 @@ {
 	CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING);
 	size_t const str_len = strlen(str);
-	size_t const name_length = tok->end - tok->start;
+	size_t const name_length = (size_t)(tok->end - tok->start);
 	return (str_len == name_length) ? strncmp((const char*)json_chunk + tok->start, str, str_len) : 128;
 }
 
@@ -2448,7 +2513,7 @@ {
 	CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
 	char tmp[128];
-	int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
+	int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
 	strncpy(tmp, (const char*)json_chunk + tok->start, size);
 	tmp[size] = 0;
 	return CGLTF_ATOI(tmp);
@@ -2458,7 +2523,7 @@ {
 	CGLTF_CHECK_TOKTYPE_RETTYPE(*tok, JSMN_PRIMITIVE, cgltf_size);
 	char tmp[128];
-	int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
+	int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
 	strncpy(tmp, (const char*)json_chunk + tok->start, size);
 	tmp[size] = 0;
 	return (cgltf_size)CGLTF_ATOLL(tmp);
@@ -2468,7 +2533,7 @@ {
 	CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
 	char tmp[128];
-	int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
+	int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
 	strncpy(tmp, (const char*)json_chunk + tok->start, size);
 	tmp[size] = 0;
 	return (cgltf_float)CGLTF_ATOF(tmp);
@@ -2476,7 +2541,7 @@ 
 static cgltf_bool cgltf_json_to_bool(jsmntok_t const* tok, const uint8_t* json_chunk)
 {
-	int size = tok->end - tok->start;
+	int size = (int)(tok->end - tok->start);
 	return size == 4 && memcmp(json_chunk + tok->start, "true", 4) == 0;
 }
 
@@ -2542,7 +2607,7 @@ 	{
 		return CGLTF_ERROR_JSON;
 	}
-	int size = tokens[i].end - tokens[i].start;
+	int size = (int)(tokens[i].end - tokens[i].start);
 	char* result = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
 	if (!result)
 	{
@@ -2683,11 +2748,27 @@ 	return i;
 }
 
-static int cgltf_parse_json_extras(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extras* out_extras)
+static int cgltf_parse_json_extras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extras* out_extras)
 {
-	(void)json_chunk;
+	if (out_extras->data)
+	{
+		return CGLTF_ERROR_JSON;
+	}
+
+	/* fill deprecated fields for now, this will be removed in the future */
 	out_extras->start_offset = tokens[i].start;
 	out_extras->end_offset = tokens[i].end;
+
+	size_t start = tokens[i].start;
+	size_t size = tokens[i].end - start;
+	out_extras->data = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
+	if (!out_extras->data)
+	{
+		return CGLTF_ERROR_NOMEM;
+	}
+	strncpy(out_extras->data, (const char*)json_chunk + start, size);
+	out_extras->data[size] = '\0';
+
 	i = cgltf_skip_json(tokens, i);
 	return i;
 }
@@ -2842,7 +2923,7 @@ 
 		int material = -1;
 		int variants_tok = -1;
-		cgltf_extras extras = {0, 0};
+		int extras_tok = -1;
 
 		for (int k = 0; k < obj_size; ++k)
 		{
@@ -2863,7 +2944,8 @@ 			}
 			else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 			{
-				i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &extras);
+				extras_tok = i + 1;
+				i = cgltf_skip_json(tokens, extras_tok);
 			}
 			else
 			{
@@ -2891,8 +2973,14 @@ 
 				out_mappings[*offset].material = CGLTF_PTRINDEX(cgltf_material, material);
 				out_mappings[*offset].variant = variant;
-				out_mappings[*offset].extras = extras;
 
+				if (extras_tok >= 0)
+				{
+					int e = cgltf_parse_json_extras(options, tokens, extras_tok, json_chunk, &out_mappings[*offset].extras);
+					if (e < 0)
+						return e;
+				}
+
 				(*offset)++;
 			}
 		}
@@ -3006,7 +3094,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_prim->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_prim->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -3253,7 +3341,7 @@ 				}
 				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 				{
-					i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->indices_extras);
+					i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sparse->indices_extras);
 				}
 				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 				{
@@ -3296,7 +3384,7 @@ 				}
 				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 				{
-					i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->values_extras);
+					i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sparse->values_extras);
 				}
 				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 				{
@@ -3315,7 +3403,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sparse->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sparse->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -3438,7 +3526,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_accessor->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_accessor->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -3544,7 +3632,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture_view->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_texture_view->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -3640,10 +3728,6 @@ 			i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
 				&out_pbr->metallic_roughness_texture);
 		}
-		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
-		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_pbr->extras);
-		}
 		else
 		{
 			i = cgltf_skip_json(tokens, i+1);
@@ -4076,7 +4160,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_image->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_image->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -4145,7 +4229,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -4194,7 +4278,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_texture->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_texture->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -4357,7 +4441,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_material->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_material->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -4710,7 +4794,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer_view->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer_view->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -4813,7 +4897,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_buffer->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -4897,7 +4981,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_skin->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_skin->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -4951,19 +5035,6 @@ 		{
 			i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name);
 		}
-		else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
-		{
-			++i;
-			if (cgltf_json_strcmp(tokens + i, json_chunk, "perspective") == 0)
-			{
-				out_camera->type = cgltf_camera_type_perspective;
-			}
-			else if (cgltf_json_strcmp(tokens + i, json_chunk, "orthographic") == 0)
-			{
-				out_camera->type = cgltf_camera_type_orthographic;
-			}
-			++i;
-		}
 		else if (cgltf_json_strcmp(tokens+i, json_chunk, "perspective") == 0)
 		{
 			++i;
@@ -4973,6 +5044,11 @@ 			int data_size = tokens[i].size;
 			++i;
 
+			if (out_camera->type != cgltf_camera_type_invalid)
+			{
+				return CGLTF_ERROR_JSON;
+			}
+
 			out_camera->type = cgltf_camera_type_perspective;
 
 			for (int k = 0; k < data_size; ++k)
@@ -5007,7 +5083,7 @@ 				}
 				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 				{
-					i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
+					i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
 				}
 				else
 				{
@@ -5029,6 +5105,11 @@ 			int data_size = tokens[i].size;
 			++i;
 
+			if (out_camera->type != cgltf_camera_type_invalid)
+			{
+				return CGLTF_ERROR_JSON;
+			}
+
 			out_camera->type = cgltf_camera_type_orthographic;
 
 			for (int k = 0; k < data_size; ++k)
@@ -5061,7 +5142,7 @@ 				}
 				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 				{
-					i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
+					i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
 				}
 				else
 				{
@@ -5076,7 +5157,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -5209,7 +5290,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_light->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_light->extras);
 		}
 		else
 		{
@@ -5335,7 +5416,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_node->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_node->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -5473,7 +5554,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_scene->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_scene->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -5555,7 +5636,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_sampler->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -5635,7 +5716,7 @@ 				}
 				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 				{
-					i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_channel->extras);
+					i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_channel->extras);
 				}
 				else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 				{
@@ -5717,7 +5798,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_animation->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_animation->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -5773,7 +5854,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_variant->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_variant->extras);
 		}
 		else
 		{
@@ -5837,7 +5918,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_asset->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_asset->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -5993,7 +6074,7 @@ 		}
 		else if (cgltf_json_strcmp(tokens+i, json_chunk, "extras") == 0)
 		{
-			i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_data->extras);
+			i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_data->extras);
 		}
 		else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
 		{
@@ -6420,7 +6501,7 @@  * Fills token type and boundaries.
  */
 static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
-				int start, int end) {
+				ptrdiff_t start, ptrdiff_t end) {
 	token->type = type;
 	token->start = start;
 	token->end = end;
@@ -6433,7 +6514,7 @@ static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
 				size_t len, jsmntok_t *tokens, size_t num_tokens) {
 	jsmntok_t *token;
-	int start;
+	ptrdiff_t start;
 
 	start = parser->pos;
 
@@ -6483,7 +6564,7 @@ 				 size_t len, jsmntok_t *tokens, size_t num_tokens) {
 	jsmntok_t *token;
 
-	int start = parser->pos;
+	ptrdiff_t start = parser->pos;
 
 	parser->pos++;
 
raylib/src/external/dr_flac.h view
@@ -1,6 +1,6 @@ /*
 FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
-dr_flac - v0.12.31 - 2021-08-16
+dr_flac - v0.12.39 - 2022-09-17
 
 David Reid - mackron@gmail.com
 
@@ -210,8 +210,11 @@ #define DR_FLAC_NO_SIMD
   Disables SIMD optimizations (SSE on x86/x64 architectures, NEON on ARM architectures). Use this if you are having compatibility issues with your compiler.
 
+#define DR_FLAC_NO_WCHAR
+  Disables all functions ending with `_w`. Use this if your compiler does not provide wchar.h. Not required if DR_FLAC_NO_STDIO is also defined.
 
 
+
 Notes
 =====
 - dr_flac does not support changing the sample rate nor channel count mid stream.
@@ -232,7 +235,7 @@ 
 #define DRFLAC_VERSION_MAJOR     0
 #define DRFLAC_VERSION_MINOR     12
-#define DRFLAC_VERSION_REVISION  31
+#define DRFLAC_VERSION_REVISION  39
 #define DRFLAC_VERSION_STRING    DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
 
 #include <stddef.h> /* For size_t. */
@@ -244,7 +247,7 @@ typedef unsigned short          drflac_uint16;
 typedef   signed int            drflac_int32;
 typedef unsigned int            drflac_uint32;
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && !defined(__clang__)
     typedef   signed __int64    drflac_int64;
     typedef unsigned __int64    drflac_uint64;
 #else
@@ -261,7 +264,7 @@         #pragma GCC diagnostic pop
     #endif
 #endif
-#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
+#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
     typedef drflac_uint64       drflac_uintptr;
 #else
     typedef drflac_uint32       drflac_uintptr;
@@ -383,15 +386,13 @@     drflac_seek_origin_current
 } drflac_seek_origin;
 
-/* Packing is important on this structure because we map this directly to the raw data within the SEEKTABLE metadata block. */
-#pragma pack(2)
+/* The order of members in this structure is important because we map this directly to the raw data within the SEEKTABLE metadata block. */
 typedef struct
 {
     drflac_uint64 firstPCMFrame;
     drflac_uint64 flacFrameOffset;   /* The offset from the first byte of the header of the first frame. */
     drflac_uint16 pcmFrameCount;
 } drflac_seekpoint;
-#pragma pack()
 
 typedef struct
 {
@@ -1280,15 +1281,13 @@     const char* pRunningData;
 } drflac_cuesheet_track_iterator;
 
-/* Packing is important on this structure because we map this directly to the raw data within the CUESHEET metadata block. */
-#pragma pack(4)
+/* The order of members here is important because we map this directly to the raw data within the CUESHEET metadata block. */
 typedef struct
 {
     drflac_uint64 offset;
     drflac_uint8 index;
     drflac_uint8 reserved[3];
 } drflac_cuesheet_track_index;
-#pragma pack()
 
 typedef struct
 {
@@ -1363,10 +1362,16 @@     I am using "__inline__" only when we're compiling in strict ANSI mode.
     */
     #if defined(__STRICT_ANSI__)
-        #define DRFLAC_INLINE __inline__ __attribute__((always_inline))
+        #define DRFLAC_GNUC_INLINE_HINT __inline__
     #else
-        #define DRFLAC_INLINE inline __attribute__((always_inline))
+        #define DRFLAC_GNUC_INLINE_HINT inline
     #endif
+
+    #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
+        #define DRFLAC_INLINE DRFLAC_GNUC_INLINE_HINT __attribute__((always_inline))
+    #else
+        #define DRFLAC_INLINE DRFLAC_GNUC_INLINE_HINT
+    #endif
 #elif defined(__WATCOMC__)
     #define DRFLAC_INLINE __inline
 #else
@@ -1378,7 +1383,7 @@     #define DRFLAC_X64
 #elif defined(__i386) || defined(_M_IX86)
     #define DRFLAC_X86
-#elif defined(__arm__) || defined(_M_ARM) || defined(_M_ARM64)
+#elif defined(__arm__) || defined(_M_ARM) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)
     #define DRFLAC_ARM
 #endif
 
@@ -1431,16 +1436,6 @@     #if defined(DRFLAC_ARM)
         #if !defined(DRFLAC_NO_NEON) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
             #define DRFLAC_SUPPORT_NEON
-        #endif
-
-        /* Fall back to looking for the #include file. */
-        #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
-            #if !defined(DRFLAC_SUPPORT_NEON) && !defined(DRFLAC_NO_NEON) && __has_include(<arm_neon.h>)
-                #define DRFLAC_SUPPORT_NEON
-            #endif
-        #endif
-
-        #if defined(DRFLAC_SUPPORT_NEON)
             #include <arm_neon.h>
         #endif
     #endif
@@ -1519,9 +1514,7 @@ {
 #if defined(DRFLAC_SUPPORT_SSE41)
     #if (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(DRFLAC_NO_SSE41)
-        #if defined(DRFLAC_X64)
-            return DRFLAC_TRUE;    /* 64-bit targets always support SSE4.1. */
-        #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE4_1__)
+        #if defined(__SSE4_1__) || defined(__AVX__)
             return DRFLAC_TRUE;    /* If the compiler is allowed to freely generate SSE41 code we can assume support. */
         #else
             #if defined(DRFLAC_NO_CPUID)
@@ -1586,18 +1579,21 @@     extern __inline drflac_uint64 _watcom_bswap64(drflac_uint64);
 #pragma aux _watcom_bswap16 = \
     "xchg al, ah" \
-    parm   [ax]   \
-    modify [ax];
+    parm  [ax]    \
+    value [ax]    \
+    modify nomemory;
 #pragma aux _watcom_bswap32 = \
-    "bswap eax"  \
-    parm   [eax] \
-    modify [eax];
+    "bswap eax" \
+    parm  [eax] \
+    value [eax] \
+    modify nomemory;
 #pragma aux _watcom_bswap64 = \
     "bswap eax"     \
     "bswap edx"     \
     "xchg eax,edx"  \
     parm [eax edx]  \
-    modify [eax edx];
+    value [eax edx] \
+    modify nomemory;
 #endif
 
 
@@ -1698,6 +1694,10 @@ #define DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE            9
 #define DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE              10
 
+#define DRFLAC_SEEKPOINT_SIZE_IN_BYTES                  18
+#define DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES             36
+#define DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES       12
+
 #define drflac_align(x, a)                              ((((x) + (a) - 1) / (a)) * (a))
 
 
@@ -1909,6 +1909,12 @@     return n;
 }
 
+static DRFLAC_INLINE drflac_uint32 drflac__be2host_32_ptr_unaligned(const void* pData)
+{
+    const drflac_uint8* pNum = (drflac_uint8*)pData;
+    return *(pNum) << 24 | *(pNum+1) << 16 | *(pNum+2) << 8 | *(pNum+3);
+}
+
 static DRFLAC_INLINE drflac_uint64 drflac__be2host_64(drflac_uint64 n)
 {
     if (drflac__is_little_endian()) {
@@ -1928,7 +1934,13 @@     return n;
 }
 
+static DRFLAC_INLINE drflac_uint32 drflac__le2host_32_ptr_unaligned(const void* pData)
+{
+    const drflac_uint8* pNum = (drflac_uint8*)pData;
+    return *pNum | *(pNum+1) << 8 |  *(pNum+2) << 16 | *(pNum+3) << 24;
+}
 
+
 static DRFLAC_INLINE drflac_uint32 drflac__unsynchsafe_32(drflac_uint32 n)
 {
     drflac_uint32 result = 0;
@@ -2429,6 +2441,10 @@         if (!drflac__reload_cache(bs)) {
             return DRFLAC_FALSE;
         }
+        if (bitCountLo > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+            /* This happens when we get to end of stream */
+            return DRFLAC_FALSE;
+        }
 
         *pResultOut = (resultHi << bitCountLo) | (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountLo);
         bs->consumedBits += bitCountLo;
@@ -2684,6 +2700,10 @@ #if  defined(__WATCOMC__) && defined(__386__)
 #define DRFLAC_IMPLEMENT_CLZ_WATCOM
 #endif
+#ifdef __MRC__
+#include <intrinsics.h>
+#define DRFLAC_IMPLEMENT_CLZ_MRC
+#endif
 
 static DRFLAC_INLINE drflac_uint32 drflac__clz_software(drflac_cache_t x)
 {
@@ -2724,6 +2744,8 @@     /* Fast compile time check for ARM. */
 #if defined(DRFLAC_HAS_LZCNT_INTRINSIC) && defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5)
     return DRFLAC_TRUE;
+#elif defined(__MRC__)
+    return DRFLAC_TRUE;
 #else
     /* If the compiler itself does not support the intrinsic then we'll need to return false. */
     #ifdef DRFLAC_HAS_LZCNT_INTRINSIC
@@ -2833,6 +2855,15 @@ 
 #ifdef DRFLAC_IMPLEMENT_CLZ_WATCOM
 static __inline drflac_uint32 drflac__clz_watcom (drflac_uint32);
+#ifdef DRFLAC_IMPLEMENT_CLZ_WATCOM_LZCNT
+/* Use the LZCNT instruction (only available on some processors since the 2010s). */
+#pragma aux drflac__clz_watcom_lzcnt = \
+    "db 0F3h, 0Fh, 0BDh, 0C0h" /* lzcnt eax, eax */ \
+    parm [eax] \
+    value [eax] \
+    modify nomemory;
+#else
+/* Use the 386+-compatible implementation. */
 #pragma aux drflac__clz_watcom = \
     "bsr eax, eax" \
     "xor eax, 31" \
@@ -2840,6 +2871,7 @@     value [eax] \
     modify exact [eax] nomemory;
 #endif
+#endif
 
 static DRFLAC_INLINE drflac_uint32 drflac__clz(drflac_cache_t x)
 {
@@ -2851,8 +2883,12 @@     {
 #ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
         return drflac__clz_msvc(x);
+#elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM_LZCNT)
+        return drflac__clz_watcom_lzcnt(x);
 #elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM)
         return (x == 0) ? sizeof(x)*8 : drflac__clz_watcom(x);
+#elif defined(__MRC__)
+        return __cntlzw(x);
 #else
         return drflac__clz_software(x);
 #endif
@@ -2872,9 +2908,24 @@         }
     }
 
+    if (bs->cache == 1) {
+        /* Not catching this would lead to undefined behaviour: a shift of a 32-bit number by 32 or more is undefined */
+        *pOffsetOut = zeroCounter + (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs) - 1;
+        if (!drflac__reload_cache(bs)) {
+            return DRFLAC_FALSE;
+        }
+
+        return DRFLAC_TRUE;
+    }
+
     setBitOffsetPlus1 = drflac__clz(bs->cache);
     setBitOffsetPlus1 += 1;
 
+    if (setBitOffsetPlus1 > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+        /* This happens when we get to end of stream */
+        return DRFLAC_FALSE;
+    }
+
     bs->consumedBits += setBitOffsetPlus1;
     bs->cache <<= setBitOffsetPlus1;
 
@@ -2989,13 +3040,35 @@ }
 
 
+static DRFLAC_INLINE drflac_uint32 drflac__ilog2_u32(drflac_uint32 x)
+{
+#if 1   /* Needs optimizing. */
+    drflac_uint32 result = 0;
+    while (x > 0) {
+        result += 1;
+        x >>= 1;
+    }
 
+    return result;
+#endif
+}
+
+static DRFLAC_INLINE drflac_bool32 drflac__use_64_bit_prediction(drflac_uint32 bitsPerSample, drflac_uint32 order, drflac_uint32 precision)
+{
+    /* https://web.archive.org/web/20220205005724/https://github.com/ietf-wg-cellar/flac-specification/blob/37a49aa48ba4ba12e8757badfc59c0df35435fec/rfc_backmatter.md */
+    return bitsPerSample + precision + drflac__ilog2_u32(order) > 32;
+}
+
+
 /*
 The next two functions are responsible for calculating the prediction.
 
 When the bits per sample is >16 we need to use 64-bit integer arithmetic because otherwise we'll run out of precision. It's
 safe to assume this will be slower on 32-bit platforms so we use a more optimal solution when the bits per sample is <=16.
 */
+#if defined(__clang__)
+__attribute__((no_sanitize("signed-integer-overflow")))
+#endif
 static DRFLAC_INLINE drflac_int32 drflac__calculate_prediction_32(drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pDecodedSamples)
 {
     drflac_int32 prediction = 0;
@@ -3231,7 +3304,7 @@ Reference implementation for reading and decoding samples with residual. This is intentionally left unoptimized for the
 sake of readability and should only be used as a reference.
 */
-static drflac_bool32 drflac__decode_samples_with_residual__rice__reference(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+static drflac_bool32 drflac__decode_samples_with_residual__rice__reference(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
 {
     drflac_uint32 i;
 
@@ -3270,10 +3343,10 @@         }
 
 
-        if (bitsPerSample+shift >= 32) {
-            pSamplesOut[i] = decodedRice + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i);
+        if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+            pSamplesOut[i] = decodedRice + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + i);
         } else {
-            pSamplesOut[i] = decodedRice + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + i);
+            pSamplesOut[i] = decodedRice + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + i);
         }
     }
 
@@ -3370,6 +3443,10 @@             if (!drflac__reload_cache(bs)) {
                 return DRFLAC_FALSE;
             }
+            if (bitCountLo > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+                /* This happens when we get to end of stream */
+                return DRFLAC_FALSE;
+            }
         }
 
         riceParamPart = (drflac_uint32)(resultHi | DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE(bs, bitCountLo));
@@ -3450,6 +3527,10 @@                 if (!drflac__reload_cache(bs)) {
                     return DRFLAC_FALSE;
                 }
+                if (riceParamPartLoBitCount > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+                    /* This happens when we get to end of stream */
+                    return DRFLAC_FALSE;
+                }
 
                 bs_cache = bs->cache;
                 bs_consumedBits = bs->consumedBits + riceParamPartLoBitCount;
@@ -3560,6 +3641,11 @@                     return DRFLAC_FALSE;
                 }
 
+                if (riceParamPartLoBitCount > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+                    /* This happens when we get to end of stream */
+                    return DRFLAC_FALSE;
+                }
+
                 bs_cache = bs->cache;
                 bs_consumedBits = bs->consumedBits + riceParamPartLoBitCount;
             }
@@ -3646,7 +3732,7 @@     return DRFLAC_TRUE;
 }
 
-static drflac_bool32 drflac__decode_samples_with_residual__rice__scalar(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+static drflac_bool32 drflac__decode_samples_with_residual__rice__scalar(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
 {
     drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
     drflac_uint32 zeroCountPart0 = 0;
@@ -3664,14 +3750,14 @@     DRFLAC_ASSERT(bs != NULL);
     DRFLAC_ASSERT(pSamplesOut != NULL);
 
-    if (order == 0) {
-        return drflac__decode_samples_with_residual__rice__scalar_zeroorder(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
+    if (lpcOrder == 0) {
+        return drflac__decode_samples_with_residual__rice__scalar_zeroorder(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, coefficients, pSamplesOut);
     }
 
     riceParamMask  = (drflac_uint32)~((~0UL) << riceParam);
     pSamplesOutEnd = pSamplesOut + (count & ~3);
 
-    if (bitsPerSample+shift > 32) {
+    if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
         while (pSamplesOut < pSamplesOutEnd) {
             /*
             Rice extraction. It's faster to do this one at a time against local variables than it is to use the x4 version
@@ -3699,10 +3785,10 @@             riceParamPart2  = (riceParamPart2 >> 1) ^ t[riceParamPart2 & 0x01];
             riceParamPart3  = (riceParamPart3 >> 1) ^ t[riceParamPart3 & 0x01];
 
-            pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 0);
-            pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 1);
-            pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 2);
-            pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 3);
+            pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + 0);
+            pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + 1);
+            pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + 2);
+            pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + 3);
 
             pSamplesOut += 4;
         }
@@ -3730,10 +3816,10 @@             riceParamPart2  = (riceParamPart2 >> 1) ^ t[riceParamPart2 & 0x01];
             riceParamPart3  = (riceParamPart3 >> 1) ^ t[riceParamPart3 & 0x01];
 
-            pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 0);
-            pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 1);
-            pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 2);
-            pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 3);
+            pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + 0);
+            pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + 1);
+            pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + 2);
+            pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + 3);
 
             pSamplesOut += 4;
         }
@@ -3753,10 +3839,10 @@         /*riceParamPart0  = (riceParamPart0 >> 1) ^ (~(riceParamPart0 & 0x01) + 1);*/
 
         /* Sample reconstruction. */
-        if (bitsPerSample+shift > 32) {
-            pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + 0);
+        if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+            pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + 0);
         } else {
-            pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + 0);
+            pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + 0);
         }
 
         i += 1;
@@ -4212,20 +4298,20 @@     return DRFLAC_TRUE;
 }
 
-static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
 {
     DRFLAC_ASSERT(bs != NULL);
     DRFLAC_ASSERT(pSamplesOut != NULL);
 
     /* In my testing the order is rarely > 12, so in this case I'm going to simplify the SSE implementation by only handling order <= 12. */
-    if (order > 0 && order <= 12) {
-        if (bitsPerSample+shift > 32) {
-            return drflac__decode_samples_with_residual__rice__sse41_64(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
+    if (lpcOrder > 0 && lpcOrder <= 12) {
+        if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+            return drflac__decode_samples_with_residual__rice__sse41_64(bs, count, riceParam, lpcOrder, lpcShift, coefficients, pSamplesOut);
         } else {
-            return drflac__decode_samples_with_residual__rice__sse41_32(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
+            return drflac__decode_samples_with_residual__rice__sse41_32(bs, count, riceParam, lpcOrder, lpcShift, coefficients, pSamplesOut);
         }
     } else {
-        return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
+        return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
     }
 }
 #endif
@@ -4364,7 +4450,7 @@ 
     const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
 
-    riceParamMask    = ~((~0UL) << riceParam);
+    riceParamMask    = (drflac_uint32)~((~0UL) << riceParam);
     riceParamMask128 = vdupq_n_u32(riceParamMask);
 
     riceParam128 = vdupq_n_s32(riceParam);
@@ -4550,10 +4636,13 @@     int32x4_t riceParam128;
     int64x1_t shift64;
     uint32x4_t one128;
+    int64x2_t prediction128 = { 0 };
+    uint32x4_t zeroCountPart128;
+    uint32x4_t riceParamPart128;
 
     const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
 
-    riceParamMask    = ~((~0UL) << riceParam);
+    riceParamMask    = (drflac_uint32)~((~0UL) << riceParam);
     riceParamMask128 = vdupq_n_u32(riceParamMask);
 
     riceParam128 = vdupq_n_s32(riceParam);
@@ -4562,7 +4651,7 @@ 
     /*
     Pre-loading the coefficients and prior samples is annoying because we need to ensure we don't try reading more than
-    what's available in the input buffers. It would be conenient to use a fall-through switch to do this, but this results
+    what's available in the input buffers. It would be convenient to use a fall-through switch to do this, but this results
     in strict aliasing warnings with GCC. To work around this I'm just doing something hacky. This feels a bit convoluted
     so I think there's opportunity for this to be simplified.
     */
@@ -4630,10 +4719,6 @@ 
     /* For this version we are doing one sample at a time. */
     while (pDecodedSamples < pDecodedSamplesEnd) {
-        int64x2_t prediction128;
-        uint32x4_t zeroCountPart128;
-        uint32x4_t riceParamPart128;
-
         if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0]) ||
             !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[1], &riceParamParts[1]) ||
             !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[2], &riceParamParts[2]) ||
@@ -4710,41 +4795,41 @@     return DRFLAC_TRUE;
 }
 
-static drflac_bool32 drflac__decode_samples_with_residual__rice__neon(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+static drflac_bool32 drflac__decode_samples_with_residual__rice__neon(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
 {
     DRFLAC_ASSERT(bs != NULL);
     DRFLAC_ASSERT(pSamplesOut != NULL);
 
     /* In my testing the order is rarely > 12, so in this case I'm going to simplify the NEON implementation by only handling order <= 12. */
-    if (order > 0 && order <= 12) {
-        if (bitsPerSample+shift > 32) {
-            return drflac__decode_samples_with_residual__rice__neon_64(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
+    if (lpcOrder > 0 && lpcOrder <= 12) {
+        if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+            return drflac__decode_samples_with_residual__rice__neon_64(bs, count, riceParam, lpcOrder, lpcShift, coefficients, pSamplesOut);
         } else {
-            return drflac__decode_samples_with_residual__rice__neon_32(bs, count, riceParam, order, shift, coefficients, pSamplesOut);
+            return drflac__decode_samples_with_residual__rice__neon_32(bs, count, riceParam, lpcOrder, lpcShift, coefficients, pSamplesOut);
         }
     } else {
-        return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
+        return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
     }
 }
 #endif
 
-static drflac_bool32 drflac__decode_samples_with_residual__rice(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+static drflac_bool32 drflac__decode_samples_with_residual__rice(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
 {
 #if defined(DRFLAC_SUPPORT_SSE41)
     if (drflac__gIsSSE41Supported) {
-        return drflac__decode_samples_with_residual__rice__sse41(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
+        return drflac__decode_samples_with_residual__rice__sse41(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
     } else
 #elif defined(DRFLAC_SUPPORT_NEON)
     if (drflac__gIsNEONSupported) {
-        return drflac__decode_samples_with_residual__rice__neon(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
+        return drflac__decode_samples_with_residual__rice__neon(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
     } else
 #endif
     {
         /* Scalar fallback. */
     #if 0
-        return drflac__decode_samples_with_residual__rice__reference(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
+        return drflac__decode_samples_with_residual__rice__reference(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
     #else
-        return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, order, shift, coefficients, pSamplesOut);
+        return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
     #endif
     }
 }
@@ -4765,7 +4850,10 @@     return DRFLAC_TRUE;
 }
 
-static drflac_bool32 drflac__decode_samples_with_residual__unencoded(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 unencodedBitsPerSample, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+#if defined(__clang__)
+__attribute__((no_sanitize("signed-integer-overflow")))
+#endif
+static drflac_bool32 drflac__decode_samples_with_residual__unencoded(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 unencodedBitsPerSample, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
 {
     drflac_uint32 i;
 
@@ -4782,10 +4870,10 @@             pSamplesOut[i] = 0;
         }
 
-        if (bitsPerSample >= 24) {
-            pSamplesOut[i] += drflac__calculate_prediction_64(order, shift, coefficients, pSamplesOut + i);
+        if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+            pSamplesOut[i] += drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + i);
         } else {
-            pSamplesOut[i] += drflac__calculate_prediction_32(order, shift, coefficients, pSamplesOut + i);
+            pSamplesOut[i] += drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + i);
         }
     }
 
@@ -4798,7 +4886,7 @@ when the decoder is sitting at the very start of the RESIDUAL block. The first <order> residuals will be ignored. The
 <blockSize> and <order> parameters are used to determine how many residual values need to be decoded.
 */
-static drflac_bool32 drflac__decode_samples_with_residual(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 blockSize, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pDecodedSamples)
+static drflac_bool32 drflac__decode_samples_with_residual(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 blockSize, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pDecodedSamples)
 {
     drflac_uint8 residualMethod;
     drflac_uint8 partitionOrder;
@@ -4818,7 +4906,7 @@     }
 
     /* Ignore the first <order> values. */
-    pDecodedSamples += order;
+    pDecodedSamples += lpcOrder;
 
     if (!drflac__read_uint8(bs, 4, &partitionOrder)) {
         return DRFLAC_FALSE;
@@ -4833,11 +4921,11 @@     }
 
     /* Validation check. */
-    if ((blockSize / (1 << partitionOrder)) < order) {
+    if ((blockSize / (1 << partitionOrder)) < lpcOrder) {
         return DRFLAC_FALSE;
     }
 
-    samplesInPartition = (blockSize / (1 << partitionOrder)) - order;
+    samplesInPartition = (blockSize / (1 << partitionOrder)) - lpcOrder;
     partitionsRemaining = (1 << partitionOrder);
     for (;;) {
         drflac_uint8 riceParam = 0;
@@ -4858,7 +4946,7 @@         }
 
         if (riceParam != 0xFF) {
-            if (!drflac__decode_samples_with_residual__rice(bs, bitsPerSample, samplesInPartition, riceParam, order, shift, coefficients, pDecodedSamples)) {
+            if (!drflac__decode_samples_with_residual__rice(bs, bitsPerSample, samplesInPartition, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pDecodedSamples)) {
                 return DRFLAC_FALSE;
             }
         } else {
@@ -4867,7 +4955,7 @@                 return DRFLAC_FALSE;
             }
 
-            if (!drflac__decode_samples_with_residual__unencoded(bs, bitsPerSample, samplesInPartition, unencodedBitsPerSample, order, shift, coefficients, pDecodedSamples)) {
+            if (!drflac__decode_samples_with_residual__unencoded(bs, bitsPerSample, samplesInPartition, unencodedBitsPerSample, lpcOrder, lpcShift, lpcPrecision, coefficients, pDecodedSamples)) {
                 return DRFLAC_FALSE;
             }
         }
@@ -5036,7 +5124,7 @@         pDecodedSamples[i] = sample;
     }
 
-    if (!drflac__decode_samples_with_residual(bs, subframeBitsPerSample, blockSize, lpcOrder, 0, lpcCoefficientsTable[lpcOrder], pDecodedSamples)) {
+    if (!drflac__decode_samples_with_residual(bs, subframeBitsPerSample, blockSize, lpcOrder, 0, 4, lpcCoefficientsTable[lpcOrder], pDecodedSamples)) {
         return DRFLAC_FALSE;
     }
 
@@ -5091,7 +5179,7 @@         }
     }
 
-    if (!drflac__decode_samples_with_residual(bs, bitsPerSample, blockSize, lpcOrder, lpcShift, coefficients, pDecodedSamples)) {
+    if (!drflac__decode_samples_with_residual(bs, bitsPerSample, blockSize, lpcOrder, lpcShift, lpcPrecision, coefficients, pDecodedSamples)) {
         return DRFLAC_FALSE;
     }
 
@@ -5219,6 +5307,9 @@                 return DRFLAC_FALSE;
             }
             crc8 = drflac_crc8(crc8, header->blockSizeInPCMFrames, 16);
+            if (header->blockSizeInPCMFrames == 0xFFFF) {
+                return DRFLAC_FALSE;    /* Frame is too big. This is the size of the frame minus 1. The STREAMINFO block defines the max block size which is 16-bits. Adding one will make it 17 bits and therefore too big. */
+            }
             header->blockSizeInPCMFrames += 1;
         } else {
             DRFLAC_ASSERT(blockSize >= 8);
@@ -5257,6 +5348,11 @@             header->bitsPerSample = streaminfoBitsPerSample;
         }
 
+        if (header->bitsPerSample != streaminfoBitsPerSample) {
+            /* If this subframe has a different bitsPerSample then streaminfo or the first frame, reject it */
+            return DRFLAC_FALSE;
+        }
+
         if (!drflac__read_uint8(bs, 8, &header->crc8)) {
             return DRFLAC_FALSE;
         }
@@ -5343,6 +5439,11 @@         subframeBitsPerSample += 1;
     }
 
+    if (subframeBitsPerSample > 32) {
+        /* libFLAC and ffmpeg reject 33-bit subframes as well */
+        return DRFLAC_FALSE;
+    }
+
     /* Need to handle wasted bits per sample. */
     if (pSubframe->wastedBitsPerSample >= subframeBitsPerSample) {
         return DRFLAC_FALSE;
@@ -6013,6 +6114,11 @@         return DRFLAC_FALSE;
     }
 
+    /* Do not use the seektable if pcmFramIndex is not coverd by it. */
+    if (pFlac->pSeekpoints[0].firstPCMFrame > pcmFrameIndex) {
+        return DRFLAC_FALSE;
+    }
+
     for (iSeekpoint = 0; iSeekpoint < pFlac->seekpointCount; ++iSeekpoint) {
         if (pFlac->pSeekpoints[iSeekpoint].firstPCMFrame >= pcmFrameIndex) {
             break;
@@ -6360,7 +6466,7 @@ }
 
 
-static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeektableSize, drflac_allocation_callbacks* pAllocationCallbacks)
+static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeekpointCount, drflac_allocation_callbacks* pAllocationCallbacks)
 {
     /*
     We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that
@@ -6420,32 +6526,37 @@                 seektableSize = blockSize;
 
                 if (onMeta) {
+                    drflac_uint32 seekpointCount;
                     drflac_uint32 iSeekpoint;
                     void* pRawData;
 
-                    pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
+                    seekpointCount = blockSize/DRFLAC_SEEKPOINT_SIZE_IN_BYTES;
+
+                    pRawData = drflac__malloc_from_callbacks(seekpointCount * sizeof(drflac_seekpoint), pAllocationCallbacks);
                     if (pRawData == NULL) {
                         return DRFLAC_FALSE;
                     }
 
-                    if (onRead(pUserData, pRawData, blockSize) != blockSize) {
-                        drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
-                        return DRFLAC_FALSE;
-                    }
+                    /* We need to read seekpoint by seekpoint and do some processing. */
+                    for (iSeekpoint = 0; iSeekpoint < seekpointCount; ++iSeekpoint) {
+                        drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint;
 
-                    metadata.pRawData = pRawData;
-                    metadata.rawDataSize = blockSize;
-                    metadata.data.seektable.seekpointCount = blockSize/sizeof(drflac_seekpoint);
-                    metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
+                        if (onRead(pUserData, pSeekpoint, DRFLAC_SEEKPOINT_SIZE_IN_BYTES) != DRFLAC_SEEKPOINT_SIZE_IN_BYTES) {
+                            drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+                            return DRFLAC_FALSE;
+                        }
 
-                    /* Endian swap. */
-                    for (iSeekpoint = 0; iSeekpoint < metadata.data.seektable.seekpointCount; ++iSeekpoint) {
-                        drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint;
+                        /* Endian swap. */
                         pSeekpoint->firstPCMFrame   = drflac__be2host_64(pSeekpoint->firstPCMFrame);
                         pSeekpoint->flacFrameOffset = drflac__be2host_64(pSeekpoint->flacFrameOffset);
                         pSeekpoint->pcmFrameCount   = drflac__be2host_16(pSeekpoint->pcmFrameCount);
                     }
 
+                    metadata.pRawData = pRawData;
+                    metadata.rawDataSize = blockSize;
+                    metadata.data.seektable.seekpointCount = seekpointCount;
+                    metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
+
                     onMeta(pUserDataMD, &metadata);
 
                     drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
@@ -6480,7 +6591,7 @@                     pRunningData    = (const char*)pRawData;
                     pRunningDataEnd = (const char*)pRawData + blockSize;
 
-                    metadata.data.vorbis_comment.vendorLength = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
+                    metadata.data.vorbis_comment.vendorLength = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
 
                     /* Need space for the rest of the block */
                     if ((pRunningDataEnd - pRunningData) - 4 < (drflac_int64)metadata.data.vorbis_comment.vendorLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
@@ -6488,7 +6599,7 @@                         return DRFLAC_FALSE;
                     }
                     metadata.data.vorbis_comment.vendor       = pRunningData;                                            pRunningData += metadata.data.vorbis_comment.vendorLength;
-                    metadata.data.vorbis_comment.commentCount = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
+                    metadata.data.vorbis_comment.commentCount = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
 
                     /* Need space for 'commentCount' comments after the block, which at minimum is a drflac_uint32 per comment */
                     if ((pRunningDataEnd - pRunningData) / sizeof(drflac_uint32) < metadata.data.vorbis_comment.commentCount) { /* <-- Note the order of operations to avoid overflow to a valid value */
@@ -6506,7 +6617,7 @@                             return DRFLAC_FALSE;
                         }
 
-                        commentLength = drflac__le2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
+                        commentLength = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
                         if (pRunningDataEnd - pRunningData < (drflac_int64)commentLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
                             drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
                             return DRFLAC_FALSE;
@@ -6530,9 +6641,15 @@                     void* pRawData;
                     const char* pRunningData;
                     const char* pRunningDataEnd;
+                    size_t bufferSize;
                     drflac_uint8 iTrack;
                     drflac_uint8 iIndex;
+                    void* pTrackData;
 
+                    /*
+                    This needs to be loaded in two passes. The first pass is used to calculate the size of the memory allocation
+                    we need for storing the necessary data. The second pass will fill that buffer with usable data.
+                    */
                     pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
                     if (pRawData == NULL) {
                         return DRFLAC_FALSE;
@@ -6553,38 +6670,91 @@                     metadata.data.cuesheet.leadInSampleCount = drflac__be2host_64(*(const drflac_uint64*)pRunningData); pRunningData += 8;
                     metadata.data.cuesheet.isCD              = (pRunningData[0] & 0x80) != 0;                           pRunningData += 259;
                     metadata.data.cuesheet.trackCount        = pRunningData[0];                                         pRunningData += 1;
-                    metadata.data.cuesheet.pTrackData        = pRunningData;
+                    metadata.data.cuesheet.pTrackData        = NULL;    /* Will be filled later. */
 
-                    /* Check that the cuesheet tracks are valid before passing it to the callback */
-                    for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
-                        drflac_uint8 indexCount;
-                        drflac_uint32 indexPointSize;
+                    /* Pass 1: Calculate the size of the buffer for the track data. */
+                    {
+                        const char* pRunningDataSaved = pRunningData;   /* Will be restored at the end in preparation for the second pass. */
 
-                        if (pRunningDataEnd - pRunningData < 36) {
-                            drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
-                            return DRFLAC_FALSE;
+                        bufferSize = metadata.data.cuesheet.trackCount * DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES;
+
+                        for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
+                            drflac_uint8 indexCount;
+                            drflac_uint32 indexPointSize;
+
+                            if (pRunningDataEnd - pRunningData < DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES) {
+                                drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+                                return DRFLAC_FALSE;
+                            }
+
+                            /* Skip to the index point count */
+                            pRunningData += 35;
+                            
+                            indexCount = pRunningData[0];
+                            pRunningData += 1;
+                            
+                            bufferSize += indexCount * sizeof(drflac_cuesheet_track_index);
+
+                            /* Quick validation check. */
+                            indexPointSize = indexCount * DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES;
+                            if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
+                                drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+                                return DRFLAC_FALSE;
+                            }
+
+                            pRunningData += indexPointSize;
                         }
 
-                        /* Skip to the index point count */
-                        pRunningData += 35;
-                        indexCount = pRunningData[0]; pRunningData += 1;
-                        indexPointSize = indexCount * sizeof(drflac_cuesheet_track_index);
-                        if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
+                        pRunningData = pRunningDataSaved;
+                    }
+
+                    /* Pass 2: Allocate a buffer and fill the data. Validation was done in the step above so can be skipped. */
+                    {
+                        char* pRunningTrackData;
+
+                        pTrackData = drflac__malloc_from_callbacks(bufferSize, pAllocationCallbacks);
+                        if (pTrackData == NULL) {
                             drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
                             return DRFLAC_FALSE;
                         }
 
-                        /* Endian swap. */
-                        for (iIndex = 0; iIndex < indexCount; ++iIndex) {
-                            drflac_cuesheet_track_index* pTrack = (drflac_cuesheet_track_index*)pRunningData;
-                            pRunningData += sizeof(drflac_cuesheet_track_index);
-                            pTrack->offset = drflac__be2host_64(pTrack->offset);
+                        pRunningTrackData = (char*)pTrackData;
+
+                        for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
+                            drflac_uint8 indexCount;
+
+                            DRFLAC_COPY_MEMORY(pRunningTrackData, pRunningData, DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES);
+                            pRunningData      += DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES-1; /* Skip forward, but not beyond the last byte in the CUESHEET_TRACK block which is the index count. */
+                            pRunningTrackData += DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES-1;
+
+                            /* Grab the index count for the next part. */
+                            indexCount = pRunningData[0];
+                            pRunningData      += 1;
+                            pRunningTrackData += 1;
+
+                            /* Extract each track index. */
+                            for (iIndex = 0; iIndex < indexCount; ++iIndex) {
+                                drflac_cuesheet_track_index* pTrackIndex = (drflac_cuesheet_track_index*)pRunningTrackData;
+
+                                DRFLAC_COPY_MEMORY(pRunningTrackData, pRunningData, DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES);
+                                pRunningData      += DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES;
+                                pRunningTrackData += sizeof(drflac_cuesheet_track_index);
+
+                                pTrackIndex->offset = drflac__be2host_64(pTrackIndex->offset);
+                            }
                         }
+
+                        metadata.data.cuesheet.pTrackData = pTrackData;
                     }
 
+                    /* The original data is no longer needed. */
+                    drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+                    pRawData = NULL;
+
                     onMeta(pUserDataMD, &metadata);
 
-                    drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+                    drflac__free_from_callbacks(pTrackData, pAllocationCallbacks);
+                    pTrackData = NULL;
                 }
             } break;
 
@@ -6615,28 +6785,28 @@                     pRunningData    = (const char*)pRawData;
                     pRunningDataEnd = (const char*)pRawData + blockSize;
 
-                    metadata.data.picture.type       = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
-                    metadata.data.picture.mimeLength = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
+                    metadata.data.picture.type       = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
+                    metadata.data.picture.mimeLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
 
                     /* Need space for the rest of the block */
                     if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
                         drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
                         return DRFLAC_FALSE;
                     }
-                    metadata.data.picture.mime              = pRunningData;                                            pRunningData += metadata.data.picture.mimeLength;
-                    metadata.data.picture.descriptionLength = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
+                    metadata.data.picture.mime              = pRunningData;                                   pRunningData += metadata.data.picture.mimeLength;
+                    metadata.data.picture.descriptionLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
 
                     /* Need space for the rest of the block */
                     if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
                         drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
                         return DRFLAC_FALSE;
                     }
-                    metadata.data.picture.description     = pRunningData;                                            pRunningData += metadata.data.picture.descriptionLength;
-                    metadata.data.picture.width           = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
-                    metadata.data.picture.height          = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
-                    metadata.data.picture.colorDepth      = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
-                    metadata.data.picture.indexColorCount = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
-                    metadata.data.picture.pictureDataSize = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
+                    metadata.data.picture.description     = pRunningData;                                   pRunningData += metadata.data.picture.descriptionLength;
+                    metadata.data.picture.width           = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
+                    metadata.data.picture.height          = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
+                    metadata.data.picture.colorDepth      = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
+                    metadata.data.picture.indexColorCount = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
+                    metadata.data.picture.pictureDataSize = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
                     metadata.data.picture.pPictureData    = (const drflac_uint8*)pRunningData;
 
                     /* Need space for the picture after the block */
@@ -6714,9 +6884,9 @@         }
     }
 
-    *pSeektablePos = seektablePos;
-    *pSeektableSize = seektableSize;
-    *pFirstFramePos = runningFilePos;
+    *pSeektablePos   = seektablePos;
+    *pSeekpointCount = seektableSize / DRFLAC_SEEKPOINT_SIZE_IN_BYTES;
+    *pFirstFramePos  = runningFilePos;
 
     return DRFLAC_TRUE;
 }
@@ -7746,11 +7916,11 @@     drflac_uint32 wholeSIMDVectorCountPerChannel;
     drflac_uint32 decodedSamplesAllocationSize;
 #ifndef DR_FLAC_NO_OGG
-    drflac_oggbs oggbs;
+    drflac_oggbs* pOggbs = NULL;
 #endif
     drflac_uint64 firstFramePos;
     drflac_uint64 seektablePos;
-    drflac_uint32 seektableSize;
+    drflac_uint32 seekpointCount;
     drflac_allocation_callbacks allocationCallbacks;
     drflac* pFlac;
 
@@ -7804,18 +7974,21 @@     /* There's additional data required for Ogg streams. */
     if (init.container == drflac_container_ogg) {
         allocationSize += sizeof(drflac_oggbs);
-    }
 
-    DRFLAC_ZERO_MEMORY(&oggbs, sizeof(oggbs));
-    if (init.container == drflac_container_ogg) {
-        oggbs.onRead = onRead;
-        oggbs.onSeek = onSeek;
-        oggbs.pUserData = pUserData;
-        oggbs.currentBytePos = init.oggFirstBytePos;
-        oggbs.firstBytePos = init.oggFirstBytePos;
-        oggbs.serialNumber = init.oggSerial;
-        oggbs.bosPageHeader = init.oggBosHeader;
-        oggbs.bytesRemainingInPage = 0;
+        pOggbs = (drflac_oggbs*)drflac__malloc_from_callbacks(sizeof(*pOggbs), &allocationCallbacks);
+        if (pOggbs == NULL) {
+            return NULL; /*DRFLAC_OUT_OF_MEMORY;*/
+        }
+
+        DRFLAC_ZERO_MEMORY(pOggbs, sizeof(*pOggbs));
+        pOggbs->onRead = onRead;
+        pOggbs->onSeek = onSeek;
+        pOggbs->pUserData = pUserData;
+        pOggbs->currentBytePos = init.oggFirstBytePos;
+        pOggbs->firstBytePos = init.oggFirstBytePos;
+        pOggbs->serialNumber = init.oggSerial;
+        pOggbs->bosPageHeader = init.oggBosHeader;
+        pOggbs->bytesRemainingInPage = 0;
     }
 #endif
 
@@ -7824,9 +7997,9 @@     consist of only a single heap allocation. To this, the size of the seek table needs to be known, which we determine when reading
     and decoding the metadata.
     */
-    firstFramePos = 42;   /* <-- We know we are at byte 42 at this point. */
-    seektablePos  = 0;
-    seektableSize = 0;
+    firstFramePos  = 42;   /* <-- We know we are at byte 42 at this point. */
+    seektablePos   = 0;
+    seekpointCount = 0;
     if (init.hasMetadataBlocks) {
         drflac_read_proc onReadOverride = onRead;
         drflac_seek_proc onSeekOverride = onSeek;
@@ -7836,20 +8009,26 @@         if (init.container == drflac_container_ogg) {
             onReadOverride = drflac__on_read_ogg;
             onSeekOverride = drflac__on_seek_ogg;
-            pUserDataOverride = (void*)&oggbs;
+            pUserDataOverride = (void*)pOggbs;
         }
 #endif
 
-        if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seektableSize, &allocationCallbacks)) {
+        if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
+        #ifndef DR_FLAC_NO_OGG
+            drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
+        #endif
             return NULL;
         }
 
-        allocationSize += seektableSize;
+        allocationSize += seekpointCount * sizeof(drflac_seekpoint);
     }
 
 
     pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
     if (pFlac == NULL) {
+    #ifndef DR_FLAC_NO_OGG
+        drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
+    #endif
         return NULL;
     }
 
@@ -7859,9 +8038,13 @@ 
 #ifndef DR_FLAC_NO_OGG
     if (init.container == drflac_container_ogg) {
-        drflac_oggbs* pInternalOggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize + seektableSize);
-        *pInternalOggbs = oggbs;
+        drflac_oggbs* pInternalOggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize + (seekpointCount * sizeof(drflac_seekpoint)));
+        DRFLAC_COPY_MEMORY(pInternalOggbs, pOggbs, sizeof(*pOggbs));
 
+        /* At this point the pOggbs object has been handed over to pInternalOggbs and can be freed. */
+        drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
+        pOggbs = NULL;
+
         /* The Ogg bistream needs to be layered on top of the original bitstream. */
         pFlac->bs.onRead = drflac__on_read_ogg;
         pFlac->bs.onSeek = drflac__on_seek_ogg;
@@ -7884,7 +8067,7 @@     {
         /* If we have a seektable we need to load it now, making sure we move back to where we were previously. */
         if (seektablePos != 0) {
-            pFlac->seekpointCount = seektableSize / sizeof(*pFlac->pSeekpoints);
+            pFlac->seekpointCount = seekpointCount;
             pFlac->pSeekpoints = (drflac_seekpoint*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize);
 
             DRFLAC_ASSERT(pFlac->bs.onSeek != NULL);
@@ -7892,18 +8075,20 @@ 
             /* Seek to the seektable, then just read directly into our seektable buffer. */
             if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) {
-                if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints, seektableSize) == seektableSize) {
-                    /* Endian swap. */
-                    drflac_uint32 iSeekpoint;
-                    for (iSeekpoint = 0; iSeekpoint < pFlac->seekpointCount; ++iSeekpoint) {
+                drflac_uint32 iSeekpoint;
+
+                for (iSeekpoint = 0; iSeekpoint < seekpointCount; iSeekpoint += 1) {
+                    if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints + iSeekpoint, DRFLAC_SEEKPOINT_SIZE_IN_BYTES) == DRFLAC_SEEKPOINT_SIZE_IN_BYTES) {
+                        /* Endian swap. */
                         pFlac->pSeekpoints[iSeekpoint].firstPCMFrame   = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].firstPCMFrame);
                         pFlac->pSeekpoints[iSeekpoint].flacFrameOffset = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].flacFrameOffset);
                         pFlac->pSeekpoints[iSeekpoint].pcmFrameCount   = drflac__be2host_16(pFlac->pSeekpoints[iSeekpoint].pcmFrameCount);
+                    } else {
+                        /* Failed to read the seektable. Pretend we don't have one. */
+                        pFlac->pSeekpoints = NULL;
+                        pFlac->seekpointCount = 0;
+                        break;
                     }
-                } else {
-                    /* Failed to read the seektable. Pretend we don't have one. */
-                    pFlac->pSeekpoints = NULL;
-                    pFlac->seekpointCount = 0;
                 }
 
                 /* We need to seek back to where we were. If this fails it's a critical error. */
@@ -7952,7 +8137,9 @@ 
 #ifndef DR_FLAC_NO_STDIO
 #include <stdio.h>
+#ifndef DR_FLAC_NO_WCHAR
 #include <wchar.h>      /* For wcslen(), wcsrtombs() */
+#endif
 
 /* drflac_result_from_errno() is only used for fopen() and wfopen() so putting it inside DR_WAV_NO_STDIO for now. If something else needs this later we can move it out. */
 #include <errno.h>
@@ -8418,6 +8605,7 @@     #endif
 #endif
 
+#ifndef DR_FLAC_NO_WCHAR
 static drflac_result drflac_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drflac_allocation_callbacks* pAllocationCallbacks)
 {
     if (ppFile != NULL) {
@@ -8446,10 +8634,23 @@     }
 #else
     /*
-    Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
-    think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
-    maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
+    Use fopen() on anything other than Windows. Requires a conversion. This is annoying because
+	fopen() is locale specific. The only real way I can think of to do this is with wcsrtombs(). Note
+	that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
+    maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler
+	error I'll look into improving compatibility.
     */
+
+	/*
+	Some compilers don't support wchar_t or wcsrtombs() which we're using below. In this case we just
+	need to abort with an error. If you encounter a compiler lacking such support, add it to this list
+	and submit a bug report and it'll be added to the library upstream.
+	*/
+	#if defined(__DJGPP__)
+	{
+		/* Nothing to do here. This will fall through to the error check below. */
+	}
+	#else
     {
         mbstate_t mbs;
         size_t lenMB;
@@ -8491,6 +8692,7 @@ 
         drflac__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
     }
+	#endif
 
     if (*ppFile == NULL) {
         return DRFLAC_ERROR;
@@ -8499,6 +8701,7 @@ 
     return DRFLAC_SUCCESS;
 }
+#endif
 
 static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
 {
@@ -8531,6 +8734,7 @@     return pFlac;
 }
 
+#ifndef DR_FLAC_NO_WCHAR
 DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
 {
     drflac* pFlac;
@@ -8548,6 +8752,7 @@ 
     return pFlac;
 }
+#endif
 
 DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
 {
@@ -8567,6 +8772,7 @@     return pFlac;
 }
 
+#ifndef DR_FLAC_NO_WCHAR
 DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
 {
     drflac* pFlac;
@@ -8584,6 +8790,7 @@ 
     return pFlac;
 }
+#endif
 #endif  /* DR_FLAC_NO_STDIO */
 
 static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t bytesToRead)
@@ -11781,7 +11988,7 @@         return NULL;
     }
 
-    length = drflac__le2host_32(*(const drflac_uint32*)pIter->pRunningData);
+    length = drflac__le2host_32_ptr_unaligned(pIter->pRunningData);
     pIter->pRunningData += 4;
 
     pComment = pIter->pRunningData;
@@ -11851,6 +12058,37 @@ /*
 REVISION HISTORY
 ================
+v0.12.39 - 2022-09-17
+  - Fix compilation with DJGPP.
+  - Fix compilation error with Visual Studio 2019 and the ARM build.
+  - Fix an error with SSE 4.1 detection.
+  - Add support for disabling wchar_t with DR_WAV_NO_WCHAR.
+  - Improve compatibility with compilers which lack support for explicit struct packing.
+  - Improve compatibility with low-end and embedded hardware by reducing the amount of stack
+    allocation when loading an Ogg encapsulated file.
+
+v0.12.38 - 2022-04-10
+  - Fix compilation error on older versions of GCC.
+
+v0.12.37 - 2022-02-12
+  - Improve ARM detection.
+
+v0.12.36 - 2022-02-07
+  - Fix a compilation error with the ARM build.
+
+v0.12.35 - 2022-02-06
+  - Fix a bug due to underestimating the amount of precision required for the prediction stage.
+  - Fix some bugs found from fuzz testing.
+
+v0.12.34 - 2022-01-07
+  - Fix some misalignment bugs when reading metadata.
+
+v0.12.33 - 2021-12-22
+  - Fix a bug with seeking when the seek table does not start at PCM frame 0.
+
+v0.12.32 - 2021-12-11
+  - Fix a warning with Clang.
+
 v0.12.31 - 2021-08-16
   - Silence some warnings.
 
raylib/src/external/dr_mp3.h view
@@ -1,6 +1,6 @@ /*
 MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
-dr_mp3 - v0.6.31 - 2021-08-22
+dr_mp3 - v0.6.34 - 2022-09-17
 
 David Reid - mackron@gmail.com
 
@@ -95,7 +95,7 @@ 
 #define DRMP3_VERSION_MAJOR     0
 #define DRMP3_VERSION_MINOR     6
-#define DRMP3_VERSION_REVISION  31
+#define DRMP3_VERSION_REVISION  34
 #define DRMP3_VERSION_STRING    DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
 
 #include <stddef.h> /* For size_t. */
@@ -107,7 +107,7 @@ typedef unsigned short          drmp3_uint16;
 typedef   signed int            drmp3_int32;
 typedef unsigned int            drmp3_uint32;
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && !defined(__clang__)
     typedef   signed __int64    drmp3_int64;
     typedef unsigned __int64    drmp3_uint64;
 #else
@@ -235,10 +235,16 @@     I am using "__inline__" only when we're compiling in strict ANSI mode.
     */
     #if defined(__STRICT_ANSI__)
-        #define DRMP3_INLINE __inline__ __attribute__((always_inline))
+        #define DRMP3_GNUC_INLINE_HINT __inline__
     #else
-        #define DRMP3_INLINE inline __attribute__((always_inline))
+        #define DRMP3_GNUC_INLINE_HINT inline
     #endif
+
+    #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
+        #define DRMP3_INLINE DRMP3_GNUC_INLINE_HINT __attribute__((always_inline))
+    #else
+        #define DRMP3_INLINE DRMP3_GNUC_INLINE_HINT
+    #endif
 #elif defined(__WATCOMC__)
     #define DRMP3_INLINE __inline
 #else
@@ -340,7 +346,6 @@ typedef struct
 {
     drmp3dec decoder;
-    drmp3dec_frame_info frameInfo;
     drmp3_uint32 channels;
     drmp3_uint32 sampleRate;
     drmp3_read_proc onRead;
@@ -595,7 +600,7 @@ #define DR_MP3_ONLY_SIMD
 #endif
 
-#if ((defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_IX86) || defined(_M_X64))) || ((defined(__i386__) || defined(__x86_64__)) && defined(__SSE2__))
+#if ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)))
 #if defined(_MSC_VER)
 #include <intrin.h>
 #endif
@@ -1296,7 +1301,7 @@     static const drmp3_int16 tabindex[2*16] = { 0,32,64,98,0,132,180,218,292,364,426,538,648,746,0,1126,1460,1460,1460,1460,1460,1460,1460,1460,1842,1842,1842,1842,1842,1842,1842,1842 };
     static const drmp3_uint8 g_linbits[] =  { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,6,8,10,13,4,5,6,7,8,9,11,13 };
 
-#define DRMP3_PEEK_BITS(n)    (bs_cache >> (32 - n))
+#define DRMP3_PEEK_BITS(n)    (bs_cache >> (32 - (n)))
 #define DRMP3_FLUSH_BITS(n)   { bs_cache <<= (n); bs_sh += (n); }
 #define DRMP3_CHECK_BITS      while (bs_sh >= 0) { bs_cache |= (drmp3_uint32)*bs_next_ptr++ << bs_sh; bs_sh -= 8; }
 #define DRMP3_BSPOS           ((bs_next_ptr - bs->buf)*8 - 24 + bs_sh)
@@ -1864,7 +1869,7 @@ #if DRMP3_HAVE_SSE
 #define DRMP3_VSAVE2(i, v) _mm_storel_pi((__m64 *)(void*)&y[i*18], v)
 #else
-#define DRMP3_VSAVE2(i, v) vst1_f32((float32_t *)&y[i*18],  vget_low_f32(v))
+#define DRMP3_VSAVE2(i, v) vst1_f32((float32_t *)&y[(i)*18],  vget_low_f32(v))
 #endif
             for (i = 0; i < 7; i++, y += 4*18)
             {
@@ -1880,7 +1885,7 @@             DRMP3_VSAVE2(3, t[3][7]);
         } else
         {
-#define DRMP3_VSAVE4(i, v) DRMP3_VSTORE(&y[i*18], v)
+#define DRMP3_VSAVE4(i, v) DRMP3_VSTORE(&y[(i)*18], v)
             for (i = 0; i < 7; i++, y += 4*18)
             {
                 drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]);
@@ -2103,7 +2108,11 @@             vst1_lane_s16(dstl + (49 + i)*nch, pcmb, 2);
 #endif
 #else
+        #if DRMP3_HAVE_SSE
             static const drmp3_f4 g_scale = { 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f };
+        #else
+            const drmp3_f4 g_scale = vdupq_n_f32(1.0f/32768.0f);
+        #endif
             a = DRMP3_VMUL(a, g_scale);
             b = DRMP3_VMUL(b, g_scale);
 #if DRMP3_HAVE_SSE
@@ -2406,8 +2415,6 @@  Main Public API
 
  ************************************************************************************************************************************************************/
-#include <math.h>   /* For sin() and exp(). */
-
 #if defined(SIZE_MAX)
     #define DRMP3_SIZE_MAX  SIZE_MAX
 #else
@@ -2427,7 +2434,7 @@ 
 /* The size in bytes of each chunk of data to read from the MP3 stream. minimp3 recommends at least 16K, but in an attempt to reduce data movement I'm making this slightly larger. */
 #ifndef DRMP3_DATA_CHUNK_SIZE
-#define DRMP3_DATA_CHUNK_SIZE  DRMP3_MIN_DATA_CHUNK_SIZE*4
+#define DRMP3_DATA_CHUNK_SIZE  (DRMP3_MIN_DATA_CHUNK_SIZE*4)
 #endif
 
 
@@ -2472,24 +2479,6 @@ }
 
 
-static DRMP3_INLINE double drmp3_sin(double x)
-{
-    /* TODO: Implement custom sin(x). */
-    return sin(x);
-}
-
-static DRMP3_INLINE double drmp3_exp(double x)
-{
-    /* TODO: Implement custom exp(x). */
-    return exp(x);
-}
-
-static DRMP3_INLINE double drmp3_cos(double x)
-{
-    return drmp3_sin((DRMP3_PI_D*0.5) - x);
-}
-
-
 static void* drmp3__malloc_default(size_t sz, void* pUserData)
 {
     (void)pUserData;
@@ -3434,10 +3423,23 @@     }
 #else
     /*
-    Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
-    think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
-    maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
+    Use fopen() on anything other than Windows. Requires a conversion. This is annoying because
+	fopen() is locale specific. The only real way I can think of to do this is with wcsrtombs(). Note
+	that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
+    maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler
+	error I'll look into improving compatibility.
     */
+
+	/*
+	Some compilers don't support wchar_t or wcsrtombs() which we're using below. In this case we just
+	need to abort with an error. If you encounter a compiler lacking such support, add it to this list
+	and submit a bug report and it'll be added to the library upstream.
+	*/
+	#if defined(__DJGPP__)
+	{
+		/* Nothing to do here. This will fall through to the error check below. */
+	}
+	#else
     {
         mbstate_t mbs;
         size_t lenMB;
@@ -3479,6 +3481,7 @@ 
         drmp3__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
     }
+	#endif
 
     if (*ppFile == NULL) {
         return DRMP3_ERROR;
@@ -4473,6 +4476,19 @@ /*
 REVISION HISTORY
 ================
+v0.6.34 - 2022-09-17
+  - Fix compilation with DJGPP.
+  - Fix compilation when compiling with x86 with no SSE2.
+  - Remove an unnecessary variable from the drmp3 structure.
+
+v0.6.33 - 2022-04-10
+  - Fix compilation error with the MSVC ARM64 build.
+  - Fix compilation error on older versions of GCC.
+  - Remove some unused functions.
+
+v0.6.32 - 2021-12-11
+  - Fix a warning with Clang.
+
 v0.6.31 - 2021-08-22
   - Fix a bug when loading from memory.
 
raylib/src/external/dr_wav.h view
@@ -1,6 +1,6 @@ /*
 WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
-dr_wav - v0.13.4 - 2021-12-08
+dr_wav - v0.13.7 - 2022-09-17
 
 David Reid - mackron@gmail.com
 
@@ -92,8 +92,11 @@ #define DR_WAV_NO_STDIO
   Disables APIs that initialize a decoder from a file such as `drwav_init_file()`, `drwav_init_file_write()`, etc.
 
+#define DR_WAV_NO_WCHAR
+  Disables all functions ending with `_w`. Use this if your compiler does not provide wchar.h. Not required if DR_WAV_NO_STDIO is also defined.
 
 
+
 Notes
 =====
 - Samples are always interleaved.
@@ -125,7 +128,7 @@ 
 #define DRWAV_VERSION_MAJOR     0
 #define DRWAV_VERSION_MINOR     13
-#define DRWAV_VERSION_REVISION  4
+#define DRWAV_VERSION_REVISION  7
 #define DRWAV_VERSION_STRING    DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
 
 #include <stddef.h> /* For size_t. */
@@ -1297,14 +1300,21 @@ #ifndef dr_wav_c
 #define dr_wav_c
 
+#ifdef __MRC__
+/* MrC currently doesn't compile dr_wav correctly with any optimizations enabled. */
+#pragma options opt off
+#endif
+
 #include <stdlib.h>
-#include <string.h> /* For memcpy(), memset() */
+#include <string.h>
 #include <limits.h> /* For INT_MAX */
 
 #ifndef DR_WAV_NO_STDIO
 #include <stdio.h>
+#ifndef DR_WAV_NO_WCHAR
 #include <wchar.h>
 #endif
+#endif
 
 /* Standard library stuff. */
 #ifndef DRWAV_ASSERT
@@ -1359,10 +1369,16 @@     I am using "__inline__" only when we're compiling in strict ANSI mode.
     */
     #if defined(__STRICT_ANSI__)
-        #define DRWAV_INLINE __inline__ __attribute__((always_inline))
+        #define DRWAV_GNUC_INLINE_HINT __inline__
     #else
-        #define DRWAV_INLINE inline __attribute__((always_inline))
+        #define DRWAV_GNUC_INLINE_HINT inline
     #endif
+
+    #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
+        #define DRWAV_INLINE DRWAV_GNUC_INLINE_HINT __attribute__((always_inline))
+    #else
+        #define DRWAV_INLINE DRWAV_GNUC_INLINE_HINT
+    #endif
 #elif defined(__WATCOMC__)
     #define DRWAV_INLINE __inline
 #else
@@ -1966,7 +1982,7 @@     fmtOut->extendedSize       = 0;
     fmtOut->validBitsPerSample = 0;
     fmtOut->channelMask        = 0;
-    memset(fmtOut->subFormat, 0, sizeof(fmtOut->subFormat));
+    DRWAV_ZERO_MEMORY(fmtOut->subFormat, sizeof(fmtOut->subFormat));
 
     if (header.sizeInBytes > 16) {
         drwav_uint8 fmt_cbSize[2];
@@ -2137,7 +2153,7 @@ DRWAV_PRIVATE drwav_result drwav__metadata_alloc(drwav__metadata_parser* pParser, drwav_allocation_callbacks* pAllocationCallbacks)
 {
     if (pParser->extraCapacity != 0 || pParser->metadataCount != 0) {
-        free(pParser->pData);
+        pAllocationCallbacks->onFree(pParser->pData, pAllocationCallbacks->pUserData);
 
         pParser->pData = (drwav_uint8*)pAllocationCallbacks->onMalloc(drwav__metadata_memory_capacity(pParser), pAllocationCallbacks->pUserData);
         pParser->pDataCursor = pParser->pData;
@@ -2316,6 +2332,17 @@     return bytesRead;
 }
 
+DRWAV_PRIVATE size_t drwav__strlen(const char* str)
+{
+    size_t result = 0;
+
+    while (*str++) {
+        result += 1;
+    }
+
+    return result;
+}
+
 DRWAV_PRIVATE size_t drwav__strlen_clamped(const char* str, size_t maxToRead)
 {
     size_t result = 0;
@@ -2335,7 +2362,7 @@         char* result = (char*)drwav__metadata_get_memory(pParser, len + 1, 1);
         DRWAV_ASSERT(result != NULL);
 
-        memcpy(result, str, len);
+        DRWAV_COPY_MEMORY(result, str, len);
         result[len] = '\0';
 
         return result;
@@ -2516,7 +2543,7 @@                 DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
 
                 bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
-                pMetadata->data.bext.codingHistorySize = (drwav_uint32)strlen(pMetadata->data.bext.pCodingHistory);
+                pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__strlen(pMetadata->data.bext.pCodingHistory);
             } else {
                 pMetadata->data.bext.pCodingHistory    = NULL;
                 pMetadata->data.bext.codingHistorySize = 0;
@@ -2780,21 +2807,21 @@                 if (bytesJustRead != DRWAV_BEXT_DESCRIPTION_BYTES) {
                     return bytesRead;
                 }
-                allocSizeNeeded += strlen(buffer) + 1;
+                allocSizeNeeded += drwav__strlen(buffer) + 1;
 
                 buffer[DRWAV_BEXT_ORIGINATOR_NAME_BYTES] = '\0';
                 bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_NAME_BYTES, &bytesRead);
                 if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_NAME_BYTES) {
                     return bytesRead;
                 }
-                allocSizeNeeded += strlen(buffer) + 1;
+                allocSizeNeeded += drwav__strlen(buffer) + 1;
 
                 buffer[DRWAV_BEXT_ORIGINATOR_REF_BYTES] = '\0';
                 bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_REF_BYTES, &bytesRead);
                 if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_REF_BYTES) {
                     return bytesRead;
                 }
-                allocSizeNeeded += strlen(buffer) + 1;
+                allocSizeNeeded += drwav__strlen(buffer) + 1;
                 allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES; /* Coding history. */
 
                 drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
@@ -3157,7 +3184,7 @@         translatedFormatTag = drwav_bytes_to_u16(fmt.subFormat + 0);
     }
 
-    memset(&metadataParser, 0, sizeof(metadataParser));
+    DRWAV_ZERO_MEMORY(&metadataParser, sizeof(metadataParser));
 
     /* Not tested on W64. */
     if (!sequential && pWav->allowedMetadataTypes != drwav_metadata_type_none && (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64)) {
@@ -3746,7 +3773,7 @@                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxMomentaryLoudness);
                 bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxShortTermLoudness);
 
-                memset(reservedBuf, 0, sizeof(reservedBuf));
+                DRWAV_ZERO_MEMORY(reservedBuf, sizeof(reservedBuf));
                 bytesWritten += drwav__write_or_count(pWav, reservedBuf, sizeof(reservedBuf));
 
                 if (pMetadata->data.bext.codingHistorySize > 0) {
@@ -4704,6 +4731,7 @@     #endif
 #endif
 
+#ifndef DR_WAV_NO_WCHAR
 DRWAV_PRIVATE drwav_result drwav_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drwav_allocation_callbacks* pAllocationCallbacks)
 {
     if (ppFile != NULL) {
@@ -4731,11 +4759,24 @@         (void)pAllocationCallbacks;
     }
 #else
-    /*
-    Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
-    think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
-    maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
+	/*
+    Use fopen() on anything other than Windows. Requires a conversion. This is annoying because
+	fopen() is locale specific. The only real way I can think of to do this is with wcsrtombs(). Note
+	that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
+    maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler
+	error I'll look into improving compatibility.
     */
+
+	/*
+	Some compilers don't support wchar_t or wcsrtombs() which we're using below. In this case we just
+	need to abort with an error. If you encounter a compiler lacking such support, add it to this list
+	and submit a bug report and it'll be added to the library upstream.
+	*/
+	#if defined(__DJGPP__)
+	{
+		/* Nothing to do here. This will fall through to the error check below. */
+	}
+	#else
     {
         mbstate_t mbs;
         size_t lenMB;
@@ -4777,6 +4818,7 @@ 
         drwav__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
     }
+	#endif
 
     if (*ppFile == NULL) {
         return DRWAV_ERROR;
@@ -4785,6 +4827,7 @@ 
     return DRWAV_SUCCESS;
 }
+#endif
 
 
 DRWAV_PRIVATE size_t drwav__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
@@ -4840,6 +4883,7 @@     return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, drwav_metadata_type_none, pAllocationCallbacks);
 }
 
+#ifndef DR_WAV_NO_WCHAR
 DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
 {
     return drwav_init_file_ex_w(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
@@ -4855,6 +4899,7 @@     /* This takes ownership of the FILE* object. */
     return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, drwav_metadata_type_none, pAllocationCallbacks);
 }
+#endif
 
 DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
 {
@@ -4867,6 +4912,7 @@     return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags, drwav_metadata_type_all_including_unknown, pAllocationCallbacks);
 }
 
+#ifndef DR_WAV_NO_WCHAR
 DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
 {
     FILE* pFile;
@@ -4877,6 +4923,7 @@     /* This takes ownership of the FILE* object. */
     return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags, drwav_metadata_type_all_including_unknown, pAllocationCallbacks);
 }
+#endif
 
 
 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal_FILE(drwav* pWav, FILE* pFile, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
@@ -4909,6 +4956,7 @@     return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
 }
 
+#ifndef DR_WAV_NO_WCHAR
 DRWAV_PRIVATE drwav_bool32 drwav_init_file_write_w__internal(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
 {
     FILE* pFile;
@@ -4919,6 +4967,7 @@     /* This takes ownership of the FILE* object. */
     return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
 }
+#endif
 
 DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
 {
@@ -4939,6 +4988,7 @@     return drwav_init_file_write_sequential(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
 }
 
+#ifndef DR_WAV_NO_WCHAR
 DRWAV_API drwav_bool32 drwav_init_file_write_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
 {
     return drwav_init_file_write_w__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
@@ -4957,6 +5007,7 @@ 
     return drwav_init_file_write_sequential_w(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
 }
+#endif
 #endif  /* DR_WAV_NO_STDIO */
 
 
@@ -5441,8 +5492,8 @@     }
 
     /* Make sure the sample is clamped. */
-    if (targetFrameIndex >= pWav->totalPCMFrameCount) {
-        targetFrameIndex  = pWav->totalPCMFrameCount - 1;
+    if (targetFrameIndex > pWav->totalPCMFrameCount) {
+        targetFrameIndex = pWav->totalPCMFrameCount;
     }
 
     /*
@@ -7650,6 +7701,7 @@ }
 
 
+#ifndef DR_WAV_NO_WCHAR
 DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
 {
     drwav wav;
@@ -7712,7 +7764,8 @@ 
     return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
 }
-#endif
+#endif /* DR_WAV_NO_WCHAR */
+#endif /* DR_WAV_NO_STDIO */
 
 DRWAV_API drwav_int16* drwav_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
 {
@@ -7853,12 +7906,28 @@         a[3] == b[3];
 }
 
+#ifdef __MRC__
+/* Undo the pragma at the beginning of this file. */
+#pragma options opt reset
+#endif
+
 #endif  /* dr_wav_c */
 #endif  /* DR_WAV_IMPLEMENTATION */
 
 /*
 REVISION HISTORY
 ================
+v0.13.7 - 2022-09-17
+  - Fix compilation with DJGPP.
+  - Add support for disabling wchar_t with DR_WAV_NO_WCHAR.
+
+v0.13.6 - 2022-04-10
+  - Fix compilation error on older versions of GCC.
+  - Remove some dependencies on the standard library.
+
+v0.13.5 - 2022-01-26
+  - Fix an error when seeking to the end of the file.
+
 v0.13.4 - 2021-12-08
   - Fix some static analysis warnings.
 
+ raylib/src/external/glad_gles2.h view
@@ -0,0 +1,4774 @@+/**
+ * Loader generated by glad 2.0.2 on Wed Dec 28 13:28:51 2022
+ *
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ *
+ * Generator: C/C++
+ * Specification: gl
+ * Extensions: 170
+ *
+ * APIs:
+ *  - gles2=2.0
+ *
+ * Options:
+ *  - ALIAS = False
+ *  - DEBUG = False
+ *  - HEADER_ONLY = True
+ *  - LOADER = False
+ *  - MX = False
+ *  - ON_DEMAND = False
+ *
+ * Commandline:
+ *    --api='gles2=2.0' --extensions='GL_EXT_EGL_image_array,GL_EXT_EGL_image_storage,GL_EXT_EGL_image_storage_compression,GL_EXT_YUV_target,GL_EXT_base_instance,GL_EXT_blend_func_extended,GL_EXT_blend_minmax,GL_EXT_buffer_storage,GL_EXT_clear_texture,GL_EXT_clip_control,GL_EXT_clip_cull_distance,GL_EXT_color_buffer_float,GL_EXT_color_buffer_half_float,GL_EXT_conservative_depth,GL_EXT_copy_image,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_depth_clamp,GL_EXT_discard_framebuffer,GL_EXT_disjoint_timer_query,GL_EXT_draw_buffers,GL_EXT_draw_buffers_indexed,GL_EXT_draw_elements_base_vertex,GL_EXT_draw_instanced,GL_EXT_draw_transform_feedback,GL_EXT_external_buffer,GL_EXT_float_blend,GL_EXT_fragment_shading_rate,GL_EXT_geometry_point_size,GL_EXT_geometry_shader,GL_EXT_gpu_shader5,GL_EXT_instanced_arrays,GL_EXT_map_buffer_range,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_memory_object_win32,GL_EXT_multi_draw_arrays,GL_EXT_multi_draw_indirect,GL_EXT_multisampled_compatibility,GL_EXT_multisampled_render_to_texture,GL_EXT_multisampled_render_to_texture2,GL_EXT_multiview_draw_buffers,GL_EXT_multiview_tessellation_geometry_shader,GL_EXT_multiview_texture_multisample,GL_EXT_multiview_timer_query,GL_EXT_occlusion_query_boolean,GL_EXT_polygon_offset_clamp,GL_EXT_post_depth_coverage,GL_EXT_primitive_bounding_box,GL_EXT_protected_textures,GL_EXT_pvrtc_sRGB,GL_EXT_raster_multisample,GL_EXT_read_format_bgra,GL_EXT_render_snorm,GL_EXT_robustness,GL_EXT_sRGB,GL_EXT_sRGB_write_control,GL_EXT_semaphore,GL_EXT_semaphore_fd,GL_EXT_semaphore_win32,GL_EXT_separate_depth_stencil,GL_EXT_separate_shader_objects,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_framebuffer_fetch_non_coherent,GL_EXT_shader_group_vote,GL_EXT_shader_implicit_conversions,GL_EXT_shader_integer_mix,GL_EXT_shader_io_blocks,GL_EXT_shader_non_constant_global_initializers,GL_EXT_shader_pixel_local_storage,GL_EXT_shader_pixel_local_storage2,GL_EXT_shader_samples_identical,GL_EXT_shader_texture_lod,GL_EXT_shadow_samplers,GL_EXT_sparse_texture,GL_EXT_sparse_texture2,GL_EXT_tessellation_point_size,GL_EXT_tessellation_shader,GL_EXT_texture_border_clamp,GL_EXT_texture_buffer,GL_EXT_texture_compression_astc_decode_mode,GL_EXT_texture_compression_bptc,GL_EXT_texture_compression_dxt1,GL_EXT_texture_compression_rgtc,GL_EXT_texture_compression_s3tc,GL_EXT_texture_compression_s3tc_srgb,GL_EXT_texture_cube_map_array,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_filter_minmax,GL_EXT_texture_format_BGRA8888,GL_EXT_texture_format_sRGB_override,GL_EXT_texture_mirror_clamp_to_edge,GL_EXT_texture_norm16,GL_EXT_texture_query_lod,GL_EXT_texture_rg,GL_EXT_texture_sRGB_R8,GL_EXT_texture_sRGB_RG8,GL_EXT_texture_sRGB_decode,GL_EXT_texture_shadow_lod,GL_EXT_texture_storage,GL_EXT_texture_storage_compression,GL_EXT_texture_type_2_10_10_10_REV,GL_EXT_texture_view,GL_EXT_unpack_subimage,GL_EXT_win32_keyed_mutex,GL_EXT_window_rectangles,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_context_flush_control,GL_KHR_debug,GL_KHR_no_error,GL_KHR_parallel_shader_compile,GL_KHR_robust_buffer_access_behavior,GL_KHR_robustness,GL_KHR_shader_subgroup,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_KHR_texture_compression_astc_sliced_3d,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_compressed_ETC1_RGB8_sub_texture,GL_OES_compressed_ETC1_RGB8_texture,GL_OES_compressed_paletted_texture,GL_OES_copy_image,GL_OES_depth24,GL_OES_depth32,GL_OES_depth_texture,GL_OES_draw_buffers_indexed,GL_OES_draw_elements_base_vertex,GL_OES_element_index_uint,GL_OES_fbo_render_mipmap,GL_OES_fragment_precision_high,GL_OES_geometry_point_size,GL_OES_geometry_shader,GL_OES_get_program_binary,GL_OES_gpu_shader5,GL_OES_mapbuffer,GL_OES_packed_depth_stencil,GL_OES_primitive_bounding_box,GL_OES_required_internalformat,GL_OES_rgb8_rgba8,GL_OES_sample_shading,GL_OES_sample_variables,GL_OES_shader_image_atomic,GL_OES_shader_io_blocks,GL_OES_shader_multisample_interpolation,GL_OES_standard_derivatives,GL_OES_stencil1,GL_OES_stencil4,GL_OES_surfaceless_context,GL_OES_tessellation_point_size,GL_OES_tessellation_shader,GL_OES_texture_3D,GL_OES_texture_border_clamp,GL_OES_texture_buffer,GL_OES_texture_compression_astc,GL_OES_texture_cube_map_array,GL_OES_texture_float,GL_OES_texture_float_linear,GL_OES_texture_half_float,GL_OES_texture_half_float_linear,GL_OES_texture_npot,GL_OES_texture_stencil8,GL_OES_texture_storage_multisample_2d_array,GL_OES_texture_view,GL_OES_vertex_array_object,GL_OES_vertex_half_float,GL_OES_vertex_type_10_10_10_2,GL_OES_viewport_array' c --header-only
+ *
+ * Online:
+ *    http://glad.sh/#api=gles2%3D2.0&generator=c&options=HEADER_ONLY
+ *
+ */
+
+#ifndef GLAD_GLES2_H_
+#define GLAD_GLES2_H_
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreserved-id-macro"
+#endif
+#ifdef __gl2_h_
+  #error OpenGL ES 2 header already included (API: gles2), remove previous include!
+#endif
+#define __gl2_h_ 1
+#ifdef __gles2_gl2_h_
+  #error OpenGL ES 2 header already included (API: gles2), remove previous include!
+#endif
+#define __gles2_gl2_h_ 1
+#ifdef __gl3_h_
+  #error OpenGL ES 3 header already included (API: gles2), remove previous include!
+#endif
+#define __gl3_h_ 1
+#ifdef __gles2_gl3_h_
+  #error OpenGL ES 3 header already included (API: gles2), remove previous include!
+#endif
+#define __gles2_gl3_h_ 1
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#define GLAD_GLES2
+#define GLAD_OPTION_GLES2_HEADER_ONLY
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GLAD_PLATFORM_H_
+#define GLAD_PLATFORM_H_
+
+#ifndef GLAD_PLATFORM_WIN32
+  #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
+    #define GLAD_PLATFORM_WIN32 1
+  #else
+    #define GLAD_PLATFORM_WIN32 0
+  #endif
+#endif
+
+#ifndef GLAD_PLATFORM_APPLE
+  #ifdef __APPLE__
+    #define GLAD_PLATFORM_APPLE 1
+  #else
+    #define GLAD_PLATFORM_APPLE 0
+  #endif
+#endif
+
+#ifndef GLAD_PLATFORM_EMSCRIPTEN
+  #ifdef __EMSCRIPTEN__
+    #define GLAD_PLATFORM_EMSCRIPTEN 1
+  #else
+    #define GLAD_PLATFORM_EMSCRIPTEN 0
+  #endif
+#endif
+
+#ifndef GLAD_PLATFORM_UWP
+  #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
+    #ifdef __has_include
+      #if __has_include(<winapifamily.h>)
+        #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+      #endif
+    #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
+      #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+    #endif
+  #endif
+
+  #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
+    #include <winapifamily.h>
+    #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+      #define GLAD_PLATFORM_UWP 1
+    #endif
+  #endif
+
+  #ifndef GLAD_PLATFORM_UWP
+    #define GLAD_PLATFORM_UWP 0
+  #endif
+#endif
+
+#ifdef __GNUC__
+  #define GLAD_GNUC_EXTENSION __extension__
+#else
+  #define GLAD_GNUC_EXTENSION
+#endif
+
+#define GLAD_UNUSED(x) (void)(x)
+
+#ifndef GLAD_API_CALL
+  #if defined(GLAD_API_CALL_EXPORT)
+    #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
+      #if defined(GLAD_API_CALL_EXPORT_BUILD)
+        #if defined(__GNUC__)
+          #define GLAD_API_CALL __attribute__ ((dllexport)) extern
+        #else
+          #define GLAD_API_CALL __declspec(dllexport) extern
+        #endif
+      #else
+        #if defined(__GNUC__)
+          #define GLAD_API_CALL __attribute__ ((dllimport)) extern
+        #else
+          #define GLAD_API_CALL __declspec(dllimport) extern
+        #endif
+      #endif
+    #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
+      #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
+    #else
+      #define GLAD_API_CALL extern
+    #endif
+  #else
+    #define GLAD_API_CALL extern
+  #endif
+#endif
+
+#ifdef APIENTRY
+  #define GLAD_API_PTR APIENTRY
+#elif GLAD_PLATFORM_WIN32
+  #define GLAD_API_PTR __stdcall
+#else
+  #define GLAD_API_PTR
+#endif
+
+#ifndef GLAPI
+#define GLAPI GLAD_API_CALL
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY GLAD_API_PTR
+#endif
+
+#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
+#define GLAD_VERSION_MAJOR(version) (version / 10000)
+#define GLAD_VERSION_MINOR(version) (version % 10000)
+
+#define GLAD_GENERATOR_VERSION "2.0.2"
+
+typedef void (*GLADapiproc)(void);
+
+typedef GLADapiproc (*GLADloadfunc)(const char *name);
+typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name);
+
+typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
+typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
+
+#endif /* GLAD_PLATFORM_H_ */
+
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_ACTIVE_PROGRAM_EXT 0x8259
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF
+#define GL_ALPHA 0x1906
+#define GL_ALPHA16F_EXT 0x881C
+#define GL_ALPHA32F_EXT 0x8816
+#define GL_ALPHA8_EXT 0x803C
+#define GL_ALPHA8_OES 0x803C
+#define GL_ALPHA_BITS 0x0D55
+#define GL_ALWAYS 0x0207
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
+#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_BACK 0x0405
+#define GL_BGRA8_EXT 0x93A1
+#define GL_BGRA_EXT 0x80E1
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLUE_BITS 0x0D54
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_BUFFER_ACCESS_OES 0x88BB
+#define GL_BUFFER_IMMUTABLE_STORAGE_EXT 0x821F
+#define GL_BUFFER_KHR 0x82E0
+#define GL_BUFFER_MAPPED_OES 0x88BC
+#define GL_BUFFER_MAP_POINTER_OES 0x88BD
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_STORAGE_FLAGS_EXT 0x8220
+#define GL_BUFFER_USAGE 0x8765
+#define GL_BYTE 0x1400
+#define GL_CCW 0x0901
+#define GL_CLAMP_TO_BORDER_EXT 0x812D
+#define GL_CLAMP_TO_BORDER_OES 0x812D
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
+#define GL_CLIENT_STORAGE_BIT_EXT 0x0200
+#define GL_CLIP_DEPTH_MODE 0x935D
+#define GL_CLIP_DEPTH_MODE_EXT 0x935D
+#define GL_CLIP_DISTANCE0_EXT 0x3000
+#define GL_CLIP_DISTANCE1_EXT 0x3001
+#define GL_CLIP_DISTANCE2_EXT 0x3002
+#define GL_CLIP_DISTANCE3_EXT 0x3003
+#define GL_CLIP_DISTANCE4_EXT 0x3004
+#define GL_CLIP_DISTANCE5_EXT 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE6_EXT 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_CLIP_DISTANCE7_EXT 0x3007
+#define GL_CLIP_ORIGIN 0x935C
+#define GL_CLIP_ORIGIN_EXT 0x935C
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+#define GL_COLORBURN_KHR 0x929A
+#define GL_COLORDODGE_KHR 0x9299
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#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_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_ATTACHMENT_EXT 0x90F0
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_EXT 0x1800
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_COMPLETION_STATUS_KHR 0x91B1
+#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#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_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_RGBA_ASTC_3x3x3_OES 0x93C0
+#define GL_COMPRESSED_RGBA_ASTC_4x3x3_OES 0x93C1
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_4x4x3_OES 0x93C2
+#define GL_COMPRESSED_RGBA_ASTC_4x4x4_OES 0x93C3
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x4x4_OES 0x93C4
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_5x5x4_OES 0x93C5
+#define GL_COMPRESSED_RGBA_ASTC_5x5x5_OES 0x93C6
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x5x5_OES 0x93C7
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_6x6x5_OES 0x93C8
+#define GL_COMPRESSED_RGBA_ASTC_6x6x6_OES 0x93C9
+#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_BPTC_UNORM_EXT 0x8E8C
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT 0x8E8F
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#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_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES 0x93E0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES 0x93E1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES 0x93E2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES 0x93E3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES 0x93E4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES 0x93E5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES 0x93E6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES 0x93E7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES 0x93E8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES 0x93E9
+#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_SRGB_ALPHA_BPTC_UNORM_EXT 0x8E8D
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG 0x93F0
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG 0x93F1
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#define GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
+#define GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
+#define GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT 0x00000010
+#define GL_CONTEXT_LOST_KHR 0x0507
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC
+#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB
+#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3
+#define GL_CONTEXT_ROBUST_ACCESS_KHR 0x90F3
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_CURRENT_QUERY_EXT 0x8865
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_CW 0x0900
+#define GL_D3D12_FENCE_VALUE_EXT 0x9595
+#define GL_DARKEN_KHR 0x9297
+#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245
+#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D
+#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243
+#define GL_DEBUG_OUTPUT_KHR 0x92E0
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242
+#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146
+#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148
+#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147
+#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B
+#define GL_DEBUG_SOURCE_API_KHR 0x8246
+#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A
+#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D
+#define GL_DEBUG_TYPE_ERROR_KHR 0x824C
+#define GL_DEBUG_TYPE_MARKER_KHR 0x8268
+#define GL_DEBUG_TYPE_OTHER_KHR 0x8251
+#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250
+#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A
+#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F
+#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E
+#define GL_DECODE_EXT 0x8A49
+#define GL_DECR 0x1E03
+#define GL_DECR_WRAP 0x8508
+#define GL_DEDICATED_MEMORY_OBJECT_EXT 0x9581
+#define GL_DELETE_STATUS 0x8B80
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_DEPTH_BITS 0x0D56
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_DEPTH_CLAMP_EXT 0x864F
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT16_OES 0x81A5
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#define GL_DEPTH_EXT 0x1801
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEVICE_LUID_EXT 0x9599
+#define GL_DEVICE_NODE_MASK_EXT 0x959A
+#define GL_DEVICE_UUID_EXT 0x9597
+#define GL_DIFFERENCE_KHR 0x929E
+#define GL_DITHER 0x0BD0
+#define GL_DONT_CARE 0x1100
+#define GL_DRAW_BUFFER0_EXT 0x8825
+#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_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_BUFFER_EXT 0x0C01
+#define GL_DRIVER_UUID_EXT 0x9598
+#define GL_DST_ALPHA 0x0304
+#define GL_DST_COLOR 0x0306
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_STORAGE_BIT_EXT 0x0100
+#define GL_EFFECTIVE_RASTER_SAMPLES_EXT 0x932C
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_EQUAL 0x0202
+#define GL_ETC1_RGB8_OES 0x8D64
+#define GL_EXCLUSION_KHR 0x92A0
+#define GL_EXCLUSIVE_EXT 0x8F11
+#define GL_EXTENSIONS 0x1F03
+#define GL_FALSE 0
+#define GL_FASTEST 0x1101
+#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D
+#define GL_FIRST_VERTEX_CONVENTION_OES 0x8E4D
+#define GL_FIXED 0x140C
+#define GL_FLOAT 0x1406
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_FRACTIONAL_EVEN_EXT 0x8E7C
+#define GL_FRACTIONAL_EVEN_OES 0x8E7C
+#define GL_FRACTIONAL_ODD_EXT 0x8E7B
+#define GL_FRACTIONAL_ODD_OES 0x8E7B
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES 0x8E5D
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+#define GL_FRAGMENT_SHADING_RATE_ATTACHMENT_WITH_DEFAULT_FRAMEBUFFER_SUPPORTED_EXT 0x96DF
+#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT 0x96D2
+#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT 0x96D5
+#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT 0x96D4
+#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT 0x96D6
+#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT 0x96D3
+#define GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT 0x8F6F
+#define GL_FRAGMENT_SHADING_RATE_WITH_SAMPLE_MASK_SUPPORTED_EXT 0x96DE
+#define GL_FRAGMENT_SHADING_RATE_WITH_SHADER_DEPTH_STENCIL_WRITES_SUPPORTED_EXT 0x96DD
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS_OES 0x9312
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT 0x9652
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRONT 0x0404
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_FRONT_FACE 0x0B46
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_GEOMETRY_LINKED_INPUT_TYPE_EXT 0x8917
+#define GL_GEOMETRY_LINKED_INPUT_TYPE_OES 0x8917
+#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT 0x8918
+#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES 0x8918
+#define GL_GEOMETRY_LINKED_VERTICES_OUT_EXT 0x8916
+#define GL_GEOMETRY_LINKED_VERTICES_OUT_OES 0x8916
+#define GL_GEOMETRY_SHADER_BIT_EXT 0x00000004
+#define GL_GEOMETRY_SHADER_BIT_OES 0x00000004
+#define GL_GEOMETRY_SHADER_EXT 0x8DD9
+#define GL_GEOMETRY_SHADER_INVOCATIONS_EXT 0x887F
+#define GL_GEOMETRY_SHADER_INVOCATIONS_OES 0x887F
+#define GL_GEOMETRY_SHADER_OES 0x8DD9
+#define GL_GEQUAL 0x0206
+#define GL_GPU_DISJOINT_EXT 0x8FBB
+#define GL_GREATER 0x0204
+#define GL_GREEN_BITS 0x0D53
+#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253
+#define GL_GUILTY_CONTEXT_RESET_KHR 0x8253
+#define GL_HALF_FLOAT_OES 0x8D61
+#define GL_HANDLE_TYPE_D3D11_IMAGE_EXT 0x958B
+#define GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT 0x958C
+#define GL_HANDLE_TYPE_D3D12_FENCE_EXT 0x9594
+#define GL_HANDLE_TYPE_D3D12_RESOURCE_EXT 0x958A
+#define GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT 0x9589
+#define GL_HANDLE_TYPE_OPAQUE_FD_EXT 0x9586
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_EXT 0x9587
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT 0x9588
+#define GL_HARDLIGHT_KHR 0x929B
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_HIGH_INT 0x8DF5
+#define GL_HSL_COLOR_KHR 0x92AF
+#define GL_HSL_HUE_KHR 0x92AD
+#define GL_HSL_LUMINOSITY_KHR 0x92B0
+#define GL_HSL_SATURATION_KHR 0x92AE
+#define GL_IMAGE_BUFFER_EXT 0x9051
+#define GL_IMAGE_BUFFER_OES 0x9051
+#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054
+#define GL_IMAGE_CUBE_MAP_ARRAY_OES 0x9054
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_INCLUSIVE_EXT 0x8F10
+#define GL_INCR 0x1E02
+#define GL_INCR_WRAP 0x8507
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254
+#define GL_INNOCENT_CONTEXT_RESET_KHR 0x8254
+#define GL_INT 0x1404
+#define GL_INT_10_10_10_2_OES 0x8DF7
+#define GL_INT_IMAGE_BUFFER_EXT 0x905C
+#define GL_INT_IMAGE_BUFFER_OES 0x905C
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x905F
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910C
+#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0
+#define GL_INT_SAMPLER_BUFFER_OES 0x8DD0
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900E
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900E
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_INVALID_OPERATION 0x0502
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVERT 0x150A
+#define GL_ISOLINES_EXT 0x8E7A
+#define GL_ISOLINES_OES 0x8E7A
+#define GL_IS_PER_PATCH_EXT 0x92E7
+#define GL_IS_PER_PATCH_OES 0x92E7
+#define GL_KEEP 0x1E00
+#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E
+#define GL_LAST_VERTEX_CONVENTION_OES 0x8E4E
+#define GL_LAYER_PROVOKING_VERTEX_EXT 0x825E
+#define GL_LAYER_PROVOKING_VERTEX_OES 0x825E
+#define GL_LAYOUT_COLOR_ATTACHMENT_EXT 0x958E
+#define GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT 0x9531
+#define GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT 0x9530
+#define GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT 0x958F
+#define GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT 0x9590
+#define GL_LAYOUT_GENERAL_EXT 0x958D
+#define GL_LAYOUT_SHADER_READ_ONLY_EXT 0x9591
+#define GL_LAYOUT_TRANSFER_DST_EXT 0x9593
+#define GL_LAYOUT_TRANSFER_SRC_EXT 0x9592
+#define GL_LEQUAL 0x0203
+#define GL_LESS 0x0201
+#define GL_LIGHTEN_KHR 0x9298
+#define GL_LINEAR 0x2601
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINEAR_TILING_EXT 0x9585
+#define GL_LINES 0x0001
+#define GL_LINES_ADJACENCY_EXT 0x000A
+#define GL_LINES_ADJACENCY_OES 0x000A
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B
+#define GL_LINE_STRIP_ADJACENCY_OES 0x000B
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINK_STATUS 0x8B82
+#define GL_LOCATION_INDEX_EXT 0x930F
+#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
+#define GL_LOSE_CONTEXT_ON_RESET_KHR 0x8252
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_LOWER_LEFT_EXT 0x8CA1
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_LOW_INT 0x8DF3
+#define GL_LUID_SIZE_EXT 8
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE16F_EXT 0x881E
+#define GL_LUMINANCE32F_EXT 0x8818
+#define GL_LUMINANCE4_ALPHA4_OES 0x8043
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_LUMINANCE8_ALPHA8_OES 0x8045
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE8_OES 0x8040
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_LUMINANCE_ALPHA16F_EXT 0x881F
+#define GL_LUMINANCE_ALPHA32F_EXT 0x8819
+#define GL_MAP_COHERENT_BIT_EXT 0x0080
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004
+#define GL_MAP_PERSISTENT_BIT_EXT 0x0040
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_READ_BIT_EXT 0x0001
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_WRITE_BIT_EXT 0x0002
+#define GL_MAX 0x8008
+#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
+#define GL_MAX_CLIP_DISTANCES_EXT 0x0D32
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8A32
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8A32
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E1E
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E1F
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E1F
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_MAX_CULL_DISTANCES 0x82F9
+#define GL_MAX_CULL_DISTANCES_EXT 0x82F9
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143
+#define GL_MAX_DRAW_BUFFERS_EXT 0x8824
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT 0x88FC
+#define GL_MAX_EXT 0x8008
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5C
+#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT 0x96DC
+#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT 0x96DB
+#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT 0x96DA
+#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT 0x96D8
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_MAX_FRAMEBUFFER_LAYERS_EXT 0x9317
+#define GL_MAX_FRAMEBUFFER_LAYERS_OES 0x9317
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT 0x92D5
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES 0x92D5
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES 0x92CF
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT 0x90CD
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES 0x90CD
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT 0x9123
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES 0x8DE0
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT 0x8E5A
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES 0x8E5A
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT 0x90D7
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES 0x90D7
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES 0x8C29
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES 0x8DE1
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT 0x8A2C
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES 0x8A2C
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8DDF
+#define GL_MAX_LABEL_LENGTH_KHR 0x82E8
+#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2
+#define GL_MAX_PATCH_VERTICES_EXT 0x8E7D
+#define GL_MAX_PATCH_VERTICES_OES 0x8E7D
+#define GL_MAX_RASTER_SAMPLES_EXT 0x9329
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT 0x9650
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT 0x9651
+#define GL_MAX_SHADER_COMPILER_THREADS_KHR 0x91B0
+#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63
+#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT 0x8F67
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT 0x919A
+#define GL_MAX_SPARSE_TEXTURE_SIZE_EXT 0x9198
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT 0x92D3
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES 0x92D3
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT 0x92CD
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES 0x92CD
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT 0x90CB
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES 0x90CB
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT 0x886C
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES 0x886C
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT 0x8E83
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES 0x8E83
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT 0x90D8
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES 0x90D8
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT 0x8E81
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES 0x8E81
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT 0x8E85
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES 0x8E85
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT 0x8E89
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES 0x8E89
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E7F
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E7F
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT 0x92D4
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES 0x92D4
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT 0x92CE
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES 0x92CE
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT 0x90CC
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES 0x90CC
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT 0x886D
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES 0x886D
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT 0x8E86
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES 0x8E86
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT 0x90D9
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES 0x90D9
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT 0x8E82
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES 0x8E82
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT 0x8E8A
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES 0x8E8A
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E80
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E80
+#define GL_MAX_TESS_GEN_LEVEL_EXT 0x8E7E
+#define GL_MAX_TESS_GEN_LEVEL_OES 0x8E7E
+#define GL_MAX_TESS_PATCH_COMPONENTS_EXT 0x8E84
+#define GL_MAX_TESS_PATCH_COMPONENTS_OES 0x8E84
+#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B
+#define GL_MAX_TEXTURE_BUFFER_SIZE_OES 0x8C2B
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VIEWPORTS_OES 0x825B
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_WINDOW_RECTANGLES_EXT 0x8F14
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_MIN 0x8007
+#define GL_MIN_EXT 0x8007
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5B
+#define GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT 0x96D9
+#define GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT 0x96D7
+#define GL_MIN_SAMPLE_SHADING_VALUE_OES 0x8C37
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MULTIPLY_KHR 0x9294
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT 0x932B
+#define GL_MULTIVIEW_EXT 0x90F1
+#define GL_NEAREST 0x2600
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEGATIVE_ONE_TO_ONE 0x935E
+#define GL_NEGATIVE_ONE_TO_ONE_EXT 0x935E
+#define GL_NEVER 0x0200
+#define GL_NICEST 0x1102
+#define GL_NONE 0
+#define GL_NOTEQUAL 0x0205
+#define GL_NO_ERROR 0
+#define GL_NO_RESET_NOTIFICATION_EXT 0x8261
+#define GL_NO_RESET_NOTIFICATION_KHR 0x8261
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_NUM_DEVICE_UUIDS_EXT 0x9596
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_NUM_SPARSE_LEVELS_EXT 0x91AA
+#define GL_NUM_SURFACE_COMPRESSION_FIXED_RATES_EXT 0x8F6E
+#define GL_NUM_TILING_TYPES_EXT 0x9582
+#define GL_NUM_VIRTUAL_PAGE_SIZES_EXT 0x91A8
+#define GL_NUM_WINDOW_RECTANGLES_EXT 0x8F15
+#define GL_ONE 1
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_ONE_MINUS_SRC1_ALPHA_EXT 0x88FB
+#define GL_ONE_MINUS_SRC1_COLOR_EXT 0x88FA
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_OPTIMAL_TILING_EXT 0x9584
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_OVERLAY_KHR 0x9296
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PATCHES_EXT 0x000E
+#define GL_PATCHES_OES 0x000E
+#define GL_PATCH_VERTICES_EXT 0x8E72
+#define GL_PATCH_VERTICES_OES 0x8E72
+#define GL_POINTS 0x0000
+#define GL_POLYGON_OFFSET_CLAMP 0x8E1B
+#define GL_POLYGON_OFFSET_CLAMP_EXT 0x8E1B
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_PRIMITIVES_GENERATED_EXT 0x8C87
+#define GL_PRIMITIVES_GENERATED_OES 0x8C87
+#define GL_PRIMITIVE_BOUNDING_BOX_EXT 0x92BE
+#define GL_PRIMITIVE_BOUNDING_BOX_OES 0x92BE
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES 0x8221
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#define GL_PROGRAM_KHR 0x82E2
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A
+#define GL_PROGRAM_PIPELINE_KHR 0x82E4
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_SEPARABLE_EXT 0x8258
+#define GL_PROTECTED_MEMORY_OBJECT_EXT 0x959B
+#define GL_QUADS_EXT 0x0007
+#define GL_QUADS_OES 0x0007
+#define GL_QUERY_COUNTER_BITS_EXT 0x8864
+#define GL_QUERY_KHR 0x82E3
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#define GL_QUERY_RESULT_EXT 0x8866
+#define GL_R16F_EXT 0x822D
+#define GL_R16_EXT 0x822A
+#define GL_R16_SNORM_EXT 0x8F98
+#define GL_R32F_EXT 0x822E
+#define GL_R8_EXT 0x8229
+#define GL_R8_SNORM 0x8F94
+#define GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT 0x932A
+#define GL_RASTER_MULTISAMPLE_EXT 0x9327
+#define GL_RASTER_SAMPLES_EXT 0x9328
+#define GL_READ_BUFFER_EXT 0x0C02
+#define GL_RED_BITS 0x0D52
+#define GL_RED_EXT 0x1903
+#define GL_REFERENCED_BY_GEOMETRY_SHADER_EXT 0x9309
+#define GL_REFERENCED_BY_GEOMETRY_SHADER_OES 0x9309
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT 0x9307
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT 0x9308
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES 0x9308
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERER 0x1F01
+#define GL_REPEAT 0x2901
+#define GL_REPLACE 0x1E01
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256
+#define GL_RG16F_EXT 0x822F
+#define GL_RG16_EXT 0x822C
+#define GL_RG16_SNORM_EXT 0x8F99
+#define GL_RG32F_EXT 0x8230
+#define GL_RG8_EXT 0x822B
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB 0x1907
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB16F_EXT 0x881B
+#define GL_RGB16_EXT 0x8054
+#define GL_RGB16_SNORM_EXT 0x8F9A
+#define GL_RGB32F_EXT 0x8815
+#define GL_RGB565 0x8D62
+#define GL_RGB565_OES 0x8D62
+#define GL_RGB5_A1 0x8057
+#define GL_RGB5_A1_OES 0x8057
+#define GL_RGB8_OES 0x8051
+#define GL_RGBA 0x1908
+#define GL_RGBA16F_EXT 0x881A
+#define GL_RGBA16_EXT 0x805B
+#define GL_RGBA16_SNORM_EXT 0x8F9B
+#define GL_RGBA32F_EXT 0x8814
+#define GL_RGBA4 0x8056
+#define GL_RGBA4_OES 0x8056
+#define GL_RGBA8_OES 0x8058
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_RG_EXT 0x8227
+#define GL_SAMPLER 0x82E6
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910B
+#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62
+#define GL_SAMPLER_3D_OES 0x8B5F
+#define GL_SAMPLER_BUFFER_EXT 0x8DC2
+#define GL_SAMPLER_BUFFER_OES 0x8DC2
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_OES 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT 0x900D
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES 0x900D
+#define GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT 0x8BE7
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+#define GL_SAMPLER_KHR 0x82E6
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_SHADING_OES 0x8C36
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_SCREEN_KHR 0x9295
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_KHR 0x82E1
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_SHADING_RATE_1X1_PIXELS_EXT 0x96A6
+#define GL_SHADING_RATE_1X1_PIXELS_QCOM 0x96A6
+#define GL_SHADING_RATE_1X2_PIXELS_EXT 0x96A7
+#define GL_SHADING_RATE_1X2_PIXELS_QCOM 0x96A7
+#define GL_SHADING_RATE_1X4_PIXELS_EXT 0x96AA
+#define GL_SHADING_RATE_1X4_PIXELS_QCOM 0x96AA
+#define GL_SHADING_RATE_2X1_PIXELS_EXT 0x96A8
+#define GL_SHADING_RATE_2X1_PIXELS_QCOM 0x96A8
+#define GL_SHADING_RATE_2X2_PIXELS_EXT 0x96A9
+#define GL_SHADING_RATE_2X2_PIXELS_QCOM 0x96A9
+#define GL_SHADING_RATE_2X4_PIXELS_EXT 0x96AD
+#define GL_SHADING_RATE_2X4_PIXELS_QCOM 0x96AD
+#define GL_SHADING_RATE_4X1_PIXELS_EXT 0x96AB
+#define GL_SHADING_RATE_4X1_PIXELS_QCOM 0x96AB
+#define GL_SHADING_RATE_4X2_PIXELS_EXT 0x96AC
+#define GL_SHADING_RATE_4X2_PIXELS_QCOM 0x96AC
+#define GL_SHADING_RATE_4X4_PIXELS_EXT 0x96AE
+#define GL_SHADING_RATE_4X4_PIXELS_QCOM 0x96AE
+#define GL_SHADING_RATE_ATTACHMENT_EXT 0x96D1
+#define GL_SHADING_RATE_EXT 0x96D0
+#define GL_SHORT 0x1402
+#define GL_SKIP_DECODE_EXT 0x8A4A
+#define GL_SOFTLIGHT_KHR 0x929C
+#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT 0x91A9
+#define GL_SR8_EXT 0x8FBD
+#define GL_SRC1_ALPHA_EXT 0x8589
+#define GL_SRC1_COLOR_EXT 0x88F9
+#define GL_SRC_ALPHA 0x0302
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_SRC_ALPHA_SATURATE_EXT 0x0308
+#define GL_SRC_COLOR 0x0300
+#define GL_SRG8_EXT 0x8FBE
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB_EXT 0x8C40
+#define GL_STACK_OVERFLOW_KHR 0x0503
+#define GL_STACK_UNDERFLOW_KHR 0x0504
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_FUNC 0x8800
+#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_STENCIL_BITS 0x0D57
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_EXT 0x1802
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_INDEX1_OES 0x8D46
+#define GL_STENCIL_INDEX4_OES 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX8_OES 0x8D48
+#define GL_STENCIL_INDEX_OES 0x1901
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STREAM_DRAW 0x88E0
+#define GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR 0x00000004
+#define GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR 0x00000008
+#define GL_SUBGROUP_FEATURE_BASIC_BIT_KHR 0x00000001
+#define GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR 0x00000040
+#define GL_SUBGROUP_FEATURE_QUAD_BIT_KHR 0x00000080
+#define GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR 0x00000010
+#define GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR 0x00000020
+#define GL_SUBGROUP_FEATURE_VOTE_BIT_KHR 0x00000002
+#define GL_SUBGROUP_QUAD_ALL_STAGES_KHR 0x9535
+#define GL_SUBGROUP_SIZE_KHR 0x9532
+#define GL_SUBGROUP_SUPPORTED_FEATURES_KHR 0x9534
+#define GL_SUBGROUP_SUPPORTED_STAGES_KHR 0x9533
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_SURFACE_COMPRESSION_EXT 0x96C0
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_10BPC_EXT 0x96CD
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_11BPC_EXT 0x96CE
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_12BPC_EXT 0x96CF
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT 0x96C4
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_2BPC_EXT 0x96C5
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_3BPC_EXT 0x96C6
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_4BPC_EXT 0x96C7
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_5BPC_EXT 0x96C8
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_6BPC_EXT 0x96C9
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_7BPC_EXT 0x96CA
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_8BPC_EXT 0x96CB
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_9BPC_EXT 0x96CC
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT 0x96C2
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT 0x96C1
+#define GL_TESS_CONTROL_OUTPUT_VERTICES_EXT 0x8E75
+#define GL_TESS_CONTROL_OUTPUT_VERTICES_OES 0x8E75
+#define GL_TESS_CONTROL_SHADER_BIT_EXT 0x00000008
+#define GL_TESS_CONTROL_SHADER_BIT_OES 0x00000008
+#define GL_TESS_CONTROL_SHADER_EXT 0x8E88
+#define GL_TESS_CONTROL_SHADER_OES 0x8E88
+#define GL_TESS_EVALUATION_SHADER_BIT_EXT 0x00000010
+#define GL_TESS_EVALUATION_SHADER_BIT_OES 0x00000010
+#define GL_TESS_EVALUATION_SHADER_EXT 0x8E87
+#define GL_TESS_EVALUATION_SHADER_OES 0x8E87
+#define GL_TESS_GEN_MODE_EXT 0x8E76
+#define GL_TESS_GEN_MODE_OES 0x8E76
+#define GL_TESS_GEN_POINT_MODE_EXT 0x8E79
+#define GL_TESS_GEN_POINT_MODE_OES 0x8E79
+#define GL_TESS_GEN_SPACING_EXT 0x8E77
+#define GL_TESS_GEN_SPACING_OES 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER_EXT 0x8E78
+#define GL_TESS_GEN_VERTEX_ORDER_OES 0x8E78
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#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_TEXTURE2 0x84C2
+#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_TEXTURE3 0x84C3
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#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_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES 0x9102
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_3D_OES 0x806F
+#define GL_TEXTURE_ASTC_DECODE_PRECISION_EXT 0x8F69
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES 0x9105
+#define GL_TEXTURE_BINDING_3D_OES 0x806A
+#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
+#define GL_TEXTURE_BINDING_BUFFER_OES 0x8C2C
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT 0x900A
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES 0x900A
+#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define GL_TEXTURE_BORDER_COLOR_EXT 0x1004
+#define GL_TEXTURE_BORDER_COLOR_OES 0x1004
+#define GL_TEXTURE_BUFFER_BINDING_EXT 0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING_OES 0x8C2A
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES 0x8C2D
+#define GL_TEXTURE_BUFFER_EXT 0x8C2A
+#define GL_TEXTURE_BUFFER_OES 0x8C2A
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT 0x919F
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES 0x919F
+#define GL_TEXTURE_BUFFER_OFFSET_EXT 0x919D
+#define GL_TEXTURE_BUFFER_OFFSET_OES 0x919D
+#define GL_TEXTURE_BUFFER_SIZE_EXT 0x919E
+#define GL_TEXTURE_BUFFER_SIZE_OES 0x919E
+#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D
+#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_CUBE_MAP_ARRAY_EXT 0x9009
+#define GL_TEXTURE_CUBE_MAP_ARRAY_OES 0x9009
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT 0x8FBF
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_PROTECTED_EXT 0x8BFA
+#define GL_TEXTURE_REDUCTION_MODE_ARB 0x9366
+#define GL_TEXTURE_REDUCTION_MODE_EXT 0x9366
+#define GL_TEXTURE_SPARSE_EXT 0x91A6
+#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define GL_TEXTURE_TILING_EXT 0x9580
+#define GL_TEXTURE_VIEW_MIN_LAYER_EXT 0x82DD
+#define GL_TEXTURE_VIEW_MIN_LAYER_OES 0x82DD
+#define GL_TEXTURE_VIEW_MIN_LEVEL_EXT 0x82DB
+#define GL_TEXTURE_VIEW_MIN_LEVEL_OES 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LAYERS_EXT 0x82DE
+#define GL_TEXTURE_VIEW_NUM_LAYERS_OES 0x82DE
+#define GL_TEXTURE_VIEW_NUM_LEVELS_EXT 0x82DC
+#define GL_TEXTURE_VIEW_NUM_LEVELS_OES 0x82DC
+#define GL_TEXTURE_WRAP_R_OES 0x8072
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TILING_TYPES_EXT 0x9583
+#define GL_TIMESTAMP_EXT 0x8E28
+#define GL_TIME_ELAPSED_EXT 0x88BF
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLES_ADJACENCY_EXT 0x000C
+#define GL_TRIANGLES_ADJACENCY_OES 0x000C
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D
+#define GL_TRIANGLE_STRIP_ADJACENCY_OES 0x000D
+#define GL_TRUE 1
+#define GL_UNDEFINED_VERTEX_EXT 0x8260
+#define GL_UNDEFINED_VERTEX_OES 0x8260
+#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255
+#define GL_UNKNOWN_CONTEXT_RESET_KHR 0x8255
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2
+#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
+#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_OES 0x9067
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x906A
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910D
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_OES 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900F
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900F
+#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_UPPER_LEFT_EXT 0x8CA2
+#define GL_UUID_SIZE_EXT 16
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_VENDOR 0x1F00
+#define GL_VERSION 0x1F02
+#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+#define GL_VERTEX_ARRAY_KHR 0x8074
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_EXT 0x88FE
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_VERTEX_SHADER_BIT_EXT 0x00000001
+#define GL_VIEWPORT 0x0BA2
+#define GL_VIEWPORT_BOUNDS_RANGE_OES 0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES 0x825F
+#define GL_VIEWPORT_SUBPIXEL_BITS_OES 0x825C
+#define GL_VIRTUAL_PAGE_SIZE_INDEX_EXT 0x91A7
+#define GL_VIRTUAL_PAGE_SIZE_X_EXT 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_EXT 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_EXT 0x9197
+#define GL_WEIGHTED_AVERAGE_ARB 0x9367
+#define GL_WEIGHTED_AVERAGE_EXT 0x9367
+#define GL_WINDOW_RECTANGLE_EXT 0x8F12
+#define GL_WINDOW_RECTANGLE_MODE_EXT 0x8F13
+#define GL_WRITE_ONLY_OES 0x88B9
+#define GL_ZERO 0
+#define GL_ZERO_TO_ONE 0x935F
+#define GL_ZERO_TO_ONE_EXT 0x935F
+
+
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2018 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.
+ *
+ * The master copy of khrplatform.h is maintained in the Khronos EGL
+ * Registry repository at https://github.com/KhronosGroup/EGL-Registry
+ * The last semantic modification to khrplatform.h was at commit ID:
+ *      67a3e0864c2d75ea5287b9f3d2eb74a745936692
+ *
+ * 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 filing pull requests or issues on
+ * the EGL Registry repository linked above.
+ *
+ *
+ * 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_GLAD_API_PTR
+ *    KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ *      KHRONOS_APICALL void KHRONOS_GLAD_API_PTR funcname(
+ *                                  int arg1,
+ *                                  int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
+#   define KHRONOS_STATIC 1
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(KHRONOS_STATIC)
+    /* If the preprocessor constant KHRONOS_STATIC is defined, make the
+     * header compatible with static linking. */
+#   define KHRONOS_APICALL
+#elif defined(_WIN32)
+#   define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+#   define KHRONOS_APICALL IMPORT_C
+#elif defined(__ANDROID__)
+#   define KHRONOS_APICALL __attribute__((visibility("default")))
+#else
+#   define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_GLAD_API_PTR
+ *-------------------------------------------------------------------------
+ * 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_GLAD_API_PTR __stdcall
+#else
+#   define KHRONOS_GLAD_API_PTR
+#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
+/*
+ * To support platform where unsigned long cannot be used interchangeably with
+ * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
+ * Ideally, we could just use (u)intptr_t everywhere, but this could result in
+ * ABI breakage if khronos_uintptr_t is changed from unsigned long to
+ * unsigned long long or similar (this results in different C++ name mangling).
+ * To avoid changes for existing platforms, we restrict usage of intptr_t to
+ * platforms where the size of a pointer is larger than the size of long.
+ */
+#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
+#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
+#define KHRONOS_USE_INTPTR_T
+#endif
+#endif
+
+#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 KHRONOS_USE_INTPTR_T
+typedef intptr_t               khronos_intptr_t;
+typedef uintptr_t              khronos_uintptr_t;
+#elif defined(_WIN64)
+typedef signed   long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+#else
+typedef signed   long  int     khronos_intptr_t;
+typedef unsigned long  int     khronos_uintptr_t;
+#endif
+
+#if defined(_WIN64)
+typedef signed   long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+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_ */
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint8_t GLubyte;
+typedef khronos_int16_t GLshort;
+typedef khronos_uint16_t GLushort;
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef khronos_int32_t GLclampx;
+typedef int GLsizei;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void *GLeglClientBufferEXT;
+typedef void *GLeglImageOES;
+typedef char GLchar;
+typedef char GLcharARB;
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef khronos_uint16_t GLhalf;
+typedef khronos_uint16_t GLhalfARB;
+typedef khronos_int32_t GLfixed;
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptr;
+#else
+typedef khronos_intptr_t GLintptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptrARB;
+#else
+typedef khronos_intptr_t GLintptrARB;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptr;
+#else
+typedef khronos_ssize_t GLsizeiptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptrARB;
+#else
+typedef khronos_ssize_t GLsizeiptrARB;
+#endif
+typedef khronos_int64_t GLint64;
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_uint64_t GLuint64EXT;
+typedef struct __GLsync *GLsync;
+struct _cl_context;
+struct _cl_event;
+typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+typedef unsigned short GLhalfNV;
+typedef GLintptr GLvdpauSurfaceNV;
+typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void);
+
+
+#define GL_ES_VERSION_2_0 1
+GLAD_API_CALL int GLAD_GL_ES_VERSION_2_0;
+#define GL_EXT_EGL_image_array 1
+GLAD_API_CALL int GLAD_GL_EXT_EGL_image_array;
+#define GL_EXT_EGL_image_storage 1
+GLAD_API_CALL int GLAD_GL_EXT_EGL_image_storage;
+#define GL_EXT_EGL_image_storage_compression 1
+GLAD_API_CALL int GLAD_GL_EXT_EGL_image_storage_compression;
+#define GL_EXT_YUV_target 1
+GLAD_API_CALL int GLAD_GL_EXT_YUV_target;
+#define GL_EXT_base_instance 1
+GLAD_API_CALL int GLAD_GL_EXT_base_instance;
+#define GL_EXT_blend_func_extended 1
+GLAD_API_CALL int GLAD_GL_EXT_blend_func_extended;
+#define GL_EXT_blend_minmax 1
+GLAD_API_CALL int GLAD_GL_EXT_blend_minmax;
+#define GL_EXT_buffer_storage 1
+GLAD_API_CALL int GLAD_GL_EXT_buffer_storage;
+#define GL_EXT_clear_texture 1
+GLAD_API_CALL int GLAD_GL_EXT_clear_texture;
+#define GL_EXT_clip_control 1
+GLAD_API_CALL int GLAD_GL_EXT_clip_control;
+#define GL_EXT_clip_cull_distance 1
+GLAD_API_CALL int GLAD_GL_EXT_clip_cull_distance;
+#define GL_EXT_color_buffer_float 1
+GLAD_API_CALL int GLAD_GL_EXT_color_buffer_float;
+#define GL_EXT_color_buffer_half_float 1
+GLAD_API_CALL int GLAD_GL_EXT_color_buffer_half_float;
+#define GL_EXT_conservative_depth 1
+GLAD_API_CALL int GLAD_GL_EXT_conservative_depth;
+#define GL_EXT_copy_image 1
+GLAD_API_CALL int GLAD_GL_EXT_copy_image;
+#define GL_EXT_debug_label 1
+GLAD_API_CALL int GLAD_GL_EXT_debug_label;
+#define GL_EXT_debug_marker 1
+GLAD_API_CALL int GLAD_GL_EXT_debug_marker;
+#define GL_EXT_depth_clamp 1
+GLAD_API_CALL int GLAD_GL_EXT_depth_clamp;
+#define GL_EXT_discard_framebuffer 1
+GLAD_API_CALL int GLAD_GL_EXT_discard_framebuffer;
+#define GL_EXT_disjoint_timer_query 1
+GLAD_API_CALL int GLAD_GL_EXT_disjoint_timer_query;
+#define GL_EXT_draw_buffers 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_buffers;
+#define GL_EXT_draw_buffers_indexed 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_buffers_indexed;
+#define GL_EXT_draw_elements_base_vertex 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_elements_base_vertex;
+#define GL_EXT_draw_instanced 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_instanced;
+#define GL_EXT_draw_transform_feedback 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_transform_feedback;
+#define GL_EXT_external_buffer 1
+GLAD_API_CALL int GLAD_GL_EXT_external_buffer;
+#define GL_EXT_float_blend 1
+GLAD_API_CALL int GLAD_GL_EXT_float_blend;
+#define GL_EXT_fragment_shading_rate 1
+GLAD_API_CALL int GLAD_GL_EXT_fragment_shading_rate;
+#define GL_EXT_geometry_point_size 1
+GLAD_API_CALL int GLAD_GL_EXT_geometry_point_size;
+#define GL_EXT_geometry_shader 1
+GLAD_API_CALL int GLAD_GL_EXT_geometry_shader;
+#define GL_EXT_gpu_shader5 1
+GLAD_API_CALL int GLAD_GL_EXT_gpu_shader5;
+#define GL_EXT_instanced_arrays 1
+GLAD_API_CALL int GLAD_GL_EXT_instanced_arrays;
+#define GL_EXT_map_buffer_range 1
+GLAD_API_CALL int GLAD_GL_EXT_map_buffer_range;
+#define GL_EXT_memory_object 1
+GLAD_API_CALL int GLAD_GL_EXT_memory_object;
+#define GL_EXT_memory_object_fd 1
+GLAD_API_CALL int GLAD_GL_EXT_memory_object_fd;
+#define GL_EXT_memory_object_win32 1
+GLAD_API_CALL int GLAD_GL_EXT_memory_object_win32;
+#define GL_EXT_multi_draw_arrays 1
+GLAD_API_CALL int GLAD_GL_EXT_multi_draw_arrays;
+#define GL_EXT_multi_draw_indirect 1
+GLAD_API_CALL int GLAD_GL_EXT_multi_draw_indirect;
+#define GL_EXT_multisampled_compatibility 1
+GLAD_API_CALL int GLAD_GL_EXT_multisampled_compatibility;
+#define GL_EXT_multisampled_render_to_texture 1
+GLAD_API_CALL int GLAD_GL_EXT_multisampled_render_to_texture;
+#define GL_EXT_multisampled_render_to_texture2 1
+GLAD_API_CALL int GLAD_GL_EXT_multisampled_render_to_texture2;
+#define GL_EXT_multiview_draw_buffers 1
+GLAD_API_CALL int GLAD_GL_EXT_multiview_draw_buffers;
+#define GL_EXT_multiview_tessellation_geometry_shader 1
+GLAD_API_CALL int GLAD_GL_EXT_multiview_tessellation_geometry_shader;
+#define GL_EXT_multiview_texture_multisample 1
+GLAD_API_CALL int GLAD_GL_EXT_multiview_texture_multisample;
+#define GL_EXT_multiview_timer_query 1
+GLAD_API_CALL int GLAD_GL_EXT_multiview_timer_query;
+#define GL_EXT_occlusion_query_boolean 1
+GLAD_API_CALL int GLAD_GL_EXT_occlusion_query_boolean;
+#define GL_EXT_polygon_offset_clamp 1
+GLAD_API_CALL int GLAD_GL_EXT_polygon_offset_clamp;
+#define GL_EXT_post_depth_coverage 1
+GLAD_API_CALL int GLAD_GL_EXT_post_depth_coverage;
+#define GL_EXT_primitive_bounding_box 1
+GLAD_API_CALL int GLAD_GL_EXT_primitive_bounding_box;
+#define GL_EXT_protected_textures 1
+GLAD_API_CALL int GLAD_GL_EXT_protected_textures;
+#define GL_EXT_pvrtc_sRGB 1
+GLAD_API_CALL int GLAD_GL_EXT_pvrtc_sRGB;
+#define GL_EXT_raster_multisample 1
+GLAD_API_CALL int GLAD_GL_EXT_raster_multisample;
+#define GL_EXT_read_format_bgra 1
+GLAD_API_CALL int GLAD_GL_EXT_read_format_bgra;
+#define GL_EXT_render_snorm 1
+GLAD_API_CALL int GLAD_GL_EXT_render_snorm;
+#define GL_EXT_robustness 1
+GLAD_API_CALL int GLAD_GL_EXT_robustness;
+#define GL_EXT_sRGB 1
+GLAD_API_CALL int GLAD_GL_EXT_sRGB;
+#define GL_EXT_sRGB_write_control 1
+GLAD_API_CALL int GLAD_GL_EXT_sRGB_write_control;
+#define GL_EXT_semaphore 1
+GLAD_API_CALL int GLAD_GL_EXT_semaphore;
+#define GL_EXT_semaphore_fd 1
+GLAD_API_CALL int GLAD_GL_EXT_semaphore_fd;
+#define GL_EXT_semaphore_win32 1
+GLAD_API_CALL int GLAD_GL_EXT_semaphore_win32;
+#define GL_EXT_separate_depth_stencil 1
+GLAD_API_CALL int GLAD_GL_EXT_separate_depth_stencil;
+#define GL_EXT_separate_shader_objects 1
+GLAD_API_CALL int GLAD_GL_EXT_separate_shader_objects;
+#define GL_EXT_shader_framebuffer_fetch 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_framebuffer_fetch;
+#define GL_EXT_shader_framebuffer_fetch_non_coherent 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_framebuffer_fetch_non_coherent;
+#define GL_EXT_shader_group_vote 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_group_vote;
+#define GL_EXT_shader_implicit_conversions 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_implicit_conversions;
+#define GL_EXT_shader_integer_mix 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_integer_mix;
+#define GL_EXT_shader_io_blocks 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_io_blocks;
+#define GL_EXT_shader_non_constant_global_initializers 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_non_constant_global_initializers;
+#define GL_EXT_shader_pixel_local_storage 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_pixel_local_storage;
+#define GL_EXT_shader_pixel_local_storage2 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_pixel_local_storage2;
+#define GL_EXT_shader_samples_identical 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_samples_identical;
+#define GL_EXT_shader_texture_lod 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_texture_lod;
+#define GL_EXT_shadow_samplers 1
+GLAD_API_CALL int GLAD_GL_EXT_shadow_samplers;
+#define GL_EXT_sparse_texture 1
+GLAD_API_CALL int GLAD_GL_EXT_sparse_texture;
+#define GL_EXT_sparse_texture2 1
+GLAD_API_CALL int GLAD_GL_EXT_sparse_texture2;
+#define GL_EXT_tessellation_point_size 1
+GLAD_API_CALL int GLAD_GL_EXT_tessellation_point_size;
+#define GL_EXT_tessellation_shader 1
+GLAD_API_CALL int GLAD_GL_EXT_tessellation_shader;
+#define GL_EXT_texture_border_clamp 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_border_clamp;
+#define GL_EXT_texture_buffer 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_buffer;
+#define GL_EXT_texture_compression_astc_decode_mode 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_astc_decode_mode;
+#define GL_EXT_texture_compression_bptc 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_bptc;
+#define GL_EXT_texture_compression_dxt1 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_dxt1;
+#define GL_EXT_texture_compression_rgtc 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_rgtc;
+#define GL_EXT_texture_compression_s3tc 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_s3tc;
+#define GL_EXT_texture_compression_s3tc_srgb 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_s3tc_srgb;
+#define GL_EXT_texture_cube_map_array 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_cube_map_array;
+#define GL_EXT_texture_filter_anisotropic 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_filter_anisotropic;
+#define GL_EXT_texture_filter_minmax 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_filter_minmax;
+#define GL_EXT_texture_format_BGRA8888 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_format_BGRA8888;
+#define GL_EXT_texture_format_sRGB_override 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_format_sRGB_override;
+#define GL_EXT_texture_mirror_clamp_to_edge 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_mirror_clamp_to_edge;
+#define GL_EXT_texture_norm16 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_norm16;
+#define GL_EXT_texture_query_lod 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_query_lod;
+#define GL_EXT_texture_rg 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_rg;
+#define GL_EXT_texture_sRGB_R8 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_sRGB_R8;
+#define GL_EXT_texture_sRGB_RG8 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_sRGB_RG8;
+#define GL_EXT_texture_sRGB_decode 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_sRGB_decode;
+#define GL_EXT_texture_shadow_lod 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_shadow_lod;
+#define GL_EXT_texture_storage 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_storage;
+#define GL_EXT_texture_storage_compression 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_storage_compression;
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_type_2_10_10_10_REV;
+#define GL_EXT_texture_view 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_view;
+#define GL_EXT_unpack_subimage 1
+GLAD_API_CALL int GLAD_GL_EXT_unpack_subimage;
+#define GL_EXT_win32_keyed_mutex 1
+GLAD_API_CALL int GLAD_GL_EXT_win32_keyed_mutex;
+#define GL_EXT_window_rectangles 1
+GLAD_API_CALL int GLAD_GL_EXT_window_rectangles;
+#define GL_KHR_blend_equation_advanced 1
+GLAD_API_CALL int GLAD_GL_KHR_blend_equation_advanced;
+#define GL_KHR_blend_equation_advanced_coherent 1
+GLAD_API_CALL int GLAD_GL_KHR_blend_equation_advanced_coherent;
+#define GL_KHR_context_flush_control 1
+GLAD_API_CALL int GLAD_GL_KHR_context_flush_control;
+#define GL_KHR_debug 1
+GLAD_API_CALL int GLAD_GL_KHR_debug;
+#define GL_KHR_no_error 1
+GLAD_API_CALL int GLAD_GL_KHR_no_error;
+#define GL_KHR_parallel_shader_compile 1
+GLAD_API_CALL int GLAD_GL_KHR_parallel_shader_compile;
+#define GL_KHR_robust_buffer_access_behavior 1
+GLAD_API_CALL int GLAD_GL_KHR_robust_buffer_access_behavior;
+#define GL_KHR_robustness 1
+GLAD_API_CALL int GLAD_GL_KHR_robustness;
+#define GL_KHR_shader_subgroup 1
+GLAD_API_CALL int GLAD_GL_KHR_shader_subgroup;
+#define GL_KHR_texture_compression_astc_hdr 1
+GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_hdr;
+#define GL_KHR_texture_compression_astc_ldr 1
+GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_ldr;
+#define GL_KHR_texture_compression_astc_sliced_3d 1
+GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_sliced_3d;
+#define GL_OES_EGL_image 1
+GLAD_API_CALL int GLAD_GL_OES_EGL_image;
+#define GL_OES_EGL_image_external 1
+GLAD_API_CALL int GLAD_GL_OES_EGL_image_external;
+#define GL_OES_EGL_image_external_essl3 1
+GLAD_API_CALL int GLAD_GL_OES_EGL_image_external_essl3;
+#define GL_OES_compressed_ETC1_RGB8_sub_texture 1
+GLAD_API_CALL int GLAD_GL_OES_compressed_ETC1_RGB8_sub_texture;
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+GLAD_API_CALL int GLAD_GL_OES_compressed_ETC1_RGB8_texture;
+#define GL_OES_compressed_paletted_texture 1
+GLAD_API_CALL int GLAD_GL_OES_compressed_paletted_texture;
+#define GL_OES_copy_image 1
+GLAD_API_CALL int GLAD_GL_OES_copy_image;
+#define GL_OES_depth24 1
+GLAD_API_CALL int GLAD_GL_OES_depth24;
+#define GL_OES_depth32 1
+GLAD_API_CALL int GLAD_GL_OES_depth32;
+#define GL_OES_depth_texture 1
+GLAD_API_CALL int GLAD_GL_OES_depth_texture;
+#define GL_OES_draw_buffers_indexed 1
+GLAD_API_CALL int GLAD_GL_OES_draw_buffers_indexed;
+#define GL_OES_draw_elements_base_vertex 1
+GLAD_API_CALL int GLAD_GL_OES_draw_elements_base_vertex;
+#define GL_OES_element_index_uint 1
+GLAD_API_CALL int GLAD_GL_OES_element_index_uint;
+#define GL_OES_fbo_render_mipmap 1
+GLAD_API_CALL int GLAD_GL_OES_fbo_render_mipmap;
+#define GL_OES_fragment_precision_high 1
+GLAD_API_CALL int GLAD_GL_OES_fragment_precision_high;
+#define GL_OES_geometry_point_size 1
+GLAD_API_CALL int GLAD_GL_OES_geometry_point_size;
+#define GL_OES_geometry_shader 1
+GLAD_API_CALL int GLAD_GL_OES_geometry_shader;
+#define GL_OES_get_program_binary 1
+GLAD_API_CALL int GLAD_GL_OES_get_program_binary;
+#define GL_OES_gpu_shader5 1
+GLAD_API_CALL int GLAD_GL_OES_gpu_shader5;
+#define GL_OES_mapbuffer 1
+GLAD_API_CALL int GLAD_GL_OES_mapbuffer;
+#define GL_OES_packed_depth_stencil 1
+GLAD_API_CALL int GLAD_GL_OES_packed_depth_stencil;
+#define GL_OES_primitive_bounding_box 1
+GLAD_API_CALL int GLAD_GL_OES_primitive_bounding_box;
+#define GL_OES_required_internalformat 1
+GLAD_API_CALL int GLAD_GL_OES_required_internalformat;
+#define GL_OES_rgb8_rgba8 1
+GLAD_API_CALL int GLAD_GL_OES_rgb8_rgba8;
+#define GL_OES_sample_shading 1
+GLAD_API_CALL int GLAD_GL_OES_sample_shading;
+#define GL_OES_sample_variables 1
+GLAD_API_CALL int GLAD_GL_OES_sample_variables;
+#define GL_OES_shader_image_atomic 1
+GLAD_API_CALL int GLAD_GL_OES_shader_image_atomic;
+#define GL_OES_shader_io_blocks 1
+GLAD_API_CALL int GLAD_GL_OES_shader_io_blocks;
+#define GL_OES_shader_multisample_interpolation 1
+GLAD_API_CALL int GLAD_GL_OES_shader_multisample_interpolation;
+#define GL_OES_standard_derivatives 1
+GLAD_API_CALL int GLAD_GL_OES_standard_derivatives;
+#define GL_OES_stencil1 1
+GLAD_API_CALL int GLAD_GL_OES_stencil1;
+#define GL_OES_stencil4 1
+GLAD_API_CALL int GLAD_GL_OES_stencil4;
+#define GL_OES_surfaceless_context 1
+GLAD_API_CALL int GLAD_GL_OES_surfaceless_context;
+#define GL_OES_tessellation_point_size 1
+GLAD_API_CALL int GLAD_GL_OES_tessellation_point_size;
+#define GL_OES_tessellation_shader 1
+GLAD_API_CALL int GLAD_GL_OES_tessellation_shader;
+#define GL_OES_texture_3D 1
+GLAD_API_CALL int GLAD_GL_OES_texture_3D;
+#define GL_OES_texture_border_clamp 1
+GLAD_API_CALL int GLAD_GL_OES_texture_border_clamp;
+#define GL_OES_texture_buffer 1
+GLAD_API_CALL int GLAD_GL_OES_texture_buffer;
+#define GL_OES_texture_compression_astc 1
+GLAD_API_CALL int GLAD_GL_OES_texture_compression_astc;
+#define GL_OES_texture_cube_map_array 1
+GLAD_API_CALL int GLAD_GL_OES_texture_cube_map_array;
+#define GL_OES_texture_float 1
+GLAD_API_CALL int GLAD_GL_OES_texture_float;
+#define GL_OES_texture_float_linear 1
+GLAD_API_CALL int GLAD_GL_OES_texture_float_linear;
+#define GL_OES_texture_half_float 1
+GLAD_API_CALL int GLAD_GL_OES_texture_half_float;
+#define GL_OES_texture_half_float_linear 1
+GLAD_API_CALL int GLAD_GL_OES_texture_half_float_linear;
+#define GL_OES_texture_npot 1
+GLAD_API_CALL int GLAD_GL_OES_texture_npot;
+#define GL_OES_texture_stencil8 1
+GLAD_API_CALL int GLAD_GL_OES_texture_stencil8;
+#define GL_OES_texture_storage_multisample_2d_array 1
+GLAD_API_CALL int GLAD_GL_OES_texture_storage_multisample_2d_array;
+#define GL_OES_texture_view 1
+GLAD_API_CALL int GLAD_GL_OES_texture_view;
+#define GL_OES_vertex_array_object 1
+GLAD_API_CALL int GLAD_GL_OES_vertex_array_object;
+#define GL_OES_vertex_half_float 1
+GLAD_API_CALL int GLAD_GL_OES_vertex_half_float;
+#define GL_OES_vertex_type_10_10_10_2 1
+GLAD_API_CALL int GLAD_GL_OES_vertex_type_10_10_10_2;
+#define GL_OES_viewport_array 1
+GLAD_API_CALL int GLAD_GL_OES_viewport_array;
+
+
+typedef GLboolean (GLAD_API_PTR *PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC)(GLuint memory, GLuint64 key, GLuint timeout);
+typedef void (GLAD_API_PTR *PFNGLACTIVESHADERPROGRAMEXTPROC)(GLuint pipeline, GLuint program);
+typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture);
+typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLBEGINQUERYEXTPROC)(GLenum target, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONEXTPROC)(GLuint program, GLuint color, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDPROGRAMPIPELINEEXTPROC)(GLuint pipeline);
+typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture);
+typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYOESPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLBLENDBARRIERKHRPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEIEXTPROC)(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEIOESPROC)(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONIEXTPROC)(GLuint buf, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONIOESPROC)(GLuint buf, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEIEXTPROC)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEIOESPROC)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCIEXTPROC)(GLuint buf, GLenum src, GLenum dst);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCIOESPROC)(GLuint buf, GLenum src, GLenum dst);
+typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSTORAGEEXTPROC)(GLenum target, GLsizeiptr size, const void * data, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSTORAGEEXTERNALEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSTORAGEMEMEXTPROC)(GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHFPROC)(GLfloat d);
+typedef void (GLAD_API_PTR *PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC)(GLsizei offset, GLsizei n, const GLuint * values);
+typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s);
+typedef void (GLAD_API_PTR *PFNGLCLEARTEXIMAGEEXTPROC)(GLuint texture, GLint level, GLenum format, GLenum type, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCLEARTEXSUBIMAGEEXTPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCLIPCONTROLEXTPROC)(GLenum origin, GLenum depth);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKIEXTPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKIOESPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DOESPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOPYIMAGESUBDATAEXTPROC)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (GLAD_API_PTR *PFNGLCOPYIMAGESUBDATAOESPROC)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DOESPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCREATEMEMORYOBJECTSEXTPROC)(GLsizei n, GLuint * memoryObjects);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROGRAMVEXTPROC)(GLenum type, GLsizei count, const GLchar *const* strings);
+typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKKHRPROC)(GLDEBUGPROCKHR callback, const void * userParam);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLKHRPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTKHRPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf);
+typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEMEMORYOBJECTSEXTPROC)(GLsizei n, const GLuint * memoryObjects);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPIPELINESEXTPROC)(GLsizei n, const GLuint * pipelines);
+typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESEXTPROC)(GLsizei n, const GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETESEMAPHORESEXTPROC)(GLsizei n, const GLuint * semaphores);
+typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSOESPROC)(GLsizei n, const GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum func);
+typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean flag);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEARRAYFVOESPROC)(GLuint first, GLsizei count, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEINDEXEDFOESPROC)(GLuint index, GLfloat n, GLfloat f);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEFPROC)(GLfloat n, GLfloat f);
+typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEIEXTPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEIOESPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISCARDFRAMEBUFFEREXTPROC)(GLenum target, GLsizei numAttachments, const GLenum * attachments);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDEXTPROC)(GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSEXTPROC)(GLsizei n, const GLenum * bufs);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSINDEXEDEXTPROC)(GLint n, const GLenum * location, const GLint * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXOESPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKEXTPROC)(GLenum mode, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC)(GLenum mode, GLuint id, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)(GLenum target, GLeglImageOES image);
+typedef void (GLAD_API_PTR *PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC)(GLenum target, GLeglImageOES image, const GLint * attrib_list);
+typedef void (GLAD_API_PTR *PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum target, GLeglImageOES image);
+typedef void (GLAD_API_PTR *PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC)(GLuint texture, GLeglImageOES image, const GLint * attrib_list);
+typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENABLEIEXTPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENABLEIOESPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENDQUERYEXTPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC)(GLuint target, GLsizei size);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERSHADINGRATEEXTPROC)(GLenum target, GLenum attachment, GLuint texture, GLint baseLayer, GLsizei numLayers, GLsizei texelWidth, GLsizei texelHeight);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DOESPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREEXTPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREOESPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLGENPROGRAMPIPELINESEXTPROC)(GLsizei n, GLuint * pipelines);
+typedef void (GLAD_API_PTR *PFNGLGENQUERIESEXTPROC)(GLsizei n, GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLGENSEMAPHORESEXTPROC)(GLsizei n, GLuint * semaphores);
+typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSOESPROC)(GLsizei n, GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders);
+typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean * data);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVOESPROC)(GLenum target, GLenum pname, void ** params);
+typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog);
+typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLGETFLOATI_VOESPROC)(GLenum target, GLuint index, GLfloat * data);
+typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum pname, GLfloat * data);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATAINDEXEXTPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETFRAGMENTSHADINGRATESEXTPROC)(GLsizei samples, GLsizei maxCount, GLsizei * count, GLenum * shadingRates);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params);
+typedef GLsizei (GLAD_API_PTR *PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC)(GLuint target);
+typedef GLenum (GLAD_API_PTR *PFNGLGETGRAPHICSRESETSTATUSEXTPROC)(void);
+typedef GLenum (GLAD_API_PTR *PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VEXTPROC)(GLenum pname, GLint64 * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VEXTPROC)(GLenum target, GLuint index, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC)(GLuint memoryObject, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTLABELEXTPROC)(GLenum type, GLuint object, GLsizei bufSize, GLsizei * length, GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTLABELKHRPROC)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTPTRLABELKHRPROC)(const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLGETPOINTERVKHRPROC)(GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMBINARYOESPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC)(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPIPELINEIVEXTPROC)(GLuint pipeline, GLenum pname, GLint * params);
+typedef GLint (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC)(GLuint program, GLenum programInterface, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTI64VEXTPROC)(GLuint id, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVEXTPROC)(GLuint id, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUI64VEXTPROC)(GLuint id, GLenum pname, GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVEXTPROC)(GLuint id, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYIVEXTPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVEXTPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVOESPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVEXTPROC)(GLuint sampler, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVOESPROC)(GLuint sampler, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC)(GLuint semaphore, GLenum pname, GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint * params);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum name);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVEXTPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVOESPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVEXTPROC)(GLenum target, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVOESPROC)(GLenum target, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNSIGNEDBYTEI_VEXTPROC)(GLenum target, GLuint index, GLubyte * data);
+typedef void (GLAD_API_PTR *PFNGLGETUNSIGNEDBYTEVEXTPROC)(GLenum pname, GLubyte * data);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMFVEXTPROC)(GLuint program, GLint location, GLsizei bufSize, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMFVKHRPROC)(GLuint program, GLint location, GLsizei bufSize, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMIVEXTPROC)(GLuint program, GLint location, GLsizei bufSize, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMIVKHRPROC)(GLuint program, GLint location, GLsizei bufSize, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMUIVKHRPROC)(GLuint program, GLint location, GLsizei bufSize, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLIMPORTMEMORYFDEXTPROC)(GLuint memory, GLuint64 size, GLenum handleType, GLint fd);
+typedef void (GLAD_API_PTR *PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC)(GLuint memory, GLuint64 size, GLenum handleType, void * handle);
+typedef void (GLAD_API_PTR *PFNGLIMPORTMEMORYWIN32NAMEEXTPROC)(GLuint memory, GLuint64 size, GLenum handleType, const void * name);
+typedef void (GLAD_API_PTR *PFNGLIMPORTSEMAPHOREFDEXTPROC)(GLuint semaphore, GLenum handleType, GLint fd);
+typedef void (GLAD_API_PTR *PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC)(GLuint semaphore, GLenum handleType, void * handle);
+typedef void (GLAD_API_PTR *PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC)(GLuint semaphore, GLenum handleType, const void * name);
+typedef void (GLAD_API_PTR *PFNGLINSERTEVENTMARKEREXTPROC)(GLsizei length, const GLchar * marker);
+typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIEXTPROC)(GLenum target, GLuint index);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIOESPROC)(GLenum target, GLuint index);
+typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISMEMORYOBJECTEXTPROC)(GLuint memoryObject);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPIPELINEEXTPROC)(GLuint pipeline);
+typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYEXTPROC)(GLuint id);
+typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSEMAPHOREEXTPROC)(GLuint semaphore);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint shader);
+typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint texture);
+typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYOESPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLLABELOBJECTEXTPROC)(GLenum type, GLuint object, GLsizei length, const GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width);
+typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFEROESPROC)(GLenum target, GLenum access);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GLAD_API_PTR *PFNGLMAXSHADERCOMPILERTHREADSKHRPROC)(GLuint count);
+typedef void (GLAD_API_PTR *PFNGLMEMORYOBJECTPARAMETERIVEXTPROC)(GLuint memoryObject, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLMINSAMPLESHADINGOESPROC)(GLfloat value);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSEXTPROC)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC)(GLenum mode, const void * indirect, GLsizei drawcount, GLsizei stride);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSEXTPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC)(GLenum mode, GLenum type, const void * indirect, GLsizei drawcount, GLsizei stride);
+typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC)(GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC)(GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLOBJECTLABELKHRPROC)(GLenum identifier, GLuint name, GLsizei length, const GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLOBJECTPTRLABELKHRPROC)(const void * ptr, GLsizei length, const GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLPATCHPARAMETERIEXTPROC)(GLenum pname, GLint value);
+typedef void (GLAD_API_PTR *PFNGLPATCHPARAMETERIOESPROC)(GLenum pname, GLint value);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETCLAMPEXTPROC)(GLfloat factor, GLfloat units, GLfloat clamp);
+typedef void (GLAD_API_PTR *PFNGLPOPDEBUGGROUPKHRPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPGROUPMARKEREXTPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPRIMITIVEBOUNDINGBOXEXTPROC)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+typedef void (GLAD_API_PTR *PFNGLPRIMITIVEBOUNDINGBOXOESPROC)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMBINARYOESPROC)(GLuint program, GLenum binaryFormat, const void * binary, GLint length);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETERIEXTPROC)(GLuint program, GLenum pname, GLint value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FEXTPROC)(GLuint program, GLint location, GLfloat v0);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IEXTPROC)(GLuint program, GLint location, GLint v0);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIEXTPROC)(GLuint program, GLint location, GLuint v0);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPUSHDEBUGGROUPKHRPROC)(GLenum source, GLuint id, GLsizei length, const GLchar * message);
+typedef void (GLAD_API_PTR *PFNGLPUSHGROUPMARKEREXTPROC)(GLsizei length, const GLchar * marker);
+typedef void (GLAD_API_PTR *PFNGLQUERYCOUNTEREXTPROC)(GLuint id, GLenum target);
+typedef void (GLAD_API_PTR *PFNGLRASTERSAMPLESEXTPROC)(GLuint samples, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLREADBUFFERINDEXEDEXTPROC)(GLenum src, GLint index);
+typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLREADNPIXELSEXTPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data);
+typedef void (GLAD_API_PTR *PFNGLREADNPIXELSKHRPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data);
+typedef GLboolean (GLAD_API_PTR *PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC)(GLuint memory, GLuint64 key);
+typedef void (GLAD_API_PTR *PFNGLRELEASESHADERCOMPILERPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVEXTPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVOESPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVEXTPROC)(GLuint sampler, GLenum pname, const GLuint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVOESPROC)(GLuint sampler, GLenum pname, const GLuint * param);
+typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSCISSORARRAYVOESPROC)(GLuint first, GLsizei count, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLSCISSORINDEXEDOESPROC)(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSCISSORINDEXEDVOESPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLSEMAPHOREPARAMETERUI64VEXTPROC)(GLuint semaphore, GLenum pname, const GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLSHADERBINARYPROC)(GLsizei count, const GLuint * shaders, GLenum binaryFormat, const void * binary, GLsizei length);
+typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length);
+typedef void (GLAD_API_PTR *PFNGLSHADINGRATECOMBINEROPSEXTPROC)(GLenum combinerOp0, GLenum combinerOp1);
+typedef void (GLAD_API_PTR *PFNGLSHADINGRATEEXTPROC)(GLenum rate);
+typedef void (GLAD_API_PTR *PFNGLSIGNALSEMAPHOREEXTPROC)(GLuint semaphore, GLuint numBufferBarriers, const GLuint * buffers, GLuint numTextureBarriers, const GLuint * textures, const GLenum * dstLayouts);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFEREXTPROC)(GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFEROESPROC)(GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFERRANGEEXTPROC)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFERRANGEOESPROC)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DOESPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXPAGECOMMITMENTEXTPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVEXTPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVOESPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVEXTPROC)(GLenum target, GLenum pname, const GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVOESPROC)(GLenum target, GLenum pname, const GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE1DEXTPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE2DEXTPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE3DEXTPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEATTRIBS2DEXTPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, const GLint * attrib_list);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEATTRIBS3DEXTPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, const GLint * attrib_list);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEMEM2DEXTPROC)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEMEM3DEXTPROC)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DOESPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE1DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE2DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE3DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGEMEM2DEXTPROC)(GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC)(GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGEMEM3DEXTPROC)(GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC)(GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREVIEWEXTPROC)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREVIEWOESPROC)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFEROESPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMSTAGESEXTPROC)(GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPIPELINEEXTPROC)(GLuint pipeline);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISOREXTPROC)(GLuint index, GLuint divisor);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTARRAYVOESPROC)(GLuint first, GLsizei count, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTINDEXEDFOESPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTINDEXEDFVOESPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLWAITSEMAPHOREEXTPROC)(GLuint semaphore, GLuint numBufferBarriers, const GLuint * buffers, GLuint numTextureBarriers, const GLuint * textures, const GLenum * srcLayouts);
+typedef void (GLAD_API_PTR *PFNGLWINDOWRECTANGLESEXTPROC)(GLenum mode, GLsizei count, const GLint * box);
+
+GLAD_API_CALL PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC glad_glAcquireKeyedMutexWin32EXT;
+#define glAcquireKeyedMutexWin32EXT glad_glAcquireKeyedMutexWin32EXT
+GLAD_API_CALL PFNGLACTIVESHADERPROGRAMEXTPROC glad_glActiveShaderProgramEXT;
+#define glActiveShaderProgramEXT glad_glActiveShaderProgramEXT
+GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
+#define glActiveTexture glad_glActiveTexture
+GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader;
+#define glAttachShader glad_glAttachShader
+GLAD_API_CALL PFNGLBEGINQUERYEXTPROC glad_glBeginQueryEXT;
+#define glBeginQueryEXT glad_glBeginQueryEXT
+GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
+#define glBindAttribLocation glad_glBindAttribLocation
+GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer;
+#define glBindBuffer glad_glBindBuffer
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONEXTPROC glad_glBindFragDataLocationEXT;
+#define glBindFragDataLocationEXT glad_glBindFragDataLocationEXT
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC glad_glBindFragDataLocationIndexedEXT;
+#define glBindFragDataLocationIndexedEXT glad_glBindFragDataLocationIndexedEXT
+GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
+#define glBindFramebuffer glad_glBindFramebuffer
+GLAD_API_CALL PFNGLBINDPROGRAMPIPELINEEXTPROC glad_glBindProgramPipelineEXT;
+#define glBindProgramPipelineEXT glad_glBindProgramPipelineEXT
+GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
+#define glBindRenderbuffer glad_glBindRenderbuffer
+GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture;
+#define glBindTexture glad_glBindTexture
+GLAD_API_CALL PFNGLBINDVERTEXARRAYOESPROC glad_glBindVertexArrayOES;
+#define glBindVertexArrayOES glad_glBindVertexArrayOES
+GLAD_API_CALL PFNGLBLENDBARRIERKHRPROC glad_glBlendBarrierKHR;
+#define glBlendBarrierKHR glad_glBlendBarrierKHR
+GLAD_API_CALL PFNGLBLENDCOLORPROC glad_glBlendColor;
+#define glBlendColor glad_glBlendColor
+GLAD_API_CALL PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
+#define glBlendEquation glad_glBlendEquation
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
+#define glBlendEquationSeparate glad_glBlendEquationSeparate
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEIEXTPROC glad_glBlendEquationSeparateiEXT;
+#define glBlendEquationSeparateiEXT glad_glBlendEquationSeparateiEXT
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEIOESPROC glad_glBlendEquationSeparateiOES;
+#define glBlendEquationSeparateiOES glad_glBlendEquationSeparateiOES
+GLAD_API_CALL PFNGLBLENDEQUATIONIEXTPROC glad_glBlendEquationiEXT;
+#define glBlendEquationiEXT glad_glBlendEquationiEXT
+GLAD_API_CALL PFNGLBLENDEQUATIONIOESPROC glad_glBlendEquationiOES;
+#define glBlendEquationiOES glad_glBlendEquationiOES
+GLAD_API_CALL PFNGLBLENDFUNCPROC glad_glBlendFunc;
+#define glBlendFunc glad_glBlendFunc
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
+#define glBlendFuncSeparate glad_glBlendFuncSeparate
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEIEXTPROC glad_glBlendFuncSeparateiEXT;
+#define glBlendFuncSeparateiEXT glad_glBlendFuncSeparateiEXT
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEIOESPROC glad_glBlendFuncSeparateiOES;
+#define glBlendFuncSeparateiOES glad_glBlendFuncSeparateiOES
+GLAD_API_CALL PFNGLBLENDFUNCIEXTPROC glad_glBlendFunciEXT;
+#define glBlendFunciEXT glad_glBlendFunciEXT
+GLAD_API_CALL PFNGLBLENDFUNCIOESPROC glad_glBlendFunciOES;
+#define glBlendFunciOES glad_glBlendFunciOES
+GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData;
+#define glBufferData glad_glBufferData
+GLAD_API_CALL PFNGLBUFFERSTORAGEEXTPROC glad_glBufferStorageEXT;
+#define glBufferStorageEXT glad_glBufferStorageEXT
+GLAD_API_CALL PFNGLBUFFERSTORAGEEXTERNALEXTPROC glad_glBufferStorageExternalEXT;
+#define glBufferStorageExternalEXT glad_glBufferStorageExternalEXT
+GLAD_API_CALL PFNGLBUFFERSTORAGEMEMEXTPROC glad_glBufferStorageMemEXT;
+#define glBufferStorageMemEXT glad_glBufferStorageMemEXT
+GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
+#define glBufferSubData glad_glBufferSubData
+GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
+#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
+GLAD_API_CALL PFNGLCLEARPROC glad_glClear;
+#define glClear glad_glClear
+GLAD_API_CALL PFNGLCLEARCOLORPROC glad_glClearColor;
+#define glClearColor glad_glClearColor
+GLAD_API_CALL PFNGLCLEARDEPTHFPROC glad_glClearDepthf;
+#define glClearDepthf glad_glClearDepthf
+GLAD_API_CALL PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC glad_glClearPixelLocalStorageuiEXT;
+#define glClearPixelLocalStorageuiEXT glad_glClearPixelLocalStorageuiEXT
+GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil;
+#define glClearStencil glad_glClearStencil
+GLAD_API_CALL PFNGLCLEARTEXIMAGEEXTPROC glad_glClearTexImageEXT;
+#define glClearTexImageEXT glad_glClearTexImageEXT
+GLAD_API_CALL PFNGLCLEARTEXSUBIMAGEEXTPROC glad_glClearTexSubImageEXT;
+#define glClearTexSubImageEXT glad_glClearTexSubImageEXT
+GLAD_API_CALL PFNGLCLIPCONTROLEXTPROC glad_glClipControlEXT;
+#define glClipControlEXT glad_glClipControlEXT
+GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask;
+#define glColorMask glad_glColorMask
+GLAD_API_CALL PFNGLCOLORMASKIEXTPROC glad_glColorMaskiEXT;
+#define glColorMaskiEXT glad_glColorMaskiEXT
+GLAD_API_CALL PFNGLCOLORMASKIOESPROC glad_glColorMaskiOES;
+#define glColorMaskiOES glad_glColorMaskiOES
+GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader;
+#define glCompileShader glad_glCompileShader
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
+#define glCompressedTexImage2D glad_glCompressedTexImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DOESPROC glad_glCompressedTexImage3DOES;
+#define glCompressedTexImage3DOES glad_glCompressedTexImage3DOES
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
+#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC glad_glCompressedTexSubImage3DOES;
+#define glCompressedTexSubImage3DOES glad_glCompressedTexSubImage3DOES
+GLAD_API_CALL PFNGLCOPYIMAGESUBDATAEXTPROC glad_glCopyImageSubDataEXT;
+#define glCopyImageSubDataEXT glad_glCopyImageSubDataEXT
+GLAD_API_CALL PFNGLCOPYIMAGESUBDATAOESPROC glad_glCopyImageSubDataOES;
+#define glCopyImageSubDataOES glad_glCopyImageSubDataOES
+GLAD_API_CALL PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
+#define glCopyTexImage2D glad_glCopyTexImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
+#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE3DOESPROC glad_glCopyTexSubImage3DOES;
+#define glCopyTexSubImage3DOES glad_glCopyTexSubImage3DOES
+GLAD_API_CALL PFNGLCREATEMEMORYOBJECTSEXTPROC glad_glCreateMemoryObjectsEXT;
+#define glCreateMemoryObjectsEXT glad_glCreateMemoryObjectsEXT
+GLAD_API_CALL PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
+#define glCreateProgram glad_glCreateProgram
+GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader;
+#define glCreateShader glad_glCreateShader
+GLAD_API_CALL PFNGLCREATESHADERPROGRAMVEXTPROC glad_glCreateShaderProgramvEXT;
+#define glCreateShaderProgramvEXT glad_glCreateShaderProgramvEXT
+GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace;
+#define glCullFace glad_glCullFace
+GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR;
+#define glDebugMessageCallbackKHR glad_glDebugMessageCallbackKHR
+GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR;
+#define glDebugMessageControlKHR glad_glDebugMessageControlKHR
+GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR;
+#define glDebugMessageInsertKHR glad_glDebugMessageInsertKHR
+GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
+#define glDeleteBuffers glad_glDeleteBuffers
+GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
+#define glDeleteFramebuffers glad_glDeleteFramebuffers
+GLAD_API_CALL PFNGLDELETEMEMORYOBJECTSEXTPROC glad_glDeleteMemoryObjectsEXT;
+#define glDeleteMemoryObjectsEXT glad_glDeleteMemoryObjectsEXT
+GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
+#define glDeleteProgram glad_glDeleteProgram
+GLAD_API_CALL PFNGLDELETEPROGRAMPIPELINESEXTPROC glad_glDeleteProgramPipelinesEXT;
+#define glDeleteProgramPipelinesEXT glad_glDeleteProgramPipelinesEXT
+GLAD_API_CALL PFNGLDELETEQUERIESEXTPROC glad_glDeleteQueriesEXT;
+#define glDeleteQueriesEXT glad_glDeleteQueriesEXT
+GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
+#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
+GLAD_API_CALL PFNGLDELETESEMAPHORESEXTPROC glad_glDeleteSemaphoresEXT;
+#define glDeleteSemaphoresEXT glad_glDeleteSemaphoresEXT
+GLAD_API_CALL PFNGLDELETESHADERPROC glad_glDeleteShader;
+#define glDeleteShader glad_glDeleteShader
+GLAD_API_CALL PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
+#define glDeleteTextures glad_glDeleteTextures
+GLAD_API_CALL PFNGLDELETEVERTEXARRAYSOESPROC glad_glDeleteVertexArraysOES;
+#define glDeleteVertexArraysOES glad_glDeleteVertexArraysOES
+GLAD_API_CALL PFNGLDEPTHFUNCPROC glad_glDepthFunc;
+#define glDepthFunc glad_glDepthFunc
+GLAD_API_CALL PFNGLDEPTHMASKPROC glad_glDepthMask;
+#define glDepthMask glad_glDepthMask
+GLAD_API_CALL PFNGLDEPTHRANGEARRAYFVOESPROC glad_glDepthRangeArrayfvOES;
+#define glDepthRangeArrayfvOES glad_glDepthRangeArrayfvOES
+GLAD_API_CALL PFNGLDEPTHRANGEINDEXEDFOESPROC glad_glDepthRangeIndexedfOES;
+#define glDepthRangeIndexedfOES glad_glDepthRangeIndexedfOES
+GLAD_API_CALL PFNGLDEPTHRANGEFPROC glad_glDepthRangef;
+#define glDepthRangef glad_glDepthRangef
+GLAD_API_CALL PFNGLDETACHSHADERPROC glad_glDetachShader;
+#define glDetachShader glad_glDetachShader
+GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable;
+#define glDisable glad_glDisable
+GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
+#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
+GLAD_API_CALL PFNGLDISABLEIEXTPROC glad_glDisableiEXT;
+#define glDisableiEXT glad_glDisableiEXT
+GLAD_API_CALL PFNGLDISABLEIOESPROC glad_glDisableiOES;
+#define glDisableiOES glad_glDisableiOES
+GLAD_API_CALL PFNGLDISCARDFRAMEBUFFEREXTPROC glad_glDiscardFramebufferEXT;
+#define glDiscardFramebufferEXT glad_glDiscardFramebufferEXT
+GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays;
+#define glDrawArrays glad_glDrawArrays
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC glad_glDrawArraysInstancedBaseInstanceEXT;
+#define glDrawArraysInstancedBaseInstanceEXT glad_glDrawArraysInstancedBaseInstanceEXT
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDEXTPROC glad_glDrawArraysInstancedEXT;
+#define glDrawArraysInstancedEXT glad_glDrawArraysInstancedEXT
+GLAD_API_CALL PFNGLDRAWBUFFERSEXTPROC glad_glDrawBuffersEXT;
+#define glDrawBuffersEXT glad_glDrawBuffersEXT
+GLAD_API_CALL PFNGLDRAWBUFFERSINDEXEDEXTPROC glad_glDrawBuffersIndexedEXT;
+#define glDrawBuffersIndexedEXT glad_glDrawBuffersIndexedEXT
+GLAD_API_CALL PFNGLDRAWELEMENTSPROC glad_glDrawElements;
+#define glDrawElements glad_glDrawElements
+GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXEXTPROC glad_glDrawElementsBaseVertexEXT;
+#define glDrawElementsBaseVertexEXT glad_glDrawElementsBaseVertexEXT
+GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXOESPROC glad_glDrawElementsBaseVertexOES;
+#define glDrawElementsBaseVertexOES glad_glDrawElementsBaseVertexOES
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC glad_glDrawElementsInstancedBaseInstanceEXT;
+#define glDrawElementsInstancedBaseInstanceEXT glad_glDrawElementsInstancedBaseInstanceEXT
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC glad_glDrawElementsInstancedBaseVertexBaseInstanceEXT;
+#define glDrawElementsInstancedBaseVertexBaseInstanceEXT glad_glDrawElementsInstancedBaseVertexBaseInstanceEXT
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC glad_glDrawElementsInstancedBaseVertexEXT;
+#define glDrawElementsInstancedBaseVertexEXT glad_glDrawElementsInstancedBaseVertexEXT
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC glad_glDrawElementsInstancedBaseVertexOES;
+#define glDrawElementsInstancedBaseVertexOES glad_glDrawElementsInstancedBaseVertexOES
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDEXTPROC glad_glDrawElementsInstancedEXT;
+#define glDrawElementsInstancedEXT glad_glDrawElementsInstancedEXT
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC glad_glDrawRangeElementsBaseVertexEXT;
+#define glDrawRangeElementsBaseVertexEXT glad_glDrawRangeElementsBaseVertexEXT
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC glad_glDrawRangeElementsBaseVertexOES;
+#define glDrawRangeElementsBaseVertexOES glad_glDrawRangeElementsBaseVertexOES
+GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKEXTPROC glad_glDrawTransformFeedbackEXT;
+#define glDrawTransformFeedbackEXT glad_glDrawTransformFeedbackEXT
+GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC glad_glDrawTransformFeedbackInstancedEXT;
+#define glDrawTransformFeedbackInstancedEXT glad_glDrawTransformFeedbackInstancedEXT
+GLAD_API_CALL PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glad_glEGLImageTargetRenderbufferStorageOES;
+#define glEGLImageTargetRenderbufferStorageOES glad_glEGLImageTargetRenderbufferStorageOES
+GLAD_API_CALL PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC glad_glEGLImageTargetTexStorageEXT;
+#define glEGLImageTargetTexStorageEXT glad_glEGLImageTargetTexStorageEXT
+GLAD_API_CALL PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glad_glEGLImageTargetTexture2DOES;
+#define glEGLImageTargetTexture2DOES glad_glEGLImageTargetTexture2DOES
+GLAD_API_CALL PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC glad_glEGLImageTargetTextureStorageEXT;
+#define glEGLImageTargetTextureStorageEXT glad_glEGLImageTargetTextureStorageEXT
+GLAD_API_CALL PFNGLENABLEPROC glad_glEnable;
+#define glEnable glad_glEnable
+GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
+#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
+GLAD_API_CALL PFNGLENABLEIEXTPROC glad_glEnableiEXT;
+#define glEnableiEXT glad_glEnableiEXT
+GLAD_API_CALL PFNGLENABLEIOESPROC glad_glEnableiOES;
+#define glEnableiOES glad_glEnableiOES
+GLAD_API_CALL PFNGLENDQUERYEXTPROC glad_glEndQueryEXT;
+#define glEndQueryEXT glad_glEndQueryEXT
+GLAD_API_CALL PFNGLFINISHPROC glad_glFinish;
+#define glFinish glad_glFinish
+GLAD_API_CALL PFNGLFLUSHPROC glad_glFlush;
+#define glFlush glad_glFlush
+GLAD_API_CALL PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC glad_glFlushMappedBufferRangeEXT;
+#define glFlushMappedBufferRangeEXT glad_glFlushMappedBufferRangeEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC glad_glFramebufferFetchBarrierEXT;
+#define glFramebufferFetchBarrierEXT glad_glFramebufferFetchBarrierEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC glad_glFramebufferPixelLocalStorageSizeEXT;
+#define glFramebufferPixelLocalStorageSizeEXT glad_glFramebufferPixelLocalStorageSizeEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
+#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
+GLAD_API_CALL PFNGLFRAMEBUFFERSHADINGRATEEXTPROC glad_glFramebufferShadingRateEXT;
+#define glFramebufferShadingRateEXT glad_glFramebufferShadingRateEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
+#define glFramebufferTexture2D glad_glFramebufferTexture2D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glad_glFramebufferTexture2DMultisampleEXT;
+#define glFramebufferTexture2DMultisampleEXT glad_glFramebufferTexture2DMultisampleEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DOESPROC glad_glFramebufferTexture3DOES;
+#define glFramebufferTexture3DOES glad_glFramebufferTexture3DOES
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREEXTPROC glad_glFramebufferTextureEXT;
+#define glFramebufferTextureEXT glad_glFramebufferTextureEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREOESPROC glad_glFramebufferTextureOES;
+#define glFramebufferTextureOES glad_glFramebufferTextureOES
+GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace;
+#define glFrontFace glad_glFrontFace
+GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers;
+#define glGenBuffers glad_glGenBuffers
+GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
+#define glGenFramebuffers glad_glGenFramebuffers
+GLAD_API_CALL PFNGLGENPROGRAMPIPELINESEXTPROC glad_glGenProgramPipelinesEXT;
+#define glGenProgramPipelinesEXT glad_glGenProgramPipelinesEXT
+GLAD_API_CALL PFNGLGENQUERIESEXTPROC glad_glGenQueriesEXT;
+#define glGenQueriesEXT glad_glGenQueriesEXT
+GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
+#define glGenRenderbuffers glad_glGenRenderbuffers
+GLAD_API_CALL PFNGLGENSEMAPHORESEXTPROC glad_glGenSemaphoresEXT;
+#define glGenSemaphoresEXT glad_glGenSemaphoresEXT
+GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures;
+#define glGenTextures glad_glGenTextures
+GLAD_API_CALL PFNGLGENVERTEXARRAYSOESPROC glad_glGenVertexArraysOES;
+#define glGenVertexArraysOES glad_glGenVertexArraysOES
+GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
+#define glGenerateMipmap glad_glGenerateMipmap
+GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
+#define glGetActiveAttrib glad_glGetActiveAttrib
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
+#define glGetActiveUniform glad_glGetActiveUniform
+GLAD_API_CALL PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
+#define glGetAttachedShaders glad_glGetAttachedShaders
+GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
+#define glGetAttribLocation glad_glGetAttribLocation
+GLAD_API_CALL PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
+#define glGetBooleanv glad_glGetBooleanv
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
+#define glGetBufferParameteriv glad_glGetBufferParameteriv
+GLAD_API_CALL PFNGLGETBUFFERPOINTERVOESPROC glad_glGetBufferPointervOES;
+#define glGetBufferPointervOES glad_glGetBufferPointervOES
+GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR;
+#define glGetDebugMessageLogKHR glad_glGetDebugMessageLogKHR
+GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError;
+#define glGetError glad_glGetError
+GLAD_API_CALL PFNGLGETFLOATI_VOESPROC glad_glGetFloati_vOES;
+#define glGetFloati_vOES glad_glGetFloati_vOES
+GLAD_API_CALL PFNGLGETFLOATVPROC glad_glGetFloatv;
+#define glGetFloatv glad_glGetFloatv
+GLAD_API_CALL PFNGLGETFRAGDATAINDEXEXTPROC glad_glGetFragDataIndexEXT;
+#define glGetFragDataIndexEXT glad_glGetFragDataIndexEXT
+GLAD_API_CALL PFNGLGETFRAGMENTSHADINGRATESEXTPROC glad_glGetFragmentShadingRatesEXT;
+#define glGetFragmentShadingRatesEXT glad_glGetFragmentShadingRatesEXT
+GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
+#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
+GLAD_API_CALL PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC glad_glGetFramebufferPixelLocalStorageSizeEXT;
+#define glGetFramebufferPixelLocalStorageSizeEXT glad_glGetFramebufferPixelLocalStorageSizeEXT
+GLAD_API_CALL PFNGLGETGRAPHICSRESETSTATUSEXTPROC glad_glGetGraphicsResetStatusEXT;
+#define glGetGraphicsResetStatusEXT glad_glGetGraphicsResetStatusEXT
+GLAD_API_CALL PFNGLGETGRAPHICSRESETSTATUSKHRPROC glad_glGetGraphicsResetStatusKHR;
+#define glGetGraphicsResetStatusKHR glad_glGetGraphicsResetStatusKHR
+GLAD_API_CALL PFNGLGETINTEGER64VEXTPROC glad_glGetInteger64vEXT;
+#define glGetInteger64vEXT glad_glGetInteger64vEXT
+GLAD_API_CALL PFNGLGETINTEGERI_VEXTPROC glad_glGetIntegeri_vEXT;
+#define glGetIntegeri_vEXT glad_glGetIntegeri_vEXT
+GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv;
+#define glGetIntegerv glad_glGetIntegerv
+GLAD_API_CALL PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC glad_glGetMemoryObjectParameterivEXT;
+#define glGetMemoryObjectParameterivEXT glad_glGetMemoryObjectParameterivEXT
+GLAD_API_CALL PFNGLGETOBJECTLABELEXTPROC glad_glGetObjectLabelEXT;
+#define glGetObjectLabelEXT glad_glGetObjectLabelEXT
+GLAD_API_CALL PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR;
+#define glGetObjectLabelKHR glad_glGetObjectLabelKHR
+GLAD_API_CALL PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR;
+#define glGetObjectPtrLabelKHR glad_glGetObjectPtrLabelKHR
+GLAD_API_CALL PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR;
+#define glGetPointervKHR glad_glGetPointervKHR
+GLAD_API_CALL PFNGLGETPROGRAMBINARYOESPROC glad_glGetProgramBinaryOES;
+#define glGetProgramBinaryOES glad_glGetProgramBinaryOES
+GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
+#define glGetProgramInfoLog glad_glGetProgramInfoLog
+GLAD_API_CALL PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC glad_glGetProgramPipelineInfoLogEXT;
+#define glGetProgramPipelineInfoLogEXT glad_glGetProgramPipelineInfoLogEXT
+GLAD_API_CALL PFNGLGETPROGRAMPIPELINEIVEXTPROC glad_glGetProgramPipelineivEXT;
+#define glGetProgramPipelineivEXT glad_glGetProgramPipelineivEXT
+GLAD_API_CALL PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC glad_glGetProgramResourceLocationIndexEXT;
+#define glGetProgramResourceLocationIndexEXT glad_glGetProgramResourceLocationIndexEXT
+GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
+#define glGetProgramiv glad_glGetProgramiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTI64VEXTPROC glad_glGetQueryObjecti64vEXT;
+#define glGetQueryObjecti64vEXT glad_glGetQueryObjecti64vEXT
+GLAD_API_CALL PFNGLGETQUERYOBJECTIVEXTPROC glad_glGetQueryObjectivEXT;
+#define glGetQueryObjectivEXT glad_glGetQueryObjectivEXT
+GLAD_API_CALL PFNGLGETQUERYOBJECTUI64VEXTPROC glad_glGetQueryObjectui64vEXT;
+#define glGetQueryObjectui64vEXT glad_glGetQueryObjectui64vEXT
+GLAD_API_CALL PFNGLGETQUERYOBJECTUIVEXTPROC glad_glGetQueryObjectuivEXT;
+#define glGetQueryObjectuivEXT glad_glGetQueryObjectuivEXT
+GLAD_API_CALL PFNGLGETQUERYIVEXTPROC glad_glGetQueryivEXT;
+#define glGetQueryivEXT glad_glGetQueryivEXT
+GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
+#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVEXTPROC glad_glGetSamplerParameterIivEXT;
+#define glGetSamplerParameterIivEXT glad_glGetSamplerParameterIivEXT
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVOESPROC glad_glGetSamplerParameterIivOES;
+#define glGetSamplerParameterIivOES glad_glGetSamplerParameterIivOES
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVEXTPROC glad_glGetSamplerParameterIuivEXT;
+#define glGetSamplerParameterIuivEXT glad_glGetSamplerParameterIuivEXT
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVOESPROC glad_glGetSamplerParameterIuivOES;
+#define glGetSamplerParameterIuivOES glad_glGetSamplerParameterIuivOES
+GLAD_API_CALL PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC glad_glGetSemaphoreParameterui64vEXT;
+#define glGetSemaphoreParameterui64vEXT glad_glGetSemaphoreParameterui64vEXT
+GLAD_API_CALL PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
+#define glGetShaderInfoLog glad_glGetShaderInfoLog
+GLAD_API_CALL PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat;
+#define glGetShaderPrecisionFormat glad_glGetShaderPrecisionFormat
+GLAD_API_CALL PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
+#define glGetShaderSource glad_glGetShaderSource
+GLAD_API_CALL PFNGLGETSHADERIVPROC glad_glGetShaderiv;
+#define glGetShaderiv glad_glGetShaderiv
+GLAD_API_CALL PFNGLGETSTRINGPROC glad_glGetString;
+#define glGetString glad_glGetString
+GLAD_API_CALL PFNGLGETTEXPARAMETERIIVEXTPROC glad_glGetTexParameterIivEXT;
+#define glGetTexParameterIivEXT glad_glGetTexParameterIivEXT
+GLAD_API_CALL PFNGLGETTEXPARAMETERIIVOESPROC glad_glGetTexParameterIivOES;
+#define glGetTexParameterIivOES glad_glGetTexParameterIivOES
+GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVEXTPROC glad_glGetTexParameterIuivEXT;
+#define glGetTexParameterIuivEXT glad_glGetTexParameterIuivEXT
+GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVOESPROC glad_glGetTexParameterIuivOES;
+#define glGetTexParameterIuivOES glad_glGetTexParameterIuivOES
+GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
+#define glGetTexParameterfv glad_glGetTexParameterfv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
+#define glGetTexParameteriv glad_glGetTexParameteriv
+GLAD_API_CALL PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
+#define glGetUniformLocation glad_glGetUniformLocation
+GLAD_API_CALL PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
+#define glGetUniformfv glad_glGetUniformfv
+GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
+#define glGetUniformiv glad_glGetUniformiv
+GLAD_API_CALL PFNGLGETUNSIGNEDBYTEI_VEXTPROC glad_glGetUnsignedBytei_vEXT;
+#define glGetUnsignedBytei_vEXT glad_glGetUnsignedBytei_vEXT
+GLAD_API_CALL PFNGLGETUNSIGNEDBYTEVEXTPROC glad_glGetUnsignedBytevEXT;
+#define glGetUnsignedBytevEXT glad_glGetUnsignedBytevEXT
+GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
+#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
+#define glGetVertexAttribfv glad_glGetVertexAttribfv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
+#define glGetVertexAttribiv glad_glGetVertexAttribiv
+GLAD_API_CALL PFNGLGETNUNIFORMFVEXTPROC glad_glGetnUniformfvEXT;
+#define glGetnUniformfvEXT glad_glGetnUniformfvEXT
+GLAD_API_CALL PFNGLGETNUNIFORMFVKHRPROC glad_glGetnUniformfvKHR;
+#define glGetnUniformfvKHR glad_glGetnUniformfvKHR
+GLAD_API_CALL PFNGLGETNUNIFORMIVEXTPROC glad_glGetnUniformivEXT;
+#define glGetnUniformivEXT glad_glGetnUniformivEXT
+GLAD_API_CALL PFNGLGETNUNIFORMIVKHRPROC glad_glGetnUniformivKHR;
+#define glGetnUniformivKHR glad_glGetnUniformivKHR
+GLAD_API_CALL PFNGLGETNUNIFORMUIVKHRPROC glad_glGetnUniformuivKHR;
+#define glGetnUniformuivKHR glad_glGetnUniformuivKHR
+GLAD_API_CALL PFNGLHINTPROC glad_glHint;
+#define glHint glad_glHint
+GLAD_API_CALL PFNGLIMPORTMEMORYFDEXTPROC glad_glImportMemoryFdEXT;
+#define glImportMemoryFdEXT glad_glImportMemoryFdEXT
+GLAD_API_CALL PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC glad_glImportMemoryWin32HandleEXT;
+#define glImportMemoryWin32HandleEXT glad_glImportMemoryWin32HandleEXT
+GLAD_API_CALL PFNGLIMPORTMEMORYWIN32NAMEEXTPROC glad_glImportMemoryWin32NameEXT;
+#define glImportMemoryWin32NameEXT glad_glImportMemoryWin32NameEXT
+GLAD_API_CALL PFNGLIMPORTSEMAPHOREFDEXTPROC glad_glImportSemaphoreFdEXT;
+#define glImportSemaphoreFdEXT glad_glImportSemaphoreFdEXT
+GLAD_API_CALL PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC glad_glImportSemaphoreWin32HandleEXT;
+#define glImportSemaphoreWin32HandleEXT glad_glImportSemaphoreWin32HandleEXT
+GLAD_API_CALL PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC glad_glImportSemaphoreWin32NameEXT;
+#define glImportSemaphoreWin32NameEXT glad_glImportSemaphoreWin32NameEXT
+GLAD_API_CALL PFNGLINSERTEVENTMARKEREXTPROC glad_glInsertEventMarkerEXT;
+#define glInsertEventMarkerEXT glad_glInsertEventMarkerEXT
+GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer;
+#define glIsBuffer glad_glIsBuffer
+GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled;
+#define glIsEnabled glad_glIsEnabled
+GLAD_API_CALL PFNGLISENABLEDIEXTPROC glad_glIsEnablediEXT;
+#define glIsEnablediEXT glad_glIsEnablediEXT
+GLAD_API_CALL PFNGLISENABLEDIOESPROC glad_glIsEnablediOES;
+#define glIsEnablediOES glad_glIsEnablediOES
+GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
+#define glIsFramebuffer glad_glIsFramebuffer
+GLAD_API_CALL PFNGLISMEMORYOBJECTEXTPROC glad_glIsMemoryObjectEXT;
+#define glIsMemoryObjectEXT glad_glIsMemoryObjectEXT
+GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram;
+#define glIsProgram glad_glIsProgram
+GLAD_API_CALL PFNGLISPROGRAMPIPELINEEXTPROC glad_glIsProgramPipelineEXT;
+#define glIsProgramPipelineEXT glad_glIsProgramPipelineEXT
+GLAD_API_CALL PFNGLISQUERYEXTPROC glad_glIsQueryEXT;
+#define glIsQueryEXT glad_glIsQueryEXT
+GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
+#define glIsRenderbuffer glad_glIsRenderbuffer
+GLAD_API_CALL PFNGLISSEMAPHOREEXTPROC glad_glIsSemaphoreEXT;
+#define glIsSemaphoreEXT glad_glIsSemaphoreEXT
+GLAD_API_CALL PFNGLISSHADERPROC glad_glIsShader;
+#define glIsShader glad_glIsShader
+GLAD_API_CALL PFNGLISTEXTUREPROC glad_glIsTexture;
+#define glIsTexture glad_glIsTexture
+GLAD_API_CALL PFNGLISVERTEXARRAYOESPROC glad_glIsVertexArrayOES;
+#define glIsVertexArrayOES glad_glIsVertexArrayOES
+GLAD_API_CALL PFNGLLABELOBJECTEXTPROC glad_glLabelObjectEXT;
+#define glLabelObjectEXT glad_glLabelObjectEXT
+GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth;
+#define glLineWidth glad_glLineWidth
+GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram;
+#define glLinkProgram glad_glLinkProgram
+GLAD_API_CALL PFNGLMAPBUFFEROESPROC glad_glMapBufferOES;
+#define glMapBufferOES glad_glMapBufferOES
+GLAD_API_CALL PFNGLMAPBUFFERRANGEEXTPROC glad_glMapBufferRangeEXT;
+#define glMapBufferRangeEXT glad_glMapBufferRangeEXT
+GLAD_API_CALL PFNGLMAXSHADERCOMPILERTHREADSKHRPROC glad_glMaxShaderCompilerThreadsKHR;
+#define glMaxShaderCompilerThreadsKHR glad_glMaxShaderCompilerThreadsKHR
+GLAD_API_CALL PFNGLMEMORYOBJECTPARAMETERIVEXTPROC glad_glMemoryObjectParameterivEXT;
+#define glMemoryObjectParameterivEXT glad_glMemoryObjectParameterivEXT
+GLAD_API_CALL PFNGLMINSAMPLESHADINGOESPROC glad_glMinSampleShadingOES;
+#define glMinSampleShadingOES glad_glMinSampleShadingOES
+GLAD_API_CALL PFNGLMULTIDRAWARRAYSEXTPROC glad_glMultiDrawArraysEXT;
+#define glMultiDrawArraysEXT glad_glMultiDrawArraysEXT
+GLAD_API_CALL PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC glad_glMultiDrawArraysIndirectEXT;
+#define glMultiDrawArraysIndirectEXT glad_glMultiDrawArraysIndirectEXT
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC glad_glMultiDrawElementsBaseVertexEXT;
+#define glMultiDrawElementsBaseVertexEXT glad_glMultiDrawElementsBaseVertexEXT
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSEXTPROC glad_glMultiDrawElementsEXT;
+#define glMultiDrawElementsEXT glad_glMultiDrawElementsEXT
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC glad_glMultiDrawElementsIndirectEXT;
+#define glMultiDrawElementsIndirectEXT glad_glMultiDrawElementsIndirectEXT
+GLAD_API_CALL PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC glad_glNamedBufferStorageExternalEXT;
+#define glNamedBufferStorageExternalEXT glad_glNamedBufferStorageExternalEXT
+GLAD_API_CALL PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC glad_glNamedBufferStorageMemEXT;
+#define glNamedBufferStorageMemEXT glad_glNamedBufferStorageMemEXT
+GLAD_API_CALL PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR;
+#define glObjectLabelKHR glad_glObjectLabelKHR
+GLAD_API_CALL PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR;
+#define glObjectPtrLabelKHR glad_glObjectPtrLabelKHR
+GLAD_API_CALL PFNGLPATCHPARAMETERIEXTPROC glad_glPatchParameteriEXT;
+#define glPatchParameteriEXT glad_glPatchParameteriEXT
+GLAD_API_CALL PFNGLPATCHPARAMETERIOESPROC glad_glPatchParameteriOES;
+#define glPatchParameteriOES glad_glPatchParameteriOES
+GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei;
+#define glPixelStorei glad_glPixelStorei
+GLAD_API_CALL PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
+#define glPolygonOffset glad_glPolygonOffset
+GLAD_API_CALL PFNGLPOLYGONOFFSETCLAMPEXTPROC glad_glPolygonOffsetClampEXT;
+#define glPolygonOffsetClampEXT glad_glPolygonOffsetClampEXT
+GLAD_API_CALL PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR;
+#define glPopDebugGroupKHR glad_glPopDebugGroupKHR
+GLAD_API_CALL PFNGLPOPGROUPMARKEREXTPROC glad_glPopGroupMarkerEXT;
+#define glPopGroupMarkerEXT glad_glPopGroupMarkerEXT
+GLAD_API_CALL PFNGLPRIMITIVEBOUNDINGBOXEXTPROC glad_glPrimitiveBoundingBoxEXT;
+#define glPrimitiveBoundingBoxEXT glad_glPrimitiveBoundingBoxEXT
+GLAD_API_CALL PFNGLPRIMITIVEBOUNDINGBOXOESPROC glad_glPrimitiveBoundingBoxOES;
+#define glPrimitiveBoundingBoxOES glad_glPrimitiveBoundingBoxOES
+GLAD_API_CALL PFNGLPROGRAMBINARYOESPROC glad_glProgramBinaryOES;
+#define glProgramBinaryOES glad_glProgramBinaryOES
+GLAD_API_CALL PFNGLPROGRAMPARAMETERIEXTPROC glad_glProgramParameteriEXT;
+#define glProgramParameteriEXT glad_glProgramParameteriEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1FEXTPROC glad_glProgramUniform1fEXT;
+#define glProgramUniform1fEXT glad_glProgramUniform1fEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1FVEXTPROC glad_glProgramUniform1fvEXT;
+#define glProgramUniform1fvEXT glad_glProgramUniform1fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1IEXTPROC glad_glProgramUniform1iEXT;
+#define glProgramUniform1iEXT glad_glProgramUniform1iEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1IVEXTPROC glad_glProgramUniform1ivEXT;
+#define glProgramUniform1ivEXT glad_glProgramUniform1ivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIEXTPROC glad_glProgramUniform1uiEXT;
+#define glProgramUniform1uiEXT glad_glProgramUniform1uiEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIVEXTPROC glad_glProgramUniform1uivEXT;
+#define glProgramUniform1uivEXT glad_glProgramUniform1uivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2FEXTPROC glad_glProgramUniform2fEXT;
+#define glProgramUniform2fEXT glad_glProgramUniform2fEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2FVEXTPROC glad_glProgramUniform2fvEXT;
+#define glProgramUniform2fvEXT glad_glProgramUniform2fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2IEXTPROC glad_glProgramUniform2iEXT;
+#define glProgramUniform2iEXT glad_glProgramUniform2iEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2IVEXTPROC glad_glProgramUniform2ivEXT;
+#define glProgramUniform2ivEXT glad_glProgramUniform2ivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIEXTPROC glad_glProgramUniform2uiEXT;
+#define glProgramUniform2uiEXT glad_glProgramUniform2uiEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIVEXTPROC glad_glProgramUniform2uivEXT;
+#define glProgramUniform2uivEXT glad_glProgramUniform2uivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3FEXTPROC glad_glProgramUniform3fEXT;
+#define glProgramUniform3fEXT glad_glProgramUniform3fEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3FVEXTPROC glad_glProgramUniform3fvEXT;
+#define glProgramUniform3fvEXT glad_glProgramUniform3fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3IEXTPROC glad_glProgramUniform3iEXT;
+#define glProgramUniform3iEXT glad_glProgramUniform3iEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3IVEXTPROC glad_glProgramUniform3ivEXT;
+#define glProgramUniform3ivEXT glad_glProgramUniform3ivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIEXTPROC glad_glProgramUniform3uiEXT;
+#define glProgramUniform3uiEXT glad_glProgramUniform3uiEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIVEXTPROC glad_glProgramUniform3uivEXT;
+#define glProgramUniform3uivEXT glad_glProgramUniform3uivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4FEXTPROC glad_glProgramUniform4fEXT;
+#define glProgramUniform4fEXT glad_glProgramUniform4fEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4FVEXTPROC glad_glProgramUniform4fvEXT;
+#define glProgramUniform4fvEXT glad_glProgramUniform4fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4IEXTPROC glad_glProgramUniform4iEXT;
+#define glProgramUniform4iEXT glad_glProgramUniform4iEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4IVEXTPROC glad_glProgramUniform4ivEXT;
+#define glProgramUniform4ivEXT glad_glProgramUniform4ivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIEXTPROC glad_glProgramUniform4uiEXT;
+#define glProgramUniform4uiEXT glad_glProgramUniform4uiEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIVEXTPROC glad_glProgramUniform4uivEXT;
+#define glProgramUniform4uivEXT glad_glProgramUniform4uivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC glad_glProgramUniformMatrix2fvEXT;
+#define glProgramUniformMatrix2fvEXT glad_glProgramUniformMatrix2fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC glad_glProgramUniformMatrix2x3fvEXT;
+#define glProgramUniformMatrix2x3fvEXT glad_glProgramUniformMatrix2x3fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC glad_glProgramUniformMatrix2x4fvEXT;
+#define glProgramUniformMatrix2x4fvEXT glad_glProgramUniformMatrix2x4fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC glad_glProgramUniformMatrix3fvEXT;
+#define glProgramUniformMatrix3fvEXT glad_glProgramUniformMatrix3fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC glad_glProgramUniformMatrix3x2fvEXT;
+#define glProgramUniformMatrix3x2fvEXT glad_glProgramUniformMatrix3x2fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC glad_glProgramUniformMatrix3x4fvEXT;
+#define glProgramUniformMatrix3x4fvEXT glad_glProgramUniformMatrix3x4fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC glad_glProgramUniformMatrix4fvEXT;
+#define glProgramUniformMatrix4fvEXT glad_glProgramUniformMatrix4fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC glad_glProgramUniformMatrix4x2fvEXT;
+#define glProgramUniformMatrix4x2fvEXT glad_glProgramUniformMatrix4x2fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC glad_glProgramUniformMatrix4x3fvEXT;
+#define glProgramUniformMatrix4x3fvEXT glad_glProgramUniformMatrix4x3fvEXT
+GLAD_API_CALL PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR;
+#define glPushDebugGroupKHR glad_glPushDebugGroupKHR
+GLAD_API_CALL PFNGLPUSHGROUPMARKEREXTPROC glad_glPushGroupMarkerEXT;
+#define glPushGroupMarkerEXT glad_glPushGroupMarkerEXT
+GLAD_API_CALL PFNGLQUERYCOUNTEREXTPROC glad_glQueryCounterEXT;
+#define glQueryCounterEXT glad_glQueryCounterEXT
+GLAD_API_CALL PFNGLRASTERSAMPLESEXTPROC glad_glRasterSamplesEXT;
+#define glRasterSamplesEXT glad_glRasterSamplesEXT
+GLAD_API_CALL PFNGLREADBUFFERINDEXEDEXTPROC glad_glReadBufferIndexedEXT;
+#define glReadBufferIndexedEXT glad_glReadBufferIndexedEXT
+GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels;
+#define glReadPixels glad_glReadPixels
+GLAD_API_CALL PFNGLREADNPIXELSEXTPROC glad_glReadnPixelsEXT;
+#define glReadnPixelsEXT glad_glReadnPixelsEXT
+GLAD_API_CALL PFNGLREADNPIXELSKHRPROC glad_glReadnPixelsKHR;
+#define glReadnPixelsKHR glad_glReadnPixelsKHR
+GLAD_API_CALL PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC glad_glReleaseKeyedMutexWin32EXT;
+#define glReleaseKeyedMutexWin32EXT glad_glReleaseKeyedMutexWin32EXT
+GLAD_API_CALL PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler;
+#define glReleaseShaderCompiler glad_glReleaseShaderCompiler
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
+#define glRenderbufferStorage glad_glRenderbufferStorage
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT;
+#define glRenderbufferStorageMultisampleEXT glad_glRenderbufferStorageMultisampleEXT
+GLAD_API_CALL PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
+#define glSampleCoverage glad_glSampleCoverage
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVEXTPROC glad_glSamplerParameterIivEXT;
+#define glSamplerParameterIivEXT glad_glSamplerParameterIivEXT
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVOESPROC glad_glSamplerParameterIivOES;
+#define glSamplerParameterIivOES glad_glSamplerParameterIivOES
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVEXTPROC glad_glSamplerParameterIuivEXT;
+#define glSamplerParameterIuivEXT glad_glSamplerParameterIuivEXT
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVOESPROC glad_glSamplerParameterIuivOES;
+#define glSamplerParameterIuivOES glad_glSamplerParameterIuivOES
+GLAD_API_CALL PFNGLSCISSORPROC glad_glScissor;
+#define glScissor glad_glScissor
+GLAD_API_CALL PFNGLSCISSORARRAYVOESPROC glad_glScissorArrayvOES;
+#define glScissorArrayvOES glad_glScissorArrayvOES
+GLAD_API_CALL PFNGLSCISSORINDEXEDOESPROC glad_glScissorIndexedOES;
+#define glScissorIndexedOES glad_glScissorIndexedOES
+GLAD_API_CALL PFNGLSCISSORINDEXEDVOESPROC glad_glScissorIndexedvOES;
+#define glScissorIndexedvOES glad_glScissorIndexedvOES
+GLAD_API_CALL PFNGLSEMAPHOREPARAMETERUI64VEXTPROC glad_glSemaphoreParameterui64vEXT;
+#define glSemaphoreParameterui64vEXT glad_glSemaphoreParameterui64vEXT
+GLAD_API_CALL PFNGLSHADERBINARYPROC glad_glShaderBinary;
+#define glShaderBinary glad_glShaderBinary
+GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource;
+#define glShaderSource glad_glShaderSource
+GLAD_API_CALL PFNGLSHADINGRATECOMBINEROPSEXTPROC glad_glShadingRateCombinerOpsEXT;
+#define glShadingRateCombinerOpsEXT glad_glShadingRateCombinerOpsEXT
+GLAD_API_CALL PFNGLSHADINGRATEEXTPROC glad_glShadingRateEXT;
+#define glShadingRateEXT glad_glShadingRateEXT
+GLAD_API_CALL PFNGLSIGNALSEMAPHOREEXTPROC glad_glSignalSemaphoreEXT;
+#define glSignalSemaphoreEXT glad_glSignalSemaphoreEXT
+GLAD_API_CALL PFNGLSTENCILFUNCPROC glad_glStencilFunc;
+#define glStencilFunc glad_glStencilFunc
+GLAD_API_CALL PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
+#define glStencilFuncSeparate glad_glStencilFuncSeparate
+GLAD_API_CALL PFNGLSTENCILMASKPROC glad_glStencilMask;
+#define glStencilMask glad_glStencilMask
+GLAD_API_CALL PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
+#define glStencilMaskSeparate glad_glStencilMaskSeparate
+GLAD_API_CALL PFNGLSTENCILOPPROC glad_glStencilOp;
+#define glStencilOp glad_glStencilOp
+GLAD_API_CALL PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
+#define glStencilOpSeparate glad_glStencilOpSeparate
+GLAD_API_CALL PFNGLTEXBUFFEREXTPROC glad_glTexBufferEXT;
+#define glTexBufferEXT glad_glTexBufferEXT
+GLAD_API_CALL PFNGLTEXBUFFEROESPROC glad_glTexBufferOES;
+#define glTexBufferOES glad_glTexBufferOES
+GLAD_API_CALL PFNGLTEXBUFFERRANGEEXTPROC glad_glTexBufferRangeEXT;
+#define glTexBufferRangeEXT glad_glTexBufferRangeEXT
+GLAD_API_CALL PFNGLTEXBUFFERRANGEOESPROC glad_glTexBufferRangeOES;
+#define glTexBufferRangeOES glad_glTexBufferRangeOES
+GLAD_API_CALL PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
+#define glTexImage2D glad_glTexImage2D
+GLAD_API_CALL PFNGLTEXIMAGE3DOESPROC glad_glTexImage3DOES;
+#define glTexImage3DOES glad_glTexImage3DOES
+GLAD_API_CALL PFNGLTEXPAGECOMMITMENTEXTPROC glad_glTexPageCommitmentEXT;
+#define glTexPageCommitmentEXT glad_glTexPageCommitmentEXT
+GLAD_API_CALL PFNGLTEXPARAMETERIIVEXTPROC glad_glTexParameterIivEXT;
+#define glTexParameterIivEXT glad_glTexParameterIivEXT
+GLAD_API_CALL PFNGLTEXPARAMETERIIVOESPROC glad_glTexParameterIivOES;
+#define glTexParameterIivOES glad_glTexParameterIivOES
+GLAD_API_CALL PFNGLTEXPARAMETERIUIVEXTPROC glad_glTexParameterIuivEXT;
+#define glTexParameterIuivEXT glad_glTexParameterIuivEXT
+GLAD_API_CALL PFNGLTEXPARAMETERIUIVOESPROC glad_glTexParameterIuivOES;
+#define glTexParameterIuivOES glad_glTexParameterIuivOES
+GLAD_API_CALL PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
+#define glTexParameterf glad_glTexParameterf
+GLAD_API_CALL PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
+#define glTexParameterfv glad_glTexParameterfv
+GLAD_API_CALL PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
+#define glTexParameteri glad_glTexParameteri
+GLAD_API_CALL PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
+#define glTexParameteriv glad_glTexParameteriv
+GLAD_API_CALL PFNGLTEXSTORAGE1DEXTPROC glad_glTexStorage1DEXT;
+#define glTexStorage1DEXT glad_glTexStorage1DEXT
+GLAD_API_CALL PFNGLTEXSTORAGE2DEXTPROC glad_glTexStorage2DEXT;
+#define glTexStorage2DEXT glad_glTexStorage2DEXT
+GLAD_API_CALL PFNGLTEXSTORAGE3DEXTPROC glad_glTexStorage3DEXT;
+#define glTexStorage3DEXT glad_glTexStorage3DEXT
+GLAD_API_CALL PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC glad_glTexStorage3DMultisampleOES;
+#define glTexStorage3DMultisampleOES glad_glTexStorage3DMultisampleOES
+GLAD_API_CALL PFNGLTEXSTORAGEATTRIBS2DEXTPROC glad_glTexStorageAttribs2DEXT;
+#define glTexStorageAttribs2DEXT glad_glTexStorageAttribs2DEXT
+GLAD_API_CALL PFNGLTEXSTORAGEATTRIBS3DEXTPROC glad_glTexStorageAttribs3DEXT;
+#define glTexStorageAttribs3DEXT glad_glTexStorageAttribs3DEXT
+GLAD_API_CALL PFNGLTEXSTORAGEMEM2DEXTPROC glad_glTexStorageMem2DEXT;
+#define glTexStorageMem2DEXT glad_glTexStorageMem2DEXT
+GLAD_API_CALL PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTexStorageMem2DMultisampleEXT;
+#define glTexStorageMem2DMultisampleEXT glad_glTexStorageMem2DMultisampleEXT
+GLAD_API_CALL PFNGLTEXSTORAGEMEM3DEXTPROC glad_glTexStorageMem3DEXT;
+#define glTexStorageMem3DEXT glad_glTexStorageMem3DEXT
+GLAD_API_CALL PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTexStorageMem3DMultisampleEXT;
+#define glTexStorageMem3DMultisampleEXT glad_glTexStorageMem3DMultisampleEXT
+GLAD_API_CALL PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
+#define glTexSubImage2D glad_glTexSubImage2D
+GLAD_API_CALL PFNGLTEXSUBIMAGE3DOESPROC glad_glTexSubImage3DOES;
+#define glTexSubImage3DOES glad_glTexSubImage3DOES
+GLAD_API_CALL PFNGLTEXTURESTORAGE1DEXTPROC glad_glTextureStorage1DEXT;
+#define glTextureStorage1DEXT glad_glTextureStorage1DEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGE2DEXTPROC glad_glTextureStorage2DEXT;
+#define glTextureStorage2DEXT glad_glTextureStorage2DEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGE3DEXTPROC glad_glTextureStorage3DEXT;
+#define glTextureStorage3DEXT glad_glTextureStorage3DEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGEMEM2DEXTPROC glad_glTextureStorageMem2DEXT;
+#define glTextureStorageMem2DEXT glad_glTextureStorageMem2DEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTextureStorageMem2DMultisampleEXT;
+#define glTextureStorageMem2DMultisampleEXT glad_glTextureStorageMem2DMultisampleEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGEMEM3DEXTPROC glad_glTextureStorageMem3DEXT;
+#define glTextureStorageMem3DEXT glad_glTextureStorageMem3DEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTextureStorageMem3DMultisampleEXT;
+#define glTextureStorageMem3DMultisampleEXT glad_glTextureStorageMem3DMultisampleEXT
+GLAD_API_CALL PFNGLTEXTUREVIEWEXTPROC glad_glTextureViewEXT;
+#define glTextureViewEXT glad_glTextureViewEXT
+GLAD_API_CALL PFNGLTEXTUREVIEWOESPROC glad_glTextureViewOES;
+#define glTextureViewOES glad_glTextureViewOES
+GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f;
+#define glUniform1f glad_glUniform1f
+GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv;
+#define glUniform1fv glad_glUniform1fv
+GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i;
+#define glUniform1i glad_glUniform1i
+GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv;
+#define glUniform1iv glad_glUniform1iv
+GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f;
+#define glUniform2f glad_glUniform2f
+GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv;
+#define glUniform2fv glad_glUniform2fv
+GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i;
+#define glUniform2i glad_glUniform2i
+GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv;
+#define glUniform2iv glad_glUniform2iv
+GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f;
+#define glUniform3f glad_glUniform3f
+GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv;
+#define glUniform3fv glad_glUniform3fv
+GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i;
+#define glUniform3i glad_glUniform3i
+GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv;
+#define glUniform3iv glad_glUniform3iv
+GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f;
+#define glUniform4f glad_glUniform4f
+GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv;
+#define glUniform4fv glad_glUniform4fv
+GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i;
+#define glUniform4i glad_glUniform4i
+GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv;
+#define glUniform4iv glad_glUniform4iv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
+#define glUniformMatrix2fv glad_glUniformMatrix2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
+#define glUniformMatrix3fv glad_glUniformMatrix3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
+#define glUniformMatrix4fv glad_glUniformMatrix4fv
+GLAD_API_CALL PFNGLUNMAPBUFFEROESPROC glad_glUnmapBufferOES;
+#define glUnmapBufferOES glad_glUnmapBufferOES
+GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram;
+#define glUseProgram glad_glUseProgram
+GLAD_API_CALL PFNGLUSEPROGRAMSTAGESEXTPROC glad_glUseProgramStagesEXT;
+#define glUseProgramStagesEXT glad_glUseProgramStagesEXT
+GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
+#define glValidateProgram glad_glValidateProgram
+GLAD_API_CALL PFNGLVALIDATEPROGRAMPIPELINEEXTPROC glad_glValidateProgramPipelineEXT;
+#define glValidateProgramPipelineEXT glad_glValidateProgramPipelineEXT
+GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
+#define glVertexAttrib1f glad_glVertexAttrib1f
+GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
+#define glVertexAttrib1fv glad_glVertexAttrib1fv
+GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
+#define glVertexAttrib2f glad_glVertexAttrib2f
+GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
+#define glVertexAttrib2fv glad_glVertexAttrib2fv
+GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
+#define glVertexAttrib3f glad_glVertexAttrib3f
+GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
+#define glVertexAttrib3fv glad_glVertexAttrib3fv
+GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
+#define glVertexAttrib4f glad_glVertexAttrib4f
+GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
+#define glVertexAttrib4fv glad_glVertexAttrib4fv
+GLAD_API_CALL PFNGLVERTEXATTRIBDIVISOREXTPROC glad_glVertexAttribDivisorEXT;
+#define glVertexAttribDivisorEXT glad_glVertexAttribDivisorEXT
+GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
+#define glVertexAttribPointer glad_glVertexAttribPointer
+GLAD_API_CALL PFNGLVIEWPORTPROC glad_glViewport;
+#define glViewport glad_glViewport
+GLAD_API_CALL PFNGLVIEWPORTARRAYVOESPROC glad_glViewportArrayvOES;
+#define glViewportArrayvOES glad_glViewportArrayvOES
+GLAD_API_CALL PFNGLVIEWPORTINDEXEDFOESPROC glad_glViewportIndexedfOES;
+#define glViewportIndexedfOES glad_glViewportIndexedfOES
+GLAD_API_CALL PFNGLVIEWPORTINDEXEDFVOESPROC glad_glViewportIndexedfvOES;
+#define glViewportIndexedfvOES glad_glViewportIndexedfvOES
+GLAD_API_CALL PFNGLWAITSEMAPHOREEXTPROC glad_glWaitSemaphoreEXT;
+#define glWaitSemaphoreEXT glad_glWaitSemaphoreEXT
+GLAD_API_CALL PFNGLWINDOWRECTANGLESEXTPROC glad_glWindowRectanglesEXT;
+#define glWindowRectanglesEXT glad_glWindowRectanglesEXT
+
+
+
+
+
+GLAD_API_CALL int gladLoadGLES2UserPtr( GLADuserptrloadfunc load, void *userptr);
+GLAD_API_CALL int gladLoadGLES2( GLADloadfunc load);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+/* Source */
+#ifdef GLAD_GLES2_IMPLEMENTATION
+/**
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef GLAD_IMPL_UTIL_C_
+#define GLAD_IMPL_UTIL_C_
+
+#ifdef _MSC_VER
+#define GLAD_IMPL_UTIL_SSCANF sscanf_s
+#else
+#define GLAD_IMPL_UTIL_SSCANF sscanf
+#endif
+
+#endif /* GLAD_IMPL_UTIL_C_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+int GLAD_GL_ES_VERSION_2_0 = 0;
+int GLAD_GL_EXT_EGL_image_array = 0;
+int GLAD_GL_EXT_EGL_image_storage = 0;
+int GLAD_GL_EXT_EGL_image_storage_compression = 0;
+int GLAD_GL_EXT_YUV_target = 0;
+int GLAD_GL_EXT_base_instance = 0;
+int GLAD_GL_EXT_blend_func_extended = 0;
+int GLAD_GL_EXT_blend_minmax = 0;
+int GLAD_GL_EXT_buffer_storage = 0;
+int GLAD_GL_EXT_clear_texture = 0;
+int GLAD_GL_EXT_clip_control = 0;
+int GLAD_GL_EXT_clip_cull_distance = 0;
+int GLAD_GL_EXT_color_buffer_float = 0;
+int GLAD_GL_EXT_color_buffer_half_float = 0;
+int GLAD_GL_EXT_conservative_depth = 0;
+int GLAD_GL_EXT_copy_image = 0;
+int GLAD_GL_EXT_debug_label = 0;
+int GLAD_GL_EXT_debug_marker = 0;
+int GLAD_GL_EXT_depth_clamp = 0;
+int GLAD_GL_EXT_discard_framebuffer = 0;
+int GLAD_GL_EXT_disjoint_timer_query = 0;
+int GLAD_GL_EXT_draw_buffers = 0;
+int GLAD_GL_EXT_draw_buffers_indexed = 0;
+int GLAD_GL_EXT_draw_elements_base_vertex = 0;
+int GLAD_GL_EXT_draw_instanced = 0;
+int GLAD_GL_EXT_draw_transform_feedback = 0;
+int GLAD_GL_EXT_external_buffer = 0;
+int GLAD_GL_EXT_float_blend = 0;
+int GLAD_GL_EXT_fragment_shading_rate = 0;
+int GLAD_GL_EXT_geometry_point_size = 0;
+int GLAD_GL_EXT_geometry_shader = 0;
+int GLAD_GL_EXT_gpu_shader5 = 0;
+int GLAD_GL_EXT_instanced_arrays = 0;
+int GLAD_GL_EXT_map_buffer_range = 0;
+int GLAD_GL_EXT_memory_object = 0;
+int GLAD_GL_EXT_memory_object_fd = 0;
+int GLAD_GL_EXT_memory_object_win32 = 0;
+int GLAD_GL_EXT_multi_draw_arrays = 0;
+int GLAD_GL_EXT_multi_draw_indirect = 0;
+int GLAD_GL_EXT_multisampled_compatibility = 0;
+int GLAD_GL_EXT_multisampled_render_to_texture = 0;
+int GLAD_GL_EXT_multisampled_render_to_texture2 = 0;
+int GLAD_GL_EXT_multiview_draw_buffers = 0;
+int GLAD_GL_EXT_multiview_tessellation_geometry_shader = 0;
+int GLAD_GL_EXT_multiview_texture_multisample = 0;
+int GLAD_GL_EXT_multiview_timer_query = 0;
+int GLAD_GL_EXT_occlusion_query_boolean = 0;
+int GLAD_GL_EXT_polygon_offset_clamp = 0;
+int GLAD_GL_EXT_post_depth_coverage = 0;
+int GLAD_GL_EXT_primitive_bounding_box = 0;
+int GLAD_GL_EXT_protected_textures = 0;
+int GLAD_GL_EXT_pvrtc_sRGB = 0;
+int GLAD_GL_EXT_raster_multisample = 0;
+int GLAD_GL_EXT_read_format_bgra = 0;
+int GLAD_GL_EXT_render_snorm = 0;
+int GLAD_GL_EXT_robustness = 0;
+int GLAD_GL_EXT_sRGB = 0;
+int GLAD_GL_EXT_sRGB_write_control = 0;
+int GLAD_GL_EXT_semaphore = 0;
+int GLAD_GL_EXT_semaphore_fd = 0;
+int GLAD_GL_EXT_semaphore_win32 = 0;
+int GLAD_GL_EXT_separate_depth_stencil = 0;
+int GLAD_GL_EXT_separate_shader_objects = 0;
+int GLAD_GL_EXT_shader_framebuffer_fetch = 0;
+int GLAD_GL_EXT_shader_framebuffer_fetch_non_coherent = 0;
+int GLAD_GL_EXT_shader_group_vote = 0;
+int GLAD_GL_EXT_shader_implicit_conversions = 0;
+int GLAD_GL_EXT_shader_integer_mix = 0;
+int GLAD_GL_EXT_shader_io_blocks = 0;
+int GLAD_GL_EXT_shader_non_constant_global_initializers = 0;
+int GLAD_GL_EXT_shader_pixel_local_storage = 0;
+int GLAD_GL_EXT_shader_pixel_local_storage2 = 0;
+int GLAD_GL_EXT_shader_samples_identical = 0;
+int GLAD_GL_EXT_shader_texture_lod = 0;
+int GLAD_GL_EXT_shadow_samplers = 0;
+int GLAD_GL_EXT_sparse_texture = 0;
+int GLAD_GL_EXT_sparse_texture2 = 0;
+int GLAD_GL_EXT_tessellation_point_size = 0;
+int GLAD_GL_EXT_tessellation_shader = 0;
+int GLAD_GL_EXT_texture_border_clamp = 0;
+int GLAD_GL_EXT_texture_buffer = 0;
+int GLAD_GL_EXT_texture_compression_astc_decode_mode = 0;
+int GLAD_GL_EXT_texture_compression_bptc = 0;
+int GLAD_GL_EXT_texture_compression_dxt1 = 0;
+int GLAD_GL_EXT_texture_compression_rgtc = 0;
+int GLAD_GL_EXT_texture_compression_s3tc = 0;
+int GLAD_GL_EXT_texture_compression_s3tc_srgb = 0;
+int GLAD_GL_EXT_texture_cube_map_array = 0;
+int GLAD_GL_EXT_texture_filter_anisotropic = 0;
+int GLAD_GL_EXT_texture_filter_minmax = 0;
+int GLAD_GL_EXT_texture_format_BGRA8888 = 0;
+int GLAD_GL_EXT_texture_format_sRGB_override = 0;
+int GLAD_GL_EXT_texture_mirror_clamp_to_edge = 0;
+int GLAD_GL_EXT_texture_norm16 = 0;
+int GLAD_GL_EXT_texture_query_lod = 0;
+int GLAD_GL_EXT_texture_rg = 0;
+int GLAD_GL_EXT_texture_sRGB_R8 = 0;
+int GLAD_GL_EXT_texture_sRGB_RG8 = 0;
+int GLAD_GL_EXT_texture_sRGB_decode = 0;
+int GLAD_GL_EXT_texture_shadow_lod = 0;
+int GLAD_GL_EXT_texture_storage = 0;
+int GLAD_GL_EXT_texture_storage_compression = 0;
+int GLAD_GL_EXT_texture_type_2_10_10_10_REV = 0;
+int GLAD_GL_EXT_texture_view = 0;
+int GLAD_GL_EXT_unpack_subimage = 0;
+int GLAD_GL_EXT_win32_keyed_mutex = 0;
+int GLAD_GL_EXT_window_rectangles = 0;
+int GLAD_GL_KHR_blend_equation_advanced = 0;
+int GLAD_GL_KHR_blend_equation_advanced_coherent = 0;
+int GLAD_GL_KHR_context_flush_control = 0;
+int GLAD_GL_KHR_debug = 0;
+int GLAD_GL_KHR_no_error = 0;
+int GLAD_GL_KHR_parallel_shader_compile = 0;
+int GLAD_GL_KHR_robust_buffer_access_behavior = 0;
+int GLAD_GL_KHR_robustness = 0;
+int GLAD_GL_KHR_shader_subgroup = 0;
+int GLAD_GL_KHR_texture_compression_astc_hdr = 0;
+int GLAD_GL_KHR_texture_compression_astc_ldr = 0;
+int GLAD_GL_KHR_texture_compression_astc_sliced_3d = 0;
+int GLAD_GL_OES_EGL_image = 0;
+int GLAD_GL_OES_EGL_image_external = 0;
+int GLAD_GL_OES_EGL_image_external_essl3 = 0;
+int GLAD_GL_OES_compressed_ETC1_RGB8_sub_texture = 0;
+int GLAD_GL_OES_compressed_ETC1_RGB8_texture = 0;
+int GLAD_GL_OES_compressed_paletted_texture = 0;
+int GLAD_GL_OES_copy_image = 0;
+int GLAD_GL_OES_depth24 = 0;
+int GLAD_GL_OES_depth32 = 0;
+int GLAD_GL_OES_depth_texture = 0;
+int GLAD_GL_OES_draw_buffers_indexed = 0;
+int GLAD_GL_OES_draw_elements_base_vertex = 0;
+int GLAD_GL_OES_element_index_uint = 0;
+int GLAD_GL_OES_fbo_render_mipmap = 0;
+int GLAD_GL_OES_fragment_precision_high = 0;
+int GLAD_GL_OES_geometry_point_size = 0;
+int GLAD_GL_OES_geometry_shader = 0;
+int GLAD_GL_OES_get_program_binary = 0;
+int GLAD_GL_OES_gpu_shader5 = 0;
+int GLAD_GL_OES_mapbuffer = 0;
+int GLAD_GL_OES_packed_depth_stencil = 0;
+int GLAD_GL_OES_primitive_bounding_box = 0;
+int GLAD_GL_OES_required_internalformat = 0;
+int GLAD_GL_OES_rgb8_rgba8 = 0;
+int GLAD_GL_OES_sample_shading = 0;
+int GLAD_GL_OES_sample_variables = 0;
+int GLAD_GL_OES_shader_image_atomic = 0;
+int GLAD_GL_OES_shader_io_blocks = 0;
+int GLAD_GL_OES_shader_multisample_interpolation = 0;
+int GLAD_GL_OES_standard_derivatives = 0;
+int GLAD_GL_OES_stencil1 = 0;
+int GLAD_GL_OES_stencil4 = 0;
+int GLAD_GL_OES_surfaceless_context = 0;
+int GLAD_GL_OES_tessellation_point_size = 0;
+int GLAD_GL_OES_tessellation_shader = 0;
+int GLAD_GL_OES_texture_3D = 0;
+int GLAD_GL_OES_texture_border_clamp = 0;
+int GLAD_GL_OES_texture_buffer = 0;
+int GLAD_GL_OES_texture_compression_astc = 0;
+int GLAD_GL_OES_texture_cube_map_array = 0;
+int GLAD_GL_OES_texture_float = 0;
+int GLAD_GL_OES_texture_float_linear = 0;
+int GLAD_GL_OES_texture_half_float = 0;
+int GLAD_GL_OES_texture_half_float_linear = 0;
+int GLAD_GL_OES_texture_npot = 0;
+int GLAD_GL_OES_texture_stencil8 = 0;
+int GLAD_GL_OES_texture_storage_multisample_2d_array = 0;
+int GLAD_GL_OES_texture_view = 0;
+int GLAD_GL_OES_vertex_array_object = 0;
+int GLAD_GL_OES_vertex_half_float = 0;
+int GLAD_GL_OES_vertex_type_10_10_10_2 = 0;
+int GLAD_GL_OES_viewport_array = 0;
+
+
+
+PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC glad_glAcquireKeyedMutexWin32EXT = NULL;
+PFNGLACTIVESHADERPROGRAMEXTPROC glad_glActiveShaderProgramEXT = NULL;
+PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
+PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
+PFNGLBEGINQUERYEXTPROC glad_glBeginQueryEXT = NULL;
+PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
+PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
+PFNGLBINDFRAGDATALOCATIONEXTPROC glad_glBindFragDataLocationEXT = NULL;
+PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC glad_glBindFragDataLocationIndexedEXT = NULL;
+PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
+PFNGLBINDPROGRAMPIPELINEEXTPROC glad_glBindProgramPipelineEXT = NULL;
+PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
+PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
+PFNGLBINDVERTEXARRAYOESPROC glad_glBindVertexArrayOES = NULL;
+PFNGLBLENDBARRIERKHRPROC glad_glBlendBarrierKHR = NULL;
+PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
+PFNGLBLENDEQUATIONSEPARATEIEXTPROC glad_glBlendEquationSeparateiEXT = NULL;
+PFNGLBLENDEQUATIONSEPARATEIOESPROC glad_glBlendEquationSeparateiOES = NULL;
+PFNGLBLENDEQUATIONIEXTPROC glad_glBlendEquationiEXT = NULL;
+PFNGLBLENDEQUATIONIOESPROC glad_glBlendEquationiOES = NULL;
+PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
+PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
+PFNGLBLENDFUNCSEPARATEIEXTPROC glad_glBlendFuncSeparateiEXT = NULL;
+PFNGLBLENDFUNCSEPARATEIOESPROC glad_glBlendFuncSeparateiOES = NULL;
+PFNGLBLENDFUNCIEXTPROC glad_glBlendFunciEXT = NULL;
+PFNGLBLENDFUNCIOESPROC glad_glBlendFunciOES = NULL;
+PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
+PFNGLBUFFERSTORAGEEXTPROC glad_glBufferStorageEXT = NULL;
+PFNGLBUFFERSTORAGEEXTERNALEXTPROC glad_glBufferStorageExternalEXT = NULL;
+PFNGLBUFFERSTORAGEMEMEXTPROC glad_glBufferStorageMemEXT = NULL;
+PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
+PFNGLCLEARPROC glad_glClear = NULL;
+PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
+PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL;
+PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC glad_glClearPixelLocalStorageuiEXT = NULL;
+PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
+PFNGLCLEARTEXIMAGEEXTPROC glad_glClearTexImageEXT = NULL;
+PFNGLCLEARTEXSUBIMAGEEXTPROC glad_glClearTexSubImageEXT = NULL;
+PFNGLCLIPCONTROLEXTPROC glad_glClipControlEXT = NULL;
+PFNGLCOLORMASKPROC glad_glColorMask = NULL;
+PFNGLCOLORMASKIEXTPROC glad_glColorMaskiEXT = NULL;
+PFNGLCOLORMASKIOESPROC glad_glColorMaskiOES = NULL;
+PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DOESPROC glad_glCompressedTexImage3DOES = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC glad_glCompressedTexSubImage3DOES = NULL;
+PFNGLCOPYIMAGESUBDATAEXTPROC glad_glCopyImageSubDataEXT = NULL;
+PFNGLCOPYIMAGESUBDATAOESPROC glad_glCopyImageSubDataOES = NULL;
+PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE3DOESPROC glad_glCopyTexSubImage3DOES = NULL;
+PFNGLCREATEMEMORYOBJECTSEXTPROC glad_glCreateMemoryObjectsEXT = NULL;
+PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
+PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
+PFNGLCREATESHADERPROGRAMVEXTPROC glad_glCreateShaderProgramvEXT = NULL;
+PFNGLCULLFACEPROC glad_glCullFace = NULL;
+PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR = NULL;
+PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR = NULL;
+PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR = NULL;
+PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
+PFNGLDELETEMEMORYOBJECTSEXTPROC glad_glDeleteMemoryObjectsEXT = NULL;
+PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
+PFNGLDELETEPROGRAMPIPELINESEXTPROC glad_glDeleteProgramPipelinesEXT = NULL;
+PFNGLDELETEQUERIESEXTPROC glad_glDeleteQueriesEXT = NULL;
+PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
+PFNGLDELETESEMAPHORESEXTPROC glad_glDeleteSemaphoresEXT = NULL;
+PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
+PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
+PFNGLDELETEVERTEXARRAYSOESPROC glad_glDeleteVertexArraysOES = NULL;
+PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
+PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
+PFNGLDEPTHRANGEARRAYFVOESPROC glad_glDepthRangeArrayfvOES = NULL;
+PFNGLDEPTHRANGEINDEXEDFOESPROC glad_glDepthRangeIndexedfOES = NULL;
+PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL;
+PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
+PFNGLDISABLEPROC glad_glDisable = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
+PFNGLDISABLEIEXTPROC glad_glDisableiEXT = NULL;
+PFNGLDISABLEIOESPROC glad_glDisableiOES = NULL;
+PFNGLDISCARDFRAMEBUFFEREXTPROC glad_glDiscardFramebufferEXT = NULL;
+PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
+PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC glad_glDrawArraysInstancedBaseInstanceEXT = NULL;
+PFNGLDRAWARRAYSINSTANCEDEXTPROC glad_glDrawArraysInstancedEXT = NULL;
+PFNGLDRAWBUFFERSEXTPROC glad_glDrawBuffersEXT = NULL;
+PFNGLDRAWBUFFERSINDEXEDEXTPROC glad_glDrawBuffersIndexedEXT = NULL;
+PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXEXTPROC glad_glDrawElementsBaseVertexEXT = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXOESPROC glad_glDrawElementsBaseVertexOES = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC glad_glDrawElementsInstancedBaseInstanceEXT = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC glad_glDrawElementsInstancedBaseVertexBaseInstanceEXT = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC glad_glDrawElementsInstancedBaseVertexEXT = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC glad_glDrawElementsInstancedBaseVertexOES = NULL;
+PFNGLDRAWELEMENTSINSTANCEDEXTPROC glad_glDrawElementsInstancedEXT = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC glad_glDrawRangeElementsBaseVertexEXT = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC glad_glDrawRangeElementsBaseVertexOES = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKEXTPROC glad_glDrawTransformFeedbackEXT = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC glad_glDrawTransformFeedbackInstancedEXT = NULL;
+PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glad_glEGLImageTargetRenderbufferStorageOES = NULL;
+PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC glad_glEGLImageTargetTexStorageEXT = NULL;
+PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glad_glEGLImageTargetTexture2DOES = NULL;
+PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC glad_glEGLImageTargetTextureStorageEXT = NULL;
+PFNGLENABLEPROC glad_glEnable = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
+PFNGLENABLEIEXTPROC glad_glEnableiEXT = NULL;
+PFNGLENABLEIOESPROC glad_glEnableiOES = NULL;
+PFNGLENDQUERYEXTPROC glad_glEndQueryEXT = NULL;
+PFNGLFINISHPROC glad_glFinish = NULL;
+PFNGLFLUSHPROC glad_glFlush = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC glad_glFlushMappedBufferRangeEXT = NULL;
+PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC glad_glFramebufferFetchBarrierEXT = NULL;
+PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC glad_glFramebufferPixelLocalStorageSizeEXT = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERSHADINGRATEEXTPROC glad_glFramebufferShadingRateEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glad_glFramebufferTexture2DMultisampleEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DOESPROC glad_glFramebufferTexture3DOES = NULL;
+PFNGLFRAMEBUFFERTEXTUREEXTPROC glad_glFramebufferTextureEXT = NULL;
+PFNGLFRAMEBUFFERTEXTUREOESPROC glad_glFramebufferTextureOES = NULL;
+PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
+PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
+PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
+PFNGLGENPROGRAMPIPELINESEXTPROC glad_glGenProgramPipelinesEXT = NULL;
+PFNGLGENQUERIESEXTPROC glad_glGenQueriesEXT = NULL;
+PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
+PFNGLGENSEMAPHORESEXTPROC glad_glGenSemaphoresEXT = NULL;
+PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
+PFNGLGENVERTEXARRAYSOESPROC glad_glGenVertexArraysOES = NULL;
+PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
+PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
+PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
+PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPOINTERVOESPROC glad_glGetBufferPointervOES = NULL;
+PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR = NULL;
+PFNGLGETERRORPROC glad_glGetError = NULL;
+PFNGLGETFLOATI_VOESPROC glad_glGetFloati_vOES = NULL;
+PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
+PFNGLGETFRAGDATAINDEXEXTPROC glad_glGetFragDataIndexEXT = NULL;
+PFNGLGETFRAGMENTSHADINGRATESEXTPROC glad_glGetFragmentShadingRatesEXT = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC glad_glGetFramebufferPixelLocalStorageSizeEXT = NULL;
+PFNGLGETGRAPHICSRESETSTATUSEXTPROC glad_glGetGraphicsResetStatusEXT = NULL;
+PFNGLGETGRAPHICSRESETSTATUSKHRPROC glad_glGetGraphicsResetStatusKHR = NULL;
+PFNGLGETINTEGER64VEXTPROC glad_glGetInteger64vEXT = NULL;
+PFNGLGETINTEGERI_VEXTPROC glad_glGetIntegeri_vEXT = NULL;
+PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
+PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC glad_glGetMemoryObjectParameterivEXT = NULL;
+PFNGLGETOBJECTLABELEXTPROC glad_glGetObjectLabelEXT = NULL;
+PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR = NULL;
+PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR = NULL;
+PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR = NULL;
+PFNGLGETPROGRAMBINARYOESPROC glad_glGetProgramBinaryOES = NULL;
+PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC glad_glGetProgramPipelineInfoLogEXT = NULL;
+PFNGLGETPROGRAMPIPELINEIVEXTPROC glad_glGetProgramPipelineivEXT = NULL;
+PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC glad_glGetProgramResourceLocationIndexEXT = NULL;
+PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
+PFNGLGETQUERYOBJECTI64VEXTPROC glad_glGetQueryObjecti64vEXT = NULL;
+PFNGLGETQUERYOBJECTIVEXTPROC glad_glGetQueryObjectivEXT = NULL;
+PFNGLGETQUERYOBJECTUI64VEXTPROC glad_glGetQueryObjectui64vEXT = NULL;
+PFNGLGETQUERYOBJECTUIVEXTPROC glad_glGetQueryObjectuivEXT = NULL;
+PFNGLGETQUERYIVEXTPROC glad_glGetQueryivEXT = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
+PFNGLGETSAMPLERPARAMETERIIVEXTPROC glad_glGetSamplerParameterIivEXT = NULL;
+PFNGLGETSAMPLERPARAMETERIIVOESPROC glad_glGetSamplerParameterIivOES = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVEXTPROC glad_glGetSamplerParameterIuivEXT = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVOESPROC glad_glGetSamplerParameterIuivOES = NULL;
+PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC glad_glGetSemaphoreParameterui64vEXT = NULL;
+PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
+PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat = NULL;
+PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
+PFNGLGETSTRINGPROC glad_glGetString = NULL;
+PFNGLGETTEXPARAMETERIIVEXTPROC glad_glGetTexParameterIivEXT = NULL;
+PFNGLGETTEXPARAMETERIIVOESPROC glad_glGetTexParameterIivOES = NULL;
+PFNGLGETTEXPARAMETERIUIVEXTPROC glad_glGetTexParameterIuivEXT = NULL;
+PFNGLGETTEXPARAMETERIUIVOESPROC glad_glGetTexParameterIuivOES = NULL;
+PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
+PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
+PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
+PFNGLGETUNSIGNEDBYTEI_VEXTPROC glad_glGetUnsignedBytei_vEXT = NULL;
+PFNGLGETUNSIGNEDBYTEVEXTPROC glad_glGetUnsignedBytevEXT = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
+PFNGLGETNUNIFORMFVEXTPROC glad_glGetnUniformfvEXT = NULL;
+PFNGLGETNUNIFORMFVKHRPROC glad_glGetnUniformfvKHR = NULL;
+PFNGLGETNUNIFORMIVEXTPROC glad_glGetnUniformivEXT = NULL;
+PFNGLGETNUNIFORMIVKHRPROC glad_glGetnUniformivKHR = NULL;
+PFNGLGETNUNIFORMUIVKHRPROC glad_glGetnUniformuivKHR = NULL;
+PFNGLHINTPROC glad_glHint = NULL;
+PFNGLIMPORTMEMORYFDEXTPROC glad_glImportMemoryFdEXT = NULL;
+PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC glad_glImportMemoryWin32HandleEXT = NULL;
+PFNGLIMPORTMEMORYWIN32NAMEEXTPROC glad_glImportMemoryWin32NameEXT = NULL;
+PFNGLIMPORTSEMAPHOREFDEXTPROC glad_glImportSemaphoreFdEXT = NULL;
+PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC glad_glImportSemaphoreWin32HandleEXT = NULL;
+PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC glad_glImportSemaphoreWin32NameEXT = NULL;
+PFNGLINSERTEVENTMARKEREXTPROC glad_glInsertEventMarkerEXT = NULL;
+PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
+PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
+PFNGLISENABLEDIEXTPROC glad_glIsEnablediEXT = NULL;
+PFNGLISENABLEDIOESPROC glad_glIsEnablediOES = NULL;
+PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
+PFNGLISMEMORYOBJECTEXTPROC glad_glIsMemoryObjectEXT = NULL;
+PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
+PFNGLISPROGRAMPIPELINEEXTPROC glad_glIsProgramPipelineEXT = NULL;
+PFNGLISQUERYEXTPROC glad_glIsQueryEXT = NULL;
+PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
+PFNGLISSEMAPHOREEXTPROC glad_glIsSemaphoreEXT = NULL;
+PFNGLISSHADERPROC glad_glIsShader = NULL;
+PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
+PFNGLISVERTEXARRAYOESPROC glad_glIsVertexArrayOES = NULL;
+PFNGLLABELOBJECTEXTPROC glad_glLabelObjectEXT = NULL;
+PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
+PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
+PFNGLMAPBUFFEROESPROC glad_glMapBufferOES = NULL;
+PFNGLMAPBUFFERRANGEEXTPROC glad_glMapBufferRangeEXT = NULL;
+PFNGLMAXSHADERCOMPILERTHREADSKHRPROC glad_glMaxShaderCompilerThreadsKHR = NULL;
+PFNGLMEMORYOBJECTPARAMETERIVEXTPROC glad_glMemoryObjectParameterivEXT = NULL;
+PFNGLMINSAMPLESHADINGOESPROC glad_glMinSampleShadingOES = NULL;
+PFNGLMULTIDRAWARRAYSEXTPROC glad_glMultiDrawArraysEXT = NULL;
+PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC glad_glMultiDrawArraysIndirectEXT = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC glad_glMultiDrawElementsBaseVertexEXT = NULL;
+PFNGLMULTIDRAWELEMENTSEXTPROC glad_glMultiDrawElementsEXT = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC glad_glMultiDrawElementsIndirectEXT = NULL;
+PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC glad_glNamedBufferStorageExternalEXT = NULL;
+PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC glad_glNamedBufferStorageMemEXT = NULL;
+PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR = NULL;
+PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR = NULL;
+PFNGLPATCHPARAMETERIEXTPROC glad_glPatchParameteriEXT = NULL;
+PFNGLPATCHPARAMETERIOESPROC glad_glPatchParameteriOES = NULL;
+PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
+PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
+PFNGLPOLYGONOFFSETCLAMPEXTPROC glad_glPolygonOffsetClampEXT = NULL;
+PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR = NULL;
+PFNGLPOPGROUPMARKEREXTPROC glad_glPopGroupMarkerEXT = NULL;
+PFNGLPRIMITIVEBOUNDINGBOXEXTPROC glad_glPrimitiveBoundingBoxEXT = NULL;
+PFNGLPRIMITIVEBOUNDINGBOXOESPROC glad_glPrimitiveBoundingBoxOES = NULL;
+PFNGLPROGRAMBINARYOESPROC glad_glProgramBinaryOES = NULL;
+PFNGLPROGRAMPARAMETERIEXTPROC glad_glProgramParameteriEXT = NULL;
+PFNGLPROGRAMUNIFORM1FEXTPROC glad_glProgramUniform1fEXT = NULL;
+PFNGLPROGRAMUNIFORM1FVEXTPROC glad_glProgramUniform1fvEXT = NULL;
+PFNGLPROGRAMUNIFORM1IEXTPROC glad_glProgramUniform1iEXT = NULL;
+PFNGLPROGRAMUNIFORM1IVEXTPROC glad_glProgramUniform1ivEXT = NULL;
+PFNGLPROGRAMUNIFORM1UIEXTPROC glad_glProgramUniform1uiEXT = NULL;
+PFNGLPROGRAMUNIFORM1UIVEXTPROC glad_glProgramUniform1uivEXT = NULL;
+PFNGLPROGRAMUNIFORM2FEXTPROC glad_glProgramUniform2fEXT = NULL;
+PFNGLPROGRAMUNIFORM2FVEXTPROC glad_glProgramUniform2fvEXT = NULL;
+PFNGLPROGRAMUNIFORM2IEXTPROC glad_glProgramUniform2iEXT = NULL;
+PFNGLPROGRAMUNIFORM2IVEXTPROC glad_glProgramUniform2ivEXT = NULL;
+PFNGLPROGRAMUNIFORM2UIEXTPROC glad_glProgramUniform2uiEXT = NULL;
+PFNGLPROGRAMUNIFORM2UIVEXTPROC glad_glProgramUniform2uivEXT = NULL;
+PFNGLPROGRAMUNIFORM3FEXTPROC glad_glProgramUniform3fEXT = NULL;
+PFNGLPROGRAMUNIFORM3FVEXTPROC glad_glProgramUniform3fvEXT = NULL;
+PFNGLPROGRAMUNIFORM3IEXTPROC glad_glProgramUniform3iEXT = NULL;
+PFNGLPROGRAMUNIFORM3IVEXTPROC glad_glProgramUniform3ivEXT = NULL;
+PFNGLPROGRAMUNIFORM3UIEXTPROC glad_glProgramUniform3uiEXT = NULL;
+PFNGLPROGRAMUNIFORM3UIVEXTPROC glad_glProgramUniform3uivEXT = NULL;
+PFNGLPROGRAMUNIFORM4FEXTPROC glad_glProgramUniform4fEXT = NULL;
+PFNGLPROGRAMUNIFORM4FVEXTPROC glad_glProgramUniform4fvEXT = NULL;
+PFNGLPROGRAMUNIFORM4IEXTPROC glad_glProgramUniform4iEXT = NULL;
+PFNGLPROGRAMUNIFORM4IVEXTPROC glad_glProgramUniform4ivEXT = NULL;
+PFNGLPROGRAMUNIFORM4UIEXTPROC glad_glProgramUniform4uiEXT = NULL;
+PFNGLPROGRAMUNIFORM4UIVEXTPROC glad_glProgramUniform4uivEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC glad_glProgramUniformMatrix2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC glad_glProgramUniformMatrix2x3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC glad_glProgramUniformMatrix2x4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC glad_glProgramUniformMatrix3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC glad_glProgramUniformMatrix3x2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC glad_glProgramUniformMatrix3x4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC glad_glProgramUniformMatrix4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC glad_glProgramUniformMatrix4x2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC glad_glProgramUniformMatrix4x3fvEXT = NULL;
+PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR = NULL;
+PFNGLPUSHGROUPMARKEREXTPROC glad_glPushGroupMarkerEXT = NULL;
+PFNGLQUERYCOUNTEREXTPROC glad_glQueryCounterEXT = NULL;
+PFNGLRASTERSAMPLESEXTPROC glad_glRasterSamplesEXT = NULL;
+PFNGLREADBUFFERINDEXEDEXTPROC glad_glReadBufferIndexedEXT = NULL;
+PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
+PFNGLREADNPIXELSEXTPROC glad_glReadnPixelsEXT = NULL;
+PFNGLREADNPIXELSKHRPROC glad_glReadnPixelsKHR = NULL;
+PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC glad_glReleaseKeyedMutexWin32EXT = NULL;
+PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT = NULL;
+PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
+PFNGLSAMPLERPARAMETERIIVEXTPROC glad_glSamplerParameterIivEXT = NULL;
+PFNGLSAMPLERPARAMETERIIVOESPROC glad_glSamplerParameterIivOES = NULL;
+PFNGLSAMPLERPARAMETERIUIVEXTPROC glad_glSamplerParameterIuivEXT = NULL;
+PFNGLSAMPLERPARAMETERIUIVOESPROC glad_glSamplerParameterIuivOES = NULL;
+PFNGLSCISSORPROC glad_glScissor = NULL;
+PFNGLSCISSORARRAYVOESPROC glad_glScissorArrayvOES = NULL;
+PFNGLSCISSORINDEXEDOESPROC glad_glScissorIndexedOES = NULL;
+PFNGLSCISSORINDEXEDVOESPROC glad_glScissorIndexedvOES = NULL;
+PFNGLSEMAPHOREPARAMETERUI64VEXTPROC glad_glSemaphoreParameterui64vEXT = NULL;
+PFNGLSHADERBINARYPROC glad_glShaderBinary = NULL;
+PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
+PFNGLSHADINGRATECOMBINEROPSEXTPROC glad_glShadingRateCombinerOpsEXT = NULL;
+PFNGLSHADINGRATEEXTPROC glad_glShadingRateEXT = NULL;
+PFNGLSIGNALSEMAPHOREEXTPROC glad_glSignalSemaphoreEXT = NULL;
+PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
+PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
+PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
+PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
+PFNGLTEXBUFFEREXTPROC glad_glTexBufferEXT = NULL;
+PFNGLTEXBUFFEROESPROC glad_glTexBufferOES = NULL;
+PFNGLTEXBUFFERRANGEEXTPROC glad_glTexBufferRangeEXT = NULL;
+PFNGLTEXBUFFERRANGEOESPROC glad_glTexBufferRangeOES = NULL;
+PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
+PFNGLTEXIMAGE3DOESPROC glad_glTexImage3DOES = NULL;
+PFNGLTEXPAGECOMMITMENTEXTPROC glad_glTexPageCommitmentEXT = NULL;
+PFNGLTEXPARAMETERIIVEXTPROC glad_glTexParameterIivEXT = NULL;
+PFNGLTEXPARAMETERIIVOESPROC glad_glTexParameterIivOES = NULL;
+PFNGLTEXPARAMETERIUIVEXTPROC glad_glTexParameterIuivEXT = NULL;
+PFNGLTEXPARAMETERIUIVOESPROC glad_glTexParameterIuivOES = NULL;
+PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
+PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
+PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
+PFNGLTEXSTORAGE1DEXTPROC glad_glTexStorage1DEXT = NULL;
+PFNGLTEXSTORAGE2DEXTPROC glad_glTexStorage2DEXT = NULL;
+PFNGLTEXSTORAGE3DEXTPROC glad_glTexStorage3DEXT = NULL;
+PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC glad_glTexStorage3DMultisampleOES = NULL;
+PFNGLTEXSTORAGEATTRIBS2DEXTPROC glad_glTexStorageAttribs2DEXT = NULL;
+PFNGLTEXSTORAGEATTRIBS3DEXTPROC glad_glTexStorageAttribs3DEXT = NULL;
+PFNGLTEXSTORAGEMEM2DEXTPROC glad_glTexStorageMem2DEXT = NULL;
+PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTexStorageMem2DMultisampleEXT = NULL;
+PFNGLTEXSTORAGEMEM3DEXTPROC glad_glTexStorageMem3DEXT = NULL;
+PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTexStorageMem3DMultisampleEXT = NULL;
+PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
+PFNGLTEXSUBIMAGE3DOESPROC glad_glTexSubImage3DOES = NULL;
+PFNGLTEXTURESTORAGE1DEXTPROC glad_glTextureStorage1DEXT = NULL;
+PFNGLTEXTURESTORAGE2DEXTPROC glad_glTextureStorage2DEXT = NULL;
+PFNGLTEXTURESTORAGE3DEXTPROC glad_glTextureStorage3DEXT = NULL;
+PFNGLTEXTURESTORAGEMEM2DEXTPROC glad_glTextureStorageMem2DEXT = NULL;
+PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTextureStorageMem2DMultisampleEXT = NULL;
+PFNGLTEXTURESTORAGEMEM3DEXTPROC glad_glTextureStorageMem3DEXT = NULL;
+PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTextureStorageMem3DMultisampleEXT = NULL;
+PFNGLTEXTUREVIEWEXTPROC glad_glTextureViewEXT = NULL;
+PFNGLTEXTUREVIEWOESPROC glad_glTextureViewOES = NULL;
+PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
+PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
+PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
+PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
+PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
+PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
+PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
+PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
+PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
+PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
+PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
+PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
+PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
+PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
+PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
+PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
+PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
+PFNGLUNMAPBUFFEROESPROC glad_glUnmapBufferOES = NULL;
+PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
+PFNGLUSEPROGRAMSTAGESEXTPROC glad_glUseProgramStagesEXT = NULL;
+PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
+PFNGLVALIDATEPROGRAMPIPELINEEXTPROC glad_glValidateProgramPipelineEXT = NULL;
+PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIBDIVISOREXTPROC glad_glVertexAttribDivisorEXT = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
+PFNGLVIEWPORTPROC glad_glViewport = NULL;
+PFNGLVIEWPORTARRAYVOESPROC glad_glViewportArrayvOES = NULL;
+PFNGLVIEWPORTINDEXEDFOESPROC glad_glViewportIndexedfOES = NULL;
+PFNGLVIEWPORTINDEXEDFVOESPROC glad_glViewportIndexedfvOES = NULL;
+PFNGLWAITSEMAPHOREEXTPROC glad_glWaitSemaphoreEXT = NULL;
+PFNGLWINDOWRECTANGLESEXTPROC glad_glWindowRectanglesEXT = NULL;
+
+
+static void glad_gl_load_GL_ES_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_ES_VERSION_2_0) return;
+    glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture");
+    glad_glAttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader");
+    glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation");
+    glad_glBindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer");
+    glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer");
+    glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer");
+    glad_glBindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture");
+    glad_glBlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor");
+    glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation");
+    glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate");
+    glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc");
+    glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate");
+    glad_glBufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData");
+    glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData");
+    glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus");
+    glad_glClear = (PFNGLCLEARPROC) load(userptr, "glClear");
+    glad_glClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor");
+    glad_glClearDepthf = (PFNGLCLEARDEPTHFPROC) load(userptr, "glClearDepthf");
+    glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil");
+    glad_glColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask");
+    glad_glCompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader");
+    glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D");
+    glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D");
+    glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D");
+    glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D");
+    glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram");
+    glad_glCreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader");
+    glad_glCullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace");
+    glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers");
+    glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers");
+    glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram");
+    glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers");
+    glad_glDeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader");
+    glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures");
+    glad_glDepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc");
+    glad_glDepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask");
+    glad_glDepthRangef = (PFNGLDEPTHRANGEFPROC) load(userptr, "glDepthRangef");
+    glad_glDetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader");
+    glad_glDisable = (PFNGLDISABLEPROC) load(userptr, "glDisable");
+    glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray");
+    glad_glDrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays");
+    glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements");
+    glad_glEnable = (PFNGLENABLEPROC) load(userptr, "glEnable");
+    glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray");
+    glad_glFinish = (PFNGLFINISHPROC) load(userptr, "glFinish");
+    glad_glFlush = (PFNGLFLUSHPROC) load(userptr, "glFlush");
+    glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer");
+    glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D");
+    glad_glFrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace");
+    glad_glGenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers");
+    glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers");
+    glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers");
+    glad_glGenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures");
+    glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap");
+    glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib");
+    glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform");
+    glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders");
+    glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation");
+    glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv");
+    glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv");
+    glad_glGetError = (PFNGLGETERRORPROC) load(userptr, "glGetError");
+    glad_glGetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv");
+    glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv");
+    glad_glGetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv");
+    glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog");
+    glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv");
+    glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv");
+    glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog");
+    glad_glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC) load(userptr, "glGetShaderPrecisionFormat");
+    glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource");
+    glad_glGetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv");
+    glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+    glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv");
+    glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv");
+    glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation");
+    glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv");
+    glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv");
+    glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv");
+    glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv");
+    glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv");
+    glad_glHint = (PFNGLHINTPROC) load(userptr, "glHint");
+    glad_glIsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer");
+    glad_glIsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled");
+    glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer");
+    glad_glIsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram");
+    glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer");
+    glad_glIsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader");
+    glad_glIsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture");
+    glad_glLineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth");
+    glad_glLinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram");
+    glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei");
+    glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset");
+    glad_glReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels");
+    glad_glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC) load(userptr, "glReleaseShaderCompiler");
+    glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage");
+    glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage");
+    glad_glScissor = (PFNGLSCISSORPROC) load(userptr, "glScissor");
+    glad_glShaderBinary = (PFNGLSHADERBINARYPROC) load(userptr, "glShaderBinary");
+    glad_glShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource");
+    glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc");
+    glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate");
+    glad_glStencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask");
+    glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate");
+    glad_glStencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp");
+    glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate");
+    glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D");
+    glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf");
+    glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv");
+    glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri");
+    glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv");
+    glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D");
+    glad_glUniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f");
+    glad_glUniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv");
+    glad_glUniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i");
+    glad_glUniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv");
+    glad_glUniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f");
+    glad_glUniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv");
+    glad_glUniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i");
+    glad_glUniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv");
+    glad_glUniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f");
+    glad_glUniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv");
+    glad_glUniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i");
+    glad_glUniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv");
+    glad_glUniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f");
+    glad_glUniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv");
+    glad_glUniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i");
+    glad_glUniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv");
+    glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv");
+    glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv");
+    glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv");
+    glad_glUseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram");
+    glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram");
+    glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f");
+    glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv");
+    glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f");
+    glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv");
+    glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f");
+    glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv");
+    glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f");
+    glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv");
+    glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer");
+    glad_glViewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport");
+}
+static void glad_gl_load_GL_EXT_EGL_image_storage( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_EGL_image_storage) return;
+    glad_glEGLImageTargetTexStorageEXT = (PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC) load(userptr, "glEGLImageTargetTexStorageEXT");
+    glad_glEGLImageTargetTextureStorageEXT = (PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC) load(userptr, "glEGLImageTargetTextureStorageEXT");
+}
+static void glad_gl_load_GL_EXT_base_instance( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_base_instance) return;
+    glad_glDrawArraysInstancedBaseInstanceEXT = (PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC) load(userptr, "glDrawArraysInstancedBaseInstanceEXT");
+    glad_glDrawElementsInstancedBaseInstanceEXT = (PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC) load(userptr, "glDrawElementsInstancedBaseInstanceEXT");
+    glad_glDrawElementsInstancedBaseVertexBaseInstanceEXT = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC) load(userptr, "glDrawElementsInstancedBaseVertexBaseInstanceEXT");
+}
+static void glad_gl_load_GL_EXT_blend_func_extended( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_blend_func_extended) return;
+    glad_glBindFragDataLocationEXT = (PFNGLBINDFRAGDATALOCATIONEXTPROC) load(userptr, "glBindFragDataLocationEXT");
+    glad_glBindFragDataLocationIndexedEXT = (PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC) load(userptr, "glBindFragDataLocationIndexedEXT");
+    glad_glGetFragDataIndexEXT = (PFNGLGETFRAGDATAINDEXEXTPROC) load(userptr, "glGetFragDataIndexEXT");
+    glad_glGetProgramResourceLocationIndexEXT = (PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC) load(userptr, "glGetProgramResourceLocationIndexEXT");
+}
+static void glad_gl_load_GL_EXT_buffer_storage( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_buffer_storage) return;
+    glad_glBufferStorageEXT = (PFNGLBUFFERSTORAGEEXTPROC) load(userptr, "glBufferStorageEXT");
+}
+static void glad_gl_load_GL_EXT_clear_texture( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_clear_texture) return;
+    glad_glClearTexImageEXT = (PFNGLCLEARTEXIMAGEEXTPROC) load(userptr, "glClearTexImageEXT");
+    glad_glClearTexSubImageEXT = (PFNGLCLEARTEXSUBIMAGEEXTPROC) load(userptr, "glClearTexSubImageEXT");
+}
+static void glad_gl_load_GL_EXT_clip_control( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_clip_control) return;
+    glad_glClipControlEXT = (PFNGLCLIPCONTROLEXTPROC) load(userptr, "glClipControlEXT");
+}
+static void glad_gl_load_GL_EXT_copy_image( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_copy_image) return;
+    glad_glCopyImageSubDataEXT = (PFNGLCOPYIMAGESUBDATAEXTPROC) load(userptr, "glCopyImageSubDataEXT");
+}
+static void glad_gl_load_GL_EXT_debug_label( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_debug_label) return;
+    glad_glGetObjectLabelEXT = (PFNGLGETOBJECTLABELEXTPROC) load(userptr, "glGetObjectLabelEXT");
+    glad_glLabelObjectEXT = (PFNGLLABELOBJECTEXTPROC) load(userptr, "glLabelObjectEXT");
+}
+static void glad_gl_load_GL_EXT_debug_marker( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_debug_marker) return;
+    glad_glInsertEventMarkerEXT = (PFNGLINSERTEVENTMARKEREXTPROC) load(userptr, "glInsertEventMarkerEXT");
+    glad_glPopGroupMarkerEXT = (PFNGLPOPGROUPMARKEREXTPROC) load(userptr, "glPopGroupMarkerEXT");
+    glad_glPushGroupMarkerEXT = (PFNGLPUSHGROUPMARKEREXTPROC) load(userptr, "glPushGroupMarkerEXT");
+}
+static void glad_gl_load_GL_EXT_discard_framebuffer( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_discard_framebuffer) return;
+    glad_glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC) load(userptr, "glDiscardFramebufferEXT");
+}
+static void glad_gl_load_GL_EXT_disjoint_timer_query( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_disjoint_timer_query) return;
+    glad_glBeginQueryEXT = (PFNGLBEGINQUERYEXTPROC) load(userptr, "glBeginQueryEXT");
+    glad_glDeleteQueriesEXT = (PFNGLDELETEQUERIESEXTPROC) load(userptr, "glDeleteQueriesEXT");
+    glad_glEndQueryEXT = (PFNGLENDQUERYEXTPROC) load(userptr, "glEndQueryEXT");
+    glad_glGenQueriesEXT = (PFNGLGENQUERIESEXTPROC) load(userptr, "glGenQueriesEXT");
+    glad_glGetInteger64vEXT = (PFNGLGETINTEGER64VEXTPROC) load(userptr, "glGetInteger64vEXT");
+    glad_glGetQueryObjecti64vEXT = (PFNGLGETQUERYOBJECTI64VEXTPROC) load(userptr, "glGetQueryObjecti64vEXT");
+    glad_glGetQueryObjectivEXT = (PFNGLGETQUERYOBJECTIVEXTPROC) load(userptr, "glGetQueryObjectivEXT");
+    glad_glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC) load(userptr, "glGetQueryObjectui64vEXT");
+    glad_glGetQueryObjectuivEXT = (PFNGLGETQUERYOBJECTUIVEXTPROC) load(userptr, "glGetQueryObjectuivEXT");
+    glad_glGetQueryivEXT = (PFNGLGETQUERYIVEXTPROC) load(userptr, "glGetQueryivEXT");
+    glad_glIsQueryEXT = (PFNGLISQUERYEXTPROC) load(userptr, "glIsQueryEXT");
+    glad_glQueryCounterEXT = (PFNGLQUERYCOUNTEREXTPROC) load(userptr, "glQueryCounterEXT");
+}
+static void glad_gl_load_GL_EXT_draw_buffers( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_draw_buffers) return;
+    glad_glDrawBuffersEXT = (PFNGLDRAWBUFFERSEXTPROC) load(userptr, "glDrawBuffersEXT");
+}
+static void glad_gl_load_GL_EXT_draw_buffers_indexed( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_draw_buffers_indexed) return;
+    glad_glBlendEquationSeparateiEXT = (PFNGLBLENDEQUATIONSEPARATEIEXTPROC) load(userptr, "glBlendEquationSeparateiEXT");
+    glad_glBlendEquationiEXT = (PFNGLBLENDEQUATIONIEXTPROC) load(userptr, "glBlendEquationiEXT");
+    glad_glBlendFuncSeparateiEXT = (PFNGLBLENDFUNCSEPARATEIEXTPROC) load(userptr, "glBlendFuncSeparateiEXT");
+    glad_glBlendFunciEXT = (PFNGLBLENDFUNCIEXTPROC) load(userptr, "glBlendFunciEXT");
+    glad_glColorMaskiEXT = (PFNGLCOLORMASKIEXTPROC) load(userptr, "glColorMaskiEXT");
+    glad_glDisableiEXT = (PFNGLDISABLEIEXTPROC) load(userptr, "glDisableiEXT");
+    glad_glEnableiEXT = (PFNGLENABLEIEXTPROC) load(userptr, "glEnableiEXT");
+    glad_glIsEnablediEXT = (PFNGLISENABLEDIEXTPROC) load(userptr, "glIsEnablediEXT");
+}
+static void glad_gl_load_GL_EXT_draw_elements_base_vertex( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_draw_elements_base_vertex) return;
+    glad_glDrawElementsBaseVertexEXT = (PFNGLDRAWELEMENTSBASEVERTEXEXTPROC) load(userptr, "glDrawElementsBaseVertexEXT");
+    glad_glDrawElementsInstancedBaseVertexEXT = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) load(userptr, "glDrawElementsInstancedBaseVertexEXT");
+    glad_glDrawRangeElementsBaseVertexEXT = (PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) load(userptr, "glDrawRangeElementsBaseVertexEXT");
+    glad_glMultiDrawElementsBaseVertexEXT = (PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) load(userptr, "glMultiDrawElementsBaseVertexEXT");
+}
+static void glad_gl_load_GL_EXT_draw_instanced( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_draw_instanced) return;
+    glad_glDrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC) load(userptr, "glDrawArraysInstancedEXT");
+    glad_glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC) load(userptr, "glDrawElementsInstancedEXT");
+}
+static void glad_gl_load_GL_EXT_draw_transform_feedback( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_draw_transform_feedback) return;
+    glad_glDrawTransformFeedbackEXT = (PFNGLDRAWTRANSFORMFEEDBACKEXTPROC) load(userptr, "glDrawTransformFeedbackEXT");
+    glad_glDrawTransformFeedbackInstancedEXT = (PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC) load(userptr, "glDrawTransformFeedbackInstancedEXT");
+}
+static void glad_gl_load_GL_EXT_external_buffer( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_external_buffer) return;
+    glad_glBufferStorageExternalEXT = (PFNGLBUFFERSTORAGEEXTERNALEXTPROC) load(userptr, "glBufferStorageExternalEXT");
+    glad_glNamedBufferStorageExternalEXT = (PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC) load(userptr, "glNamedBufferStorageExternalEXT");
+}
+static void glad_gl_load_GL_EXT_fragment_shading_rate( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_fragment_shading_rate) return;
+    glad_glFramebufferShadingRateEXT = (PFNGLFRAMEBUFFERSHADINGRATEEXTPROC) load(userptr, "glFramebufferShadingRateEXT");
+    glad_glGetFragmentShadingRatesEXT = (PFNGLGETFRAGMENTSHADINGRATESEXTPROC) load(userptr, "glGetFragmentShadingRatesEXT");
+    glad_glShadingRateCombinerOpsEXT = (PFNGLSHADINGRATECOMBINEROPSEXTPROC) load(userptr, "glShadingRateCombinerOpsEXT");
+    glad_glShadingRateEXT = (PFNGLSHADINGRATEEXTPROC) load(userptr, "glShadingRateEXT");
+}
+static void glad_gl_load_GL_EXT_geometry_shader( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_geometry_shader) return;
+    glad_glFramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC) load(userptr, "glFramebufferTextureEXT");
+}
+static void glad_gl_load_GL_EXT_instanced_arrays( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_instanced_arrays) return;
+    glad_glDrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC) load(userptr, "glDrawArraysInstancedEXT");
+    glad_glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC) load(userptr, "glDrawElementsInstancedEXT");
+    glad_glVertexAttribDivisorEXT = (PFNGLVERTEXATTRIBDIVISOREXTPROC) load(userptr, "glVertexAttribDivisorEXT");
+}
+static void glad_gl_load_GL_EXT_map_buffer_range( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_map_buffer_range) return;
+    glad_glFlushMappedBufferRangeEXT = (PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) load(userptr, "glFlushMappedBufferRangeEXT");
+    glad_glMapBufferRangeEXT = (PFNGLMAPBUFFERRANGEEXTPROC) load(userptr, "glMapBufferRangeEXT");
+}
+static void glad_gl_load_GL_EXT_memory_object( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_memory_object) return;
+    glad_glBufferStorageMemEXT = (PFNGLBUFFERSTORAGEMEMEXTPROC) load(userptr, "glBufferStorageMemEXT");
+    glad_glCreateMemoryObjectsEXT = (PFNGLCREATEMEMORYOBJECTSEXTPROC) load(userptr, "glCreateMemoryObjectsEXT");
+    glad_glDeleteMemoryObjectsEXT = (PFNGLDELETEMEMORYOBJECTSEXTPROC) load(userptr, "glDeleteMemoryObjectsEXT");
+    glad_glGetMemoryObjectParameterivEXT = (PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC) load(userptr, "glGetMemoryObjectParameterivEXT");
+    glad_glGetUnsignedBytei_vEXT = (PFNGLGETUNSIGNEDBYTEI_VEXTPROC) load(userptr, "glGetUnsignedBytei_vEXT");
+    glad_glGetUnsignedBytevEXT = (PFNGLGETUNSIGNEDBYTEVEXTPROC) load(userptr, "glGetUnsignedBytevEXT");
+    glad_glIsMemoryObjectEXT = (PFNGLISMEMORYOBJECTEXTPROC) load(userptr, "glIsMemoryObjectEXT");
+    glad_glMemoryObjectParameterivEXT = (PFNGLMEMORYOBJECTPARAMETERIVEXTPROC) load(userptr, "glMemoryObjectParameterivEXT");
+    glad_glNamedBufferStorageMemEXT = (PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC) load(userptr, "glNamedBufferStorageMemEXT");
+    glad_glTexStorageMem2DEXT = (PFNGLTEXSTORAGEMEM2DEXTPROC) load(userptr, "glTexStorageMem2DEXT");
+    glad_glTexStorageMem2DMultisampleEXT = (PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC) load(userptr, "glTexStorageMem2DMultisampleEXT");
+    glad_glTexStorageMem3DEXT = (PFNGLTEXSTORAGEMEM3DEXTPROC) load(userptr, "glTexStorageMem3DEXT");
+    glad_glTexStorageMem3DMultisampleEXT = (PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC) load(userptr, "glTexStorageMem3DMultisampleEXT");
+    glad_glTextureStorageMem2DEXT = (PFNGLTEXTURESTORAGEMEM2DEXTPROC) load(userptr, "glTextureStorageMem2DEXT");
+    glad_glTextureStorageMem2DMultisampleEXT = (PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC) load(userptr, "glTextureStorageMem2DMultisampleEXT");
+    glad_glTextureStorageMem3DEXT = (PFNGLTEXTURESTORAGEMEM3DEXTPROC) load(userptr, "glTextureStorageMem3DEXT");
+    glad_glTextureStorageMem3DMultisampleEXT = (PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC) load(userptr, "glTextureStorageMem3DMultisampleEXT");
+}
+static void glad_gl_load_GL_EXT_memory_object_fd( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_memory_object_fd) return;
+    glad_glImportMemoryFdEXT = (PFNGLIMPORTMEMORYFDEXTPROC) load(userptr, "glImportMemoryFdEXT");
+}
+static void glad_gl_load_GL_EXT_memory_object_win32( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_memory_object_win32) return;
+    glad_glImportMemoryWin32HandleEXT = (PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC) load(userptr, "glImportMemoryWin32HandleEXT");
+    glad_glImportMemoryWin32NameEXT = (PFNGLIMPORTMEMORYWIN32NAMEEXTPROC) load(userptr, "glImportMemoryWin32NameEXT");
+}
+static void glad_gl_load_GL_EXT_multi_draw_arrays( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_multi_draw_arrays) return;
+    glad_glMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC) load(userptr, "glMultiDrawArraysEXT");
+    glad_glMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC) load(userptr, "glMultiDrawElementsEXT");
+}
+static void glad_gl_load_GL_EXT_multi_draw_indirect( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_multi_draw_indirect) return;
+    glad_glMultiDrawArraysIndirectEXT = (PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC) load(userptr, "glMultiDrawArraysIndirectEXT");
+    glad_glMultiDrawElementsIndirectEXT = (PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC) load(userptr, "glMultiDrawElementsIndirectEXT");
+}
+static void glad_gl_load_GL_EXT_multisampled_render_to_texture( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_multisampled_render_to_texture) return;
+    glad_glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) load(userptr, "glFramebufferTexture2DMultisampleEXT");
+    glad_glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) load(userptr, "glRenderbufferStorageMultisampleEXT");
+}
+static void glad_gl_load_GL_EXT_multiview_draw_buffers( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_multiview_draw_buffers) return;
+    glad_glDrawBuffersIndexedEXT = (PFNGLDRAWBUFFERSINDEXEDEXTPROC) load(userptr, "glDrawBuffersIndexedEXT");
+    glad_glGetIntegeri_vEXT = (PFNGLGETINTEGERI_VEXTPROC) load(userptr, "glGetIntegeri_vEXT");
+    glad_glReadBufferIndexedEXT = (PFNGLREADBUFFERINDEXEDEXTPROC) load(userptr, "glReadBufferIndexedEXT");
+}
+static void glad_gl_load_GL_EXT_occlusion_query_boolean( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_occlusion_query_boolean) return;
+    glad_glBeginQueryEXT = (PFNGLBEGINQUERYEXTPROC) load(userptr, "glBeginQueryEXT");
+    glad_glDeleteQueriesEXT = (PFNGLDELETEQUERIESEXTPROC) load(userptr, "glDeleteQueriesEXT");
+    glad_glEndQueryEXT = (PFNGLENDQUERYEXTPROC) load(userptr, "glEndQueryEXT");
+    glad_glGenQueriesEXT = (PFNGLGENQUERIESEXTPROC) load(userptr, "glGenQueriesEXT");
+    glad_glGetQueryObjectuivEXT = (PFNGLGETQUERYOBJECTUIVEXTPROC) load(userptr, "glGetQueryObjectuivEXT");
+    glad_glGetQueryivEXT = (PFNGLGETQUERYIVEXTPROC) load(userptr, "glGetQueryivEXT");
+    glad_glIsQueryEXT = (PFNGLISQUERYEXTPROC) load(userptr, "glIsQueryEXT");
+}
+static void glad_gl_load_GL_EXT_polygon_offset_clamp( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_polygon_offset_clamp) return;
+    glad_glPolygonOffsetClampEXT = (PFNGLPOLYGONOFFSETCLAMPEXTPROC) load(userptr, "glPolygonOffsetClampEXT");
+}
+static void glad_gl_load_GL_EXT_primitive_bounding_box( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_primitive_bounding_box) return;
+    glad_glPrimitiveBoundingBoxEXT = (PFNGLPRIMITIVEBOUNDINGBOXEXTPROC) load(userptr, "glPrimitiveBoundingBoxEXT");
+}
+static void glad_gl_load_GL_EXT_raster_multisample( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_raster_multisample) return;
+    glad_glRasterSamplesEXT = (PFNGLRASTERSAMPLESEXTPROC) load(userptr, "glRasterSamplesEXT");
+}
+static void glad_gl_load_GL_EXT_robustness( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_robustness) return;
+    glad_glGetGraphicsResetStatusEXT = (PFNGLGETGRAPHICSRESETSTATUSEXTPROC) load(userptr, "glGetGraphicsResetStatusEXT");
+    glad_glGetnUniformfvEXT = (PFNGLGETNUNIFORMFVEXTPROC) load(userptr, "glGetnUniformfvEXT");
+    glad_glGetnUniformivEXT = (PFNGLGETNUNIFORMIVEXTPROC) load(userptr, "glGetnUniformivEXT");
+    glad_glReadnPixelsEXT = (PFNGLREADNPIXELSEXTPROC) load(userptr, "glReadnPixelsEXT");
+}
+static void glad_gl_load_GL_EXT_semaphore( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_semaphore) return;
+    glad_glDeleteSemaphoresEXT = (PFNGLDELETESEMAPHORESEXTPROC) load(userptr, "glDeleteSemaphoresEXT");
+    glad_glGenSemaphoresEXT = (PFNGLGENSEMAPHORESEXTPROC) load(userptr, "glGenSemaphoresEXT");
+    glad_glGetSemaphoreParameterui64vEXT = (PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC) load(userptr, "glGetSemaphoreParameterui64vEXT");
+    glad_glGetUnsignedBytei_vEXT = (PFNGLGETUNSIGNEDBYTEI_VEXTPROC) load(userptr, "glGetUnsignedBytei_vEXT");
+    glad_glGetUnsignedBytevEXT = (PFNGLGETUNSIGNEDBYTEVEXTPROC) load(userptr, "glGetUnsignedBytevEXT");
+    glad_glIsSemaphoreEXT = (PFNGLISSEMAPHOREEXTPROC) load(userptr, "glIsSemaphoreEXT");
+    glad_glSemaphoreParameterui64vEXT = (PFNGLSEMAPHOREPARAMETERUI64VEXTPROC) load(userptr, "glSemaphoreParameterui64vEXT");
+    glad_glSignalSemaphoreEXT = (PFNGLSIGNALSEMAPHOREEXTPROC) load(userptr, "glSignalSemaphoreEXT");
+    glad_glWaitSemaphoreEXT = (PFNGLWAITSEMAPHOREEXTPROC) load(userptr, "glWaitSemaphoreEXT");
+}
+static void glad_gl_load_GL_EXT_semaphore_fd( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_semaphore_fd) return;
+    glad_glImportSemaphoreFdEXT = (PFNGLIMPORTSEMAPHOREFDEXTPROC) load(userptr, "glImportSemaphoreFdEXT");
+}
+static void glad_gl_load_GL_EXT_semaphore_win32( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_semaphore_win32) return;
+    glad_glImportSemaphoreWin32HandleEXT = (PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC) load(userptr, "glImportSemaphoreWin32HandleEXT");
+    glad_glImportSemaphoreWin32NameEXT = (PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC) load(userptr, "glImportSemaphoreWin32NameEXT");
+}
+static void glad_gl_load_GL_EXT_separate_shader_objects( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_separate_shader_objects) return;
+    glad_glActiveShaderProgramEXT = (PFNGLACTIVESHADERPROGRAMEXTPROC) load(userptr, "glActiveShaderProgramEXT");
+    glad_glBindProgramPipelineEXT = (PFNGLBINDPROGRAMPIPELINEEXTPROC) load(userptr, "glBindProgramPipelineEXT");
+    glad_glCreateShaderProgramvEXT = (PFNGLCREATESHADERPROGRAMVEXTPROC) load(userptr, "glCreateShaderProgramvEXT");
+    glad_glDeleteProgramPipelinesEXT = (PFNGLDELETEPROGRAMPIPELINESEXTPROC) load(userptr, "glDeleteProgramPipelinesEXT");
+    glad_glGenProgramPipelinesEXT = (PFNGLGENPROGRAMPIPELINESEXTPROC) load(userptr, "glGenProgramPipelinesEXT");
+    glad_glGetProgramPipelineInfoLogEXT = (PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) load(userptr, "glGetProgramPipelineInfoLogEXT");
+    glad_glGetProgramPipelineivEXT = (PFNGLGETPROGRAMPIPELINEIVEXTPROC) load(userptr, "glGetProgramPipelineivEXT");
+    glad_glIsProgramPipelineEXT = (PFNGLISPROGRAMPIPELINEEXTPROC) load(userptr, "glIsProgramPipelineEXT");
+    glad_glProgramParameteriEXT = (PFNGLPROGRAMPARAMETERIEXTPROC) load(userptr, "glProgramParameteriEXT");
+    glad_glProgramUniform1fEXT = (PFNGLPROGRAMUNIFORM1FEXTPROC) load(userptr, "glProgramUniform1fEXT");
+    glad_glProgramUniform1fvEXT = (PFNGLPROGRAMUNIFORM1FVEXTPROC) load(userptr, "glProgramUniform1fvEXT");
+    glad_glProgramUniform1iEXT = (PFNGLPROGRAMUNIFORM1IEXTPROC) load(userptr, "glProgramUniform1iEXT");
+    glad_glProgramUniform1ivEXT = (PFNGLPROGRAMUNIFORM1IVEXTPROC) load(userptr, "glProgramUniform1ivEXT");
+    glad_glProgramUniform1uiEXT = (PFNGLPROGRAMUNIFORM1UIEXTPROC) load(userptr, "glProgramUniform1uiEXT");
+    glad_glProgramUniform1uivEXT = (PFNGLPROGRAMUNIFORM1UIVEXTPROC) load(userptr, "glProgramUniform1uivEXT");
+    glad_glProgramUniform2fEXT = (PFNGLPROGRAMUNIFORM2FEXTPROC) load(userptr, "glProgramUniform2fEXT");
+    glad_glProgramUniform2fvEXT = (PFNGLPROGRAMUNIFORM2FVEXTPROC) load(userptr, "glProgramUniform2fvEXT");
+    glad_glProgramUniform2iEXT = (PFNGLPROGRAMUNIFORM2IEXTPROC) load(userptr, "glProgramUniform2iEXT");
+    glad_glProgramUniform2ivEXT = (PFNGLPROGRAMUNIFORM2IVEXTPROC) load(userptr, "glProgramUniform2ivEXT");
+    glad_glProgramUniform2uiEXT = (PFNGLPROGRAMUNIFORM2UIEXTPROC) load(userptr, "glProgramUniform2uiEXT");
+    glad_glProgramUniform2uivEXT = (PFNGLPROGRAMUNIFORM2UIVEXTPROC) load(userptr, "glProgramUniform2uivEXT");
+    glad_glProgramUniform3fEXT = (PFNGLPROGRAMUNIFORM3FEXTPROC) load(userptr, "glProgramUniform3fEXT");
+    glad_glProgramUniform3fvEXT = (PFNGLPROGRAMUNIFORM3FVEXTPROC) load(userptr, "glProgramUniform3fvEXT");
+    glad_glProgramUniform3iEXT = (PFNGLPROGRAMUNIFORM3IEXTPROC) load(userptr, "glProgramUniform3iEXT");
+    glad_glProgramUniform3ivEXT = (PFNGLPROGRAMUNIFORM3IVEXTPROC) load(userptr, "glProgramUniform3ivEXT");
+    glad_glProgramUniform3uiEXT = (PFNGLPROGRAMUNIFORM3UIEXTPROC) load(userptr, "glProgramUniform3uiEXT");
+    glad_glProgramUniform3uivEXT = (PFNGLPROGRAMUNIFORM3UIVEXTPROC) load(userptr, "glProgramUniform3uivEXT");
+    glad_glProgramUniform4fEXT = (PFNGLPROGRAMUNIFORM4FEXTPROC) load(userptr, "glProgramUniform4fEXT");
+    glad_glProgramUniform4fvEXT = (PFNGLPROGRAMUNIFORM4FVEXTPROC) load(userptr, "glProgramUniform4fvEXT");
+    glad_glProgramUniform4iEXT = (PFNGLPROGRAMUNIFORM4IEXTPROC) load(userptr, "glProgramUniform4iEXT");
+    glad_glProgramUniform4ivEXT = (PFNGLPROGRAMUNIFORM4IVEXTPROC) load(userptr, "glProgramUniform4ivEXT");
+    glad_glProgramUniform4uiEXT = (PFNGLPROGRAMUNIFORM4UIEXTPROC) load(userptr, "glProgramUniform4uiEXT");
+    glad_glProgramUniform4uivEXT = (PFNGLPROGRAMUNIFORM4UIVEXTPROC) load(userptr, "glProgramUniform4uivEXT");
+    glad_glProgramUniformMatrix2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) load(userptr, "glProgramUniformMatrix2fvEXT");
+    glad_glProgramUniformMatrix2x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) load(userptr, "glProgramUniformMatrix2x3fvEXT");
+    glad_glProgramUniformMatrix2x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) load(userptr, "glProgramUniformMatrix2x4fvEXT");
+    glad_glProgramUniformMatrix3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) load(userptr, "glProgramUniformMatrix3fvEXT");
+    glad_glProgramUniformMatrix3x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) load(userptr, "glProgramUniformMatrix3x2fvEXT");
+    glad_glProgramUniformMatrix3x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) load(userptr, "glProgramUniformMatrix3x4fvEXT");
+    glad_glProgramUniformMatrix4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) load(userptr, "glProgramUniformMatrix4fvEXT");
+    glad_glProgramUniformMatrix4x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) load(userptr, "glProgramUniformMatrix4x2fvEXT");
+    glad_glProgramUniformMatrix4x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) load(userptr, "glProgramUniformMatrix4x3fvEXT");
+    glad_glUseProgramStagesEXT = (PFNGLUSEPROGRAMSTAGESEXTPROC) load(userptr, "glUseProgramStagesEXT");
+    glad_glValidateProgramPipelineEXT = (PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) load(userptr, "glValidateProgramPipelineEXT");
+}
+static void glad_gl_load_GL_EXT_shader_framebuffer_fetch_non_coherent( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_shader_framebuffer_fetch_non_coherent) return;
+    glad_glFramebufferFetchBarrierEXT = (PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC) load(userptr, "glFramebufferFetchBarrierEXT");
+}
+static void glad_gl_load_GL_EXT_shader_pixel_local_storage2( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_shader_pixel_local_storage2) return;
+    glad_glClearPixelLocalStorageuiEXT = (PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC) load(userptr, "glClearPixelLocalStorageuiEXT");
+    glad_glFramebufferPixelLocalStorageSizeEXT = (PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) load(userptr, "glFramebufferPixelLocalStorageSizeEXT");
+    glad_glGetFramebufferPixelLocalStorageSizeEXT = (PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) load(userptr, "glGetFramebufferPixelLocalStorageSizeEXT");
+}
+static void glad_gl_load_GL_EXT_sparse_texture( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_sparse_texture) return;
+    glad_glTexPageCommitmentEXT = (PFNGLTEXPAGECOMMITMENTEXTPROC) load(userptr, "glTexPageCommitmentEXT");
+}
+static void glad_gl_load_GL_EXT_tessellation_shader( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_tessellation_shader) return;
+    glad_glPatchParameteriEXT = (PFNGLPATCHPARAMETERIEXTPROC) load(userptr, "glPatchParameteriEXT");
+}
+static void glad_gl_load_GL_EXT_texture_border_clamp( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_texture_border_clamp) return;
+    glad_glGetSamplerParameterIivEXT = (PFNGLGETSAMPLERPARAMETERIIVEXTPROC) load(userptr, "glGetSamplerParameterIivEXT");
+    glad_glGetSamplerParameterIuivEXT = (PFNGLGETSAMPLERPARAMETERIUIVEXTPROC) load(userptr, "glGetSamplerParameterIuivEXT");
+    glad_glGetTexParameterIivEXT = (PFNGLGETTEXPARAMETERIIVEXTPROC) load(userptr, "glGetTexParameterIivEXT");
+    glad_glGetTexParameterIuivEXT = (PFNGLGETTEXPARAMETERIUIVEXTPROC) load(userptr, "glGetTexParameterIuivEXT");
+    glad_glSamplerParameterIivEXT = (PFNGLSAMPLERPARAMETERIIVEXTPROC) load(userptr, "glSamplerParameterIivEXT");
+    glad_glSamplerParameterIuivEXT = (PFNGLSAMPLERPARAMETERIUIVEXTPROC) load(userptr, "glSamplerParameterIuivEXT");
+    glad_glTexParameterIivEXT = (PFNGLTEXPARAMETERIIVEXTPROC) load(userptr, "glTexParameterIivEXT");
+    glad_glTexParameterIuivEXT = (PFNGLTEXPARAMETERIUIVEXTPROC) load(userptr, "glTexParameterIuivEXT");
+}
+static void glad_gl_load_GL_EXT_texture_buffer( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_texture_buffer) return;
+    glad_glTexBufferEXT = (PFNGLTEXBUFFEREXTPROC) load(userptr, "glTexBufferEXT");
+    glad_glTexBufferRangeEXT = (PFNGLTEXBUFFERRANGEEXTPROC) load(userptr, "glTexBufferRangeEXT");
+}
+static void glad_gl_load_GL_EXT_texture_storage( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_texture_storage) return;
+    glad_glTexStorage1DEXT = (PFNGLTEXSTORAGE1DEXTPROC) load(userptr, "glTexStorage1DEXT");
+    glad_glTexStorage2DEXT = (PFNGLTEXSTORAGE2DEXTPROC) load(userptr, "glTexStorage2DEXT");
+    glad_glTexStorage3DEXT = (PFNGLTEXSTORAGE3DEXTPROC) load(userptr, "glTexStorage3DEXT");
+    glad_glTextureStorage1DEXT = (PFNGLTEXTURESTORAGE1DEXTPROC) load(userptr, "glTextureStorage1DEXT");
+    glad_glTextureStorage2DEXT = (PFNGLTEXTURESTORAGE2DEXTPROC) load(userptr, "glTextureStorage2DEXT");
+    glad_glTextureStorage3DEXT = (PFNGLTEXTURESTORAGE3DEXTPROC) load(userptr, "glTextureStorage3DEXT");
+}
+static void glad_gl_load_GL_EXT_texture_storage_compression( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_texture_storage_compression) return;
+    glad_glTexStorageAttribs2DEXT = (PFNGLTEXSTORAGEATTRIBS2DEXTPROC) load(userptr, "glTexStorageAttribs2DEXT");
+    glad_glTexStorageAttribs3DEXT = (PFNGLTEXSTORAGEATTRIBS3DEXTPROC) load(userptr, "glTexStorageAttribs3DEXT");
+}
+static void glad_gl_load_GL_EXT_texture_view( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_texture_view) return;
+    glad_glTextureViewEXT = (PFNGLTEXTUREVIEWEXTPROC) load(userptr, "glTextureViewEXT");
+}
+static void glad_gl_load_GL_EXT_win32_keyed_mutex( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_win32_keyed_mutex) return;
+    glad_glAcquireKeyedMutexWin32EXT = (PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC) load(userptr, "glAcquireKeyedMutexWin32EXT");
+    glad_glReleaseKeyedMutexWin32EXT = (PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC) load(userptr, "glReleaseKeyedMutexWin32EXT");
+}
+static void glad_gl_load_GL_EXT_window_rectangles( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_EXT_window_rectangles) return;
+    glad_glWindowRectanglesEXT = (PFNGLWINDOWRECTANGLESEXTPROC) load(userptr, "glWindowRectanglesEXT");
+}
+static void glad_gl_load_GL_KHR_blend_equation_advanced( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_KHR_blend_equation_advanced) return;
+    glad_glBlendBarrierKHR = (PFNGLBLENDBARRIERKHRPROC) load(userptr, "glBlendBarrierKHR");
+}
+static void glad_gl_load_GL_KHR_debug( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_KHR_debug) return;
+    glad_glDebugMessageCallbackKHR = (PFNGLDEBUGMESSAGECALLBACKKHRPROC) load(userptr, "glDebugMessageCallbackKHR");
+    glad_glDebugMessageControlKHR = (PFNGLDEBUGMESSAGECONTROLKHRPROC) load(userptr, "glDebugMessageControlKHR");
+    glad_glDebugMessageInsertKHR = (PFNGLDEBUGMESSAGEINSERTKHRPROC) load(userptr, "glDebugMessageInsertKHR");
+    glad_glGetDebugMessageLogKHR = (PFNGLGETDEBUGMESSAGELOGKHRPROC) load(userptr, "glGetDebugMessageLogKHR");
+    glad_glGetObjectLabelKHR = (PFNGLGETOBJECTLABELKHRPROC) load(userptr, "glGetObjectLabelKHR");
+    glad_glGetObjectPtrLabelKHR = (PFNGLGETOBJECTPTRLABELKHRPROC) load(userptr, "glGetObjectPtrLabelKHR");
+    glad_glGetPointervKHR = (PFNGLGETPOINTERVKHRPROC) load(userptr, "glGetPointervKHR");
+    glad_glObjectLabelKHR = (PFNGLOBJECTLABELKHRPROC) load(userptr, "glObjectLabelKHR");
+    glad_glObjectPtrLabelKHR = (PFNGLOBJECTPTRLABELKHRPROC) load(userptr, "glObjectPtrLabelKHR");
+    glad_glPopDebugGroupKHR = (PFNGLPOPDEBUGGROUPKHRPROC) load(userptr, "glPopDebugGroupKHR");
+    glad_glPushDebugGroupKHR = (PFNGLPUSHDEBUGGROUPKHRPROC) load(userptr, "glPushDebugGroupKHR");
+}
+static void glad_gl_load_GL_KHR_parallel_shader_compile( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_KHR_parallel_shader_compile) return;
+    glad_glMaxShaderCompilerThreadsKHR = (PFNGLMAXSHADERCOMPILERTHREADSKHRPROC) load(userptr, "glMaxShaderCompilerThreadsKHR");
+}
+static void glad_gl_load_GL_KHR_robustness( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_KHR_robustness) return;
+    glad_glGetGraphicsResetStatusKHR = (PFNGLGETGRAPHICSRESETSTATUSKHRPROC) load(userptr, "glGetGraphicsResetStatusKHR");
+    glad_glGetnUniformfvKHR = (PFNGLGETNUNIFORMFVKHRPROC) load(userptr, "glGetnUniformfvKHR");
+    glad_glGetnUniformivKHR = (PFNGLGETNUNIFORMIVKHRPROC) load(userptr, "glGetnUniformivKHR");
+    glad_glGetnUniformuivKHR = (PFNGLGETNUNIFORMUIVKHRPROC) load(userptr, "glGetnUniformuivKHR");
+    glad_glReadnPixelsKHR = (PFNGLREADNPIXELSKHRPROC) load(userptr, "glReadnPixelsKHR");
+}
+static void glad_gl_load_GL_OES_EGL_image( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_EGL_image) return;
+    glad_glEGLImageTargetRenderbufferStorageOES = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) load(userptr, "glEGLImageTargetRenderbufferStorageOES");
+    glad_glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) load(userptr, "glEGLImageTargetTexture2DOES");
+}
+static void glad_gl_load_GL_OES_copy_image( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_copy_image) return;
+    glad_glCopyImageSubDataOES = (PFNGLCOPYIMAGESUBDATAOESPROC) load(userptr, "glCopyImageSubDataOES");
+}
+static void glad_gl_load_GL_OES_draw_buffers_indexed( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_draw_buffers_indexed) return;
+    glad_glBlendEquationSeparateiOES = (PFNGLBLENDEQUATIONSEPARATEIOESPROC) load(userptr, "glBlendEquationSeparateiOES");
+    glad_glBlendEquationiOES = (PFNGLBLENDEQUATIONIOESPROC) load(userptr, "glBlendEquationiOES");
+    glad_glBlendFuncSeparateiOES = (PFNGLBLENDFUNCSEPARATEIOESPROC) load(userptr, "glBlendFuncSeparateiOES");
+    glad_glBlendFunciOES = (PFNGLBLENDFUNCIOESPROC) load(userptr, "glBlendFunciOES");
+    glad_glColorMaskiOES = (PFNGLCOLORMASKIOESPROC) load(userptr, "glColorMaskiOES");
+    glad_glDisableiOES = (PFNGLDISABLEIOESPROC) load(userptr, "glDisableiOES");
+    glad_glEnableiOES = (PFNGLENABLEIOESPROC) load(userptr, "glEnableiOES");
+    glad_glIsEnablediOES = (PFNGLISENABLEDIOESPROC) load(userptr, "glIsEnablediOES");
+}
+static void glad_gl_load_GL_OES_draw_elements_base_vertex( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_draw_elements_base_vertex) return;
+    glad_glDrawElementsBaseVertexOES = (PFNGLDRAWELEMENTSBASEVERTEXOESPROC) load(userptr, "glDrawElementsBaseVertexOES");
+    glad_glDrawElementsInstancedBaseVertexOES = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) load(userptr, "glDrawElementsInstancedBaseVertexOES");
+    glad_glDrawRangeElementsBaseVertexOES = (PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) load(userptr, "glDrawRangeElementsBaseVertexOES");
+    glad_glMultiDrawElementsBaseVertexEXT = (PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) load(userptr, "glMultiDrawElementsBaseVertexEXT");
+}
+static void glad_gl_load_GL_OES_geometry_shader( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_geometry_shader) return;
+    glad_glFramebufferTextureOES = (PFNGLFRAMEBUFFERTEXTUREOESPROC) load(userptr, "glFramebufferTextureOES");
+}
+static void glad_gl_load_GL_OES_get_program_binary( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_get_program_binary) return;
+    glad_glGetProgramBinaryOES = (PFNGLGETPROGRAMBINARYOESPROC) load(userptr, "glGetProgramBinaryOES");
+    glad_glProgramBinaryOES = (PFNGLPROGRAMBINARYOESPROC) load(userptr, "glProgramBinaryOES");
+}
+static void glad_gl_load_GL_OES_mapbuffer( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_mapbuffer) return;
+    glad_glGetBufferPointervOES = (PFNGLGETBUFFERPOINTERVOESPROC) load(userptr, "glGetBufferPointervOES");
+    glad_glMapBufferOES = (PFNGLMAPBUFFEROESPROC) load(userptr, "glMapBufferOES");
+    glad_glUnmapBufferOES = (PFNGLUNMAPBUFFEROESPROC) load(userptr, "glUnmapBufferOES");
+}
+static void glad_gl_load_GL_OES_primitive_bounding_box( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_primitive_bounding_box) return;
+    glad_glPrimitiveBoundingBoxOES = (PFNGLPRIMITIVEBOUNDINGBOXOESPROC) load(userptr, "glPrimitiveBoundingBoxOES");
+}
+static void glad_gl_load_GL_OES_sample_shading( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_sample_shading) return;
+    glad_glMinSampleShadingOES = (PFNGLMINSAMPLESHADINGOESPROC) load(userptr, "glMinSampleShadingOES");
+}
+static void glad_gl_load_GL_OES_tessellation_shader( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_tessellation_shader) return;
+    glad_glPatchParameteriOES = (PFNGLPATCHPARAMETERIOESPROC) load(userptr, "glPatchParameteriOES");
+}
+static void glad_gl_load_GL_OES_texture_3D( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_texture_3D) return;
+    glad_glCompressedTexImage3DOES = (PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) load(userptr, "glCompressedTexImage3DOES");
+    glad_glCompressedTexSubImage3DOES = (PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) load(userptr, "glCompressedTexSubImage3DOES");
+    glad_glCopyTexSubImage3DOES = (PFNGLCOPYTEXSUBIMAGE3DOESPROC) load(userptr, "glCopyTexSubImage3DOES");
+    glad_glFramebufferTexture3DOES = (PFNGLFRAMEBUFFERTEXTURE3DOESPROC) load(userptr, "glFramebufferTexture3DOES");
+    glad_glTexImage3DOES = (PFNGLTEXIMAGE3DOESPROC) load(userptr, "glTexImage3DOES");
+    glad_glTexSubImage3DOES = (PFNGLTEXSUBIMAGE3DOESPROC) load(userptr, "glTexSubImage3DOES");
+}
+static void glad_gl_load_GL_OES_texture_border_clamp( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_texture_border_clamp) return;
+    glad_glGetSamplerParameterIivOES = (PFNGLGETSAMPLERPARAMETERIIVOESPROC) load(userptr, "glGetSamplerParameterIivOES");
+    glad_glGetSamplerParameterIuivOES = (PFNGLGETSAMPLERPARAMETERIUIVOESPROC) load(userptr, "glGetSamplerParameterIuivOES");
+    glad_glGetTexParameterIivOES = (PFNGLGETTEXPARAMETERIIVOESPROC) load(userptr, "glGetTexParameterIivOES");
+    glad_glGetTexParameterIuivOES = (PFNGLGETTEXPARAMETERIUIVOESPROC) load(userptr, "glGetTexParameterIuivOES");
+    glad_glSamplerParameterIivOES = (PFNGLSAMPLERPARAMETERIIVOESPROC) load(userptr, "glSamplerParameterIivOES");
+    glad_glSamplerParameterIuivOES = (PFNGLSAMPLERPARAMETERIUIVOESPROC) load(userptr, "glSamplerParameterIuivOES");
+    glad_glTexParameterIivOES = (PFNGLTEXPARAMETERIIVOESPROC) load(userptr, "glTexParameterIivOES");
+    glad_glTexParameterIuivOES = (PFNGLTEXPARAMETERIUIVOESPROC) load(userptr, "glTexParameterIuivOES");
+}
+static void glad_gl_load_GL_OES_texture_buffer( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_texture_buffer) return;
+    glad_glTexBufferOES = (PFNGLTEXBUFFEROESPROC) load(userptr, "glTexBufferOES");
+    glad_glTexBufferRangeOES = (PFNGLTEXBUFFERRANGEOESPROC) load(userptr, "glTexBufferRangeOES");
+}
+static void glad_gl_load_GL_OES_texture_storage_multisample_2d_array( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_texture_storage_multisample_2d_array) return;
+    glad_glTexStorage3DMultisampleOES = (PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC) load(userptr, "glTexStorage3DMultisampleOES");
+}
+static void glad_gl_load_GL_OES_texture_view( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_texture_view) return;
+    glad_glTextureViewOES = (PFNGLTEXTUREVIEWOESPROC) load(userptr, "glTextureViewOES");
+}
+static void glad_gl_load_GL_OES_vertex_array_object( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_vertex_array_object) return;
+    glad_glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC) load(userptr, "glBindVertexArrayOES");
+    glad_glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC) load(userptr, "glDeleteVertexArraysOES");
+    glad_glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC) load(userptr, "glGenVertexArraysOES");
+    glad_glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC) load(userptr, "glIsVertexArrayOES");
+}
+static void glad_gl_load_GL_OES_viewport_array( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_OES_viewport_array) return;
+    glad_glDepthRangeArrayfvOES = (PFNGLDEPTHRANGEARRAYFVOESPROC) load(userptr, "glDepthRangeArrayfvOES");
+    glad_glDepthRangeIndexedfOES = (PFNGLDEPTHRANGEINDEXEDFOESPROC) load(userptr, "glDepthRangeIndexedfOES");
+    glad_glDisableiOES = (PFNGLDISABLEIOESPROC) load(userptr, "glDisableiOES");
+    glad_glEnableiOES = (PFNGLENABLEIOESPROC) load(userptr, "glEnableiOES");
+    glad_glGetFloati_vOES = (PFNGLGETFLOATI_VOESPROC) load(userptr, "glGetFloati_vOES");
+    glad_glIsEnablediOES = (PFNGLISENABLEDIOESPROC) load(userptr, "glIsEnablediOES");
+    glad_glScissorArrayvOES = (PFNGLSCISSORARRAYVOESPROC) load(userptr, "glScissorArrayvOES");
+    glad_glScissorIndexedOES = (PFNGLSCISSORINDEXEDOESPROC) load(userptr, "glScissorIndexedOES");
+    glad_glScissorIndexedvOES = (PFNGLSCISSORINDEXEDVOESPROC) load(userptr, "glScissorIndexedvOES");
+    glad_glViewportArrayvOES = (PFNGLVIEWPORTARRAYVOESPROC) load(userptr, "glViewportArrayvOES");
+    glad_glViewportIndexedfOES = (PFNGLVIEWPORTINDEXEDFOESPROC) load(userptr, "glViewportIndexedfOES");
+    glad_glViewportIndexedfvOES = (PFNGLVIEWPORTINDEXEDFVOESPROC) load(userptr, "glViewportIndexedfvOES");
+}
+
+
+
+#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
+#define GLAD_GL_IS_SOME_NEW_VERSION 1
+#else
+#define GLAD_GL_IS_SOME_NEW_VERSION 0
+#endif
+
+static int glad_gl_get_extensions( int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) {
+#if GLAD_GL_IS_SOME_NEW_VERSION
+    if(GLAD_VERSION_MAJOR(version) < 3) {
+#else
+    GLAD_UNUSED(version);
+    GLAD_UNUSED(out_num_exts_i);
+    GLAD_UNUSED(out_exts_i);
+#endif
+        if (glad_glGetString == NULL) {
+            return 0;
+        }
+        *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS);
+#if GLAD_GL_IS_SOME_NEW_VERSION
+    } else {
+        unsigned int index = 0;
+        unsigned int num_exts_i = 0;
+        char **exts_i = NULL;
+        if (glad_glGetStringi == NULL || glad_glGetIntegerv == NULL) {
+            return 0;
+        }
+        glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i);
+        if (num_exts_i > 0) {
+            exts_i = (char **) malloc(num_exts_i * (sizeof *exts_i));
+        }
+        if (exts_i == NULL) {
+            return 0;
+        }
+        for(index = 0; index < num_exts_i; index++) {
+            const char *gl_str_tmp = (const char*) glad_glGetStringi(GL_EXTENSIONS, index);
+            size_t len = strlen(gl_str_tmp) + 1;
+
+            char *local_str = (char*) malloc(len * sizeof(char));
+            if(local_str != NULL) {
+                memcpy(local_str, gl_str_tmp, len * sizeof(char));
+            }
+
+            exts_i[index] = local_str;
+        }
+
+        *out_num_exts_i = num_exts_i;
+        *out_exts_i = exts_i;
+    }
+#endif
+    return 1;
+}
+static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) {
+    if (exts_i != NULL) {
+        unsigned int index;
+        for(index = 0; index < num_exts_i; index++) {
+            free((void *) (exts_i[index]));
+        }
+        free((void *)exts_i);
+        exts_i = NULL;
+    }
+}
+static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) {
+    if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) {
+        const char *extensions;
+        const char *loc;
+        const char *terminator;
+        extensions = exts;
+        if(extensions == NULL || ext == NULL) {
+            return 0;
+        }
+        while(1) {
+            loc = strstr(extensions, ext);
+            if(loc == NULL) {
+                return 0;
+            }
+            terminator = loc + strlen(ext);
+            if((loc == extensions || *(loc - 1) == ' ') &&
+                (*terminator == ' ' || *terminator == '\0')) {
+                return 1;
+            }
+            extensions = terminator;
+        }
+    } else {
+        unsigned int index;
+        for(index = 0; index < num_exts_i; index++) {
+            const char *e = exts_i[index];
+            if(strcmp(e, ext) == 0) {
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) {
+    return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static int glad_gl_find_extensions_gles2( int version) {
+    const char *exts = NULL;
+    unsigned int num_exts_i = 0;
+    char **exts_i = NULL;
+    if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0;
+
+    GLAD_GL_EXT_EGL_image_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_EGL_image_array");
+    GLAD_GL_EXT_EGL_image_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_EGL_image_storage");
+    GLAD_GL_EXT_EGL_image_storage_compression = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_EGL_image_storage_compression");
+    GLAD_GL_EXT_YUV_target = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_YUV_target");
+    GLAD_GL_EXT_base_instance = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_base_instance");
+    GLAD_GL_EXT_blend_func_extended = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_blend_func_extended");
+    GLAD_GL_EXT_blend_minmax = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_blend_minmax");
+    GLAD_GL_EXT_buffer_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_buffer_storage");
+    GLAD_GL_EXT_clear_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_clear_texture");
+    GLAD_GL_EXT_clip_control = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_clip_control");
+    GLAD_GL_EXT_clip_cull_distance = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_clip_cull_distance");
+    GLAD_GL_EXT_color_buffer_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_color_buffer_float");
+    GLAD_GL_EXT_color_buffer_half_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_color_buffer_half_float");
+    GLAD_GL_EXT_conservative_depth = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_conservative_depth");
+    GLAD_GL_EXT_copy_image = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_copy_image");
+    GLAD_GL_EXT_debug_label = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_debug_label");
+    GLAD_GL_EXT_debug_marker = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_debug_marker");
+    GLAD_GL_EXT_depth_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_depth_clamp");
+    GLAD_GL_EXT_discard_framebuffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_discard_framebuffer");
+    GLAD_GL_EXT_disjoint_timer_query = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_disjoint_timer_query");
+    GLAD_GL_EXT_draw_buffers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_buffers");
+    GLAD_GL_EXT_draw_buffers_indexed = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_buffers_indexed");
+    GLAD_GL_EXT_draw_elements_base_vertex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_elements_base_vertex");
+    GLAD_GL_EXT_draw_instanced = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_instanced");
+    GLAD_GL_EXT_draw_transform_feedback = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_transform_feedback");
+    GLAD_GL_EXT_external_buffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_external_buffer");
+    GLAD_GL_EXT_float_blend = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_float_blend");
+    GLAD_GL_EXT_fragment_shading_rate = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_fragment_shading_rate");
+    GLAD_GL_EXT_geometry_point_size = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_geometry_point_size");
+    GLAD_GL_EXT_geometry_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_geometry_shader");
+    GLAD_GL_EXT_gpu_shader5 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_gpu_shader5");
+    GLAD_GL_EXT_instanced_arrays = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_instanced_arrays");
+    GLAD_GL_EXT_map_buffer_range = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_map_buffer_range");
+    GLAD_GL_EXT_memory_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_memory_object");
+    GLAD_GL_EXT_memory_object_fd = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_memory_object_fd");
+    GLAD_GL_EXT_memory_object_win32 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_memory_object_win32");
+    GLAD_GL_EXT_multi_draw_arrays = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multi_draw_arrays");
+    GLAD_GL_EXT_multi_draw_indirect = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multi_draw_indirect");
+    GLAD_GL_EXT_multisampled_compatibility = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multisampled_compatibility");
+    GLAD_GL_EXT_multisampled_render_to_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multisampled_render_to_texture");
+    GLAD_GL_EXT_multisampled_render_to_texture2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multisampled_render_to_texture2");
+    GLAD_GL_EXT_multiview_draw_buffers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multiview_draw_buffers");
+    GLAD_GL_EXT_multiview_tessellation_geometry_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multiview_tessellation_geometry_shader");
+    GLAD_GL_EXT_multiview_texture_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multiview_texture_multisample");
+    GLAD_GL_EXT_multiview_timer_query = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multiview_timer_query");
+    GLAD_GL_EXT_occlusion_query_boolean = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_occlusion_query_boolean");
+    GLAD_GL_EXT_polygon_offset_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_polygon_offset_clamp");
+    GLAD_GL_EXT_post_depth_coverage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_post_depth_coverage");
+    GLAD_GL_EXT_primitive_bounding_box = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_primitive_bounding_box");
+    GLAD_GL_EXT_protected_textures = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_protected_textures");
+    GLAD_GL_EXT_pvrtc_sRGB = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_pvrtc_sRGB");
+    GLAD_GL_EXT_raster_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_raster_multisample");
+    GLAD_GL_EXT_read_format_bgra = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_read_format_bgra");
+    GLAD_GL_EXT_render_snorm = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_render_snorm");
+    GLAD_GL_EXT_robustness = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_robustness");
+    GLAD_GL_EXT_sRGB = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_sRGB");
+    GLAD_GL_EXT_sRGB_write_control = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_sRGB_write_control");
+    GLAD_GL_EXT_semaphore = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_semaphore");
+    GLAD_GL_EXT_semaphore_fd = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_semaphore_fd");
+    GLAD_GL_EXT_semaphore_win32 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_semaphore_win32");
+    GLAD_GL_EXT_separate_depth_stencil = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_separate_depth_stencil");
+    GLAD_GL_EXT_separate_shader_objects = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_separate_shader_objects");
+    GLAD_GL_EXT_shader_framebuffer_fetch = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_framebuffer_fetch");
+    GLAD_GL_EXT_shader_framebuffer_fetch_non_coherent = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_framebuffer_fetch_non_coherent");
+    GLAD_GL_EXT_shader_group_vote = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_group_vote");
+    GLAD_GL_EXT_shader_implicit_conversions = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_implicit_conversions");
+    GLAD_GL_EXT_shader_integer_mix = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_integer_mix");
+    GLAD_GL_EXT_shader_io_blocks = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_io_blocks");
+    GLAD_GL_EXT_shader_non_constant_global_initializers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_non_constant_global_initializers");
+    GLAD_GL_EXT_shader_pixel_local_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_pixel_local_storage");
+    GLAD_GL_EXT_shader_pixel_local_storage2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_pixel_local_storage2");
+    GLAD_GL_EXT_shader_samples_identical = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_samples_identical");
+    GLAD_GL_EXT_shader_texture_lod = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_texture_lod");
+    GLAD_GL_EXT_shadow_samplers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shadow_samplers");
+    GLAD_GL_EXT_sparse_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_sparse_texture");
+    GLAD_GL_EXT_sparse_texture2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_sparse_texture2");
+    GLAD_GL_EXT_tessellation_point_size = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_tessellation_point_size");
+    GLAD_GL_EXT_tessellation_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_tessellation_shader");
+    GLAD_GL_EXT_texture_border_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_border_clamp");
+    GLAD_GL_EXT_texture_buffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_buffer");
+    GLAD_GL_EXT_texture_compression_astc_decode_mode = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_astc_decode_mode");
+    GLAD_GL_EXT_texture_compression_bptc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_bptc");
+    GLAD_GL_EXT_texture_compression_dxt1 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_dxt1");
+    GLAD_GL_EXT_texture_compression_rgtc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_rgtc");
+    GLAD_GL_EXT_texture_compression_s3tc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_s3tc");
+    GLAD_GL_EXT_texture_compression_s3tc_srgb = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_s3tc_srgb");
+    GLAD_GL_EXT_texture_cube_map_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_cube_map_array");
+    GLAD_GL_EXT_texture_filter_anisotropic = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_filter_anisotropic");
+    GLAD_GL_EXT_texture_filter_minmax = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_filter_minmax");
+    GLAD_GL_EXT_texture_format_BGRA8888 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_format_BGRA8888");
+    GLAD_GL_EXT_texture_format_sRGB_override = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_format_sRGB_override");
+    GLAD_GL_EXT_texture_mirror_clamp_to_edge = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_mirror_clamp_to_edge");
+    GLAD_GL_EXT_texture_norm16 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_norm16");
+    GLAD_GL_EXT_texture_query_lod = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_query_lod");
+    GLAD_GL_EXT_texture_rg = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_rg");
+    GLAD_GL_EXT_texture_sRGB_R8 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_sRGB_R8");
+    GLAD_GL_EXT_texture_sRGB_RG8 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_sRGB_RG8");
+    GLAD_GL_EXT_texture_sRGB_decode = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_sRGB_decode");
+    GLAD_GL_EXT_texture_shadow_lod = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_shadow_lod");
+    GLAD_GL_EXT_texture_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_storage");
+    GLAD_GL_EXT_texture_storage_compression = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_storage_compression");
+    GLAD_GL_EXT_texture_type_2_10_10_10_REV = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_type_2_10_10_10_REV");
+    GLAD_GL_EXT_texture_view = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_view");
+    GLAD_GL_EXT_unpack_subimage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_unpack_subimage");
+    GLAD_GL_EXT_win32_keyed_mutex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_win32_keyed_mutex");
+    GLAD_GL_EXT_window_rectangles = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_window_rectangles");
+    GLAD_GL_KHR_blend_equation_advanced = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_blend_equation_advanced");
+    GLAD_GL_KHR_blend_equation_advanced_coherent = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_blend_equation_advanced_coherent");
+    GLAD_GL_KHR_context_flush_control = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_context_flush_control");
+    GLAD_GL_KHR_debug = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_debug");
+    GLAD_GL_KHR_no_error = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_no_error");
+    GLAD_GL_KHR_parallel_shader_compile = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_parallel_shader_compile");
+    GLAD_GL_KHR_robust_buffer_access_behavior = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_robust_buffer_access_behavior");
+    GLAD_GL_KHR_robustness = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_robustness");
+    GLAD_GL_KHR_shader_subgroup = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_shader_subgroup");
+    GLAD_GL_KHR_texture_compression_astc_hdr = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_texture_compression_astc_hdr");
+    GLAD_GL_KHR_texture_compression_astc_ldr = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_texture_compression_astc_ldr");
+    GLAD_GL_KHR_texture_compression_astc_sliced_3d = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_texture_compression_astc_sliced_3d");
+    GLAD_GL_OES_EGL_image = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_EGL_image");
+    GLAD_GL_OES_EGL_image_external = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_EGL_image_external");
+    GLAD_GL_OES_EGL_image_external_essl3 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_EGL_image_external_essl3");
+    GLAD_GL_OES_compressed_ETC1_RGB8_sub_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_compressed_ETC1_RGB8_sub_texture");
+    GLAD_GL_OES_compressed_ETC1_RGB8_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_compressed_ETC1_RGB8_texture");
+    GLAD_GL_OES_compressed_paletted_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_compressed_paletted_texture");
+    GLAD_GL_OES_copy_image = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_copy_image");
+    GLAD_GL_OES_depth24 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_depth24");
+    GLAD_GL_OES_depth32 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_depth32");
+    GLAD_GL_OES_depth_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_depth_texture");
+    GLAD_GL_OES_draw_buffers_indexed = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_draw_buffers_indexed");
+    GLAD_GL_OES_draw_elements_base_vertex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_draw_elements_base_vertex");
+    GLAD_GL_OES_element_index_uint = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_element_index_uint");
+    GLAD_GL_OES_fbo_render_mipmap = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_fbo_render_mipmap");
+    GLAD_GL_OES_fragment_precision_high = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_fragment_precision_high");
+    GLAD_GL_OES_geometry_point_size = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_geometry_point_size");
+    GLAD_GL_OES_geometry_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_geometry_shader");
+    GLAD_GL_OES_get_program_binary = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_get_program_binary");
+    GLAD_GL_OES_gpu_shader5 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_gpu_shader5");
+    GLAD_GL_OES_mapbuffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_mapbuffer");
+    GLAD_GL_OES_packed_depth_stencil = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_packed_depth_stencil");
+    GLAD_GL_OES_primitive_bounding_box = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_primitive_bounding_box");
+    GLAD_GL_OES_required_internalformat = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_required_internalformat");
+    GLAD_GL_OES_rgb8_rgba8 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_rgb8_rgba8");
+    GLAD_GL_OES_sample_shading = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_sample_shading");
+    GLAD_GL_OES_sample_variables = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_sample_variables");
+    GLAD_GL_OES_shader_image_atomic = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_shader_image_atomic");
+    GLAD_GL_OES_shader_io_blocks = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_shader_io_blocks");
+    GLAD_GL_OES_shader_multisample_interpolation = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_shader_multisample_interpolation");
+    GLAD_GL_OES_standard_derivatives = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_standard_derivatives");
+    GLAD_GL_OES_stencil1 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_stencil1");
+    GLAD_GL_OES_stencil4 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_stencil4");
+    GLAD_GL_OES_surfaceless_context = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_surfaceless_context");
+    GLAD_GL_OES_tessellation_point_size = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_tessellation_point_size");
+    GLAD_GL_OES_tessellation_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_tessellation_shader");
+    GLAD_GL_OES_texture_3D = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_3D");
+    GLAD_GL_OES_texture_border_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_border_clamp");
+    GLAD_GL_OES_texture_buffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_buffer");
+    GLAD_GL_OES_texture_compression_astc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_compression_astc");
+    GLAD_GL_OES_texture_cube_map_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_cube_map_array");
+    GLAD_GL_OES_texture_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_float");
+    GLAD_GL_OES_texture_float_linear = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_float_linear");
+    GLAD_GL_OES_texture_half_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_half_float");
+    GLAD_GL_OES_texture_half_float_linear = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_half_float_linear");
+    GLAD_GL_OES_texture_npot = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_npot");
+    GLAD_GL_OES_texture_stencil8 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_stencil8");
+    GLAD_GL_OES_texture_storage_multisample_2d_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_storage_multisample_2d_array");
+    GLAD_GL_OES_texture_view = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_view");
+    GLAD_GL_OES_vertex_array_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_vertex_array_object");
+    GLAD_GL_OES_vertex_half_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_vertex_half_float");
+    GLAD_GL_OES_vertex_type_10_10_10_2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_vertex_type_10_10_10_2");
+    GLAD_GL_OES_viewport_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_viewport_array");
+
+    glad_gl_free_extensions(exts_i, num_exts_i);
+
+    return 1;
+}
+
+static int glad_gl_find_core_gles2(void) {
+    int i;
+    const char* version;
+    const char* prefixes[] = {
+        "OpenGL ES-CM ",
+        "OpenGL ES-CL ",
+        "OpenGL ES ",
+        "OpenGL SC ",
+        NULL
+    };
+    int major = 0;
+    int minor = 0;
+    version = (const char*) glad_glGetString(GL_VERSION);
+    if (!version) return 0;
+    for (i = 0;  prefixes[i];  i++) {
+        const size_t length = strlen(prefixes[i]);
+        if (strncmp(version, prefixes[i], length) == 0) {
+            version += length;
+            break;
+        }
+    }
+
+    GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
+
+    GLAD_GL_ES_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
+
+    return GLAD_MAKE_VERSION(major, minor);
+}
+
+int gladLoadGLES2UserPtr( GLADuserptrloadfunc load, void *userptr) {
+    int version;
+
+    glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+    if(glad_glGetString == NULL) return 0;
+    if(glad_glGetString(GL_VERSION) == NULL) return 0;
+    version = glad_gl_find_core_gles2();
+
+    glad_gl_load_GL_ES_VERSION_2_0(load, userptr);
+
+    if (!glad_gl_find_extensions_gles2(version)) return 0;
+    glad_gl_load_GL_EXT_EGL_image_storage(load, userptr);
+    glad_gl_load_GL_EXT_base_instance(load, userptr);
+    glad_gl_load_GL_EXT_blend_func_extended(load, userptr);
+    glad_gl_load_GL_EXT_buffer_storage(load, userptr);
+    glad_gl_load_GL_EXT_clear_texture(load, userptr);
+    glad_gl_load_GL_EXT_clip_control(load, userptr);
+    glad_gl_load_GL_EXT_copy_image(load, userptr);
+    glad_gl_load_GL_EXT_debug_label(load, userptr);
+    glad_gl_load_GL_EXT_debug_marker(load, userptr);
+    glad_gl_load_GL_EXT_discard_framebuffer(load, userptr);
+    glad_gl_load_GL_EXT_disjoint_timer_query(load, userptr);
+    glad_gl_load_GL_EXT_draw_buffers(load, userptr);
+    glad_gl_load_GL_EXT_draw_buffers_indexed(load, userptr);
+    glad_gl_load_GL_EXT_draw_elements_base_vertex(load, userptr);
+    glad_gl_load_GL_EXT_draw_instanced(load, userptr);
+    glad_gl_load_GL_EXT_draw_transform_feedback(load, userptr);
+    glad_gl_load_GL_EXT_external_buffer(load, userptr);
+    glad_gl_load_GL_EXT_fragment_shading_rate(load, userptr);
+    glad_gl_load_GL_EXT_geometry_shader(load, userptr);
+    glad_gl_load_GL_EXT_instanced_arrays(load, userptr);
+    glad_gl_load_GL_EXT_map_buffer_range(load, userptr);
+    glad_gl_load_GL_EXT_memory_object(load, userptr);
+    glad_gl_load_GL_EXT_memory_object_fd(load, userptr);
+    glad_gl_load_GL_EXT_memory_object_win32(load, userptr);
+    glad_gl_load_GL_EXT_multi_draw_arrays(load, userptr);
+    glad_gl_load_GL_EXT_multi_draw_indirect(load, userptr);
+    glad_gl_load_GL_EXT_multisampled_render_to_texture(load, userptr);
+    glad_gl_load_GL_EXT_multiview_draw_buffers(load, userptr);
+    glad_gl_load_GL_EXT_occlusion_query_boolean(load, userptr);
+    glad_gl_load_GL_EXT_polygon_offset_clamp(load, userptr);
+    glad_gl_load_GL_EXT_primitive_bounding_box(load, userptr);
+    glad_gl_load_GL_EXT_raster_multisample(load, userptr);
+    glad_gl_load_GL_EXT_robustness(load, userptr);
+    glad_gl_load_GL_EXT_semaphore(load, userptr);
+    glad_gl_load_GL_EXT_semaphore_fd(load, userptr);
+    glad_gl_load_GL_EXT_semaphore_win32(load, userptr);
+    glad_gl_load_GL_EXT_separate_shader_objects(load, userptr);
+    glad_gl_load_GL_EXT_shader_framebuffer_fetch_non_coherent(load, userptr);
+    glad_gl_load_GL_EXT_shader_pixel_local_storage2(load, userptr);
+    glad_gl_load_GL_EXT_sparse_texture(load, userptr);
+    glad_gl_load_GL_EXT_tessellation_shader(load, userptr);
+    glad_gl_load_GL_EXT_texture_border_clamp(load, userptr);
+    glad_gl_load_GL_EXT_texture_buffer(load, userptr);
+    glad_gl_load_GL_EXT_texture_storage(load, userptr);
+    glad_gl_load_GL_EXT_texture_storage_compression(load, userptr);
+    glad_gl_load_GL_EXT_texture_view(load, userptr);
+    glad_gl_load_GL_EXT_win32_keyed_mutex(load, userptr);
+    glad_gl_load_GL_EXT_window_rectangles(load, userptr);
+    glad_gl_load_GL_KHR_blend_equation_advanced(load, userptr);
+    glad_gl_load_GL_KHR_debug(load, userptr);
+    glad_gl_load_GL_KHR_parallel_shader_compile(load, userptr);
+    glad_gl_load_GL_KHR_robustness(load, userptr);
+    glad_gl_load_GL_OES_EGL_image(load, userptr);
+    glad_gl_load_GL_OES_copy_image(load, userptr);
+    glad_gl_load_GL_OES_draw_buffers_indexed(load, userptr);
+    glad_gl_load_GL_OES_draw_elements_base_vertex(load, userptr);
+    glad_gl_load_GL_OES_geometry_shader(load, userptr);
+    glad_gl_load_GL_OES_get_program_binary(load, userptr);
+    glad_gl_load_GL_OES_mapbuffer(load, userptr);
+    glad_gl_load_GL_OES_primitive_bounding_box(load, userptr);
+    glad_gl_load_GL_OES_sample_shading(load, userptr);
+    glad_gl_load_GL_OES_tessellation_shader(load, userptr);
+    glad_gl_load_GL_OES_texture_3D(load, userptr);
+    glad_gl_load_GL_OES_texture_border_clamp(load, userptr);
+    glad_gl_load_GL_OES_texture_buffer(load, userptr);
+    glad_gl_load_GL_OES_texture_storage_multisample_2d_array(load, userptr);
+    glad_gl_load_GL_OES_texture_view(load, userptr);
+    glad_gl_load_GL_OES_vertex_array_object(load, userptr);
+    glad_gl_load_GL_OES_viewport_array(load, userptr);
+
+
+
+    return version;
+}
+
+
+int gladLoadGLES2( GLADloadfunc load) {
+    return gladLoadGLES2UserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
+}
+
+
+
+ 
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GLAD_GLES2_IMPLEMENTATION */
+
raylib/src/external/miniaudio.h view

file too large to diff

+ raylib/src/external/qoa.h view
@@ -0,0 +1,660 @@+/*
+
+Copyright (c) 2023, Dominic Szablewski - https://phoboslab.org
+SPDX-License-Identifier: MIT
+
+QOA - The "Quite OK Audio" format for fast, lossy audio compression
+
+
+-- Data Format
+
+A QOA file has an 8 byte file header, followed by a number of frames. Each frame 
+consists of an 8 byte frame header, the current 8 byte en-/decoder state per
+channel and 256 slices per channel. Each slice is 8 bytes wide and encodes 20 
+samples of audio data.
+
+Note that the last frame of a file may contain less than 256 slices per channel.
+The last slice (per channel) in the last frame may contain less 20 samples, but
+the slice will still be 8 bytes wide, with the unused samples zeroed out.
+
+The samplerate and number of channels is only stated in the frame headers, but
+not in the file header. A decoder may peek into the first frame of the file to 
+find these values.
+
+In a valid QOA file all frames have the same number of channels and the same
+samplerate. These restriction may be releaxed for streaming. This remains to 
+be decided.
+
+All values in a QOA file are BIG ENDIAN. Luckily, EVERYTHING in a QOA file,
+including the headers, is 64 bit aligned, so it's possible to read files with 
+just a read_u64() that does the byte swapping if neccessary.
+
+In pseudocode, the file layout is as follows:
+
+struct {
+	struct {
+		char     magic[4];         // magic bytes 'qoaf'
+		uint32_t samples;          // number of samples per channel in this file
+	} file_header;                 // = 64 bits
+
+	struct {
+		struct {
+			uint8_t  num_channels; // number of channels
+			uint24_t samplerate;   // samplerate in hz
+			uint16_t fsamples;     // sample count per channel in this frame
+			uint16_t fsize;        // frame size (including the frame header)
+		} frame_header;            // = 64 bits
+
+		struct {
+			int16_t history[4];    // = 64 bits
+			int16_t weights[4];    // = 64 bits
+		} lms_state[num_channels]; 
+
+		qoa_slice_t slices[256][num_channels]; // = 64 bits each
+	} frames[samples * channels / qoa_max_framesize()];
+} qoa_file;
+
+Wheras the 64bit qoa_slice_t is defined as follows:
+
+.- QOA_SLICE -- 64 bits, 20 samples --------------------------/  /------------.
+|        Byte[0]         |        Byte[1]         |  Byte[2]  \  \  Byte[7]   |
+| 7  6  5  4  3  2  1  0 | 7  6  5  4  3  2  1  0 | 7  6  5   /  /    2  1  0 |
+|------------+--------+--------+--------+---------+---------+-\  \--+---------|
+|  sf_index  |  r00   |   r01  |   r02  |  r03    |   r04   | /  /  |   r19   |
+`-------------------------------------------------------------\  \------------`
+
+`sf_index` defines the scalefactor to use for this slice as an index into the
+qoa_scalefactor_tab[16]
+
+`r00`--`r19` are the residuals for the individiual samples, divided by the
+scalefactor and quantized by the qoa_quant_tab[].
+
+In the decoder, a prediction of the next sample is computed by multiplying the 
+state (the last four output samples) with the predictor. The residual from the 
+slice is then dequantized using the qoa_dequant_tab[] and added to the 
+prediction. The result is clamped to int16 to form the final output sample.
+
+*/
+
+
+
+/* -----------------------------------------------------------------------------
+	Header - Public functions */
+
+#ifndef QOA_H
+#define QOA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define QOA_MIN_FILESIZE 16
+#define QOA_MAX_CHANNELS 8
+
+#define QOA_SLICE_LEN 20
+#define QOA_SLICES_PER_FRAME 256
+#define QOA_FRAME_LEN (QOA_SLICES_PER_FRAME * QOA_SLICE_LEN)
+#define QOA_LMS_LEN 4
+#define QOA_MAGIC 0x716f6166 /* 'qoaf' */
+
+#define QOA_FRAME_SIZE(channels, slices) \
+	(8 + QOA_LMS_LEN * 4 * channels + 8 * slices * channels)
+
+typedef struct {
+	int history[QOA_LMS_LEN];
+	int weights[QOA_LMS_LEN];
+} qoa_lms_t;
+
+typedef struct {
+	unsigned int channels;
+	unsigned int samplerate;
+	unsigned int samples;
+	qoa_lms_t lms[QOA_MAX_CHANNELS];
+	#ifdef QOA_RECORD_TOTAL_ERROR
+		double error;
+	#endif
+} qoa_desc;
+
+unsigned int qoa_encode_header(qoa_desc *qoa, unsigned char *bytes);
+unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned int frame_len, unsigned char *bytes);
+void *qoa_encode(const short *sample_data, qoa_desc *qoa, unsigned int *out_len);
+
+unsigned int qoa_max_frame_size(qoa_desc *qoa);
+unsigned int qoa_decode_header(const unsigned char *bytes, int size, qoa_desc *qoa);
+unsigned int qoa_decode_frame(const unsigned char *bytes, unsigned int size, qoa_desc *qoa, short *sample_data, unsigned int *frame_len);
+short *qoa_decode(const unsigned char *bytes, int size, qoa_desc *file);
+
+#ifndef QOA_NO_STDIO
+
+int qoa_write(const char *filename, const short *sample_data, qoa_desc *qoa);
+void *qoa_read(const char *filename, qoa_desc *qoa);
+
+#endif /* QOA_NO_STDIO */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* QOA_H */
+
+
+/* -----------------------------------------------------------------------------
+	Implementation */
+
+#ifdef QOA_IMPLEMENTATION
+#include <stdlib.h>
+
+#ifndef QOA_MALLOC
+	#define QOA_MALLOC(sz) malloc(sz)
+	#define QOA_FREE(p) free(p)
+#endif
+
+typedef unsigned long long qoa_uint64_t;
+
+
+/* The quant_tab provides an index into the dequant_tab for residuals in the
+range of -8 .. 8. It maps this range to just 3bits and becommes less accurate at 
+the higher end. Note that the residual zero is identical to the lowest positive 
+value. This is mostly fine, since the qoa_div() function always rounds away 
+from zero. */
+
+static int qoa_quant_tab[17] = {
+	7, 7, 7, 5, 5, 3, 3, 1, /* -8..-1 */
+	0,                      /*  0     */
+	0, 2, 2, 4, 4, 6, 6, 6  /*  1.. 8 */
+};
+
+
+/* We have 16 different scalefactors. Like the quantized residuals these become
+less accurate at the higher end. In theory, the highest scalefactor that we
+would need to encode the highest 16bit residual is (2**16)/8 = 8192. However we
+rely on the LMS filter to predict samples accurately enough that a maximum 
+residual of one quarter of the 16 bit range is high sufficent. I.e. with the 
+scalefactor 2048 times the quant range of 8 we can encode residuals up to 2**14.
+
+The scalefactor values are computed as:
+scalefactor_tab[s] <- round(pow(s + 1, 2.75)) */
+
+static int qoa_scalefactor_tab[16] = {
+	1, 7, 21, 45, 84, 138, 211, 304, 421, 562, 731, 928, 1157, 1419, 1715, 2048
+};
+
+
+/* The reciprocal_tab maps each of the 16 scalefactors to their rounded 
+reciprocals 1/scalefactor. This allows us to calculate the scaled residuals in 
+the encoder with just one multiplication instead of an expensive division. We 
+do this in .16 fixed point with integers, instead of floats.
+
+The reciprocal_tab is computed as:
+reciprocal_tab[s] <- ((1<<16) + scalefactor_tab[s] - 1) / scalefactor_tab[s] */
+
+static int qoa_reciprocal_tab[16] = {
+	65536, 9363, 3121, 1457, 781, 475, 311, 216, 156, 117, 90, 71, 57, 47, 39, 32
+};
+
+
+/* The dequant_tab maps each of the scalefactors and quantized residuals to 
+their unscaled & dequantized version.
+
+Since qoa_div rounds away from the zero, the smallest entries are mapped to 3/4
+instead of 1. The dequant_tab assumes the following dequantized values for each 
+of the quant_tab indices and is computed as:
+float dqt[8] = {0.75, -0.75, 2.5, -2.5, 4.5, -4.5, 7, -7};
+dequant_tab[s][q] <- round(scalefactor_tab[s] * dqt[q]) */
+
+static int qoa_dequant_tab[16][8] = {
+	{   1,    -1,    3,    -3,    5,    -5,     7,     -7},
+	{   5,    -5,   18,   -18,   32,   -32,    49,    -49},
+	{  16,   -16,   53,   -53,   95,   -95,   147,   -147},
+	{  34,   -34,  113,  -113,  203,  -203,   315,   -315},
+	{  63,   -63,  210,  -210,  378,  -378,   588,   -588},
+	{ 104,  -104,  345,  -345,  621,  -621,   966,   -966},
+	{ 158,  -158,  528,  -528,  950,  -950,  1477,  -1477},
+	{ 228,  -228,  760,  -760, 1368, -1368,  2128,  -2128},
+	{ 316,  -316, 1053, -1053, 1895, -1895,  2947,  -2947},
+	{ 422,  -422, 1405, -1405, 2529, -2529,  3934,  -3934},
+	{ 548,  -548, 1828, -1828, 3290, -3290,  5117,  -5117},
+	{ 696,  -696, 2320, -2320, 4176, -4176,  6496,  -6496},
+	{ 868,  -868, 2893, -2893, 5207, -5207,  8099,  -8099},
+	{1064, -1064, 3548, -3548, 6386, -6386,  9933,  -9933},
+	{1286, -1286, 4288, -4288, 7718, -7718, 12005, -12005},
+	{1536, -1536, 5120, -5120, 9216, -9216, 14336, -14336},
+};
+
+
+/* The Least Mean Squares Filter is the heart of QOA. It predicts the next
+sample based on the previous 4 reconstructed samples. It does so by continuously
+adjusting 4 weights based on the residual of the previous prediction.
+
+The next sample is predicted as the sum of (weight[i] * history[i]).
+
+The adjustment of the weights is done with a "Sign-Sign-LMS" that adds or
+subtracts the residual to each weight, based on the corresponding sample from 
+the history. This, suprisingly, is sufficent to get worthwhile predictions. 
+
+This is all done with fixed point integers. Hence the right-shifts when updating
+the weights and calculating the prediction. */
+
+static int qoa_lms_predict(qoa_lms_t *lms) {
+	int prediction = 0;
+	for (int i = 0; i < QOA_LMS_LEN; i++) {
+		prediction += lms->weights[i] * lms->history[i];
+	}
+	return prediction >> 13;
+}
+
+static void qoa_lms_update(qoa_lms_t *lms, int sample, int residual) {
+	int delta = residual >> 4;
+	for (int i = 0; i < QOA_LMS_LEN; i++) {
+		lms->weights[i] += lms->history[i] < 0 ? -delta : delta;
+	}
+
+	for (int i = 0; i < QOA_LMS_LEN-1; i++) {
+		lms->history[i] = lms->history[i+1];
+	}
+	lms->history[QOA_LMS_LEN-1] = sample;
+}
+
+
+/* qoa_div() implements a rounding division, but avoids rounding to zero for 
+small numbers. E.g. 0.1 will be rounded to 1. Note that 0 itself still 
+returns as 0, which is handled in the qoa_quant_tab[].
+qoa_div() takes an index into the .16 fixed point qoa_reciprocal_tab as an
+argument, so it can do the division with a cheaper integer multiplication. */
+
+static inline int qoa_div(int v, int scalefactor) {
+	int reciprocal = qoa_reciprocal_tab[scalefactor];
+	int n = (v * reciprocal + (1 << 15)) >> 16;
+	n = n + ((v > 0) - (v < 0)) - ((n > 0) - (n < 0)); /* round away from 0 */
+	return n;
+}
+
+static inline int qoa_clamp(int v, int min, int max) {
+	return (v < min) ? min : (v > max) ? max : v;
+}
+
+static inline qoa_uint64_t qoa_read_u64(const unsigned char *bytes, unsigned int *p) {
+	bytes += *p;
+	*p += 8;
+	return 
+		((qoa_uint64_t)(bytes[0]) << 56) | ((qoa_uint64_t)(bytes[1]) << 48) |
+		((qoa_uint64_t)(bytes[2]) << 40) | ((qoa_uint64_t)(bytes[3]) << 32) |
+		((qoa_uint64_t)(bytes[4]) << 24) | ((qoa_uint64_t)(bytes[5]) << 16) |
+		((qoa_uint64_t)(bytes[6]) <<  8) | ((qoa_uint64_t)(bytes[7]) <<  0);
+}
+
+static inline void qoa_write_u64(qoa_uint64_t v, unsigned char *bytes, unsigned int *p) {
+	bytes += *p;
+	*p += 8;
+	bytes[0] = (v >> 56) & 0xff;
+	bytes[1] = (v >> 48) & 0xff;
+	bytes[2] = (v >> 40) & 0xff;
+	bytes[3] = (v >> 32) & 0xff;
+	bytes[4] = (v >> 24) & 0xff;
+	bytes[5] = (v >> 16) & 0xff;
+	bytes[6] = (v >>  8) & 0xff;
+	bytes[7] = (v >>  0) & 0xff;
+}
+
+
+/* -----------------------------------------------------------------------------
+	Encoder */
+
+unsigned int qoa_encode_header(qoa_desc *qoa, unsigned char *bytes) {
+	unsigned int p = 0;
+	qoa_write_u64(((qoa_uint64_t)QOA_MAGIC << 32) | qoa->samples, bytes, &p);
+	return p;
+}
+
+unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned int frame_len, unsigned char *bytes) {
+	unsigned int channels = qoa->channels;
+
+	unsigned int p = 0;
+	unsigned int slices = (frame_len + QOA_SLICE_LEN - 1) / QOA_SLICE_LEN;
+	unsigned int frame_size = QOA_FRAME_SIZE(channels, slices);
+
+	/* Write the frame header */
+	qoa_write_u64((
+		(qoa_uint64_t)qoa->channels   << 56 |
+		(qoa_uint64_t)qoa->samplerate << 32 |
+		(qoa_uint64_t)frame_len       << 16 |
+		(qoa_uint64_t)frame_size
+	), bytes, &p);
+
+	/* Write the current LMS state */
+	for (int c = 0; c < channels; c++) {
+		qoa_uint64_t weights = 0;
+		qoa_uint64_t history = 0;
+		for (int i = 0; i < QOA_LMS_LEN; i++) {
+			history = (history << 16) | (qoa->lms[c].history[i] & 0xffff);
+			weights = (weights << 16) | (qoa->lms[c].weights[i] & 0xffff);
+		}
+		qoa_write_u64(history, bytes, &p);
+		qoa_write_u64(weights, bytes, &p);
+	}
+
+	/* We encode all samples with the channels interleaved on a slice level.
+	E.g. for stereo: (ch-0, slice 0), (ch 1, slice 0), (ch 0, slice 1), ...*/
+	for (int sample_index = 0; sample_index < frame_len; sample_index += QOA_SLICE_LEN) {
+
+		for (int c = 0; c < channels; c++) {
+			int slice_len = qoa_clamp(QOA_SLICE_LEN, 0, frame_len - sample_index);
+			int slice_start = sample_index * channels + c;
+			int slice_end = (sample_index + slice_len) * channels + c;			
+
+			/* Brute for search for the best scalefactor. Just go through all
+			16 scalefactors, encode all samples for the current slice and 
+			meassure the total squared error. */
+			qoa_uint64_t best_error = -1;
+			qoa_uint64_t best_slice;
+			qoa_lms_t best_lms;
+
+			for (int scalefactor = 0; scalefactor < 16; scalefactor++) {
+
+				/* We have to reset the LMS state to the last known good one
+				before trying each scalefactor, as each pass updates the LMS
+				state when encoding. */
+				qoa_lms_t lms = qoa->lms[c];
+				qoa_uint64_t slice = scalefactor;
+				qoa_uint64_t current_error = 0;
+
+				for (int si = slice_start; si < slice_end; si += channels) {
+					int sample = sample_data[si];
+					int predicted = qoa_lms_predict(&lms);
+
+					int residual = sample - predicted;
+					int scaled = qoa_div(residual, scalefactor);
+					int clamped = qoa_clamp(scaled, -8, 8);
+					int quantized = qoa_quant_tab[clamped + 8];
+					int dequantized = qoa_dequant_tab[scalefactor][quantized];
+					int reconstructed = qoa_clamp(predicted + dequantized, -32768, 32767);
+
+					int error = (sample - reconstructed);
+					current_error += error * error;
+					if (current_error > best_error) {
+						break;
+					}
+
+					qoa_lms_update(&lms, reconstructed, dequantized);
+					slice = (slice << 3) | quantized;
+				}
+
+				if (current_error < best_error) {
+					best_error = current_error;
+					best_slice = slice;
+					best_lms = lms;
+				}
+			}
+
+			qoa->lms[c] = best_lms;
+			#ifdef QOA_RECORD_TOTAL_ERROR
+				qoa->error += best_error;
+			#endif
+
+			/* If this slice was shorter than QOA_SLICE_LEN, we have to left-
+			shift all encoded data, to ensure the rightmost bits are the empty
+			ones. This should only happen in the last frame of a file as all
+			slices are completely filled otherwise. */
+			best_slice <<= (QOA_SLICE_LEN - slice_len) * 3;
+			qoa_write_u64(best_slice, bytes, &p);
+		}
+	}
+	
+	return p;
+}
+
+void *qoa_encode(const short *sample_data, qoa_desc *qoa, unsigned int *out_len) {
+	if (
+		qoa->samples == 0 || 
+		qoa->samplerate == 0 || qoa->samplerate > 0xffffff ||
+		qoa->channels == 0 || qoa->channels > QOA_MAX_CHANNELS
+	) {
+		return NULL;
+	}
+
+	/* Calculate the encoded size and allocate */
+	unsigned int num_frames = (qoa->samples + QOA_FRAME_LEN-1) / QOA_FRAME_LEN;
+	unsigned int num_slices = (qoa->samples + QOA_SLICE_LEN-1) / QOA_SLICE_LEN;
+	unsigned int encoded_size = 8 +                    /* 8 byte file header */
+		num_frames * 8 +                               /* 8 byte frame headers */
+		num_frames * QOA_LMS_LEN * 4 * qoa->channels + /* 4 * 4 bytes lms state per channel */
+		num_slices * 8 * qoa->channels;                /* 8 byte slices */
+
+	unsigned char *bytes = QOA_MALLOC(encoded_size);
+
+	for (int c = 0; c < qoa->channels; c++) {
+		/* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the 
+		prediction of the first few ms of a file. */
+		qoa->lms[c].weights[0] = 0;
+		qoa->lms[c].weights[1] = 0;
+		qoa->lms[c].weights[2] = -(1<<13);
+		qoa->lms[c].weights[3] =  (1<<14);
+
+		/* Explicitly set the history samples to 0, as we might have some
+		garbage in there. */
+		for (int i = 0; i < QOA_LMS_LEN; i++) {
+			qoa->lms[c].history[i] = 0;
+		}
+	}
+
+
+	/* Encode the header and go through all frames */
+	unsigned int p = qoa_encode_header(qoa, bytes);
+	#ifdef QOA_RECORD_TOTAL_ERROR
+		qoa->error = 0;
+	#endif
+
+	int frame_len = QOA_FRAME_LEN;
+	for (int sample_index = 0; sample_index < qoa->samples; sample_index += frame_len) {
+		frame_len = qoa_clamp(QOA_FRAME_LEN, 0, qoa->samples - sample_index);		
+		const short *frame_samples = sample_data + sample_index * qoa->channels;
+		unsigned int frame_size = qoa_encode_frame(frame_samples, qoa, frame_len, bytes + p);
+		p += frame_size;
+	}
+
+	*out_len = p;
+	return bytes;
+}
+
+
+
+/* -----------------------------------------------------------------------------
+	Decoder */
+
+unsigned int qoa_max_frame_size(qoa_desc *qoa) {
+	return QOA_FRAME_SIZE(qoa->channels, QOA_SLICES_PER_FRAME);
+}
+
+unsigned int qoa_decode_header(const unsigned char *bytes, int size, qoa_desc *qoa) {
+	unsigned int p = 0;
+	if (size < QOA_MIN_FILESIZE) {
+		return 0;
+	}
+
+
+	/* Read the file header, verify the magic number ('qoaf') and read the 
+	total number of samples. */
+	qoa_uint64_t file_header = qoa_read_u64(bytes, &p);
+
+	if ((file_header >> 32) != QOA_MAGIC) {
+		return 0;
+	}
+
+	qoa->samples = file_header & 0xffffffff;
+	if (!qoa->samples) {
+		return 0;
+	}
+
+	/* Peek into the first frame header to get the number of channels and
+	the samplerate. */
+	qoa_uint64_t frame_header = qoa_read_u64(bytes, &p);
+	qoa->channels   = (frame_header >> 56) & 0x0000ff;
+	qoa->samplerate = (frame_header >> 32) & 0xffffff;
+
+	if (qoa->channels == 0 || qoa->samples == 0 || qoa->samplerate == 0) {
+		return 0;
+	}
+
+	return 8;
+}
+
+unsigned int qoa_decode_frame(const unsigned char *bytes, unsigned int size, qoa_desc *qoa, short *sample_data, unsigned int *frame_len) {
+	unsigned int p = 0;
+	*frame_len = 0;
+
+	if (size < 8 + QOA_LMS_LEN * 4 * qoa->channels) {
+		return 0;
+	}
+
+	/* Read and verify the frame header */
+	qoa_uint64_t frame_header = qoa_read_u64(bytes, &p);
+	int channels   = (frame_header >> 56) & 0x0000ff;
+	int samplerate = (frame_header >> 32) & 0xffffff;
+	int samples    = (frame_header >> 16) & 0x00ffff;
+	int frame_size = (frame_header      ) & 0x00ffff;
+
+	int data_size = frame_size - 8 - QOA_LMS_LEN * 4 * channels;
+	int num_slices = data_size / 8;
+	int max_total_samples = num_slices * QOA_SLICE_LEN;
+
+	if (
+		channels != qoa->channels || 
+		samplerate != qoa->samplerate ||
+		frame_size > size ||
+		samples * channels > max_total_samples
+	) {
+		return 0;
+	}
+
+
+	/* Read the LMS state: 4 x 2 bytes history, 4 x 2 bytes weights per channel */
+	for (int c = 0; c < channels; c++) {
+		qoa_uint64_t history = qoa_read_u64(bytes, &p);
+		qoa_uint64_t weights = qoa_read_u64(bytes, &p);
+		for (int i = 0; i < QOA_LMS_LEN; i++) {
+			qoa->lms[c].history[i] = ((signed short)(history >> 48));
+			history <<= 16;
+			qoa->lms[c].weights[i] = ((signed short)(weights >> 48));
+			weights <<= 16;
+		}
+	}
+
+
+	/* Decode all slices for all channels in this frame */
+	for (int sample_index = 0; sample_index < samples; sample_index += QOA_SLICE_LEN) {
+		for (int c = 0; c < channels; c++) {
+			qoa_uint64_t slice = qoa_read_u64(bytes, &p);
+
+			int scalefactor = (slice >> 60) & 0xf;
+			int slice_start = sample_index * channels + c;
+			int slice_end = qoa_clamp(sample_index + QOA_SLICE_LEN, 0, samples) * channels + c;
+
+			for (int si = slice_start; si < slice_end; si += channels) {
+				int predicted = qoa_lms_predict(&qoa->lms[c]);
+				int quantized = (slice >> 57) & 0x7;
+				int dequantized = qoa_dequant_tab[scalefactor][quantized];
+				int reconstructed = qoa_clamp(predicted + dequantized, -32768, 32767);
+				
+				sample_data[si] = reconstructed;
+				slice <<= 3;
+
+				qoa_lms_update(&qoa->lms[c], reconstructed, dequantized);
+			}
+		}
+	}
+
+	*frame_len = samples;
+	return p;
+}
+
+short *qoa_decode(const unsigned char *bytes, int size, qoa_desc *qoa) {
+	unsigned int p = qoa_decode_header(bytes, size, qoa);
+	if (!p) {
+		return NULL;
+	}
+
+	/* Calculate the required size of the sample buffer and allocate */
+	int total_samples = qoa->samples * qoa->channels;
+	short *sample_data = QOA_MALLOC(total_samples * sizeof(short));
+
+	unsigned int sample_index = 0;
+	unsigned int frame_len;
+	unsigned int frame_size;
+
+	/* Decode all frames */
+	do {
+		short *sample_ptr = sample_data + sample_index * qoa->channels;
+		frame_size = qoa_decode_frame(bytes + p, size - p, qoa, sample_ptr, &frame_len);
+
+		p += frame_size;
+		sample_index += frame_len;
+	} while (frame_size && sample_index < qoa->samples);
+
+	qoa->samples = sample_index;
+	return sample_data;
+}
+
+
+
+/* -----------------------------------------------------------------------------
+	File read/write convenience functions */
+
+#ifndef QOA_NO_STDIO
+#include <stdio.h>
+
+int qoa_write(const char *filename, const short *sample_data, qoa_desc *qoa) {
+	FILE *f = fopen(filename, "wb");
+	unsigned int size;
+	void *encoded;
+
+	if (!f) {
+		return 0;
+	}
+
+	encoded = qoa_encode(sample_data, qoa, &size);
+	if (!encoded) {
+		fclose(f);
+		return 0;
+	}
+
+	fwrite(encoded, 1, size, f);
+	fclose(f);
+
+	QOA_FREE(encoded);
+	return size;
+}
+
+void *qoa_read(const char *filename, qoa_desc *qoa) {
+	FILE *f = fopen(filename, "rb");
+	int size, bytes_read;
+	void *data;
+	short *sample_data;
+
+	if (!f) {
+		return NULL;
+	}
+
+	fseek(f, 0, SEEK_END);
+	size = ftell(f);
+	if (size <= 0) {
+		fclose(f);
+		return NULL;
+	}
+	fseek(f, 0, SEEK_SET);
+
+	data = QOA_MALLOC(size);
+	if (!data) {
+		fclose(f);
+		return NULL;
+	}
+
+	bytes_read = fread(data, 1, size, f);
+	fclose(f);
+
+	sample_data = qoa_decode(data, bytes_read, qoa);
+	QOA_FREE(data);
+	return sample_data;
+}
+
+#endif /* QOA_NO_STDIO */
+#endif /* QOA_IMPLEMENTATION */
raylib/src/external/qoi.h view
@@ -1,30 +1,10 @@ /*
 
-QOI - The "Quite OK Image" format for fast, lossless image compression
-
-Dominic Szablewski - https://phoboslab.org
+Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
+SPDX-License-Identifier: MIT
 
 
--- LICENSE: The MIT License(MIT)
-
-Copyright(c) 2021 Dominic Szablewski
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files(the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions :
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
+QOI - The "Quite OK Image" format for fast, lossless image compression
 
 -- About
 
@@ -424,13 +404,12 @@ 	channels = desc->channels;
 
 	for (px_pos = 0; px_pos < px_len; px_pos += channels) {
+		px.rgba.r = pixels[px_pos + 0];
+		px.rgba.g = pixels[px_pos + 1];
+		px.rgba.b = pixels[px_pos + 2];
+
 		if (channels == 4) {
-			px = *(qoi_rgba_t *)(pixels + px_pos);
-		}
-		else {
-			px.rgba.r = pixels[px_pos + 0];
-			px.rgba.g = pixels[px_pos + 1];
-			px.rgba.b = pixels[px_pos + 2];
+			px.rgba.a = pixels[px_pos + 3];
 		}
 
 		if (px.v == px_prev.v) {
@@ -598,13 +577,12 @@ 			index[QOI_COLOR_HASH(px) % 64] = px;
 		}
 
+		pixels[px_pos + 0] = px.rgba.r;
+		pixels[px_pos + 1] = px.rgba.g;
+		pixels[px_pos + 2] = px.rgba.b;
+		
 		if (channels == 4) {
-			*(qoi_rgba_t*)(pixels + px_pos) = px;
-		}
-		else {
-			pixels[px_pos + 0] = px.rgba.r;
-			pixels[px_pos + 1] = px.rgba.g;
-			pixels[px_pos + 2] = px.rgba.b;
+			pixels[px_pos + 3] = px.rgba.a;
 		}
 	}
 
raylib/src/external/rl_gputex.h view
@@ -477,10 +477,10 @@     // Calculate file data_size required
     int data_size = sizeof(ktx_header);
 
-    for (int i = 0, width = width, height = height; i < mipmaps; i++)
+    for (int i = 0, w = width, h = height; i < mipmaps; i++)
     {
-        data_size += get_pixel_data_size(width, height, format);
-        width /= 2; height /= 2;
+        data_size += get_pixel_data_size(w, h, format);
+        w /= 2; h /= 2;
     }
 
     unsigned char *file_data = RL_CALLOC(data_size, 1);
raylib/src/external/stb_image.h view
@@ -1,4 +1,4 @@-/* stb_image - v2.27 - public domain image loader - http://nothings.org/stb
+/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb
                                   no warranty implied; use at your own risk
 
    Do this:
@@ -48,6 +48,7 @@ 
 RECENT REVISION HISTORY:
 
+      2.28  (2023-01-29) many error fixes, security errors, just tons of stuff
       2.27  (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
       2.26  (2020-07-13) many minor fixes
       2.25  (2020-02-02) fix warnings
@@ -108,7 +109,7 @@     Cass Everitt            Ryamond Barbiero                        github:grim210
     Paul Du Bois            Engin Manap        Aldo Culquicondor    github:sammyhw
     Philipp Wiesemann       Dale Weiler        Oriol Ferrer Mesia   github:phprus
-    Josh Tobin                                 Matthew Gregan       github:poppolopoppo
+    Josh Tobin              Neil Bickford      Matthew Gregan       github:poppolopoppo
     Julian Raschke          Gregory Mullen     Christian Floisand   github:darealshinji
     Baldur Karlsson         Kevin Schmidt      JR Smith             github:Michaelangel007
                             Brad Weinberger    Matvey Cherevko      github:mosra
@@ -140,7 +141,7 @@ //    // ... x = width, y = height, n = # 8-bit components per pixel ...
 //    // ... replace '0' with '1'..'4' to force that many components per pixel
 //    // ... but 'n' will always be the number that it would have been if you said 0
-//    stbi_image_free(data)
+//    stbi_image_free(data);
 //
 // Standard parameters:
 //    int *x                 -- outputs image width in pixels
@@ -635,7 +636,7 @@    #endif
 #endif
 
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SYMBIAN32__)
 typedef unsigned short stbi__uint16;
 typedef   signed short stbi__int16;
 typedef unsigned int   stbi__uint32;
@@ -1063,6 +1064,23 @@ }
 #endif
 
+// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow.
+static int stbi__addints_valid(int a, int b)
+{
+   if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow
+   if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0.
+   return a <= INT_MAX - b;
+}
+
+// returns 1 if the product of two signed shorts is valid, 0 on overflow.
+static int stbi__mul2shorts_valid(short a, short b)
+{
+   if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
+   if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid
+   if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN
+   return a >= SHRT_MIN / b;
+}
+
 // stbi__err - error
 // stbi__errpf - error returning pointer to float
 // stbi__errpuc - error returning pointer to unsigned char
@@ -1985,9 +2003,12 @@    int i,j,k=0;
    unsigned int code;
    // build size list for each symbol (from JPEG spec)
-   for (i=0; i < 16; ++i)
-      for (j=0; j < count[i]; ++j)
+   for (i=0; i < 16; ++i) {
+      for (j=0; j < count[i]; ++j) {
          h->size[k++] = (stbi_uc) (i+1);
+         if(k >= 257) return stbi__err("bad size list","Corrupt JPEG");
+      }
+   }
    h->size[k] = 0;
 
    // compute actual symbols (from jpeg spec)
@@ -2112,6 +2133,8 @@ 
    // convert the huffman code to the symbol id
    c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];
+   if(c < 0 || c >= 256) // symbol id out of bounds!
+       return -1;
    STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);
 
    // convert the id to a symbol
@@ -2130,6 +2153,7 @@    unsigned int k;
    int sgn;
    if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+   if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
 
    sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative)
    k = stbi_lrot(j->code_buffer, n);
@@ -2144,6 +2168,7 @@ {
    unsigned int k;
    if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+   if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
    k = stbi_lrot(j->code_buffer, n);
    j->code_buffer = k & ~stbi__bmask[n];
    k &= stbi__bmask[n];
@@ -2155,6 +2180,7 @@ {
    unsigned int k;
    if (j->code_bits < 1) stbi__grow_buffer_unsafe(j);
+   if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing
    k = j->code_buffer;
    j->code_buffer <<= 1;
    --j->code_bits;
@@ -2192,8 +2218,10 @@    memset(data,0,64*sizeof(data[0]));
 
    diff = t ? stbi__extend_receive(j, t) : 0;
+   if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG");
    dc = j->img_comp[b].dc_pred + diff;
    j->img_comp[b].dc_pred = dc;
+   if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
    data[0] = (short) (dc * dequant[0]);
 
    // decode AC components, see JPEG spec
@@ -2207,6 +2235,7 @@       if (r) { // fast-AC path
          k += (r >> 4) & 15; // run
          s = r & 15; // combined length
+         if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
          j->code_buffer <<= s;
          j->code_bits -= s;
          // decode into unzigzag'd location
@@ -2246,8 +2275,10 @@       if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
       diff = t ? stbi__extend_receive(j, t) : 0;
 
+      if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG");
       dc = j->img_comp[b].dc_pred + diff;
       j->img_comp[b].dc_pred = dc;
+      if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
       data[0] = (short) (dc * (1 << j->succ_low));
    } else {
       // refinement scan for DC coefficient
@@ -2282,6 +2313,7 @@          if (r) { // fast-AC path
             k += (r >> 4) & 15; // run
             s = r & 15; // combined length
+            if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
             j->code_buffer <<= s;
             j->code_bits -= s;
             zig = stbi__jpeg_dezigzag[k++];
@@ -3102,6 +3134,7 @@                sizes[i] = stbi__get8(z->s);
                n += sizes[i];
             }
+            if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values!
             L -= 17;
             if (tc == 0) {
                if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;
@@ -3351,6 +3384,28 @@    return 1;
 }
 
+static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
+{
+   // some JPEGs have junk at end, skip over it but if we find what looks
+   // like a valid marker, resume there
+   while (!stbi__at_eof(j->s)) {
+      int x = stbi__get8(j->s);
+      while (x == 255) { // might be a marker
+         if (stbi__at_eof(j->s)) return STBI__MARKER_none;
+         x = stbi__get8(j->s);
+         if (x != 0x00 && x != 0xff) {
+            // not a stuffed zero or lead-in to another marker, looks
+            // like an actual marker, return it
+            return x;
+         }
+         // stuffed zero has x=0 now which ends the loop, meaning we go
+         // back to regular scan loop.
+         // repeated 0xff keeps trying to read the next byte of the marker.
+      }
+   }
+   return STBI__MARKER_none;
+}
+
 // decode image to YCbCr format
 static int stbi__decode_jpeg_image(stbi__jpeg *j)
 {
@@ -3367,25 +3422,22 @@          if (!stbi__process_scan_header(j)) return 0;
          if (!stbi__parse_entropy_coded_data(j)) return 0;
          if (j->marker == STBI__MARKER_none ) {
-            // handle 0s at the end of image data from IP Kamera 9060
-            while (!stbi__at_eof(j->s)) {
-               int x = stbi__get8(j->s);
-               if (x == 255) {
-                  j->marker = stbi__get8(j->s);
-                  break;
-               }
-            }
+         j->marker = stbi__skip_jpeg_junk_at_end(j);
             // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
          }
+         m = stbi__get_marker(j);
+         if (STBI__RESTART(m))
+            m = stbi__get_marker(j);
       } else if (stbi__DNL(m)) {
          int Ld = stbi__get16be(j->s);
          stbi__uint32 NL = stbi__get16be(j->s);
          if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");
          if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");
+         m = stbi__get_marker(j);
       } else {
-         if (!stbi__process_marker(j, m)) return 0;
+         if (!stbi__process_marker(j, m)) return 1;
+         m = stbi__get_marker(j);
       }
-      m = stbi__get_marker(j);
    }
    if (j->progressive)
       stbi__jpeg_finish(j);
@@ -3976,6 +4028,7 @@    unsigned char* result;
    stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
    if (!j) return stbi__errpuc("outofmem", "Out of memory");
+   memset(j, 0, sizeof(stbi__jpeg));
    STBI_NOTUSED(ri);
    j->s = s;
    stbi__setup_jpeg(j);
@@ -3989,6 +4042,7 @@    int r;
    stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
    if (!j) return stbi__err("outofmem", "Out of memory");
+   memset(j, 0, sizeof(stbi__jpeg));
    j->s = s;
    stbi__setup_jpeg(j);
    r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
@@ -4014,6 +4068,7 @@    int result;
    stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
    if (!j) return stbi__err("outofmem", "Out of memory");
+   memset(j, 0, sizeof(stbi__jpeg));
    j->s = s;
    result = stbi__jpeg_info_raw(j, x, y, comp);
    STBI_FREE(j);
@@ -4256,11 +4311,12 @@             a->zout = zout;
             return 1;
          }
+         if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
          z -= 257;
          len = stbi__zlength_base[z];
          if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]);
          z = stbi__zhuffman_decode(a, &a->z_distance);
-         if (z < 0) return stbi__err("bad huffman code","Corrupt PNG");
+         if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data
          dist = stbi__zdist_base[z];
          if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
          if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
@@ -4955,7 +5011,7 @@ static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set;
 static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set;
 
-STBIDEF void stbi__unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
+STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
 {
    stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply;
    stbi__unpremultiply_on_load_set = 1;
@@ -5064,14 +5120,13 @@             if (!pal_img_n) {
                s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
                if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
-               if (scan == STBI__SCAN_header) return 1;
             } else {
                // if paletted, then pal_n is our final components, and
                // img_n is # components to decompress/filter.
                s->img_n = 1;
                if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG");
-               // if SCAN_header, have to scan to see if we have a tRNS
             }
+            // even with SCAN_header, have to scan to see if we have a tRNS
             break;
          }
 
@@ -5103,6 +5158,8 @@                if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
                if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
                has_trans = 1;
+               // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now.
+               if (scan == STBI__SCAN_header) { ++s->img_n; return 1; }
                if (z->depth == 16) {
                   for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
                } else {
@@ -5115,7 +5172,13 @@          case STBI__PNG_TYPE('I','D','A','T'): {
             if (first) return stbi__err("first not IHDR", "Corrupt PNG");
             if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
-            if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
+            if (scan == STBI__SCAN_header) {
+               // header scan definitely stops at first IDAT
+               if (pal_img_n)
+                  s->img_n = pal_img_n;
+               return 1;
+            }
+            if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes");
             if ((int)(ioff + c.length) < (int)ioff) return 0;
             if (ioff + c.length > idata_limit) {
                stbi__uint32 idata_limit_old = idata_limit;
@@ -5498,9 +5561,23 @@          psize = (info.offset - info.extra_read - info.hsz) >> 2;
    }
    if (psize == 0) {
-      if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) {
-        return stbi__errpuc("bad offset", "Corrupt BMP");
+      // accept some number of extra bytes after the header, but if the offset points either to before
+      // the header ends or implies a large amount of extra data, reject the file as malformed
+      int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original);
+      int header_limit = 1024; // max we actually read is below 256 bytes currently.
+      int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size.
+      if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) {
+         return stbi__errpuc("bad header", "Corrupt BMP");
       }
+      // we established that bytes_read_so_far is positive and sensible.
+      // the first half of this test rejects offsets that are either too small positives, or
+      // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn
+      // ensures the number computed in the second half of the test can't overflow.
+      if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) {
+         return stbi__errpuc("bad offset", "Corrupt BMP");
+      } else {
+         stbi__skip(s, info.offset - bytes_read_so_far);
+      }
    }
 
    if (info.bpp == 24 && ma == 0xff000000)
@@ -7187,12 +7264,12 @@                   // Run
                   value = stbi__get8(s);
                   count -= 128;
-                  if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
+                  if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
                   for (z = 0; z < count; ++z)
                      scanline[i++ * 4 + k] = value;
                } else {
                   // Dump
-                  if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
+                  if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
                   for (z = 0; z < count; ++z)
                      scanline[i++ * 4 + k] = stbi__get8(s);
                }
@@ -7446,10 +7523,17 @@ 
    out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0);
    if (!out) return stbi__errpuc("outofmem", "Out of memory");
-   stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8));
+   if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) {
+      STBI_FREE(out);
+      return stbi__errpuc("bad PNM", "PNM file truncated");
+   }
 
    if (req_comp && req_comp != s->img_n) {
-      out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
+      if (ri->bits_per_channel == 16) {
+         out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y);
+      } else {
+         out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
+      }
       if (out == NULL) return out; // stbi__convert_format frees input on failure
    }
    return out;
@@ -7486,6 +7570,8 @@    while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
       value = value*10 + (*c - '0');
       *c = (char) stbi__get8(s);
+      if((value > 214748364) || (value == 214748364 && *c > '7'))
+          return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int");
    }
 
    return value;
@@ -7516,9 +7602,13 @@    stbi__pnm_skip_whitespace(s, &c);
 
    *x = stbi__pnm_getinteger(s, &c); // read width
+   if(*x == 0)
+       return stbi__err("invalid width", "PPM image header had zero or overflowing width");
    stbi__pnm_skip_whitespace(s, &c);
 
    *y = stbi__pnm_getinteger(s, &c); // read height
+   if (*y == 0)
+       return stbi__err("invalid width", "PPM image header had zero or overflowing width");
    stbi__pnm_skip_whitespace(s, &c);
 
    maxv = stbi__pnm_getinteger(s, &c);  // read max value
− raylib/src/external/stb_vorbis.h
@@ -1,5475 +0,0 @@-// Ogg Vorbis audio decoder - v1.14 - public domain
-// http://nothings.org/stb_vorbis/
-//
-// Original version written by Sean Barrett in 2007.
-//
-// Originally sponsored by RAD Game Tools. Seeking implementation
-// sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker,
-// Elias Software, Aras Pranckevicius, and Sean Barrett.
-//
-// LICENSE
-//
-//   See end of file for license information.
-//
-// Limitations:
-//
-//   - floor 0 not supported (used in old ogg vorbis files pre-2004)
-//   - lossless sample-truncation at beginning ignored
-//   - cannot concatenate multiple vorbis streams
-//   - sample positions are 32-bit, limiting seekable 192Khz
-//       files to around 6 hours (Ogg supports 64-bit)
-//
-// Feature contributors:
-//    Dougall Johnson (sample-exact seeking)
-//
-// Bugfix/warning contributors:
-//    Terje Mathisen     Niklas Frykholm     Andy Hill
-//    Casey Muratori     John Bolton         Gargaj
-//    Laurent Gomila     Marc LeBlanc        Ronny Chevalier
-//    Bernhard Wodo      Evan Balster        alxprd@github
-//    Tom Beaumont       Ingo Leitgeb        Nicolas Guillemot
-//    Phillip Bennefall  Rohit               Thiago Goulart
-//    manxorist@github   saga musix          github:infatum
-//    Timur Gagiev       BareRose
-//
-// Partial history:
-//    1.14    - 2018-02-11 - delete bogus dealloca usage
-//    1.13    - 2018-01-29 - fix truncation of last frame (hopefully)
-//    1.12    - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
-//    1.11    - 2017-07-23 - fix MinGW compilation 
-//    1.10    - 2017-03-03 - more robust seeking; fix negative stbv_ilog(); clear error in open_memory
-//    1.09    - 2016-04-04 - back out 'truncation of last frame' fix from previous version
-//    1.08    - 2016-04-02 - warnings; setup memory leaks; truncation of last frame
-//    1.07    - 2015-01-16 - fixes for crashes on invalid files; warning fixes; const
-//    1.06    - 2015-08-31 - full, correct support for seeking API (Dougall Johnson)
-//                           some crash fixes when out of memory or with corrupt files
-//                           fix some inappropriately signed shifts
-//    1.05    - 2015-04-19 - don't define __forceinline if it's redundant
-//    1.04    - 2014-08-27 - fix missing const-correct case in API
-//    1.03    - 2014-08-07 - warning fixes
-//    1.02    - 2014-07-09 - declare qsort comparison as explicitly _cdecl in Windows
-//    1.01    - 2014-06-18 - fix stb_vorbis_get_samples_float (interleaved was correct)
-//    1.0     - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
-//                           (API change) report sample rate for decode-full-file funcs
-//
-// See end of file for full version history.
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-//  HEADER BEGINS HERE
-//
-
-#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H
-#define STB_VORBIS_INCLUDE_STB_VORBIS_H
-
-#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)
-#define STB_VORBIS_NO_STDIO
-#endif
-
-#ifndef STB_VORBIS_NO_STDIO
-#include <stdio.h>
-#endif
-
-// NOTE: Added to work with raylib on Android
-#if defined(PLATFORM_ANDROID)
-    #include "utils.h"  // Android fopen function map
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef STB_VORBIS_STATIC
-#define STBVDEF static
-#else
-#define STBVDEF extern
-#endif
-
-///////////   THREAD SAFETY
-
-// Individual stb_vorbis* handles are not thread-safe; you cannot decode from
-// them from multiple threads at the same time. However, you can have multiple
-// stb_vorbis* handles and decode from them independently in multiple thrads.
-
-
-///////////   MEMORY ALLOCATION
-
-// normally stb_vorbis uses malloc() to allocate memory at startup,
-// and alloca() to allocate temporary memory during a frame on the
-// stack. (Memory consumption will depend on the amount of setup
-// data in the file and how you set the compile flags for speed
-// vs. size. In my test files the maximal-size usage is ~150KB.)
-//
-// You can modify the wrapper functions in the source (stbv_setup_malloc,
-// stbv_setup_temp_malloc, temp_malloc) to change this behavior, or you
-// can use a simpler allocation model: you pass in a buffer from
-// which stb_vorbis will allocate _all_ its memory (including the
-// temp memory). "open" may fail with a VORBIS_outofmem if you
-// do not pass in enough data; there is no way to determine how
-// much you do need except to succeed (at which point you can
-// query get_info to find the exact amount required. yes I know
-// this is lame).
-//
-// If you pass in a non-NULL buffer of the type below, allocation
-// will occur from it as described above. Otherwise just pass NULL
-// to use malloc()/alloca()
-
-typedef struct
-{
-   char *alloc_buffer;
-   int   alloc_buffer_length_in_bytes;
-} stb_vorbis_alloc;
-
-
-///////////   FUNCTIONS USEABLE WITH ALL INPUT MODES
-
-typedef struct stb_vorbis stb_vorbis;
-
-typedef struct
-{
-   unsigned int sample_rate;
-   int channels;
-
-   unsigned int setup_memory_required;
-   unsigned int setup_temp_memory_required;
-   unsigned int temp_memory_required;
-
-   int max_frame_size;
-} stb_vorbis_info;
-
-// get general information about the file
-STBVDEF stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f);
-
-// get the last error detected (clears it, too)
-STBVDEF int stb_vorbis_get_error(stb_vorbis *f);
-
-// close an ogg vorbis file and free all memory in use
-STBVDEF void stb_vorbis_close(stb_vorbis *f);
-
-// this function returns the offset (in samples) from the beginning of the
-// file that will be returned by the next decode, if it is known, or -1
-// otherwise. after a flush_pushdata() call, this may take a while before
-// it becomes valid again.
-// NOT WORKING YET after a seek with PULLDATA API
-STBVDEF int stb_vorbis_get_sample_offset(stb_vorbis *f);
-
-// returns the current seek point within the file, or offset from the beginning
-// of the memory buffer. In pushdata mode it returns 0.
-STBVDEF unsigned int stb_vorbis_get_file_offset(stb_vorbis *f);
-
-///////////   PUSHDATA API
-
-#ifndef STB_VORBIS_NO_PUSHDATA_API
-
-// this API allows you to get blocks of data from any source and hand
-// them to stb_vorbis. you have to buffer them; stb_vorbis will tell
-// you how much it used, and you have to give it the rest next time;
-// and stb_vorbis may not have enough data to work with and you will
-// need to give it the same data again PLUS more. Note that the Vorbis
-// specification does not bound the size of an individual frame.
-
-STBVDEF stb_vorbis *stb_vorbis_open_pushdata(
-         const unsigned char * datablock, int datablock_length_in_bytes,
-         int *datablock_memory_consumed_in_bytes,
-         int *error,
-         const stb_vorbis_alloc *alloc_buffer);
-// create a vorbis decoder by passing in the initial data block containing
-//    the ogg&vorbis headers (you don't need to do parse them, just provide
-//    the first N bytes of the file--you're told if it's not enough, see below)
-// on success, returns an stb_vorbis *, does not set error, returns the amount of
-//    data parsed/consumed on this call in *datablock_memory_consumed_in_bytes;
-// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed
-// if returns NULL and *error is VORBIS_need_more_data, then the input block was
-//       incomplete and you need to pass in a larger block from the start of the file
-
-STBVDEF int stb_vorbis_decode_frame_pushdata(
-         stb_vorbis *f,
-         const unsigned char *datablock, int datablock_length_in_bytes,
-         int *channels,             // place to write number of float * buffers
-         float ***output,           // place to write float ** array of float * buffers
-         int *samples               // place to write number of output samples
-     );
-// decode a frame of audio sample data if possible from the passed-in data block
-//
-// return value: number of bytes we used from datablock
-//
-// possible cases:
-//     0 bytes used, 0 samples output (need more data)
-//     N bytes used, 0 samples output (resynching the stream, keep going)
-//     N bytes used, M samples output (one frame of data)
-// note that after opening a file, you will ALWAYS get one N-bytes,0-sample
-// frame, because Vorbis always "discards" the first frame.
-//
-// Note that on resynch, stb_vorbis will rarely consume all of the buffer,
-// instead only datablock_length_in_bytes-3 or less. This is because it wants
-// to avoid missing parts of a page header if they cross a datablock boundary,
-// without writing state-machiney code to record a partial detection.
-//
-// The number of channels returned are stored in *channels (which can be
-// NULL--it is always the same as the number of channels reported by
-// get_info). *output will contain an array of float* buffers, one per
-// channel. In other words, (*output)[0][0] contains the first sample from
-// the first channel, and (*output)[1][0] contains the first sample from
-// the second channel.
-
-STBVDEF void stb_vorbis_flush_pushdata(stb_vorbis *f);
-// inform stb_vorbis that your next datablock will not be contiguous with
-// previous ones (e.g. you've seeked in the data); future attempts to decode
-// frames will cause stb_vorbis to resynchronize (as noted above), and
-// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it
-// will begin decoding the _next_ frame.
-//
-// if you want to seek using pushdata, you need to seek in your file, then
-// call stb_vorbis_flush_pushdata(), then start calling decoding, then once
-// decoding is returning you data, call stb_vorbis_get_sample_offset, and
-// if you don't like the result, seek your file again and repeat.
-#endif
-
-
-//////////   PULLING INPUT API
-
-#ifndef STB_VORBIS_NO_PULLDATA_API
-// This API assumes stb_vorbis is allowed to pull data from a source--
-// either a block of memory containing the _entire_ vorbis stream, or a
-// FILE * that you or it create, or possibly some other reading mechanism
-// if you go modify the source to replace the FILE * case with some kind
-// of callback to your code. (But if you don't support seeking, you may
-// just want to go ahead and use pushdata.)
-
-#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION)
-STBVDEF int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output);
-#endif
-#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
-STBVDEF int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output);
-#endif
-// decode an entire file and output the data interleaved into a malloc()ed
-// buffer stored in *output. The return value is the number of samples
-// decoded, or -1 if the file could not be opened or was not an ogg vorbis file.
-// When you're done with it, just free() the pointer returned in *output.
-
-STBVDEF stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len,
-                                  int *error, const stb_vorbis_alloc *alloc_buffer);
-// create an ogg vorbis decoder from an ogg vorbis stream in memory (note
-// this must be the entire stream!). on failure, returns NULL and sets *error
-
-#ifndef STB_VORBIS_NO_STDIO
-STBVDEF stb_vorbis * stb_vorbis_open_filename(const char *filename,
-                                  int *error, const stb_vorbis_alloc *alloc_buffer);
-// create an ogg vorbis decoder from a filename via fopen(). on failure,
-// returns NULL and sets *error (possibly to VORBIS_file_open_failure).
-
-STBVDEF stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
-                                  int *error, const stb_vorbis_alloc *alloc_buffer);
-// create an ogg vorbis decoder from an open FILE *, looking for a stream at
-// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
-// note that stb_vorbis must "own" this stream; if you seek it in between
-// calls to stb_vorbis, it will become confused. Morever, if you attempt to
-// perform stb_vorbis_seek_*() operations on this file, it will assume it
-// owns the _entire_ rest of the file after the start point. Use the next
-// function, stb_vorbis_open_file_section(), to limit it.
-
-STBVDEF stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,
-                int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len);
-// create an ogg vorbis decoder from an open FILE *, looking for a stream at
-// the _current_ seek point (ftell); the stream will be of length 'len' bytes.
-// on failure, returns NULL and sets *error. note that stb_vorbis must "own"
-// this stream; if you seek it in between calls to stb_vorbis, it will become
-// confused.
-#endif
-
-STBVDEF int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);
-STBVDEF int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
-// these functions seek in the Vorbis file to (approximately) 'sample_number'.
-// after calling seek_frame(), the next call to get_frame_*() will include
-// the specified sample. after calling stb_vorbis_seek(), the next call to
-// stb_vorbis_get_samples_* will start with the specified sample. If you
-// do not need to seek to EXACTLY the target sample when using get_samples_*,
-// you can also use seek_frame().
-
-STBVDEF int stb_vorbis_seek_start(stb_vorbis *f);
-// this function is equivalent to stb_vorbis_seek(f,0)
-
-STBVDEF unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);
-STBVDEF float        stb_vorbis_stream_length_in_seconds(stb_vorbis *f);
-// these functions return the total length of the vorbis stream
-
-STBVDEF int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output);
-// decode the next frame and return the number of samples. the number of
-// channels returned are stored in *channels (which can be NULL--it is always
-// the same as the number of channels reported by get_info). *output will
-// contain an array of float* buffers, one per channel. These outputs will
-// be overwritten on the next call to stb_vorbis_get_frame_*.
-//
-// You generally should not intermix calls to stb_vorbis_get_frame_*()
-// and stb_vorbis_get_samples_*(), since the latter calls the former.
-
-#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
-STBVDEF int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);
-STBVDEF int stb_vorbis_get_frame_short            (stb_vorbis *f, int num_c, short **buffer, int num_samples);
-#endif
-// decode the next frame and return the number of *samples* per channel.
-// Note that for interleaved data, you pass in the number of shorts (the
-// size of your array), but the return value is the number of samples per
-// channel, not the total number of samples.
-//
-// The data is coerced to the number of channels you request according to the
-// channel coercion rules (see below). You must pass in the size of your
-// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
-// The maximum buffer size needed can be gotten from get_info(); however,
-// the Vorbis I specification implies an absolute maximum of 4096 samples
-// per channel.
-
-// Channel coercion rules:
-//    Let M be the number of channels requested, and N the number of channels present,
-//    and Cn be the nth channel; let stereo L be the sum of all L and center channels,
-//    and stereo R be the sum of all R and center channels (channel assignment from the
-//    vorbis spec).
-//        M    N       output
-//        1    k      sum(Ck) for all k
-//        2    *      stereo L, stereo R
-//        k    l      k > l, the first l channels, then 0s
-//        k    l      k <= l, the first k channels
-//    Note that this is not _good_ surround etc. mixing at all! It's just so
-//    you get something useful.
-
-STBVDEF int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats);
-STBVDEF int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples);
-// gets num_samples samples, not necessarily on a frame boundary--this requires
-// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES.
-// Returns the number of samples stored per channel; it may be less than requested
-// at the end of the file. If there are no more samples in the file, returns 0.
-
-#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
-STBVDEF int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts);
-STBVDEF int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples);
-#endif
-// gets num_samples samples, not necessarily on a frame boundary--this requires
-// buffering so you have to supply the buffers. Applies the coercion rules above
-// to produce 'channels' channels. Returns the number of samples stored per channel;
-// it may be less than requested at the end of the file. If there are no more
-// samples in the file, returns 0.
-
-#endif
-
-////////   ERROR CODES
-
-enum STBVorbisError
-{
-   VORBIS__no_error,
-
-   VORBIS_need_more_data=1,             // not a real error
-
-   VORBIS_invalid_api_mixing,           // can't mix API modes
-   VORBIS_outofmem,                     // not enough memory
-   VORBIS_feature_not_supported,        // uses floor 0
-   VORBIS_too_many_channels,            // STB_VORBIS_MAX_CHANNELS is too small
-   VORBIS_file_open_failure,            // fopen() failed
-   VORBIS_seek_without_length,          // can't seek in unknown-length file
-
-   VORBIS_unexpected_eof=10,            // file is truncated?
-   VORBIS_seek_invalid,                 // seek past EOF
-
-   // decoding errors (corrupt/invalid stream) -- you probably
-   // don't care about the exact details of these
-
-   // vorbis errors:
-   VORBIS_invalid_setup=20,
-   VORBIS_invalid_stream,
-
-   // ogg errors:
-   VORBIS_missing_capture_pattern=30,
-   VORBIS_invalid_stream_structure_version,
-   VORBIS_continued_packet_flag_invalid,
-   VORBIS_incorrect_stream_serial_number,
-   VORBIS_invalid_first_page,
-   VORBIS_bad_packet_type,
-   VORBIS_cant_find_last_page,
-   VORBIS_seek_failed
-};
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H
-//
-//  HEADER ENDS HERE
-//
-//////////////////////////////////////////////////////////////////////////////
-
-#ifdef STB_VORBIS_IMPLEMENTATION
-
-// global configuration settings (e.g. set these in the project/makefile),
-// or just set them in this file at the top (although ideally the first few
-// should be visible when the header file is compiled too, although it's not
-// crucial)
-
-// STB_VORBIS_NO_PUSHDATA_API
-//     does not compile the code for the various stb_vorbis_*_pushdata()
-//     functions
-// #define STB_VORBIS_NO_PUSHDATA_API
-
-// STB_VORBIS_NO_PULLDATA_API
-//     does not compile the code for the non-pushdata APIs
-// #define STB_VORBIS_NO_PULLDATA_API
-
-// STB_VORBIS_NO_STDIO
-//     does not compile the code for the APIs that use FILE *s internally
-//     or externally (implied by STB_VORBIS_NO_PULLDATA_API)
-// #define STB_VORBIS_NO_STDIO
-
-// STB_VORBIS_NO_INTEGER_CONVERSION
-//     does not compile the code for converting audio sample data from
-//     float to integer (implied by STB_VORBIS_NO_PULLDATA_API)
-// #define STB_VORBIS_NO_INTEGER_CONVERSION
-
-// STB_VORBIS_NO_FAST_SCALED_FLOAT
-//      does not use a fast float-to-int trick to accelerate float-to-int on
-//      most platforms which requires endianness be defined correctly.
-// #define STB_VORBIS_NO_FAST_SCALED_FLOAT
-
-
-// STB_VORBIS_MAX_CHANNELS [number]
-//     globally define this to the maximum number of channels you need.
-//     The spec does not put a restriction on channels except that
-//     the count is stored in a byte, so 255 is the hard limit.
-//     Reducing this saves about 16 bytes per value, so using 16 saves
-//     (255-16)*16 or around 4KB. Plus anything other memory usage
-//     I forgot to account for. Can probably go as low as 8 (7.1 audio),
-//     6 (5.1 audio), or 2 (stereo only).
-#ifndef STB_VORBIS_MAX_CHANNELS
-#define STB_VORBIS_MAX_CHANNELS    16  // enough for anyone?
-#endif
-
-// STB_VORBIS_PUSHDATA_CRC_COUNT [number]
-//     after a flush_pushdata(), stb_vorbis begins scanning for the
-//     next valid page, without backtracking. when it finds something
-//     that looks like a page, it streams through it and verifies its
-//     CRC32. Should that validation fail, it keeps scanning. But it's
-//     possible that _while_ streaming through to check the CRC32 of
-//     one candidate page, it sees another candidate page. This #define
-//     determines how many "overlapping" candidate pages it can search
-//     at once. Note that "real" pages are typically ~4KB to ~8KB, whereas
-//     garbage pages could be as big as 64KB, but probably average ~16KB.
-//     So don't hose ourselves by scanning an apparent 64KB page and
-//     missing a ton of real ones in the interim; so minimum of 2
-#ifndef STB_VORBIS_PUSHDATA_CRC_COUNT
-#define STB_VORBIS_PUSHDATA_CRC_COUNT  4
-#endif
-
-// STB_VORBIS_FAST_HUFFMAN_LENGTH [number]
-//     sets the log size of the huffman-acceleration table.  Maximum
-//     supported value is 24. with larger numbers, more decodings are O(1),
-//     but the table size is larger so worse cache missing, so you'll have
-//     to probe (and try multiple ogg vorbis files) to find the sweet spot.
-#ifndef STB_VORBIS_FAST_HUFFMAN_LENGTH
-#define STB_VORBIS_FAST_HUFFMAN_LENGTH   10
-#endif
-
-// STB_VORBIS_FAST_BINARY_LENGTH [number]
-//     sets the log size of the binary-search acceleration table. this
-//     is used in similar fashion to the fast-huffman size to set initial
-//     parameters for the binary search
-
-// STB_VORBIS_FAST_HUFFMAN_INT
-//     The fast huffman tables are much more efficient if they can be
-//     stored as 16-bit results instead of 32-bit results. This restricts
-//     the codebooks to having only 65535 possible outcomes, though.
-//     (At least, accelerated by the huffman table.)
-#ifndef STB_VORBIS_FAST_HUFFMAN_INT
-#define STB_VORBIS_FAST_HUFFMAN_SHORT
-#endif
-
-// STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH
-//     If the 'fast huffman' search doesn't succeed, then stb_vorbis falls
-//     back on binary searching for the correct one. This requires storing
-//     extra tables with the huffman codes in sorted order. Defining this
-//     symbol trades off space for speed by forcing a linear search in the
-//     non-fast case, except for "sparse" codebooks.
-// #define STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH
-
-// STB_VORBIS_DIVIDES_IN_RESIDUE
-//     stb_vorbis precomputes the result of the scalar residue decoding
-//     that would otherwise require a divide per chunk. you can trade off
-//     space for time by defining this symbol.
-// #define STB_VORBIS_DIVIDES_IN_RESIDUE
-
-// STB_VORBIS_DIVIDES_IN_CODEBOOK
-//     vorbis VQ codebooks can be encoded two ways: with every case explicitly
-//     stored, or with all elements being chosen from a small range of values,
-//     and all values possible in all elements. By default, stb_vorbis expands
-//     this latter kind out to look like the former kind for ease of decoding,
-//     because otherwise an integer divide-per-vector-element is required to
-//     unpack the index. If you define STB_VORBIS_DIVIDES_IN_CODEBOOK, you can
-//     trade off storage for speed.
-//#define STB_VORBIS_DIVIDES_IN_CODEBOOK
-
-#ifdef STB_VORBIS_CODEBOOK_SHORTS
-#error "STB_VORBIS_CODEBOOK_SHORTS is no longer supported as it produced incorrect results for some input formats"
-#endif
-
-// STB_VORBIS_DIVIDE_TABLE
-//     this replaces small integer divides in the floor decode loop with
-//     table lookups. made less than 1% difference, so disabled by default.
-
-// STB_VORBIS_NO_INLINE_DECODE
-//     disables the inlining of the scalar codebook fast-huffman decode.
-//     might save a little codespace; useful for debugging
-// #define STB_VORBIS_NO_INLINE_DECODE
-
-// STB_VORBIS_NO_DEFER_FLOOR
-//     Normally we only decode the floor without synthesizing the actual
-//     full curve. We can instead synthesize the curve immediately. This
-//     requires more memory and is very likely slower, so I don't think
-//     you'd ever want to do it except for debugging.
-// #define STB_VORBIS_NO_DEFER_FLOOR
-
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-
-#ifdef STB_VORBIS_NO_PULLDATA_API
-   #define STB_VORBIS_NO_INTEGER_CONVERSION
-   #define STB_VORBIS_NO_STDIO
-#endif
-
-#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)
-   #define STB_VORBIS_NO_STDIO 1
-#endif
-
-#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
-#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT
-
-   // only need endianness for fast-float-to-int, which we don't
-   // use for pushdata
-
-   #ifndef STB_VORBIS_BIG_ENDIAN
-     #define STB_VORBIS_ENDIAN  0
-   #else
-     #define STB_VORBIS_ENDIAN  1
-   #endif
-
-#endif
-#endif
-
-
-#ifndef STB_VORBIS_NO_STDIO
-#include <stdio.h>
-#endif
-
-#ifndef STB_VORBIS_NO_CRT
-   #include <stdlib.h>
-   #include <string.h>
-   #include <assert.h>
-   #include <math.h>
-
-   // find definition of alloca if it's not in stdlib.h:
-   #if defined(_MSC_VER) || defined(__MINGW32__)
-      #include <malloc.h>
-   #endif
-   #if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) || defined(__APPLE__) || defined(__CYGWIN__)
-      #include <alloca.h>
-   #endif
-#else // STB_VORBIS_NO_CRT
-   #define NULL 0
-   #define malloc(s)   0
-   #define free(s)     ((void) 0)
-   #define realloc(s)  0
-#endif // STB_VORBIS_NO_CRT
-
-#include <limits.h>
-
-#ifdef __MINGW32__
-   // eff you mingw:
-   //     "fixed":
-   //         http://sourceforge.net/p/mingw-w64/mailman/message/32882927/
-   //     "no that broke the build, reverted, who cares about C":
-   //         http://sourceforge.net/p/mingw-w64/mailman/message/32890381/
-   #ifdef __forceinline
-   #undef __forceinline
-   #endif
-   #define __forceinline
-   #ifndef alloca
-   #define alloca(s) __builtin_alloca(s)
-   #endif
-#elif !defined(_MSC_VER)
-   #if __GNUC__
-      #define __forceinline inline
-   #else
-      #define __forceinline
-   #endif
-#endif
-
-#if STB_VORBIS_MAX_CHANNELS > 256
-#error "Value of STB_VORBIS_MAX_CHANNELS outside of allowed range"
-#endif
-
-#if STB_VORBIS_FAST_HUFFMAN_LENGTH > 24
-#error "Value of STB_VORBIS_FAST_HUFFMAN_LENGTH outside of allowed range"
-#endif
-
-
-#if 0
-#include <crtdbg.h>
-#define STBV_CHECK(f)   _CrtIsValidHeapPointer(f->channel_buffers[1])
-#else
-#define STBV_CHECK(f)   ((void) 0)
-#endif
-
-#define STBV_MAX_BLOCKSIZE_LOG  13   // from specification
-#define STBV_MAX_BLOCKSIZE      (1 << STBV_MAX_BLOCKSIZE_LOG)
-
-
-typedef unsigned char  stbv_uint8;
-typedef   signed char  stbv_int8;
-typedef unsigned short stbv_uint16;
-typedef   signed short stbv_int16;
-typedef unsigned int   stbv_uint32;
-typedef   signed int   stbv_int32;
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-
-typedef float stbv_codetype;
-
-// @NOTE
-//
-// Some arrays below are tagged "//varies", which means it's actually
-// a variable-sized piece of data, but rather than malloc I assume it's
-// small enough it's better to just allocate it all together with the
-// main thing
-//
-// Most of the variables are specified with the smallest size I could pack
-// them into. It might give better performance to make them all full-sized
-// integers. It should be safe to freely rearrange the structures or change
-// the sizes larger--nothing relies on silently truncating etc., nor the
-// order of variables.
-
-#define STBV_FAST_HUFFMAN_TABLE_SIZE   (1 << STB_VORBIS_FAST_HUFFMAN_LENGTH)
-#define STBV_FAST_HUFFMAN_TABLE_MASK   (STBV_FAST_HUFFMAN_TABLE_SIZE - 1)
-
-typedef struct
-{
-   int dimensions, entries;
-   stbv_uint8 *codeword_lengths;
-   float  minimum_value;
-   float  delta_value;
-   stbv_uint8  value_bits;
-   stbv_uint8  lookup_type;
-   stbv_uint8  sequence_p;
-   stbv_uint8  sparse;
-   stbv_uint32 lookup_values;
-   stbv_codetype *multiplicands;
-   stbv_uint32 *codewords;
-   #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT
-    stbv_int16  fast_huffman[STBV_FAST_HUFFMAN_TABLE_SIZE];
-   #else
-    stbv_int32  fast_huffman[STBV_FAST_HUFFMAN_TABLE_SIZE];
-   #endif
-   stbv_uint32 *sorted_codewords;
-   int    *sorted_values;
-   int     sorted_entries;
-} StbvCodebook;
-
-typedef struct
-{
-   stbv_uint8 order;
-   stbv_uint16 rate;
-   stbv_uint16 bark_map_size;
-   stbv_uint8 amplitude_bits;
-   stbv_uint8 amplitude_offset;
-   stbv_uint8 number_of_books;
-   stbv_uint8 book_list[16]; // varies
-} StbvFloor0;
-
-typedef struct
-{
-   stbv_uint8 partitions;
-   stbv_uint8 partition_class_list[32]; // varies
-   stbv_uint8 class_dimensions[16]; // varies
-   stbv_uint8 class_subclasses[16]; // varies
-   stbv_uint8 class_masterbooks[16]; // varies
-   stbv_int16 subclass_books[16][8]; // varies
-   stbv_uint16 Xlist[31*8+2]; // varies
-   stbv_uint8 sorted_order[31*8+2];
-   stbv_uint8 stbv_neighbors[31*8+2][2];
-   stbv_uint8 floor1_multiplier;
-   stbv_uint8 rangebits;
-   int values;
-} StbvFloor1;
-
-typedef union
-{
-   StbvFloor0 floor0;
-   StbvFloor1 floor1;
-} StbvFloor;
-
-typedef struct
-{
-   stbv_uint32 begin, end;
-   stbv_uint32 part_size;
-   stbv_uint8 classifications;
-   stbv_uint8 classbook;
-   stbv_uint8 **classdata;
-   stbv_int16 (*residue_books)[8];
-} StbvResidue;
-
-typedef struct
-{
-   stbv_uint8 magnitude;
-   stbv_uint8 angle;
-   stbv_uint8 mux;
-} StbvMappingChannel;
-
-typedef struct
-{
-   stbv_uint16 coupling_steps;
-   StbvMappingChannel *chan;
-   stbv_uint8  submaps;
-   stbv_uint8  submap_floor[15]; // varies
-   stbv_uint8  submap_residue[15]; // varies
-} StbvMapping;
-
-typedef struct
-{
-   stbv_uint8 blockflag;
-   stbv_uint8 mapping;
-   stbv_uint16 windowtype;
-   stbv_uint16 transformtype;
-} StbvMode;
-
-typedef struct
-{
-   stbv_uint32  goal_crc;    // expected crc if match
-   int     bytes_left;  // bytes left in packet
-   stbv_uint32  crc_so_far;  // running crc
-   int     bytes_done;  // bytes processed in _current_ chunk
-   stbv_uint32  sample_loc;  // granule pos encoded in page
-} StbvCRCscan;
-
-typedef struct
-{
-   stbv_uint32 page_start, page_end;
-   stbv_uint32 last_decoded_sample;
-} StbvProbedPage;
-
-struct stb_vorbis
-{
-  // user-accessible info
-   unsigned int sample_rate;
-   int channels;
-
-   unsigned int setup_memory_required;
-   unsigned int temp_memory_required;
-   unsigned int setup_temp_memory_required;
-
-  // input config
-#ifndef STB_VORBIS_NO_STDIO
-   FILE *f;
-   stbv_uint32 f_start;
-   int close_on_free;
-#endif
-
-   stbv_uint8 *stream;
-   stbv_uint8 *stream_start;
-   stbv_uint8 *stream_end;
-
-   stbv_uint32 stream_len;
-
-   stbv_uint8  push_mode;
-
-   stbv_uint32 first_audio_page_offset;
-
-   StbvProbedPage p_first, p_last;
-
-  // memory management
-   stb_vorbis_alloc alloc;
-   int setup_offset;
-   int temp_offset;
-
-  // run-time results
-   int eof;
-   enum STBVorbisError error;
-
-  // user-useful data
-
-  // header info
-   int blocksize[2];
-   int blocksize_0, blocksize_1;
-   int codebook_count;
-   StbvCodebook *codebooks;
-   int floor_count;
-   stbv_uint16 floor_types[64]; // varies
-   StbvFloor *floor_config;
-   int residue_count;
-   stbv_uint16 residue_types[64]; // varies
-   StbvResidue *residue_config;
-   int mapping_count;
-   StbvMapping *mapping;
-   int mode_count;
-   StbvMode mode_config[64];  // varies
-
-   stbv_uint32 total_samples;
-
-  // decode buffer
-   float *channel_buffers[STB_VORBIS_MAX_CHANNELS];
-   float *outputs        [STB_VORBIS_MAX_CHANNELS];
-
-   float *previous_window[STB_VORBIS_MAX_CHANNELS];
-   int previous_length;
-
-   #ifndef STB_VORBIS_NO_DEFER_FLOOR
-   stbv_int16 *finalY[STB_VORBIS_MAX_CHANNELS];
-   #else
-   float *floor_buffers[STB_VORBIS_MAX_CHANNELS];
-   #endif
-
-   stbv_uint32 current_loc; // sample location of next frame to decode
-   int    current_loc_valid;
-
-  // per-blocksize precomputed data
-   
-   // twiddle factors
-   float *A[2],*B[2],*C[2];
-   float *window[2];
-   stbv_uint16 *stbv_bit_reverse[2];
-
-  // current page/packet/segment streaming info
-   stbv_uint32 serial; // stream serial number for verification
-   int last_page;
-   int segment_count;
-   stbv_uint8 segments[255];
-   stbv_uint8 page_flag;
-   stbv_uint8 bytes_in_seg;
-   stbv_uint8 first_decode;
-   int next_seg;
-   int last_seg;  // flag that we're on the last segment
-   int last_seg_which; // what was the segment number of the last seg?
-   stbv_uint32 acc;
-   int valid_bits;
-   int packet_bytes;
-   int end_seg_with_known_loc;
-   stbv_uint32 known_loc_for_packet;
-   int discard_samples_deferred;
-   stbv_uint32 samples_output;
-
-  // push mode scanning
-   int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching
-#ifndef STB_VORBIS_NO_PUSHDATA_API
-   StbvCRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT];
-#endif
-
-  // sample-access
-   int channel_buffer_start;
-   int channel_buffer_end;
-};
-
-#if defined(STB_VORBIS_NO_PUSHDATA_API)
-   #define STBV_IS_PUSH_MODE(f)   FALSE
-#elif defined(STB_VORBIS_NO_PULLDATA_API)
-   #define STBV_IS_PUSH_MODE(f)   TRUE
-#else
-   #define STBV_IS_PUSH_MODE(f)   ((f)->push_mode)
-#endif
-
-typedef struct stb_vorbis stbv_vorb;
-
-static int stbv_error(stbv_vorb *f, enum STBVorbisError e)
-{
-   f->error = e;
-   if (!f->eof && e != VORBIS_need_more_data) {
-      f->error=e; // breakpoint for debugging
-   }
-   return 0;
-}
-
-
-// these functions are used for allocating temporary memory
-// while decoding. if you can afford the stack space, use
-// alloca(); otherwise, provide a temp buffer and it will
-// allocate out of those.
-
-#define stbv_array_size_required(count,size)  (count*(sizeof(void *)+(size)))
-
-#define stbv_temp_alloc(f,size)              (f->alloc.alloc_buffer ? stbv_setup_temp_malloc(f,size) : alloca(size))
-#define stbv_temp_free(f,p)                  0
-#define stbv_temp_alloc_save(f)              ((f)->temp_offset)
-#define stbv_temp_alloc_restore(f,p)         ((f)->temp_offset = (p))
-
-#define stbv_temp_block_array(f,count,size)  stbv_make_block_array(stbv_temp_alloc(f,stbv_array_size_required(count,size)), count, size)
-
-// given a sufficiently large block of memory, make an array of pointers to subblocks of it
-static void *stbv_make_block_array(void *mem, int count, int size)
-{
-   int i;
-   void ** p = (void **) mem;
-   char *q = (char *) (p + count);
-   for (i=0; i < count; ++i) {
-      p[i] = q;
-      q += size;
-   }
-   return p;
-}
-
-static void *stbv_setup_malloc(stbv_vorb *f, int sz)
-{
-   sz = (sz+3) & ~3;
-   f->setup_memory_required += sz;
-   if (f->alloc.alloc_buffer) {
-      void *p = (char *) f->alloc.alloc_buffer + f->setup_offset;
-      if (f->setup_offset + sz > f->temp_offset) return NULL;
-      f->setup_offset += sz;
-      return p;
-   }
-   return sz ? malloc(sz) : NULL;
-}
-
-static void stbv_setup_free(stbv_vorb *f, void *p)
-{
-   if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack
-   free(p);
-}
-
-static void *stbv_setup_temp_malloc(stbv_vorb *f, int sz)
-{
-   sz = (sz+3) & ~3;
-   if (f->alloc.alloc_buffer) {
-      if (f->temp_offset - sz < f->setup_offset) return NULL;
-      f->temp_offset -= sz;
-      return (char *) f->alloc.alloc_buffer + f->temp_offset;
-   }
-   return malloc(sz);
-}
-
-static void stbv_setup_temp_free(stbv_vorb *f, void *p, int sz)
-{
-   if (f->alloc.alloc_buffer) {
-      f->temp_offset += (sz+3)&~3;
-      return;
-   }
-   free(p);
-}
-
-#define STBV_CRC32_POLY    0x04c11db7   // from spec
-
-static stbv_uint32 stbv_crc_table[256];
-static void stbv_crc32_init(void)
-{
-   int i,j;
-   stbv_uint32 s;
-   for(i=0; i < 256; i++) {
-      for (s=(stbv_uint32) i << 24, j=0; j < 8; ++j)
-         s = (s << 1) ^ (s >= (1U<<31) ? STBV_CRC32_POLY : 0);
-      stbv_crc_table[i] = s;
-   }
-}
-
-static __forceinline stbv_uint32 stbv_crc32_update(stbv_uint32 crc, stbv_uint8 byte)
-{
-   return (crc << 8) ^ stbv_crc_table[byte ^ (crc >> 24)];
-}
-
-
-// used in setup, and for huffman that doesn't go fast path
-static unsigned int stbv_bit_reverse(unsigned int n)
-{
-  n = ((n & 0xAAAAAAAA) >>  1) | ((n & 0x55555555) << 1);
-  n = ((n & 0xCCCCCCCC) >>  2) | ((n & 0x33333333) << 2);
-  n = ((n & 0xF0F0F0F0) >>  4) | ((n & 0x0F0F0F0F) << 4);
-  n = ((n & 0xFF00FF00) >>  8) | ((n & 0x00FF00FF) << 8);
-  return (n >> 16) | (n << 16);
-}
-
-static float stbv_square(float x)
-{
-   return x*x;
-}
-
-// this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3
-// as required by the specification. fast(?) implementation from stb.h
-// @OPTIMIZE: called multiple times per-packet with "constants"; move to setup
-static int stbv_ilog(stbv_int32 n)
-{
-   static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 };
-
-   if (n < 0) return 0; // signed n returns 0
-
-   // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29)
-   if (n < (1 << 14))
-        if (n < (1 <<  4))            return  0 + log2_4[n      ];
-        else if (n < (1 <<  9))       return  5 + log2_4[n >>  5];
-             else                     return 10 + log2_4[n >> 10];
-   else if (n < (1 << 24))
-             if (n < (1 << 19))       return 15 + log2_4[n >> 15];
-             else                     return 20 + log2_4[n >> 20];
-        else if (n < (1 << 29))       return 25 + log2_4[n >> 25];
-             else                     return 30 + log2_4[n >> 30];
-}
-
-#ifndef M_PI
-  #define M_PI  3.14159265358979323846264f  // from CRC
-#endif
-
-// code length assigned to a value with no huffman encoding
-#define NO_CODE   255
-
-/////////////////////// LEAF SETUP FUNCTIONS //////////////////////////
-//
-// these functions are only called at setup, and only a few times
-// per file
-
-static float stbv_float32_unpack(stbv_uint32 x)
-{
-   // from the specification
-   stbv_uint32 mantissa = x & 0x1fffff;
-   stbv_uint32 sign = x & 0x80000000;
-   stbv_uint32 exp = (x & 0x7fe00000) >> 21;
-   double res = sign ? -(double)mantissa : (double)mantissa;
-   return (float) ldexp((float)res, exp-788);
-}
-
-
-// zlib & jpeg huffman tables assume that the output symbols
-// can either be arbitrarily arranged, or have monotonically
-// increasing frequencies--they rely on the lengths being sorted;
-// this makes for a very simple generation algorithm.
-// vorbis allows a huffman table with non-sorted lengths. This
-// requires a more sophisticated construction, since symbols in
-// order do not map to huffman codes "in order".
-static void stbv_add_entry(StbvCodebook *c, stbv_uint32 huff_code, int symbol, int count, int len, stbv_uint32 *values)
-{
-   if (!c->sparse) {
-      c->codewords      [symbol] = huff_code;
-   } else {
-      c->codewords       [count] = huff_code;
-      c->codeword_lengths[count] = len;
-      values             [count] = symbol;
-   }
-}
-
-static int stbv_compute_codewords(StbvCodebook *c, stbv_uint8 *len, int n, stbv_uint32 *values)
-{
-   int i,k,m=0;
-   stbv_uint32 available[32];
-
-   memset(available, 0, sizeof(available));
-   // find the first entry
-   for (k=0; k < n; ++k) if (len[k] < NO_CODE) break;
-   if (k == n) { assert(c->sorted_entries == 0); return TRUE; }
-   // add to the list
-   stbv_add_entry(c, 0, k, m++, len[k], values);
-   // add all available leaves
-   for (i=1; i <= len[k]; ++i)
-      available[i] = 1U << (32-i);
-   // note that the above code treats the first case specially,
-   // but it's really the same as the following code, so they
-   // could probably be combined (except the initial code is 0,
-   // and I use 0 in available[] to mean 'empty')
-   for (i=k+1; i < n; ++i) {
-      stbv_uint32 res;
-      int z = len[i], y;
-      if (z == NO_CODE) continue;
-      // find lowest available leaf (should always be earliest,
-      // which is what the specification calls for)
-      // note that this property, and the fact we can never have
-      // more than one free leaf at a given level, isn't totally
-      // trivial to prove, but it seems true and the assert never
-      // fires, so!
-      while (z > 0 && !available[z]) --z;
-      if (z == 0) { return FALSE; }
-      res = available[z];
-      assert(z >= 0 && z < 32);
-      available[z] = 0;
-      stbv_add_entry(c, stbv_bit_reverse(res), i, m++, len[i], values);
-      // propogate availability up the tree
-      if (z != len[i]) {
-         assert(len[i] >= 0 && len[i] < 32);
-         for (y=len[i]; y > z; --y) {
-            assert(available[y] == 0);
-            available[y] = res + (1 << (32-y));
-         }
-      }
-   }
-   return TRUE;
-}
-
-// accelerated huffman table allows fast O(1) match of all symbols
-// of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH
-static void stbv_compute_accelerated_huffman(StbvCodebook *c)
-{
-   int i, len;
-   for (i=0; i < STBV_FAST_HUFFMAN_TABLE_SIZE; ++i)
-      c->fast_huffman[i] = -1;
-
-   len = c->sparse ? c->sorted_entries : c->entries;
-   #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT
-   if (len > 32767) len = 32767; // largest possible value we can encode!
-   #endif
-   for (i=0; i < len; ++i) {
-      if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) {
-         stbv_uint32 z = c->sparse ? stbv_bit_reverse(c->sorted_codewords[i]) : c->codewords[i];
-         // set table entries for all bit combinations in the higher bits
-         while (z < STBV_FAST_HUFFMAN_TABLE_SIZE) {
-             c->fast_huffman[z] = i;
-             z += 1 << c->codeword_lengths[i];
-         }
-      }
-   }
-}
-
-#ifdef _MSC_VER
-#define STBV_CDECL __cdecl
-#else
-#define STBV_CDECL
-#endif
-
-static int STBV_CDECL stbv_uint32_compare(const void *p, const void *q)
-{
-   stbv_uint32 x = * (stbv_uint32 *) p;
-   stbv_uint32 y = * (stbv_uint32 *) q;
-   return x < y ? -1 : x > y;
-}
-
-static int stbv_include_in_sort(StbvCodebook *c, stbv_uint8 len)
-{
-   if (c->sparse) { assert(len != NO_CODE); return TRUE; }
-   if (len == NO_CODE) return FALSE;
-   if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE;
-   return FALSE;
-}
-
-// if the fast table above doesn't work, we want to binary
-// search them... need to reverse the bits
-static void stbv_compute_sorted_huffman(StbvCodebook *c, stbv_uint8 *lengths, stbv_uint32 *values)
-{
-   int i, len;
-   // build a list of all the entries
-   // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN.
-   // this is kind of a frivolous optimization--I don't see any performance improvement,
-   // but it's like 4 extra lines of code, so.
-   if (!c->sparse) {
-      int k = 0;
-      for (i=0; i < c->entries; ++i)
-         if (stbv_include_in_sort(c, lengths[i])) 
-            c->sorted_codewords[k++] = stbv_bit_reverse(c->codewords[i]);
-      assert(k == c->sorted_entries);
-   } else {
-      for (i=0; i < c->sorted_entries; ++i)
-         c->sorted_codewords[i] = stbv_bit_reverse(c->codewords[i]);
-   }
-
-   qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), stbv_uint32_compare);
-   c->sorted_codewords[c->sorted_entries] = 0xffffffff;
-
-   len = c->sparse ? c->sorted_entries : c->entries;
-   // now we need to indicate how they correspond; we could either
-   //   #1: sort a different data structure that says who they correspond to
-   //   #2: for each sorted entry, search the original list to find who corresponds
-   //   #3: for each original entry, find the sorted entry
-   // #1 requires extra storage, #2 is slow, #3 can use binary search!
-   for (i=0; i < len; ++i) {
-      int huff_len = c->sparse ? lengths[values[i]] : lengths[i];
-      if (stbv_include_in_sort(c,huff_len)) {
-         stbv_uint32 code = stbv_bit_reverse(c->codewords[i]);
-         int x=0, n=c->sorted_entries;
-         while (n > 1) {
-            // invariant: sc[x] <= code < sc[x+n]
-            int m = x + (n >> 1);
-            if (c->sorted_codewords[m] <= code) {
-               x = m;
-               n -= (n>>1);
-            } else {
-               n >>= 1;
-            }
-         }
-         assert(c->sorted_codewords[x] == code);
-         if (c->sparse) {
-            c->sorted_values[x] = values[i];
-            c->codeword_lengths[x] = huff_len;
-         } else {
-            c->sorted_values[x] = i;
-         }
-      }
-   }
-}
-
-// only run while parsing the header (3 times)
-static int stbv_vorbis_validate(stbv_uint8 *data)
-{
-   static stbv_uint8 vorbis[6] = { 'v', 'o', 'r', 'b', 'i', 's' };
-   return memcmp(data, vorbis, 6) == 0;
-}
-
-// called from setup only, once per code book
-// (formula implied by specification)
-static int stbv_lookup1_values(int entries, int dim)
-{
-   int r = (int) floor(exp((float) log((float) entries) / dim));
-   if ((int) floor(pow((float) r+1, dim)) <= entries)   // (int) cast for MinGW warning;
-      ++r;                                              // floor() to avoid _ftol() when non-CRT
-   assert(pow((float) r+1, dim) > entries);
-   assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above
-   return r;
-}
-
-// called twice per file
-static void stbv_compute_twiddle_factors(int n, float *A, float *B, float *C)
-{
-   int n4 = n >> 2, n8 = n >> 3;
-   int k,k2;
-
-   for (k=k2=0; k < n4; ++k,k2+=2) {
-      A[k2  ] = (float)  cos(4*k*M_PI/n);
-      A[k2+1] = (float) -sin(4*k*M_PI/n);
-      B[k2  ] = (float)  cos((k2+1)*M_PI/n/2) * 0.5f;
-      B[k2+1] = (float)  sin((k2+1)*M_PI/n/2) * 0.5f;
-   }
-   for (k=k2=0; k < n8; ++k,k2+=2) {
-      C[k2  ] = (float)  cos(2*(k2+1)*M_PI/n);
-      C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n);
-   }
-}
-
-static void stbv_compute_window(int n, float *window)
-{
-   int n2 = n >> 1, i;
-   for (i=0; i < n2; ++i)
-      window[i] = (float) sin(0.5 * M_PI * stbv_square((float) sin((i - 0 + 0.5) / n2 * 0.5 * M_PI)));
-}
-
-static void stbv_compute_bitreverse(int n, stbv_uint16 *rev)
-{
-   int ld = stbv_ilog(n) - 1; // stbv_ilog is off-by-one from normal definitions
-   int i, n8 = n >> 3;
-   for (i=0; i < n8; ++i)
-      rev[i] = (stbv_bit_reverse(i) >> (32-ld+3)) << 2;
-}
-
-static int stbv_init_blocksize(stbv_vorb *f, int b, int n)
-{
-   int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3;
-   f->A[b] = (float *) stbv_setup_malloc(f, sizeof(float) * n2);
-   f->B[b] = (float *) stbv_setup_malloc(f, sizeof(float) * n2);
-   f->C[b] = (float *) stbv_setup_malloc(f, sizeof(float) * n4);
-   if (!f->A[b] || !f->B[b] || !f->C[b]) return stbv_error(f, VORBIS_outofmem);
-   stbv_compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]);
-   f->window[b] = (float *) stbv_setup_malloc(f, sizeof(float) * n2);
-   if (!f->window[b]) return stbv_error(f, VORBIS_outofmem);
-   stbv_compute_window(n, f->window[b]);
-   f->stbv_bit_reverse[b] = (stbv_uint16 *) stbv_setup_malloc(f, sizeof(stbv_uint16) * n8);
-   if (!f->stbv_bit_reverse[b]) return stbv_error(f, VORBIS_outofmem);
-   stbv_compute_bitreverse(n, f->stbv_bit_reverse[b]);
-   return TRUE;
-}
-
-static void stbv_neighbors(stbv_uint16 *x, int n, int *plow, int *phigh)
-{
-   int low = -1;
-   int high = 65536;
-   int i;
-   for (i=0; i < n; ++i) {
-      if (x[i] > low  && x[i] < x[n]) { *plow  = i; low = x[i]; }
-      if (x[i] < high && x[i] > x[n]) { *phigh = i; high = x[i]; }
-   }
-}
-
-// this has been repurposed so y is now the original index instead of y
-typedef struct
-{
-   stbv_uint16 x,id;
-} stbv_floor_ordering;
-
-static int STBV_CDECL stbv_point_compare(const void *p, const void *q)
-{
-   stbv_floor_ordering *a = (stbv_floor_ordering *) p;
-   stbv_floor_ordering *b = (stbv_floor_ordering *) q;
-   return a->x < b->x ? -1 : a->x > b->x;
-}
-
-//
-/////////////////////// END LEAF SETUP FUNCTIONS //////////////////////////
-
-
-#if defined(STB_VORBIS_NO_STDIO)
-   #define STBV_USE_MEMORY(z)    TRUE
-#else
-   #define STBV_USE_MEMORY(z)    ((z)->stream)
-#endif
-
-static stbv_uint8 stbv_get8(stbv_vorb *z)
-{
-   if (STBV_USE_MEMORY(z)) {
-      if (z->stream >= z->stream_end) { z->eof = TRUE; return 0; }
-      return *z->stream++;
-   }
-
-   #ifndef STB_VORBIS_NO_STDIO
-   {
-   int c = fgetc(z->f);
-   if (c == EOF) { z->eof = TRUE; return 0; }
-   return c;
-   }
-   #endif
-}
-
-static stbv_uint32 stbv_get32(stbv_vorb *f)
-{
-   stbv_uint32 x;
-   x = stbv_get8(f);
-   x += stbv_get8(f) << 8;
-   x += stbv_get8(f) << 16;
-   x += (stbv_uint32) stbv_get8(f) << 24;
-   return x;
-}
-
-static int stbv_getn(stbv_vorb *z, stbv_uint8 *data, int n)
-{
-   if (STBV_USE_MEMORY(z)) {
-      if (z->stream+n > z->stream_end) { z->eof = 1; return 0; }
-      memcpy(data, z->stream, n);
-      z->stream += n;
-      return 1;
-   }
-
-   #ifndef STB_VORBIS_NO_STDIO   
-   if (fread(data, n, 1, z->f) == 1)
-      return 1;
-   else {
-      z->eof = 1;
-      return 0;
-   }
-   #endif
-}
-
-static void stbv_skip(stbv_vorb *z, int n)
-{
-   if (STBV_USE_MEMORY(z)) {
-      z->stream += n;
-      if (z->stream >= z->stream_end) z->eof = 1;
-      return;
-   }
-   #ifndef STB_VORBIS_NO_STDIO
-   {
-      long x = ftell(z->f);
-      fseek(z->f, x+n, SEEK_SET);
-   }
-   #endif
-}
-
-static int stbv_set_file_offset(stb_vorbis *f, unsigned int loc)
-{
-   #ifndef STB_VORBIS_NO_PUSHDATA_API
-   if (f->push_mode) return 0;
-   #endif
-   f->eof = 0;
-   if (STBV_USE_MEMORY(f)) {
-      if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) {
-         f->stream = f->stream_end;
-         f->eof = 1;
-         return 0;
-      } else {
-         f->stream = f->stream_start + loc;
-         return 1;
-      }
-   }
-   #ifndef STB_VORBIS_NO_STDIO
-   if (loc + f->f_start < loc || loc >= 0x80000000) {
-      loc = 0x7fffffff;
-      f->eof = 1;
-   } else {
-      loc += f->f_start;
-   }
-   if (!fseek(f->f, loc, SEEK_SET))
-      return 1;
-   f->eof = 1;
-   fseek(f->f, f->f_start, SEEK_END);
-   return 0;
-   #endif
-}
-
-
-static stbv_uint8 stbv_ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 };
-
-static int stbv_capture_pattern(stbv_vorb *f)
-{
-   if (0x4f != stbv_get8(f)) return FALSE;
-   if (0x67 != stbv_get8(f)) return FALSE;
-   if (0x67 != stbv_get8(f)) return FALSE;
-   if (0x53 != stbv_get8(f)) return FALSE;
-   return TRUE;
-}
-
-#define STBV_PAGEFLAG_continued_packet   1
-#define STBV_PAGEFLAG_first_page         2
-#define STBV_PAGEFLAG_last_page          4
-
-static int stbv_start_page_no_capturepattern(stbv_vorb *f)
-{
-   stbv_uint32 loc0,loc1,n;
-   // stream structure version
-   if (0 != stbv_get8(f)) return stbv_error(f, VORBIS_invalid_stream_structure_version);
-   // header flag
-   f->page_flag = stbv_get8(f);
-   // absolute granule position
-   loc0 = stbv_get32(f); 
-   loc1 = stbv_get32(f);
-   // @TODO: validate loc0,loc1 as valid positions?
-   // stream serial number -- vorbis doesn't interleave, so discard
-   stbv_get32(f);
-   //if (f->serial != stbv_get32(f)) return stbv_error(f, VORBIS_incorrect_stream_serial_number);
-   // page sequence number
-   n = stbv_get32(f);
-   f->last_page = n;
-   // CRC32
-   stbv_get32(f);
-   // page_segments
-   f->segment_count = stbv_get8(f);
-   if (!stbv_getn(f, f->segments, f->segment_count))
-      return stbv_error(f, VORBIS_unexpected_eof);
-   // assume we _don't_ know any the sample position of any segments
-   f->end_seg_with_known_loc = -2;
-   if (loc0 != ~0U || loc1 != ~0U) {
-      int i;
-      // determine which packet is the last one that will complete
-      for (i=f->segment_count-1; i >= 0; --i)
-         if (f->segments[i] < 255)
-            break;
-      // 'i' is now the index of the _last_ segment of a packet that ends
-      if (i >= 0) {
-         f->end_seg_with_known_loc = i;
-         f->known_loc_for_packet   = loc0;
-      }
-   }
-   if (f->first_decode) {
-      int i,len;
-      StbvProbedPage p;
-      len = 0;
-      for (i=0; i < f->segment_count; ++i)
-         len += f->segments[i];
-      len += 27 + f->segment_count;
-      p.page_start = f->first_audio_page_offset;
-      p.page_end = p.page_start + len;
-      p.last_decoded_sample = loc0;
-      f->p_first = p;
-   }
-   f->next_seg = 0;
-   return TRUE;
-}
-
-static int stbv_start_page(stbv_vorb *f)
-{
-   if (!stbv_capture_pattern(f)) return stbv_error(f, VORBIS_missing_capture_pattern);
-   return stbv_start_page_no_capturepattern(f);
-}
-
-static int stbv_start_packet(stbv_vorb *f)
-{
-   while (f->next_seg == -1) {
-      if (!stbv_start_page(f)) return FALSE;
-      if (f->page_flag & STBV_PAGEFLAG_continued_packet)
-         return stbv_error(f, VORBIS_continued_packet_flag_invalid);
-   }
-   f->last_seg = FALSE;
-   f->valid_bits = 0;
-   f->packet_bytes = 0;
-   f->bytes_in_seg = 0;
-   // f->next_seg is now valid
-   return TRUE;
-}
-
-static int stbv_maybe_start_packet(stbv_vorb *f)
-{
-   if (f->next_seg == -1) {
-      int x = stbv_get8(f);
-      if (f->eof) return FALSE; // EOF at page boundary is not an error!
-      if (0x4f != x      ) return stbv_error(f, VORBIS_missing_capture_pattern);
-      if (0x67 != stbv_get8(f)) return stbv_error(f, VORBIS_missing_capture_pattern);
-      if (0x67 != stbv_get8(f)) return stbv_error(f, VORBIS_missing_capture_pattern);
-      if (0x53 != stbv_get8(f)) return stbv_error(f, VORBIS_missing_capture_pattern);
-      if (!stbv_start_page_no_capturepattern(f)) return FALSE;
-      if (f->page_flag & STBV_PAGEFLAG_continued_packet) {
-         // set up enough state that we can read this packet if we want,
-         // e.g. during recovery
-         f->last_seg = FALSE;
-         f->bytes_in_seg = 0;
-         return stbv_error(f, VORBIS_continued_packet_flag_invalid);
-      }
-   }
-   return stbv_start_packet(f);
-}
-
-static int stbv_next_segment(stbv_vorb *f)
-{
-   int len;
-   if (f->last_seg) return 0;
-   if (f->next_seg == -1) {
-      f->last_seg_which = f->segment_count-1; // in case stbv_start_page fails
-      if (!stbv_start_page(f)) { f->last_seg = 1; return 0; }
-      if (!(f->page_flag & STBV_PAGEFLAG_continued_packet)) return stbv_error(f, VORBIS_continued_packet_flag_invalid);
-   }
-   len = f->segments[f->next_seg++];
-   if (len < 255) {
-      f->last_seg = TRUE;
-      f->last_seg_which = f->next_seg-1;
-   }
-   if (f->next_seg >= f->segment_count)
-      f->next_seg = -1;
-   assert(f->bytes_in_seg == 0);
-   f->bytes_in_seg = len;
-   return len;
-}
-
-#define STBV_EOP    (-1)
-#define STBV_INVALID_BITS  (-1)
-
-static int stbv_get8_packet_raw(stbv_vorb *f)
-{
-   if (!f->bytes_in_seg) {  // CLANG!
-      if (f->last_seg) return STBV_EOP;
-      else if (!stbv_next_segment(f)) return STBV_EOP;
-   }
-   assert(f->bytes_in_seg > 0);
-   --f->bytes_in_seg;
-   ++f->packet_bytes;
-   return stbv_get8(f);
-}
-
-static int stbv_get8_packet(stbv_vorb *f)
-{
-   int x = stbv_get8_packet_raw(f);
-   f->valid_bits = 0;
-   return x;
-}
-
-static void stbv_flush_packet(stbv_vorb *f)
-{
-   while (stbv_get8_packet_raw(f) != STBV_EOP);
-}
-
-// @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important
-// as the huffman decoder?
-static stbv_uint32 stbv_get_bits(stbv_vorb *f, int n)
-{
-   stbv_uint32 z;
-
-   if (f->valid_bits < 0) return 0;
-   if (f->valid_bits < n) {
-      if (n > 24) {
-         // the accumulator technique below would not work correctly in this case
-         z = stbv_get_bits(f, 24);
-         z += stbv_get_bits(f, n-24) << 24;
-         return z;
-      }
-      if (f->valid_bits == 0) f->acc = 0;
-      while (f->valid_bits < n) {
-         int z = stbv_get8_packet_raw(f);
-         if (z == STBV_EOP) {
-            f->valid_bits = STBV_INVALID_BITS;
-            return 0;
-         }
-         f->acc += z << f->valid_bits;
-         f->valid_bits += 8;
-      }
-   }
-   if (f->valid_bits < 0) return 0;
-   z = f->acc & ((1 << n)-1);
-   f->acc >>= n;
-   f->valid_bits -= n;
-   return z;
-}
-
-// @OPTIMIZE: primary accumulator for huffman
-// expand the buffer to as many bits as possible without reading off end of packet
-// it might be nice to allow f->valid_bits and f->acc to be stored in registers,
-// e.g. cache them locally and decode locally
-static __forceinline void stbv_prep_huffman(stbv_vorb *f)
-{
-   if (f->valid_bits <= 24) {
-      if (f->valid_bits == 0) f->acc = 0;
-      do {
-         int z;
-         if (f->last_seg && !f->bytes_in_seg) return;
-         z = stbv_get8_packet_raw(f);
-         if (z == STBV_EOP) return;
-         f->acc += (unsigned) z << f->valid_bits;
-         f->valid_bits += 8;
-      } while (f->valid_bits <= 24);
-   }
-}
-
-enum
-{
-   STBV_VORBIS_packet_id = 1,
-   STBV_VORBIS_packet_comment = 3,
-   STBV_VORBIS_packet_setup = 5
-};
-
-static int stbv_codebook_decode_scalar_raw(stbv_vorb *f, StbvCodebook *c)
-{
-   int i;
-   stbv_prep_huffman(f);
-
-   if (c->codewords == NULL && c->sorted_codewords == NULL)
-      return -1;
-
-   // cases to use binary search: sorted_codewords && !c->codewords
-   //                             sorted_codewords && c->entries > 8
-   if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) {
-      // binary search
-      stbv_uint32 code = stbv_bit_reverse(f->acc);
-      int x=0, n=c->sorted_entries, len;
-
-      while (n > 1) {
-         // invariant: sc[x] <= code < sc[x+n]
-         int m = x + (n >> 1);
-         if (c->sorted_codewords[m] <= code) {
-            x = m;
-            n -= (n>>1);
-         } else {
-            n >>= 1;
-         }
-      }
-      // x is now the sorted index
-      if (!c->sparse) x = c->sorted_values[x];
-      // x is now sorted index if sparse, or symbol otherwise
-      len = c->codeword_lengths[x];
-      if (f->valid_bits >= len) {
-         f->acc >>= len;
-         f->valid_bits -= len;
-         return x;
-      }
-
-      f->valid_bits = 0;
-      return -1;
-   }
-
-   // if small, linear search
-   assert(!c->sparse);
-   for (i=0; i < c->entries; ++i) {
-      if (c->codeword_lengths[i] == NO_CODE) continue;
-      if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) {
-         if (f->valid_bits >= c->codeword_lengths[i]) {
-            f->acc >>= c->codeword_lengths[i];
-            f->valid_bits -= c->codeword_lengths[i];
-            return i;
-         }
-         f->valid_bits = 0;
-         return -1;
-      }
-   }
-
-   stbv_error(f, VORBIS_invalid_stream);
-   f->valid_bits = 0;
-   return -1;
-}
-
-#ifndef STB_VORBIS_NO_INLINE_DECODE
-
-#define STBV_DECODE_RAW(var, f,c)                                  \
-   if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH)        \
-      stbv_prep_huffman(f);                                        \
-   var = f->acc & STBV_FAST_HUFFMAN_TABLE_MASK;                    \
-   var = c->fast_huffman[var];                                \
-   if (var >= 0) {                                            \
-      int n = c->codeword_lengths[var];                       \
-      f->acc >>= n;                                           \
-      f->valid_bits -= n;                                     \
-      if (f->valid_bits < 0) { f->valid_bits = 0; var = -1; } \
-   } else {                                                   \
-      var = stbv_codebook_decode_scalar_raw(f,c);                  \
-   }
-
-#else
-
-static int stbv_codebook_decode_scalar(stbv_vorb *f, StbvCodebook *c)
-{
-   int i;
-   if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH)
-      stbv_prep_huffman(f);
-   // fast huffman table lookup
-   i = f->acc & STBV_FAST_HUFFMAN_TABLE_MASK;
-   i = c->fast_huffman[i];
-   if (i >= 0) {
-      f->acc >>= c->codeword_lengths[i];
-      f->valid_bits -= c->codeword_lengths[i];
-      if (f->valid_bits < 0) { f->valid_bits = 0; return -1; }
-      return i;
-   }
-   return stbv_codebook_decode_scalar_raw(f,c);
-}
-
-#define STBV_DECODE_RAW(var,f,c)    var = stbv_codebook_decode_scalar(f,c);
-
-#endif
-
-#define STBV_DECODE(var,f,c)                                       \
-   STBV_DECODE_RAW(var,f,c)                                        \
-   if (c->sparse) var = c->sorted_values[var];
-
-#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
-  #define DECODE_VQ(var,f,c)   STBV_DECODE_RAW(var,f,c)
-#else
-  #define DECODE_VQ(var,f,c)   STBV_DECODE(var,f,c)
-#endif
-
-
-
-
-
-
-// STBV_CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case
-// where we avoid one addition
-#define STBV_CODEBOOK_ELEMENT(c,off)          (c->multiplicands[off])
-#define STBV_CODEBOOK_ELEMENT_FAST(c,off)     (c->multiplicands[off])
-#define STBV_CODEBOOK_ELEMENT_BASE(c)         (0)
-
-static int stbv_codebook_decode_start(stbv_vorb *f, StbvCodebook *c)
-{
-   int z = -1;
-
-   // type 0 is only legal in a scalar context
-   if (c->lookup_type == 0)
-      stbv_error(f, VORBIS_invalid_stream);
-   else {
-      DECODE_VQ(z,f,c);
-      if (c->sparse) assert(z < c->sorted_entries);
-      if (z < 0) {  // check for STBV_EOP
-         if (!f->bytes_in_seg)
-            if (f->last_seg)
-               return z;
-         stbv_error(f, VORBIS_invalid_stream);
-      }
-   }
-   return z;
-}
-
-static int stbv_codebook_decode(stbv_vorb *f, StbvCodebook *c, float *output, int len)
-{
-   int i,z = stbv_codebook_decode_start(f,c);
-   if (z < 0) return FALSE;
-   if (len > c->dimensions) len = c->dimensions;
-
-#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
-   if (c->lookup_type == 1) {
-      float last = STBV_CODEBOOK_ELEMENT_BASE(c);
-      int div = 1;
-      for (i=0; i < len; ++i) {
-         int off = (z / div) % c->lookup_values;
-         float val = STBV_CODEBOOK_ELEMENT_FAST(c,off) + last;
-         output[i] += val;
-         if (c->sequence_p) last = val + c->minimum_value;
-         div *= c->lookup_values;
-      }
-      return TRUE;
-   }
-#endif
-
-   z *= c->dimensions;
-   if (c->sequence_p) {
-      float last = STBV_CODEBOOK_ELEMENT_BASE(c);
-      for (i=0; i < len; ++i) {
-         float val = STBV_CODEBOOK_ELEMENT_FAST(c,z+i) + last;
-         output[i] += val;
-         last = val + c->minimum_value;
-      }
-   } else {
-      float last = STBV_CODEBOOK_ELEMENT_BASE(c);
-      for (i=0; i < len; ++i) {
-         output[i] += STBV_CODEBOOK_ELEMENT_FAST(c,z+i) + last;
-      }
-   }
-
-   return TRUE;
-}
-
-static int stbv_codebook_decode_step(stbv_vorb *f, StbvCodebook *c, float *output, int len, int step)
-{
-   int i,z = stbv_codebook_decode_start(f,c);
-   float last = STBV_CODEBOOK_ELEMENT_BASE(c);
-   if (z < 0) return FALSE;
-   if (len > c->dimensions) len = c->dimensions;
-
-#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
-   if (c->lookup_type == 1) {
-      int div = 1;
-      for (i=0; i < len; ++i) {
-         int off = (z / div) % c->lookup_values;
-         float val = STBV_CODEBOOK_ELEMENT_FAST(c,off) + last;
-         output[i*step] += val;
-         if (c->sequence_p) last = val;
-         div *= c->lookup_values;
-      }
-      return TRUE;
-   }
-#endif
-
-   z *= c->dimensions;
-   for (i=0; i < len; ++i) {
-      float val = STBV_CODEBOOK_ELEMENT_FAST(c,z+i) + last;
-      output[i*step] += val;
-      if (c->sequence_p) last = val;
-   }
-
-   return TRUE;
-}
-
-static int stbv_codebook_decode_deinterleave_repeat(stbv_vorb *f, StbvCodebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode)
-{
-   int c_inter = *c_inter_p;
-   int p_inter = *p_inter_p;
-   int i,z, effective = c->dimensions;
-
-   // type 0 is only legal in a scalar context
-   if (c->lookup_type == 0)   return stbv_error(f, VORBIS_invalid_stream);
-
-   while (total_decode > 0) {
-      float last = STBV_CODEBOOK_ELEMENT_BASE(c);
-      DECODE_VQ(z,f,c);
-      #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
-      assert(!c->sparse || z < c->sorted_entries);
-      #endif
-      if (z < 0) {
-         if (!f->bytes_in_seg)
-            if (f->last_seg) return FALSE;
-         return stbv_error(f, VORBIS_invalid_stream);
-      }
-
-      // if this will take us off the end of the buffers, stop short!
-      // we check by computing the length of the virtual interleaved
-      // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter),
-      // and the length we'll be using (effective)
-      if (c_inter + p_inter*ch + effective > len * ch) {
-         effective = len*ch - (p_inter*ch - c_inter);
-      }
-
-   #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
-      if (c->lookup_type == 1) {
-         int div = 1;
-         for (i=0; i < effective; ++i) {
-            int off = (z / div) % c->lookup_values;
-            float val = STBV_CODEBOOK_ELEMENT_FAST(c,off) + last;
-            if (outputs[c_inter])
-               outputs[c_inter][p_inter] += val;
-            if (++c_inter == ch) { c_inter = 0; ++p_inter; }
-            if (c->sequence_p) last = val;
-            div *= c->lookup_values;
-         }
-      } else
-   #endif
-      {
-         z *= c->dimensions;
-         if (c->sequence_p) {
-            for (i=0; i < effective; ++i) {
-               float val = STBV_CODEBOOK_ELEMENT_FAST(c,z+i) + last;
-               if (outputs[c_inter])
-                  outputs[c_inter][p_inter] += val;
-               if (++c_inter == ch) { c_inter = 0; ++p_inter; }
-               last = val;
-            }
-         } else {
-            for (i=0; i < effective; ++i) {
-               float val = STBV_CODEBOOK_ELEMENT_FAST(c,z+i) + last;
-               if (outputs[c_inter])
-                  outputs[c_inter][p_inter] += val;
-               if (++c_inter == ch) { c_inter = 0; ++p_inter; }
-            }
-         }
-      }
-
-      total_decode -= effective;
-   }
-   *c_inter_p = c_inter;
-   *p_inter_p = p_inter;
-   return TRUE;
-}
-
-static int stbv_predict_point(int x, int x0, int x1, int y0, int y1)
-{
-   int dy = y1 - y0;
-   int adx = x1 - x0;
-   // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86?
-   int err = abs(dy) * (x - x0);
-   int off = err / adx;
-   return dy < 0 ? y0 - off : y0 + off;
-}
-
-// the following table is block-copied from the specification
-static float stbv_inverse_db_table[256] =
-{
-  1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, 
-  1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, 
-  1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, 
-  2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, 
-  2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, 
-  3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, 
-  4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, 
-  6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, 
-  7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, 
-  1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, 
-  1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, 
-  1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, 
-  2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, 
-  2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, 
-  3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, 
-  4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, 
-  5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, 
-  7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, 
-  9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, 
-  1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, 
-  1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, 
-  2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, 
-  2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, 
-  3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, 
-  4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, 
-  5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, 
-  7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, 
-  9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, 
-  0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, 
-  0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, 
-  0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, 
-  0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, 
-  0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, 
-  0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, 
-  0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, 
-  0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, 
-  0.00092223983f, 0.00098217216f, 0.0010459992f,  0.0011139742f, 
-  0.0011863665f,  0.0012634633f,  0.0013455702f,  0.0014330129f, 
-  0.0015261382f,  0.0016253153f,  0.0017309374f,  0.0018434235f, 
-  0.0019632195f,  0.0020908006f,  0.0022266726f,  0.0023713743f, 
-  0.0025254795f,  0.0026895994f,  0.0028643847f,  0.0030505286f, 
-  0.0032487691f,  0.0034598925f,  0.0036847358f,  0.0039241906f, 
-  0.0041792066f,  0.0044507950f,  0.0047400328f,  0.0050480668f, 
-  0.0053761186f,  0.0057254891f,  0.0060975636f,  0.0064938176f, 
-  0.0069158225f,  0.0073652516f,  0.0078438871f,  0.0083536271f, 
-  0.0088964928f,  0.009474637f,   0.010090352f,   0.010746080f, 
-  0.011444421f,   0.012188144f,   0.012980198f,   0.013823725f, 
-  0.014722068f,   0.015678791f,   0.016697687f,   0.017782797f, 
-  0.018938423f,   0.020169149f,   0.021479854f,   0.022875735f, 
-  0.024362330f,   0.025945531f,   0.027631618f,   0.029427276f, 
-  0.031339626f,   0.033376252f,   0.035545228f,   0.037855157f, 
-  0.040315199f,   0.042935108f,   0.045725273f,   0.048696758f, 
-  0.051861348f,   0.055231591f,   0.058820850f,   0.062643361f, 
-  0.066714279f,   0.071049749f,   0.075666962f,   0.080584227f, 
-  0.085821044f,   0.091398179f,   0.097337747f,   0.10366330f, 
-  0.11039993f,    0.11757434f,    0.12521498f,    0.13335215f, 
-  0.14201813f,    0.15124727f,    0.16107617f,    0.17154380f, 
-  0.18269168f,    0.19456402f,    0.20720788f,    0.22067342f, 
-  0.23501402f,    0.25028656f,    0.26655159f,    0.28387361f, 
-  0.30232132f,    0.32196786f,    0.34289114f,    0.36517414f, 
-  0.38890521f,    0.41417847f,    0.44109412f,    0.46975890f, 
-  0.50028648f,    0.53279791f,    0.56742212f,    0.60429640f, 
-  0.64356699f,    0.68538959f,    0.72993007f,    0.77736504f, 
-  0.82788260f,    0.88168307f,    0.9389798f,     1.0f
-};
-
-
-// @OPTIMIZE: if you want to replace this bresenham line-drawing routine,
-// note that you must produce bit-identical output to decode correctly;
-// this specific sequence of operations is specified in the spec (it's
-// drawing integer-quantized frequency-space lines that the encoder
-// expects to be exactly the same)
-//     ... also, isn't the whole point of Bresenham's algorithm to NOT
-// have to divide in the setup? sigh.
-#ifndef STB_VORBIS_NO_DEFER_FLOOR
-#define STBV_LINE_OP(a,b)   a *= b
-#else
-#define STBV_LINE_OP(a,b)   a = b
-#endif
-
-#ifdef STB_VORBIS_DIVIDE_TABLE
-#define STBV_DIVTAB_NUMER   32
-#define STBV_DIVTAB_DENOM   64
-stbv_int8 stbv_integer_divide_table[STBV_DIVTAB_NUMER][STBV_DIVTAB_DENOM]; // 2KB
-#endif
-
-static __forceinline void stbv_draw_line(float *output, int x0, int y0, int x1, int y1, int n)
-{
-   int dy = y1 - y0;
-   int adx = x1 - x0;
-   int ady = abs(dy);
-   int base;
-   int x=x0,y=y0;
-   int err = 0;
-   int sy;
-
-#ifdef STB_VORBIS_DIVIDE_TABLE
-   if (adx < STBV_DIVTAB_DENOM && ady < STBV_DIVTAB_NUMER) {
-      if (dy < 0) {
-         base = -stbv_integer_divide_table[ady][adx];
-         sy = base-1;
-      } else {
-         base =  stbv_integer_divide_table[ady][adx];
-         sy = base+1;
-      }
-   } else {
-      base = dy / adx;
-      if (dy < 0)
-         sy = base - 1;
-      else
-         sy = base+1;
-   }
-#else
-   base = dy / adx;
-   if (dy < 0)
-      sy = base - 1;
-   else
-      sy = base+1;
-#endif
-   ady -= abs(base) * adx;
-   if (x1 > n) x1 = n;
-   if (x < x1) {
-      STBV_LINE_OP(output[x], stbv_inverse_db_table[y]);
-      for (++x; x < x1; ++x) {
-         err += ady;
-         if (err >= adx) {
-            err -= adx;
-            y += sy;
-         } else
-            y += base;
-         STBV_LINE_OP(output[x], stbv_inverse_db_table[y]);
-      }
-   }
-}
-
-static int stbv_residue_decode(stbv_vorb *f, StbvCodebook *book, float *target, int offset, int n, int rtype)
-{
-   int k;
-   if (rtype == 0) {
-      int step = n / book->dimensions;
-      for (k=0; k < step; ++k)
-         if (!stbv_codebook_decode_step(f, book, target+offset+k, n-offset-k, step))
-            return FALSE;
-   } else {
-      for (k=0; k < n; ) {
-         if (!stbv_codebook_decode(f, book, target+offset, n-k))
-            return FALSE;
-         k += book->dimensions;
-         offset += book->dimensions;
-      }
-   }
-   return TRUE;
-}
-
-// n is 1/2 of the blocksize --
-// specification: "Correct per-vector decode length is [n]/2"
-static void stbv_decode_residue(stbv_vorb *f, float *residue_buffers[], int ch, int n, int rn, stbv_uint8 *do_not_decode)
-{
-   int i,j,pass;
-   StbvResidue *r = f->residue_config + rn;
-   int rtype = f->residue_types[rn];
-   int c = r->classbook;
-   int classwords = f->codebooks[c].dimensions;
-   unsigned int actual_size = rtype == 2 ? n*2 : n;
-   unsigned int limit_r_begin = (r->begin < actual_size ? r->begin : actual_size);
-   unsigned int limit_r_end   = (r->end   < actual_size ? r->end   : actual_size);
-   int n_read = limit_r_end - limit_r_begin;
-   int part_read = n_read / r->part_size;
-   int temp_alloc_point = stbv_temp_alloc_save(f);
-   #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-   stbv_uint8 ***part_classdata = (stbv_uint8 ***) stbv_temp_block_array(f,f->channels, part_read * sizeof(**part_classdata));
-   #else
-   int **classifications = (int **) stbv_temp_block_array(f,f->channels, part_read * sizeof(**classifications));
-   #endif
-
-   STBV_CHECK(f);
-
-   for (i=0; i < ch; ++i)
-      if (!do_not_decode[i])
-         memset(residue_buffers[i], 0, sizeof(float) * n);
-
-   if (rtype == 2 && ch != 1) {
-      for (j=0; j < ch; ++j)
-         if (!do_not_decode[j])
-            break;
-      if (j == ch)
-         goto done;
-
-      for (pass=0; pass < 8; ++pass) {
-         int pcount = 0, class_set = 0;
-         if (ch == 2) {
-            while (pcount < part_read) {
-               int z = r->begin + pcount*r->part_size;
-               int c_inter = (z & 1), p_inter = z>>1;
-               if (pass == 0) {
-                  StbvCodebook *c = f->codebooks+r->classbook;
-                  int q;
-                  STBV_DECODE(q,f,c);
-                  if (q == STBV_EOP) goto done;
-                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-                  part_classdata[0][class_set] = r->classdata[q];
-                  #else
-                  for (i=classwords-1; i >= 0; --i) {
-                     classifications[0][i+pcount] = q % r->classifications;
-                     q /= r->classifications;
-                  }
-                  #endif
-               }
-               for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
-                  int z = r->begin + pcount*r->part_size;
-                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-                  int c = part_classdata[0][class_set][i];
-                  #else
-                  int c = classifications[0][pcount];
-                  #endif
-                  int b = r->residue_books[c][pass];
-                  if (b >= 0) {
-                     StbvCodebook *book = f->codebooks + b;
-                     #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
-                     if (!stbv_codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
-                        goto done;
-                     #else
-                     // saves 1%
-                     if (!stbv_codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
-                        goto done;
-                     #endif
-                  } else {
-                     z += r->part_size;
-                     c_inter = z & 1;
-                     p_inter = z >> 1;
-                  }
-               }
-               #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-               ++class_set;
-               #endif
-            }
-         } else if (ch == 1) {
-            while (pcount < part_read) {
-               int z = r->begin + pcount*r->part_size;
-               int c_inter = 0, p_inter = z;
-               if (pass == 0) {
-                  StbvCodebook *c = f->codebooks+r->classbook;
-                  int q;
-                  STBV_DECODE(q,f,c);
-                  if (q == STBV_EOP) goto done;
-                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-                  part_classdata[0][class_set] = r->classdata[q];
-                  #else
-                  for (i=classwords-1; i >= 0; --i) {
-                     classifications[0][i+pcount] = q % r->classifications;
-                     q /= r->classifications;
-                  }
-                  #endif
-               }
-               for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
-                  int z = r->begin + pcount*r->part_size;
-                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-                  int c = part_classdata[0][class_set][i];
-                  #else
-                  int c = classifications[0][pcount];
-                  #endif
-                  int b = r->residue_books[c][pass];
-                  if (b >= 0) {
-                     StbvCodebook *book = f->codebooks + b;
-                     if (!stbv_codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
-                        goto done;
-                  } else {
-                     z += r->part_size;
-                     c_inter = 0;
-                     p_inter = z;
-                  }
-               }
-               #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-               ++class_set;
-               #endif
-            }
-         } else {
-            while (pcount < part_read) {
-               int z = r->begin + pcount*r->part_size;
-               int c_inter = z % ch, p_inter = z/ch;
-               if (pass == 0) {
-                  StbvCodebook *c = f->codebooks+r->classbook;
-                  int q;
-                  STBV_DECODE(q,f,c);
-                  if (q == STBV_EOP) goto done;
-                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-                  part_classdata[0][class_set] = r->classdata[q];
-                  #else
-                  for (i=classwords-1; i >= 0; --i) {
-                     classifications[0][i+pcount] = q % r->classifications;
-                     q /= r->classifications;
-                  }
-                  #endif
-               }
-               for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
-                  int z = r->begin + pcount*r->part_size;
-                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-                  int c = part_classdata[0][class_set][i];
-                  #else
-                  int c = classifications[0][pcount];
-                  #endif
-                  int b = r->residue_books[c][pass];
-                  if (b >= 0) {
-                     StbvCodebook *book = f->codebooks + b;
-                     if (!stbv_codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))
-                        goto done;
-                  } else {
-                     z += r->part_size;
-                     c_inter = z % ch;
-                     p_inter = z / ch;
-                  }
-               }
-               #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-               ++class_set;
-               #endif
-            }
-         }
-      }
-      goto done;
-   }
-   STBV_CHECK(f);
-
-   for (pass=0; pass < 8; ++pass) {
-      int pcount = 0, class_set=0;
-      while (pcount < part_read) {
-         if (pass == 0) {
-            for (j=0; j < ch; ++j) {
-               if (!do_not_decode[j]) {
-                  StbvCodebook *c = f->codebooks+r->classbook;
-                  int temp;
-                  STBV_DECODE(temp,f,c);
-                  if (temp == STBV_EOP) goto done;
-                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-                  part_classdata[j][class_set] = r->classdata[temp];
-                  #else
-                  for (i=classwords-1; i >= 0; --i) {
-                     classifications[j][i+pcount] = temp % r->classifications;
-                     temp /= r->classifications;
-                  }
-                  #endif
-               }
-            }
-         }
-         for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {
-            for (j=0; j < ch; ++j) {
-               if (!do_not_decode[j]) {
-                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-                  int c = part_classdata[j][class_set][i];
-                  #else
-                  int c = classifications[j][pcount];
-                  #endif
-                  int b = r->residue_books[c][pass];
-                  if (b >= 0) {
-                     float *target = residue_buffers[j];
-                     int offset = r->begin + pcount * r->part_size;
-                     int n = r->part_size;
-                     StbvCodebook *book = f->codebooks + b;
-                     if (!stbv_residue_decode(f, book, target, offset, n, rtype))
-                        goto done;
-                  }
-               }
-            }
-         }
-         #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-         ++class_set;
-         #endif
-      }
-   }
-  done:
-   STBV_CHECK(f);
-   #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-   stbv_temp_free(f,part_classdata);
-   #else
-   stbv_temp_free(f,classifications);
-   #endif
-   stbv_temp_alloc_restore(f,temp_alloc_point);
-}
-
-
-#if 0
-// slow way for debugging
-void inverse_mdct_slow(float *buffer, int n)
-{
-   int i,j;
-   int n2 = n >> 1;
-   float *x = (float *) malloc(sizeof(*x) * n2);
-   memcpy(x, buffer, sizeof(*x) * n2);
-   for (i=0; i < n; ++i) {
-      float acc = 0;
-      for (j=0; j < n2; ++j)
-         // formula from paper:
-         //acc += n/4.0f * x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1));
-         // formula from wikipedia
-         //acc += 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5));
-         // these are equivalent, except the formula from the paper inverts the multiplier!
-         // however, what actually works is NO MULTIPLIER!?!
-         //acc += 64 * 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5));
-         acc += x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1));
-      buffer[i] = acc;
-   }
-   free(x);
-}
-#elif 0
-// same as above, but just barely able to run in real time on modern machines
-void inverse_mdct_slow(float *buffer, int n, stbv_vorb *f, int blocktype)
-{
-   float mcos[16384];
-   int i,j;
-   int n2 = n >> 1, nmask = (n << 2) -1;
-   float *x = (float *) malloc(sizeof(*x) * n2);
-   memcpy(x, buffer, sizeof(*x) * n2);
-   for (i=0; i < 4*n; ++i)
-      mcos[i] = (float) cos(M_PI / 2 * i / n);
-
-   for (i=0; i < n; ++i) {
-      float acc = 0;
-      for (j=0; j < n2; ++j)
-         acc += x[j] * mcos[(2 * i + 1 + n2)*(2*j+1) & nmask];
-      buffer[i] = acc;
-   }
-   free(x);
-}
-#elif 0
-// transform to use a slow dct-iv; this is STILL basically trivial,
-// but only requires half as many ops
-void dct_iv_slow(float *buffer, int n)
-{
-   float mcos[16384];
-   float x[2048];
-   int i,j;
-   int n2 = n >> 1, nmask = (n << 3) - 1;
-   memcpy(x, buffer, sizeof(*x) * n);
-   for (i=0; i < 8*n; ++i)
-      mcos[i] = (float) cos(M_PI / 4 * i / n);
-   for (i=0; i < n; ++i) {
-      float acc = 0;
-      for (j=0; j < n; ++j)
-         acc += x[j] * mcos[((2 * i + 1)*(2*j+1)) & nmask];
-      buffer[i] = acc;
-   }
-}
-
-void inverse_mdct_slow(float *buffer, int n, stbv_vorb *f, int blocktype)
-{
-   int i, n4 = n >> 2, n2 = n >> 1, n3_4 = n - n4;
-   float temp[4096];
-
-   memcpy(temp, buffer, n2 * sizeof(float));
-   dct_iv_slow(temp, n2);  // returns -c'-d, a-b'
-
-   for (i=0; i < n4  ; ++i) buffer[i] = temp[i+n4];            // a-b'
-   for (   ; i < n3_4; ++i) buffer[i] = -temp[n3_4 - i - 1];   // b-a', c+d'
-   for (   ; i < n   ; ++i) buffer[i] = -temp[i - n3_4];       // c'+d
-}
-#endif
-
-#ifndef LIBVORBIS_MDCT
-#define LIBVORBIS_MDCT 0
-#endif
-
-#if LIBVORBIS_MDCT
-// directly call the vorbis MDCT using an interface documented
-// by Jeff Roberts... useful for performance comparison
-typedef struct 
-{
-  int n;
-  int log2n;
-  
-  float *trig;
-  int   *bitrev;
-
-  float scale;
-} mdct_lookup;
-
-extern void mdct_init(mdct_lookup *lookup, int n);
-extern void mdct_clear(mdct_lookup *l);
-extern void mdct_backward(mdct_lookup *init, float *in, float *out);
-
-mdct_lookup M1,M2;
-
-void stbv_inverse_mdct(float *buffer, int n, stbv_vorb *f, int blocktype)
-{
-   mdct_lookup *M;
-   if (M1.n == n) M = &M1;
-   else if (M2.n == n) M = &M2;
-   else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; }
-   else { 
-      if (M2.n) __asm int 3;
-      mdct_init(&M2, n);
-      M = &M2;
-   }
-
-   mdct_backward(M, buffer, buffer);
-}
-#endif
-
-
-// the following were split out into separate functions while optimizing;
-// they could be pushed back up but eh. __forceinline showed no change;
-// they're probably already being inlined.
-static void stbv_imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A)
-{
-   float *ee0 = e + i_off;
-   float *ee2 = ee0 + k_off;
-   int i;
-
-   assert((n & 3) == 0);
-   for (i=(n>>2); i > 0; --i) {
-      float k00_20, k01_21;
-      k00_20  = ee0[ 0] - ee2[ 0];
-      k01_21  = ee0[-1] - ee2[-1];
-      ee0[ 0] += ee2[ 0];//ee0[ 0] = ee0[ 0] + ee2[ 0];
-      ee0[-1] += ee2[-1];//ee0[-1] = ee0[-1] + ee2[-1];
-      ee2[ 0] = k00_20 * A[0] - k01_21 * A[1];
-      ee2[-1] = k01_21 * A[0] + k00_20 * A[1];
-      A += 8;
-
-      k00_20  = ee0[-2] - ee2[-2];
-      k01_21  = ee0[-3] - ee2[-3];
-      ee0[-2] += ee2[-2];//ee0[-2] = ee0[-2] + ee2[-2];
-      ee0[-3] += ee2[-3];//ee0[-3] = ee0[-3] + ee2[-3];
-      ee2[-2] = k00_20 * A[0] - k01_21 * A[1];
-      ee2[-3] = k01_21 * A[0] + k00_20 * A[1];
-      A += 8;
-
-      k00_20  = ee0[-4] - ee2[-4];
-      k01_21  = ee0[-5] - ee2[-5];
-      ee0[-4] += ee2[-4];//ee0[-4] = ee0[-4] + ee2[-4];
-      ee0[-5] += ee2[-5];//ee0[-5] = ee0[-5] + ee2[-5];
-      ee2[-4] = k00_20 * A[0] - k01_21 * A[1];
-      ee2[-5] = k01_21 * A[0] + k00_20 * A[1];
-      A += 8;
-
-      k00_20  = ee0[-6] - ee2[-6];
-      k01_21  = ee0[-7] - ee2[-7];
-      ee0[-6] += ee2[-6];//ee0[-6] = ee0[-6] + ee2[-6];
-      ee0[-7] += ee2[-7];//ee0[-7] = ee0[-7] + ee2[-7];
-      ee2[-6] = k00_20 * A[0] - k01_21 * A[1];
-      ee2[-7] = k01_21 * A[0] + k00_20 * A[1];
-      A += 8;
-      ee0 -= 8;
-      ee2 -= 8;
-   }
-}
-
-static void stbv_imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1)
-{
-   int i;
-   float k00_20, k01_21;
-
-   float *e0 = e + d0;
-   float *e2 = e0 + k_off;
-
-   for (i=lim >> 2; i > 0; --i) {
-      k00_20 = e0[-0] - e2[-0];
-      k01_21 = e0[-1] - e2[-1];
-      e0[-0] += e2[-0];//e0[-0] = e0[-0] + e2[-0];
-      e0[-1] += e2[-1];//e0[-1] = e0[-1] + e2[-1];
-      e2[-0] = (k00_20)*A[0] - (k01_21) * A[1];
-      e2[-1] = (k01_21)*A[0] + (k00_20) * A[1];
-
-      A += k1;
-
-      k00_20 = e0[-2] - e2[-2];
-      k01_21 = e0[-3] - e2[-3];
-      e0[-2] += e2[-2];//e0[-2] = e0[-2] + e2[-2];
-      e0[-3] += e2[-3];//e0[-3] = e0[-3] + e2[-3];
-      e2[-2] = (k00_20)*A[0] - (k01_21) * A[1];
-      e2[-3] = (k01_21)*A[0] + (k00_20) * A[1];
-
-      A += k1;
-
-      k00_20 = e0[-4] - e2[-4];
-      k01_21 = e0[-5] - e2[-5];
-      e0[-4] += e2[-4];//e0[-4] = e0[-4] + e2[-4];
-      e0[-5] += e2[-5];//e0[-5] = e0[-5] + e2[-5];
-      e2[-4] = (k00_20)*A[0] - (k01_21) * A[1];
-      e2[-5] = (k01_21)*A[0] + (k00_20) * A[1];
-
-      A += k1;
-
-      k00_20 = e0[-6] - e2[-6];
-      k01_21 = e0[-7] - e2[-7];
-      e0[-6] += e2[-6];//e0[-6] = e0[-6] + e2[-6];
-      e0[-7] += e2[-7];//e0[-7] = e0[-7] + e2[-7];
-      e2[-6] = (k00_20)*A[0] - (k01_21) * A[1];
-      e2[-7] = (k01_21)*A[0] + (k00_20) * A[1];
-
-      e0 -= 8;
-      e2 -= 8;
-
-      A += k1;
-   }
-}
-
-static void stbv_imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0)
-{
-   int i;
-   float A0 = A[0];
-   float A1 = A[0+1];
-   float A2 = A[0+a_off];
-   float A3 = A[0+a_off+1];
-   float A4 = A[0+a_off*2+0];
-   float A5 = A[0+a_off*2+1];
-   float A6 = A[0+a_off*3+0];
-   float A7 = A[0+a_off*3+1];
-
-   float k00,k11;
-
-   float *ee0 = e  +i_off;
-   float *ee2 = ee0+k_off;
-
-   for (i=n; i > 0; --i) {
-      k00     = ee0[ 0] - ee2[ 0];
-      k11     = ee0[-1] - ee2[-1];
-      ee0[ 0] =  ee0[ 0] + ee2[ 0];
-      ee0[-1] =  ee0[-1] + ee2[-1];
-      ee2[ 0] = (k00) * A0 - (k11) * A1;
-      ee2[-1] = (k11) * A0 + (k00) * A1;
-
-      k00     = ee0[-2] - ee2[-2];
-      k11     = ee0[-3] - ee2[-3];
-      ee0[-2] =  ee0[-2] + ee2[-2];
-      ee0[-3] =  ee0[-3] + ee2[-3];
-      ee2[-2] = (k00) * A2 - (k11) * A3;
-      ee2[-3] = (k11) * A2 + (k00) * A3;
-
-      k00     = ee0[-4] - ee2[-4];
-      k11     = ee0[-5] - ee2[-5];
-      ee0[-4] =  ee0[-4] + ee2[-4];
-      ee0[-5] =  ee0[-5] + ee2[-5];
-      ee2[-4] = (k00) * A4 - (k11) * A5;
-      ee2[-5] = (k11) * A4 + (k00) * A5;
-
-      k00     = ee0[-6] - ee2[-6];
-      k11     = ee0[-7] - ee2[-7];
-      ee0[-6] =  ee0[-6] + ee2[-6];
-      ee0[-7] =  ee0[-7] + ee2[-7];
-      ee2[-6] = (k00) * A6 - (k11) * A7;
-      ee2[-7] = (k11) * A6 + (k00) * A7;
-
-      ee0 -= k0;
-      ee2 -= k0;
-   }
-}
-
-static __forceinline void stbv_iter_54(float *z)
-{
-   float k00,k11,k22,k33;
-   float y0,y1,y2,y3;
-
-   k00  = z[ 0] - z[-4];
-   y0   = z[ 0] + z[-4];
-   y2   = z[-2] + z[-6];
-   k22  = z[-2] - z[-6];
-
-   z[-0] = y0 + y2;      // z0 + z4 + z2 + z6
-   z[-2] = y0 - y2;      // z0 + z4 - z2 - z6
-
-   // done with y0,y2
-
-   k33  = z[-3] - z[-7];
-
-   z[-4] = k00 + k33;    // z0 - z4 + z3 - z7
-   z[-6] = k00 - k33;    // z0 - z4 - z3 + z7
-
-   // done with k33
-
-   k11  = z[-1] - z[-5];
-   y1   = z[-1] + z[-5];
-   y3   = z[-3] + z[-7];
-
-   z[-1] = y1 + y3;      // z1 + z5 + z3 + z7
-   z[-3] = y1 - y3;      // z1 + z5 - z3 - z7
-   z[-5] = k11 - k22;    // z1 - z5 + z2 - z6
-   z[-7] = k11 + k22;    // z1 - z5 - z2 + z6
-}
-
-static void stbv_imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n)
-{
-   int a_off = base_n >> 3;
-   float A2 = A[0+a_off];
-   float *z = e + i_off;
-   float *base = z - 16 * n;
-
-   while (z > base) {
-      float k00,k11;
-
-      k00   = z[-0] - z[-8];
-      k11   = z[-1] - z[-9];
-      z[-0] = z[-0] + z[-8];
-      z[-1] = z[-1] + z[-9];
-      z[-8] =  k00;
-      z[-9] =  k11 ;
-
-      k00    = z[ -2] - z[-10];
-      k11    = z[ -3] - z[-11];
-      z[ -2] = z[ -2] + z[-10];
-      z[ -3] = z[ -3] + z[-11];
-      z[-10] = (k00+k11) * A2;
-      z[-11] = (k11-k00) * A2;
-
-      k00    = z[-12] - z[ -4];  // reverse to avoid a unary negation
-      k11    = z[ -5] - z[-13];
-      z[ -4] = z[ -4] + z[-12];
-      z[ -5] = z[ -5] + z[-13];
-      z[-12] = k11;
-      z[-13] = k00;
-
-      k00    = z[-14] - z[ -6];  // reverse to avoid a unary negation
-      k11    = z[ -7] - z[-15];
-      z[ -6] = z[ -6] + z[-14];
-      z[ -7] = z[ -7] + z[-15];
-      z[-14] = (k00+k11) * A2;
-      z[-15] = (k00-k11) * A2;
-
-      stbv_iter_54(z);
-      stbv_iter_54(z-8);
-      z -= 16;
-   }
-}
-
-static void stbv_inverse_mdct(float *buffer, int n, stbv_vorb *f, int blocktype)
-{
-   int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l;
-   int ld;
-   // @OPTIMIZE: reduce register pressure by using fewer variables?
-   int save_point = stbv_temp_alloc_save(f);
-   float *buf2 = (float *) stbv_temp_alloc(f, n2 * sizeof(*buf2));
-   float *u=NULL,*v=NULL;
-   // twiddle factors
-   float *A = f->A[blocktype];
-
-   // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio"
-   // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function.
-
-   // kernel from paper
-
-
-   // merged:
-   //   copy and reflect spectral data
-   //   step 0
-
-   // note that it turns out that the items added together during
-   // this step are, in fact, being added to themselves (as reflected
-   // by step 0). inexplicable inefficiency! this became obvious
-   // once I combined the passes.
-
-   // so there's a missing 'times 2' here (for adding X to itself).
-   // this propogates through linearly to the end, where the numbers
-   // are 1/2 too small, and need to be compensated for.
-
-   {
-      float *d,*e, *AA, *e_stop;
-      d = &buf2[n2-2];
-      AA = A;
-      e = &buffer[0];
-      e_stop = &buffer[n2];
-      while (e != e_stop) {
-         d[1] = (e[0] * AA[0] - e[2]*AA[1]);
-         d[0] = (e[0] * AA[1] + e[2]*AA[0]);
-         d -= 2;
-         AA += 2;
-         e += 4;
-      }
-
-      e = &buffer[n2-3];
-      while (d >= buf2) {
-         d[1] = (-e[2] * AA[0] - -e[0]*AA[1]);
-         d[0] = (-e[2] * AA[1] + -e[0]*AA[0]);
-         d -= 2;
-         AA += 2;
-         e -= 4;
-      }
-   }
-
-   // now we use symbolic names for these, so that we can
-   // possibly swap their meaning as we change which operations
-   // are in place
-
-   u = buffer;
-   v = buf2;
-
-   // step 2    (paper output is w, now u)
-   // this could be in place, but the data ends up in the wrong
-   // place... _somebody_'s got to swap it, so this is nominated
-   {
-      float *AA = &A[n2-8];
-      float *d0,*d1, *e0, *e1;
-
-      e0 = &v[n4];
-      e1 = &v[0];
-
-      d0 = &u[n4];
-      d1 = &u[0];
-
-      while (AA >= A) {
-         float v40_20, v41_21;
-
-         v41_21 = e0[1] - e1[1];
-         v40_20 = e0[0] - e1[0];
-         d0[1]  = e0[1] + e1[1];
-         d0[0]  = e0[0] + e1[0];
-         d1[1]  = v41_21*AA[4] - v40_20*AA[5];
-         d1[0]  = v40_20*AA[4] + v41_21*AA[5];
-
-         v41_21 = e0[3] - e1[3];
-         v40_20 = e0[2] - e1[2];
-         d0[3]  = e0[3] + e1[3];
-         d0[2]  = e0[2] + e1[2];
-         d1[3]  = v41_21*AA[0] - v40_20*AA[1];
-         d1[2]  = v40_20*AA[0] + v41_21*AA[1];
-
-         AA -= 8;
-
-         d0 += 4;
-         d1 += 4;
-         e0 += 4;
-         e1 += 4;
-      }
-   }
-
-   // step 3
-   ld = stbv_ilog(n) - 1; // stbv_ilog is off-by-one from normal definitions
-
-   // optimized step 3:
-
-   // the original step3 loop can be nested r inside s or s inside r;
-   // it's written originally as s inside r, but this is dumb when r
-   // iterates many times, and s few. So I have two copies of it and
-   // switch between them halfway.
-
-   // this is iteration 0 of step 3
-   stbv_imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n >> 3), A);
-   stbv_imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n >> 3), A);
-
-   // this is iteration 1 of step 3
-   stbv_imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n >> 4), A, 16);
-   stbv_imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n >> 4), A, 16);
-   stbv_imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n >> 4), A, 16);
-   stbv_imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n >> 4), A, 16);
-
-   l=2;
-   for (; l < (ld-3)>>1; ++l) {
-      int k0 = n >> (l+2), k0_2 = k0>>1;
-      int lim = 1 << (l+1);
-      int i;
-      for (i=0; i < lim; ++i)
-         stbv_imdct_step3_inner_r_loop(n >> (l+4), u, n2-1 - k0*i, -k0_2, A, 1 << (l+3));
-   }
-
-   for (; l < ld-6; ++l) {
-      int k0 = n >> (l+2), k1 = 1 << (l+3), k0_2 = k0>>1;
-      int rlim = n >> (l+6), r;
-      int lim = 1 << (l+1);
-      int i_off;
-      float *A0 = A;
-      i_off = n2-1;
-      for (r=rlim; r > 0; --r) {
-         stbv_imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0);
-         A0 += k1*4;
-         i_off -= 8;
-      }
-   }
-
-   // iterations with count:
-   //   ld-6,-5,-4 all interleaved together
-   //       the big win comes from getting rid of needless flops
-   //         due to the constants on pass 5 & 4 being all 1 and 0;
-   //       combining them to be simultaneous to improve cache made little difference
-   stbv_imdct_step3_inner_s_loop_ld654(n >> 5, u, n2-1, A, n);
-
-   // output is u
-
-   // step 4, 5, and 6
-   // cannot be in-place because of step 5
-   {
-      stbv_uint16 *bitrev = f->stbv_bit_reverse[blocktype];
-      // weirdly, I'd have thought reading sequentially and writing
-      // erratically would have been better than vice-versa, but in
-      // fact that's not what my testing showed. (That is, with
-      // j = bitreverse(i), do you read i and write j, or read j and write i.)
-
-      float *d0 = &v[n4-4];
-      float *d1 = &v[n2-4];
-      while (d0 >= v) {
-         int k4;
-
-         k4 = bitrev[0];
-         d1[3] = u[k4+0];
-         d1[2] = u[k4+1];
-         d0[3] = u[k4+2];
-         d0[2] = u[k4+3];
-
-         k4 = bitrev[1];
-         d1[1] = u[k4+0];
-         d1[0] = u[k4+1];
-         d0[1] = u[k4+2];
-         d0[0] = u[k4+3];
-         
-         d0 -= 4;
-         d1 -= 4;
-         bitrev += 2;
-      }
-   }
-   // (paper output is u, now v)
-
-
-   // data must be in buf2
-   assert(v == buf2);
-
-   // step 7   (paper output is v, now v)
-   // this is now in place
-   {
-      float *C = f->C[blocktype];
-      float *d, *e;
-
-      d = v;
-      e = v + n2 - 4;
-
-      while (d < e) {
-         float a02,a11,b0,b1,b2,b3;
-
-         a02 = d[0] - e[2];
-         a11 = d[1] + e[3];
-
-         b0 = C[1]*a02 + C[0]*a11;
-         b1 = C[1]*a11 - C[0]*a02;
-
-         b2 = d[0] + e[ 2];
-         b3 = d[1] - e[ 3];
-
-         d[0] = b2 + b0;
-         d[1] = b3 + b1;
-         e[2] = b2 - b0;
-         e[3] = b1 - b3;
-
-         a02 = d[2] - e[0];
-         a11 = d[3] + e[1];
-
-         b0 = C[3]*a02 + C[2]*a11;
-         b1 = C[3]*a11 - C[2]*a02;
-
-         b2 = d[2] + e[ 0];
-         b3 = d[3] - e[ 1];
-
-         d[2] = b2 + b0;
-         d[3] = b3 + b1;
-         e[0] = b2 - b0;
-         e[1] = b1 - b3;
-
-         C += 4;
-         d += 4;
-         e -= 4;
-      }
-   }
-
-   // data must be in buf2
-
-
-   // step 8+decode   (paper output is X, now buffer)
-   // this generates pairs of data a la 8 and pushes them directly through
-   // the decode kernel (pushing rather than pulling) to avoid having
-   // to make another pass later
-
-   // this cannot POSSIBLY be in place, so we refer to the buffers directly
-
-   {
-      float *d0,*d1,*d2,*d3;
-
-      float *B = f->B[blocktype] + n2 - 8;
-      float *e = buf2 + n2 - 8;
-      d0 = &buffer[0];
-      d1 = &buffer[n2-4];
-      d2 = &buffer[n2];
-      d3 = &buffer[n-4];
-      while (e >= v) {
-         float p0,p1,p2,p3;
-
-         p3 =  e[6]*B[7] - e[7]*B[6];
-         p2 = -e[6]*B[6] - e[7]*B[7]; 
-
-         d0[0] =   p3;
-         d1[3] = - p3;
-         d2[0] =   p2;
-         d3[3] =   p2;
-
-         p1 =  e[4]*B[5] - e[5]*B[4];
-         p0 = -e[4]*B[4] - e[5]*B[5]; 
-
-         d0[1] =   p1;
-         d1[2] = - p1;
-         d2[1] =   p0;
-         d3[2] =   p0;
-
-         p3 =  e[2]*B[3] - e[3]*B[2];
-         p2 = -e[2]*B[2] - e[3]*B[3]; 
-
-         d0[2] =   p3;
-         d1[1] = - p3;
-         d2[2] =   p2;
-         d3[1] =   p2;
-
-         p1 =  e[0]*B[1] - e[1]*B[0];
-         p0 = -e[0]*B[0] - e[1]*B[1]; 
-
-         d0[3] =   p1;
-         d1[0] = - p1;
-         d2[3] =   p0;
-         d3[0] =   p0;
-
-         B -= 8;
-         e -= 8;
-         d0 += 4;
-         d2 += 4;
-         d1 -= 4;
-         d3 -= 4;
-      }
-   }
-
-   stbv_temp_free(f,buf2);
-   stbv_temp_alloc_restore(f,save_point);
-}
-
-#if 0
-// this is the original version of the above code, if you want to optimize it from scratch
-void inverse_mdct_naive(float *buffer, int n)
-{
-   float s;
-   float A[1 << 12], B[1 << 12], C[1 << 11];
-   int i,k,k2,k4, n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l;
-   int n3_4 = n - n4, ld;
-   // how can they claim this only uses N words?!
-   // oh, because they're only used sparsely, whoops
-   float u[1 << 13], X[1 << 13], v[1 << 13], w[1 << 13];
-   // set up twiddle factors
-
-   for (k=k2=0; k < n4; ++k,k2+=2) {
-      A[k2  ] = (float)  cos(4*k*M_PI/n);
-      A[k2+1] = (float) -sin(4*k*M_PI/n);
-      B[k2  ] = (float)  cos((k2+1)*M_PI/n/2);
-      B[k2+1] = (float)  sin((k2+1)*M_PI/n/2);
-   }
-   for (k=k2=0; k < n8; ++k,k2+=2) {
-      C[k2  ] = (float)  cos(2*(k2+1)*M_PI/n);
-      C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n);
-   }
-
-   // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio"
-   // Note there are bugs in that pseudocode, presumably due to them attempting
-   // to rename the arrays nicely rather than representing the way their actual
-   // implementation bounces buffers back and forth. As a result, even in the
-   // "some formulars corrected" version, a direct implementation fails. These
-   // are noted below as "paper bug".
-
-   // copy and reflect spectral data
-   for (k=0; k < n2; ++k) u[k] = buffer[k];
-   for (   ; k < n ; ++k) u[k] = -buffer[n - k - 1];
-   // kernel from paper
-   // step 1
-   for (k=k2=k4=0; k < n4; k+=1, k2+=2, k4+=4) {
-      v[n-k4-1] = (u[k4] - u[n-k4-1]) * A[k2]   - (u[k4+2] - u[n-k4-3])*A[k2+1];
-      v[n-k4-3] = (u[k4] - u[n-k4-1]) * A[k2+1] + (u[k4+2] - u[n-k4-3])*A[k2];
-   }
-   // step 2
-   for (k=k4=0; k < n8; k+=1, k4+=4) {
-      w[n2+3+k4] = v[n2+3+k4] + v[k4+3];
-      w[n2+1+k4] = v[n2+1+k4] + v[k4+1];
-      w[k4+3]    = (v[n2+3+k4] - v[k4+3])*A[n2-4-k4] - (v[n2+1+k4]-v[k4+1])*A[n2-3-k4];
-      w[k4+1]    = (v[n2+1+k4] - v[k4+1])*A[n2-4-k4] + (v[n2+3+k4]-v[k4+3])*A[n2-3-k4];
-   }
-   // step 3
-   ld = stbv_ilog(n) - 1; // stbv_ilog is off-by-one from normal definitions
-   for (l=0; l < ld-3; ++l) {
-      int k0 = n >> (l+2), k1 = 1 << (l+3);
-      int rlim = n >> (l+4), r4, r;
-      int s2lim = 1 << (l+2), s2;
-      for (r=r4=0; r < rlim; r4+=4,++r) {
-         for (s2=0; s2 < s2lim; s2+=2) {
-            u[n-1-k0*s2-r4] = w[n-1-k0*s2-r4] + w[n-1-k0*(s2+1)-r4];
-            u[n-3-k0*s2-r4] = w[n-3-k0*s2-r4] + w[n-3-k0*(s2+1)-r4];
-            u[n-1-k0*(s2+1)-r4] = (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1]
-                                - (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1+1];
-            u[n-3-k0*(s2+1)-r4] = (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1]
-                                + (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1+1];
-         }
-      }
-      if (l+1 < ld-3) {
-         // paper bug: ping-ponging of u&w here is omitted
-         memcpy(w, u, sizeof(u));
-      }
-   }
-
-   // step 4
-   for (i=0; i < n8; ++i) {
-      int j = stbv_bit_reverse(i) >> (32-ld+3);
-      assert(j < n8);
-      if (i == j) {
-         // paper bug: original code probably swapped in place; if copying,
-         //            need to directly copy in this case
-         int i8 = i << 3;
-         v[i8+1] = u[i8+1];
-         v[i8+3] = u[i8+3];
-         v[i8+5] = u[i8+5];
-         v[i8+7] = u[i8+7];
-      } else if (i < j) {
-         int i8 = i << 3, j8 = j << 3;
-         v[j8+1] = u[i8+1], v[i8+1] = u[j8 + 1];
-         v[j8+3] = u[i8+3], v[i8+3] = u[j8 + 3];
-         v[j8+5] = u[i8+5], v[i8+5] = u[j8 + 5];
-         v[j8+7] = u[i8+7], v[i8+7] = u[j8 + 7];
-      }
-   }
-   // step 5
-   for (k=0; k < n2; ++k) {
-      w[k] = v[k*2+1];
-   }
-   // step 6
-   for (k=k2=k4=0; k < n8; ++k, k2 += 2, k4 += 4) {
-      u[n-1-k2] = w[k4];
-      u[n-2-k2] = w[k4+1];
-      u[n3_4 - 1 - k2] = w[k4+2];
-      u[n3_4 - 2 - k2] = w[k4+3];
-   }
-   // step 7
-   for (k=k2=0; k < n8; ++k, k2 += 2) {
-      v[n2 + k2 ] = ( u[n2 + k2] + u[n-2-k2] + C[k2+1]*(u[n2+k2]-u[n-2-k2]) + C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2;
-      v[n-2 - k2] = ( u[n2 + k2] + u[n-2-k2] - C[k2+1]*(u[n2+k2]-u[n-2-k2]) - C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2;
-      v[n2+1+ k2] = ( u[n2+1+k2] - u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2;
-      v[n-1 - k2] = (-u[n2+1+k2] + u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2;
-   }
-   // step 8
-   for (k=k2=0; k < n4; ++k,k2 += 2) {
-      X[k]      = v[k2+n2]*B[k2  ] + v[k2+1+n2]*B[k2+1];
-      X[n2-1-k] = v[k2+n2]*B[k2+1] - v[k2+1+n2]*B[k2  ];
-   }
-
-   // decode kernel to output
-   // determined the following value experimentally
-   // (by first figuring out what made inverse_mdct_slow work); then matching that here
-   // (probably vorbis encoder premultiplies by n or n/2, to save it on the decoder?)
-   s = 0.5; // theoretically would be n4
-
-   // [[[ note! the s value of 0.5 is compensated for by the B[] in the current code,
-   //     so it needs to use the "old" B values to behave correctly, or else
-   //     set s to 1.0 ]]]
-   for (i=0; i < n4  ; ++i) buffer[i] = s * X[i+n4];
-   for (   ; i < n3_4; ++i) buffer[i] = -s * X[n3_4 - i - 1];
-   for (   ; i < n   ; ++i) buffer[i] = -s * X[i - n3_4];
-}
-#endif
-
-static float *stbv_get_window(stbv_vorb *f, int len)
-{
-   len <<= 1;
-   if (len == f->blocksize_0) return f->window[0];
-   if (len == f->blocksize_1) return f->window[1];
-   assert(0);
-   return NULL;
-}
-
-#ifndef STB_VORBIS_NO_DEFER_FLOOR
-typedef stbv_int16 STBV_YTYPE;
-#else
-typedef int STBV_YTYPE;
-#endif
-static int stbv_do_floor(stbv_vorb *f, StbvMapping *map, int i, int n, float *target, STBV_YTYPE *finalY, stbv_uint8 *step2_flag)
-{
-   int n2 = n >> 1;
-   int s = map->chan[i].mux, floor;
-   floor = map->submap_floor[s];
-   if (f->floor_types[floor] == 0) {
-      return stbv_error(f, VORBIS_invalid_stream);
-   } else {
-      StbvFloor1 *g = &f->floor_config[floor].floor1;
-      int j,q;
-      int lx = 0, ly = finalY[0] * g->floor1_multiplier;
-      for (q=1; q < g->values; ++q) {
-         j = g->sorted_order[q];
-         #ifndef STB_VORBIS_NO_DEFER_FLOOR
-         if (finalY[j] >= 0)
-         #else
-         if (step2_flag[j])
-         #endif
-         {
-            int hy = finalY[j] * g->floor1_multiplier;
-            int hx = g->Xlist[j];
-            if (lx != hx)
-               stbv_draw_line(target, lx,ly, hx,hy, n2);
-            STBV_CHECK(f);
-            lx = hx, ly = hy;
-         }
-      }
-      if (lx < n2) {
-         // optimization of: stbv_draw_line(target, lx,ly, n,ly, n2);
-         for (j=lx; j < n2; ++j)
-            STBV_LINE_OP(target[j], stbv_inverse_db_table[ly]);
-         STBV_CHECK(f);
-      }
-   }
-   return TRUE;
-}
-
-// The meaning of "left" and "right"
-//
-// For a given frame:
-//     we compute samples from 0..n
-//     window_center is n/2
-//     we'll window and mix the samples from left_start to left_end with data from the previous frame
-//     all of the samples from left_end to right_start can be output without mixing; however,
-//        this interval is 0-length except when transitioning between short and long frames
-//     all of the samples from right_start to right_end need to be mixed with the next frame,
-//        which we don't have, so those get saved in a buffer
-//     frame N's right_end-right_start, the number of samples to mix with the next frame,
-//        has to be the same as frame N+1's left_end-left_start (which they are by
-//        construction)
-
-static int stbv_vorbis_decode_initial(stbv_vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode)
-{
-   StbvMode *m;
-   int i, n, prev, next, window_center;
-   f->channel_buffer_start = f->channel_buffer_end = 0;
-
-  retry:
-   if (f->eof) return FALSE;
-   if (!stbv_maybe_start_packet(f))
-      return FALSE;
-   // check packet type
-   if (stbv_get_bits(f,1) != 0) {
-      if (STBV_IS_PUSH_MODE(f))
-         return stbv_error(f,VORBIS_bad_packet_type);
-      while (STBV_EOP != stbv_get8_packet(f));
-      goto retry;
-   }
-
-   if (f->alloc.alloc_buffer)
-      assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
-
-   i = stbv_get_bits(f, stbv_ilog(f->mode_count-1));
-   if (i == STBV_EOP) return FALSE;
-   if (i >= f->mode_count) return FALSE;
-   *mode = i;
-   m = f->mode_config + i;
-   if (m->blockflag) {
-      n = f->blocksize_1;
-      prev = stbv_get_bits(f,1);
-      next = stbv_get_bits(f,1);
-   } else {
-      prev = next = 0;
-      n = f->blocksize_0;
-   }
-
-// WINDOWING
-
-   window_center = n >> 1;
-   if (m->blockflag && !prev) {
-      *p_left_start = (n - f->blocksize_0) >> 2;
-      *p_left_end   = (n + f->blocksize_0) >> 2;
-   } else {
-      *p_left_start = 0;
-      *p_left_end   = window_center;
-   }
-   if (m->blockflag && !next) {
-      *p_right_start = (n*3 - f->blocksize_0) >> 2;
-      *p_right_end   = (n*3 + f->blocksize_0) >> 2;
-   } else {
-      *p_right_start = window_center;
-      *p_right_end   = n;
-   }
-
-   return TRUE;
-}
-
-static int stbv_vorbis_decode_packet_rest(stbv_vorb *f, int *len, StbvMode *m, int left_start, int left_end, int right_start, int right_end, int *p_left)
-{
-   StbvMapping *map;
-   int i,j,k,n,n2;
-   int zero_channel[256];
-   int really_zero_channel[256];
-
-// WINDOWING
-
-   n = f->blocksize[m->blockflag];
-   map = &f->mapping[m->mapping];
-
-// FLOORS
-   n2 = n >> 1;
-
-   STBV_CHECK(f);
-
-   for (i=0; i < f->channels; ++i) {
-      int s = map->chan[i].mux, floor;
-      zero_channel[i] = FALSE;
-      floor = map->submap_floor[s];
-      if (f->floor_types[floor] == 0) {
-         return stbv_error(f, VORBIS_invalid_stream);
-      } else {
-         StbvFloor1 *g = &f->floor_config[floor].floor1;
-         if (stbv_get_bits(f, 1)) {
-            short *finalY;
-            stbv_uint8 step2_flag[256];
-            static int range_list[4] = { 256, 128, 86, 64 };
-            int range = range_list[g->floor1_multiplier-1];
-            int offset = 2;
-            finalY = f->finalY[i];
-            finalY[0] = stbv_get_bits(f, stbv_ilog(range)-1);
-            finalY[1] = stbv_get_bits(f, stbv_ilog(range)-1);
-            for (j=0; j < g->partitions; ++j) {
-               int pclass = g->partition_class_list[j];
-               int cdim = g->class_dimensions[pclass];
-               int cbits = g->class_subclasses[pclass];
-               int csub = (1 << cbits)-1;
-               int cval = 0;
-               if (cbits) {
-                  StbvCodebook *c = f->codebooks + g->class_masterbooks[pclass];
-                  STBV_DECODE(cval,f,c);
-               }
-               for (k=0; k < cdim; ++k) {
-                  int book = g->subclass_books[pclass][cval & csub];
-                  cval = cval >> cbits;
-                  if (book >= 0) {
-                     int temp;
-                     StbvCodebook *c = f->codebooks + book;
-                     STBV_DECODE(temp,f,c);
-                     finalY[offset++] = temp;
-                  } else
-                     finalY[offset++] = 0;
-               }
-            }
-            if (f->valid_bits == STBV_INVALID_BITS) goto error; // behavior according to spec
-            step2_flag[0] = step2_flag[1] = 1;
-            for (j=2; j < g->values; ++j) {
-               int low, high, pred, highroom, lowroom, room, val;
-               low = g->stbv_neighbors[j][0];
-               high = g->stbv_neighbors[j][1];
-               //stbv_neighbors(g->Xlist, j, &low, &high);
-               pred = stbv_predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]);
-               val = finalY[j];
-               highroom = range - pred;
-               lowroom = pred;
-               if (highroom < lowroom)
-                  room = highroom * 2;
-               else
-                  room = lowroom * 2;
-               if (val) {
-                  step2_flag[low] = step2_flag[high] = 1;
-                  step2_flag[j] = 1;
-                  if (val >= room)
-                     if (highroom > lowroom)
-                        finalY[j] = val - lowroom + pred;
-                     else
-                        finalY[j] = pred - val + highroom - 1;
-                  else
-                     if (val & 1)
-                        finalY[j] = pred - ((val+1)>>1);
-                     else
-                        finalY[j] = pred + (val>>1);
-               } else {
-                  step2_flag[j] = 0;
-                  finalY[j] = pred;
-               }
-            }
-
-#ifdef STB_VORBIS_NO_DEFER_FLOOR
-            stbv_do_floor(f, map, i, n, f->floor_buffers[i], finalY, step2_flag);
-#else
-            // defer final floor computation until _after_ residue
-            for (j=0; j < g->values; ++j) {
-               if (!step2_flag[j])
-                  finalY[j] = -1;
-            }
-#endif
-         } else {
-           error:
-            zero_channel[i] = TRUE;
-         }
-         // So we just defer everything else to later
-
-         // at this point we've decoded the floor into buffer
-      }
-   }
-   STBV_CHECK(f);
-   // at this point we've decoded all floors
-
-   if (f->alloc.alloc_buffer)
-      assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
-
-   // re-enable coupled channels if necessary
-   memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels);
-   for (i=0; i < map->coupling_steps; ++i)
-      if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) {
-         zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE;
-      }
-
-   STBV_CHECK(f);
-// RESIDUE STBV_DECODE
-   for (i=0; i < map->submaps; ++i) {
-      float *residue_buffers[STB_VORBIS_MAX_CHANNELS];
-      int r;
-      stbv_uint8 do_not_decode[256];
-      int ch = 0;
-      for (j=0; j < f->channels; ++j) {
-         if (map->chan[j].mux == i) {
-            if (zero_channel[j]) {
-               do_not_decode[ch] = TRUE;
-               residue_buffers[ch] = NULL;
-            } else {
-               do_not_decode[ch] = FALSE;
-               residue_buffers[ch] = f->channel_buffers[j];
-            }
-            ++ch;
-         }
-      }
-      r = map->submap_residue[i];
-      stbv_decode_residue(f, residue_buffers, ch, n2, r, do_not_decode);
-   }
-
-   if (f->alloc.alloc_buffer)
-      assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
-   STBV_CHECK(f);
-
-// INVERSE COUPLING
-   for (i = map->coupling_steps-1; i >= 0; --i) {
-      int n2 = n >> 1;
-      float *m = f->channel_buffers[map->chan[i].magnitude];
-      float *a = f->channel_buffers[map->chan[i].angle    ];
-      for (j=0; j < n2; ++j) {
-         float a2,m2;
-         if (m[j] > 0)
-            if (a[j] > 0)
-               m2 = m[j], a2 = m[j] - a[j];
-            else
-               a2 = m[j], m2 = m[j] + a[j];
-         else
-            if (a[j] > 0)
-               m2 = m[j], a2 = m[j] + a[j];
-            else
-               a2 = m[j], m2 = m[j] - a[j];
-         m[j] = m2;
-         a[j] = a2;
-      }
-   }
-   STBV_CHECK(f);
-
-   // finish decoding the floors
-#ifndef STB_VORBIS_NO_DEFER_FLOOR
-   for (i=0; i < f->channels; ++i) {
-      if (really_zero_channel[i]) {
-         memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2);
-      } else {
-         stbv_do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL);
-      }
-   }
-#else
-   for (i=0; i < f->channels; ++i) {
-      if (really_zero_channel[i]) {
-         memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2);
-      } else {
-         for (j=0; j < n2; ++j)
-            f->channel_buffers[i][j] *= f->floor_buffers[i][j];
-      }
-   }
-#endif
-
-// INVERSE MDCT
-   STBV_CHECK(f);
-   for (i=0; i < f->channels; ++i)
-      stbv_inverse_mdct(f->channel_buffers[i], n, f, m->blockflag);
-   STBV_CHECK(f);
-
-   // this shouldn't be necessary, unless we exited on an error
-   // and want to flush to get to the next packet
-   stbv_flush_packet(f);
-
-   if (f->first_decode) {
-      // assume we start so first non-discarded sample is sample 0
-      // this isn't to spec, but spec would require us to read ahead
-      // and decode the size of all current frames--could be done,
-      // but presumably it's not a commonly used feature
-      f->current_loc = -n2; // start of first frame is positioned for discard
-      // we might have to discard samples "from" the next frame too,
-      // if we're lapping a large block then a small at the start?
-      f->discard_samples_deferred = n - right_end;
-      f->current_loc_valid = TRUE;
-      f->first_decode = FALSE;
-   } else if (f->discard_samples_deferred) {
-      if (f->discard_samples_deferred >= right_start - left_start) {
-         f->discard_samples_deferred -= (right_start - left_start);
-         left_start = right_start;
-         *p_left = left_start;
-      } else {
-         left_start += f->discard_samples_deferred;
-         *p_left = left_start;
-         f->discard_samples_deferred = 0;
-      }
-   } else if (f->previous_length == 0 && f->current_loc_valid) {
-      // we're recovering from a seek... that means we're going to discard
-      // the samples from this packet even though we know our position from
-      // the last page header, so we need to update the position based on
-      // the discarded samples here
-      // but wait, the code below is going to add this in itself even
-      // on a discard, so we don't need to do it here...
-   }
-
-   // check if we have ogg information about the sample # for this packet
-   if (f->last_seg_which == f->end_seg_with_known_loc) {
-      // if we have a valid current loc, and this is final:
-      if (f->current_loc_valid && (f->page_flag & STBV_PAGEFLAG_last_page)) {
-         stbv_uint32 current_end = f->known_loc_for_packet;
-         // then let's infer the size of the (probably) short final frame
-         if (current_end < f->current_loc + (right_end-left_start)) {
-            if (current_end < f->current_loc) {
-               // negative truncation, that's impossible!
-               *len = 0;
-            } else {
-               *len = current_end - f->current_loc;
-            }
-            *len += left_start; // this doesn't seem right, but has no ill effect on my test files
-            if (*len > right_end) *len = right_end; // this should never happen
-            f->current_loc += *len;
-            return TRUE;
-         }
-      }
-      // otherwise, just set our sample loc
-      // guess that the ogg granule pos refers to the _middle_ of the
-      // last frame?
-      // set f->current_loc to the position of left_start
-      f->current_loc = f->known_loc_for_packet - (n2-left_start);
-      f->current_loc_valid = TRUE;
-   }
-   if (f->current_loc_valid)
-      f->current_loc += (right_start - left_start);
-
-   if (f->alloc.alloc_buffer)
-      assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);
-   *len = right_end;  // ignore samples after the window goes to 0
-   STBV_CHECK(f);
-
-   return TRUE;
-}
-
-static int stbv_vorbis_decode_packet(stbv_vorb *f, int *len, int *p_left, int *p_right)
-{
-   int mode, left_end, right_end;
-   if (!stbv_vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0;
-   return stbv_vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left);
-}
-
-static int stbv_vorbis_finish_frame(stb_vorbis *f, int len, int left, int right)
-{
-   int prev,i,j;
-   // we use right&left (the start of the right- and left-window sin()-regions)
-   // to determine how much to return, rather than inferring from the rules
-   // (same result, clearer code); 'left' indicates where our sin() window
-   // starts, therefore where the previous window's right edge starts, and
-   // therefore where to start mixing from the previous buffer. 'right'
-   // indicates where our sin() ending-window starts, therefore that's where
-   // we start saving, and where our returned-data ends.
-
-   // mixin from previous window
-   if (f->previous_length) {
-      int i,j, n = f->previous_length;
-      float *w = stbv_get_window(f, n);
-      for (i=0; i < f->channels; ++i) {
-         for (j=0; j < n; ++j)
-            f->channel_buffers[i][left+j] =
-               f->channel_buffers[i][left+j]*w[    j] +
-               f->previous_window[i][     j]*w[n-1-j];
-      }
-   }
-
-   prev = f->previous_length;
-
-   // last half of this data becomes previous window
-   f->previous_length = len - right;
-
-   // @OPTIMIZE: could avoid this copy by double-buffering the
-   // output (flipping previous_window with channel_buffers), but
-   // then previous_window would have to be 2x as large, and
-   // channel_buffers couldn't be temp mem (although they're NOT
-   // currently temp mem, they could be (unless we want to level
-   // performance by spreading out the computation))
-   for (i=0; i < f->channels; ++i)
-      for (j=0; right+j < len; ++j)
-         f->previous_window[i][j] = f->channel_buffers[i][right+j];
-
-   if (!prev)
-      // there was no previous packet, so this data isn't valid...
-      // this isn't entirely true, only the would-have-overlapped data
-      // isn't valid, but this seems to be what the spec requires
-      return 0;
-
-   // truncate a short frame
-   if (len < right) right = len;
-
-   f->samples_output += right-left;
-
-   return right - left;
-}
-
-static int stbv_vorbis_pump_first_frame(stb_vorbis *f)
-{
-   int len, right, left, res;
-   res = stbv_vorbis_decode_packet(f, &len, &left, &right);
-   if (res)
-      stbv_vorbis_finish_frame(f, len, left, right);
-   return res;
-}
-
-#ifndef STB_VORBIS_NO_PUSHDATA_API
-static int stbv_is_whole_packet_present(stb_vorbis *f, int end_page)
-{
-   // make sure that we have the packet available before continuing...
-   // this requires a full ogg parse, but we know we can fetch from f->stream
-
-   // instead of coding this out explicitly, we could save the current read state,
-   // read the next packet with stbv_get8() until end-of-packet, check f->eof, then
-   // reset the state? but that would be slower, esp. since we'd have over 256 bytes
-   // of state to restore (primarily the page segment table)
-
-   int s = f->next_seg, first = TRUE;
-   stbv_uint8 *p = f->stream;
-
-   if (s != -1) { // if we're not starting the packet with a 'continue on next page' flag
-      for (; s < f->segment_count; ++s) {
-         p += f->segments[s];
-         if (f->segments[s] < 255)               // stop at first short segment
-            break;
-      }
-      // either this continues, or it ends it...
-      if (end_page)
-         if (s < f->segment_count-1)             return stbv_error(f, VORBIS_invalid_stream);
-      if (s == f->segment_count)
-         s = -1; // set 'crosses page' flag
-      if (p > f->stream_end)                     return stbv_error(f, VORBIS_need_more_data);
-      first = FALSE;
-   }
-   for (; s == -1;) {
-      stbv_uint8 *q; 
-      int n;
-
-      // check that we have the page header ready
-      if (p + 26 >= f->stream_end)               return stbv_error(f, VORBIS_need_more_data);
-      // validate the page
-      if (memcmp(p, stbv_ogg_page_header, 4))         return stbv_error(f, VORBIS_invalid_stream);
-      if (p[4] != 0)                             return stbv_error(f, VORBIS_invalid_stream);
-      if (first) { // the first segment must NOT have 'continued_packet', later ones MUST
-         if (f->previous_length)
-            if ((p[5] & STBV_PAGEFLAG_continued_packet))  return stbv_error(f, VORBIS_invalid_stream);
-         // if no previous length, we're resynching, so we can come in on a continued-packet,
-         // which we'll just drop
-      } else {
-         if (!(p[5] & STBV_PAGEFLAG_continued_packet)) return stbv_error(f, VORBIS_invalid_stream);
-      }
-      n = p[26]; // segment counts
-      q = p+27;  // q points to segment table
-      p = q + n; // advance past header
-      // make sure we've read the segment table
-      if (p > f->stream_end)                     return stbv_error(f, VORBIS_need_more_data);
-      for (s=0; s < n; ++s) {
-         p += q[s];
-         if (q[s] < 255)
-            break;
-      }
-      if (end_page)
-         if (s < n-1)                            return stbv_error(f, VORBIS_invalid_stream);
-      if (s == n)
-         s = -1; // set 'crosses page' flag
-      if (p > f->stream_end)                     return stbv_error(f, VORBIS_need_more_data);
-      first = FALSE;
-   }
-   return TRUE;
-}
-#endif // !STB_VORBIS_NO_PUSHDATA_API
-
-static int stbv_start_decoder(stbv_vorb *f)
-{
-   stbv_uint8 header[6], x,y;
-   int len,i,j,k, max_submaps = 0;
-   int longest_floorlist=0;
-
-   // first page, first packet
-
-   if (!stbv_start_page(f))                              return FALSE;
-   // validate page flag
-   if (!(f->page_flag & STBV_PAGEFLAG_first_page))       return stbv_error(f, VORBIS_invalid_first_page);
-   if (f->page_flag & STBV_PAGEFLAG_last_page)           return stbv_error(f, VORBIS_invalid_first_page);
-   if (f->page_flag & STBV_PAGEFLAG_continued_packet)    return stbv_error(f, VORBIS_invalid_first_page);
-   // check for expected packet length
-   if (f->segment_count != 1)                       return stbv_error(f, VORBIS_invalid_first_page);
-   if (f->segments[0] != 30)                        return stbv_error(f, VORBIS_invalid_first_page);
-   // read packet
-   // check packet header
-   if (stbv_get8(f) != STBV_VORBIS_packet_id)                 return stbv_error(f, VORBIS_invalid_first_page);
-   if (!stbv_getn(f, header, 6))                         return stbv_error(f, VORBIS_unexpected_eof);
-   if (!stbv_vorbis_validate(header))                    return stbv_error(f, VORBIS_invalid_first_page);
-   // vorbis_version
-   if (stbv_get32(f) != 0)                               return stbv_error(f, VORBIS_invalid_first_page);
-   f->channels = stbv_get8(f); if (!f->channels)         return stbv_error(f, VORBIS_invalid_first_page);
-   if (f->channels > STB_VORBIS_MAX_CHANNELS)       return stbv_error(f, VORBIS_too_many_channels);
-   f->sample_rate = stbv_get32(f); if (!f->sample_rate)  return stbv_error(f, VORBIS_invalid_first_page);
-   stbv_get32(f); // bitrate_maximum
-   stbv_get32(f); // bitrate_nominal
-   stbv_get32(f); // bitrate_minimum
-   x = stbv_get8(f);
-   {
-      int log0,log1;
-      log0 = x & 15;
-      log1 = x >> 4;
-      f->blocksize_0 = 1 << log0;
-      f->blocksize_1 = 1 << log1;
-      if (log0 < 6 || log0 > 13)                       return stbv_error(f, VORBIS_invalid_setup);
-      if (log1 < 6 || log1 > 13)                       return stbv_error(f, VORBIS_invalid_setup);
-      if (log0 > log1)                                 return stbv_error(f, VORBIS_invalid_setup);
-   }
-
-   // framing_flag
-   x = stbv_get8(f);
-   if (!(x & 1))                                    return stbv_error(f, VORBIS_invalid_first_page);
-
-   // second packet!
-   if (!stbv_start_page(f))                              return FALSE;
-
-   if (!stbv_start_packet(f))                            return FALSE;
-   do {
-      len = stbv_next_segment(f);
-      stbv_skip(f, len);
-      f->bytes_in_seg = 0;
-   } while (len);
-
-   // third packet!
-   if (!stbv_start_packet(f))                            return FALSE;
-
-   #ifndef STB_VORBIS_NO_PUSHDATA_API
-   if (STBV_IS_PUSH_MODE(f)) {
-      if (!stbv_is_whole_packet_present(f, TRUE)) {
-         // convert error in ogg header to write type
-         if (f->error == VORBIS_invalid_stream)
-            f->error = VORBIS_invalid_setup;
-         return FALSE;
-      }
-   }
-   #endif
-
-   stbv_crc32_init(); // always init it, to avoid multithread race conditions
-
-   if (stbv_get8_packet(f) != STBV_VORBIS_packet_setup)       return stbv_error(f, VORBIS_invalid_setup);
-   for (i=0; i < 6; ++i) header[i] = stbv_get8_packet(f);
-   if (!stbv_vorbis_validate(header))                    return stbv_error(f, VORBIS_invalid_setup);
-
-   // codebooks
-
-   f->codebook_count = stbv_get_bits(f,8) + 1;
-   f->codebooks = (StbvCodebook *) stbv_setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count);
-   if (f->codebooks == NULL)                        return stbv_error(f, VORBIS_outofmem);
-   memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count);
-   for (i=0; i < f->codebook_count; ++i) {
-      stbv_uint32 *values;
-      int ordered, sorted_count;
-      int total=0;
-      stbv_uint8 *lengths;
-      StbvCodebook *c = f->codebooks+i;
-      STBV_CHECK(f);
-      x = stbv_get_bits(f, 8); if (x != 0x42)            return stbv_error(f, VORBIS_invalid_setup);
-      x = stbv_get_bits(f, 8); if (x != 0x43)            return stbv_error(f, VORBIS_invalid_setup);
-      x = stbv_get_bits(f, 8); if (x != 0x56)            return stbv_error(f, VORBIS_invalid_setup);
-      x = stbv_get_bits(f, 8);
-      c->dimensions = (stbv_get_bits(f, 8)<<8) + x;
-      x = stbv_get_bits(f, 8);
-      y = stbv_get_bits(f, 8);
-      c->entries = (stbv_get_bits(f, 8)<<16) + (y<<8) + x;
-      ordered = stbv_get_bits(f,1);
-      c->sparse = ordered ? 0 : stbv_get_bits(f,1);
-
-      if (c->dimensions == 0 && c->entries != 0)    return stbv_error(f, VORBIS_invalid_setup);
-
-      if (c->sparse)
-         lengths = (stbv_uint8 *) stbv_setup_temp_malloc(f, c->entries);
-      else
-         lengths = c->codeword_lengths = (stbv_uint8 *) stbv_setup_malloc(f, c->entries);
-
-      if (!lengths) return stbv_error(f, VORBIS_outofmem);
-
-      if (ordered) {
-         int current_entry = 0;
-         int current_length = stbv_get_bits(f,5) + 1;
-         while (current_entry < c->entries) {
-            int limit = c->entries - current_entry;
-            int n = stbv_get_bits(f, stbv_ilog(limit));
-            if (current_entry + n > (int) c->entries) { return stbv_error(f, VORBIS_invalid_setup); }
-            memset(lengths + current_entry, current_length, n);
-            current_entry += n;
-            ++current_length;
-         }
-      } else {
-         for (j=0; j < c->entries; ++j) {
-            int present = c->sparse ? stbv_get_bits(f,1) : 1;
-            if (present) {
-               lengths[j] = stbv_get_bits(f, 5) + 1;
-               ++total;
-               if (lengths[j] == 32)
-                  return stbv_error(f, VORBIS_invalid_setup);
-            } else {
-               lengths[j] = NO_CODE;
-            }
-         }
-      }
-
-      if (c->sparse && total >= c->entries >> 2) {
-         // convert sparse items to non-sparse!
-         if (c->entries > (int) f->setup_temp_memory_required)
-            f->setup_temp_memory_required = c->entries;
-
-         c->codeword_lengths = (stbv_uint8 *) stbv_setup_malloc(f, c->entries);
-         if (c->codeword_lengths == NULL) return stbv_error(f, VORBIS_outofmem);
-         memcpy(c->codeword_lengths, lengths, c->entries);
-         stbv_setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs!
-         lengths = c->codeword_lengths;
-         c->sparse = 0;
-      }
-
-      // compute the size of the sorted tables
-      if (c->sparse) {
-         sorted_count = total;
-      } else {
-         sorted_count = 0;
-         #ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH
-         for (j=0; j < c->entries; ++j)
-            if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE)
-               ++sorted_count;
-         #endif
-      }
-
-      c->sorted_entries = sorted_count;
-      values = NULL;
-
-      STBV_CHECK(f);
-      if (!c->sparse) {
-         c->codewords = (stbv_uint32 *) stbv_setup_malloc(f, sizeof(c->codewords[0]) * c->entries);
-         if (!c->codewords)                  return stbv_error(f, VORBIS_outofmem);
-      } else {
-         unsigned int size;
-         if (c->sorted_entries) {
-            c->codeword_lengths = (stbv_uint8 *) stbv_setup_malloc(f, c->sorted_entries);
-            if (!c->codeword_lengths)           return stbv_error(f, VORBIS_outofmem);
-            c->codewords = (stbv_uint32 *) stbv_setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries);
-            if (!c->codewords)                  return stbv_error(f, VORBIS_outofmem);
-            values = (stbv_uint32 *) stbv_setup_temp_malloc(f, sizeof(*values) * c->sorted_entries);
-            if (!values)                        return stbv_error(f, VORBIS_outofmem);
-         }
-         size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries;
-         if (size > f->setup_temp_memory_required)
-            f->setup_temp_memory_required = size;
-      }
-
-      if (!stbv_compute_codewords(c, lengths, c->entries, values)) {
-         if (c->sparse) stbv_setup_temp_free(f, values, 0);
-         return stbv_error(f, VORBIS_invalid_setup);
-      }
-
-      if (c->sorted_entries) {
-         // allocate an extra slot for sentinels
-         c->sorted_codewords = (stbv_uint32 *) stbv_setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1));
-         if (c->sorted_codewords == NULL) return stbv_error(f, VORBIS_outofmem);
-         // allocate an extra slot at the front so that c->sorted_values[-1] is defined
-         // so that we can catch that case without an extra if
-         c->sorted_values    = ( int   *) stbv_setup_malloc(f, sizeof(*c->sorted_values   ) * (c->sorted_entries+1));
-         if (c->sorted_values == NULL) return stbv_error(f, VORBIS_outofmem);
-         ++c->sorted_values;
-         c->sorted_values[-1] = -1;
-         stbv_compute_sorted_huffman(c, lengths, values);
-      }
-
-      if (c->sparse) {
-         stbv_setup_temp_free(f, values, sizeof(*values)*c->sorted_entries);
-         stbv_setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries);
-         stbv_setup_temp_free(f, lengths, c->entries);
-         c->codewords = NULL;
-      }
-
-      stbv_compute_accelerated_huffman(c);
-
-      STBV_CHECK(f);
-      c->lookup_type = stbv_get_bits(f, 4);
-      if (c->lookup_type > 2) return stbv_error(f, VORBIS_invalid_setup);
-      if (c->lookup_type > 0) {
-         stbv_uint16 *mults;
-         c->minimum_value = stbv_float32_unpack(stbv_get_bits(f, 32));
-         c->delta_value = stbv_float32_unpack(stbv_get_bits(f, 32));
-         c->value_bits = stbv_get_bits(f, 4)+1;
-         c->sequence_p = stbv_get_bits(f,1);
-         if (c->lookup_type == 1) {
-            c->lookup_values = stbv_lookup1_values(c->entries, c->dimensions);
-         } else {
-            c->lookup_values = c->entries * c->dimensions;
-         }
-         if (c->lookup_values == 0) return stbv_error(f, VORBIS_invalid_setup);
-         mults = (stbv_uint16 *) stbv_setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values);
-         if (mults == NULL) return stbv_error(f, VORBIS_outofmem);
-         for (j=0; j < (int) c->lookup_values; ++j) {
-            int q = stbv_get_bits(f, c->value_bits);
-            if (q == STBV_EOP) { stbv_setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return stbv_error(f, VORBIS_invalid_setup); }
-            mults[j] = q;
-         }
-
-#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
-         if (c->lookup_type == 1) {
-            int len, sparse = c->sparse;
-            float last=0;
-            // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop
-            if (sparse) {
-               if (c->sorted_entries == 0) goto stbv_skip;
-               c->multiplicands = (stbv_codetype *) stbv_setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions);
-            } else
-               c->multiplicands = (stbv_codetype *) stbv_setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries        * c->dimensions);
-            if (c->multiplicands == NULL) { stbv_setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return stbv_error(f, VORBIS_outofmem); }
-            len = sparse ? c->sorted_entries : c->entries;
-            for (j=0; j < len; ++j) {
-               unsigned int z = sparse ? c->sorted_values[j] : j;
-               unsigned int div=1;
-               for (k=0; k < c->dimensions; ++k) {
-                  int off = (z / div) % c->lookup_values;
-                  float val = mults[off];
-                  val = mults[off]*c->delta_value + c->minimum_value + last;
-                  c->multiplicands[j*c->dimensions + k] = val;
-                  if (c->sequence_p)
-                     last = val;
-                  if (k+1 < c->dimensions) {
-                     if (div > UINT_MAX / (unsigned int) c->lookup_values) {
-                        stbv_setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
-                        return stbv_error(f, VORBIS_invalid_setup);
-                     }
-                     div *= c->lookup_values;
-                  }
-               }
-            }
-            c->lookup_type = 2;
-         }
-         else
-#endif
-         {
-            float last=0;
-            STBV_CHECK(f);
-            c->multiplicands = (stbv_codetype *) stbv_setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values);
-            if (c->multiplicands == NULL) { stbv_setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return stbv_error(f, VORBIS_outofmem); }
-            for (j=0; j < (int) c->lookup_values; ++j) {
-               float val = mults[j] * c->delta_value + c->minimum_value + last;
-               c->multiplicands[j] = val;
-               if (c->sequence_p)
-                  last = val;
-            }
-         }
-#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
-        stbv_skip:;
-#endif
-         stbv_setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values);
-
-         STBV_CHECK(f);
-      }
-      STBV_CHECK(f);
-   }
-
-   // time domain transfers (notused)
-
-   x = stbv_get_bits(f, 6) + 1;
-   for (i=0; i < x; ++i) {
-      stbv_uint32 z = stbv_get_bits(f, 16);
-      if (z != 0) return stbv_error(f, VORBIS_invalid_setup);
-   }
-
-   // Floors
-   f->floor_count = stbv_get_bits(f, 6)+1;
-   f->floor_config = (StbvFloor *)  stbv_setup_malloc(f, f->floor_count * sizeof(*f->floor_config));
-   if (f->floor_config == NULL) return stbv_error(f, VORBIS_outofmem);
-   for (i=0; i < f->floor_count; ++i) {
-      f->floor_types[i] = stbv_get_bits(f, 16);
-      if (f->floor_types[i] > 1) return stbv_error(f, VORBIS_invalid_setup);
-      if (f->floor_types[i] == 0) {
-         StbvFloor0 *g = &f->floor_config[i].floor0;
-         g->order = stbv_get_bits(f,8);
-         g->rate = stbv_get_bits(f,16);
-         g->bark_map_size = stbv_get_bits(f,16);
-         g->amplitude_bits = stbv_get_bits(f,6);
-         g->amplitude_offset = stbv_get_bits(f,8);
-         g->number_of_books = stbv_get_bits(f,4) + 1;
-         for (j=0; j < g->number_of_books; ++j)
-            g->book_list[j] = stbv_get_bits(f,8);
-         return stbv_error(f, VORBIS_feature_not_supported);
-      } else {
-         stbv_floor_ordering p[31*8+2];
-         StbvFloor1 *g = &f->floor_config[i].floor1;
-         int max_class = -1; 
-         g->partitions = stbv_get_bits(f, 5);
-         for (j=0; j < g->partitions; ++j) {
-            g->partition_class_list[j] = stbv_get_bits(f, 4);
-            if (g->partition_class_list[j] > max_class)
-               max_class = g->partition_class_list[j];
-         }
-         for (j=0; j <= max_class; ++j) {
-            g->class_dimensions[j] = stbv_get_bits(f, 3)+1;
-            g->class_subclasses[j] = stbv_get_bits(f, 2);
-            if (g->class_subclasses[j]) {
-               g->class_masterbooks[j] = stbv_get_bits(f, 8);
-               if (g->class_masterbooks[j] >= f->codebook_count) return stbv_error(f, VORBIS_invalid_setup);
-            }
-            for (k=0; k < 1 << g->class_subclasses[j]; ++k) {
-               g->subclass_books[j][k] = stbv_get_bits(f,8)-1;
-               if (g->subclass_books[j][k] >= f->codebook_count) return stbv_error(f, VORBIS_invalid_setup);
-            }
-         }
-         g->floor1_multiplier = stbv_get_bits(f,2)+1;
-         g->rangebits = stbv_get_bits(f,4);
-         g->Xlist[0] = 0;
-         g->Xlist[1] = 1 << g->rangebits;
-         g->values = 2;
-         for (j=0; j < g->partitions; ++j) {
-            int c = g->partition_class_list[j];
-            for (k=0; k < g->class_dimensions[c]; ++k) {
-               g->Xlist[g->values] = stbv_get_bits(f, g->rangebits);
-               ++g->values;
-            }
-         }
-         // precompute the sorting
-         for (j=0; j < g->values; ++j) {
-            p[j].x = g->Xlist[j];
-            p[j].id = j;
-         }
-         qsort(p, g->values, sizeof(p[0]), stbv_point_compare);
-         for (j=0; j < g->values; ++j)
-            g->sorted_order[j] = (stbv_uint8) p[j].id;
-         // precompute the stbv_neighbors
-         for (j=2; j < g->values; ++j) {
-            int low,hi;
-            stbv_neighbors(g->Xlist, j, &low,&hi);
-            g->stbv_neighbors[j][0] = low;
-            g->stbv_neighbors[j][1] = hi;
-         }
-
-         if (g->values > longest_floorlist)
-            longest_floorlist = g->values;
-      }
-   }
-
-   // StbvResidue
-   f->residue_count = stbv_get_bits(f, 6)+1;
-   f->residue_config = (StbvResidue *) stbv_setup_malloc(f, f->residue_count * sizeof(f->residue_config[0]));
-   if (f->residue_config == NULL) return stbv_error(f, VORBIS_outofmem);
-   memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0]));
-   for (i=0; i < f->residue_count; ++i) {
-      stbv_uint8 residue_cascade[64];
-      StbvResidue *r = f->residue_config+i;
-      f->residue_types[i] = stbv_get_bits(f, 16);
-      if (f->residue_types[i] > 2) return stbv_error(f, VORBIS_invalid_setup);
-      r->begin = stbv_get_bits(f, 24);
-      r->end = stbv_get_bits(f, 24);
-      if (r->end < r->begin) return stbv_error(f, VORBIS_invalid_setup);
-      r->part_size = stbv_get_bits(f,24)+1;
-      r->classifications = stbv_get_bits(f,6)+1;
-      r->classbook = stbv_get_bits(f,8);
-      if (r->classbook >= f->codebook_count) return stbv_error(f, VORBIS_invalid_setup);
-      for (j=0; j < r->classifications; ++j) {
-         stbv_uint8 high_bits=0;
-         stbv_uint8 low_bits=stbv_get_bits(f,3);
-         if (stbv_get_bits(f,1))
-            high_bits = stbv_get_bits(f,5);
-         residue_cascade[j] = high_bits*8 + low_bits;
-      }
-      r->residue_books = (short (*)[8]) stbv_setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications);
-      if (r->residue_books == NULL) return stbv_error(f, VORBIS_outofmem);
-      for (j=0; j < r->classifications; ++j) {
-         for (k=0; k < 8; ++k) {
-            if (residue_cascade[j] & (1 << k)) {
-               r->residue_books[j][k] = stbv_get_bits(f, 8);
-               if (r->residue_books[j][k] >= f->codebook_count) return stbv_error(f, VORBIS_invalid_setup);
-            } else {
-               r->residue_books[j][k] = -1;
-            }
-         }
-      }
-      // precompute the classifications[] array to avoid inner-loop mod/divide
-      // call it 'classdata' since we already have r->classifications
-      r->classdata = (stbv_uint8 **) stbv_setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries);
-      if (!r->classdata) return stbv_error(f, VORBIS_outofmem);
-      memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries);
-      for (j=0; j < f->codebooks[r->classbook].entries; ++j) {
-         int classwords = f->codebooks[r->classbook].dimensions;
-         int temp = j;
-         r->classdata[j] = (stbv_uint8 *) stbv_setup_malloc(f, sizeof(r->classdata[j][0]) * classwords);
-         if (r->classdata[j] == NULL) return stbv_error(f, VORBIS_outofmem);
-         for (k=classwords-1; k >= 0; --k) {
-            r->classdata[j][k] = temp % r->classifications;
-            temp /= r->classifications;
-         }
-      }
-   }
-
-   f->mapping_count = stbv_get_bits(f,6)+1;
-   f->mapping = (StbvMapping *) stbv_setup_malloc(f, f->mapping_count * sizeof(*f->mapping));
-   if (f->mapping == NULL) return stbv_error(f, VORBIS_outofmem);
-   memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping));
-   for (i=0; i < f->mapping_count; ++i) {
-      StbvMapping *m = f->mapping + i;      
-      int mapping_type = stbv_get_bits(f,16);
-      if (mapping_type != 0) return stbv_error(f, VORBIS_invalid_setup);
-      m->chan = (StbvMappingChannel *) stbv_setup_malloc(f, f->channels * sizeof(*m->chan));
-      if (m->chan == NULL) return stbv_error(f, VORBIS_outofmem);
-      if (stbv_get_bits(f,1))
-         m->submaps = stbv_get_bits(f,4)+1;
-      else
-         m->submaps = 1;
-      if (m->submaps > max_submaps)
-         max_submaps = m->submaps;
-      if (stbv_get_bits(f,1)) {
-         m->coupling_steps = stbv_get_bits(f,8)+1;
-         for (k=0; k < m->coupling_steps; ++k) {
-            m->chan[k].magnitude = stbv_get_bits(f, stbv_ilog(f->channels-1));
-            m->chan[k].angle = stbv_get_bits(f, stbv_ilog(f->channels-1));
-            if (m->chan[k].magnitude >= f->channels)        return stbv_error(f, VORBIS_invalid_setup);
-            if (m->chan[k].angle     >= f->channels)        return stbv_error(f, VORBIS_invalid_setup);
-            if (m->chan[k].magnitude == m->chan[k].angle)   return stbv_error(f, VORBIS_invalid_setup);
-         }
-      } else
-         m->coupling_steps = 0;
-
-      // reserved field
-      if (stbv_get_bits(f,2)) return stbv_error(f, VORBIS_invalid_setup);
-      if (m->submaps > 1) {
-         for (j=0; j < f->channels; ++j) {
-            m->chan[j].mux = stbv_get_bits(f, 4);
-            if (m->chan[j].mux >= m->submaps)                return stbv_error(f, VORBIS_invalid_setup);
-         }
-      } else
-         // @SPECIFICATION: this case is missing from the spec
-         for (j=0; j < f->channels; ++j)
-            m->chan[j].mux = 0;
-
-      for (j=0; j < m->submaps; ++j) {
-         stbv_get_bits(f,8); // discard
-         m->submap_floor[j] = stbv_get_bits(f,8);
-         m->submap_residue[j] = stbv_get_bits(f,8);
-         if (m->submap_floor[j] >= f->floor_count)      return stbv_error(f, VORBIS_invalid_setup);
-         if (m->submap_residue[j] >= f->residue_count)  return stbv_error(f, VORBIS_invalid_setup);
-      }
-   }
-
-   // Modes
-   f->mode_count = stbv_get_bits(f, 6)+1;
-   for (i=0; i < f->mode_count; ++i) {
-      StbvMode *m = f->mode_config+i;
-      m->blockflag = stbv_get_bits(f,1);
-      m->windowtype = stbv_get_bits(f,16);
-      m->transformtype = stbv_get_bits(f,16);
-      m->mapping = stbv_get_bits(f,8);
-      if (m->windowtype != 0)                 return stbv_error(f, VORBIS_invalid_setup);
-      if (m->transformtype != 0)              return stbv_error(f, VORBIS_invalid_setup);
-      if (m->mapping >= f->mapping_count)     return stbv_error(f, VORBIS_invalid_setup);
-   }
-
-   stbv_flush_packet(f);
-
-   f->previous_length = 0;
-
-   for (i=0; i < f->channels; ++i) {
-      f->channel_buffers[i] = (float *) stbv_setup_malloc(f, sizeof(float) * f->blocksize_1);
-      f->previous_window[i] = (float *) stbv_setup_malloc(f, sizeof(float) * f->blocksize_1/2);
-      f->finalY[i]          = (stbv_int16 *) stbv_setup_malloc(f, sizeof(stbv_int16) * longest_floorlist);
-      if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return stbv_error(f, VORBIS_outofmem);
-      memset(f->channel_buffers[i], 0, sizeof(float) * f->blocksize_1);
-      #ifdef STB_VORBIS_NO_DEFER_FLOOR
-      f->floor_buffers[i]   = (float *) stbv_setup_malloc(f, sizeof(float) * f->blocksize_1/2);
-      if (f->floor_buffers[i] == NULL) return stbv_error(f, VORBIS_outofmem);
-      #endif
-   }
-
-   if (!stbv_init_blocksize(f, 0, f->blocksize_0)) return FALSE;
-   if (!stbv_init_blocksize(f, 1, f->blocksize_1)) return FALSE;
-   f->blocksize[0] = f->blocksize_0;
-   f->blocksize[1] = f->blocksize_1;
-
-#ifdef STB_VORBIS_DIVIDE_TABLE
-   if (stbv_integer_divide_table[1][1]==0)
-      for (i=0; i < STBV_DIVTAB_NUMER; ++i)
-         for (j=1; j < STBV_DIVTAB_DENOM; ++j)
-            stbv_integer_divide_table[i][j] = i / j;
-#endif
-
-   // compute how much temporary memory is needed
-
-   // 1.
-   {
-      stbv_uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1);
-      stbv_uint32 classify_mem;
-      int i,max_part_read=0;
-      for (i=0; i < f->residue_count; ++i) {
-         StbvResidue *r = f->residue_config + i;
-         unsigned int actual_size = f->blocksize_1 / 2;
-         unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size;
-         unsigned int limit_r_end   = r->end   < actual_size ? r->end   : actual_size;
-         int n_read = limit_r_end - limit_r_begin;
-         int part_read = n_read / r->part_size;
-         if (part_read > max_part_read)
-            max_part_read = part_read;
-      }
-      #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
-      classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(stbv_uint8 *));
-      #else
-      classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *));
-      #endif
-
-      // maximum reasonable partition size is f->blocksize_1
-
-      f->temp_memory_required = classify_mem;
-      if (imdct_mem > f->temp_memory_required)
-         f->temp_memory_required = imdct_mem;
-   }
-
-   f->first_decode = TRUE;
-
-   if (f->alloc.alloc_buffer) {
-      assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes);
-      // check if there's enough temp memory so we don't error later
-      if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset)
-         return stbv_error(f, VORBIS_outofmem);
-   }
-
-   f->first_audio_page_offset = stb_vorbis_get_file_offset(f);
-
-   return TRUE;
-}
-
-static void stbv_vorbis_deinit(stb_vorbis *p)
-{
-   int i,j;
-   if (p->residue_config) {
-      for (i=0; i < p->residue_count; ++i) {
-         StbvResidue *r = p->residue_config+i;
-         if (r->classdata) {
-            for (j=0; j < p->codebooks[r->classbook].entries; ++j)
-               stbv_setup_free(p, r->classdata[j]);
-            stbv_setup_free(p, r->classdata);
-         }
-         stbv_setup_free(p, r->residue_books);
-      }
-   }
-
-   if (p->codebooks) {
-      STBV_CHECK(p);
-      for (i=0; i < p->codebook_count; ++i) {
-         StbvCodebook *c = p->codebooks + i;
-         stbv_setup_free(p, c->codeword_lengths);
-         stbv_setup_free(p, c->multiplicands);
-         stbv_setup_free(p, c->codewords);
-         stbv_setup_free(p, c->sorted_codewords);
-         // c->sorted_values[-1] is the first entry in the array
-         stbv_setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL);
-      }
-      stbv_setup_free(p, p->codebooks);
-   }
-   stbv_setup_free(p, p->floor_config);
-   stbv_setup_free(p, p->residue_config);
-   if (p->mapping) {
-      for (i=0; i < p->mapping_count; ++i)
-         stbv_setup_free(p, p->mapping[i].chan);
-      stbv_setup_free(p, p->mapping);
-   }
-   STBV_CHECK(p);
-   for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) {
-      stbv_setup_free(p, p->channel_buffers[i]);
-      stbv_setup_free(p, p->previous_window[i]);
-      #ifdef STB_VORBIS_NO_DEFER_FLOOR
-      stbv_setup_free(p, p->floor_buffers[i]);
-      #endif
-      stbv_setup_free(p, p->finalY[i]);
-   }
-   for (i=0; i < 2; ++i) {
-      stbv_setup_free(p, p->A[i]);
-      stbv_setup_free(p, p->B[i]);
-      stbv_setup_free(p, p->C[i]);
-      stbv_setup_free(p, p->window[i]);
-      stbv_setup_free(p, p->stbv_bit_reverse[i]);
-   }
-   #ifndef STB_VORBIS_NO_STDIO
-   if (p->close_on_free) fclose(p->f);
-   #endif
-}
-
-STBVDEF void stb_vorbis_close(stb_vorbis *p)
-{
-   if (p == NULL) return;
-   stbv_vorbis_deinit(p);
-   stbv_setup_free(p,p);
-}
-
-static void stbv_vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z)
-{
-   memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start
-   if (z) {
-      p->alloc = *z;
-      p->alloc.alloc_buffer_length_in_bytes = (p->alloc.alloc_buffer_length_in_bytes+3) & ~3;
-      p->temp_offset = p->alloc.alloc_buffer_length_in_bytes;
-   }
-   p->eof = 0;
-   p->error = VORBIS__no_error;
-   p->stream = NULL;
-   p->codebooks = NULL;
-   p->page_crc_tests = -1;
-   #ifndef STB_VORBIS_NO_STDIO
-   p->close_on_free = FALSE;
-   p->f = NULL;
-   #endif
-}
-
-STBVDEF int stb_vorbis_get_sample_offset(stb_vorbis *f)
-{
-   if (f->current_loc_valid)
-      return f->current_loc;
-   else
-      return -1;
-}
-
-STBVDEF stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f)
-{
-   stb_vorbis_info d;
-   d.channels = f->channels;
-   d.sample_rate = f->sample_rate;
-   d.setup_memory_required = f->setup_memory_required;
-   d.setup_temp_memory_required = f->setup_temp_memory_required;
-   d.temp_memory_required = f->temp_memory_required;
-   d.max_frame_size = f->blocksize_1 >> 1;
-   return d;
-}
-
-STBVDEF int stb_vorbis_get_error(stb_vorbis *f)
-{
-   int e = f->error;
-   f->error = VORBIS__no_error;
-   return e;
-}
-
-static stb_vorbis * stbv_vorbis_alloc(stb_vorbis *f)
-{
-   stb_vorbis *p = (stb_vorbis *) stbv_setup_malloc(f, sizeof(*p));
-   return p;
-}
-
-#ifndef STB_VORBIS_NO_PUSHDATA_API
-
-STBVDEF void stb_vorbis_flush_pushdata(stb_vorbis *f)
-{
-   f->previous_length = 0;
-   f->page_crc_tests  = 0;
-   f->discard_samples_deferred = 0;
-   f->current_loc_valid = FALSE;
-   f->first_decode = FALSE;
-   f->samples_output = 0;
-   f->channel_buffer_start = 0;
-   f->channel_buffer_end = 0;
-}
-
-static int stbv_vorbis_search_for_page_pushdata(stbv_vorb *f, stbv_uint8 *data, int data_len)
-{
-   int i,n;
-   for (i=0; i < f->page_crc_tests; ++i)
-      f->scan[i].bytes_done = 0;
-
-   // if we have room for more scans, search for them first, because
-   // they may cause us to stop early if their header is incomplete
-   if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) {
-      if (data_len < 4) return 0;
-      data_len -= 3; // need to look for 4-byte sequence, so don't miss
-                     // one that straddles a boundary
-      for (i=0; i < data_len; ++i) {
-         if (data[i] == 0x4f) {
-            if (0==memcmp(data+i, stbv_ogg_page_header, 4)) {
-               int j,len;
-               stbv_uint32 crc;
-               // make sure we have the whole page header
-               if (i+26 >= data_len || i+27+data[i+26] >= data_len) {
-                  // only read up to this page start, so hopefully we'll
-                  // have the whole page header start next time
-                  data_len = i;
-                  break;
-               }
-               // ok, we have it all; compute the length of the page
-               len = 27 + data[i+26];
-               for (j=0; j < data[i+26]; ++j)
-                  len += data[i+27+j];
-               // scan everything up to the embedded crc (which we must 0)
-               crc = 0;
-               for (j=0; j < 22; ++j)
-                  crc = stbv_crc32_update(crc, data[i+j]);
-               // now process 4 0-bytes
-               for (   ; j < 26; ++j)
-                  crc = stbv_crc32_update(crc, 0);
-               // len is the total number of bytes we need to scan
-               n = f->page_crc_tests++;
-               f->scan[n].bytes_left = len-j;
-               f->scan[n].crc_so_far = crc;
-               f->scan[n].goal_crc = data[i+22] + (data[i+23] << 8) + (data[i+24]<<16) + (data[i+25]<<24);
-               // if the last frame on a page is continued to the next, then
-               // we can't recover the sample_loc immediately
-               if (data[i+27+data[i+26]-1] == 255)
-                  f->scan[n].sample_loc = ~0;
-               else
-                  f->scan[n].sample_loc = data[i+6] + (data[i+7] << 8) + (data[i+ 8]<<16) + (data[i+ 9]<<24);
-               f->scan[n].bytes_done = i+j;
-               if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT)
-                  break;
-               // keep going if we still have room for more
-            }
-         }
-      }
-   }
-
-   for (i=0; i < f->page_crc_tests;) {
-      stbv_uint32 crc;
-      int j;
-      int n = f->scan[i].bytes_done;
-      int m = f->scan[i].bytes_left;
-      if (m > data_len - n) m = data_len - n;
-      // m is the bytes to scan in the current chunk
-      crc = f->scan[i].crc_so_far;
-      for (j=0; j < m; ++j)
-         crc = stbv_crc32_update(crc, data[n+j]);
-      f->scan[i].bytes_left -= m;
-      f->scan[i].crc_so_far = crc;
-      if (f->scan[i].bytes_left == 0) {
-         // does it match?
-         if (f->scan[i].crc_so_far == f->scan[i].goal_crc) {
-            // Houston, we have page
-            data_len = n+m; // consumption amount is wherever that scan ended
-            f->page_crc_tests = -1; // drop out of page scan mode
-            f->previous_length = 0; // decode-but-don't-output one frame
-            f->next_seg = -1;       // start a new page
-            f->current_loc = f->scan[i].sample_loc; // set the current sample location
-                                    // to the amount we'd have decoded had we decoded this page
-            f->current_loc_valid = f->current_loc != ~0U;
-            return data_len;
-         }
-         // delete entry
-         f->scan[i] = f->scan[--f->page_crc_tests];
-      } else {
-         ++i;
-      }
-   }
-
-   return data_len;
-}
-
-// return value: number of bytes we used
-STBVDEF int stb_vorbis_decode_frame_pushdata(
-         stb_vorbis *f,                   // the file we're decoding
-         const stbv_uint8 *data, int data_len, // the memory available for decoding
-         int *channels,                   // place to write number of float * buffers
-         float ***output,                 // place to write float ** array of float * buffers
-         int *samples                     // place to write number of output samples
-     )
-{
-   int i;
-   int len,right,left;
-
-   if (!STBV_IS_PUSH_MODE(f)) return stbv_error(f, VORBIS_invalid_api_mixing);
-
-   if (f->page_crc_tests >= 0) {
-      *samples = 0;
-      return stbv_vorbis_search_for_page_pushdata(f, (stbv_uint8 *) data, data_len);
-   }
-
-   f->stream     = (stbv_uint8 *) data;
-   f->stream_end = (stbv_uint8 *) data + data_len;
-   f->error      = VORBIS__no_error;
-
-   // check that we have the entire packet in memory
-   if (!stbv_is_whole_packet_present(f, FALSE)) {
-      *samples = 0;
-      return 0;
-   }
-
-   if (!stbv_vorbis_decode_packet(f, &len, &left, &right)) {
-      // save the actual error we encountered
-      enum STBVorbisError error = f->error;
-      if (error == VORBIS_bad_packet_type) {
-         // flush and resynch
-         f->error = VORBIS__no_error;
-         while (stbv_get8_packet(f) != STBV_EOP)
-            if (f->eof) break;
-         *samples = 0;
-         return (int) (f->stream - data);
-      }
-      if (error == VORBIS_continued_packet_flag_invalid) {
-         if (f->previous_length == 0) {
-            // we may be resynching, in which case it's ok to hit one
-            // of these; just discard the packet
-            f->error = VORBIS__no_error;
-            while (stbv_get8_packet(f) != STBV_EOP)
-               if (f->eof) break;
-            *samples = 0;
-            return (int) (f->stream - data);
-         }
-      }
-      // if we get an error while parsing, what to do?
-      // well, it DEFINITELY won't work to continue from where we are!
-      stb_vorbis_flush_pushdata(f);
-      // restore the error that actually made us bail
-      f->error = error;
-      *samples = 0;
-      return 1;
-   }
-
-   // success!
-   len = stbv_vorbis_finish_frame(f, len, left, right);
-   for (i=0; i < f->channels; ++i)
-      f->outputs[i] = f->channel_buffers[i] + left;
-
-   if (channels) *channels = f->channels;
-   *samples = len;
-   *output = f->outputs;
-   return (int) (f->stream - data);
-}
-
-STBVDEF stb_vorbis *stb_vorbis_open_pushdata(
-         const unsigned char *data, int data_len, // the memory available for decoding
-         int *data_used,              // only defined if result is not NULL
-         int *error, const stb_vorbis_alloc *alloc)
-{
-   stb_vorbis *f, p;
-   stbv_vorbis_init(&p, alloc);
-   p.stream     = (stbv_uint8 *) data;
-   p.stream_end = (stbv_uint8 *) data + data_len;
-   p.push_mode  = TRUE;
-   if (!stbv_start_decoder(&p)) {
-      if (p.eof)
-         *error = VORBIS_need_more_data;
-      else
-         *error = p.error;
-      return NULL;
-   }
-   f = stbv_vorbis_alloc(&p);
-   if (f) {
-      *f = p;
-      *data_used = (int) (f->stream - data);
-      *error = 0;
-      return f;
-   } else {
-      stbv_vorbis_deinit(&p);
-      return NULL;
-   }
-}
-#endif // STB_VORBIS_NO_PUSHDATA_API
-
-STBVDEF unsigned int stb_vorbis_get_file_offset(stb_vorbis *f)
-{
-   #ifndef STB_VORBIS_NO_PUSHDATA_API
-   if (f->push_mode) return 0;
-   #endif
-   if (STBV_USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start);
-   #ifndef STB_VORBIS_NO_STDIO
-   return (unsigned int) (ftell(f->f) - f->f_start);
-   #endif
-}
-
-#ifndef STB_VORBIS_NO_PULLDATA_API
-//
-// DATA-PULLING API
-//
-
-static stbv_uint32 stbv_vorbis_find_page(stb_vorbis *f, stbv_uint32 *end, stbv_uint32 *last)
-{
-   for(;;) {
-      int n;
-      if (f->eof) return 0;
-      n = stbv_get8(f);
-      if (n == 0x4f) { // page header candidate
-         unsigned int retry_loc = stb_vorbis_get_file_offset(f);
-         int i;
-         // check if we're off the end of a file_section stream
-         if (retry_loc - 25 > f->stream_len)
-            return 0;
-         // check the rest of the header
-         for (i=1; i < 4; ++i)
-            if (stbv_get8(f) != stbv_ogg_page_header[i])
-               break;
-         if (f->eof) return 0;
-         if (i == 4) {
-            stbv_uint8 header[27];
-            stbv_uint32 i, crc, goal, len;
-            for (i=0; i < 4; ++i)
-               header[i] = stbv_ogg_page_header[i];
-            for (; i < 27; ++i)
-               header[i] = stbv_get8(f);
-            if (f->eof) return 0;
-            if (header[4] != 0) goto invalid;
-            goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24);
-            for (i=22; i < 26; ++i)
-               header[i] = 0;
-            crc = 0;
-            for (i=0; i < 27; ++i)
-               crc = stbv_crc32_update(crc, header[i]);
-            len = 0;
-            for (i=0; i < header[26]; ++i) {
-               int s = stbv_get8(f);
-               crc = stbv_crc32_update(crc, s);
-               len += s;
-            }
-            if (len && f->eof) return 0;
-            for (i=0; i < len; ++i)
-               crc = stbv_crc32_update(crc, stbv_get8(f));
-            // finished parsing probable page
-            if (crc == goal) {
-               // we could now check that it's either got the last
-               // page flag set, OR it's followed by the capture
-               // pattern, but I guess TECHNICALLY you could have
-               // a file with garbage between each ogg page and recover
-               // from it automatically? So even though that paranoia
-               // might decrease the chance of an invalid decode by
-               // another 2^32, not worth it since it would hose those
-               // invalid-but-useful files?
-               if (end)
-                  *end = stb_vorbis_get_file_offset(f);
-               if (last) {
-                  if (header[5] & 0x04)
-                     *last = 1;
-                  else
-                     *last = 0;
-               }
-               stbv_set_file_offset(f, retry_loc-1);
-               return 1;
-            }
-         }
-        invalid:
-         // not a valid page, so rewind and look for next one
-         stbv_set_file_offset(f, retry_loc);
-      }
-   }
-}
-
-
-#define STBV_SAMPLE_unknown  0xffffffff
-
-// seeking is implemented with a binary search, which narrows down the range to
-// 64K, before using a linear search (because finding the synchronization
-// pattern can be expensive, and the chance we'd find the end page again is
-// relatively high for small ranges)
-//
-// two initial interpolation-style probes are used at the start of the search
-// to try to bound either side of the binary search sensibly, while still
-// working in O(log n) time if they fail.
-
-static int stbv_get_seek_page_info(stb_vorbis *f, StbvProbedPage *z)
-{
-   stbv_uint8 header[27], lacing[255];
-   int i,len;
-
-   // record where the page starts
-   z->page_start = stb_vorbis_get_file_offset(f);
-
-   // parse the header
-   stbv_getn(f, header, 27);
-   if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S')
-      return 0;
-   stbv_getn(f, lacing, header[26]);
-
-   // determine the length of the payload
-   len = 0;
-   for (i=0; i < header[26]; ++i)
-      len += lacing[i];
-
-   // this implies where the page ends
-   z->page_end = z->page_start + 27 + header[26] + len;
-
-   // read the last-decoded sample out of the data
-   z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24);
-
-   // restore file state to where we were
-   stbv_set_file_offset(f, z->page_start);
-   return 1;
-}
-
-// rarely used function to seek back to the preceeding page while finding the
-// start of a packet
-static int stbv_go_to_page_before(stb_vorbis *f, unsigned int limit_offset)
-{
-   unsigned int previous_safe, end;
-
-   // now we want to seek back 64K from the limit
-   if (limit_offset >= 65536 && limit_offset-65536 >= f->first_audio_page_offset)
-      previous_safe = limit_offset - 65536;
-   else
-      previous_safe = f->first_audio_page_offset;
-
-   stbv_set_file_offset(f, previous_safe);
-
-   while (stbv_vorbis_find_page(f, &end, NULL)) {
-      if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset)
-         return 1;
-      stbv_set_file_offset(f, end);
-   }
-
-   return 0;
-}
-
-// implements the search logic for finding a page and starting decoding. if
-// the function succeeds, current_loc_valid will be true and current_loc will
-// be less than or equal to the provided sample number (the closer the
-// better).
-static int stbv_seek_to_sample_coarse(stb_vorbis *f, stbv_uint32 sample_number)
-{
-   StbvProbedPage left, right, mid;
-   int i, start_seg_with_known_loc, end_pos, page_start;
-   stbv_uint32 delta, stream_length, padding;
-   double offset, bytes_per_sample;
-   int probe = 0;
-
-   // find the last page and validate the target sample
-   stream_length = stb_vorbis_stream_length_in_samples(f);
-   if (stream_length == 0)            return stbv_error(f, VORBIS_seek_without_length);
-   if (sample_number > stream_length) return stbv_error(f, VORBIS_seek_invalid);
-
-   // this is the maximum difference between the window-center (which is the
-   // actual granule position value), and the right-start (which the spec
-   // indicates should be the granule position (give or take one)).
-   padding = ((f->blocksize_1 - f->blocksize_0) >> 2);
-   if (sample_number < padding)
-      sample_number = 0;
-   else
-      sample_number -= padding;
-
-   left = f->p_first;
-   while (left.last_decoded_sample == ~0U) {
-      // (untested) the first page does not have a 'last_decoded_sample'
-      stbv_set_file_offset(f, left.page_end);
-      if (!stbv_get_seek_page_info(f, &left)) goto error;
-   }
-
-   right = f->p_last;
-   assert(right.last_decoded_sample != ~0U);
-
-   // starting from the start is handled differently
-   if (sample_number <= left.last_decoded_sample) {
-      if (stb_vorbis_seek_start(f))
-         return 1;
-      return 0;
-   }
-
-   while (left.page_end != right.page_start) {
-      assert(left.page_end < right.page_start);
-      // search range in bytes
-      delta = right.page_start - left.page_end;
-      if (delta <= 65536) {
-         // there's only 64K left to search - handle it linearly
-         stbv_set_file_offset(f, left.page_end);
-      } else {
-         if (probe < 2) {
-            if (probe == 0) {
-               // first probe (interpolate)
-               double data_bytes = right.page_end - left.page_start;
-               bytes_per_sample = data_bytes / right.last_decoded_sample;
-               offset = left.page_start + bytes_per_sample * (sample_number - left.last_decoded_sample);
-            } else {
-               // second probe (try to bound the other side)
-               double error = ((double) sample_number - mid.last_decoded_sample) * bytes_per_sample;
-               if (error >= 0 && error <  8000) error =  8000;
-               if (error <  0 && error > -8000) error = -8000;
-               offset += error * 2;
-            }
-
-            // ensure the offset is valid
-            if (offset < left.page_end)
-               offset = left.page_end;
-            if (offset > right.page_start - 65536)
-               offset = right.page_start - 65536;
-
-            stbv_set_file_offset(f, (unsigned int) offset);
-         } else {
-            // binary search for large ranges (offset by 32K to ensure
-            // we don't hit the right page)
-            stbv_set_file_offset(f, left.page_end + (delta / 2) - 32768);
-         }
-
-         if (!stbv_vorbis_find_page(f, NULL, NULL)) goto error;
-      }
-
-      for (;;) {
-         if (!stbv_get_seek_page_info(f, &mid)) goto error;
-         if (mid.last_decoded_sample != ~0U) break;
-         // (untested) no frames end on this page
-         stbv_set_file_offset(f, mid.page_end);
-         assert(mid.page_start < right.page_start);
-      }
-
-      // if we've just found the last page again then we're in a tricky file,
-      // and we're close enough.
-      if (mid.page_start == right.page_start)
-         break;
-
-      if (sample_number < mid.last_decoded_sample)
-         right = mid;
-      else
-         left = mid;
-
-      ++probe;
-   }
-
-   // seek back to start of the last packet
-   page_start = left.page_start;
-   stbv_set_file_offset(f, page_start);
-   if (!stbv_start_page(f)) return stbv_error(f, VORBIS_seek_failed);
-   end_pos = f->end_seg_with_known_loc;
-   assert(end_pos >= 0);
-
-   for (;;) {
-      for (i = end_pos; i > 0; --i)
-         if (f->segments[i-1] != 255)
-            break;
-
-      start_seg_with_known_loc = i;
-
-      if (start_seg_with_known_loc > 0 || !(f->page_flag & STBV_PAGEFLAG_continued_packet))
-         break;
-
-      // (untested) the final packet begins on an earlier page
-      if (!stbv_go_to_page_before(f, page_start))
-         goto error;
-
-      page_start = stb_vorbis_get_file_offset(f);
-      if (!stbv_start_page(f)) goto error;
-      end_pos = f->segment_count - 1;
-   }
-
-   // prepare to start decoding
-   f->current_loc_valid = FALSE;
-   f->last_seg = FALSE;
-   f->valid_bits = 0;
-   f->packet_bytes = 0;
-   f->bytes_in_seg = 0;
-   f->previous_length = 0;
-   f->next_seg = start_seg_with_known_loc;
-
-   for (i = 0; i < start_seg_with_known_loc; i++)
-      stbv_skip(f, f->segments[i]);
-
-   // start decoding (optimizable - this frame is generally discarded)
-   if (!stbv_vorbis_pump_first_frame(f))
-      return 0;
-   if (f->current_loc > sample_number)
-      return stbv_error(f, VORBIS_seek_failed);
-   return 1;
-
-error:
-   // try to restore the file to a valid state
-   stb_vorbis_seek_start(f);
-   return stbv_error(f, VORBIS_seek_failed);
-}
-
-// the same as stbv_vorbis_decode_initial, but without advancing
-static int stbv_peek_decode_initial(stbv_vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode)
-{
-   int bits_read, bytes_read;
-
-   if (!stbv_vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode))
-      return 0;
-
-   // either 1 or 2 bytes were read, figure out which so we can rewind
-   bits_read = 1 + stbv_ilog(f->mode_count-1);
-   if (f->mode_config[*mode].blockflag)
-      bits_read += 2;
-   bytes_read = (bits_read + 7) / 8;
-
-   f->bytes_in_seg += bytes_read;
-   f->packet_bytes -= bytes_read;
-   stbv_skip(f, -bytes_read);
-   if (f->next_seg == -1)
-      f->next_seg = f->segment_count - 1;
-   else
-      f->next_seg--;
-   f->valid_bits = 0;
-
-   return 1;
-}
-
-STBVDEF int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number)
-{
-   stbv_uint32 max_frame_samples;
-
-   if (STBV_IS_PUSH_MODE(f)) return stbv_error(f, VORBIS_invalid_api_mixing);
-
-   // fast page-level search
-   if (!stbv_seek_to_sample_coarse(f, sample_number))
-      return 0;
-
-   assert(f->current_loc_valid);
-   assert(f->current_loc <= sample_number);
-
-   // linear search for the relevant packet
-   max_frame_samples = (f->blocksize_1*3 - f->blocksize_0) >> 2;
-   while (f->current_loc < sample_number) {
-      int left_start, left_end, right_start, right_end, mode, frame_samples;
-      if (!stbv_peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode))
-         return stbv_error(f, VORBIS_seek_failed);
-      // calculate the number of samples returned by the next frame
-      frame_samples = right_start - left_start;
-      if (f->current_loc + frame_samples > sample_number) {
-         return 1; // the next frame will contain the sample
-      } else if (f->current_loc + frame_samples + max_frame_samples > sample_number) {
-         // there's a chance the frame after this could contain the sample
-         stbv_vorbis_pump_first_frame(f);
-      } else {
-         // this frame is too early to be relevant
-         f->current_loc += frame_samples;
-         f->previous_length = 0;
-         stbv_maybe_start_packet(f);
-         stbv_flush_packet(f);
-      }
-   }
-   // the next frame will start with the sample
-   assert(f->current_loc == sample_number);
-   return 1;
-}
-
-STBVDEF int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number)
-{
-   if (!stb_vorbis_seek_frame(f, sample_number))
-      return 0;
-
-   if (sample_number != f->current_loc) {
-      int n;
-      stbv_uint32 frame_start = f->current_loc;
-      stb_vorbis_get_frame_float(f, &n, NULL);
-      assert(sample_number > frame_start);
-      assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end);
-      f->channel_buffer_start += (sample_number - frame_start);
-   }
-
-   return 1;
-}
-
-STBVDEF int stb_vorbis_seek_start(stb_vorbis *f)
-{
-   if (STBV_IS_PUSH_MODE(f)) { return stbv_error(f, VORBIS_invalid_api_mixing); }
-   stbv_set_file_offset(f, f->first_audio_page_offset);
-   f->previous_length = 0;
-   f->first_decode = TRUE;
-   f->next_seg = -1;
-   return stbv_vorbis_pump_first_frame(f);
-}
-
-STBVDEF unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f)
-{
-   unsigned int restore_offset, previous_safe;
-   unsigned int end, last_page_loc;
-
-   if (STBV_IS_PUSH_MODE(f)) return stbv_error(f, VORBIS_invalid_api_mixing);
-   if (!f->total_samples) {
-      unsigned int last;
-      stbv_uint32 lo,hi;
-      char header[6];
-
-      // first, store the current decode position so we can restore it
-      restore_offset = stb_vorbis_get_file_offset(f);
-
-      // now we want to seek back 64K from the end (the last page must
-      // be at most a little less than 64K, but let's allow a little slop)
-      if (f->stream_len >= 65536 && f->stream_len-65536 >= f->first_audio_page_offset)
-         previous_safe = f->stream_len - 65536;
-      else
-         previous_safe = f->first_audio_page_offset;
-
-      stbv_set_file_offset(f, previous_safe);
-      // previous_safe is now our candidate 'earliest known place that seeking
-      // to will lead to the final page'
-
-      if (!stbv_vorbis_find_page(f, &end, &last)) {
-         // if we can't find a page, we're hosed!
-         f->error = VORBIS_cant_find_last_page;
-         f->total_samples = 0xffffffff;
-         goto done;
-      }
-
-      // check if there are more pages
-      last_page_loc = stb_vorbis_get_file_offset(f);
-
-      // stop when the last_page flag is set, not when we reach eof;
-      // this allows us to stop short of a 'file_section' end without
-      // explicitly checking the length of the section
-      while (!last) {
-         stbv_set_file_offset(f, end);
-         if (!stbv_vorbis_find_page(f, &end, &last)) {
-            // the last page we found didn't have the 'last page' flag
-            // set. whoops!
-            break;
-         }
-         previous_safe = last_page_loc+1;
-         last_page_loc = stb_vorbis_get_file_offset(f);
-      }
-
-      stbv_set_file_offset(f, last_page_loc);
-
-      // parse the header
-      stbv_getn(f, (unsigned char *)header, 6);
-      // extract the absolute granule position
-      lo = stbv_get32(f);
-      hi = stbv_get32(f);
-      if (lo == 0xffffffff && hi == 0xffffffff) {
-         f->error = VORBIS_cant_find_last_page;
-         f->total_samples = STBV_SAMPLE_unknown;
-         goto done;
-      }
-      if (hi)
-         lo = 0xfffffffe; // saturate
-      f->total_samples = lo;
-
-      f->p_last.page_start = last_page_loc;
-      f->p_last.page_end   = end;
-      f->p_last.last_decoded_sample = lo;
-
-     done:
-      stbv_set_file_offset(f, restore_offset);
-   }
-   return f->total_samples == STBV_SAMPLE_unknown ? 0 : f->total_samples;
-}
-
-STBVDEF float stb_vorbis_stream_length_in_seconds(stb_vorbis *f)
-{
-   return stb_vorbis_stream_length_in_samples(f) / (float) f->sample_rate;
-}
-
-
-
-STBVDEF int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output)
-{
-   int len, right,left,i;
-   if (STBV_IS_PUSH_MODE(f)) return stbv_error(f, VORBIS_invalid_api_mixing);
-
-   if (!stbv_vorbis_decode_packet(f, &len, &left, &right)) {
-      f->channel_buffer_start = f->channel_buffer_end = 0;
-      return 0;
-   }
-
-   len = stbv_vorbis_finish_frame(f, len, left, right);
-   for (i=0; i < f->channels; ++i)
-      f->outputs[i] = f->channel_buffers[i] + left;
-
-   f->channel_buffer_start = left;
-   f->channel_buffer_end   = left+len;
-
-   if (channels) *channels = f->channels;
-   if (output)   *output = f->outputs;
-   return len;
-}
-
-#ifndef STB_VORBIS_NO_STDIO
-
-STBVDEF stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length)
-{
-   stb_vorbis *f, p;
-   stbv_vorbis_init(&p, alloc);
-   p.f = file;
-   p.f_start = (stbv_uint32) ftell(file);
-   p.stream_len   = length;
-   p.close_on_free = close_on_free;
-   if (stbv_start_decoder(&p)) {
-      f = stbv_vorbis_alloc(&p);
-      if (f) {
-         *f = p;
-         stbv_vorbis_pump_first_frame(f);
-         return f;
-      }
-   }
-   if (error) *error = p.error;
-   stbv_vorbis_deinit(&p);
-   return NULL;
-}
-
-STBVDEF stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc)
-{
-   unsigned int len, start;
-   start = (unsigned int) ftell(file);
-   fseek(file, 0, SEEK_END);
-   len = (unsigned int) (ftell(file) - start);
-   fseek(file, start, SEEK_SET);
-   return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len);
-}
-
-STBVDEF stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc)
-{
-   FILE *f = fopen(filename, "rb");
-   if (f) 
-      return stb_vorbis_open_file(f, TRUE, error, alloc);
-   if (error) *error = VORBIS_file_open_failure;
-   return NULL;
-}
-#endif // STB_VORBIS_NO_STDIO
-
-STBVDEF stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc)
-{
-   stb_vorbis *f, p;
-   if (data == NULL) return NULL;
-   stbv_vorbis_init(&p, alloc);
-   p.stream = (stbv_uint8 *) data;
-   p.stream_end = (stbv_uint8 *) data + len;
-   p.stream_start = (stbv_uint8 *) p.stream;
-   p.stream_len = len;
-   p.push_mode = FALSE;
-   if (stbv_start_decoder(&p)) {
-      f = stbv_vorbis_alloc(&p);
-      if (f) {
-         *f = p;
-         stbv_vorbis_pump_first_frame(f);
-         if (error) *error = VORBIS__no_error;
-         return f;
-      }
-   }
-   if (error) *error = p.error;
-   stbv_vorbis_deinit(&p);
-   return NULL;
-}
-
-#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
-#define STBV_PLAYBACK_MONO 1
-#define STBV_PLAYBACK_LEFT 2
-#define STBV_PLAYBACK_RIGHT 4
-
-#define STBV_L  (STBV_PLAYBACK_LEFT  | STBV_PLAYBACK_MONO)
-#define STBV_C  (STBV_PLAYBACK_LEFT  | STBV_PLAYBACK_RIGHT | STBV_PLAYBACK_MONO)
-#define STBV_R  (STBV_PLAYBACK_RIGHT | STBV_PLAYBACK_MONO)
-
-static stbv_int8 stbv_channel_position[7][6] =
-{
-   { 0 },
-   { STBV_C },
-   { STBV_L, STBV_R },
-   { STBV_L, STBV_C, STBV_R },
-   { STBV_L, STBV_R, STBV_L, STBV_R },
-   { STBV_L, STBV_C, STBV_R, STBV_L, STBV_R },
-   { STBV_L, STBV_C, STBV_R, STBV_L, STBV_R, STBV_C },
-};
-
-
-#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT
-   typedef union {
-      float f;
-      int i;
-   } stbv_float_conv;
-   typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4];
-   #define STBV_FASTDEF(x) stbv_float_conv x
-   // add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round
-   #define STBV_MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT))
-   #define STBV_ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22))
-   #define STBV_FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + STBV_MAGIC(s), temp.i - STBV_ADDEND(s))
-   #define stbv_check_endianness()  
-#else
-   #define STBV_FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s))))
-   #define stbv_check_endianness()
-   #define STBV_FASTDEF(x)
-#endif
-
-static void stbv_copy_samples(short *dest, float *src, int len)
-{
-   int i;
-   stbv_check_endianness();
-   for (i=0; i < len; ++i) {
-      STBV_FASTDEF(temp);
-      int v = STBV_FAST_SCALED_FLOAT_TO_INT(temp, src[i],15);
-      if ((unsigned int) (v + 32768) > 65535)
-         v = v < 0 ? -32768 : 32767;
-      dest[i] = v;
-   }
-}
-
-static void stbv_compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len)
-{
-   #define BUFFER_SIZE  32
-   float buffer[BUFFER_SIZE];
-   int i,j,o,n = BUFFER_SIZE;
-   stbv_check_endianness();
-   for (o = 0; o < len; o += BUFFER_SIZE) {
-      memset(buffer, 0, sizeof(buffer));
-      if (o + n > len) n = len - o;
-      for (j=0; j < num_c; ++j) {
-         if (stbv_channel_position[num_c][j] & mask) {
-            for (i=0; i < n; ++i)
-               buffer[i] += data[j][d_offset+o+i];
-         }
-      }
-      for (i=0; i < n; ++i) {
-         STBV_FASTDEF(temp);
-         int v = STBV_FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15);
-         if ((unsigned int) (v + 32768) > 65535)
-            v = v < 0 ? -32768 : 32767;
-         output[o+i] = v;
-      }
-   }
-}
-
-static void stbv_compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len)
-{
-   #define BUFFER_SIZE  32
-   float buffer[BUFFER_SIZE];
-   int i,j,o,n = BUFFER_SIZE >> 1;
-   // o is the offset in the source data
-   stbv_check_endianness();
-   for (o = 0; o < len; o += BUFFER_SIZE >> 1) {
-      // o2 is the offset in the output data
-      int o2 = o << 1;
-      memset(buffer, 0, sizeof(buffer));
-      if (o + n > len) n = len - o;
-      for (j=0; j < num_c; ++j) {
-         int m = stbv_channel_position[num_c][j] & (STBV_PLAYBACK_LEFT | STBV_PLAYBACK_RIGHT);
-         if (m == (STBV_PLAYBACK_LEFT | STBV_PLAYBACK_RIGHT)) {
-            for (i=0; i < n; ++i) {
-               buffer[i*2+0] += data[j][d_offset+o+i];
-               buffer[i*2+1] += data[j][d_offset+o+i];
-            }
-         } else if (m == STBV_PLAYBACK_LEFT) {
-            for (i=0; i < n; ++i) {
-               buffer[i*2+0] += data[j][d_offset+o+i];
-            }
-         } else if (m == STBV_PLAYBACK_RIGHT) {
-            for (i=0; i < n; ++i) {
-               buffer[i*2+1] += data[j][d_offset+o+i];
-            }
-         }
-      }
-      for (i=0; i < (n<<1); ++i) {
-         STBV_FASTDEF(temp);
-         int v = STBV_FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15);
-         if ((unsigned int) (v + 32768) > 65535)
-            v = v < 0 ? -32768 : 32767;
-         output[o2+i] = v;
-      }
-   }
-}
-
-static void stbv_convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples)
-{
-   int i;
-   if (buf_c != data_c && buf_c <= 2 && data_c <= 6) {
-      static int channel_selector[3][2] = { {0}, {STBV_PLAYBACK_MONO}, {STBV_PLAYBACK_LEFT, STBV_PLAYBACK_RIGHT} };
-      for (i=0; i < buf_c; ++i)
-         stbv_compute_samples(channel_selector[buf_c][i], buffer[i]+b_offset, data_c, data, d_offset, samples);
-   } else {
-      int limit = buf_c < data_c ? buf_c : data_c;
-      for (i=0; i < limit; ++i)
-         stbv_copy_samples(buffer[i]+b_offset, data[i]+d_offset, samples);
-      for (   ; i < buf_c; ++i)
-         memset(buffer[i]+b_offset, 0, sizeof(short) * samples);
-   }
-}
-
-STBVDEF int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples)
-{
-   float **output;
-   int len = stb_vorbis_get_frame_float(f, NULL, &output);
-   if (len > num_samples) len = num_samples;
-   if (len)
-      stbv_convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len);
-   return len;
-}
-
-static void stbv_convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len)
-{
-   int i;
-   stbv_check_endianness();
-   if (buf_c != data_c && buf_c <= 2 && data_c <= 6) {
-      assert(buf_c == 2);
-      for (i=0; i < buf_c; ++i)
-         stbv_compute_stereo_samples(buffer, data_c, data, d_offset, len);
-   } else {
-      int limit = buf_c < data_c ? buf_c : data_c;
-      int j;
-      for (j=0; j < len; ++j) {
-         for (i=0; i < limit; ++i) {
-            STBV_FASTDEF(temp);
-            float f = data[i][d_offset+j];
-            int v = STBV_FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15);
-            if ((unsigned int) (v + 32768) > 65535)
-               v = v < 0 ? -32768 : 32767;
-            *buffer++ = v;
-         }
-         for (   ; i < buf_c; ++i)
-            *buffer++ = 0;
-      }
-   }
-}
-
-STBVDEF int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts)
-{
-   float **output;
-   int len;
-   if (num_c == 1) return stb_vorbis_get_frame_short(f,num_c,&buffer, num_shorts);
-   len = stb_vorbis_get_frame_float(f, NULL, &output);
-   if (len) {
-      if (len*num_c > num_shorts) len = num_shorts / num_c;
-      stbv_convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len);
-   }
-   return len;
-}
-
-STBVDEF int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts)
-{
-   float **outputs;
-   int len = num_shorts / channels;
-   int n=0;
-   int z = f->channels;
-   if (z > channels) z = channels;
-   while (n < len) {
-      int k = f->channel_buffer_end - f->channel_buffer_start;
-      if (n+k >= len) k = len - n;
-      if (k)
-         stbv_convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, k);
-      buffer += k*channels;
-      n += k;
-      f->channel_buffer_start += k;
-      if (n == len) break;
-      if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break;
-   }
-   return n;
-}
-
-STBVDEF int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len)
-{
-   float **outputs;
-   int n=0;
-   int z = f->channels;
-   if (z > channels) z = channels;
-   while (n < len) {
-      int k = f->channel_buffer_end - f->channel_buffer_start;
-      if (n+k >= len) k = len - n;
-      if (k)
-         stbv_convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k);
-      n += k;
-      f->channel_buffer_start += k;
-      if (n == len) break;
-      if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break;
-   }
-   return n;
-}
-
-#ifndef STB_VORBIS_NO_STDIO
-STBVDEF int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output)
-{
-   int data_len, offset, total, limit, error;
-   short *data;
-   stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL);
-   if (v == NULL) return -1;
-   limit = v->channels * 4096;
-   *channels = v->channels;
-   if (sample_rate)
-      *sample_rate = v->sample_rate;
-   offset = data_len = 0;
-   total = limit;
-   data = (short *) malloc(total * sizeof(*data));
-   if (data == NULL) {
-      stb_vorbis_close(v);
-      return -2;
-   }
-   for (;;) {
-      int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset);
-      if (n == 0) break;
-      data_len += n;
-      offset += n * v->channels;
-      if (offset + limit > total) {
-         short *data2;
-         total *= 2;
-         data2 = (short *) realloc(data, total * sizeof(*data));
-         if (data2 == NULL) {
-            free(data);
-            stb_vorbis_close(v);
-            return -2;
-         }
-         data = data2;
-      }
-   }
-   *output = data;
-   stb_vorbis_close(v);
-   return data_len;
-}
-#endif // NO_STDIO
-
-STBVDEF int stb_vorbis_decode_memory(const stbv_uint8 *mem, int len, int *channels, int *sample_rate, short **output)
-{
-   int data_len, offset, total, limit, error;
-   short *data;
-   stb_vorbis *v = stb_vorbis_open_memory(mem, len, &error, NULL);
-   if (v == NULL) return -1;
-   limit = v->channels * 4096;
-   *channels = v->channels;
-   if (sample_rate)
-      *sample_rate = v->sample_rate;
-   offset = data_len = 0;
-   total = limit;
-   data = (short *) malloc(total * sizeof(*data));
-   if (data == NULL) {
-      stb_vorbis_close(v);
-      return -2;
-   }
-   for (;;) {
-      int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset);
-      if (n == 0) break;
-      data_len += n;
-      offset += n * v->channels;
-      if (offset + limit > total) {
-         short *data2;
-         total *= 2;
-         data2 = (short *) realloc(data, total * sizeof(*data));
-         if (data2 == NULL) {
-            free(data);
-            stb_vorbis_close(v);
-            return -2;
-         }
-         data = data2;
-      }
-   }
-   *output = data;
-   stb_vorbis_close(v);
-   return data_len;
-}
-#endif // STB_VORBIS_NO_INTEGER_CONVERSION
-
-STBVDEF int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats)
-{
-   float **outputs;
-   int len = num_floats / channels;
-   int n=0;
-   int z = f->channels;
-   if (z > channels) z = channels;
-   while (n < len) {
-      int i,j;
-      int k = f->channel_buffer_end - f->channel_buffer_start;
-      if (n+k >= len) k = len - n;
-      for (j=0; j < k; ++j) {
-         for (i=0; i < z; ++i)
-            *buffer++ = f->channel_buffers[i][f->channel_buffer_start+j];
-         for (   ; i < channels; ++i)
-            *buffer++ = 0;
-      }
-      n += k;
-      f->channel_buffer_start += k;
-      if (n == len)
-         break;
-      if (!stb_vorbis_get_frame_float(f, NULL, &outputs))
-         break;
-   }
-   return n;
-}
-
-STBVDEF int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples)
-{
-   float **outputs;
-   int n=0;
-   int z = f->channels;
-   if (z > channels) z = channels;
-   while (n < num_samples) {
-      int i;
-      int k = f->channel_buffer_end - f->channel_buffer_start;
-      if (n+k >= num_samples) k = num_samples - n;
-      if (k) {
-         for (i=0; i < z; ++i)
-            memcpy(buffer[i]+n, f->channel_buffers[i]+f->channel_buffer_start, sizeof(float)*k);
-         for (   ; i < channels; ++i)
-            memset(buffer[i]+n, 0, sizeof(float) * k);
-      }
-      n += k;
-      f->channel_buffer_start += k;
-      if (n == num_samples)
-         break;
-      if (!stb_vorbis_get_frame_float(f, NULL, &outputs))
-         break;
-   }
-   return n;
-}
-#endif // STB_VORBIS_NO_PULLDATA_API
-
-/* Version history
-    1.12    - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
-    1.11    - 2017-07-23 - fix MinGW compilation 
-    1.10    - 2017-03-03 - more robust seeking; fix negative stbv_ilog(); clear error in open_memory
-    1.09    - 2016-04-04 - back out 'avoid discarding last frame' fix from previous version
-    1.08    - 2016-04-02 - fixed multiple warnings; fix setup memory leaks;
-                           avoid discarding last frame of audio data
-    1.07    - 2015-01-16 - fixed some warnings, fix mingw, const-correct API
-                           some more crash fixes when out of memory or with corrupt files 
-    1.06    - 2015-08-31 - full, correct support for seeking API (Dougall Johnson)
-                           some crash fixes when out of memory or with corrupt files
-    1.05    - 2015-04-19 - don't define __forceinline if it's redundant
-    1.04    - 2014-08-27 - fix missing const-correct case in API
-    1.03    - 2014-08-07 - Warning fixes
-    1.02    - 2014-07-09 - Declare qsort compare function _cdecl on windows
-    1.01    - 2014-06-18 - fix stb_vorbis_get_samples_float
-    1.0     - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in multichannel
-                           (API change) report sample rate for decode-full-file funcs
-    0.99996 - bracket #include <malloc.h> for macintosh compilation by Laurent Gomila
-    0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem
-    0.99994 - change fast-float-to-int to work in single-precision FPU mode, remove endian-dependence
-    0.99993 - remove assert that fired on legal files with empty tables
-    0.99992 - rewind-to-start
-    0.99991 - bugfix to stb_vorbis_get_samples_short by Bernhard Wodo
-    0.9999 - (should have been 0.99990) fix no-CRT support, compiling as C++
-    0.9998 - add a full-decode function with a memory source
-    0.9997 - fix a bug in the read-from-FILE case in 0.9996 addition
-    0.9996 - query length of vorbis stream in samples/seconds
-    0.9995 - bugfix to another optimization that only happened in certain files
-    0.9994 - bugfix to one of the optimizations that caused significant (but inaudible?) errors
-    0.9993 - performance improvements; runs in 99% to 104% of time of reference implementation
-    0.9992 - performance improvement of IMDCT; now performs close to reference implementation
-    0.9991 - performance improvement of IMDCT
-    0.999 - (should have been 0.9990) performance improvement of IMDCT
-    0.998 - no-CRT support from Casey Muratori
-    0.997 - bugfixes for bugs found by Terje Mathisen
-    0.996 - bugfix: fast-huffman decode initialized incorrectly for sparse codebooks; fixing gives 10% speedup - found by Terje Mathisen
-    0.995 - bugfix: fix to 'effective' overrun detection - found by Terje Mathisen
-    0.994 - bugfix: garbage decode on final VQ symbol of a non-multiple - found by Terje Mathisen
-    0.993 - bugfix: pushdata API required 1 extra byte for empty page (failed to consume final page if empty) - found by Terje Mathisen
-    0.992 - fixes for MinGW warning
-    0.991 - turn fast-float-conversion on by default
-    0.990 - fix push-mode seek recovery if you seek into the headers
-    0.98b - fix to bad release of 0.98
-    0.98 - fix push-mode seek recovery; robustify float-to-int and support non-fast mode
-    0.97 - builds under c++ (typecasting, don't use 'class' keyword)
-    0.96 - somehow MY 0.95 was right, but the web one was wrong, so here's my 0.95 rereleased as 0.96, fixes a typo in the clamping code
-    0.95 - clamping code for 16-bit functions
-    0.94 - not publically released
-    0.93 - fixed all-zero-floor case (was decoding garbage)
-    0.92 - fixed a memory leak
-    0.91 - conditional compiles to omit parts of the API and the infrastructure to support them: STB_VORBIS_NO_PULLDATA_API, STB_VORBIS_NO_PUSHDATA_API, STB_VORBIS_NO_STDIO, STB_VORBIS_NO_INTEGER_CONVERSION
-    0.90 - first public release
-*/
-
-#endif // STB_VORBIS_IMPLEMENTATION
-
-
-/*
-------------------------------------------------------------------------------
-This software is available under 2 licenses -- choose whichever you prefer.
-------------------------------------------------------------------------------
-ALTERNATIVE A - MIT License
-Copyright (c) 2017 Sean Barrett
-Permission is hereby granted, free of charge, to any person obtaining a copy of 
-this software and associated documentation files (the "Software"), to deal in 
-the Software without restriction, including without limitation the rights to 
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
-of the Software, and to permit persons to whom the Software is furnished to do 
-so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all 
-copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
-SOFTWARE.
-------------------------------------------------------------------------------
-ALTERNATIVE B - Public Domain (www.unlicense.org)
-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.
-------------------------------------------------------------------------------
-*/
raylib/src/raudio.c view
@@ -21,10 +21,11 @@ *
 *   #define SUPPORT_FILEFORMAT_WAV
 *   #define SUPPORT_FILEFORMAT_OGG
+*   #define SUPPORT_FILEFORMAT_MP3
+*   #define SUPPORT_FILEFORMAT_QOA
+*   #define SUPPORT_FILEFORMAT_FLAC
 *   #define SUPPORT_FILEFORMAT_XM
 *   #define SUPPORT_FILEFORMAT_MOD
-*   #define SUPPORT_FILEFORMAT_FLAC
-*   #define SUPPORT_FILEFORMAT_MP3
 *       Selected desired fileformats to be supported for loading. Some of those formats are
 *       supported by default, to remove support, just comment unrequired #define in this module
 *
@@ -196,29 +197,6 @@     #endif
 #endif
 
-#if defined(SUPPORT_FILEFORMAT_OGG)
-    // TODO: Remap stb_vorbis malloc()/free() calls to RL_MALLOC/RL_FREE
-
-    #define STB_VORBIS_IMPLEMENTATION
-    #include "external/stb_vorbis.h"    // OGG loading functions
-#endif
-
-#if defined(SUPPORT_FILEFORMAT_XM)
-    #define JARXM_MALLOC RL_MALLOC
-    #define JARXM_FREE RL_FREE
-
-    #define JAR_XM_IMPLEMENTATION
-    #include "external/jar_xm.h"        // XM loading functions
-#endif
-
-#if defined(SUPPORT_FILEFORMAT_MOD)
-    #define JARMOD_MALLOC RL_MALLOC
-    #define JARMOD_FREE RL_FREE
-
-    #define JAR_MOD_IMPLEMENTATION
-    #include "external/jar_mod.h"       // MOD loading functions
-#endif
-
 #if defined(SUPPORT_FILEFORMAT_WAV)
     #define DRWAV_MALLOC RL_MALLOC
     #define DRWAV_REALLOC RL_REALLOC
@@ -228,6 +206,11 @@     #include "external/dr_wav.h"        // WAV loading functions
 #endif
 
+#if defined(SUPPORT_FILEFORMAT_OGG)
+    // TODO: Remap stb_vorbis malloc()/free() calls to RL_MALLOC/RL_FREE
+    #include "external/stb_vorbis.c"    // OGG loading functions
+#endif
+
 #if defined(SUPPORT_FILEFORMAT_MP3)
     #define DRMP3_MALLOC RL_MALLOC
     #define DRMP3_REALLOC RL_REALLOC
@@ -237,6 +220,14 @@     #include "external/dr_mp3.h"        // MP3 loading functions
 #endif
 
+#if defined(SUPPORT_FILEFORMAT_QOA)
+    #define QOA_MALLOC RL_MALLOC
+    #define QOA_FREE RL_FREE
+
+    #define QOA_IMPLEMENTATION
+    #include "external/qoa.h"           // QOA loading and saving functions
+#endif
+
 #if defined(SUPPORT_FILEFORMAT_FLAC)
     #define DRFLAC_MALLOC RL_MALLOC
     #define DRFLAC_REALLOC RL_REALLOC
@@ -247,6 +238,31 @@     #include "external/dr_flac.h"       // FLAC loading functions
 #endif
 
+#if defined(SUPPORT_FILEFORMAT_XM)
+    #define JARXM_MALLOC RL_MALLOC
+    #define JARXM_FREE RL_FREE
+
+    #if defined(_MSC_VER )              // jar_xm has warnings on windows, so disable them just for this file
+        #pragma warning( push )
+        #pragma warning( disable : 4244)
+    #endif
+
+    #define JAR_XM_IMPLEMENTATION
+    #include "external/jar_xm.h"        // XM loading functions
+
+    #if defined(_MSC_VER )
+        #pragma warning( pop )
+    #endif
+#endif
+
+#if defined(SUPPORT_FILEFORMAT_MOD)
+    #define JARMOD_MALLOC RL_MALLOC
+    #define JARMOD_FREE RL_FREE
+
+    #define JAR_MOD_IMPLEMENTATION
+    #include "external/jar_mod.h"       // MOD loading functions
+#endif
+
 //----------------------------------------------------------------------------------
 // Defines and Macros
 //----------------------------------------------------------------------------------
@@ -277,6 +293,7 @@     MUSIC_AUDIO_OGG,        // OGG audio context
     MUSIC_AUDIO_FLAC,       // FLAC audio context
     MUSIC_AUDIO_MP3,        // MP3 audio context
+    MUSIC_AUDIO_QOA,        // QOA audio context
     MUSIC_MODULE_XM,        // XM module audio context
     MUSIC_MODULE_MOD        // MOD module audio context
 } MusicContextType;
@@ -297,7 +314,7 @@ #endif
 
 // NOTE: Different logic is used when feeding data to the playback device
-// depending on whether or not data is streamed (Music vs Sound)
+// depending on whether data is streamed (Music vs Sound)
 typedef enum {
     AUDIO_BUFFER_USAGE_STATIC = 0,
     AUDIO_BUFFER_USAGE_STREAM
@@ -457,7 +474,7 @@         return;
     }
 
-    // Mixing happens on a seperate thread which means we need to synchronize. I'm using a mutex here to make things simple, but may
+    // Mixing happens on a separate thread which means we need to synchronize. I'm using a mutex here to make things simple, but may
     // want to look at something a bit smarter later on to keep everything real-time, if that's necessary.
     if (ma_mutex_init(&AUDIO.System.lock) != MA_SUCCESS)
     {
@@ -511,7 +528,7 @@         RL_FREE(AUDIO.System.pcmBuffer);
         AUDIO.System.pcmBuffer = NULL;
         AUDIO.System.pcmBufferSize = 0;
-        
+
         TRACELOG(LOG_INFO, "AUDIO: Device closed successfully");
     }
     else TRACELOG(LOG_WARNING, "AUDIO: Device could not be closed, not currently initialized");
@@ -787,19 +804,6 @@         else TRACELOG(LOG_WARNING, "WAVE: Failed to load OGG data");
     }
 #endif
-#if defined(SUPPORT_FILEFORMAT_FLAC)
-    else if (strcmp(fileType, ".flac") == 0)
-    {
-        unsigned long long int totalFrameCount = 0;
-
-        // NOTE: We are forcing conversion to 16bit sample size on reading
-        wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
-        wave.sampleSize = 16;
-
-        if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount;
-        else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data");
-    }
-#endif
 #if defined(SUPPORT_FILEFORMAT_MP3)
     else if (strcmp(fileType, ".mp3") == 0)
     {
@@ -820,6 +824,38 @@ 
     }
 #endif
+#if defined(SUPPORT_FILEFORMAT_QOA)
+    else if (strcmp(fileType, ".qoa") == 0)
+    {
+        qoa_desc qoa = { 0 };
+
+        // NOTE: Returned sample data is always 16 bit?
+        wave.data = qoa_decode(fileData, dataSize, &qoa);
+        wave.sampleSize = 16;
+
+        if (wave.data != NULL)
+        {
+            wave.channels = qoa.channels;
+            wave.sampleRate = qoa.samplerate;
+            wave.frameCount = qoa.samples;
+        }
+        else TRACELOG(LOG_WARNING, "WAVE: Failed to load QOA data");
+
+    }
+#endif
+#if defined(SUPPORT_FILEFORMAT_FLAC)
+    else if (strcmp(fileType, ".flac") == 0)
+    {
+        unsigned long long int totalFrameCount = 0;
+
+        // NOTE: We are forcing conversion to 16bit sample size on reading
+        wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
+        wave.sampleSize = 16;
+
+        if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount;
+        else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data");
+    }
+#endif
     else TRACELOG(LOG_WARNING, "WAVE: Data format not supported");
 
     TRACELOG(LOG_INFO, "WAVE: Data loaded successfully (%i Hz, %i bit, %i channels)", wave.sampleRate, wave.sampleSize, wave.channels);
@@ -827,6 +863,12 @@     return wave;
 }
 
+// Checks if wave data is ready
+bool IsWaveReady(Wave wave)
+{
+    return wave.data != NULL;
+}
+
 // Load sound from file
 // NOTE: The entire file is loaded to memory to be played (no-streaming)
 Sound LoadSound(const char *fileName)
@@ -883,6 +925,12 @@     return sound;
 }
 
+// Checks if a sound is ready
+bool IsSoundReady(Sound sound)
+{
+    return sound.stream.buffer != NULL;
+}
+
 // Unload wave data
 void UnloadWave(Wave wave)
 {
@@ -938,6 +986,18 @@         drwav_free(fileData, NULL);
     }
 #endif
+#if defined(SUPPORT_FILEFORMAT_QOA)
+    else if (IsFileExtension(fileName, ".qoa"))
+    {
+        qoa_desc qoa = { 0 };
+        qoa.channels = wave.channels;
+        qoa.samplerate = wave.sampleRate;
+        qoa.samples = wave.frameCount;
+
+        // TODO: Review wave.data format required for export
+        success = qoa_write(fileName, wave.data, &qoa);
+    }
+#endif
     else if (IsFileExtension(fileName, ".raw"))
     {
         // Export raw sample data (without header)
@@ -1029,7 +1089,7 @@     unsigned int oldAge = 0;
     int oldIndex = -1;
 
-    // find the first non playing pool entry
+    // find the first non-playing pool entry
     for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
     {
         if (AUDIO.MultiChannel.channels[i] > oldAge)
@@ -1045,7 +1105,7 @@         }
     }
 
-    // If no none playing pool members can be index choose the oldest
+    // If no none playing pool members can be indexed choose the oldest
     if (index == -1)
     {
         TRACELOG(LOG_WARNING, "SOUND: Buffer pool is already full, count: %i", AUDIO.MultiChannel.poolCounter);
@@ -1053,7 +1113,7 @@         if (oldIndex == -1)
         {
             // Shouldn't be able to get here... but just in case something odd happens!
-            TRACELOG(LOG_WARNING, "SOUND: Buffer pool could not determine oldest buffer not playing sound");
+            TRACELOG(LOG_WARNING, "SOUND: Buffer pool could not determine the oldest buffer not playing sound");
             return;
         }
 
@@ -1296,23 +1356,6 @@         }
     }
 #endif
-#if defined(SUPPORT_FILEFORMAT_FLAC)
-    else if (IsFileExtension(fileName, ".flac"))
-    {
-        music.ctxType = MUSIC_AUDIO_FLAC;
-        music.ctxData = drflac_open_file(fileName, NULL);
-
-        if (music.ctxData != NULL)
-        {
-            drflac *ctxFlac = (drflac *)music.ctxData;
-
-            music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
-            music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
-            music.looping = true;   // Looping enabled by default
-            musicLoaded = true;
-        }
-    }
-#endif
 #if defined(SUPPORT_FILEFORMAT_MP3)
     else if (IsFileExtension(fileName, ".mp3"))
     {
@@ -1331,6 +1374,46 @@         }
     }
 #endif
+#if defined(SUPPORT_FILEFORMAT_QOA)
+    else if (IsFileExtension(fileName, ".qoa"))
+    {
+        qoa_desc *ctxQoa = RL_CALLOC(1, sizeof(qoa_desc));
+
+        // TODO: QOA stream support: Init context from file
+        int result = 0;
+
+        music.ctxType = MUSIC_AUDIO_QOA;
+        music.ctxData = ctxQoa;
+
+        if (result > 0)
+        {
+            music.stream = LoadAudioStream(ctxQoa->samplerate, 16, ctxQoa->channels);
+
+            // TODO: Read next frame(s) from QOA stream
+            //music.frameCount = qoa_decode_frame(const unsigned char *bytes, unsigned int size, ctxQoa, short *sample_data, unsigned int *frame_len);
+
+            music.looping = true;   // Looping enabled by default
+            musicLoaded = true;
+        }
+    }
+#endif
+#if defined(SUPPORT_FILEFORMAT_FLAC)
+    else if (IsFileExtension(fileName, ".flac"))
+    {
+        music.ctxType = MUSIC_AUDIO_FLAC;
+        music.ctxData = drflac_open_file(fileName, NULL);
+
+        if (music.ctxData != NULL)
+        {
+            drflac *ctxFlac = (drflac *)music.ctxData;
+
+            music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
+            music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
+            music.looping = true;   // Looping enabled by default
+            musicLoaded = true;
+        }
+    }
+#endif
 #if defined(SUPPORT_FILEFORMAT_XM)
     else if (IsFileExtension(fileName, ".xm"))
     {
@@ -1388,12 +1471,15 @@     #if defined(SUPPORT_FILEFORMAT_OGG)
         else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
     #endif
-    #if defined(SUPPORT_FILEFORMAT_FLAC)
-        else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);
-    #endif
     #if defined(SUPPORT_FILEFORMAT_MP3)
         else if (music.ctxType == MUSIC_AUDIO_MP3) { drmp3_uninit((drmp3 *)music.ctxData); RL_FREE(music.ctxData); }
     #endif
+    #if defined(SUPPORT_FILEFORMAT_QOA)
+        else if (music.ctxType == MUSIC_AUDIO_QOA) { /*TODO: Release QOA context data*/ RL_FREE(music.ctxData); }
+    #endif
+    #if defined(SUPPORT_FILEFORMAT_FLAC)
+        else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);
+    #endif
     #if defined(SUPPORT_FILEFORMAT_XM)
         else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData);
     #endif
@@ -1447,18 +1533,23 @@         }
     }
 #endif
-#if defined(SUPPORT_FILEFORMAT_FLAC)
-    else if (strcmp(fileType, ".flac") == 0)
+#if defined(SUPPORT_FILEFORMAT_OGG)
+    else if (strcmp(fileType, ".ogg") == 0)
     {
-        music.ctxType = MUSIC_AUDIO_FLAC;
-        music.ctxData = drflac_open_memory((const void*)data, dataSize, NULL);
+        // Open ogg audio stream
+        music.ctxType = MUSIC_AUDIO_OGG;
+        //music.ctxData = stb_vorbis_open_filename(fileName, NULL, NULL);
+        music.ctxData = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL);
 
         if (music.ctxData != NULL)
         {
-            drflac *ctxFlac = (drflac *)music.ctxData;
+            stb_vorbis_info info = stb_vorbis_get_info((stb_vorbis *)music.ctxData);  // Get Ogg file info
 
-            music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
-            music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
+            // OGG bit rate defaults to 16 bit, it's enough for compressed format
+            music.stream = LoadAudioStream(info.sample_rate, 16, info.channels);
+
+            // WARNING: It seems this function returns length in frames, not samples, so we multiply by channels
+            music.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData);
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
@@ -1482,28 +1573,46 @@         }
     }
 #endif
-#if defined(SUPPORT_FILEFORMAT_OGG)
-    else if (strcmp(fileType, ".ogg") == 0)
+#if defined(SUPPORT_FILEFORMAT_QOA)
+    else if (strcmp(fileType, ".qoa") == 0)
     {
-        // Open ogg audio stream
-        music.ctxType = MUSIC_AUDIO_OGG;
-        //music.ctxData = stb_vorbis_open_filename(fileName, NULL, NULL);
-        music.ctxData = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL);
+        qoa_desc *ctxQoa = RL_CALLOC(1, sizeof(qoa_desc));
 
-        if (music.ctxData != NULL)
+        // TODO: Init QOA context data
+        int result = 0;
+
+        music.ctxType = MUSIC_AUDIO_QOA;
+        music.ctxData = ctxQoa;
+
+        if (result > 0)
         {
-            stb_vorbis_info info = stb_vorbis_get_info((stb_vorbis *)music.ctxData);  // Get Ogg file info
+            music.stream = LoadAudioStream(ctxQoa->samplerate, 16, ctxQoa->channels);
 
-            // OGG bit rate defaults to 16 bit, it's enough for compressed format
-            music.stream = LoadAudioStream(info.sample_rate, 16, info.channels);
+            // TODO: Read next frame(s) from QOA stream
+            //music.frameCount = qoa_decode_frame(const unsigned char *bytes, unsigned int size, ctxQoa, short *sample_data, unsigned int *frame_len);
 
-            // WARNING: It seems this function returns length in frames, not samples, so we multiply by channels
-            music.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData);
             music.looping = true;   // Looping enabled by default
             musicLoaded = true;
         }
     }
 #endif
+#if defined(SUPPORT_FILEFORMAT_FLAC)
+    else if (strcmp(fileType, ".flac") == 0)
+    {
+        music.ctxType = MUSIC_AUDIO_FLAC;
+        music.ctxData = drflac_open_memory((const void*)data, dataSize, NULL);
+
+        if (music.ctxData != NULL)
+        {
+            drflac *ctxFlac = (drflac *)music.ctxData;
+
+            music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
+            music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
+            music.looping = true;   // Looping enabled by default
+            musicLoaded = true;
+        }
+    }
+#endif
 #if defined(SUPPORT_FILEFORMAT_XM)
     else if (strcmp(fileType, ".xm") == 0)
     {
@@ -1573,15 +1682,18 @@     #if defined(SUPPORT_FILEFORMAT_WAV)
         else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData);
     #endif
-    #if defined(SUPPORT_FILEFORMAT_FLAC)
-        else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);
+    #if defined(SUPPORT_FILEFORMAT_OGG)
+        else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
     #endif
     #if defined(SUPPORT_FILEFORMAT_MP3)
         else if (music.ctxType == MUSIC_AUDIO_MP3) { drmp3_uninit((drmp3 *)music.ctxData); RL_FREE(music.ctxData); }
     #endif
-    #if defined(SUPPORT_FILEFORMAT_OGG)
-        else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
+    #if defined(SUPPORT_FILEFORMAT_QOA)
+        else if (music.ctxType == MUSIC_AUDIO_QOA) { /*TODO: Release QOA context*/ RL_FREE(music.ctxData); }
     #endif
+    #if defined(SUPPORT_FILEFORMAT_FLAC)
+        else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);
+    #endif
     #if defined(SUPPORT_FILEFORMAT_XM)
         else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData);
     #endif
@@ -1605,6 +1717,12 @@     return music;
 }
 
+// Checks if a music stream is ready
+bool IsMusicReady(Music music)
+{
+    return music.ctxData != NULL;
+}
+
 // Unload music stream
 void UnloadMusicStream(Music music)
 {
@@ -1619,12 +1737,15 @@ #if defined(SUPPORT_FILEFORMAT_OGG)
         else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
 #endif
-#if defined(SUPPORT_FILEFORMAT_FLAC)
-        else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);
-#endif
 #if defined(SUPPORT_FILEFORMAT_MP3)
         else if (music.ctxType == MUSIC_AUDIO_MP3) { drmp3_uninit((drmp3 *)music.ctxData); RL_FREE(music.ctxData); }
 #endif
+#if defined(SUPPORT_FILEFORMAT_QOA)
+        else if (music.ctxType == MUSIC_AUDIO_QOA) { /*TODO: Release QOA context*/ RL_FREE(music.ctxData); }
+#endif
+#if defined(SUPPORT_FILEFORMAT_FLAC)
+        else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_free((drflac *)music.ctxData, NULL);
+#endif
 #if defined(SUPPORT_FILEFORMAT_XM)
         else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData);
 #endif
@@ -1674,12 +1795,15 @@ #if defined(SUPPORT_FILEFORMAT_OGG)
         case MUSIC_AUDIO_OGG: stb_vorbis_seek_start((stb_vorbis *)music.ctxData); break;
 #endif
-#if defined(SUPPORT_FILEFORMAT_FLAC)
-        case MUSIC_AUDIO_FLAC: drflac__seek_to_first_frame((drflac *)music.ctxData); break;
-#endif
 #if defined(SUPPORT_FILEFORMAT_MP3)
         case MUSIC_AUDIO_MP3: drmp3_seek_to_start_of_stream((drmp3 *)music.ctxData); break;
 #endif
+#if defined(SUPPORT_FILEFORMAT_QOA)
+        case MUSIC_AUDIO_QOA: /*TODO: Restart QOA context to beginning*/ break;
+#endif
+#if defined(SUPPORT_FILEFORMAT_FLAC)
+        case MUSIC_AUDIO_FLAC: drflac__seek_to_first_frame((drflac *)music.ctxData); break;
+#endif
 #if defined(SUPPORT_FILEFORMAT_XM)
         case MUSIC_MODULE_XM: jar_xm_reset((jar_xm_context_t *)music.ctxData); break;
 #endif
@@ -1706,12 +1830,15 @@ #if defined(SUPPORT_FILEFORMAT_OGG)
         case MUSIC_AUDIO_OGG: stb_vorbis_seek_frame((stb_vorbis *)music.ctxData, positionInFrames); break;
 #endif
-#if defined(SUPPORT_FILEFORMAT_FLAC)
-        case MUSIC_AUDIO_FLAC: drflac_seek_to_pcm_frame((drflac *)music.ctxData, positionInFrames); break;
-#endif
 #if defined(SUPPORT_FILEFORMAT_MP3)
         case MUSIC_AUDIO_MP3: drmp3_seek_to_pcm_frame((drmp3 *)music.ctxData, positionInFrames); break;
 #endif
+#if defined(SUPPORT_FILEFORMAT_QOA)
+        case MUSIC_AUDIO_QOA: /*TODO: Seek to specific QOA frame*/ break;
+#endif
+#if defined(SUPPORT_FILEFORMAT_FLAC)
+        case MUSIC_AUDIO_FLAC: drflac_seek_to_pcm_frame((drflac *)music.ctxData, positionInFrames); break;
+#endif
         default: break;
     }
 
@@ -1728,6 +1855,7 @@     // On first call of this function we lazily pre-allocated a temp buffer to read audio files/memory data in
     int frameSize = music.stream.channels*music.stream.sampleSize/8;
     unsigned int pcmSize = subBufferSizeInFrames*frameSize;
+
     if (AUDIO.System.pcmBufferSize < pcmSize)
     {
         RL_FREE(AUDIO.System.pcmBuffer);
@@ -1756,7 +1884,7 @@                 {
                     while (true)
                     {
-                        int frameCountRed = drwav_read_pcm_frames_s16((drwav *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
+                        int frameCountRed = (int)drwav_read_pcm_frames_s16((drwav *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
                         frameCountRedTotal += frameCountRed;
                         frameCountStillNeeded -= frameCountRed;
                         if (frameCountStillNeeded == 0) break;
@@ -1767,7 +1895,7 @@                 {
                     while (true)
                     {
-                        int frameCountRed = drwav_read_pcm_frames_f32((drwav *)music.ctxData, frameCountStillNeeded, (float *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
+                        int frameCountRed = (int)drwav_read_pcm_frames_f32((drwav *)music.ctxData, frameCountStillNeeded, (float *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
                         frameCountRedTotal += frameCountRed;
                         frameCountStillNeeded -= frameCountRed;
                         if (frameCountStillNeeded == 0) break;
@@ -1789,29 +1917,35 @@                 }
             } break;
         #endif
-        #if defined(SUPPORT_FILEFORMAT_FLAC)
-            case MUSIC_AUDIO_FLAC:
+        #if defined(SUPPORT_FILEFORMAT_MP3)
+            case MUSIC_AUDIO_MP3:
             {
                 while (true)
                 {
-                    int frameCountRed = drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
+                    int frameCountRed = (int)drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, frameCountStillNeeded, (float *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
                     frameCountRedTotal += frameCountRed;
                     frameCountStillNeeded -= frameCountRed;
                     if (frameCountStillNeeded == 0) break;
-                    else drflac__seek_to_first_frame((drflac *)music.ctxData);
+                    else drmp3_seek_to_start_of_stream((drmp3 *)music.ctxData);
                 }
             } break;
         #endif
-        #if defined(SUPPORT_FILEFORMAT_MP3)
-            case MUSIC_AUDIO_MP3:
+        #if defined(SUPPORT_FILEFORMAT_QOA)
+            case MUSIC_AUDIO_QOA:
             {
+                // TODO: Read QOA required framecount to fill buffer to keep music playing
+            } break;
+        #endif
+        #if defined(SUPPORT_FILEFORMAT_FLAC)
+            case MUSIC_AUDIO_FLAC:
+            {
                 while (true)
                 {
-                    int frameCountRed = drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, frameCountStillNeeded, (float *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
+                    int frameCountRed = drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountRedTotal*frameSize));
                     frameCountRedTotal += frameCountRed;
                     frameCountStillNeeded -= frameCountRed;
                     if (frameCountStillNeeded == 0) break;
-                    else drmp3_seek_to_start_of_stream((drmp3 *)music.ctxData);
+                    else drflac__seek_to_first_frame((drflac *)music.ctxData);
                 }
             } break;
         #endif
@@ -1958,6 +2092,12 @@     return stream;
 }
 
+// Checks if an audio stream is ready
+RLAPI bool IsAudioStreamReady(AudioStream stream)
+{
+    return stream.buffer != NULL;
+}
+
 // Unload audio stream and free memory
 void UnloadAudioStream(AudioStream stream)
 {
@@ -1967,8 +2107,8 @@ }
 
 // Update audio stream buffers with data
-// NOTE 1: Only updates one buffer of the stream source: unqueue -> update -> queue
-// NOTE 2: To unqueue a buffer it needs to be processed: IsAudioStreamProcessed()
+// NOTE 1: Only updates one buffer of the stream source: dequeue -> update -> queue
+// NOTE 2: To dequeue a buffer it needs to be processed: IsAudioStreamProcessed()
 void UpdateAudioStream(AudioStream stream, const void *data, int frameCount)
 {
     if (stream.buffer != NULL)
@@ -2165,7 +2305,7 @@ 
     if (currentSubBufferIndex > 1) return 0;
 
-    // Another thread can update the processed state of buffers so
+    // Another thread can update the processed state of buffers, so
     // we just take a copy here to try and avoid potential synchronization problems
     bool isSubBufferProcessed[2] = { 0 };
     isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0];
@@ -2179,7 +2319,7 @@     {
         // We break from this loop differently depending on the buffer's usage
         //  - For static buffers, we simply fill as much data as we can
-        //  - For streaming buffers we only fill the halves of the buffer that are processed
+        //  - For streaming buffers we only fill half of the buffer that are processed
         //    Unprocessed halves must keep their audio data in-tact
         if (audioBuffer->usage == AUDIO_BUFFER_USAGE_STATIC)
         {
@@ -2236,7 +2376,7 @@ 
         // For static buffers we can fill the remaining frames with silence for safety, but we don't want
         // to report those frames as "read". The reason for this is that the caller uses the return value
-        // to know whether or not a non-looping sound has finished playback.
+        // to know whether a non-looping sound has finished playback.
         if (audioBuffer->usage != AUDIO_BUFFER_USAGE_STATIC) framesRead += totalFramesRemaining;
     }
 
raylib/src/raylib.h view
@@ -81,6 +81,9 @@ 
 #include <stdarg.h>     // Required for: va_list - Only used by TraceLogCallback
 
+#define RAYLIB_VERSION_MAJOR 4
+#define RAYLIB_VERSION_MINOR 5
+#define RAYLIB_VERSION_PATCH 0
 #define RAYLIB_VERSION  "4.5-dev"
 
 // Function specifiers in case library is build/used as a shared library (Windows)
@@ -213,7 +216,7 @@ // Quaternion, 4 components (Vector4 alias)
 typedef Vector4 Quaternion;
 
-// Matrix, 4x4 components, column major, OpenGL style, right handed
+// Matrix, 4x4 components, column major, OpenGL style, right-handed
 typedef struct Matrix {
     float m0, m4, m8, m12;  // Matrix first row (4 components)
     float m1, m5, m9, m13;  // Matrix second row (4 components)
@@ -410,8 +413,8 @@ // RayCollision, ray hit information
 typedef struct RayCollision {
     bool hit;               // Did the ray hit something?
-    float distance;         // Distance to nearest hit
-    Vector3 point;          // Point of nearest hit
+    float distance;         // Distance to the nearest hit
+    Vector3 point;          // Point of the nearest hit
     Vector3 normal;         // Surface normal of hit
 } RayCollision;
 
@@ -678,7 +681,7 @@     MOUSE_CURSOR_RESIZE_NS     = 6,     // Vertical resize/move arrow shape
     MOUSE_CURSOR_RESIZE_NWSE   = 7,     // Top-left to bottom-right diagonal resize/move arrow shape
     MOUSE_CURSOR_RESIZE_NESW   = 8,     // The top-right to bottom-left diagonal resize/move arrow shape
-    MOUSE_CURSOR_RESIZE_ALL    = 9,     // The omni-directional resize/move cursor shape
+    MOUSE_CURSOR_RESIZE_ALL    = 9,     // The omnidirectional resize/move cursor shape
     MOUSE_CURSOR_NOT_ALLOWED   = 10     // The operation-not-allowed shape
 } MouseCursor;
 
@@ -836,10 +839,10 @@ typedef enum {
     CUBEMAP_LAYOUT_AUTO_DETECT = 0,         // Automatically detect layout type
     CUBEMAP_LAYOUT_LINE_VERTICAL,           // Layout is defined by a vertical line with faces
-    CUBEMAP_LAYOUT_LINE_HORIZONTAL,         // Layout is defined by an horizontal line with faces
+    CUBEMAP_LAYOUT_LINE_HORIZONTAL,         // Layout is defined by a horizontal line with faces
     CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR,     // Layout is defined by a 3x4 cross with cubemap faces
     CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE,     // Layout is defined by a 4x3 cross with cubemap faces
-    CUBEMAP_LAYOUT_PANORAMA                 // Layout is defined by a panorama image (equirectangular map)
+    CUBEMAP_LAYOUT_PANORAMA                 // Layout is defined by a panorama image (equirrectangular map)
 } CubemapLayout;
 
 // Font type, defines generation method
@@ -900,7 +903,7 @@ } NPatchLayout;
 
 // Callbacks to hook some internal functions
-// WARNING: This callbacks are intended for advance users
+// WARNING: These callbacks are intended for advance users
 typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args);  // Logging: Redirect trace log messages
 typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, unsigned int *bytesRead);      // FileIO: Load binary data
 typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, unsigned int bytesToWrite);  // FileIO: Save binary data
@@ -1009,6 +1012,7 @@ // NOTE: Shader functionality is not available on OpenGL 1.1
 RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName);   // Load shader from files and bind default locations
 RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
+RLAPI bool IsShaderReady(Shader shader);                                   // Check if a shader is ready
 RLAPI int GetShaderLocation(Shader shader, const char *uniformName);       // Get shader uniform location
 RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName);  // Get shader attribute location
 RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType);               // Set shader uniform value
@@ -1224,13 +1228,14 @@ //------------------------------------------------------------------------------------
 
 // Image loading functions
-// NOTE: This functions do not require GPU access
+// NOTE: These functions do not require GPU access
 RLAPI Image LoadImage(const char *fileName);                                                             // Load image from file into CPU memory (RAM)
 RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize);       // Load image from RAW file data
 RLAPI Image LoadImageAnim(const char *fileName, int *frames);                                            // Load image sequence from file (frames appended to image.data)
 RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize);      // Load image from memory buffer, fileType refers to extension: i.e. '.png'
 RLAPI Image LoadImageFromTexture(Texture2D texture);                                                     // Load image from GPU texture data
 RLAPI Image LoadImageFromScreen(void);                                                                   // Load image from screen buffer and (screenshot)
+RLAPI bool IsImageReady(Image image);                                                                    // Check if an image is ready
 RLAPI void UnloadImage(Image image);                                                                     // Unload image from CPU memory (RAM)
 RLAPI bool ExportImage(Image image, const char *fileName);                                               // Export image data to file, returns true on success
 RLAPI bool ExportImageAsCode(Image image, const char *fileName);                                         // Export image as code file defining an array of bytes, returns true on success
@@ -1306,7 +1311,9 @@ RLAPI Texture2D LoadTextureFromImage(Image image);                                                       // Load texture from image data
 RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout);                                        // Load cubemap from image, multiple image cubemap layouts supported
 RLAPI RenderTexture2D LoadRenderTexture(int width, int height);                                          // Load texture for rendering (framebuffer)
+RLAPI bool IsTextureReady(Texture2D texture);                                                            // Check if a texture is ready
 RLAPI void UnloadTexture(Texture2D texture);                                                             // Unload texture from GPU memory (VRAM)
+RLAPI bool IsRenderTextureReady(RenderTexture2D target);                                                       // Check if a render texture is ready
 RLAPI void UnloadRenderTexture(RenderTexture2D target);                                                  // Unload render texture from GPU memory (VRAM)
 RLAPI void UpdateTexture(Texture2D texture, const void *pixels);                                         // Update GPU texture with new data
 RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels);                       // Update GPU texture rectangle with new data
@@ -1351,6 +1358,7 @@ RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount);  // Load font from file with extended parameters, use NULL for fontChars and 0 for glyphCount to load the default character set
 RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar);                        // Load font from Image (XNA style)
 RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
+RLAPI bool IsFontReady(Font font);                                                          // Check if a font is ready
 RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use
 RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
 RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount);                                // Unload font chars info data (RAM)
@@ -1435,6 +1443,7 @@ // Model management functions
 RLAPI Model LoadModel(const char *fileName);                                                // Load model from files (meshes and materials)
 RLAPI Model LoadModelFromMesh(Mesh mesh);                                                   // Load model from generated mesh (default material)
+RLAPI bool IsModelReady(Model model);                                                       // Check if a model is ready
 RLAPI void UnloadModel(Model model);                                                        // Unload model (including meshes) from memory (RAM and/or VRAM)
 RLAPI void UnloadModelKeepMeshes(Model model);                                              // Unload model (but not meshes) from memory (RAM and/or VRAM)
 RLAPI BoundingBox GetModelBoundingBox(Model model);                                         // Compute model bounding box limits (considers all meshes)
@@ -1475,6 +1484,7 @@ // Material loading/unloading functions
 RLAPI Material *LoadMaterials(const char *fileName, int *materialCount);                    // Load materials from model file
 RLAPI Material LoadMaterialDefault(void);                                                   // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
+RLAPI bool IsMaterialReady(Material material);                                              // Check if a material is ready
 RLAPI void UnloadMaterial(Material material);                                               // Unload material from GPU memory (VRAM)
 RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture);          // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
 RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId);                  // Set material for a mesh
@@ -1510,8 +1520,10 @@ // Wave/Sound loading/unloading functions
 RLAPI Wave LoadWave(const char *fileName);                            // Load wave data from file
 RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
+RLAPI bool IsWaveReady(Wave wave);                                    // Checks if wave data is ready
 RLAPI Sound LoadSound(const char *fileName);                          // Load sound from file
 RLAPI Sound LoadSoundFromWave(Wave wave);                             // Load sound from wave data
+RLAPI bool IsSoundReady(Sound sound);                                 // Checks if a sound is ready
 RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
 RLAPI void UnloadWave(Wave wave);                                     // Unload wave data
 RLAPI void UnloadSound(Sound sound);                                  // Unload sound
@@ -1539,6 +1551,7 @@ // Music management functions
 RLAPI Music LoadMusicStream(const char *fileName);                    // Load music stream from file
 RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
+RLAPI bool IsMusicReady(Music music);                                 // Checks if a music stream is ready
 RLAPI void UnloadMusicStream(Music music);                            // Unload music stream
 RLAPI void PlayMusicStream(Music music);                              // Start music playing
 RLAPI bool IsMusicStreamPlaying(Music music);                         // Check if music is playing
@@ -1555,6 +1568,7 @@ 
 // AudioStream management functions
 RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
+RLAPI bool IsAudioStreamReady(AudioStream stream);                    // Checks if an audio stream is ready
 RLAPI void UnloadAudioStream(AudioStream stream);                     // Unload audio stream and free memory
 RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
 RLAPI bool IsAudioStreamProcessed(AudioStream stream);                // Check if any audio stream buffers requires refill
raylib/src/raymath.h view
@@ -306,24 +306,33 @@     return result;
 }
 
-// Calculate angle from two vectors
+// Calculate angle between two vectors
+// NOTE: Angle is calculated from origin point (0, 0)
+RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
+{
+    float result = atan2f(v2.y - v1.y, v2.x - v1.x);
+
+    return result;
+}
+
+// Calculate angle defined by a two vectors line
 // NOTE: Parameters need to be normalized
 // Current implementation should be aligned with glm::angle
-RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
+RMAPI float Vector2LineAngle(Vector2 start, Vector2 end)
 {
     float result = 0.0f;
-    
-    float dot = v1.x*v2.x + v1.y*v2.y;      // Dot product
 
-    float dotClamp = (dot < -1.0f)? -1.0f : dot;  // Clamp
+    float dot = start.x*end.x + start.y*end.y;      // Dot product
+
+    float dotClamp = (dot < -1.0f)? -1.0f : dot;    // Clamp
     if (dotClamp > 1.0f) dotClamp = 1.0f;
 
     result = acosf(dotClamp);
-    
+
     // Alternative implementation, more costly
-    //float v1Length = sqrtf((v1.x*v1.x) + (v1.y*v1.y));
-    //float v2Length = sqrtf((v2.x*v2.x) + (v2.y*v2.y));
-    //float result = -acosf((v1.x*v2.x + v1.y*v2.y)/(v1Length*v2Length));
+    //float v1Length = sqrtf((start.x*start.x) + (start.y*start.y));
+    //float v2Length = sqrtf((end.x*end.x) + (end.y*end.y));
+    //float result = -acosf((start.x*end.x + start.y*end.y)/(v1Length*v2Length));
 
     return result;
 }
@@ -903,7 +912,7 @@ {
     Vector3 result = { 0 };
 
-    // Calculate unproject matrix (multiply view patrix by projection matrix) and invert it
+    // Calculate unprojected matrix (multiply view matrix by projection matrix) and invert it
     Matrix matViewProj = {      // MatrixMultiply(view, projection);
         view.m0*projection.m0 + view.m1*projection.m4 + view.m2*projection.m8 + view.m3*projection.m12,
         view.m0*projection.m1 + view.m1*projection.m5 + view.m2*projection.m9 + view.m3*projection.m13,
@@ -966,7 +975,7 @@     // Create quaternion from source point
     Quaternion quat = { source.x, source.y, source.z, 1.0f };
 
-    // Multiply quat point by unproject matrix
+    // Multiply quat point by unprojecte matrix
     Quaternion qtransformed = {     // QuaternionTransform(quat, matViewProjInv)
         matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w,
         matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w,
raylib/src/rcamera.h view
@@ -73,7 +73,7 @@         Vector3 target;         // Camera target it looks-at
         Vector3 up;             // Camera up vector (rotation over its axis)
         float fovy;             // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic
-        int type;               // Camera type, defines projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
+        int projection;         // Camera type, defines projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
     } Camera3D;
 
     typedef Camera3D Camera;    // Camera type fallback, defaults to Camera3D
@@ -150,7 +150,7 @@ #endif
 
 // Camera mouse movement sensitivity
-#define CAMERA_MOUSE_MOVE_SENSITIVITY                   0.5f    // TODO: it should be independant of framerate
+#define CAMERA_MOUSE_MOVE_SENSITIVITY                   0.5f    // TODO: it should be independent of framerate
 #define CAMERA_MOUSE_SCROLL_SENSITIVITY                 1.5f
 
 // FREE_CAMERA
@@ -405,6 +405,9 @@         } break;
         case CAMERA_FIRST_PERSON:   // Camera moves as in a first-person game, controls are configurable
         {
+            // NOTE: On CAMERA_FIRST_PERSON player Y-movement is limited to player 'eyes position'
+            camera->position.y = CAMERA.playerEyesPosition;
+
             camera->position.x += (sinf(CAMERA.angle.x)*direction[MOVE_BACK] -
                                    sinf(CAMERA.angle.x)*direction[MOVE_FRONT] -
                                    cosf(CAMERA.angle.x)*direction[MOVE_LEFT] +
@@ -478,10 +481,6 @@             camera->target.x = camera->position.x - matTransform.m12;
             camera->target.y = camera->position.y - matTransform.m13;
             camera->target.z = camera->position.z - matTransform.m14;
-
-            // Camera position update
-            // NOTE: On CAMERA_FIRST_PERSON player Y-movement is limited to player 'eyes position'
-            camera->position.y = CAMERA.playerEyesPosition;
 
             // Camera swinging (y-movement), only when walking (some key pressed)
             for (int i = 0; i < 6; i++) if (direction[i]) { swingCounter += GetFrameTime(); break; }
raylib/src/rcore.c view
@@ -155,6 +155,9 @@     #undef _POSIX_C_SOURCE
     #define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext.
 #endif
+#if defined(__linux__) && !defined(_GNU_SOURCE)
+    #define _GNU_SOURCE
+#endif
 
 // Platform specific defines to handle GetApplicationDirectory()
 #if defined (PLATFORM_DESKTOP)
@@ -239,6 +242,7 @@         #include <unistd.h>                 // Required for: usleep()
 
         //#define GLFW_EXPOSE_NATIVE_COCOA    // WARNING: Fails due to type redefinition
+        void *glfwGetCocoaWindow(GLFWwindow* handle);
         #include "GLFW/glfw3native.h"       // Required for: glfwGetCocoaWindow()
     #endif
 
@@ -861,7 +865,7 @@     LoadFontDefault();
     #if defined(SUPPORT_MODULE_RSHAPES)
     Rectangle rec = GetFontDefault().recs[95];
-    // NOTE: We setup a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
+    // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
     SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); // WARNING: Module required: rshapes
     #endif
 #else
@@ -1314,7 +1318,7 @@ void MinimizeWindow(void)
 {
 #if defined(PLATFORM_DESKTOP)
-    // NOTE: Following function launches callback that sets appropiate flag!
+    // NOTE: Following function launches callback that sets appropriate flag!
     glfwIconifyWindow(CORE.Window.handle);
 #endif
 }
@@ -1413,13 +1417,13 @@     // State change: FLAG_WINDOW_TRANSPARENT
     if (((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) != (flags & FLAG_WINDOW_TRANSPARENT)) && ((flags & FLAG_WINDOW_TRANSPARENT) > 0))
     {
-        TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only by configured before window initialization");
+        TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization");
     }
 
     // State change: FLAG_WINDOW_HIGHDPI
     if (((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) != (flags & FLAG_WINDOW_HIGHDPI)) && ((flags & FLAG_WINDOW_HIGHDPI) > 0))
     {
-        TRACELOG(LOG_WARNING, "WINDOW: High DPI can only by configured before window initialization");
+        TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization");
     }
 
     // State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
@@ -1432,13 +1436,13 @@     // State change: FLAG_MSAA_4X_HINT
     if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) != (flags & FLAG_MSAA_4X_HINT)) && ((flags & FLAG_MSAA_4X_HINT) > 0))
     {
-        TRACELOG(LOG_WARNING, "WINDOW: MSAA can only by configured before window initialization");
+        TRACELOG(LOG_WARNING, "WINDOW: MSAA can only be configured before window initialization");
     }
 
     // State change: FLAG_INTERLACED_HINT
     if (((CORE.Window.flags & FLAG_INTERLACED_HINT) != (flags & FLAG_INTERLACED_HINT)) && ((flags & FLAG_INTERLACED_HINT) > 0))
     {
-        TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only by configured before window initialization");
+        TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization");
     }
 #endif
 }
@@ -1521,13 +1525,13 @@     // State change: FLAG_WINDOW_TRANSPARENT
     if (((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) && ((flags & FLAG_WINDOW_TRANSPARENT) > 0))
     {
-        TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only by configured before window initialization");
+        TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization");
     }
 
     // State change: FLAG_WINDOW_HIGHDPI
     if (((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) && ((flags & FLAG_WINDOW_HIGHDPI) > 0))
     {
-        TRACELOG(LOG_WARNING, "WINDOW: High DPI can only by configured before window initialization");
+        TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization");
     }
 
     // State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
@@ -1540,13 +1544,13 @@     // State change: FLAG_MSAA_4X_HINT
     if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) > 0) && ((flags & FLAG_MSAA_4X_HINT) > 0))
     {
-        TRACELOG(LOG_WARNING, "WINDOW: MSAA can only by configured before window initialization");
+        TRACELOG(LOG_WARNING, "WINDOW: MSAA can only be configured before window initialization");
     }
 
     // State change: FLAG_INTERLACED_HINT
     if (((CORE.Window.flags & FLAG_INTERLACED_HINT) > 0) && ((flags & FLAG_INTERLACED_HINT) > 0))
     {
-        TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only by configured before window initialization");
+        TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization");
     }
 #endif
 }
@@ -1674,7 +1678,7 @@ #endif
 #if defined(__APPLE__)
     // NOTE: Returned handle is: (objc_object *)
-    return NULL;    // TODO: return (void *)glfwGetCocoaWindow(window);
+    return (void *)glfwGetCocoaWindow(CORE.Window.handle);
 #endif
 
     return NULL;
@@ -1952,10 +1956,10 @@         .then(text => { document.getElementById('clipboard').innerText = text; console.log('Pasted content: ', text); }) \
         .catch(err => { console.error('Failed to read clipboard contents: ', err); });"
     );
-    
+
     // The main issue is getting that data, one approach could be using ASYNCIFY and wait
     // for the data but it requires adding Asyncify emscripten library on compilation
-    
+
     // Another approach could be just copy the data in a HTML text field and try to retrieve it
     // later on if available... and clean it for future accesses
 
@@ -2475,13 +2479,13 @@         //          vertex texcoord2 location   = 5
 
         // NOTE: If any location is not found, loc point becomes -1
-        
+
         shader.locs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int));
 
-        // All locations reseted to -1 (no location)
+        // All locations reset to -1 (no location)
         for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
 
-        // Get handles to GLSL input attibute locations
+        // Get handles to GLSL input attribute locations
         shader.locs[SHADER_LOC_VERTEX_POSITION] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION);
         shader.locs[SHADER_LOC_VERTEX_TEXCOORD01] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
         shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2);
@@ -2506,13 +2510,19 @@     return shader;
 }
 
+// Check if a shader is ready
+bool IsShaderReady(Shader shader)
+{
+    return shader.locs != NULL;
+}
+
 // Unload shader from GPU memory (VRAM)
 void UnloadShader(Shader shader)
 {
     if (shader.id != rlGetShaderIdDefault())
     {
         rlUnloadShaderProgram(shader.id);
-        
+
         // NOTE: If shader loading failed, it should be 0
         RL_FREE(shader.locs);
     }
@@ -2543,7 +2553,7 @@     {
         rlEnableShader(shader.id);
         rlSetUniform(locIndex, value, uniformType, count);
-        //rlDisableShader();      // Avoid reseting current shader program, in case other uniforms are set
+        //rlDisableShader();      // Avoid resetting current shader program, in case other uniforms are set
     }
 }
 
@@ -2608,7 +2618,7 @@     Vector3 farPoint = Vector3Unproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView);
 
     // Unproject the mouse cursor in the near plane.
-    // We need this as the source position because orthographic projects, compared to perspect doesn't have a
+    // We need this as the source position because orthographic projects, compared to perspective doesn't have a
     // convergence point, meaning that the "eye" of the camera is more like a plane than a point.
     Vector3 cameraPlanePointerPos = Vector3Unproject((Vector3){ deviceCoords.x, deviceCoords.y, -1.0f }, matProj, matView);
 
@@ -2798,7 +2808,7 @@ 
 // Setup window configuration flags (view FLAGS)
 // NOTE: This function is expected to be called before window creation,
-// because it setups some flags for the window creation process.
+// because it sets up some flags for the window creation process.
 // To configure window states after creation, just use SetWindowState()
 void SetConfigFlags(unsigned int flags)
 {
@@ -2837,7 +2847,7 @@ 
 // Get a random value between min and max (both included)
 // WARNING: Ranges higher than RAND_MAX will return invalid results
-// More specifically, if (max - min) > INT_MAX there will be an overflow, 
+// More specifically, if (max - min) > INT_MAX there will be an overflow,
 // and otherwise if (max - min) > RAND_MAX the random value will incorrectly never exceed a certain threshold
 int GetRandomValue(int min, int max)
 {
@@ -2847,7 +2857,7 @@         max = min;
         min = tmp;
     }
-    
+
     if ((unsigned int)(max - min) > (unsigned int)RAND_MAX)
     {
         TRACELOG(LOG_WARNING, "Invalid GetRandomValue() arguments, range should not be higher than %i", RAND_MAX);
@@ -3023,7 +3033,7 @@     if (filePath[1] != ':' && filePath[0] != '\\' && filePath[0] != '/')
     {
         // For security, we set starting path to current directory,
-        // obtained path will be concated to this
+        // obtained path will be concatenated to this
         dirPath[0] = '.';
         dirPath[1] = '/';
     }
@@ -3307,7 +3317,7 @@     compData = (unsigned char *)RL_CALLOC(bounds, 1);
     *compDataSize = sdeflate(&sdefl, compData, data, dataSize, COMPRESSION_QUALITY_DEFLATE);   // Compression level 8, same as stbwi
 
-    TraceLog(LOG_INFO, "SYSTEM: Compress data: Original size: %i -> Comp. size: %i", dataSize, *compDataSize);
+    TRACELOG(LOG_INFO, "SYSTEM: Compress data: Original size: %i -> Comp. size: %i", dataSize, *compDataSize);
 #endif
 
     return compData;
@@ -3332,7 +3342,7 @@ 
     *dataSize = length;
 
-    TraceLog(LOG_INFO, "SYSTEM: Decompress data: Comp. size: %i -> Original size: %i", compDataSize, *dataSize);
+    TRACELOG(LOG_INFO, "SYSTEM: Decompress data: Comp. size: %i -> Original size: %i", compDataSize, *dataSize);
 #endif
 
     return data;
@@ -3919,7 +3929,7 @@     CORE.Window.screenScale = MatrixIdentity();  // No draw scaling required by default
 
     // NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
-    // ...in top-down or left-right to match display aspect ratio (no weird scalings)
+    // ...in top-down or left-right to match display aspect ratio (no weird scaling)
 
 #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
     glfwSetErrorCallback(ErrorCallback);
@@ -4040,7 +4050,7 @@         glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);   // Enable OpenGL Debug Context
 #endif
     }
-    else if (rlGetVersion() == RL_OPENGL_ES_20)                    // Request OpenGL ES 2.0 context
+    else if (rlGetVersion() == RL_OPENGL_ES_20)                 // Request OpenGL ES 2.0 context
     {
         glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
         glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
@@ -4088,8 +4098,18 @@     if (CORE.Window.fullscreen)
     {
         // remember center for switchinging from fullscreen to window
-        CORE.Window.position.x = CORE.Window.display.width/2 - CORE.Window.screen.width/2;
-        CORE.Window.position.y = CORE.Window.display.height/2 - CORE.Window.screen.height/2;
+        if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))
+        {
+            // If screen width/height equal to the display, we can't calculate the window pos for toggling full-screened/windowed.
+            // Toggling full-screened/windowed with pos(0, 0) can cause problems in some platforms, such as X11.
+            CORE.Window.position.x = CORE.Window.display.width/4;
+            CORE.Window.position.y = CORE.Window.display.height/4;
+        }
+        else
+        {
+            CORE.Window.position.x = CORE.Window.display.width/2 - CORE.Window.screen.width/2;
+            CORE.Window.position.y = CORE.Window.display.height/2 - CORE.Window.screen.height/2;
+        }
 
         if (CORE.Window.position.x < 0) CORE.Window.position.x = 0;
         if (CORE.Window.position.y < 0) CORE.Window.position.y = 0;
@@ -4118,7 +4138,7 @@         // framebuffer is rendered correctly but once displayed on a 16:9 monitor, it gets stretched
         // by the sides to fit all monitor space...
 
-        // Try to setup the most appropiate fullscreen framebuffer for the requested screenWidth/screenHeight
+        // Try to setup the most appropriate fullscreen framebuffer for the requested screenWidth/screenHeight
         // It considers device display resolution mode and setups a framebuffer with black bars if required (render size/offset)
         // Modified global variables: CORE.Window.screen.width/CORE.Window.screen.height - CORE.Window.render.width/CORE.Window.render.height - CORE.Window.renderOffset.x/CORE.Window.renderOffset.y - CORE.Window.screenScale
         // TODO: It is a quite cumbersome solution to display size vs requested size, it should be reviewed or removed...
@@ -4185,7 +4205,7 @@     // NOTE: V-Sync can be enabled by graphic driver configuration
     if (CORE.Window.flags & FLAG_VSYNC_HINT)
     {
-        // WARNING: It seems to hits a critical render path in Intel HD Graphics
+        // WARNING: It seems to hit a critical render path in Intel HD Graphics
         glfwSwapInterval(1);
         TRACELOG(LOG_INFO, "DISPLAY: Trying to enable VSYNC");
     }
@@ -4196,12 +4216,12 @@ #if defined(PLATFORM_DESKTOP)
     if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
     {
-        // NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling
+        // NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling.
         // Framebuffer scaling should be activated with: glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
     #if !defined(__APPLE__)
         glfwGetFramebufferSize(CORE.Window.handle, &fbWidth, &fbHeight);
 
-        // Screen scaling matrix is required in case desired screen area is different than display area
+        // Screen scaling matrix is required in case desired screen area is different from display area
         CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f);
 
         // Mouse input scaling for the new screen size
@@ -4799,7 +4819,7 @@ // NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could
 // take longer than expected... for that reason we use the busy wait loop
 // Ref: http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected
-// Ref: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timming on Win32!
+// Ref: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timing on Win32!
 void WaitTime(double seconds)
 {
 #if defined(SUPPORT_BUSY_WAIT_LOOP) || defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
@@ -5394,7 +5414,7 @@     //TRACELOG(LOG_DEBUG, "Char Callback: KEY:%i(%c)", key, key);
 
     // NOTE: Registers any key down considering OS keyboard layout but
-    // do not detects action events, those should be managed by user...
+    // does not detect action events, those should be managed by user...
     // Ref: https://github.com/glfw/glfw/issues/668#issuecomment-166794907
     // Ref: https://www.glfw.org/docs/latest/input_guide.html#input_char
 
@@ -5437,7 +5457,7 @@     gestureEvent.position[0].x /= (float)GetScreenWidth();
     gestureEvent.position[0].y /= (float)GetScreenHeight();
 
-    // Gesture data is sent to gestures system for processing
+    // Gesture data is sent to gestures-system for processing
     ProcessGestureEvent(gestureEvent);
 #endif
 }
@@ -5468,7 +5488,7 @@     gestureEvent.position[0].x /= (float)GetScreenWidth();
     gestureEvent.position[0].y /= (float)GetScreenHeight();
 
-    // Gesture data is sent to gestures system for processing
+    // Gesture data is sent to gestures-system for processing
     ProcessGestureEvent(gestureEvent);
 #endif
 }
@@ -5737,7 +5757,7 @@             CORE.Input.Gamepad.ready[0] = true;
 
             GamepadButton button = AndroidTranslateGamepadButton(keycode);
-            
+
             if (button == GAMEPAD_BUTTON_UNKNOWN) return 1;
 
             if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
@@ -5745,7 +5765,7 @@                 CORE.Input.Gamepad.currentButtonState[0][button] = 1;
             }
             else CORE.Input.Gamepad.currentButtonState[0][button] = 0;  // Key up
-            
+
             return 1; // Handled gamepad button
         }
 
@@ -6841,7 +6861,7 @@     if ((fileId[0] == 'r') && (fileId[1] == 'E') && (fileId[2] == 'P') && (fileId[1] == ' '))
     {
         fread(&eventCount, sizeof(int), 1, repFile);
-        TraceLog(LOG_WARNING, "Events loaded: %i\n", eventCount);
+        TRACELOG(LOG_WARNING, "Events loaded: %i\n", eventCount);
         fread(events, sizeof(AutomationEvent), eventCount, repFile);
     }
 
raylib/src/rgestures.h view
@@ -249,7 +249,7 @@ // Module Functions Definition
 //----------------------------------------------------------------------------------
 
-// Enable only desired getures to be detected
+// Enable only desired gestures to be detected
 void SetGesturesEnabled(unsigned int flags)
 {
     GESTURES.enabledFlags = flags;
@@ -300,7 +300,7 @@         {
             if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.upPosition = event.position[0];
 
-            // NOTE: GESTURES.Drag.intensity dependend on the resolution of the screen
+            // NOTE: GESTURES.Drag.intensity dependent on the resolution of the screen
             GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
             GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rgGetCurrentTime() - GESTURES.Swipe.timeDuration));
 
@@ -472,7 +472,7 @@ }
 
 // Get drag angle
-// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
+// NOTE: Angle in degrees, horizontal-right is 0, counterclockwise
 float GetGestureDragAngle(void)
 {
     // NOTE: drag angle is calculated on one touch points TOUCH_ACTION_UP
@@ -488,8 +488,8 @@     return GESTURES.Pinch.vector;
 }
 
-// Get angle beween two pinch points
-// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
+// Get angle between two pinch points
+// NOTE: Angle in degrees, horizontal-right is 0, counterclockwise
 float GetGesturePinchAngle(void)
 {
     // NOTE: pinch angle is calculated on two touch points TOUCH_ACTION_MOVE
raylib/src/rglfw.c view
@@ -75,7 +75,7 @@     #include "external/glfw/src/win32_time.c"
     #include "external/glfw/src/win32_thread.c"
     #include "external/glfw/src/wgl_context.c"
-    
+
     #include "external/glfw/src/egl_context.c"
     #include "external/glfw/src/osmesa_context.c"
 #endif
@@ -87,10 +87,10 @@     #include "external/glfw/src/posix_poll.c"
     #include "external/glfw/src/linux_joystick.c"
     #include "external/glfw/src/xkb_unicode.c"
-    
+
     #include "external/glfw/src/egl_context.c"
     #include "external/glfw/src/osmesa_context.c"
-    
+
     #if defined(_GLFW_WAYLAND)
         #include "external/glfw/src/wl_init.c"
         #include "external/glfw/src/wl_monitor.c"
@@ -110,7 +110,7 @@     #include "external/glfw/src/posix_time.c"
     #include "external/glfw/src/null_joystick.c"
     #include "external/glfw/src/xkb_unicode.c"
-    
+
     #include "external/glfw/src/x11_init.c"
     #include "external/glfw/src/x11_monitor.c"
     #include "external/glfw/src/x11_window.c"
@@ -129,7 +129,7 @@     #include "external/glfw/src/cocoa_window.m"
     #include "external/glfw/src/cocoa_time.c"
     #include "external/glfw/src/nsgl_context.m"
-    
+
     #include "external/glfw/src/egl_context.c"
     #include "external/glfw/src/osmesa_context.c"
 #endif
raylib/src/rlgl.h view
@@ -5,11 +5,11 @@ *   An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0)
 *   that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
 *
-*   When chosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
+*   When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
 *   initialized on rlglInit() to accumulate vertex data.
 *
 *   When an internal state change is required all the stored vertex data is renderer in batch,
-*   additioanlly, rlDrawRenderBatchActive() could be called to force flushing of the batch.
+*   additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch.
 *
 *   Some additional resources are also loaded for convenience, here the complete list:
 *      - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data
@@ -61,12 +61,11 @@ *   When loading a shader, the following vertex attribute and uniform
 *   location names are tried to be set automatically:
 *
-*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION     "vertexPosition"    // Binded by default to shader location: 0
-*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD     "vertexTexCoord"    // Binded by default to shader location: 1
-*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL       "vertexNormal"      // Binded by default to shader location: 2
-*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR        "vertexColor"       // Binded by default to shader location: 3
-*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT      "vertexTangent"     // Binded by default to shader location: 4
-*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2    "vertexTexCoord2"   // Binded by default to shader location: 5
+*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION     "vertexPosition"    // Bound by default to shader location: 0
+*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD     "vertexTexCoord"    // Bound by default to shader location: 1
+*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL       "vertexNormal"      // Bound by default to shader location: 2
+*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR        "vertexColor"       // Bound by default to shader location: 3
+*   #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT      "vertexTangent"     // Bound by default to shader location: 4
 *   #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP         "mvp"               // model-view-projection matrix
 *   #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW        "matView"           // view matrix
 *   #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION  "matProjection"     // projection matrix
@@ -282,33 +281,33 @@ 
 // GL blending factors
 #define RL_ZERO                                 0           // GL_ZERO
-#define RL_ONE                                  1           // GL_ONE  
-#define RL_SRC_COLOR                            0x0300      // GL_SRC_COLOR            
-#define RL_ONE_MINUS_SRC_COLOR                  0x0301      // GL_ONE_MINUS_SRC_COLOR 
-#define RL_SRC_ALPHA                            0x0302      // GL_SRC_ALPHA           
-#define RL_ONE_MINUS_SRC_ALPHA                  0x0303      // GL_ONE_MINUS_SRC_ALPHA 
-#define RL_DST_ALPHA                            0x0304      // GL_DST_ALPHA           
-#define RL_ONE_MINUS_DST_ALPHA                  0x0305      // GL_ONE_MINUS_DST_ALPHA 
-#define RL_DST_COLOR                            0x0306      // GL_DST_COLOR           
-#define RL_ONE_MINUS_DST_COLOR                  0x0307      // GL_ONE_MINUS_DST_COLOR 
-#define RL_SRC_ALPHA_SATURATE                   0x0308      // GL_SRC_ALPHA_SATURATE  
-#define RL_CONSTANT_COLOR                       0x8001      // GL_CONSTANT_COLOR          
+#define RL_ONE                                  1           // GL_ONE
+#define RL_SRC_COLOR                            0x0300      // GL_SRC_COLOR
+#define RL_ONE_MINUS_SRC_COLOR                  0x0301      // GL_ONE_MINUS_SRC_COLOR
+#define RL_SRC_ALPHA                            0x0302      // GL_SRC_ALPHA
+#define RL_ONE_MINUS_SRC_ALPHA                  0x0303      // GL_ONE_MINUS_SRC_ALPHA
+#define RL_DST_ALPHA                            0x0304      // GL_DST_ALPHA
+#define RL_ONE_MINUS_DST_ALPHA                  0x0305      // GL_ONE_MINUS_DST_ALPHA
+#define RL_DST_COLOR                            0x0306      // GL_DST_COLOR
+#define RL_ONE_MINUS_DST_COLOR                  0x0307      // GL_ONE_MINUS_DST_COLOR
+#define RL_SRC_ALPHA_SATURATE                   0x0308      // GL_SRC_ALPHA_SATURATE
+#define RL_CONSTANT_COLOR                       0x8001      // GL_CONSTANT_COLOR
 #define RL_ONE_MINUS_CONSTANT_COLOR             0x8002      // GL_ONE_MINUS_CONSTANT_COLOR
-#define RL_CONSTANT_ALPHA                       0x8003      // GL_CONSTANT_ALPHA          
+#define RL_CONSTANT_ALPHA                       0x8003      // GL_CONSTANT_ALPHA
 #define RL_ONE_MINUS_CONSTANT_ALPHA             0x8004      // GL_ONE_MINUS_CONSTANT_ALPHA
 
 // GL blending functions/equations
-#define RL_FUNC_ADD                             0x8006      // GL_FUNC_ADD             
-#define RL_FUNC_SUBTRACT                        0x800A      // GL_FUNC_SUBTRACT        
+#define RL_FUNC_ADD                             0x8006      // GL_FUNC_ADD
+#define RL_FUNC_SUBTRACT                        0x800A      // GL_FUNC_SUBTRACT
 #define RL_FUNC_REVERSE_SUBTRACT                0x800B      // GL_FUNC_REVERSE_SUBTRACT
-#define RL_BLEND_EQUATION                       0x8009      // GL_BLEND_EQUATION       
+#define RL_BLEND_EQUATION                       0x8009      // GL_BLEND_EQUATION
 #define RL_BLEND_EQUATION_RGB                   0x8009      // GL_BLEND_EQUATION_RGB   // (Same as BLEND_EQUATION)
-#define RL_BLEND_EQUATION_ALPHA                 0x883D      // GL_BLEND_EQUATION_ALPHA 
-#define RL_BLEND_DST_RGB                        0x80C8      // GL_BLEND_DST_RGB        
-#define RL_BLEND_SRC_RGB                        0x80C9      // GL_BLEND_SRC_RGB        
-#define RL_BLEND_DST_ALPHA                      0x80CA      // GL_BLEND_DST_ALPHA      
-#define RL_BLEND_SRC_ALPHA                      0x80CB      // GL_BLEND_SRC_ALPHA                   
-#define RL_BLEND_COLOR                          0x8005      // GL_BLEND_COLOR               
+#define RL_BLEND_EQUATION_ALPHA                 0x883D      // GL_BLEND_EQUATION_ALPHA
+#define RL_BLEND_DST_RGB                        0x80C8      // GL_BLEND_DST_RGB
+#define RL_BLEND_SRC_RGB                        0x80C9      // GL_BLEND_SRC_RGB
+#define RL_BLEND_DST_ALPHA                      0x80CA      // GL_BLEND_DST_ALPHA
+#define RL_BLEND_SRC_ALPHA                      0x80CB      // GL_BLEND_SRC_ALPHA
+#define RL_BLEND_COLOR                          0x8005      // GL_BLEND_COLOR
 
 
 //----------------------------------------------------------------------------------
@@ -503,18 +502,18 @@ } rlShaderAttributeDataType;
 
 // Framebuffer attachment type
-// NOTE: By default up to 8 color channels defined but it can be more
+// NOTE: By default up to 8 color channels defined, but it can be more
 typedef enum {
-    RL_ATTACHMENT_COLOR_CHANNEL0 = 0,   // Framebuffer attachmment type: color 0
-    RL_ATTACHMENT_COLOR_CHANNEL1,       // Framebuffer attachmment type: color 1
-    RL_ATTACHMENT_COLOR_CHANNEL2,       // Framebuffer attachmment type: color 2
-    RL_ATTACHMENT_COLOR_CHANNEL3,       // Framebuffer attachmment type: color 3
-    RL_ATTACHMENT_COLOR_CHANNEL4,       // Framebuffer attachmment type: color 4
-    RL_ATTACHMENT_COLOR_CHANNEL5,       // Framebuffer attachmment type: color 5
-    RL_ATTACHMENT_COLOR_CHANNEL6,       // Framebuffer attachmment type: color 6
-    RL_ATTACHMENT_COLOR_CHANNEL7,       // Framebuffer attachmment type: color 7
-    RL_ATTACHMENT_DEPTH = 100,          // Framebuffer attachmment type: depth
-    RL_ATTACHMENT_STENCIL = 200,        // Framebuffer attachmment type: stencil
+    RL_ATTACHMENT_COLOR_CHANNEL0 = 0,   // Framebuffer attachment type: color 0
+    RL_ATTACHMENT_COLOR_CHANNEL1,       // Framebuffer attachment type: color 1
+    RL_ATTACHMENT_COLOR_CHANNEL2,       // Framebuffer attachment type: color 2
+    RL_ATTACHMENT_COLOR_CHANNEL3,       // Framebuffer attachment type: color 3
+    RL_ATTACHMENT_COLOR_CHANNEL4,       // Framebuffer attachment type: color 4
+    RL_ATTACHMENT_COLOR_CHANNEL5,       // Framebuffer attachment type: color 5
+    RL_ATTACHMENT_COLOR_CHANNEL6,       // Framebuffer attachment type: color 6
+    RL_ATTACHMENT_COLOR_CHANNEL7,       // Framebuffer attachment type: color 7
+    RL_ATTACHMENT_DEPTH = 100,          // Framebuffer attachment type: depth
+    RL_ATTACHMENT_STENCIL = 200,        // Framebuffer attachment type: stencil
 } rlFramebufferAttachType;
 
 // Framebuffer texture attachment type
@@ -545,7 +544,7 @@ 
 RLAPI void rlMatrixMode(int mode);                    // Choose the current matrix to be transformed
 RLAPI void rlPushMatrix(void);                        // Push the current matrix to stack
-RLAPI void rlPopMatrix(void);                         // Pop lattest inserted matrix from stack
+RLAPI void rlPopMatrix(void);                         // Pop latest inserted matrix from stack
 RLAPI void rlLoadIdentity(void);                      // Reset current matrix to identity matrix
 RLAPI void rlTranslatef(float x, float y, float z);   // Multiply the current matrix by a translation matrix
 RLAPI void rlRotatef(float angle, float x, float y, float z);  // Multiply the current matrix by a rotation matrix
@@ -596,6 +595,7 @@ RLAPI void rlEnableTextureCubemap(unsigned int id);     // Enable texture cubemap
 RLAPI void rlDisableTextureCubemap(void);               // Disable texture cubemap
 RLAPI void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap)
+RLAPI void rlCubemapParameters(unsigned int id, int param, int value); // Set cubemap parameters (filter, wrap)
 
 // Shader state
 RLAPI void rlEnableShader(unsigned int id);             // Enable shader program
@@ -641,7 +641,7 @@ //------------------------------------------------------------------------------------
 // rlgl initialization functions
 RLAPI void rlglInit(int width, int height);             // Initialize rlgl (buffers, shaders, textures, states)
-RLAPI void rlglClose(void);                             // De-inititialize rlgl (buffers, shaders, textures)
+RLAPI void rlglClose(void);                             // De-initialize rlgl (buffers, shaders, textures)
 RLAPI void rlLoadExtensions(void *loader);              // Load OpenGL extensions (loader function required)
 RLAPI int rlGetVersion(void);                           // Get current OpenGL version
 RLAPI void rlSetFramebufferWidth(int width);            // Set current framebuffer width
@@ -715,7 +715,7 @@ 
 // Compute shader management
 RLAPI unsigned int rlLoadComputeShaderProgram(unsigned int shaderId);           // Load compute shader program
-RLAPI void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ);  // Dispatch compute shader (equivalent to *draw* for graphics pilepine)
+RLAPI void rlComputeShaderDispatch(unsigned int groupX, unsigned int groupY, unsigned int groupZ);  // Dispatch compute shader (equivalent to *draw* for graphics pipeline)
 
 // Shader buffer storage object management (ssbo)
 RLAPI unsigned int rlLoadShaderBuffer(unsigned int size, const void *data, int usageHint); // Load shader storage buffer object (SSBO)
@@ -789,10 +789,17 @@ #endif
 
 #if defined(GRAPHICS_API_OPENGL_ES2)
-    #define GL_GLEXT_PROTOTYPES
-    //#include <EGL/egl.h>              // EGL library -> not required, platform layer
-    #include <GLES2/gl2.h>              // OpenGL ES 2.0 library
-    #include <GLES2/gl2ext.h>           // OpenGL ES 2.0 extensions library
+    // NOTE: OpenGL ES 2.0 can be enabled on PLATFORM_DESKTOP,
+    // in that case, functions are loaded from a custom glad for OpenGL ES 2.0
+    #if defined(PLATFORM_DESKTOP)
+        #define GLAD_GLES2_IMPLEMENTATION
+        #include "external/glad_gles2.h"
+    #else
+        #define GL_GLEXT_PROTOTYPES
+        //#include <EGL/egl.h>          // EGL library -> not required, platform layer
+        #include <GLES2/gl2.h>          // OpenGL ES 2.0 library
+        #include <GLES2/gl2ext.h>       // OpenGL ES 2.0 extensions library
+    #endif
 
     // It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi
     // provided headers (despite being defined in official Khronos GLES2 headers)
@@ -884,22 +891,22 @@ 
 // Default shader vertex attribute names to set location points
 #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION
-    #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION     "vertexPosition"    // Binded by default to shader location: 0
+    #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION     "vertexPosition"    // Bound by default to shader location: 0
 #endif
 #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD
-    #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD     "vertexTexCoord"    // Binded by default to shader location: 1
+    #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD     "vertexTexCoord"    // Bound by default to shader location: 1
 #endif
 #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL
-    #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL       "vertexNormal"      // Binded by default to shader location: 2
+    #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL       "vertexNormal"      // Bound by default to shader location: 2
 #endif
 #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR
-    #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR        "vertexColor"       // Binded by default to shader location: 3
+    #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR        "vertexColor"       // Bound by default to shader location: 3
 #endif
 #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT
-    #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT      "vertexTangent"     // Binded by default to shader location: 4
+    #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT      "vertexTangent"     // Bound by default to shader location: 4
 #endif
 #ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2
-    #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2    "vertexTexCoord2"   // Binded by default to shader location: 5
+    #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2    "vertexTexCoord2"   // Bound by default to shader location: 5
 #endif
 
 #ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP
@@ -1617,6 +1624,50 @@     glBindTexture(GL_TEXTURE_2D, 0);
 }
 
+// Set cubemap parameters (wrap mode/filter mode)
+void rlCubemapParameters(unsigned int id, int param, int value)
+{
+#if !defined(GRAPHICS_API_OPENGL_11)
+    glBindTexture(GL_TEXTURE_CUBE_MAP, id);
+
+    // Reset anisotropy filter, in case it was set
+    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
+
+    switch (param)
+    {
+        case RL_TEXTURE_WRAP_S:
+        case RL_TEXTURE_WRAP_T:
+        {
+            if (value == RL_TEXTURE_WRAP_MIRROR_CLAMP)
+            {
+                if (RLGL.ExtSupported.texMirrorClamp) glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value);
+                else TRACELOG(RL_LOG_WARNING, "GL: Clamp mirror wrap mode not supported (GL_MIRROR_CLAMP_EXT)");
+            }
+            else glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value);
+
+        } break;
+        case RL_TEXTURE_MAG_FILTER:
+        case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_CUBE_MAP, param, value); break;
+        case RL_TEXTURE_FILTER_ANISOTROPIC:
+        {
+            if (value <= RLGL.ExtSupported.maxAnisotropyLevel) glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
+            else if (RLGL.ExtSupported.maxAnisotropyLevel > 0.0f)
+            {
+                TRACELOG(RL_LOG_WARNING, "GL: Maximum anisotropic filter level supported is %iX", id, (int)RLGL.ExtSupported.maxAnisotropyLevel);
+                glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
+            }
+            else TRACELOG(RL_LOG_WARNING, "GL: Anisotropic filtering not supported");
+        } break;
+#if defined(GRAPHICS_API_OPENGL_33)
+        case RL_TEXTURE_MIPMAP_BIAS_RATIO: glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_LOD_BIAS, value/100.0f);
+#endif
+        default: break;
+    }
+
+    glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+#endif
+}
+
 // Enable shader program
 void rlEnableShader(unsigned int id)
 {
@@ -2144,6 +2195,12 @@ #endif  // GRAPHICS_API_OPENGL_33
 
 #if defined(GRAPHICS_API_OPENGL_ES2)
+
+    #if defined(PLATFORM_DESKTOP)
+    if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions");
+    else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES2.0 loaded successfully");
+    #endif
+
     // Get supported extensions list
     GLint numExt = 0;
     const char **extList = RL_MALLOC(512*sizeof(const char *)); // Allocate 512 strings pointers (2 KB)
@@ -2709,7 +2766,7 @@ 
             for (int i = 0, vertexOffset = 0; i < batch->drawCounter; i++)
             {
-                // Bind current draw call texture, activated as GL_TEXTURE0 and binded to sampler2D texture0 by default
+                // Bind current draw call texture, activated as GL_TEXTURE0 and Bound to sampler2D texture0 by default
                 glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId);
 
                 if ((batch->draws[i].mode == RL_LINES) || (batch->draws[i].mode == RL_TRIANGLES)) glDrawArrays(batch->draws[i].mode, vertexOffset, batch->draws[i].vertexCount);
@@ -2985,7 +3042,7 @@ #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
     // In case depth textures not supported, we force renderbuffer usage
     if (!RLGL.ExtSupported.texDepth) useRenderBuffer = true;
-    
+
     // NOTE: We let the implementation to choose the best bit-depth
     // Possible formats: GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32 and GL_DEPTH_COMPONENT32F
     unsigned int glInternalFormat = GL_DEPTH_COMPONENT;
@@ -3190,6 +3247,7 @@ // NOTE: Only supports GPU mipmap generation
 void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps)
 {
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
     glBindTexture(GL_TEXTURE_2D, id);
 
     // Check if texture is power-of-two (POT)
@@ -3198,7 +3256,6 @@     if (((width > 0) && ((width & (width - 1)) == 0)) &&
         ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true;
 
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
     if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
     {
         //glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE);   // Hint for mipmaps generation algorithm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
@@ -3210,10 +3267,12 @@         *mipmaps = 1 + (int)floor(log(MAX(width, height))/log(2));
         TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Mipmaps generated automatically, total: %i", id, *mipmaps);
     }
-#endif
     else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps", id);
 
     glBindTexture(GL_TEXTURE_2D, 0);
+#else
+    TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] GPU mipmap generation not supported", id);
+#endif
 }
 
 
@@ -3796,7 +3855,7 @@     glAttachShader(program, vShaderId);
     glAttachShader(program, fShaderId);
 
-    // NOTE: Default attribute shader locations must be binded before linking
+    // NOTE: Default attribute shader locations must be Bound before linking
     glBindAttribLocation(program, 0, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION);
     glBindAttribLocation(program, 1, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
     glBindAttribLocation(program, 2, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
raylib/src/rmodels.c view
@@ -102,10 +102,21 @@     #define PAR_REALLOC(T, BUF, N) ((T*)RL_REALLOC(BUF, sizeof(T)*(N)))
     #define PAR_FREE RL_FREE
 
+#if defined(_MSC_VER ) // par shapes has 2 warnings on windows, so disable them just fof this file
+#pragma warning( push )
+#pragma warning( disable : 4244)
+#pragma warning( disable : 4305)
+#endif
+
     #define PAR_SHAPES_IMPLEMENTATION
     #include "external/par_shapes.h"    // Shapes 3d parametric generation
+
+#if defined(_MSC_VER )  // disable MSVC warning suppression for par shapes
+#pragma warning( pop )
 #endif
 
+#endif
+
 #if defined(_WIN32)
     #include <direct.h>     // Required for: _chdir() [Used in LoadOBJ()]
     #define CHDIR _chdir
@@ -155,6 +166,9 @@ static Model LoadM3D(const char *filename);     // Load M3D mesh data
 static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, unsigned int *animCount);   // Load M3D animation data
 #endif
+#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
+static void ProcessMaterialsOBJ(Material *rayMaterials, tinyobj_material_t *materials, int materialCount);  // Process obj materials
+#endif
 
 //----------------------------------------------------------------------------------
 // Module Functions Definition
@@ -678,7 +692,7 @@     if (slices < 3) slices = 3;
 
     Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z };
-    
+
     // draw a sphere if start and end points are the same
     bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0);
     if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f};
@@ -690,7 +704,7 @@     Vector3 capCenter = endPos;
 
     float baseSliceAngle = (2.0f*PI)/slices;
-    float baseRingAngle  = PI * 0.5 / rings; 
+    float baseRingAngle  = PI * 0.5f / rings;
 
     rlBegin(RL_TRIANGLES);
         rlColor4ub(color.r, color.g, color.b, color.a);
@@ -700,7 +714,7 @@         {
             for (int i = 0; i < rings; i++)
             {
-                for (int j = 0; j < slices; j++) 
+                for (int j = 0; j < slices; j++)
                 {
 
                     // we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier
@@ -711,32 +725,32 @@                     // compute the four vertices
                     float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));
                     float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));
-                    Vector3 w1 = (Vector3){ 
+                    Vector3 w1 = (Vector3){
                         capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x) * radius,
-                        capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y) * radius, 
+                        capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y) * radius,
                         capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z) * radius
                     };
                     float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));
                     float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));
-                    Vector3 w2 = (Vector3){ 
-                        capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x) * radius, 
-                        capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y) * radius, 
-                        capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z) * radius 
+                    Vector3 w2 = (Vector3){
+                        capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x) * radius,
+                        capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y) * radius,
+                        capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z) * radius
                     };
 
                     float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));
                     float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));
-                    Vector3 w3 = (Vector3){ 
-                        capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x) * radius, 
-                        capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y) * radius, 
-                        capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z) * radius 
+                    Vector3 w3 = (Vector3){
+                        capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x) * radius,
+                        capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y) * radius,
+                        capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z) * radius
                     };
                     float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));
                     float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));
-                    Vector3 w4 = (Vector3){ 
-                        capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x) * radius, 
-                        capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y) * radius, 
-                        capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z) * radius 
+                    Vector3 w4 = (Vector3){
+                        capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x) * radius,
+                        capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y) * radius,
+                        capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z) * radius
                     };
 
                     // make sure cap triangle normals are facing outwards
@@ -745,10 +759,10 @@                         rlVertex3f(w1.x, w1.y, w1.z);
                         rlVertex3f(w2.x, w2.y, w2.z);
                         rlVertex3f(w3.x, w3.y, w3.z);
-                        
-                        rlVertex3f(w2.x, w2.y, w2.z);   
-                        rlVertex3f(w4.x, w4.y, w4.z);  
-                        rlVertex3f(w3.x, w3.y, w3.z); 
+
+                        rlVertex3f(w2.x, w2.y, w2.z);
+                        rlVertex3f(w4.x, w4.y, w4.z);
+                        rlVertex3f(w3.x, w3.y, w3.z);
                     }
                     else
                     {
@@ -756,9 +770,9 @@                         rlVertex3f(w3.x, w3.y, w3.z);
                         rlVertex3f(w2.x, w2.y, w2.z);
 
-                        rlVertex3f(w2.x, w2.y, w2.z);  
-                        rlVertex3f(w3.x, w3.y, w3.z);  
-                        rlVertex3f(w4.x, w4.y, w4.z);     
+                        rlVertex3f(w2.x, w2.y, w2.z);
+                        rlVertex3f(w3.x, w3.y, w3.z);
+                        rlVertex3f(w4.x, w4.y, w4.z);
                     }
                 }
             }
@@ -768,37 +782,37 @@         // render middle
         if (!sphereCase)
         {
-            for (int j = 0; j < slices; j++) 
+            for (int j = 0; j < slices; j++)
             {
                 // compute the four vertices
                 float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius;
                 float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius;
-                Vector3 w1 = { 
+                Vector3 w1 = {
                     startPos.x + ringSin1*b1.x + ringCos1*b2.x,
-                    startPos.y + ringSin1*b1.y + ringCos1*b2.y, 
-                    startPos.z + ringSin1*b1.z + ringCos1*b2.z 
+                    startPos.y + ringSin1*b1.y + ringCos1*b2.y,
+                    startPos.z + ringSin1*b1.z + ringCos1*b2.z
                 };
                 float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius;
                 float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius;
-                Vector3 w2 = { 
-                    startPos.x + ringSin2*b1.x + ringCos2*b2.x, 
-                    startPos.y + ringSin2*b1.y + ringCos2*b2.y, 
-                    startPos.z + ringSin2*b1.z + ringCos2*b2.z 
+                Vector3 w2 = {
+                    startPos.x + ringSin2*b1.x + ringCos2*b2.x,
+                    startPos.y + ringSin2*b1.y + ringCos2*b2.y,
+                    startPos.z + ringSin2*b1.z + ringCos2*b2.z
                 };
 
                 float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius;
                 float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius;
-                Vector3 w3 = { 
-                    endPos.x + ringSin3*b1.x + ringCos3*b2.x, 
-                    endPos.y + ringSin3*b1.y + ringCos3*b2.y, 
-                    endPos.z + ringSin3*b1.z + ringCos3*b2.z 
+                Vector3 w3 = {
+                    endPos.x + ringSin3*b1.x + ringCos3*b2.x,
+                    endPos.y + ringSin3*b1.y + ringCos3*b2.y,
+                    endPos.z + ringSin3*b1.z + ringCos3*b2.z
                 };
                 float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius;
                 float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius;
-                Vector3 w4 = { 
-                    endPos.x + ringSin4*b1.x + ringCos4*b2.x, 
-                    endPos.y + ringSin4*b1.y + ringCos4*b2.y, 
-                    endPos.z + ringSin4*b1.z + ringCos4*b2.z 
+                Vector3 w4 = {
+                    endPos.x + ringSin4*b1.x + ringCos4*b2.x,
+                    endPos.y + ringSin4*b1.y + ringCos4*b2.y,
+                    endPos.z + ringSin4*b1.z + ringCos4*b2.z
                 };
                                                                         //          w2 x.-----------x startPos
                 rlVertex3f(w1.x, w1.y, w1.z);                         // |           |\'.  T0    /
@@ -833,7 +847,7 @@     Vector3 capCenter = endPos;
 
     float baseSliceAngle = (2.0f*PI)/slices;
-    float baseRingAngle  = PI * 0.5 / rings; 
+    float baseRingAngle  = PI * 0.5f / rings;
 
     rlBegin(RL_LINES);
         rlColor4ub(color.r, color.g, color.b, color.a);
@@ -843,7 +857,7 @@         {
             for (int i = 0; i < rings; i++)
             {
-                for (int j = 0; j < slices; j++) 
+                for (int j = 0; j < slices; j++)
                 {
 
                     // we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier
@@ -854,32 +868,32 @@                     // compute the four vertices
                     float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));
                     float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 ));
-                    Vector3 w1 = (Vector3){ 
+                    Vector3 w1 = (Vector3){
                         capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x) * radius,
-                        capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y) * radius, 
+                        capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y) * radius,
                         capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z) * radius
                     };
                     float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));
                     float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 ));
-                    Vector3 w2 = (Vector3){ 
-                        capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x) * radius, 
-                        capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y) * radius, 
-                        capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z) * radius 
+                    Vector3 w2 = (Vector3){
+                        capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x) * radius,
+                        capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y) * radius,
+                        capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z) * radius
                     };
 
                     float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));
                     float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 ));
-                    Vector3 w3 = (Vector3){ 
-                        capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x) * radius, 
-                        capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y) * radius, 
-                        capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z) * radius 
+                    Vector3 w3 = (Vector3){
+                        capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x) * radius,
+                        capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y) * radius,
+                        capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z) * radius
                     };
                     float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));
                     float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 ));
-                    Vector3 w4 = (Vector3){ 
-                        capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x) * radius, 
-                        capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y) * radius, 
-                        capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z) * radius 
+                    Vector3 w4 = (Vector3){
+                        capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x) * radius,
+                        capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y) * radius,
+                        capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z) * radius
                     };
 
                     rlVertex3f(w1.x, w1.y, w1.z);
@@ -890,12 +904,12 @@ 
                     rlVertex3f(w1.x, w1.y, w1.z);
                     rlVertex3f(w3.x, w3.y, w3.z);
-                    
-                    rlVertex3f(w2.x, w2.y, w2.z);   
-                    rlVertex3f(w4.x, w4.y, w4.z); 
 
+                    rlVertex3f(w2.x, w2.y, w2.z);
+                    rlVertex3f(w4.x, w4.y, w4.z);
+
                     rlVertex3f(w3.x, w3.y, w3.z);
-                    rlVertex3f(w4.x, w4.y, w4.z); 
+                    rlVertex3f(w4.x, w4.y, w4.z);
                 }
             }
             capCenter = startPos;
@@ -904,46 +918,46 @@         // render middle
         if (!sphereCase)
         {
-            for (int j = 0; j < slices; j++) 
+            for (int j = 0; j < slices; j++)
             {
                 // compute the four vertices
                 float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius;
                 float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius;
-                Vector3 w1 = { 
+                Vector3 w1 = {
                     startPos.x + ringSin1*b1.x + ringCos1*b2.x,
-                    startPos.y + ringSin1*b1.y + ringCos1*b2.y, 
-                    startPos.z + ringSin1*b1.z + ringCos1*b2.z 
+                    startPos.y + ringSin1*b1.y + ringCos1*b2.y,
+                    startPos.z + ringSin1*b1.z + ringCos1*b2.z
                 };
                 float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius;
                 float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius;
-                Vector3 w2 = { 
-                    startPos.x + ringSin2*b1.x + ringCos2*b2.x, 
-                    startPos.y + ringSin2*b1.y + ringCos2*b2.y, 
-                    startPos.z + ringSin2*b1.z + ringCos2*b2.z 
+                Vector3 w2 = {
+                    startPos.x + ringSin2*b1.x + ringCos2*b2.x,
+                    startPos.y + ringSin2*b1.y + ringCos2*b2.y,
+                    startPos.z + ringSin2*b1.z + ringCos2*b2.z
                 };
 
                 float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius;
                 float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius;
-                Vector3 w3 = { 
-                    endPos.x + ringSin3*b1.x + ringCos3*b2.x, 
-                    endPos.y + ringSin3*b1.y + ringCos3*b2.y, 
-                    endPos.z + ringSin3*b1.z + ringCos3*b2.z 
+                Vector3 w3 = {
+                    endPos.x + ringSin3*b1.x + ringCos3*b2.x,
+                    endPos.y + ringSin3*b1.y + ringCos3*b2.y,
+                    endPos.z + ringSin3*b1.z + ringCos3*b2.z
                 };
                 float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius;
                 float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius;
-                Vector3 w4 = { 
-                    endPos.x + ringSin4*b1.x + ringCos4*b2.x, 
-                    endPos.y + ringSin4*b1.y + ringCos4*b2.y, 
-                    endPos.z + ringSin4*b1.z + ringCos4*b2.z 
+                Vector3 w4 = {
+                    endPos.x + ringSin4*b1.x + ringCos4*b2.x,
+                    endPos.y + ringSin4*b1.y + ringCos4*b2.y,
+                    endPos.z + ringSin4*b1.z + ringCos4*b2.z
                 };
 
-                rlVertex3f(w1.x, w1.y, w1.z); 
+                rlVertex3f(w1.x, w1.y, w1.z);
                 rlVertex3f(w3.x, w3.y, w3.z);
 
-                rlVertex3f(w2.x, w2.y, w2.z); 
-                rlVertex3f(w4.x, w4.y, w4.z); 
+                rlVertex3f(w2.x, w2.y, w2.z);
+                rlVertex3f(w4.x, w4.y, w4.z);
 
-                rlVertex3f(w2.x, w2.y, w2.z); 
+                rlVertex3f(w2.x, w2.y, w2.z);
                 rlVertex3f(w3.x, w3.y, w3.z);
             }
         }
@@ -1095,6 +1109,12 @@     return model;
 }
 
+// Check if a model is ready
+bool IsModelReady(Model model)
+{
+    return model.meshes != NULL && model.materials != NULL && model.meshMaterial != NULL && model.meshCount > 0 && model.materialCount > 0;
+}
+
 // Unload model (meshes/materials) from memory (RAM and/or VRAM)
 // NOTE: This function takes care of all model elements, for a detailed control
 // over them, use UnloadMesh() and UnloadMaterial()
@@ -1105,7 +1125,7 @@ 
     // Unload materials maps
     // NOTE: As the user could be sharing shaders and textures between models,
-    // we don't unload the material but just free it's maps,
+    // we don't unload the material but just free its maps,
     // the user is responsible for freeing models shaders and textures
     for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps);
 
@@ -1126,7 +1146,7 @@ {
     // Unload materials maps
     // NOTE: As the user could be sharing shaders and textures between models,
-    // we don't unload the material but just free it's maps,
+    // we don't unload the material but just free its maps,
     // the user is responsible for freeing models shaders and textures
     for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps);
 
@@ -1210,7 +1230,7 @@     rlEnableVertexAttribute(1);
 
     // WARNING: When setting default vertex attribute values, the values for each generic vertex attribute
-    // is part of current state and it is maintained even if a different program object is used
+    // is part of current state, and it is maintained even if a different program object is used
 
     if (mesh->normals != NULL)
     {
@@ -1363,7 +1383,7 @@     }
 
     // Get a copy of current matrices to work with,
-    // just in case stereo render is required and we need to modify them
+    // just in case stereo render is required, and we need to modify them
     // NOTE: At this point the modelview matrix just contains the view matrix (camera)
     // That's because BeginMode3D() sets it and there is no model-drawing function
     // that modifies it, all use rlPushMatrix() and rlPopMatrix()
@@ -1376,7 +1396,7 @@     if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView);
     if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);
 
-    // Model transformation matrix is send to shader uniform location: SHADER_LOC_MATRIX_MODEL
+    // Model transformation matrix is sent to shader uniform location: SHADER_LOC_MATRIX_MODEL
     if (material.shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MODEL], transform);
 
     // Accumulate several model transformations:
@@ -1497,7 +1517,7 @@         else rlDrawVertexArray(0, mesh.vertexCount);
     }
 
-    // Unbind all binded texture maps
+    // Unbind all bound texture maps
     for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
     {
         if (material.maps[i].texture.id > 0)
@@ -1567,7 +1587,7 @@     }
 
     // Get a copy of current matrices to work with,
-    // just in case stereo render is required and we need to modify them
+    // just in case stereo render is required, and we need to modify them
     // NOTE: At this point the modelview matrix just contains the view matrix (camera)
     // That's because BeginMode3D() sets it and there is no model-drawing function
     // that modifies it, all use rlPushMatrix() and rlPopMatrix()
@@ -1718,7 +1738,7 @@         else rlDrawVertexArrayInstanced(0, mesh.vertexCount, instances);
     }
 
-    // Unbind all binded texture maps
+    // Unbind all bound texture maps
     for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
     {
         if (material.maps[i].texture.id > 0)
@@ -1851,6 +1871,41 @@     return success;
 }
 
+#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
+// Process obj materials
+static void ProcessMaterialsOBJ(Material *rayMaterials, tinyobj_material_t *materials, int materialCount)
+{
+    // Init model materials
+    for (int m = 0; m < materialCount; m++)
+    {
+        // Init material to default
+        // NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE
+        rayMaterials[m] = LoadMaterialDefault();
+
+        // Get default texture, in case no texture is defined
+        // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
+        rayMaterials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
+
+        if (materials[m].diffuse_texname != NULL) rayMaterials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(materials[m].diffuse_texname);  //char *diffuse_texname; // map_Kd
+
+        rayMaterials[m].maps[MATERIAL_MAP_DIFFUSE].color = (Color){ (unsigned char)(materials[m].diffuse[0]*255.0f), (unsigned char)(materials[m].diffuse[1]*255.0f), (unsigned char)(materials[m].diffuse[2] * 255.0f), 255 }; //float diffuse[3];
+        rayMaterials[m].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f;
+
+        if (materials[m].specular_texname != NULL) rayMaterials[m].maps[MATERIAL_MAP_SPECULAR].texture = LoadTexture(materials[m].specular_texname);  //char *specular_texname; // map_Ks
+        rayMaterials[m].maps[MATERIAL_MAP_SPECULAR].color = (Color){ (unsigned char)(materials[m].specular[0]*255.0f), (unsigned char)(materials[m].specular[1]*255.0f), (unsigned char)(materials[m].specular[2] * 255.0f), 255 }; //float specular[3];
+        rayMaterials[m].maps[MATERIAL_MAP_SPECULAR].value = 0.0f;
+
+        if (materials[m].bump_texname != NULL) rayMaterials[m].maps[MATERIAL_MAP_NORMAL].texture = LoadTexture(materials[m].bump_texname);  //char *bump_texname; // map_bump, bump
+        rayMaterials[m].maps[MATERIAL_MAP_NORMAL].color = WHITE;
+        rayMaterials[m].maps[MATERIAL_MAP_NORMAL].value = materials[m].shininess;
+
+        rayMaterials[m].maps[MATERIAL_MAP_EMISSION].color = (Color){ (unsigned char)(materials[m].emission[0]*255.0f), (unsigned char)(materials[m].emission[1]*255.0f), (unsigned char)(materials[m].emission[2] * 255.0f), 255 }; //float emission[3];
+
+        if (materials[m].displacement_texname != NULL) rayMaterials[m].maps[MATERIAL_MAP_HEIGHT].texture = LoadTexture(materials[m].displacement_texname);  //char *displacement_texname; // disp
+    }
+}
+#endif
+
 // Load materials from model file
 Material *LoadMaterials(const char *fileName, int *materialCount)
 {
@@ -1867,7 +1922,8 @@         int result = tinyobj_parse_mtl_file(&mats, &count, fileName);
         if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);
 
-        // TODO: Process materials to return
+        materials = MemAlloc(count*sizeof(Material));
+        ProcessMaterialsOBJ(materials, mats, count);
 
         tinyobj_materials_free(mats, count);
     }
@@ -1875,16 +1931,6 @@     TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to load material file", fileName);
 #endif
 
-    // Set materials shader to default (DIFFUSE, SPECULAR, NORMAL)
-    if (materials != NULL)
-    {
-        for (unsigned int i = 0; i < count; i++)
-        {
-            materials[i].shader.id = rlGetShaderIdDefault();
-            materials[i].shader.locs = rlGetShaderLocsDefault();
-        }
-    }
-
     *materialCount = count;
     return materials;
 }
@@ -1910,6 +1956,12 @@     return material;
 }
 
+// Check if a material is ready
+bool IsMaterialReady(Material material)
+{
+    return material.maps != NULL;
+}
+
 // Unload material from memory
 void UnloadMaterial(Material material)
 {
@@ -1972,7 +2024,7 @@         for (int m = 0; m < model.meshCount; m++)
         {
             Mesh mesh = model.meshes[m];
-            
+
             if (mesh.boneIds == NULL || mesh.boneWeights == NULL)
             {
                 TRACELOG(LOG_WARNING, "MODEL: UpdateModelAnimation(): Mesh %i has no connection to bones", m);
@@ -2013,7 +2065,7 @@                 for (int j = 0; j < 4; j++, boneCounter++)
                 {
                     boneWeight = mesh.boneWeights[boneCounter];
-                    
+
                     // Early stop when no transformation will be applied
                     if (boneWeight == 0.0f) continue;
 
@@ -2507,7 +2559,7 @@     return mesh;
 }
 
-// Generate hemi-sphere mesh (half sphere, no bottom cap)
+// Generate hemisphere mesh (half sphere, no bottom cap)
 Mesh GenMeshHemiSphere(float radius, int rings, int slices)
 {
     Mesh mesh = { 0 };
@@ -3190,7 +3242,7 @@         }
     }
 
-    // Move data from mapVertices temp arays to vertices float array
+    // Move data from mapVertices temp arrays to vertices float array
     mesh.vertexCount = vCounter;
     mesh.triangleCount = vCounter/3;
 
@@ -3690,7 +3742,7 @@     // NOTE: We use an additional .01 to fix numerical errors
     collision.normal = Vector3Scale(collision.normal, 2.01f);
     collision.normal = Vector3Divide(collision.normal, Vector3Subtract(box.max, box.min));
-    // The relevant elemets of the vector are now slightly larger than 1.0f (or smaller than -1.0f)
+    // The relevant elements of the vector are now slightly larger than 1.0f (or smaller than -1.0f)
     // and the others are somewhere between -1.0 and 1.0 casting to int is exactly our wanted normal!
     collision.normal.x = (float)((int)collision.normal.x);
     collision.normal.y = (float)((int)collision.normal.y);
@@ -3790,7 +3842,7 @@     // Calculate u parameter and test bound
     u = Vector3DotProduct(tv, p)*invDet;
 
-    // The intersection lies outside of the triangle
+    // The intersection lies outside the triangle
     if ((u < 0.0f) || (u > 1.0f)) return collision;
 
     // Prepare to test v parameter
@@ -3799,7 +3851,7 @@     // Calculate V parameter and test bound
     v = Vector3DotProduct(ray.direction, q)*invDet;
 
-    // The intersection lies outside of the triangle
+    // The intersection lies outside the triangle
     if ((v < 0.0f) || ((u + v) > 1.0f)) return collision;
 
     t = Vector3DotProduct(edge2, q)*invDet;
@@ -3899,12 +3951,12 @@         {
             model.materialCount = materialCount;
             model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
-            TraceLog(LOG_INFO, "MODEL: model has %i material meshes", materialCount);
+            TRACELOG(LOG_INFO, "MODEL: model has %i material meshes", materialCount);
         }
         else
         {
             model.meshCount = 1;
-            TraceLog(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");
+            TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");
         }
 
         model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
@@ -3913,7 +3965,7 @@         // Count the faces for each material
         int *matFaces = RL_CALLOC(model.meshCount, sizeof(int));
 
-        // iff no materials are present use all faces on one mesh
+        // if no materials are present use all faces on one mesh
         if (materialCount > 0)
         {
             for (unsigned int fi = 0; fi < attrib.num_faces; fi++)
@@ -3989,33 +4041,7 @@         }
 
         // Init model materials
-        for (unsigned int m = 0; m < materialCount; m++)
-        {
-            // Init material to default
-            // NOTE: Uses default shader, which only supports MATERIAL_MAP_DIFFUSE
-            model.materials[m] = LoadMaterialDefault();
-
-            // Get default texture, in case no texture is defined
-            // NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
-            model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
-
-            if (materials[m].diffuse_texname != NULL) model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(materials[m].diffuse_texname);  //char *diffuse_texname; // map_Kd
-
-            model.materials[m].maps[MATERIAL_MAP_DIFFUSE].color = (Color){ (unsigned char)(materials[m].diffuse[0]*255.0f), (unsigned char)(materials[m].diffuse[1]*255.0f), (unsigned char)(materials[m].diffuse[2]*255.0f), 255 }; //float diffuse[3];
-            model.materials[m].maps[MATERIAL_MAP_DIFFUSE].value = 0.0f;
-
-            if (materials[m].specular_texname != NULL) model.materials[m].maps[MATERIAL_MAP_SPECULAR].texture = LoadTexture(materials[m].specular_texname);  //char *specular_texname; // map_Ks
-            model.materials[m].maps[MATERIAL_MAP_SPECULAR].color = (Color){ (unsigned char)(materials[m].specular[0]*255.0f), (unsigned char)(materials[m].specular[1]*255.0f), (unsigned char)(materials[m].specular[2]*255.0f), 255 }; //float specular[3];
-            model.materials[m].maps[MATERIAL_MAP_SPECULAR].value = 0.0f;
-
-            if (materials[m].bump_texname != NULL) model.materials[m].maps[MATERIAL_MAP_NORMAL].texture = LoadTexture(materials[m].bump_texname);  //char *bump_texname; // map_bump, bump
-            model.materials[m].maps[MATERIAL_MAP_NORMAL].color = WHITE;
-            model.materials[m].maps[MATERIAL_MAP_NORMAL].value = materials[m].shininess;
-
-            model.materials[m].maps[MATERIAL_MAP_EMISSION].color = (Color){ (unsigned char)(materials[m].emission[0]*255.0f), (unsigned char)(materials[m].emission[1]*255.0f), (unsigned char)(materials[m].emission[2]*255.0f), 255 }; //float emission[3];
-
-            if (materials[m].displacement_texname != NULL) model.materials[m].maps[MATERIAL_MAP_HEIGHT].texture = LoadTexture(materials[m].displacement_texname);  //char *displacement_texname; // disp
-        }
+        ProcessMaterialsOBJ(model.materials, materials, materialCount);
 
         tinyobj_attrib_free(&attrib);
         tinyobj_shapes_free(meshes, meshCount);
@@ -4438,6 +4464,12 @@         unsigned int num_extensions, ofs_extensions;
     } IQMHeader;
 
+    typedef struct IQMJoint {
+        unsigned int name;
+        int parent;
+        float translate[3], rotate[4], scale[3];
+    } IQMJoint;
+
     typedef struct IQMPose {
         int parent;
         unsigned int mask;
@@ -4491,6 +4523,10 @@     //fread(framedata, iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short), 1, iqmFile);
     memcpy(framedata, fileDataPtr + iqmHeader->ofs_frames, iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short));
 
+    // joints
+    IQMJoint *joints = RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint));
+    memcpy(joints, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint));
+
     for (unsigned int a = 0; a < iqmHeader->num_anims; a++)
     {
         animations[a].frameCount = anim[a].num_frames;
@@ -4501,7 +4537,11 @@ 
         for (unsigned int j = 0; j < iqmHeader->num_poses; j++)
         {
-            strcpy(animations[a].bones[j].name, "ANIMJOINTNAME");
+            // If animations and skeleton are in the same file, copy bone names to anim
+            if (iqmHeader->num_joints > 0)
+                memcpy(animations[a].bones[j].name, fileDataPtr + iqmHeader->ofs_text + joints[j].name, BONE_NAME_LENGTH*sizeof(char));
+            else
+                strcpy(animations[a].bones[j].name, "ANIMJOINTNAME"); // default bone name otherwise
             animations[a].bones[j].parent = poses[j].parent;
         }
 
@@ -4615,6 +4655,7 @@ 
     RL_FREE(fileData);
 
+    RL_FREE(joints);
     RL_FREE(framedata);
     RL_FREE(poses);
     RL_FREE(anim);
@@ -4630,7 +4671,7 @@ {
     Image image = { 0 };
 
-    if (cgltfImage->uri != NULL)     // Check if image data is provided as a uri (base64 or path)
+    if (cgltfImage->uri != NULL)     // Check if image data is provided as an uri (base64 or path)
     {
         if ((strlen(cgltfImage->uri) > 5) &&
             (cgltfImage->uri[0] == 'd') &&
@@ -4658,7 +4699,7 @@                 if (result == cgltf_result_success)
                 {
                     image = LoadImageFromMemory(".png", (unsigned char *)data, outSize);
-                    cgltf_free((cgltf_data*)data);
+                    MemFree(data);
                 }
             }
         }
@@ -4697,7 +4738,7 @@ // Load bone info from GLTF skin data
 static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, int *boneCount)
 {
-    *boneCount = skin.joints_count;
+    *boneCount = (int)skin.joints_count;
     BoneInfo *bones = RL_MALLOC(skin.joints_count*sizeof(BoneInfo));
 
     for (unsigned int i = 0; i < skin.joints_count; i++)
@@ -4707,7 +4748,7 @@ 
         // Find parent bone index
         unsigned int parentIndex = -1;
-        
+
         for (unsigned int j = 0; j < skin.joints_count; j++)
         {
             if (skin.joints[j] == node.parent)
@@ -4918,7 +4959,7 @@ 
                 for (unsigned int j = 0; j < data->meshes[i].primitives[p].attributes_count; j++)
                 {
-                    // Check the different attributes for every pimitive
+                    // Check the different attributes for every primitive
                     if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_position)      // POSITION
                     {
                         cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data;
@@ -5069,7 +5110,7 @@                 {
                     // The primitive actually keeps the pointer to the corresponding material,
                     // raylib instead assigns to the mesh the by its index, as loaded in model.materials array
-                    // To get the index, we check if material pointers match and we assign the corresponding index,
+                    // To get the index, we check if material pointers match, and we assign the corresponding index,
                     // skipping index 0, the default material
                     if (&data->materials[m] == data->meshes[i].primitives[p].material)
                     {
@@ -5097,7 +5138,7 @@             model.bones = LoadBoneInfoGLTF(skin, &model.boneCount);
             model.bindPose = RL_MALLOC(model.boneCount*sizeof(Transform));
 
-            for (unsigned int i = 0; i < model.boneCount; i++)
+            for (int i = 0; i < model.boneCount; i++)
             {
                 cgltf_node node = *skin.joints[i];
                 model.bindPose[i].translation.x = node.translation[0];
@@ -5197,12 +5238,12 @@     float tstart = 0.0f;
     float tend = 0.0f;
     int keyframe = 0;       // Defaults to first pose
-    
+
     for (int i = 0; i < input->count - 1; i++)
     {
         cgltf_bool r1 = cgltf_accessor_read_float(input, i, &tstart, 1);
         if (!r1) return false;
-        
+
         cgltf_bool r2 = cgltf_accessor_read_float(input, i + 1, &tend, 1);
         if (!r2) return false;
 
@@ -5237,11 +5278,11 @@         cgltf_accessor_read_float(output, keyframe+1, tmp, 4);
         Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};
         Vector4 *r = data;
-        
+
         // Only v4 is for rotations, so we know it's a quat
         *r = QuaternionSlerp(v1, v2, t);
     }
-    
+
     return true;
 }
 
@@ -5254,12 +5295,12 @@     unsigned char *fileData = LoadFileData(fileName, &dataSize);
 
     ModelAnimation *animations = NULL;
-    
+
     // glTF data loading
     cgltf_options options = { 0 };
     cgltf_data *data = NULL;
     cgltf_result result = cgltf_parse(&options, fileData, dataSize, &data);
-    
+
     if (result != cgltf_result_success)
     {
         TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load glTF data", fileName);
@@ -5275,9 +5316,9 @@         if (data->skins_count == 1)
         {
             cgltf_skin skin = data->skins[0];
-            *animCount = data->animations_count;
+            *animCount = (int)data->animations_count;
             animations = RL_MALLOC(data->animations_count*sizeof(ModelAnimation));
-            
+
             for (unsigned int i = 0; i < data->animations_count; i++)
             {
                 animations[i].bones = LoadBoneInfoGLTF(skin, &animations[i].boneCount);
@@ -5292,12 +5333,12 @@ 
                 struct Channels *boneChannels = RL_CALLOC(animations[i].boneCount, sizeof(struct Channels));
                 float animDuration = 0.0f;
-                
+
                 for (unsigned int j = 0; j < animData.channels_count; j++)
                 {
                     cgltf_animation_channel channel = animData.channels[j];
                     int boneIndex = -1;
-                    
+
                     for (unsigned int k = 0; k < skin.joints_count; k++)
                     {
                         if (animData.channels[j].target_node == skin.joints[k])
@@ -5331,12 +5372,12 @@                         {
                             TRACELOG(LOG_WARNING, "MODEL: [%s] Unsupported target_path on channel %d's sampler for animation %d. Skipping.", fileName, j, i);
                         }
-                    } 
+                    }
                     else TRACELOG(LOG_WARNING, "MODEL: [%s] Only linear interpolation curves are supported for GLTF animation.", fileName);
 
                     float t = 0.0f;
                     cgltf_bool r = cgltf_accessor_read_float(channel.sampler->input, channel.sampler->input->count - 1, &t, 1);
-                    
+
                     if (!r)
                     {
                         TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load input time", fileName);
@@ -5349,17 +5390,17 @@                 animations[i].frameCount = (int)(animDuration*1000.0f/GLTF_ANIMDELAY);
                 animations[i].framePoses = RL_MALLOC(animations[i].frameCount*sizeof(Transform *));
 
-                for (unsigned int j = 0; j < animations[i].frameCount; j++)
+                for (int j = 0; j < animations[i].frameCount; j++)
                 {
                     animations[i].framePoses[j] = RL_MALLOC(animations[i].boneCount*sizeof(Transform));
                     float time = ((float) j*GLTF_ANIMDELAY)/1000.0f;
-                    
-                    for (unsigned int k = 0; k < animations[i].boneCount; k++)
+
+                    for (int k = 0; k < animations[i].boneCount; k++)
                     {
                         Vector3 translation = {0, 0, 0};
                         Quaternion rotation = {0, 0, 0, 1};
                         Vector3 scale = {1, 1, 1};
-                        
+
                         if (boneChannels[k].translate)
                         {
                             if (!GetPoseAtTimeGLTF(boneChannels[k].translate->sampler->input, boneChannels[k].translate->sampler->output, time, &translation))
@@ -5397,7 +5438,7 @@                 TRACELOG(LOG_INFO, "MODEL: [%s] Loaded animation: %s (%d frames, %fs)", fileName, animData.name, animations[i].frameCount, animDuration);
                 RL_FREE(boneChannels);
             }
-        } 
+        }
         else TRACELOG(LOG_ERROR, "MODEL: [%s] expected exactly one skin to load animation data from, but found %i", fileName, data->skins_count);
 
         cgltf_free(data);
@@ -5567,12 +5608,12 @@         // Map no material to index 0 with default shader, everything else materialid + 1
         model.materials[0] = LoadMaterialDefault();
 
-        for (i = l = 0, k = -1; i < m3d->numface; i++, l++)
+        for (i = l = 0, k = -1; i < (int)m3d->numface; i++, l++)
         {
             // Materials are grouped together
             if (mi != m3d->face[i].materialid)
             {
-                // there should be only one material switch per material kind, but be bulletproof for unoptimal model files
+                // there should be only one material switch per material kind, but be bulletproof for non-optimal model files
                 if (k + 1 >= model.meshCount)
                 {
                     model.meshCount++;
@@ -5584,21 +5625,18 @@                 k++;
                 mi = m3d->face[i].materialid;
 
-                for (j = i, l = 0; (j < m3d->numface) && (mi == m3d->face[j].materialid); j++, l++);
+                for (j = i, l = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++);
 
                 model.meshes[k].vertexCount = l*3;
                 model.meshes[k].triangleCount = l;
                 model.meshes[k].vertices = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
                 model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float));
                 model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
-                
-                // without material, we rely on vertex colors
-                if (mi == M3D_UNDEF && model.meshes[k].colors == NULL)
-                {
-                    model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
-                    for (j = 0; j < model.meshes[k].vertexCount*4; j += 4) memcpy(&model.meshes[k].colors[j], &WHITE, 4);
-                }
-                
+
+                // If no map is provided, we allocate storage for vertex colors
+                // M3D specs only consider vertex colors if no material is provided
+                if (mi != M3D_UNDEF) model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
+
                 if (m3d->numbone && m3d->numskin)
                 {
                     model.meshes[k].boneIds = (unsigned char *)RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
@@ -5606,41 +5644,41 @@                     model.meshes[k].animVertices = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
                     model.meshes[k].animNormals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
                 }
-                
+
                 model.meshMaterial[k] = mi + 1;
                 l = 0;
             }
 
             // Process meshes per material, add triangles
-            model.meshes[k].vertices[l * 9 + 0] = m3d->vertex[m3d->face[i].vertex[0]].x*m3d->scale;
-            model.meshes[k].vertices[l * 9 + 1] = m3d->vertex[m3d->face[i].vertex[0]].y*m3d->scale;
-            model.meshes[k].vertices[l * 9 + 2] = m3d->vertex[m3d->face[i].vertex[0]].z*m3d->scale;
-            model.meshes[k].vertices[l * 9 + 3] = m3d->vertex[m3d->face[i].vertex[1]].x*m3d->scale;
-            model.meshes[k].vertices[l * 9 + 4] = m3d->vertex[m3d->face[i].vertex[1]].y*m3d->scale;
-            model.meshes[k].vertices[l * 9 + 5] = m3d->vertex[m3d->face[i].vertex[1]].z*m3d->scale;
-            model.meshes[k].vertices[l * 9 + 6] = m3d->vertex[m3d->face[i].vertex[2]].x*m3d->scale;
-            model.meshes[k].vertices[l * 9 + 7] = m3d->vertex[m3d->face[i].vertex[2]].y*m3d->scale;
-            model.meshes[k].vertices[l * 9 + 8] = m3d->vertex[m3d->face[i].vertex[2]].z*m3d->scale;
+            model.meshes[k].vertices[l*9 + 0] = m3d->vertex[m3d->face[i].vertex[0]].x*m3d->scale;
+            model.meshes[k].vertices[l*9 + 1] = m3d->vertex[m3d->face[i].vertex[0]].y*m3d->scale;
+            model.meshes[k].vertices[l*9 + 2] = m3d->vertex[m3d->face[i].vertex[0]].z*m3d->scale;
+            model.meshes[k].vertices[l*9 + 3] = m3d->vertex[m3d->face[i].vertex[1]].x*m3d->scale;
+            model.meshes[k].vertices[l*9 + 4] = m3d->vertex[m3d->face[i].vertex[1]].y*m3d->scale;
+            model.meshes[k].vertices[l*9 + 5] = m3d->vertex[m3d->face[i].vertex[1]].z*m3d->scale;
+            model.meshes[k].vertices[l*9 + 6] = m3d->vertex[m3d->face[i].vertex[2]].x*m3d->scale;
+            model.meshes[k].vertices[l*9 + 7] = m3d->vertex[m3d->face[i].vertex[2]].y*m3d->scale;
+            model.meshes[k].vertices[l*9 + 8] = m3d->vertex[m3d->face[i].vertex[2]].z*m3d->scale;
 
-            if (mi == M3D_UNDEF)
+            // without vertex color (full transparency), we use the default color
+            if (model.meshes[k].colors != NULL)
             {
-                // without vertex color (full transparency), we use the default color
                 if (m3d->vertex[m3d->face[i].vertex[0]].color & 0xFF000000)
-                    memcpy(&model.meshes[k].colors[l * 12 + 0], &m3d->vertex[m3d->face[i].vertex[0]].color, 4);
+                    memcpy(&model.meshes[k].colors[l*12 + 0], &m3d->vertex[m3d->face[i].vertex[0]].color, 4);
                 if (m3d->vertex[m3d->face[i].vertex[1]].color & 0xFF000000)
-                    memcpy(&model.meshes[k].colors[l * 12 + 4], &m3d->vertex[m3d->face[i].vertex[1]].color, 4);
+                    memcpy(&model.meshes[k].colors[l*12 + 4], &m3d->vertex[m3d->face[i].vertex[1]].color, 4);
                 if (m3d->vertex[m3d->face[i].vertex[2]].color & 0xFF000000)
-                    memcpy(&model.meshes[k].colors[l * 12 + 8], &m3d->vertex[m3d->face[i].vertex[2]].color, 4);
+                    memcpy(&model.meshes[k].colors[l*12 + 8], &m3d->vertex[m3d->face[i].vertex[2]].color, 4);
             }
 
             if (m3d->face[i].texcoord[0] != M3D_UNDEF)
             {
                 model.meshes[k].texcoords[l*6 + 0] = m3d->tmap[m3d->face[i].texcoord[0]].u;
-                model.meshes[k].texcoords[l*6 + 1] = 1.0 - m3d->tmap[m3d->face[i].texcoord[0]].v;
+                model.meshes[k].texcoords[l*6 + 1] = 1.0f - m3d->tmap[m3d->face[i].texcoord[0]].v;
                 model.meshes[k].texcoords[l*6 + 2] = m3d->tmap[m3d->face[i].texcoord[1]].u;
-                model.meshes[k].texcoords[l*6 + 3] = 1.0 - m3d->tmap[m3d->face[i].texcoord[1]].v;
+                model.meshes[k].texcoords[l*6 + 3] = 1.0f - m3d->tmap[m3d->face[i].texcoord[1]].v;
                 model.meshes[k].texcoords[l*6 + 4] = m3d->tmap[m3d->face[i].texcoord[2]].u;
-                model.meshes[k].texcoords[l*6 + 5] = 1.0 - m3d->tmap[m3d->face[i].texcoord[2]].v;
+                model.meshes[k].texcoords[l*6 + 5] = 1.0f - m3d->tmap[m3d->face[i].texcoord[2]].v;
             }
 
             if (m3d->face[i].normal[0] != M3D_UNDEF)
@@ -5664,7 +5702,7 @@                     int skinid = m3d->vertex[m3d->face[i].vertex[n]].skinid;
 
                     // Check if there is a skin for this mesh, should be, just failsafe
-                    if (skinid != M3D_UNDEF && skinid < m3d->numskin)
+                    if (skinid != M3D_UNDEF && skinid < (int)m3d->numskin)
                     {
                         for (j = 0; j < 4; j++)
                         {
@@ -5684,7 +5722,7 @@         }
 
         // Load materials
-        for (i = 0; i < m3d->nummaterial; i++)
+        for (i = 0; i < (int)m3d->nummaterial; i++)
         {
             model.materials[i + 1] = LoadMaterialDefault();
 
@@ -5761,7 +5799,7 @@             model.bones = RL_CALLOC(model.boneCount, sizeof(BoneInfo));
             model.bindPose = RL_CALLOC(model.boneCount, sizeof(Transform));
 
-            for (i = 0; i < m3d->numbone; i++)
+            for (i = 0; i < (int)m3d->numbone; i++)
             {
                 model.bones[i].parent = m3d->bone[i].parent;
                 strncpy(model.bones[i].name, m3d->bone[i].name, sizeof(model.bones[i].name));
@@ -5772,7 +5810,7 @@                 model.bindPose[i].rotation.y = m3d->vertex[m3d->bone[i].ori].y;
                 model.bindPose[i].rotation.z = m3d->vertex[m3d->bone[i].ori].z;
                 model.bindPose[i].rotation.w = m3d->vertex[m3d->bone[i].ori].w;
-                
+
                 // TODO: if the orientation quaternion not normalized, then that's encoding scaling
                 model.bindPose[i].rotation = QuaternionNormalize(model.bindPose[i].rotation);
                 model.bindPose[i].scale.x = model.bindPose[i].scale.y = model.bindPose[i].scale.z = 1.0f;
@@ -5801,7 +5839,7 @@         }
 
         // Load bone-pose default mesh into animation vertices. These will be updated when UpdateModelAnimation gets
-        // called, but not before, however DrawMesh uses these if they exists (so not good if they are left empty).
+        // called, but not before, however DrawMesh uses these if they exist (so not good if they are left empty).
         if (m3d->numbone && m3d->numskin)
         {
             for(i = 0; i < model.meshCount; i++)
@@ -5864,7 +5902,7 @@             // strncpy(animations[a].name, m3d->action[a].name, sizeof(animations[a].name));
             TRACELOG(LOG_INFO, "MODEL: [%s] animation #%i: %i msec, %i frames", fileName, a, m3d->action[a].durationmsec, animations[a].frameCount);
 
-            for (i = 0; i < m3d->numbone; i++)
+            for (i = 0; i < (int)m3d->numbone; i++)
             {
                 animations[a].bones[i].parent = m3d->bone[i].parent;
                 strncpy(animations[a].bones[i].name, m3d->bone[i].name, sizeof(animations[a].bones[i].name));
@@ -5881,10 +5919,10 @@                 animations[a].framePoses[i] = RL_MALLOC((m3d->numbone + 1)*sizeof(Transform));
 
                 m3db_t *pose = m3d_pose(m3d, a, i*M3D_ANIMDELAY);
-                
+
                 if (pose != NULL)
                 {
-                    for (j = 0; j < m3d->numbone; j++)
+                    for (j = 0; j < (int)m3d->numbone; j++)
                     {
                         animations[a].framePoses[i][j].translation.x = m3d->vertex[pose[j].pos].x*m3d->scale;
                         animations[a].framePoses[i][j].translation.y = m3d->vertex[pose[j].pos].y*m3d->scale;
raylib/src/rshapes.c view
@@ -105,7 +105,7 @@ // Draw a pixel
 void DrawPixel(int posX, int posY, Color color)
 {
-  DrawPixelV((Vector2){ posX, posY }, color);
+  DrawPixelV((Vector2){ (float)posX, (float)posY }, color);
 }
 
 // Draw a pixel (Vector version)
@@ -156,8 +156,8 @@ {
     rlBegin(RL_LINES);
         rlColor4ub(color.r, color.g, color.b, color.a);
-        rlVertex2f(startPosX, startPosY);
-        rlVertex2f(endPosX, endPosY);
+        rlVertex2f((float)startPosX, (float)startPosY);
+        rlVertex2f((float)endPosX, (float)endPosY);
     rlEnd();
 }
 
@@ -209,7 +209,7 @@ 
         float dy = current.y-previous.y;
         float dx = current.x-previous.x;
-        float size = 0.5*thick/sqrt(dx*dx+dy*dy);
+        float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
 
         if (i==1)
         {
@@ -254,7 +254,7 @@ 
         float dy = current.y-previous.y;
         float dx = current.x-previous.x;
-        float size = 0.5*thick/sqrt(dx*dx+dy*dy);
+        float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
 
         if (i==1)
         {
@@ -299,8 +299,8 @@ 
         float dy = current.y-previous.y;
         float dx = current.x-previous.x;
-        float size = 0.5*thick/sqrt(dx*dx+dy*dy);
-        
+        float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
+
         if (i==1)
         {
             points[0].x = previous.x+dy*size;
@@ -978,7 +978,7 @@     rlSetTexture(texShapes.id);
 
     rlBegin(RL_QUADS);
-        // Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
+        // Draw all the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
         for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
         {
             float angle = angles[k];
@@ -1207,7 +1207,7 @@ 
         rlBegin(RL_QUADS);
 
-            // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
+            // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
             for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
             {
                 float angle = angles[k];
@@ -1342,7 +1342,7 @@         // Use LINES to draw the outline
         rlBegin(RL_LINES);
 
-            // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
+            // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
             for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
             {
                 float angle = angles[k];
@@ -1639,19 +1639,19 @@ bool CheckCollisionPointPoly(Vector2 point, Vector2 *points, int pointCount)
 {
     bool collision = false;
-    
+
     if (pointCount > 2)
     {
         for (int i = 0; i < pointCount - 1; i++)
         {
             Vector2 vc = points[i];
             Vector2 vn = points[i + 1];
-            
+
             if ((((vc.y >= point.y) && (vn.y < point.y)) || ((vc.y < point.y) && (vn.y >= point.y))) &&
                  (point.x < ((vn.x - vc.x)*(point.y - vc.y)/(vn.y - vc.y) + vc.x))) collision = !collision;
         }
     }
-    
+
     return collision;
 }
 
raylib/src/rtext.c view
@@ -65,7 +65,7 @@ #include <stdio.h>          // Required for: vsprintf()
 #include <string.h>         // Required for: strcmp(), strstr(), strcpy(), strncpy() [Used in TextReplace()], sscanf() [Used in LoadBMFont()]
 #include <stdarg.h>         // Required for: va_list, va_start(), vsprintf(), va_end() [Used in TextFormat()]
-#include <ctype.h>          // Requried for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
+#include <ctype.h>          // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
 
 #if defined(SUPPORT_FILEFORMAT_TTF)
     #define STB_RECT_PACK_IMPLEMENTATION
@@ -336,7 +336,7 @@     }
     else
     {
-        SetTextureFilter(font.texture, TEXTURE_FILTER_POINT);    // By default we set point filter (best performance)
+        SetTextureFilter(font.texture, TEXTURE_FILTER_POINT);    // By default, we set point filter (the best performance)
         TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS);
     }
 
@@ -535,6 +535,12 @@     return font;
 }
 
+// Check if a font is ready
+bool IsFontReady(Font font)
+{
+    return font.glyphs != NULL;
+}
+
 // Load font data for further use
 // NOTE: Requires TTF font memory data and can generate SDF data
 GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type)
@@ -578,7 +584,7 @@             glyphCount = (glyphCount > 0)? glyphCount : 95;
 
             // Fill fontChars in case not provided externally
-            // NOTE: By default we fill glyphCount consecutevely, starting at 32 (Space)
+            // NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
 
             if (fontChars == NULL)
             {
@@ -641,7 +647,7 @@                     }
                 }
 
-                // Get bounding box for character (may be offset to account for chars that dip above or below the line)
+                // Get bounding box for character (maybe offset to account for chars that dip above or below the line)
                 /*
                 int chX1, chY1, chX2, chY2;
                 stbtt_GetCodepointBitmapBox(&fontInfo, ch, scaleFactor, scaleFactor, &chX1, &chY1, &chX2, &chY2);
@@ -669,7 +675,7 @@ 
     if (chars == NULL)
     {
-        TraceLog(LOG_WARNING, "FONT: Provided chars info not valid, returning empty image atlas");
+        TRACELOG(LOG_WARNING, "FONT: Provided chars info not valid, returning empty image atlas");
         return atlas;
     }
 
@@ -771,7 +777,7 @@ 
         for (int i = 0; i < glyphCount; i++)
         {
-            // It return char rectangles in atlas
+            // It returns char rectangles in atlas
             recs[i].x = rects[i].x + (float)padding;
             recs[i].y = rects[i].y + (float)padding;
             recs[i].width = (float)chars[i].image.width;
@@ -1034,7 +1040,7 @@ 
     int size = TextLength(text);    // Total size in bytes of the text, scanned by codepoints in loop
 
-    int textOffsetY = 0;            // Offset between lines (on line break '\n')
+    int textOffsetY = 0;            // Offset between lines (on linebreak '\n')
     float textOffsetX = 0.0f;       // Offset X to next character to draw
 
     float scaleFactor = fontSize/font.baseSize;         // Character quad scaling factor
@@ -1047,7 +1053,7 @@         int index = GetGlyphIndex(font, codepoint);
 
         // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
-        // but we need to draw all of the bad bytes using the '?' symbol moving one byte
+        // but we need to draw all the bad bytes using the '?' symbol moving one byte
         if (codepoint == 0x3f) codepointByteCount = 1;
 
         if (codepoint == '\n')
@@ -1113,7 +1119,7 @@ // Draw multiple character (codepoints)
 void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint)
 {
-    int textOffsetY = 0;            // Offset between lines (on line break '\n')
+    int textOffsetY = 0;            // Offset between lines (on linebreak '\n')
     float textOffsetX = 0.0f;       // Offset X to next character to draw
 
     float scaleFactor = fontSize/font.baseSize;         // Character quad scaling factor
@@ -1189,7 +1195,7 @@         index = GetGlyphIndex(font, letter);
 
         // NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
-        // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set next = 1
+        // but we need to draw all the bad bytes using the '?' symbol so to not skip any we set next = 1
         if (letter == 0x3f) next = 1;
         i += next - 1;
 
@@ -1404,7 +1410,7 @@     char *insertPoint = NULL;   // Next insert point
     char *temp = NULL;          // Temp pointer
     int replaceLen = 0;         // Replace string length of (the string to remove)
-    int byLen = 0;              // Replacement length (the string to replace replace by)
+    int byLen = 0;              // Replacement length (the string to replace by)
     int lastReplacePos = 0;     // Distance between replace and end of last replace
     int count = 0;              // Number of replacements
 
@@ -1750,7 +1756,7 @@ #endif      // SUPPORT_TEXT_MANIPULATION
 
 // Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found
-// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
+// When an invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
 // Total number of bytes processed are returned as a parameter
 // NOTE: The standard says U+FFFD should be returned in case of errors
 // but that character is not supported by the default font in raylib
@@ -1863,7 +1869,7 @@     const char *ptr = text;
     int codepoint = 0x3f;       // Codepoint (defaults to '?')
     *codepointSize = 0;
-    
+
     // Get current codepoint and bytes processed
     if (0xf0 == (0xf8 & ptr[0]))
     {
@@ -1876,20 +1882,20 @@         // 3 byte UTF-8 codepoint */
         codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
         *codepointSize = 3;
-    } 
+    }
     else if (0xc0 == (0xe0 & ptr[0]))
     {
         // 2 byte UTF-8 codepoint
         codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
         *codepointSize = 2;
-    } 
+    }
     else
     {
         // 1 byte UTF-8 codepoint
         codepoint = ptr[0];
         *codepointSize = 1;
     }
-    
+
     return codepoint;
 }
 
@@ -1904,7 +1910,7 @@     // Move to previous codepoint
     do ptr--;
     while (((0x80 & ptr[0]) != 0) && ((0xc0 & ptr[0]) ==  0x80));
-    
+
     codepoint = GetCodepointNext(ptr, &cpSize);
 
     if (codepoint != 0) *codepointSize = cpSize;
raylib/src/rtextures.c view
@@ -163,10 +163,19 @@     #define QOI_MALLOC RL_MALLOC
     #define QOI_FREE RL_FREE
 
+#if defined(_MSC_VER ) // qoi has warnings on windows, so disable them just for this file
+#pragma warning( push )
+#pragma warning( disable : 4267)
+#endif
     #define QOI_IMPLEMENTATION
     #include "external/qoi.h"
+
+#if defined(_MSC_VER )
+#pragma warning( pop )
 #endif
 
+#endif
+
 #if defined(SUPPORT_IMAGE_EXPORT)
     #define STBIW_MALLOC RL_MALLOC
     #define STBIW_FREE RL_FREE
@@ -493,6 +502,12 @@     return image;
 }
 
+// Check if an image is ready
+bool IsImageReady(Image image)
+{
+    return image.data != NULL && image.width > 0 && image.height > 0 && image.format > 0;
+}
+
 // Unload image from CPU memory (RAM)
 void UnloadImage(Image image)
 {
@@ -736,7 +751,7 @@             float factor = (dist - radius*density)/(radius*(1.0f - density));
 
             factor = (float)fmax(factor, 0.0f);
-            factor = (float)fmin(factor, 1.f); // dist can be bigger than radius so we have to check
+            factor = (float)fmin(factor, 1.f); // dist can be bigger than radius, so we have to check
 
             pixels[y*width + x].r = (int)((float)outer.r*factor + (float)inner.r*(1.0f - factor));
             pixels[y*width + x].g = (int)((float)outer.g*factor + (float)inner.g*(1.0f - factor));
@@ -883,7 +898,7 @@                 }
             }
 
-            // I made this up but it seems to give good results at all tile sizes
+            // I made this up, but it seems to give good results at all tile sizes
             int intensity = (int)(minDistance*256.0f/tileSize);
             if (intensity > 255) intensity = 255;
 
@@ -908,7 +923,7 @@ Image GenImageText(int width, int height, const char *text)
 {
     Image image = { 0 };
-    
+
     int textLength = TextLength(text);
     int imageViewSize = width*height;
 
@@ -1161,7 +1176,7 @@                 } break;
                 case PIXELFORMAT_UNCOMPRESSED_R32:
                 {
-                    // WARNING: Image is converted to GRAYSCALE eqeuivalent 32bit
+                    // WARNING: Image is converted to GRAYSCALE equivalent 32bit
 
                     image->data = (float *)RL_MALLOC(image->width*image->height*sizeof(float));
 
@@ -1199,7 +1214,7 @@             RL_FREE(pixels);
             pixels = NULL;
 
-            // In case original image had mipmaps, generate mipmaps for formated image
+            // In case original image had mipmaps, generate mipmaps for formatted image
             // NOTE: Original mipmaps are replaced by new ones, if custom mipmaps were used, they are lost
             if (image->mipmaps > 1)
             {
@@ -1254,7 +1269,7 @@     int size = (int)strlen(text);   // Get size in bytes of text
 
     int textOffsetX = 0;            // Image drawing position X
-    int textOffsetY = 0;            // Offset between lines (on line break '\n')
+    int textOffsetY = 0;            // Offset between lines (on linebreak '\n')
 
     // NOTE: Text image is generated at font base size, later scaled to desired font size
     Vector2 imSize = MeasureTextEx(font, text, (float)font.baseSize, spacing);  // WARNING: Module required: rtext
@@ -1271,7 +1286,7 @@         int index = GetGlyphIndex(font, codepoint);                         // WARNING: Module required: rtext
 
         // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
-        // but we need to draw all of the bad bytes using the '?' symbol moving one byte
+        // but we need to draw all the bad bytes using the '?' symbol moving one byte
         if (codepoint == 0x3f) codepointByteCount = 1;
 
         if (codepoint == '\n')
@@ -1316,7 +1331,7 @@ }
 
 // Crop image depending on alpha value
-// NOTE: Threshold is defined as a percentatge: 0.0f -> 1.0f
+// NOTE: Threshold is defined as a percentage: 0.0f -> 1.0f
 void ImageAlphaCrop(Image *image, float threshold)
 {
     // Security check to avoid program crash
@@ -1536,7 +1551,7 @@             float avgAlpha = 0.0f;
             int convolutionSize = blurSize+1;
 
-            for (int i = 0; i < blurSize+1; i++) 
+            for (int i = 0; i < blurSize+1; i++)
             {
                 avgR += pixelsCopy1[row*image->width + i].x;
                 avgG += pixelsCopy1[row*image->width + i].y;
@@ -1585,7 +1600,7 @@             float avgAlpha = 0.0f;
             int convolutionSize = blurSize+1;
 
-            for (int i = 0; i < blurSize+1; i++) 
+            for (int i = 0; i < blurSize+1; i++)
             {
                 avgR += pixelsCopy2[i*image->width + col].x;
                 avgG += pixelsCopy2[i*image->width + col].y;
@@ -1696,7 +1711,7 @@         Color *pixels = LoadImageColors(*image);
         Color *output = (Color *)RL_MALLOC(newWidth*newHeight*sizeof(Color));
 
-        // NOTE: Color data is casted to (unsigned char *), there shouldn't been any problem...
+        // NOTE: Color data is cast to (unsigned char *), there shouldn't been any problem...
         stbir_resize_uint8((unsigned char *)pixels, image->width, image->height, 0, (unsigned char *)output, newWidth, newHeight, 0, 4);
 
         int format = image->format;
@@ -1876,7 +1891,7 @@ }
 
 // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
-// NOTE: In case selected bpp do not represent an known 16bit format,
+// NOTE: In case selected bpp do not represent a known 16bit format,
 // dithered data is stored in the LSB part of the unsigned short
 void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp)
 {
@@ -2516,7 +2531,7 @@ }
 
 // Get image alpha border rectangle
-// NOTE: Threshold is defined as a percentatge: 0.0f -> 1.0f
+// NOTE: Threshold is defined as a percentage: 0.0f -> 1.0f
 Rectangle GetImageAlphaBorder(Image image, float threshold)
 {
     Rectangle crop = { 0 };
@@ -2916,7 +2931,7 @@         {
             y--;
             decesionParameter = decesionParameter + 4*(x - y) + 10;
-        } 
+        }
         else decesionParameter = decesionParameter + 4*x + 6;
     }
 }
@@ -3034,7 +3049,7 @@         if ((srcRec.y + srcRec.height) > src.height) srcRec.height = src.height - srcRec.y;
 
         // Check if source rectangle needs to be resized to destination rectangle
-        // In that case, we make a copy of source and we apply all required transform
+        // In that case, we make a copy of source, and we apply all required transform
         if (((int)srcRec.width != (int)dstRec.width) || ((int)srcRec.height != (int)dstRec.height))
         {
             srcMod = ImageFromImage(src, srcRec);   // Create image from another image
@@ -3258,7 +3273,7 @@             faces = GenImageColor(size, size*6, MAGENTA);
             ImageFormat(&faces, image.format);
 
-            // NOTE: Image formating does not work with compressed textures
+            // NOTE: Image formatting does not work with compressed textures
 
             for (int i = 0; i < 6; i++) ImageDraw(&faces, image, faceRecs[i], (Rectangle){ 0, (float)size*i, (float)size, (float)size }, WHITE);
         }
@@ -3315,6 +3330,12 @@     return target;
 }
 
+// Check if a texture is ready
+bool IsTextureReady(Texture2D texture)
+{
+    return texture.id > 0 && texture.width > 0 && texture.height > 0 && texture.format > 0;
+}
+
 // Unload texture from GPU memory (VRAM)
 void UnloadTexture(Texture2D texture)
 {
@@ -3326,6 +3347,12 @@     }
 }
 
+// Check if a render texture is ready
+bool IsRenderTextureReady(RenderTexture2D target)
+{
+    return target.id > 0 && IsTextureReady(target.depth) && IsTextureReady(target.texture);
+}
+
 // Unload render texture from GPU memory (VRAM)
 void UnloadRenderTexture(RenderTexture2D target)
 {
@@ -3579,7 +3606,7 @@         // NOTE: Vertex position can be transformed using matrices
         // but the process is way more costly than just calculating
         // the vertex positions manually, like done above.
-        // I leave here the old implementation for educational pourposes,
+        // I leave here the old implementation for educational purposes,
         // just in case someone wants to do some performance test
         /*
         rlSetTexture(texture.id);
@@ -3971,10 +3998,10 @@ Color ColorBrightness(Color color, float factor)
 {
     Color result = color;
-    
+
     if (factor > 1.0f) factor = 1.0f;
     else if (factor < -1.0f) factor = -1.0f;
-    
+
     float red = (float)color.r;
     float green = (float)color.g;
     float blue = (float)color.b;
@@ -3992,7 +4019,7 @@         green = (255 - green)*factor + green;
         blue = (255 - blue)*factor + blue;
     }
-    
+
     result.r = (unsigned char)red;
     result.g = (unsigned char)green;
     result.b = (unsigned char)blue;
@@ -4005,7 +4032,7 @@ Color ColorContrast(Color color, float contrast)
 {
     Color result = color;
-    
+
     if (contrast < -1.0f) contrast = -1.0f;
     else if (contrast > 1.0f) contrast = 1.0f;
 
raylib/src/utils.c view
@@ -63,10 +63,10 @@ static int logTypeLevel = LOG_INFO;                 // Minimum log type level
 
 static TraceLogCallback traceLog = NULL;            // TraceLog callback function pointer
-static LoadFileDataCallback loadFileData = NULL;    // LoadFileData callback funtion pointer
-static SaveFileDataCallback saveFileData = NULL;    // SaveFileText callback funtion pointer
-static LoadFileTextCallback loadFileText = NULL;    // LoadFileText callback funtion pointer
-static SaveFileTextCallback saveFileText = NULL;    // SaveFileText callback funtion pointer
+static LoadFileDataCallback loadFileData = NULL;    // LoadFileData callback function pointer
+static SaveFileDataCallback saveFileData = NULL;    // SaveFileText callback function pointer
+static LoadFileTextCallback loadFileText = NULL;    // LoadFileText callback function pointer
+static SaveFileTextCallback saveFileText = NULL;    // SaveFileText callback function pointer
 
 //----------------------------------------------------------------------------------
 // Functions to set internal callbacks
− src/Raylib.hs
@@ -1,5369 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}
-
-{-# OPTIONS -Wall #-}
-
-module Raylib where
-
--- Haskell bindings to raylib
-
-import Data.List (genericLength)
-import Foreign
-  ( FunPtr,
-    Ptr,
-    Storable (peek, sizeOf),
-    castPtr,
-    fromBool,
-    peekArray,
-    toBool,
-    with,
-    withArray,
-    withArrayLen,
-  )
-import Foreign.C
-  ( CBool (..),
-    CChar (..),
-    CDouble (..),
-    CFloat (..),
-    CInt (..),
-    CLong (..),
-    CString,
-    CUChar,
-    CUInt (..),
-    peekCString,
-    withCString,
-  )
-import GHC.IO (unsafePerformIO)
-import Raylib.Types
-  ( AudioStream,
-    BoundingBox,
-    Camera2D,
-    Camera3D,
-    Color,
-    FilePathList,
-    Font,
-    GlyphInfo,
-    Image (image'height, image'width),
-    Material,
-    Matrix,
-    Mesh,
-    Model,
-    ModelAnimation,
-    Music,
-    NPatchInfo,
-    Ray,
-    RayCollision,
-    Rectangle,
-    RenderTexture,
-    Shader,
-    Sound,
-    Texture,
-    Vector2 (Vector2),
-    Vector3,
-    Vector4,
-    VrDeviceInfo,
-    VrStereoConfig,
-    Wave (wave'channels, wave'frameCount),
-    MouseButton,
-    MouseCursor,
-    TraceLogLevel,
-    CameraMode,
-    Gesture,
-    BlendMode,
-    CubemapLayout,
-    FontType,
-    TextureWrap,
-    TextureFilter,
-    ConfigFlag,
-    KeyboardKey,
-    GamepadButton,
-    GamepadAxis,
-    ShaderUniformDataType,
-    PixelFormat
-  )
-import Raylib.Util (pop, withArray2D, configsToBitflag, withMaybeCString)
-import Prelude hiding (length)
-
--- Haskell doesn't support varargs in foreign calls, so these functions are impossible to call from FFI
--- type TraceLogCallback = FunPtr (CInt -> CString -> __builtin_va_list -> IO ())
--- foreign import ccall safe "wrapper"
---   mk'TraceLogCallback ::
---     (CInt -> CString -> __builtin_va_list -> IO ()) -> IO TraceLogCallback
--- foreign import ccall safe "dynamic"
---   mK'TraceLogCallback ::
---     TraceLogCallback -> (CInt -> CString -> __builtin_va_list -> IO ())
-type LoadFileDataCallback = FunPtr (CString -> Ptr CUInt -> IO (Ptr CUChar))
-
-foreign import ccall safe "wrapper"
-  mk'loadFileDataCallback ::
-    (CString -> Ptr CUInt -> IO (Ptr CUChar)) -> IO LoadFileDataCallback
-
-foreign import ccall safe "dynamic"
-  mK'loadFileDataCallback ::
-    LoadFileDataCallback -> (CString -> Ptr CUInt -> IO (Ptr CUChar))
-
-type SaveFileDataCallback = FunPtr (CString -> Ptr () -> CUInt -> IO CInt)
-
-foreign import ccall safe "wrapper"
-  mk'saveFileDataCallback ::
-    (CString -> Ptr () -> CUInt -> IO CInt) -> IO SaveFileDataCallback
-
-foreign import ccall safe "dynamic"
-  mK'saveFileDataCallback ::
-    SaveFileDataCallback -> (CString -> Ptr () -> CUInt -> IO CInt)
-
-type LoadFileTextCallback = FunPtr (CString -> IO CString)
-
-foreign import ccall safe "wrapper"
-  mk'loadFileTextCallback ::
-    (CString -> IO CString) -> IO LoadFileTextCallback
-
-foreign import ccall safe "dynamic"
-  mK'loadFileTextCallback ::
-    LoadFileTextCallback -> (CString -> IO CString)
-
-type SaveFileTextCallback = FunPtr (CString -> CString -> IO CInt)
-
-foreign import ccall safe "wrapper"
-  mk'saveFileTextCallback ::
-    (CString -> CString -> IO CInt) -> IO SaveFileTextCallback
-
-foreign import ccall safe "dynamic"
-  mK'saveFileTextCallback ::
-    SaveFileTextCallback -> (CString -> CString -> IO CInt)
-
-foreign import ccall safe "raylib.h InitWindow"
-  c'initWindow ::
-    CInt -> CInt -> CString -> IO ()
-
-initWindow :: Int -> Int -> String -> IO ()
-initWindow width height title = withCString title $ c'initWindow (fromIntegral width) (fromIntegral height)
-
-foreign import ccall safe "raylib.h &InitWindow"
-  p'initWindow ::
-    FunPtr (CInt -> CInt -> CString -> IO ())
-
-foreign import ccall safe "raylib.h WindowShouldClose"
-  c'windowShouldClose ::
-    IO CBool
-
-windowShouldClose :: IO Bool
-windowShouldClose = toBool <$> c'windowShouldClose
-
-foreign import ccall safe "raylib.h &WindowShouldClose"
-  p'windowShouldClose ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h CloseWindow"
-  closeWindow ::
-    IO ()
-
-foreign import ccall safe "raylib.h &CloseWindow"
-  p'closeWindow ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h IsWindowReady"
-  c'isWindowReady ::
-    IO CBool
-
-isWindowReady :: IO Bool
-isWindowReady = toBool <$> c'isWindowReady
-
-foreign import ccall safe "raylib.h &IsWindowReady"
-  p'isWindowReady ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h IsWindowFullscreen"
-  c'isWindowFullscreen ::
-    IO CBool
-
-isWindowFullscreen :: IO Bool
-isWindowFullscreen = toBool <$> c'isWindowFullscreen
-
-foreign import ccall safe "raylib.h &IsWindowFullscreen"
-  p'isWindowFullscreen ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h IsWindowHidden"
-  c'isWindowHidden ::
-    IO CBool
-
-isWindowHidden :: IO Bool
-isWindowHidden = toBool <$> c'isWindowHidden
-
-foreign import ccall safe "raylib.h &IsWindowHidden"
-  p'isWindowHidden ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h IsWindowMinimized"
-  c'isWindowMinimized ::
-    IO CBool
-
-isWindowMinimized :: IO Bool
-isWindowMinimized = toBool <$> c'isWindowMinimized
-
-foreign import ccall safe "raylib.h &IsWindowMinimized"
-  p'isWindowMinimized ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h IsWindowMaximized"
-  c'isWindowMaximized ::
-    IO CBool
-
-isWindowMaximized :: IO Bool
-isWindowMaximized = toBool <$> c'isWindowMaximized
-
-foreign import ccall safe "raylib.h &IsWindowMaximized"
-  p'isWindowMaximized ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h IsWindowFocused"
-  c'isWindowFocused ::
-    IO CBool
-
-isWindowFocused :: IO Bool
-isWindowFocused = toBool <$> c'isWindowFocused
-
-foreign import ccall safe "raylib.h &IsWindowFocused"
-  p'isWindowFocused ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h IsWindowResized"
-  c'isWindowResized ::
-    IO CBool
-
-isWindowResized :: IO Bool
-isWindowResized = toBool <$> c'isWindowResized
-
-foreign import ccall safe "raylib.h &IsWindowResized"
-  p'isWindowResized ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h IsWindowState"
-  c'isWindowState ::
-    CUInt -> IO CBool
-
-isWindowState :: [ConfigFlag] -> IO Bool
-isWindowState flags = toBool <$> c'isWindowState (fromIntegral $ configsToBitflag flags)
-
-foreign import ccall safe "raylib.h &IsWindowState"
-  p'isWindowState ::
-    FunPtr (CUInt -> IO CInt)
-
-foreign import ccall safe "raylib.h SetWindowState"
-  c'setWindowState ::
-    CUInt -> IO ()
-
-setWindowState :: [ConfigFlag] -> IO ()
-setWindowState = c'setWindowState . fromIntegral . configsToBitflag
-
-foreign import ccall safe "raylib.h &SetWindowState"
-  p'setWindowState ::
-    FunPtr (CUInt -> IO ())
-
-foreign import ccall safe "raylib.h ClearWindowState"
-  c'clearWindowState ::
-    CUInt -> IO ()
-
-clearWindowState :: [ConfigFlag] -> IO ()
-clearWindowState = c'clearWindowState . fromIntegral . configsToBitflag
-
-foreign import ccall safe "raylib.h &ClearWindowState"
-  p'clearWindowState ::
-    FunPtr (CUInt -> IO ())
-
-foreign import ccall safe "raylib.h ToggleFullscreen"
-  toggleFullscreen ::
-    IO ()
-
-foreign import ccall safe "raylib.h &ToggleFullscreen"
-  p'toggleFullscreen ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h MaximizeWindow"
-  maximizeWindow ::
-    IO ()
-
-foreign import ccall safe "raylib.h &MaximizeWindow"
-  p'maximizeWindow ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h MinimizeWindow"
-  minimizeWindow ::
-    IO ()
-
-foreign import ccall safe "raylib.h &MinimizeWindow"
-  p'minimizeWindow ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h RestoreWindow"
-  restoreWindow ::
-    IO ()
-
-foreign import ccall safe "raylib.h &RestoreWindow"
-  p'restoreWindow ::
-    FunPtr (IO ())
-
-foreign import ccall safe "bindings.h SetWindowIcon_" c'setWindowIcon :: Ptr Raylib.Types.Image -> IO ()
-
-setWindowIcon :: Raylib.Types.Image -> IO ()
-setWindowIcon image = with image c'setWindowIcon
-
-foreign import ccall safe "raylib.h &SetWindowIcon"
-  p'setWindowIcon ::
-    FunPtr (Raylib.Types.Image -> IO ())
-
-foreign import ccall safe "raylib.h SetWindowTitle"
-  c'setWindowTitle ::
-    CString -> IO ()
-
-setWindowTitle :: String -> IO ()
-setWindowTitle title = withCString title c'setWindowTitle
-
-foreign import ccall safe "raylib.h &SetWindowTitle"
-  p'setWindowTitle ::
-    FunPtr (CString -> IO ())
-
-foreign import ccall safe "raylib.h SetWindowPosition"
-  c'setWindowPosition ::
-    CInt -> CInt -> IO ()
-
-setWindowPosition :: Int -> Int -> IO ()
-setWindowPosition x y = c'setWindowPosition (fromIntegral x) (fromIntegral y)
-
-foreign import ccall safe "raylib.h &SetWindowPosition"
-  p'setWindowPosition ::
-    FunPtr (CInt -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h SetWindowMonitor"
-  c'setWindowMonitor ::
-    CInt -> IO ()
-
-setWindowMonitor :: Int -> IO ()
-setWindowMonitor = c'setWindowMonitor . fromIntegral
-
-foreign import ccall safe "raylib.h &SetWindowMonitor"
-  p'setWindowMonitor ::
-    FunPtr (CInt -> IO ())
-
-foreign import ccall safe "raylib.h SetWindowMinSize"
-  c'setWindowMinSize ::
-    CInt -> CInt -> IO ()
-
-setWindowMinSize :: Int -> Int -> IO ()
-setWindowMinSize x y = c'setWindowMinSize (fromIntegral x) (fromIntegral y)
-
-foreign import ccall safe "raylib.h &SetWindowMinSize"
-  p'setWindowMinSize ::
-    FunPtr (CInt -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h SetWindowSize"
-  c'setWindowSize ::
-    CInt -> CInt -> IO ()
-
-setWindowSize :: Int -> Int -> IO ()
-setWindowSize x y = c'setWindowSize (fromIntegral x) (fromIntegral y)
-
-foreign import ccall safe "raylib.h &SetWindowSize"
-  p'setWindowSize ::
-    FunPtr (CInt -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h SetWindowOpacity"
-  c'setWindowOpacity ::
-    CFloat -> IO ()
-
-setWindowOpacity :: Float -> IO ()
-setWindowOpacity opacity = c'setWindowOpacity $ realToFrac opacity
-
-foreign import ccall safe "raylib.h &SetWindowOpacity"
-  p'setWindowOpacity ::
-    FunPtr (CFloat -> IO ())
-
-foreign import ccall safe "raylib.h GetWindowHandle"
-  getWindowHandle ::
-    IO (Ptr ())
-
-foreign import ccall safe "raylib.h &GetWindowHandle"
-  p'getWindowHandle ::
-    FunPtr (IO (Ptr ()))
-
-foreign import ccall safe "raylib.h GetScreenWidth"
-  c'getScreenWidth ::
-    IO CInt
-
-getScreenWidth :: IO Int
-getScreenWidth = fromIntegral <$> c'getScreenWidth
-
-foreign import ccall safe "raylib.h &GetScreenWidth"
-  p'getScreenWidth ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetScreenHeight"
-  c'getScreenHeight ::
-    IO CInt
-
-getScreenHeight :: IO Int
-getScreenHeight = fromIntegral <$> c'getScreenHeight
-
-foreign import ccall safe "raylib.h &GetScreenHeight"
-  p'getScreenHeight ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetRenderWidth"
-  c'getRenderWidth ::
-    IO CInt
-
-getRenderWidth :: IO Int
-getRenderWidth = fromIntegral <$> c'getRenderWidth
-
-foreign import ccall safe "raylib.h &GetRenderWidth"
-  p'getRenderWidth ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetRenderHeight"
-  c'getRenderHeight ::
-    IO CInt
-
-getRenderHeight :: IO Int
-getRenderHeight = fromIntegral <$> c'getRenderHeight
-
-foreign import ccall safe "raylib.h &GetRenderHeight"
-  p'getRenderHeight ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetMonitorCount"
-  c'getMonitorCount ::
-    IO CInt
-
-getMonitorCount :: IO Int
-getMonitorCount = fromIntegral <$> c'getMonitorCount
-
-foreign import ccall safe "raylib.h &GetMonitorCount"
-  p'getMonitorCount ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetCurrentMonitor"
-  c'getCurrentMonitor ::
-    IO CInt
-
-getCurrentMonitor :: IO Int
-getCurrentMonitor = fromIntegral <$> c'getCurrentMonitor
-
-foreign import ccall safe "raylib.h &GetCurrentMonitor"
-  p'getCurrentMonitor ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "bindings.h GetMonitorPosition_" c'getMonitorPosition :: CInt -> IO (Ptr Raylib.Types.Vector2)
-
-getMonitorPosition :: Int -> IO Raylib.Types.Vector2
-getMonitorPosition monitor = c'getMonitorPosition (fromIntegral monitor) >>= pop
-
-foreign import ccall safe "raylib.h &GetMonitorPosition"
-  p'getMonitorPosition ::
-    FunPtr (CInt -> IO Raylib.Types.Vector2)
-
-foreign import ccall safe "raylib.h GetMonitorWidth"
-  c'getMonitorWidth ::
-    CInt -> IO CInt
-
-getMonitorWidth :: Int -> IO Int
-getMonitorWidth monitor = fromIntegral <$> c'getMonitorWidth (fromIntegral monitor)
-
-foreign import ccall safe "raylib.h &GetMonitorWidth"
-  p'getMonitorWidth ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetMonitorHeight"
-  c'getMonitorHeight ::
-    CInt -> IO CInt
-
-getMonitorHeight :: Int -> IO Int
-getMonitorHeight monitor = fromIntegral <$> c'getMonitorHeight (fromIntegral monitor)
-
-foreign import ccall safe "raylib.h &GetMonitorHeight"
-  p'getMonitorHeight ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetMonitorPhysicalWidth"
-  c'getMonitorPhysicalWidth ::
-    CInt -> IO CInt
-
-getMonitorPhysicalWidth :: Int -> IO Int
-getMonitorPhysicalWidth monitor = fromIntegral <$> c'getMonitorPhysicalWidth (fromIntegral monitor)
-
-foreign import ccall safe "raylib.h &GetMonitorPhysicalWidth"
-  p'getMonitorPhysicalWidth ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetMonitorPhysicalHeight"
-  c'getMonitorPhysicalHeight ::
-    CInt -> IO CInt
-
-getMonitorPhysicalHeight :: Int -> IO Int
-getMonitorPhysicalHeight monitor = fromIntegral <$> c'getMonitorPhysicalHeight (fromIntegral monitor)
-
-foreign import ccall safe "raylib.h &GetMonitorPhysicalHeight"
-  p'getMonitorPhysicalHeight ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetMonitorRefreshRate"
-  c'getMonitorRefreshRate ::
-    CInt -> IO CInt
-
-getMonitorRefreshRate :: Int -> IO Int
-getMonitorRefreshRate monitor = fromIntegral <$> c'getMonitorRefreshRate (fromIntegral monitor)
-
-foreign import ccall safe "raylib.h &GetMonitorRefreshRate"
-  p'getMonitorRefreshRate ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "bindings.h GetWindowPosition_" c'getWindowPosition :: IO (Ptr Raylib.Types.Vector2)
-
-getWindowPosition :: IO Raylib.Types.Vector2
-getWindowPosition = c'getWindowPosition >>= pop
-
-foreign import ccall safe "raylib.h &GetWindowPosition"
-  p'getWindowPosition ::
-    FunPtr (IO Raylib.Types.Vector2)
-
-foreign import ccall safe "bindings.h GetWindowScaleDPI_" c'getWindowScaleDPI :: IO (Ptr Raylib.Types.Vector2)
-
-getWindowScaleDPI :: IO Raylib.Types.Vector2
-getWindowScaleDPI = c'getWindowScaleDPI >>= pop
-
-foreign import ccall safe "raylib.h &GetWindowScaleDPI"
-  p'getWindowScaleDPI ::
-    FunPtr (IO Raylib.Types.Vector2)
-
-foreign import ccall safe "raylib.h GetMonitorName"
-  c'getMonitorName ::
-    CInt -> IO CString
-
-getMonitorName :: Int -> IO String
-getMonitorName monitor = c'getMonitorName (fromIntegral monitor) >>= peekCString
-
-foreign import ccall safe "raylib.h &GetMonitorName"
-  p'getMonitorName ::
-    FunPtr (CInt -> IO CString)
-
-foreign import ccall safe "raylib.h SetClipboardText"
-  c'setClipboardText ::
-    CString -> IO ()
-
-setClipboardText :: String -> IO ()
-setClipboardText text = withCString text c'setClipboardText
-
-foreign import ccall safe "raylib.h &SetClipboardText"
-  p'setClipboardText ::
-    FunPtr (CString -> IO ())
-
-foreign import ccall safe "raylib.h GetClipboardText"
-  c'getClipboardText ::
-    IO CString
-
-getClipboardText :: IO String
-getClipboardText = c'getClipboardText >>= peekCString
-
-foreign import ccall safe "raylib.h &GetClipboardText"
-  p'getClipboardText ::
-    FunPtr (IO CString)
-
-foreign import ccall safe "raylib.h EnableEventWaiting"
-  enableEventWaiting ::
-    IO ()
-
-foreign import ccall safe "raylib.h &EnableEventWaiting"
-  p'enableEventWaiting ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h DisableEventWaiting"
-  disableEventWaiting ::
-    IO ()
-
-foreign import ccall safe "raylib.h &DisableEventWaiting"
-  p'disableEventWaiting ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h SwapScreenBuffer"
-  swapScreenBuffer ::
-    IO ()
-
-foreign import ccall safe "raylib.h &SwapScreenBuffer"
-  p'swapScreenBuffer ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h PollInputEvents"
-  pollInputEvents ::
-    IO ()
-
-foreign import ccall safe "raylib.h &PollInputEvents"
-  p'pollInputEvents ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h WaitTime"
-  c'waitTime ::
-    CDouble -> IO ()
-
-waitTime :: Double -> IO ()
-waitTime seconds = c'waitTime $ realToFrac seconds
-
-foreign import ccall safe "raylib.h &WaitTime"
-  p'waitTime ::
-    FunPtr (CDouble -> IO ())
-
-foreign import ccall safe "raylib.h ShowCursor"
-  showCursor ::
-    IO ()
-
-foreign import ccall safe "raylib.h &ShowCursor"
-  p'showCursor ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h HideCursor"
-  hideCursor ::
-    IO ()
-
-foreign import ccall safe "raylib.h &HideCursor"
-  p'hideCursor ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h IsCursorHidden"
-  c'isCursorHidden ::
-    IO CBool
-
-isCursorHidden :: IO Bool
-isCursorHidden = toBool <$> c'isCursorHidden
-
-foreign import ccall safe "raylib.h &IsCursorHidden"
-  p'isCursorHidden ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h EnableCursor"
-  enableCursor ::
-    IO ()
-
-foreign import ccall safe "raylib.h &EnableCursor"
-  p'enableCursor ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h DisableCursor"
-  disableCursor ::
-    IO ()
-
-foreign import ccall safe "raylib.h &DisableCursor"
-  p'disableCursor ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h IsCursorOnScreen"
-  c'isCursorOnScreen ::
-    IO CBool
-
-isCursorOnScreen :: IO Bool
-isCursorOnScreen = toBool <$> c'isCursorOnScreen
-
-foreign import ccall safe "raylib.h &IsCursorOnScreen"
-  p'isCursorOnScreen ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "bindings.h ClearBackground_" c'clearBackground :: Ptr Raylib.Types.Color -> IO ()
-
-clearBackground :: Raylib.Types.Color -> IO ()
-clearBackground color = with color c'clearBackground
-
-foreign import ccall safe "raylib.h &ClearBackground"
-  p'clearBackground ::
-    FunPtr (Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "raylib.h BeginDrawing"
-  beginDrawing ::
-    IO ()
-
-foreign import ccall safe "raylib.h &BeginDrawing"
-  p'beginDrawing ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h EndDrawing"
-  endDrawing ::
-    IO ()
-
-foreign import ccall safe "raylib.h &EndDrawing"
-  p'endDrawing ::
-    FunPtr (IO ())
-
-foreign import ccall safe "bindings.h BeginMode2D_" c'beginMode2D :: Ptr Raylib.Types.Camera2D -> IO ()
-
-beginMode2D :: Raylib.Types.Camera2D -> IO ()
-beginMode2D camera = with camera c'beginMode2D
-
-foreign import ccall safe "raylib.h &BeginMode2D"
-  p'beginMode2D ::
-    FunPtr (Raylib.Types.Camera2D -> IO ())
-
-foreign import ccall safe "raylib.h EndMode2D"
-  endMode2D ::
-    IO ()
-
-foreign import ccall safe "raylib.h &EndMode2D"
-  p'endMode2D ::
-    FunPtr (IO ())
-
-foreign import ccall safe "bindings.h BeginMode3D_" c'beginMode3D :: Ptr Raylib.Types.Camera3D -> IO ()
-
-beginMode3D :: Raylib.Types.Camera3D -> IO ()
-beginMode3D camera = with camera c'beginMode3D
-
-foreign import ccall safe "raylib.h &BeginMode3D"
-  p'beginMode3D ::
-    FunPtr (Raylib.Types.Camera3D -> IO ())
-
-foreign import ccall safe "raylib.h EndMode3D"
-  endMode3D ::
-    IO ()
-
-foreign import ccall safe "raylib.h &EndMode3D"
-  p'endMode3D ::
-    FunPtr (IO ())
-
-foreign import ccall safe "bindings.h BeginTextureMode_" c'beginTextureMode :: Ptr Raylib.Types.RenderTexture -> IO ()
-
-beginTextureMode :: Raylib.Types.RenderTexture -> IO ()
-beginTextureMode renderTexture = with renderTexture c'beginTextureMode
-
-foreign import ccall safe "raylib.h &BeginTextureMode"
-  p'beginTextureMode ::
-    FunPtr (Raylib.Types.RenderTexture -> IO ())
-
-foreign import ccall safe "raylib.h EndTextureMode"
-  endTextureMode ::
-    IO ()
-
-foreign import ccall safe "raylib.h &EndTextureMode"
-  p'endTextureMode ::
-    FunPtr (IO ())
-
-foreign import ccall safe "bindings.h BeginShaderMode_" c'beginShaderMode :: Ptr Raylib.Types.Shader -> IO ()
-
-beginShaderMode :: Raylib.Types.Shader -> IO ()
-beginShaderMode shader = with shader c'beginShaderMode
-
-foreign import ccall safe "raylib.h &BeginShaderMode"
-  p'beginShaderMode ::
-    FunPtr (Raylib.Types.Shader -> IO ())
-
-foreign import ccall safe "raylib.h EndShaderMode"
-  endShaderMode ::
-    IO ()
-
-foreign import ccall safe "raylib.h &EndShaderMode"
-  p'endShaderMode ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h BeginBlendMode"
-  c'beginBlendMode ::
-    CInt -> IO ()
-
-beginBlendMode :: BlendMode -> IO ()
-beginBlendMode = c'beginBlendMode . fromIntegral . fromEnum
-
-foreign import ccall safe "raylib.h &BeginBlendMode"
-  p'beginBlendMode ::
-    FunPtr (CInt -> IO ())
-
-foreign import ccall safe "raylib.h EndBlendMode"
-  endBlendMode ::
-    IO ()
-
-foreign import ccall safe "raylib.h &EndBlendMode"
-  p'endBlendMode ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h BeginScissorMode"
-  c'beginScissorMode ::
-    CInt -> CInt -> CInt -> CInt -> IO ()
-
-beginScissorMode :: Int -> Int -> Int -> Int -> IO ()
-beginScissorMode x y width height = c'beginScissorMode (fromIntegral x) (fromIntegral y) (fromIntegral width) (fromIntegral height)
-
-foreign import ccall safe "raylib.h &BeginScissorMode"
-  p'beginScissorMode ::
-    FunPtr (CInt -> CInt -> CInt -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h EndScissorMode"
-  endScissorMode ::
-    IO ()
-
-foreign import ccall safe "raylib.h &EndScissorMode"
-  p'endScissorMode ::
-    FunPtr (IO ())
-
-foreign import ccall safe "bindings.h BeginVrStereoMode_" c'beginVrStereoMode :: Ptr Raylib.Types.VrStereoConfig -> IO ()
-
-beginVrStereoMode :: Raylib.Types.VrStereoConfig -> IO ()
-beginVrStereoMode config = with config c'beginVrStereoMode
-
-foreign import ccall safe "raylib.h &BeginVrStereoMode"
-  p'beginVrStereoMode ::
-    FunPtr (Raylib.Types.VrStereoConfig -> IO ())
-
-foreign import ccall safe "raylib.h EndVrStereoMode"
-  endVrStereoMode ::
-    IO ()
-
-foreign import ccall safe "raylib.h &EndVrStereoMode"
-  p'endVrStereoMode ::
-    FunPtr (IO ())
-
-foreign import ccall safe "bindings.h LoadVrStereoConfig_" c'loadVrStereoConfig :: Ptr Raylib.Types.VrDeviceInfo -> IO (Ptr Raylib.Types.VrStereoConfig)
-
-loadVrStereoConfig :: Raylib.Types.VrDeviceInfo -> IO Raylib.Types.VrStereoConfig
-loadVrStereoConfig deviceInfo = with deviceInfo c'loadVrStereoConfig >>= pop
-
-foreign import ccall safe "raylib.h &LoadVrStereoConfig"
-  p'loadVrStereoConfig ::
-    FunPtr (Raylib.Types.VrDeviceInfo -> IO Raylib.Types.VrStereoConfig)
-
-foreign import ccall safe "bindings.h UnloadVrStereoConfig_" c'unloadVrStereoConfig :: Ptr Raylib.Types.VrStereoConfig -> IO ()
-
-unloadVrStereoConfig :: Raylib.Types.VrStereoConfig -> IO ()
-unloadVrStereoConfig config = with config c'unloadVrStereoConfig
-
-foreign import ccall safe "raylib.h &UnloadVrStereoConfig"
-  p'unloadVrStereoConfig ::
-    FunPtr (Raylib.Types.VrStereoConfig -> IO ())
-
-foreign import ccall safe "bindings.h LoadShader_" c'loadShader :: CString -> CString -> IO (Ptr Raylib.Types.Shader)
-
-loadShader :: Maybe String -> Maybe String -> IO Raylib.Types.Shader
-loadShader vsFileName fsFileName = 
-  withMaybeCString vsFileName (withMaybeCString fsFileName . c'loadShader) >>= pop
-
-foreign import ccall safe "raylib.h &LoadShader"
-  p'loadShader ::
-    FunPtr (CString -> CString -> IO Raylib.Types.Shader)
-
-foreign import ccall safe "bindings.h LoadShaderFromMemory_" c'loadShaderFromMemory :: CString -> CString -> IO (Ptr Raylib.Types.Shader)
-
-loadShaderFromMemory :: Maybe String -> Maybe String -> IO Raylib.Types.Shader
-loadShaderFromMemory vsCode fsCode = withMaybeCString vsCode (withMaybeCString fsCode . c'loadShaderFromMemory) >>= pop
-
-foreign import ccall safe "raylib.h &LoadShaderFromMemory"
-  p'loadShaderFromMemory ::
-    FunPtr (CString -> CString -> IO Raylib.Types.Shader)
-
-foreign import ccall safe "bindings.h GetShaderLocation_" c'getShaderLocation :: Ptr Raylib.Types.Shader -> CString -> IO CInt
-
-getShaderLocation :: Raylib.Types.Shader -> String -> IO Int
-getShaderLocation shader uniformName = fromIntegral <$> with shader (withCString uniformName . c'getShaderLocation)
-
-foreign import ccall safe "raylib.h &GetShaderLocation"
-  p'getShaderLocation ::
-    FunPtr (Raylib.Types.Shader -> CString -> IO CInt)
-
-foreign import ccall safe "bindings.h GetShaderLocationAttrib_" c'getShaderLocationAttrib :: Ptr Raylib.Types.Shader -> CString -> IO CInt
-
-getShaderLocationAttrib :: Raylib.Types.Shader -> String -> IO Int
-getShaderLocationAttrib shader attribName = fromIntegral <$> with shader (withCString attribName . c'getShaderLocationAttrib)
-
-foreign import ccall safe "raylib.h &GetShaderLocationAttrib"
-  p'getShaderLocationAttrib ::
-    FunPtr (Raylib.Types.Shader -> CString -> IO CInt)
-
-foreign import ccall safe "bindings.h SetShaderValue_" c'setShaderValue :: Ptr Raylib.Types.Shader -> CInt -> Ptr () -> CInt -> IO ()
-
-setShaderValue :: Raylib.Types.Shader -> Int -> Ptr () -> ShaderUniformDataType -> IO ()
-setShaderValue shader locIndex value uniformType = with shader (\s -> c'setShaderValue s (fromIntegral locIndex) value (fromIntegral $ fromEnum uniformType))
-
-foreign import ccall safe "raylib.h &SetShaderValue"
-  p'setShaderValue ::
-    FunPtr (Raylib.Types.Shader -> CInt -> Ptr () -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h SetShaderValueV_" c'setShaderValueV :: Ptr Raylib.Types.Shader -> CInt -> Ptr () -> CInt -> CInt -> IO ()
-
-setShaderValueV :: Raylib.Types.Shader -> Int -> Ptr () -> ShaderUniformDataType -> Int -> IO ()
-setShaderValueV shader locIndex value uniformType count = with shader (\s -> c'setShaderValueV s (fromIntegral locIndex) value (fromIntegral $ fromEnum uniformType) (fromIntegral count))
-
-foreign import ccall safe "raylib.h &SetShaderValueV"
-  p'setShaderValueV ::
-    FunPtr (Raylib.Types.Shader -> CInt -> Ptr () -> CInt -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h SetShaderValueMatrix_" c'setShaderValueMatrix :: Ptr Raylib.Types.Shader -> CInt -> Ptr Raylib.Types.Matrix -> IO ()
-
-setShaderValueMatrix :: Raylib.Types.Shader -> Int -> Raylib.Types.Matrix -> IO ()
-setShaderValueMatrix shader locIndex mat = with shader (\s -> with mat (c'setShaderValueMatrix s (fromIntegral locIndex)))
-
-foreign import ccall safe "raylib.h &SetShaderValueMatrix"
-  p'setShaderValueMatrix ::
-    FunPtr (Raylib.Types.Shader -> CInt -> Raylib.Types.Matrix -> IO ())
-
-foreign import ccall safe "bindings.h SetShaderValueTexture_" c'setShaderValueTexture :: Ptr Raylib.Types.Shader -> CInt -> Ptr Raylib.Types.Texture -> IO ()
-
-setShaderValueTexture :: Raylib.Types.Shader -> Int -> Raylib.Types.Texture -> IO ()
-setShaderValueTexture shader locIndex tex = with shader (\s -> with tex (c'setShaderValueTexture s (fromIntegral locIndex)))
-
-foreign import ccall safe "raylib.h &SetShaderValueTexture"
-  p'setShaderValueTexture ::
-    FunPtr (Raylib.Types.Shader -> CInt -> Raylib.Types.Texture -> IO ())
-
-foreign import ccall safe "bindings.h UnloadShader_" c'unloadShader :: Ptr Raylib.Types.Shader -> IO ()
-
-unloadShader :: Raylib.Types.Shader -> IO ()
-unloadShader shader = with shader c'unloadShader
-
-foreign import ccall safe "raylib.h &UnloadShader"
-  p'unloadShader ::
-    FunPtr (Raylib.Types.Shader -> IO ())
-
-foreign import ccall safe "bindings.h GetMouseRay_" c'getMouseRay :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Camera3D -> IO (Ptr Raylib.Types.Ray)
-
-getMouseRay :: Raylib.Types.Vector2 -> Raylib.Types.Camera3D -> IO Raylib.Types.Ray
-getMouseRay mousePosition camera = with mousePosition (with camera . c'getMouseRay) >>= pop
-
-foreign import ccall safe "raylib.h &GetMouseRay"
-  p'getMouseRay ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Camera3D -> IO Raylib.Types.Ray)
-
-foreign import ccall safe "bindings.h GetCameraMatrix_" c'getCameraMatrix :: Ptr Raylib.Types.Camera3D -> IO (Ptr Raylib.Types.Matrix)
-
-getCameraMatrix :: Raylib.Types.Camera3D -> IO Raylib.Types.Matrix
-getCameraMatrix camera = with camera c'getCameraMatrix >>= pop
-
-foreign import ccall safe "raylib.h &GetCameraMatrix"
-  p'getCameraMatrix ::
-    FunPtr (Raylib.Types.Camera3D -> IO Raylib.Types.Matrix)
-
-foreign import ccall safe "bindings.h GetCameraMatrix2D_" c'getCameraMatrix2D :: Ptr Raylib.Types.Camera2D -> IO (Ptr Raylib.Types.Matrix)
-
-getCameraMatrix2D :: Raylib.Types.Camera2D -> IO Raylib.Types.Matrix
-getCameraMatrix2D camera = with camera c'getCameraMatrix2D >>= pop
-
-foreign import ccall safe "raylib.h &GetCameraMatrix2D"
-  p'getCameraMatrix2D ::
-    FunPtr (Raylib.Types.Camera2D -> IO Raylib.Types.Matrix)
-
-foreign import ccall safe "bindings.h GetWorldToScreen_" c'getWorldToScreen :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Camera3D -> IO (Ptr Raylib.Types.Vector2)
-
-getWorldToScreen :: Raylib.Types.Vector3 -> Raylib.Types.Camera3D -> IO Raylib.Types.Vector2
-getWorldToScreen position camera = with position (with camera . c'getWorldToScreen) >>= pop
-
-foreign import ccall safe "raylib.h &GetWorldToScreen"
-  p'getWorldToScreen ::
-    FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Camera3D -> IO Raylib.Types.Vector2)
-
-foreign import ccall safe "bindings.h GetScreenToWorld2D_" c'getScreenToWorld2D :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Camera2D -> IO (Ptr Raylib.Types.Vector2)
-
-getScreenToWorld2D :: Raylib.Types.Vector2 -> Raylib.Types.Camera2D -> IO Raylib.Types.Vector2
-getScreenToWorld2D position camera = with position (with camera . c'getScreenToWorld2D) >>= pop
-
-foreign import ccall safe "raylib.h &GetScreenToWorld2D"
-  p'getScreenToWorld2D ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Camera2D -> IO Raylib.Types.Vector2)
-
-foreign import ccall safe "bindings.h GetWorldToScreenEx_" c'getWorldToScreenEx :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Camera3D -> CInt -> CInt -> IO (Ptr Raylib.Types.Vector2)
-
-getWorldToScreenEx :: Raylib.Types.Vector3 -> Raylib.Types.Camera3D -> Int -> Int -> IO Raylib.Types.Vector2
-getWorldToScreenEx position camera width height = with position (\p -> with camera (\c -> c'getWorldToScreenEx p c (fromIntegral width) (fromIntegral height))) >>= pop
-
-foreign import ccall safe "raylib.h &GetWorldToScreenEx"
-  p'getWorldToScreenEx ::
-    FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Camera3D -> CInt -> CInt -> IO Raylib.Types.Vector2)
-
-foreign import ccall safe "bindings.h GetWorldToScreen2D_" c'getWorldToScreen2D :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Camera2D -> IO (Ptr Raylib.Types.Vector2)
-
-getWorldToScreen2D :: Raylib.Types.Vector2 -> Raylib.Types.Camera2D -> IO Raylib.Types.Vector2
-getWorldToScreen2D position camera = with position (with camera . c'getWorldToScreen2D) >>= pop
-
-foreign import ccall safe "raylib.h &GetWorldToScreen2D"
-  p'getWorldToScreen2D ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Camera2D -> IO Raylib.Types.Vector2)
-
-foreign import ccall safe "raylib.h SetTargetFPS"
-  c'setTargetFPS ::
-    CInt -> IO ()
-
-setTargetFPS :: Int -> IO ()
-setTargetFPS fps = c'setTargetFPS $ fromIntegral fps
-
-foreign import ccall safe "raylib.h &SetTargetFPS"
-  p'setTargetFPS ::
-    FunPtr (CInt -> IO ())
-
-foreign import ccall safe "raylib.h GetFPS"
-  c'getFPS ::
-    IO CInt
-
-getFPS :: IO Int
-getFPS = fromIntegral <$> c'getFPS
-
-foreign import ccall safe "raylib.h &GetFPS"
-  p'getFPS ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetFrameTime"
-  c'getFrameTime ::
-    IO CFloat
-
-getFrameTime :: IO Float
-getFrameTime = realToFrac <$> c'getFrameTime
-
-foreign import ccall safe "raylib.h &GetFrameTime"
-  p'getFrameTime ::
-    FunPtr (IO CFloat)
-
-foreign import ccall safe "raylib.h GetTime"
-  c'getTime ::
-    IO CDouble
-
-getTime :: IO Double
-getTime = realToFrac <$> c'getTime
-
-foreign import ccall safe "raylib.h &GetTime"
-  p'getTime ::
-    FunPtr (IO CDouble)
-
-foreign import ccall safe "raylib.h GetRandomValue"
-  c'getRandomValue ::
-    CInt -> CInt -> IO CInt
-
-getRandomValue :: Int -> Int -> IO Int
-getRandomValue minVal maxVal = fromIntegral <$> c'getRandomValue (fromIntegral minVal) (fromIntegral maxVal)
-
-foreign import ccall safe "raylib.h &GetRandomValue"
-  p'getRandomValue ::
-    FunPtr (CInt -> CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h SetRandomSeed"
-  c'setRandomSeed ::
-    CUInt -> IO ()
-
-setRandomSeed :: Integer -> IO ()
-setRandomSeed seed = c'setRandomSeed $ fromIntegral seed
-
-foreign import ccall safe "raylib.h &SetRandomSeed"
-  p'setRandomSeed ::
-    FunPtr (CUInt -> IO ())
-
-foreign import ccall safe "raylib.h TakeScreenshot"
-  c'takeScreenshot ::
-    CString -> IO ()
-
-takeScreenshot :: String -> IO ()
-takeScreenshot fileName = withCString fileName c'takeScreenshot
-
-foreign import ccall safe "raylib.h &TakeScreenshot"
-  p'takeScreenshot ::
-    FunPtr (CString -> IO ())
-
-foreign import ccall safe "raylib.h SetConfigFlags"
-  c'setConfigFlags ::
-    CUInt -> IO ()
-
-setConfigFlags :: [ConfigFlag] -> IO ()
-setConfigFlags flags = c'setConfigFlags $ fromIntegral $ configsToBitflag flags
-
-foreign import ccall safe "raylib.h &SetConfigFlags"
-  p'setConfigFlags ::
-    FunPtr (CUInt -> IO ())
-
-foreign import ccall safe "raylib.h TraceLog"
-  c'traceLog ::
-    CInt -> CString -> IO () -- Uses varags, can't implement complete functionality
-
-traceLog :: TraceLogLevel -> String -> IO ()
-traceLog logLevel text = withCString text $ c'traceLog $ fromIntegral $ fromEnum logLevel
-
-foreign import ccall safe "raylib.h &TraceLog"
-  p'traceLog ::
-    FunPtr (CInt -> CString -> IO ())
-
-foreign import ccall safe "raylib.h SetTraceLogLevel"
-  c'setTraceLogLevel ::
-    CInt -> IO ()
-
-setTraceLogLevel :: TraceLogLevel -> IO ()
-setTraceLogLevel = c'setTraceLogLevel . fromIntegral . fromEnum
-
-foreign import ccall safe "raylib.h &SetTraceLogLevel"
-  p'setTraceLogLevel ::
-    FunPtr (CInt -> IO ())
-
-foreign import ccall safe "raylib.h MemAlloc"
-  c'memAlloc ::
-    CInt -> IO (Ptr ())
-
-memAlloc :: (Storable a) => Int -> IO (Ptr a)
-memAlloc size = castPtr <$> c'memAlloc (fromIntegral size)
-
-foreign import ccall safe "raylib.h &MemAlloc"
-  p'memAlloc ::
-    FunPtr (CInt -> IO (Ptr ()))
-
-foreign import ccall safe "raylib.h MemRealloc"
-  c'memRealloc ::
-    Ptr () -> CInt -> IO (Ptr ())
-
-memRealloc :: (Storable a, Storable b) => Ptr a -> Int -> IO (Ptr b)
-memRealloc ptr size = castPtr <$> c'memRealloc (castPtr ptr) (fromIntegral size)
-
-foreign import ccall safe "raylib.h &MemRealloc"
-  p'memRealloc ::
-    FunPtr (Ptr () -> CInt -> IO (Ptr ()))
-
-foreign import ccall safe "raylib.h MemFree"
-  c'memFree ::
-    Ptr () -> IO ()
-
-memFree :: (Storable a) => Ptr a -> IO ()
-memFree = c'memFree . castPtr
-
-foreign import ccall safe "raylib.h &MemFree"
-  p'memFree ::
-    FunPtr (Ptr () -> IO ())
-
-foreign import ccall safe "raylib.h OpenURL"
-  c'openURL ::
-    CString -> IO ()
-
-openURL :: String -> IO ()
-openURL url = withCString url c'openURL
-
-foreign import ccall safe "raylib.h &OpenURL"
-  p'openURL ::
-    FunPtr (CString -> IO ())
-
--- These functions use varargs so they can't be implemented through FFI
--- foreign import ccall safe "raylib.h SetTraceLogCallback"
---   SetTraceLogCallback ::
---     TraceLogCallback -> IO ()
--- foreign import ccall safe "raylib.h &SetTraceLogCallback"
---   p'SetTraceLogCallback ::
---     FunPtr (TraceLogCallback -> IO ())
-
-foreign import ccall safe "raylib.h SetLoadFileDataCallback"
-  setLoadFileDataCallback ::
-    LoadFileDataCallback -> IO ()
-
-foreign import ccall safe "raylib.h &SetLoadFileDataCallback"
-  p'setLoadFileDataCallback ::
-    FunPtr (LoadFileDataCallback -> IO ())
-
-foreign import ccall safe "raylib.h SetSaveFileDataCallback"
-  setSaveFileDataCallback ::
-    SaveFileDataCallback -> IO ()
-
-foreign import ccall safe "raylib.h &SetSaveFileDataCallback"
-  p'setSaveFileDataCallback ::
-    FunPtr (SaveFileDataCallback -> IO ())
-
-foreign import ccall safe "raylib.h SetLoadFileTextCallback"
-  setLoadFileTextCallback ::
-    LoadFileTextCallback -> IO ()
-
-foreign import ccall safe "raylib.h &SetLoadFileTextCallback"
-  p'setLoadFileTextCallback ::
-    FunPtr (LoadFileTextCallback -> IO ())
-
-foreign import ccall safe "raylib.h SetSaveFileTextCallback"
-  setSaveFileTextCallback ::
-    SaveFileTextCallback -> IO ()
-
-foreign import ccall safe "raylib.h &SetSaveFileTextCallback"
-  p'setSaveFileTextCallback ::
-    FunPtr (SaveFileTextCallback -> IO ())
-
-foreign import ccall safe "raylib.h LoadFileData"
-  c'loadFileData ::
-    CString -> Ptr CUInt -> IO (Ptr CUChar)
-
-loadFileData :: String -> IO [Integer]
-loadFileData fileName =
-  with
-    0
-    ( \size -> do
-        withCString
-          fileName
-          ( \path -> do
-              ptr <- c'loadFileData path size
-              arrSize <- fromIntegral <$> peek size
-              arr <- peekArray arrSize ptr
-              c'unloadFileData ptr
-              return $ map fromIntegral arr
-          )
-    )
-
-foreign import ccall safe "raylib.h &LoadFileData"
-  p'loadFileData ::
-    FunPtr (CString -> Ptr CUInt -> IO (Ptr CUChar))
-
-foreign import ccall safe "raylib.h UnloadFileData"
-  c'unloadFileData ::
-    Ptr CUChar -> IO ()
-
-foreign import ccall safe "raylib.h &UnloadFileData"
-  p'unloadFileData ::
-    FunPtr (Ptr CUChar -> IO ())
-
-foreign import ccall safe "raylib.h SaveFileData"
-  c'saveFileData ::
-    CString -> Ptr () -> CUInt -> IO CBool
-
-saveFileData :: (Storable a) => String -> Ptr a -> Integer -> IO Bool
-saveFileData fileName contents bytesToWrite =
-  toBool <$> withCString fileName (\s -> c'saveFileData s (castPtr contents) (fromIntegral bytesToWrite))
-
-foreign import ccall safe "raylib.h &SaveFileData"
-  p'saveFileData ::
-    FunPtr (CString -> Ptr () -> CUInt -> IO CInt)
-
-foreign import ccall safe "raylib.h ExportDataAsCode"
-  c'exportDataAsCode ::
-    Ptr CUChar -> CUInt -> CString -> IO CBool
-
-exportDataAsCode :: [Integer] -> Integer -> String -> IO Bool
-exportDataAsCode contents size fileName =
-  toBool <$> withArray (map fromInteger contents) (\c -> withCString fileName (c'exportDataAsCode c (fromIntegral size)))
-
-foreign import ccall safe "raylib.h &ExportDataAsCode"
-  p'exportDataAsCode ::
-    FunPtr (CString -> CUInt -> CString -> IO CInt)
-
-foreign import ccall safe "raylib.h LoadFileText"
-  c'loadFileText ::
-    CString -> IO CString
-
-loadFileText :: String -> IO String
-loadFileText fileName = withCString fileName c'loadFileText >>= peekCString
-
-foreign import ccall safe "raylib.h &LoadFileText"
-  p'loadFileText ::
-    FunPtr (CString -> IO CString)
-
-foreign import ccall safe "raylib.h UnloadFileText"
-  c'unloadFileText ::
-    CString -> IO ()
-
-unloadFileText :: String -> IO ()
-unloadFileText text = withCString text c'unloadFileText
-
-foreign import ccall safe "raylib.h &UnloadFileText"
-  p'unloadFileText ::
-    FunPtr (CString -> IO ())
-
-foreign import ccall safe "raylib.h SaveFileText"
-  c'saveFileText ::
-    CString -> CString -> IO CBool
-
-saveFileText :: String -> String -> IO Bool
-saveFileText fileName text = toBool <$> withCString fileName (withCString text . c'saveFileText)
-
-foreign import ccall safe "raylib.h &SaveFileText"
-  p'saveFileText ::
-    FunPtr (CString -> CString -> IO CInt)
-
-foreign import ccall safe "raylib.h FileExists"
-  c'fileExists ::
-    CString -> IO CBool
-
-fileExists :: String -> IO Bool
-fileExists fileName = toBool <$> withCString fileName c'fileExists
-
-foreign import ccall safe "raylib.h &FileExists"
-  p'fileExists ::
-    FunPtr (CString -> IO CInt)
-
-foreign import ccall safe "raylib.h DirectoryExists"
-  c'directoryExists ::
-    CString -> IO CBool
-
-directoryExists :: String -> IO Bool
-directoryExists dirPath = toBool <$> withCString dirPath c'directoryExists
-
-foreign import ccall safe "raylib.h &DirectoryExists"
-  p'directoryExists ::
-    FunPtr (CString -> IO CInt)
-
-foreign import ccall safe "raylib.h IsFileExtension"
-  c'isFileExtension ::
-    CString -> CString -> IO CBool
-
-isFileExtension :: String -> String -> IO Bool
-isFileExtension fileName ext = toBool <$> withCString fileName (withCString ext . c'isFileExtension)
-
-foreign import ccall safe "raylib.h &IsFileExtension"
-  p'isFileExtension ::
-    FunPtr (CString -> CString -> IO CInt)
-
-foreign import ccall safe "raylib.h GetFileLength"
-  c'getFileLength ::
-    CString -> IO CBool
-
-getFileLength :: String -> IO Bool
-getFileLength fileName = toBool <$> withCString fileName c'getFileLength
-
-foreign import ccall safe "raylib.h &GetFileLength"
-  p'getFileLength ::
-    FunPtr (CString -> IO CInt)
-
-foreign import ccall safe "raylib.h GetFileExtension"
-  c'getFileExtension ::
-    CString -> IO CString
-
-getFileExtension :: String -> IO String
-getFileExtension fileName = withCString fileName c'getFileExtension >>= peekCString
-
-foreign import ccall safe "raylib.h &GetFileExtension"
-  p'getFileExtension ::
-    FunPtr (CString -> IO CString)
-
-foreign import ccall safe "raylib.h GetFileName"
-  c'getFileName ::
-    CString -> IO CString
-
-getFileName :: String -> IO String
-getFileName filePath = withCString filePath c'getFileName >>= peekCString
-
-foreign import ccall safe "raylib.h &GetFileName"
-  p'getFileName ::
-    FunPtr (CString -> IO CString)
-
-foreign import ccall safe "raylib.h GetFileNameWithoutExt"
-  c'getFileNameWithoutExt ::
-    CString -> IO CString
-
-getFileNameWithoutExt :: String -> IO String
-getFileNameWithoutExt fileName = withCString fileName c'getFileNameWithoutExt >>= peekCString
-
-foreign import ccall safe "raylib.h &GetFileNameWithoutExt"
-  p'getFileNameWithoutExt ::
-    FunPtr (CString -> IO CString)
-
-foreign import ccall safe "raylib.h GetDirectoryPath"
-  c'getDirectoryPath ::
-    CString -> IO CString
-
-getDirectoryPath :: String -> IO String
-getDirectoryPath filePath = withCString filePath c'getDirectoryPath >>= peekCString
-
-foreign import ccall safe "raylib.h &GetDirectoryPath"
-  p'getDirectoryPath ::
-    FunPtr (CString -> IO CString)
-
-foreign import ccall safe "raylib.h GetPrevDirectoryPath"
-  c'getPrevDirectoryPath ::
-    CString -> IO CString
-
-getPrevDirectoryPath :: String -> IO String
-getPrevDirectoryPath dirPath = withCString dirPath c'getPrevDirectoryPath >>= peekCString
-
-foreign import ccall safe "raylib.h &GetPrevDirectoryPath"
-  p'getPrevDirectoryPath ::
-    FunPtr (CString -> IO CString)
-
-foreign import ccall safe "raylib.h GetWorkingDirectory"
-  c'getWorkingDirectory ::
-    IO CString
-
-getWorkingDirectory :: IO String
-getWorkingDirectory = c'getWorkingDirectory >>= peekCString
-
-foreign import ccall safe "raylib.h &GetWorkingDirectory"
-  p'getWorkingDirectory ::
-    FunPtr (IO CString)
-
-foreign import ccall safe "raylib.h GetApplicationDirectory"
-  c'getApplicationDirectory ::
-    IO CString
-
-getApplicationDirectory :: IO String
-getApplicationDirectory = c'getApplicationDirectory >>= peekCString
-
-foreign import ccall safe "raylib.h &GetApplicationDirectory"
-  p'getApplicationDirectory ::
-    FunPtr (IO CString)
-
-foreign import ccall safe "raylib.h ChangeDirectory"
-  c'changeDirectory ::
-    CString -> IO CBool
-
-changeDirectory :: String -> IO Bool
-changeDirectory dir = toBool <$> withCString dir c'changeDirectory
-
-foreign import ccall safe "raylib.h &ChangeDirectory"
-  p'changeDirectory ::
-    FunPtr (CString -> IO CInt)
-
-foreign import ccall safe "raylib.h IsPathFile"
-  c'isPathFile ::
-    CString -> IO CBool
-
-isPathFile :: String -> IO Bool
-isPathFile path = toBool <$> withCString path c'isPathFile
-
-foreign import ccall safe "raylib.h &IsPathFile"
-  p'isPathFile ::
-    FunPtr (CString -> IO CInt)
-
-foreign import ccall safe "bindings.h LoadDirectoryFiles_" c'loadDirectoryFiles :: CString -> IO (Ptr Raylib.Types.FilePathList)
-
-loadDirectoryFiles :: String -> IO Raylib.Types.FilePathList
-loadDirectoryFiles dirPath = withCString dirPath c'loadDirectoryFiles >>= pop
-
-foreign import ccall safe "raylib.h &LoadDirectoryFiles"
-  p'loadDirectoryFiles ::
-    FunPtr (CString -> IO Raylib.Types.FilePathList)
-
-foreign import ccall safe "bindings.h LoadDirectoryFilesEx_" c'loadDirectoryFilesEx :: CString -> CString -> CInt -> IO (Ptr Raylib.Types.FilePathList)
-
-loadDirectoryFilesEx :: String -> String -> Bool -> IO Raylib.Types.FilePathList
-loadDirectoryFilesEx basePath filterStr scanSubdirs =
-  withCString basePath (\b -> withCString filterStr (\f -> c'loadDirectoryFilesEx b f (fromBool scanSubdirs))) >>= pop
-
-foreign import ccall safe "raylib.h &LoadDirectoryFilesEx"
-  p'loadDirectoryFilesEx ::
-    FunPtr (CString -> CString -> CInt -> IO Raylib.Types.FilePathList)
-
-foreign import ccall safe "bindings.h UnloadDirectoryFiles_" c'unloadDirectoryFiles :: Ptr Raylib.Types.FilePathList -> IO ()
-
-unloadDirectoryFiles :: Raylib.Types.FilePathList -> IO ()
-unloadDirectoryFiles files = with files c'unloadDirectoryFiles
-
-foreign import ccall safe "raylib.h &UnloadDirectoryFiles"
-  p'unloadDirectoryFiles ::
-    FunPtr (Raylib.Types.FilePathList -> IO ())
-
-foreign import ccall safe "raylib.h IsFileDropped"
-  c'isFileDropped ::
-    IO CBool
-
-isFileDropped :: IO Bool
-isFileDropped = toBool <$> c'isFileDropped
-
-foreign import ccall safe "raylib.h &IsFileDropped"
-  p'isFileDropped ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "bindings.h LoadDroppedFiles_" c'loadDroppedFiles :: IO (Ptr Raylib.Types.FilePathList)
-
-loadDroppedFiles :: IO Raylib.Types.FilePathList
-loadDroppedFiles = c'loadDroppedFiles >>= pop
-
-foreign import ccall safe "raylib.h &LoadDroppedFiles"
-  p'loadDroppedFiles ::
-    FunPtr (IO Raylib.Types.FilePathList)
-
-foreign import ccall safe "bindings.h UnloadDroppedFiles_" c'unloadDroppedFiles :: Ptr Raylib.Types.FilePathList -> IO ()
-
-unloadDroppedFiles :: Raylib.Types.FilePathList -> IO ()
-unloadDroppedFiles files = with files c'unloadDroppedFiles
-
-foreign import ccall safe "raylib.h &UnloadDroppedFiles"
-  p'unloadDroppedFiles ::
-    FunPtr (Raylib.Types.FilePathList -> IO ())
-
-foreign import ccall safe "raylib.h GetFileModTime"
-  c'getFileModTime ::
-    CString -> IO CLong
-
-getFileModTime :: String -> IO Integer
-getFileModTime fileName = fromIntegral <$> withCString fileName c'getFileModTime
-
-foreign import ccall safe "raylib.h &GetFileModTime"
-  p'getFileModTime ::
-    FunPtr (CString -> IO CLong)
-
-foreign import ccall safe "raylib.h CompressData"
-  c'compressData ::
-    Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr CUChar)
-
-compressData :: [Integer] -> IO [Integer]
-compressData contents = do
-  withArrayLen
-    (map fromIntegral contents)
-    ( \size c -> do
-        with
-          0
-          ( \ptr -> do
-              compressed <- c'compressData c (fromIntegral $ size * sizeOf (0 :: CUChar)) ptr
-              compressedSize <- fromIntegral <$> peek ptr
-              arr <- peekArray compressedSize compressed
-              return $ map fromIntegral arr
-          )
-    )
-
-foreign import ccall safe "raylib.h &CompressData"
-  p'compressData ::
-    FunPtr (Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr CUChar))
-
-foreign import ccall safe "raylib.h DecompressData"
-  c'decompressData ::
-    Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr CUChar)
-
-decompressData :: [Integer] -> IO [Integer]
-decompressData compressedData = do
-  withArrayLen
-    (map fromIntegral compressedData)
-    ( \size c -> do
-        with
-          0
-          ( \ptr -> do
-              decompressed <- c'decompressData c (fromIntegral $ size * sizeOf (0 :: CUChar)) ptr
-              decompressedSize <- fromIntegral <$> peek ptr
-              arr <- peekArray decompressedSize decompressed
-              return $ map fromIntegral arr
-          )
-    )
-
-foreign import ccall safe "raylib.h &DecompressData"
-  p'decompressData ::
-    FunPtr (Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr CUChar))
-
-foreign import ccall safe "raylib.h EncodeDataBase64"
-  c'encodeDataBase64 ::
-    Ptr CUChar -> CInt -> Ptr CInt -> IO CString
-
-encodeDataBase64 :: [Integer] -> IO [Integer]
-encodeDataBase64 contents = do
-  withArrayLen
-    (map fromIntegral contents)
-    ( \size c -> do
-        with
-          0
-          ( \ptr -> do
-              encoded <- c'encodeDataBase64 c (fromIntegral $ size * sizeOf (0 :: CUChar)) ptr
-              encodedSize <- fromIntegral <$> peek ptr
-              arr <- peekArray encodedSize encoded
-              return $ map fromIntegral arr
-          )
-    )
-
-foreign import ccall safe "raylib.h &EncodeDataBase64"
-  p'encodeDataBase64 ::
-    FunPtr (Ptr CUChar -> CInt -> Ptr CInt -> IO CString)
-
-foreign import ccall safe "raylib.h DecodeDataBase64"
-  c'decodeDataBase64 ::
-    Ptr CUChar -> Ptr CInt -> IO (Ptr CUChar)
-
-decodeDataBase64 :: [Integer] -> IO [Integer]
-decodeDataBase64 encodedData = do
-  withArray
-    (map fromIntegral encodedData)
-    ( \c -> do
-        with
-          0
-          ( \ptr -> do
-              decoded <- c'decodeDataBase64 c ptr
-              decodedSize <- fromIntegral <$> peek ptr
-              arr <- peekArray decodedSize decoded
-              return $ map fromIntegral arr
-          )
-    )
-
-foreign import ccall safe "raylib.h &DecodeDataBase64"
-  p'decodeDataBase64 ::
-    FunPtr (Ptr CUChar -> Ptr CInt -> IO (Ptr CUChar))
-
-foreign import ccall safe "raylib.h IsKeyPressed"
-  c'isKeyPressed ::
-    CInt -> IO CBool
-
-isKeyPressed :: KeyboardKey -> IO Bool
-isKeyPressed key = toBool <$> c'isKeyPressed (fromIntegral $ fromEnum key)
-
-foreign import ccall safe "raylib.h &IsKeyPressed"
-  p'isKeyPressed ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h IsKeyDown"
-  c'isKeyDown ::
-    CInt -> IO CBool
-
-isKeyDown :: KeyboardKey -> IO Bool
-isKeyDown key = toBool <$> c'isKeyDown (fromIntegral $ fromEnum key)
-
-foreign import ccall safe "raylib.h &IsKeyDown"
-  p'isKeyDown ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h IsKeyReleased"
-  c'isKeyReleased ::
-    CInt -> IO CBool
-
-isKeyReleased :: KeyboardKey -> IO Bool
-isKeyReleased key = toBool <$> c'isKeyReleased (fromIntegral $ fromEnum key)
-
-foreign import ccall safe "raylib.h &IsKeyReleased"
-  p'isKeyReleased ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h IsKeyUp"
-  c'isKeyUp ::
-    CInt -> IO CBool
-
-isKeyUp :: KeyboardKey -> IO Bool
-isKeyUp key = toBool <$> c'isKeyUp (fromIntegral $ fromEnum key)
-
-foreign import ccall safe "raylib.h &IsKeyUp"
-  p'isKeyUp ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h SetExitKey"
-  c'setExitKey ::
-    CInt -> IO ()
-
-setExitKey :: KeyboardKey -> IO ()
-setExitKey = c'setExitKey . fromIntegral . fromEnum
-
-foreign import ccall safe "raylib.h &SetExitKey"
-  p'setExitKey ::
-    FunPtr (CInt -> IO ())
-
-foreign import ccall safe "raylib.h GetKeyPressed"
-  c'getKeyPressed ::
-    IO CInt
-
-getKeyPressed :: IO KeyboardKey
-getKeyPressed = toEnum . fromIntegral <$> c'getKeyPressed
-
-foreign import ccall safe "raylib.h &GetKeyPressed"
-  p'getKeyPressed ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetCharPressed"
-  c'getCharPressed ::
-    IO CInt
-
-getCharPressed :: IO Int
-getCharPressed = fromIntegral <$> c'getCharPressed
-
-foreign import ccall safe "raylib.h &GetCharPressed"
-  p'getCharPressed ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h IsGamepadAvailable"
-  c'isGamepadAvailable ::
-    CInt -> IO CBool
-
-isGamepadAvailable :: Int -> IO Bool
-isGamepadAvailable gamepad = toBool <$> c'isGamepadAvailable (fromIntegral gamepad)
-
-foreign import ccall safe "raylib.h &IsGamepadAvailable"
-  p'isGamepadAvailable ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetGamepadName"
-  c'getGamepadName ::
-    CInt -> IO CString
-
-getGamepadName :: Int -> IO String
-getGamepadName gamepad = c'getGamepadName (fromIntegral gamepad) >>= peekCString
-
-foreign import ccall safe "raylib.h &GetGamepadName"
-  p'getGamepadName ::
-    FunPtr (CInt -> IO CString)
-
-foreign import ccall safe "raylib.h IsGamepadButtonPressed"
-  c'isGamepadButtonPressed ::
-    CInt -> CInt -> IO CBool
-
-isGamepadButtonPressed :: Int -> GamepadButton -> IO Bool
-isGamepadButtonPressed gamepad button = toBool <$> c'isGamepadButtonPressed (fromIntegral gamepad) (fromIntegral $ fromEnum button)
-
-foreign import ccall safe "raylib.h &IsGamepadButtonPressed"
-  p'isGamepadButtonPressed ::
-    FunPtr (CInt -> CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h IsGamepadButtonDown"
-  c'isGamepadButtonDown ::
-    CInt -> CInt -> IO CBool
-
-isGamepadButtonDown :: Int -> GamepadButton -> IO Bool
-isGamepadButtonDown gamepad button = toBool <$> c'isGamepadButtonDown (fromIntegral gamepad) (fromIntegral $ fromEnum button)
-
-foreign import ccall safe "raylib.h &IsGamepadButtonDown"
-  p'isGamepadButtonDown ::
-    FunPtr (CInt -> CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h IsGamepadButtonReleased"
-  c'isGamepadButtonReleased ::
-    CInt -> CInt -> IO CBool
-
-isGamepadButtonReleased :: Int -> GamepadButton -> IO Bool
-isGamepadButtonReleased gamepad button = toBool <$> c'isGamepadButtonReleased (fromIntegral gamepad) (fromIntegral $ fromEnum button)
-
-foreign import ccall safe "raylib.h &IsGamepadButtonReleased"
-  p'isGamepadButtonReleased ::
-    FunPtr (CInt -> CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h IsGamepadButtonUp"
-  c'isGamepadButtonUp ::
-    CInt -> CInt -> IO CBool
-
-isGamepadButtonUp :: Int -> GamepadButton -> IO Bool
-isGamepadButtonUp gamepad button = toBool <$> c'isGamepadButtonUp (fromIntegral gamepad) (fromIntegral $ fromEnum button)
-
-foreign import ccall safe "raylib.h &IsGamepadButtonUp"
-  p'isGamepadButtonUp ::
-    FunPtr (CInt -> CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetGamepadButtonPressed"
-  c'getGamepadButtonPressed ::
-    IO CInt
-
-getGamepadButtonPressed :: IO GamepadButton
-getGamepadButtonPressed = toEnum . fromIntegral <$> c'getGamepadButtonPressed
-
-foreign import ccall safe "raylib.h &GetGamepadButtonPressed"
-  p'getGamepadButtonPressed ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetGamepadAxisCount"
-  c'getGamepadAxisCount ::
-    CInt -> IO CInt
-
-getGamepadAxisCount :: Int -> IO Int
-getGamepadAxisCount gamepad = fromIntegral <$> c'getGamepadAxisCount (fromIntegral gamepad)
-
-foreign import ccall safe "raylib.h &GetGamepadAxisCount"
-  p'getGamepadAxisCount ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetGamepadAxisMovement"
-  c'getGamepadAxisMovement ::
-    CInt -> CInt -> IO CFloat
-
-getGamepadAxisMovement :: Int -> GamepadAxis -> IO Float
-getGamepadAxisMovement gamepad axis = realToFrac <$> c'getGamepadAxisMovement (fromIntegral gamepad) (fromIntegral $ fromEnum axis)
-
-foreign import ccall safe "raylib.h &GetGamepadAxisMovement"
-  p'getGamepadAxisMovement ::
-    FunPtr (CInt -> CInt -> IO CFloat)
-
-foreign import ccall safe "raylib.h SetGamepadMappings"
-  c'setGamepadMappings ::
-    CString -> IO CInt
-
-setGamepadMappings :: String -> IO Int
-setGamepadMappings mappings = fromIntegral <$> withCString mappings c'setGamepadMappings
-
-foreign import ccall safe "raylib.h &SetGamepadMappings"
-  p'setGamepadMappings ::
-    FunPtr (CString -> IO CInt)
-
-foreign import ccall safe "raylib.h IsMouseButtonPressed"
-  c'isMouseButtonPressed ::
-    CInt -> IO CBool
-
-isMouseButtonPressed :: MouseButton -> IO Bool
-isMouseButtonPressed button = toBool <$> c'isMouseButtonPressed (fromIntegral $ fromEnum button)
-
-foreign import ccall safe "raylib.h &IsMouseButtonPressed"
-  p'isMouseButtonPressed ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h IsMouseButtonDown"
-  c'isMouseButtonDown ::
-    CInt -> IO CBool
-
-isMouseButtonDown :: MouseButton -> IO Bool
-isMouseButtonDown button = toBool <$> c'isMouseButtonDown (fromIntegral $ fromEnum button)
-
-foreign import ccall safe "raylib.h &IsMouseButtonDown"
-  p'isMouseButtonDown ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h IsMouseButtonReleased"
-  c'isMouseButtonReleased ::
-    CInt -> IO CBool
-
-isMouseButtonReleased :: MouseButton -> IO Bool
-isMouseButtonReleased button = toBool <$> c'isMouseButtonReleased (fromIntegral $ fromEnum button)
-
-foreign import ccall safe "raylib.h &IsMouseButtonReleased"
-  p'isMouseButtonReleased ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h IsMouseButtonUp"
-  c'isMouseButtonUp ::
-    CInt -> IO CBool
-
-isMouseButtonUp :: MouseButton -> IO Bool
-isMouseButtonUp button = toBool <$> c'isMouseButtonUp (fromIntegral $ fromEnum button)
-
-foreign import ccall safe "raylib.h &IsMouseButtonUp"
-  p'isMouseButtonUp ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetMouseX"
-  c'getMouseX ::
-    IO CInt
-
-getMouseX :: IO Int
-getMouseX = fromIntegral <$> c'getMouseX
-
-foreign import ccall safe "raylib.h &GetMouseX"
-  p'getMouseX ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetMouseY"
-  c'getMouseY ::
-    IO CInt
-
-getMouseY :: IO Int
-getMouseY = fromIntegral <$> c'getMouseY
-
-foreign import ccall safe "raylib.h &GetMouseY"
-  p'getMouseY ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "bindings.h GetMousePosition_" c'getMousePosition :: IO (Ptr Raylib.Types.Vector2)
-
-getMousePosition :: IO Raylib.Types.Vector2
-getMousePosition = c'getMousePosition >>= pop
-
-foreign import ccall safe "raylib.h &GetMousePosition"
-  p'getMousePosition ::
-    FunPtr (IO Raylib.Types.Vector2)
-
-foreign import ccall safe "bindings.h GetMouseDelta_" c'getMouseDelta :: IO (Ptr Raylib.Types.Vector2)
-
-getMouseDelta :: IO Raylib.Types.Vector2
-getMouseDelta = c'getMouseDelta >>= pop
-
-foreign import ccall safe "raylib.h &GetMouseDelta"
-  p'getMouseDelta ::
-    FunPtr (IO Raylib.Types.Vector2)
-
-foreign import ccall safe "raylib.h SetMousePosition"
-  c'setMousePosition ::
-    CInt -> CInt -> IO ()
-
-setMousePosition :: Int -> Int -> IO ()
-setMousePosition x y = c'setMousePosition (fromIntegral x) (fromIntegral y)
-
-foreign import ccall safe "raylib.h &SetMousePosition"
-  p'setMousePosition ::
-    FunPtr (CInt -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h SetMouseOffset"
-  c'setMouseOffset ::
-    CInt -> CInt -> IO ()
-
-setMouseOffset :: Int -> Int -> IO ()
-setMouseOffset x y = c'setMouseOffset (fromIntegral x) (fromIntegral y)
-
-foreign import ccall safe "raylib.h &SetMouseOffset"
-  p'setMouseOffset ::
-    FunPtr (CInt -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h SetMouseScale"
-  c'setMouseScale ::
-    CFloat -> CFloat -> IO ()
-
-setMouseScale :: Float -> Float -> IO ()
-setMouseScale x y = c'setMouseScale (realToFrac x) (realToFrac y)
-
-foreign import ccall safe "raylib.h &SetMouseScale"
-  p'setMouseScale ::
-    FunPtr (CFloat -> CFloat -> IO ())
-
-foreign import ccall safe "raylib.h GetMouseWheelMove"
-  c'getMouseWheelMove ::
-    IO CFloat
-
-getMouseWheelMove :: IO Float
-getMouseWheelMove = realToFrac <$> c'getMouseWheelMove
-
-foreign import ccall safe "raylib.h &GetMouseWheelMove"
-  p'getMouseWheelMove ::
-    FunPtr (IO CFloat)
-
-foreign import ccall safe "bindings.h GetMouseWheelMoveV_" c'getMouseWheelMoveV :: IO (Ptr Raylib.Types.Vector2)
-
-getMouseWheelMoveV :: IO Raylib.Types.Vector2
-getMouseWheelMoveV = c'getMouseWheelMoveV >>= pop
-
-foreign import ccall safe "raylib.h &GetMouseWheelMoveV"
-  p'getMouseWheelMoveV ::
-    FunPtr (IO Raylib.Types.Vector2)
-
-foreign import ccall safe "raylib.h SetMouseCursor"
-  c'setMouseCursor ::
-    CInt -> IO ()
-
-setMouseCursor :: MouseCursor -> IO ()
-setMouseCursor cursor = c'setMouseCursor . fromIntegral $ fromEnum cursor
-
-foreign import ccall safe "raylib.h &SetMouseCursor"
-  p'setMouseCursor ::
-    FunPtr (CInt -> IO ())
-
-foreign import ccall safe "raylib.h GetTouchX"
-  c'getTouchX ::
-    IO CInt
-
-getTouchX :: IO Int
-getTouchX = fromIntegral <$> c'getTouchX
-
-foreign import ccall safe "raylib.h &GetTouchX"
-  p'getTouchX ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetTouchY"
-  c'getTouchY ::
-    IO CInt
-
-getTouchY :: IO Int
-getTouchY = fromIntegral <$> c'getTouchY
-
-foreign import ccall safe "raylib.h &GetTouchY"
-  p'getTouchY ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "bindings.h GetTouchPosition_" c'getTouchPosition :: CInt -> IO (Ptr Raylib.Types.Vector2)
-
-getTouchPosition :: Int -> IO Raylib.Types.Vector2
-getTouchPosition index = c'getTouchPosition (fromIntegral index) >>= pop
-
-foreign import ccall safe "raylib.h &GetTouchPosition"
-  p'getTouchPosition ::
-    FunPtr (CInt -> IO Raylib.Types.Vector2)
-
-foreign import ccall safe "raylib.h GetTouchPointId"
-  c'getTouchPointId ::
-    CInt -> IO CInt
-
-getTouchPointId :: Int -> IO Int
-getTouchPointId index = fromIntegral <$> c'getTouchPointId (fromIntegral index)
-
-foreign import ccall safe "raylib.h &GetTouchPointId"
-  p'getTouchPointId ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetTouchPointCount"
-  c'getTouchPointCount ::
-    IO CInt
-
-getTouchPointCount :: IO Int
-getTouchPointCount = fromIntegral <$> c'getTouchPointCount
-
-foreign import ccall safe "raylib.h &GetTouchPointCount"
-  p'getTouchPointCount ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h SetGesturesEnabled"
-  c'setGesturesEnabled ::
-    CUInt -> IO ()
-
-setGesturesEnabled :: [Gesture] -> IO ()
-setGesturesEnabled flags = c'setGesturesEnabled (fromIntegral $ configsToBitflag flags)
-
-foreign import ccall safe "raylib.h &SetGesturesEnabled"
-  p'setGesturesEnabled ::
-    FunPtr (CUInt -> IO ())
-
-foreign import ccall safe "raylib.h IsGestureDetected"
-  c'isGestureDetected ::
-    CInt -> IO CBool
-
-isGestureDetected :: Gesture -> IO Bool
-isGestureDetected gesture = toBool <$> c'isGestureDetected (fromIntegral $ fromEnum gesture)
-
-foreign import ccall safe "raylib.h &IsGestureDetected"
-  p'isGestureDetected ::
-    FunPtr (CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetGestureDetected"
-  c'getGestureDetected ::
-    IO CInt
-
-getGestureDetected :: IO Gesture
-getGestureDetected = toEnum . fromIntegral <$> c'getGestureDetected
-
-foreign import ccall safe "raylib.h &GetGestureDetected"
-  p'getGestureDetected ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h GetGestureHoldDuration"
-  c'getGestureHoldDuration ::
-    IO CFloat
-
-getGestureHoldDuration :: IO Float
-getGestureHoldDuration = realToFrac <$> c'getGestureHoldDuration
-
-foreign import ccall safe "raylib.h &GetGestureHoldDuration"
-  p'getGestureHoldDuration ::
-    FunPtr (IO CFloat)
-
-foreign import ccall safe "bindings.h GetGestureDragVector_" c'getGestureDragVector :: IO (Ptr Raylib.Types.Vector2)
-
-getGestureDragVector :: IO Raylib.Types.Vector2
-getGestureDragVector = c'getGestureDragVector >>= pop
-
-foreign import ccall safe "raylib.h &GetGestureDragVector"
-  p'getGestureDragVector ::
-    FunPtr (IO Raylib.Types.Vector2)
-
-foreign import ccall safe "raylib.h GetGestureDragAngle"
-  c'getGestureDragAngle ::
-    IO CFloat
-
-getGestureDragAngle :: IO Float
-getGestureDragAngle = realToFrac <$> c'getGestureDragAngle
-
-foreign import ccall safe "raylib.h &GetGestureDragAngle"
-  p'getGestureDragAngle ::
-    FunPtr (IO CFloat)
-
-foreign import ccall safe "bindings.h GetGesturePinchVector_" c'getGesturePinchVector :: IO (Ptr Raylib.Types.Vector2)
-
-getGesturePinchVector :: IO Raylib.Types.Vector2
-getGesturePinchVector = c'getGesturePinchVector >>= pop
-
-foreign import ccall safe "raylib.h &GetGesturePinchVector"
-  p'getGesturePinchVector ::
-    FunPtr (IO Raylib.Types.Vector2)
-
-foreign import ccall safe "raylib.h GetGesturePinchAngle"
-  c'getGesturePinchAngle ::
-    IO CFloat
-
-getGesturePinchAngle :: IO Float
-getGesturePinchAngle = realToFrac <$> c'getGesturePinchAngle
-
-foreign import ccall safe "raylib.h &GetGesturePinchAngle"
-  p'getGesturePinchAngle ::
-    FunPtr (IO CFloat)
-
-foreign import ccall safe "bindings.h SetCameraMode_" c'setCameraMode :: Ptr Raylib.Types.Camera3D -> CInt -> IO ()
-
-setCameraMode :: Raylib.Types.Camera3D -> CameraMode -> IO ()
-setCameraMode camera mode = with camera (\c -> c'setCameraMode c (fromIntegral $ fromEnum mode))
-
-foreign import ccall safe "raylib.h &SetCameraMode"
-  p'setCameraMode ::
-    FunPtr (Raylib.Types.Camera3D -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h UpdateCamera"
-  c'updateCamera ::
-    Ptr Raylib.Types.Camera3D -> IO ()
-
-updateCamera :: Raylib.Types.Camera3D -> IO Raylib.Types.Camera3D
-updateCamera camera =
-  with
-    camera
-    ( \c -> do
-        c'updateCamera c
-        peek c
-    )
-
-foreign import ccall safe "raylib.h &UpdateCamera"
-  p'updateCamera ::
-    FunPtr (Ptr Raylib.Types.Camera3D -> IO ())
-
-foreign import ccall safe "raylib.h SetCameraPanControl"
-  c'setCameraPanControl ::
-    CInt -> IO ()
-
-setCameraPanControl :: Int -> IO ()
-setCameraPanControl keyPan = c'setCameraPanControl $ fromIntegral keyPan
-
-foreign import ccall safe "raylib.h &SetCameraPanControl"
-  p'setCameraPanControl ::
-    FunPtr (CInt -> IO ())
-
-foreign import ccall safe "raylib.h SetCameraAltControl"
-  c'setCameraAltControl ::
-    CInt -> IO ()
-
-setCameraAltControl :: Int -> IO ()
-setCameraAltControl keyAlt = c'setCameraAltControl $ fromIntegral keyAlt
-
-foreign import ccall safe "raylib.h &SetCameraAltControl"
-  p'setCameraAltControl ::
-    FunPtr (CInt -> IO ())
-
-foreign import ccall safe "raylib.h SetCameraSmoothZoomControl"
-  c'setCameraSmoothZoomControl ::
-    CInt -> IO ()
-
-setCameraSmoothZoomControl :: Int -> IO ()
-setCameraSmoothZoomControl keySmoothZoom = c'setCameraSmoothZoomControl $ fromIntegral keySmoothZoom
-
-foreign import ccall safe "raylib.h &SetCameraSmoothZoomControl"
-  p'setCameraSmoothZoomControl ::
-    FunPtr (CInt -> IO ())
-
-foreign import ccall safe "raylib.h SetCameraMoveControls"
-  c'setCameraMoveControls ::
-    CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> IO ()
-
-setCameraMoveControls :: Int -> Int -> Int -> Int -> Int -> Int -> IO ()
-setCameraMoveControls keyFront keyBack keyRight keyLeft keyUp keyDown =
-  c'setCameraMoveControls
-    (fromIntegral keyFront)
-    (fromIntegral keyBack)
-    (fromIntegral keyRight)
-    (fromIntegral keyLeft)
-    (fromIntegral keyUp)
-    (fromIntegral keyDown)
-
-foreign import ccall safe "raylib.h &SetCameraMoveControls"
-  p'setCameraMoveControls ::
-    FunPtr (CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h SetShapesTexture_" c'setShapesTexture :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> IO ()
-
-setShapesTexture :: Raylib.Types.Texture -> Raylib.Types.Rectangle -> IO ()
-setShapesTexture tex source = with tex (with source . c'setShapesTexture)
-
-foreign import ccall safe "raylib.h &SetShapesTexture"
-  p'setShapesTexture ::
-    FunPtr (Raylib.Types.Texture -> Raylib.Types.Rectangle -> IO ())
-
-foreign import ccall safe "bindings.h DrawPixel_" c'drawPixel :: CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawPixel :: Int -> Int -> Raylib.Types.Color -> IO ()
-drawPixel x y color = with color $ c'drawPixel (fromIntegral x) (fromIntegral y)
-
-foreign import ccall safe "raylib.h &DrawPixel"
-  p'drawPixel ::
-    FunPtr (CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawPixelV_" c'drawPixelV :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-drawPixelV :: Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
-drawPixelV position color = with position (with color . c'drawPixelV)
-
-foreign import ccall safe "raylib.h &DrawPixelV"
-  p'drawPixelV ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawLine_" c'drawLine :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawLine :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO ()
-drawLine startX startY endX endY color =
-  with color $ c'drawLine (fromIntegral startX) (fromIntegral startY) (fromIntegral endX) (fromIntegral endY)
-
-foreign import ccall safe "raylib.h &DrawLine"
-  p'drawLine ::
-    FunPtr (CInt -> CInt -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawLineV_" c'drawLineV :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-drawLineV :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
-drawLineV start end color = with start (\s -> with end (with color . c'drawLineV s))
-
-foreign import ccall safe "raylib.h &DrawLineV"
-  p'drawLineV ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawLineEx_" c'drawLineEx :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawLineEx :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
-drawLineEx start end thickness color =
-  with start (\s -> with end (\e -> with color (c'drawLineEx s e (realToFrac thickness))))
-
-foreign import ccall safe "raylib.h &DrawLineEx"
-  p'drawLineEx ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawLineBezier_" c'drawLineBezier :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawLineBezier :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
-drawLineBezier start end thickness color =
-  with start (\s -> with end (\e -> with color (c'drawLineBezier s e (realToFrac thickness))))
-
-foreign import ccall safe "raylib.h &DrawLineBezier"
-  p'drawLineBezier ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawLineBezierQuad_" c'drawLineBezierQuad :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawLineBezierQuad :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
-drawLineBezierQuad start end control thickness color =
-  with start (\s -> with end (\e -> with control (\c -> with color (c'drawLineBezierQuad s e c (realToFrac thickness)))))
-
-foreign import ccall safe "raylib.h &DrawLineBezierQuad"
-  p'drawLineBezierQuad ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawLineBezierCubic_" c'drawLineBezierCubic :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawLineBezierCubic :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
-drawLineBezierCubic start end startControl endControl thickness color =
-  with
-    start
-    ( \s ->
-        with
-          end
-          ( \e ->
-              with
-                startControl
-                ( \sc ->
-                    with
-                      endControl
-                      ( \ec ->
-                          with
-                            color
-                            ( c'drawLineBezierCubic s e sc ec (realToFrac thickness)
-                            )
-                      )
-                )
-          )
-    )
-
-foreign import ccall safe "raylib.h &DrawLineBezierCubic"
-  p'drawLineBezierCubic ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawLineStrip_" c'drawLineStrip :: Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawLineStrip :: [Raylib.Types.Vector2] -> Raylib.Types.Color -> IO ()
-drawLineStrip points color = withArray points (\p -> with color $ c'drawLineStrip p (genericLength points))
-
-foreign import ccall safe "raylib.h &DrawLineStrip"
-  p'drawLineStrip ::
-    FunPtr (Ptr Raylib.Types.Vector2 -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCircle_" c'drawCircle :: CInt -> CInt -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawCircle :: Int -> Int -> Float -> Raylib.Types.Color -> IO ()
-drawCircle centerX centerY radius color = with color (c'drawCircle (fromIntegral centerX) (fromIntegral centerY) (realToFrac radius))
-
-foreign import ccall safe "raylib.h &DrawCircle"
-  p'drawCircle ::
-    FunPtr (CInt -> CInt -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCircleSector_" c'drawCircleSector :: Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawCircleSector :: Raylib.Types.Vector2 -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
-drawCircleSector center radius startAngle endAngle segments color =
-  with
-    center
-    ( \c ->
-        with
-          color
-          ( c'drawCircleSector c (realToFrac radius) (realToFrac startAngle) (realToFrac endAngle) (fromIntegral segments)
-          )
-    )
-
-foreign import ccall safe "raylib.h &DrawCircleSector"
-  p'drawCircleSector ::
-    FunPtr (Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCircleSectorLines_" c'drawCircleSectorLines :: Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawCircleSectorLines :: Raylib.Types.Vector2 -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
-drawCircleSectorLines center radius startAngle endAngle segments color =
-  with
-    center
-    ( \c ->
-        with
-          color
-          ( c'drawCircleSectorLines c (realToFrac radius) (realToFrac startAngle) (realToFrac endAngle) (fromIntegral segments)
-          )
-    )
-
-foreign import ccall safe "raylib.h &DrawCircleSectorLines"
-  p'drawCircleSectorLines ::
-    FunPtr (Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCircleGradient_" c'drawCircleGradient :: CInt -> CInt -> CFloat -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO ()
-
-drawCircleGradient :: Int -> Int -> Float -> Raylib.Types.Color -> Raylib.Types.Color -> IO ()
-drawCircleGradient centerX centerY radius color1 color2 =
-  with color1 (with color2 . c'drawCircleGradient (fromIntegral centerX) (fromIntegral centerY) (realToFrac radius))
-
-foreign import ccall safe "raylib.h &DrawCircleGradient"
-  p'drawCircleGradient ::
-    FunPtr (CInt -> CInt -> CFloat -> Raylib.Types.Color -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCircleV_" c'drawCircleV :: Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawCircleV :: Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
-drawCircleV center radius color =
-  with center (\c -> with color (c'drawCircleV c (realToFrac radius)))
-
-foreign import ccall safe "raylib.h &DrawCircleV"
-  p'drawCircleV ::
-    FunPtr (Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCircleLines_" c'drawCircleLines :: CInt -> CInt -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawCircleLines :: Int -> Int -> Float -> Raylib.Types.Color -> IO ()
-drawCircleLines centerX centerY radius color =
-  with color (c'drawCircleLines (fromIntegral centerX) (fromIntegral centerY) (realToFrac radius))
-
-foreign import ccall safe "raylib.h &DrawCircleLines"
-  p'drawCircleLines ::
-    FunPtr (CInt -> CInt -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawEllipse_" c'drawEllipse :: CInt -> CInt -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawEllipse :: Int -> Int -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawEllipse centerX centerY radiusH radiusV color =
-  with color (c'drawEllipse (fromIntegral centerX) (fromIntegral centerY) (realToFrac radiusH) (realToFrac radiusV))
-
-foreign import ccall safe "raylib.h &DrawEllipse"
-  p'drawEllipse ::
-    FunPtr (CInt -> CInt -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawEllipseLines_" c'drawEllipseLines :: CInt -> CInt -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawEllipseLines :: Int -> Int -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawEllipseLines centerX centerY radiusH radiusV color =
-  with color (c'drawEllipseLines (fromIntegral centerX) (fromIntegral centerY) (realToFrac radiusH) (realToFrac radiusV))
-
-foreign import ccall safe "raylib.h &DrawEllipseLines"
-  p'drawEllipseLines ::
-    FunPtr (CInt -> CInt -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRing_" c'drawRing :: Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawRing :: Raylib.Types.Vector2 -> Float -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
-drawRing center innerRadius outerRadius startAngle endAngle segments color =
-  with
-    center
-    ( \c ->
-        with
-          color
-          ( c'drawRing
-              c
-              (realToFrac innerRadius)
-              (realToFrac outerRadius)
-              (realToFrac startAngle)
-              (realToFrac endAngle)
-              (fromIntegral segments)
-          )
-    )
-
-foreign import ccall safe "raylib.h &DrawRing"
-  p'drawRing ::
-    FunPtr (Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CFloat -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRingLines_" c'drawRingLines :: Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawRingLines :: Raylib.Types.Vector2 -> Float -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
-drawRingLines center innerRadius outerRadius startAngle endAngle segments color =
-  with
-    center
-    ( \c ->
-        with
-          color
-          ( c'drawRingLines
-              c
-              (realToFrac innerRadius)
-              (realToFrac outerRadius)
-              (realToFrac startAngle)
-              (realToFrac endAngle)
-              (fromIntegral segments)
-          )
-    )
-
-foreign import ccall safe "raylib.h &DrawRingLines"
-  p'drawRingLines ::
-    FunPtr (Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CFloat -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectangle_" c'drawRectangle :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectangle :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO ()
-drawRectangle posX posY width height color =
-  with color (c'drawRectangle (fromIntegral posX) (fromIntegral posY) (fromIntegral width) (fromIntegral height))
-
-foreign import ccall safe "raylib.h &DrawRectangle"
-  p'drawRectangle ::
-    FunPtr (CInt -> CInt -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectangleV_" c'drawRectangleV :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectangleV :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
-drawRectangleV position size color = with position (\p -> with size (with color . c'drawRectangleV p))
-
-foreign import ccall safe "raylib.h &DrawRectangleV"
-  p'drawRectangleV ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectangleRec_" c'drawRectangleRec :: Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectangleRec :: Raylib.Types.Rectangle -> Raylib.Types.Color -> IO ()
-drawRectangleRec rect color = with rect (with color . c'drawRectangleRec)
-
-foreign import ccall safe "raylib.h &DrawRectangleRec"
-  p'drawRectangleRec ::
-    FunPtr (Raylib.Types.Rectangle -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectanglePro_" c'drawRectanglePro :: Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectanglePro :: Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
-drawRectanglePro rect origin rotation color =
-  with color (\c -> with rect (\r -> with origin (\o -> c'drawRectanglePro r o (realToFrac rotation) c)))
-
-foreign import ccall safe "raylib.h &DrawRectanglePro"
-  p'drawRectanglePro ::
-    FunPtr (Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectangleGradientV_" c'drawRectangleGradientV :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectangleGradientV :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> Raylib.Types.Color -> IO ()
-drawRectangleGradientV posX posY width height color1 color2 =
-  with
-    color1
-    ( with color2
-        . c'drawRectangleGradientV
-          (fromIntegral posX)
-          (fromIntegral posY)
-          (fromIntegral width)
-          (fromIntegral height)
-    )
-
-foreign import ccall safe "raylib.h &DrawRectangleGradientV"
-  p'drawRectangleGradientV ::
-    FunPtr (CInt -> CInt -> CInt -> CInt -> Raylib.Types.Color -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectangleGradientH_" c'drawRectangleGradientH :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectangleGradientH :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> Raylib.Types.Color -> IO ()
-drawRectangleGradientH posX posY width height color1 color2 =
-  with
-    color1
-    ( with color2
-        . c'drawRectangleGradientH
-          (fromIntegral posX)
-          (fromIntegral posY)
-          (fromIntegral width)
-          (fromIntegral height)
-    )
-
-foreign import ccall safe "raylib.h &DrawRectangleGradientH"
-  p'drawRectangleGradientH ::
-    FunPtr (CInt -> CInt -> CInt -> CInt -> Raylib.Types.Color -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectangleGradientEx_" c'drawRectangleGradientEx :: Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectangleGradientEx :: Raylib.Types.Rectangle -> Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color -> IO ()
-drawRectangleGradientEx rect col1 col2 col3 col4 =
-  with
-    rect
-    ( \r ->
-        with
-          col1
-          ( \c1 ->
-              with
-                col2
-                ( \c2 ->
-                    with col3 (with col4 . c'drawRectangleGradientEx r c1 c2)
-                )
-          )
-    )
-
-foreign import ccall safe "raylib.h &DrawRectangleGradientEx"
-  p'drawRectangleGradientEx ::
-    FunPtr (Raylib.Types.Rectangle -> Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectangleLines_" c'drawRectangleLines :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectangleLines :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO ()
-drawRectangleLines posX posY width height color =
-  with color (c'drawRectangleLines (fromIntegral posX) (fromIntegral posY) (fromIntegral width) (fromIntegral height))
-
-foreign import ccall safe "raylib.h &DrawRectangleLines"
-  p'drawRectangleLines ::
-    FunPtr (CInt -> CInt -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectangleLinesEx_" c'drawRectangleLinesEx :: Ptr Raylib.Types.Rectangle -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectangleLinesEx :: Raylib.Types.Rectangle -> Float -> Raylib.Types.Color -> IO ()
-drawRectangleLinesEx rect thickness color =
-  with color (\c -> with rect (\r -> c'drawRectangleLinesEx r (realToFrac thickness) c))
-
-foreign import ccall safe "raylib.h &DrawRectangleLinesEx"
-  p'drawRectangleLinesEx ::
-    FunPtr (Raylib.Types.Rectangle -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectangleRounded_" c'drawRectangleRounded :: Ptr Raylib.Types.Rectangle -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectangleRounded :: Raylib.Types.Rectangle -> Float -> Int -> Raylib.Types.Color -> IO ()
-drawRectangleRounded rect roundness segments color =
-  with rect (\r -> with color $ c'drawRectangleRounded r (realToFrac roundness) (fromIntegral segments))
-
-foreign import ccall safe "raylib.h &DrawRectangleRounded"
-  p'drawRectangleRounded ::
-    FunPtr (Raylib.Types.Rectangle -> CFloat -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRectangleRoundedLines_" c'drawRectangleRoundedLines :: Ptr Raylib.Types.Rectangle -> CFloat -> CInt -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawRectangleRoundedLines :: Raylib.Types.Rectangle -> Float -> Int -> Float -> Raylib.Types.Color -> IO ()
-drawRectangleRoundedLines rect roundness segments thickness color =
-  with rect (\r -> with color $ c'drawRectangleRoundedLines r (realToFrac roundness) (fromIntegral segments) (realToFrac thickness))
-
-foreign import ccall safe "raylib.h &DrawRectangleRoundedLines"
-  p'drawRectangleRoundedLines ::
-    FunPtr (Raylib.Types.Rectangle -> CFloat -> CInt -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTriangle_" c'drawTriangle :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-drawTriangle :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
-drawTriangle v1 v2 v3 color =
-  with
-    v1
-    ( \p1 ->
-        with
-          v2
-          ( \p2 -> with v3 (with color . c'drawTriangle p1 p2)
-          )
-    )
-
-foreign import ccall safe "raylib.h &DrawTriangle"
-  p'drawTriangle ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTriangleLines_" c'drawTriangleLines :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-drawTriangleLines :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
-drawTriangleLines v1 v2 v3 color =
-  with
-    v1
-    ( \p1 ->
-        with
-          v2
-          ( \p2 -> with v3 (with color . c'drawTriangleLines p1 p2)
-          )
-    )
-
-foreign import ccall safe "raylib.h &DrawTriangleLines"
-  p'drawTriangleLines ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTriangleFan_" c'drawTriangleFan :: Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawTriangleFan :: [Raylib.Types.Vector2] -> Raylib.Types.Color -> IO ()
-drawTriangleFan points color = withArray points (\p -> with color $ c'drawTriangleFan p (genericLength points))
-
-foreign import ccall safe "raylib.h &DrawTriangleFan"
-  p'drawTriangleFan ::
-    FunPtr (Ptr Raylib.Types.Vector2 -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTriangleStrip_" c'drawTriangleStrip :: Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawTriangleStrip :: [Raylib.Types.Vector2] -> Raylib.Types.Color -> IO ()
-drawTriangleStrip points color =
-  withArray points (\p -> with color $ c'drawTriangleStrip p (genericLength points))
-
-foreign import ccall safe "raylib.h &DrawTriangleStrip"
-  p'drawTriangleStrip ::
-    FunPtr (Ptr Raylib.Types.Vector2 -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawPoly_" c'drawPoly :: Ptr Raylib.Types.Vector2 -> CInt -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawPoly :: Raylib.Types.Vector2 -> Int -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawPoly center sides radius rotation color =
-  with center (\c -> with color $ c'drawPoly c (fromIntegral sides) (realToFrac radius) (realToFrac rotation))
-
-foreign import ccall safe "raylib.h &DrawPoly"
-  p'drawPoly ::
-    FunPtr (Raylib.Types.Vector2 -> CInt -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawPolyLines_" c'drawPolyLines :: Ptr Raylib.Types.Vector2 -> CInt -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawPolyLines :: Raylib.Types.Vector2 -> Int -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawPolyLines center sides radius rotation color =
-  with center (\c -> with color $ c'drawPolyLines c (fromIntegral sides) (realToFrac radius) (realToFrac rotation))
-
-foreign import ccall safe "raylib.h &DrawPolyLines"
-  p'drawPolyLines ::
-    FunPtr (Raylib.Types.Vector2 -> CInt -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawPolyLinesEx_" c'drawPolyLinesEx :: Ptr Raylib.Types.Vector2 -> CInt -> CFloat -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawPolyLinesEx :: Raylib.Types.Vector2 -> Int -> Float -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawPolyLinesEx center sides radius rotation thickness color =
-  with
-    center
-    ( \c ->
-        with color $
-          c'drawPolyLinesEx
-            c
-            (fromIntegral sides)
-            (realToFrac radius)
-            (realToFrac rotation)
-            (realToFrac thickness)
-    )
-
-foreign import ccall safe "raylib.h &DrawPolyLinesEx"
-  p'drawPolyLinesEx ::
-    FunPtr (Raylib.Types.Vector2 -> CInt -> CFloat -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h CheckCollisionRecs_" c'checkCollisionRecs :: Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Rectangle -> IO CBool
-
-checkCollisionRecs :: Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Bool
-checkCollisionRecs rec1 rec2 = unsafePerformIO $ toBool <$> with rec1 (with rec2 . c'checkCollisionRecs)
-
-foreign import ccall safe "raylib.h &CheckCollisionRecs"
-  p'checkCollisionRecs ::
-    FunPtr (Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> IO CInt)
-
-foreign import ccall safe "bindings.h CheckCollisionCircles_" c'checkCollisionCircles :: Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Vector2 -> CFloat -> IO CBool
-
-checkCollisionCircles :: Raylib.Types.Vector2 -> Float -> Raylib.Types.Vector2 -> Float -> Bool
-checkCollisionCircles center1 radius1 center2 radius2 =
-  unsafePerformIO $ toBool <$> with center1 (\c1 -> with center2 (\c2 -> c'checkCollisionCircles c1 (realToFrac radius1) c2 (realToFrac radius2)))
-
-foreign import ccall safe "raylib.h &CheckCollisionCircles"
-  p'checkCollisionCircles ::
-    FunPtr (Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Vector2 -> CFloat -> IO CInt)
-
-foreign import ccall safe "bindings.h CheckCollisionCircleRec_" c'checkCollisionCircleRec :: Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Rectangle -> IO CBool
-
-checkCollisionCircleRec :: Raylib.Types.Vector2 -> Float -> Raylib.Types.Rectangle -> Bool
-checkCollisionCircleRec center radius rect =
-  unsafePerformIO $ toBool <$> with center (\c -> with rect $ c'checkCollisionCircleRec c (realToFrac radius))
-
-foreign import ccall safe "raylib.h &CheckCollisionCircleRec"
-  p'checkCollisionCircleRec ::
-    FunPtr (Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Rectangle -> IO CInt)
-
-foreign import ccall safe "bindings.h CheckCollisionPointRec_" c'checkCollisionPointRec :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Rectangle -> IO CBool
-
-checkCollisionPointRec :: Raylib.Types.Vector2 -> Raylib.Types.Rectangle -> Bool
-checkCollisionPointRec point rect =
-  unsafePerformIO $ toBool <$> with point (with rect . c'checkCollisionPointRec)
-
-foreign import ccall safe "raylib.h &CheckCollisionPointRec"
-  p'checkCollisionPointRec ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Rectangle -> IO CInt)
-
-foreign import ccall safe "bindings.h CheckCollisionPointCircle_" c'checkCollisionPointCircle :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> IO CBool
-
-checkCollisionPointCircle :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Bool
-checkCollisionPointCircle point center radius =
-  unsafePerformIO $ toBool <$> with point (\p -> with center (\c -> c'checkCollisionPointCircle p c (realToFrac radius)))
-
-foreign import ccall safe "raylib.h &CheckCollisionPointCircle"
-  p'checkCollisionPointCircle ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> CFloat -> IO CInt)
-
-foreign import ccall safe "bindings.h CheckCollisionPointTriangle_" c'checkCollisionPointTriangle :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> IO CBool
-
-checkCollisionPointTriangle :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Bool
-checkCollisionPointTriangle point p1 p2 p3 =
-  unsafePerformIO $ toBool <$> with point (\p -> with p1 (\ptr1 -> with p2 (with p3 . c'checkCollisionPointTriangle p ptr1)))
-
-foreign import ccall safe "raylib.h &CheckCollisionPointTriangle"
-  p'checkCollisionPointTriangle ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> IO CInt)
-
-foreign import ccall safe "bindings.h CheckCollisionLines_" c'checkCollisionLines :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> IO CBool
-
--- | If a collision is found, returns @Just collisionPoint@, otherwise returns @Nothing@
-checkCollisionLines :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Maybe Raylib.Types.Vector2
-checkCollisionLines start1 end1 start2 end2 =
-  unsafePerformIO $
-    with
-      (Raylib.Types.Vector2 0 0)
-      ( \res -> do
-          foundCollision <- toBool <$> with start1 (\s1 -> with end1 (\e1 -> with start2 (\s2 -> with end2 (\e2 -> c'checkCollisionLines s1 e1 s2 e2 res))))
-          if foundCollision then Just <$> peek res else return Nothing
-      )
-
-foreign import ccall safe "raylib.h &CheckCollisionLines"
-  p'checkCollisionLines ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> IO CInt)
-
-foreign import ccall safe "bindings.h CheckCollisionPointLine_" c'checkCollisionPointLine :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CInt -> IO CBool
-
-checkCollisionPointLine :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Int -> Bool
-checkCollisionPointLine point p1 p2 threshold =
-  unsafePerformIO $ toBool <$> with point (\p -> with p1 (\ptr1 -> with p2 (\ptr2 -> c'checkCollisionPointLine p ptr1 ptr2 (fromIntegral threshold))))
-
-foreign import ccall safe "raylib.h &CheckCollisionPointLine"
-  p'checkCollisionPointLine ::
-    FunPtr (Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> CInt -> IO CInt)
-
-foreign import ccall safe "bindings.h GetCollisionRec_" c'getCollisionRec :: Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Rectangle -> IO (Ptr Raylib.Types.Rectangle)
-
-getCollisionRec :: Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle
-getCollisionRec rec1 rec2 =
-  unsafePerformIO $ with rec1 (with rec2 . c'getCollisionRec) >>= pop
-
-foreign import ccall safe "raylib.h &GetCollisionRec"
-  p'getCollisionRec ::
-    FunPtr (Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> IO Raylib.Types.Rectangle)
-
-foreign import ccall safe "bindings.h LoadImage_" c'loadImage :: CString -> IO (Ptr Raylib.Types.Image)
-
-loadImage :: String -> IO Raylib.Types.Image
-loadImage fileName = withCString fileName c'loadImage >>= pop
-
-foreign import ccall safe "raylib.h &LoadImage"
-  p'loadImage ::
-    FunPtr (CString -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h LoadImageRaw_" c'loadImageRaw :: CString -> CInt -> CInt -> CInt -> CInt -> IO (Ptr Raylib.Types.Image)
-
-loadImageRaw :: String -> Int -> Int -> Int -> Int -> IO Raylib.Types.Image
-loadImageRaw fileName width height format headerSize =
-  withCString fileName (\str -> c'loadImageRaw str (fromIntegral width) (fromIntegral height) (fromIntegral $ fromEnum format) (fromIntegral headerSize)) >>= pop
-
-foreign import ccall safe "raylib.h &LoadImageRaw"
-  p'loadImageRaw ::
-    FunPtr (CString -> CInt -> CInt -> CInt -> CInt -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h LoadImageAnim_" c'loadImageAnim :: CString -> Ptr CInt -> IO (Ptr Raylib.Types.Image)
-
--- | Returns the final image and the framees in a tuple, e.g. @(img, 18)@
-loadImageAnim :: String -> IO (Raylib.Types.Image, Int)
-loadImageAnim fileName =
-  with
-    0
-    ( \frames ->
-        withCString
-          fileName
-          ( \fn -> do
-              img <- c'loadImageAnim fn frames >>= pop
-              frameNum <- fromIntegral <$> peek frames
-              return (img, frameNum)
-          )
-    )
-
-foreign import ccall safe "raylib.h &LoadImageAnim"
-  p'loadImageAnim ::
-    FunPtr (CString -> Ptr CInt -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h LoadImageFromMemory_" c'loadImageFromMemory :: CString -> Ptr CUChar -> CInt -> IO (Ptr Raylib.Types.Image)
-
-loadImageFromMemory :: String -> [Integer] -> IO Raylib.Types.Image
-loadImageFromMemory fileType fileData =
-  withCString fileType (\ft -> withArrayLen (map fromIntegral fileData) (\size fd -> c'loadImageFromMemory ft fd (fromIntegral $ size * sizeOf (0 :: CUChar)))) >>= pop
-
-foreign import ccall safe "raylib.h &LoadImageFromMemory"
-  p'loadImageFromMemory ::
-    FunPtr (CString -> Ptr CUChar -> CInt -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h LoadImageFromTexture_" c'loadImageFromTexture :: Ptr Raylib.Types.Texture -> IO (Ptr Raylib.Types.Image)
-
-loadImageFromTexture :: Raylib.Types.Texture -> IO Raylib.Types.Image
-loadImageFromTexture tex = with tex c'loadImageFromTexture >>= pop
-
-foreign import ccall safe "raylib.h &LoadImageFromTexture"
-  p'loadImageFromTexture ::
-    FunPtr (Raylib.Types.Texture -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h LoadImageFromScreen_" c'loadImageFromScreen :: IO (Ptr Raylib.Types.Image)
-
-loadImageFromScreen :: IO Raylib.Types.Image
-loadImageFromScreen = c'loadImageFromScreen >>= pop
-
-foreign import ccall safe "raylib.h &LoadImageFromScreen"
-  p'loadImageFromScreen ::
-    FunPtr (IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h UnloadImage_" c'unloadImage :: Ptr Raylib.Types.Image -> IO ()
-
-unloadImage :: Raylib.Types.Image -> IO ()
-unloadImage image = with image c'unloadImage
-
-foreign import ccall safe "raylib.h &UnloadImage"
-  p'unloadImage ::
-    FunPtr (Raylib.Types.Image -> IO ())
-
-foreign import ccall safe "bindings.h ExportImage_" c'exportImage :: Ptr Raylib.Types.Image -> CString -> IO CBool
-
-exportImage :: Raylib.Types.Image -> String -> IO Bool
-exportImage image fileName = toBool <$> with image (withCString fileName . c'exportImage)
-
-foreign import ccall safe "raylib.h &ExportImage"
-  p'exportImage ::
-    FunPtr (Raylib.Types.Image -> CString -> IO CInt)
-
-foreign import ccall safe "bindings.h ExportImageAsCode_" c'exportImageAsCode :: Ptr Raylib.Types.Image -> CString -> IO CBool
-
-exportImageAsCode :: Raylib.Types.Image -> String -> IO Bool
-exportImageAsCode image fileName =
-  toBool <$> with image (withCString fileName . c'exportImageAsCode)
-
-foreign import ccall safe "raylib.h &ExportImageAsCode"
-  p'exportImageAsCode ::
-    FunPtr (Raylib.Types.Image -> CString -> IO CInt)
-
-foreign import ccall safe "bindings.h GenImageColor_" c'genImageColor :: CInt -> CInt -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
-
-genImageColor :: Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-genImageColor width height color =
-  with color (c'genImageColor (fromIntegral width) (fromIntegral height)) >>= pop
-
-foreign import ccall safe "raylib.h &GenImageColor"
-  p'genImageColor ::
-    FunPtr (CInt -> CInt -> Raylib.Types.Color -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h GenImageGradientV_" c'genImageGradientV :: CInt -> CInt -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
-
-genImageGradientV :: Int -> Int -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image
-genImageGradientV width height top bottom =
-  with top (with bottom . c'genImageGradientV (fromIntegral width) (fromIntegral height)) >>= pop
-
-foreign import ccall safe "raylib.h &GenImageGradientV"
-  p'genImageGradientV ::
-    FunPtr (CInt -> CInt -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h GenImageGradientH_" c'genImageGradientH :: CInt -> CInt -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
-
-genImageGradientH :: Int -> Int -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image
-genImageGradientH width height left right =
-  with left (with right . c'genImageGradientH (fromIntegral width) (fromIntegral height)) >>= pop
-
-foreign import ccall safe "raylib.h &GenImageGradientH"
-  p'genImageGradientH ::
-    FunPtr (CInt -> CInt -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h GenImageGradientRadial_" c'genImageGradientRadial :: CInt -> CInt -> CFloat -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
-
-genImageGradientRadial :: Int -> Int -> Float -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image
-genImageGradientRadial width height density inner outer =
-  with inner (with outer . c'genImageGradientRadial (fromIntegral width) (fromIntegral height) (realToFrac density)) >>= pop
-
-foreign import ccall safe "raylib.h &GenImageGradientRadial"
-  p'genImageGradientRadial ::
-    FunPtr (CInt -> CInt -> CFloat -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h GenImageChecked_" c'genImageChecked :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
-
-genImageChecked :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image
-genImageChecked width height checksX checksY col1 col2 =
-  with col1 (with col2 . c'genImageChecked (fromIntegral width) (fromIntegral height) (fromIntegral checksX) (fromIntegral checksY)) >>= pop
-
-foreign import ccall safe "raylib.h &GenImageChecked"
-  p'genImageChecked ::
-    FunPtr (CInt -> CInt -> CInt -> CInt -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h GenImageWhiteNoise_" c'genImageWhiteNoise :: CInt -> CInt -> CFloat -> IO (Ptr Raylib.Types.Image)
-
-genImageWhiteNoise :: Int -> Int -> Float -> IO Raylib.Types.Image
-genImageWhiteNoise width height factor =
-  c'genImageWhiteNoise (fromIntegral width) (fromIntegral height) (realToFrac factor) >>= pop
-
-foreign import ccall safe "raylib.h &GenImageWhiteNoise"
-  p'genImageWhiteNoise ::
-    FunPtr (CInt -> CInt -> CFloat -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h GenImagePerlinNoise_" c'genImagePerlinNoise :: CInt -> CInt -> CInt -> CInt -> CFloat -> IO (Ptr Raylib.Types.Image)
-
-genImagePerlinNoise :: Int -> Int -> Int -> Int -> Float -> IO Raylib.Types.Image
-genImagePerlinNoise width height offsetX offsetY scale = c'genImagePerlinNoise (fromIntegral width) (fromIntegral height) (fromIntegral offsetX) (fromIntegral offsetY) (realToFrac scale) >>= pop
-
-foreign import ccall safe "raylib.h &GenImagePerlinNoise" p'genImagePerlinNoise :: FunPtr (CInt -> CInt -> CInt -> CInt -> CFloat -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h GenImageCellular_" c'genImageCellular :: CInt -> CInt -> CInt -> IO (Ptr Raylib.Types.Image)
-
-genImageCellular :: Int -> Int -> Int -> IO Raylib.Types.Image
-genImageCellular width height tileSize =
-  c'genImageCellular (fromIntegral width) (fromIntegral height) (fromIntegral tileSize) >>= pop
-
-foreign import ccall safe "raylib.h &GenImageCellular"
-  p'genImageCellular ::
-    FunPtr (CInt -> CInt -> CInt -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h GenImageText_" c'genImageText :: CInt -> CInt -> CString -> IO (Ptr Raylib.Types.Image)
-
-genImageText :: Int -> Int -> String -> IO Raylib.Types.Image
-genImageText width height text =
-  withCString text (c'genImageText (fromIntegral width) (fromIntegral height)) >>= pop
-
-foreign import ccall safe "raylib.h &GenImageText"
-  p'genImageText ::
-    FunPtr (CInt -> CInt -> CString -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h ImageCopy_" c'imageCopy :: Ptr Raylib.Types.Image -> IO (Ptr Raylib.Types.Image)
-
-imageCopy :: Raylib.Types.Image -> IO Raylib.Types.Image
-imageCopy image = with image c'imageCopy >>= pop
-
-foreign import ccall safe "raylib.h &ImageCopy"
-  p'imageCopy ::
-    FunPtr (Raylib.Types.Image -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h ImageFromImage_" c'imageFromImage :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Rectangle -> IO (Ptr Raylib.Types.Image)
-
-imageFromImage :: Raylib.Types.Image -> Raylib.Types.Rectangle -> IO Raylib.Types.Image
-imageFromImage image rect = with image (with rect . c'imageFromImage) >>= pop
-
-foreign import ccall safe "raylib.h &ImageFromImage"
-  p'imageFromImage ::
-    FunPtr (Raylib.Types.Image -> Raylib.Types.Rectangle -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h ImageText_" c'imageText :: CString -> CInt -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
-
-imageText :: String -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageText text fontSize color =
-  withCString text (\t -> with color $ c'imageText t (fromIntegral fontSize)) >>= pop
-
-foreign import ccall safe "raylib.h &ImageText"
-  p'imageText ::
-    FunPtr (CString -> CInt -> Raylib.Types.Color -> IO Raylib.Types.Image)
-
-foreign import ccall safe "bindings.h ImageTextEx_" c'imageTextEx :: Ptr Raylib.Types.Font -> CString -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
-
-imageTextEx :: Raylib.Types.Font -> String -> Float -> Float -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageTextEx font text fontSize spacing tint =
-  with font (\f -> withCString text (\t -> with tint $ c'imageTextEx f t (realToFrac fontSize) (realToFrac spacing))) >>= pop
-
-foreign import ccall safe "raylib.h &ImageTextEx"
-  p'imageTextEx ::
-    FunPtr (Raylib.Types.Font -> CString -> CFloat -> CFloat -> Raylib.Types.Color -> IO Raylib.Types.Image)
-
-foreign import ccall safe "raylib.h ImageFormat"
-  c'imageFormat ::
-    Ptr Raylib.Types.Image -> CInt -> IO ()
-
-imageFormat :: Raylib.Types.Image -> PixelFormat -> IO Raylib.Types.Image
-imageFormat image newFormat =
-  with image (\i -> c'imageFormat i (fromIntegral $ fromEnum newFormat) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageFormat"
-  p'imageFormat ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h ImageToPOT_" c'imageToPOT :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> IO ()
-
-imageToPOT :: Raylib.Types.Image -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageToPOT image color = with image (\i -> with color (c'imageToPOT i) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageToPOT"
-  p'imageToPOT ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageCrop_" c'imageCrop :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Rectangle -> IO ()
-
-imageCrop :: Raylib.Types.Image -> Raylib.Types.Rectangle -> IO Raylib.Types.Image
-imageCrop image crop = with image (\i -> with crop (c'imageCrop i) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageCrop"
-  p'imageCrop ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Rectangle -> IO ())
-
-foreign import ccall safe "raylib.h ImageAlphaCrop"
-  c'imageAlphaCrop ::
-    Ptr Raylib.Types.Image -> CFloat -> IO ()
-
-imageAlphaCrop :: Raylib.Types.Image -> Float -> IO Raylib.Types.Image
-imageAlphaCrop image threshold = with image (\i -> c'imageAlphaCrop i (realToFrac threshold) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageAlphaCrop"
-  p'imageAlphaCrop ::
-    FunPtr (Ptr Raylib.Types.Image -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h ImageAlphaClear_" c'imageAlphaClear :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> CFloat -> IO ()
-
-imageAlphaClear :: Raylib.Types.Image -> Raylib.Types.Color -> Float -> IO Raylib.Types.Image
-imageAlphaClear image color threshold = with image (\i -> with color (\c -> c'imageAlphaClear i c (realToFrac threshold) >> peek i))
-
-foreign import ccall safe "raylib.h &ImageAlphaClear"
-  p'imageAlphaClear ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Color -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h ImageAlphaMask_" c'imageAlphaMask :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Image -> IO ()
-
-imageAlphaMask :: Raylib.Types.Image -> Raylib.Types.Image -> IO Raylib.Types.Image
-imageAlphaMask image alphaMask = with image (\i -> with alphaMask (c'imageAlphaMask i) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageAlphaMask"
-  p'imageAlphaMask ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Image -> IO ())
-
-foreign import ccall safe "raylib.h ImageAlphaPremultiply"
-  c'imageAlphaPremultiply ::
-    Ptr Raylib.Types.Image -> IO ()
-
-imageAlphaPremultiply :: Raylib.Types.Image -> IO Raylib.Types.Image
-imageAlphaPremultiply image = with image (\i -> c'imageAlphaPremultiply i >> peek i)
-
-foreign import ccall safe "raylib.h &ImageAlphaPremultiply"
-  p'imageAlphaPremultiply ::
-    FunPtr (Ptr Raylib.Types.Image -> IO ())
-
-
-foreign import ccall safe "raylib.h ImageBlurGaussian"
-  c'imageBlurGaussian ::
-    Ptr Raylib.Types.Image -> CInt -> IO ()
-
-imageBlurGaussian :: Raylib.Types.Image -> Int -> IO Raylib.Types.Image
-imageBlurGaussian image blurSize = with image (\i -> c'imageBlurGaussian i (fromIntegral blurSize) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageBlurGaussian"
-  p'imageBlurGaussian ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h ImageResize"
-  c'imageResize ::
-    Ptr Raylib.Types.Image -> CInt -> CInt -> IO ()
-
-imageResize :: Raylib.Types.Image -> Int -> Int -> IO Raylib.Types.Image
-imageResize image newWidth newHeight = with image (\i -> c'imageResize i (fromIntegral newWidth) (fromIntegral newHeight) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageResize"
-  p'imageResize ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h ImageResizeNN"
-  c'imageResizeNN ::
-    Ptr Raylib.Types.Image -> CInt -> CInt -> IO ()
-
-imageResizeNN :: Raylib.Types.Image -> Int -> Int -> IO Raylib.Types.Image
-imageResizeNN image newWidth newHeight = with image (\i -> c'imageResizeNN i (fromIntegral newWidth) (fromIntegral newHeight) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageResizeNN"
-  p'imageResizeNN ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h ImageResizeCanvas_" c'imageResizeCanvas :: Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-imageResizeCanvas :: Raylib.Types.Image -> Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageResizeCanvas image newWidth newHeight offsetX offsetY fill = with image (\i -> with fill (c'imageResizeCanvas i (fromIntegral newWidth) (fromIntegral newHeight) (fromIntegral offsetX) (fromIntegral offsetY)) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageResizeCanvas"
-  p'imageResizeCanvas ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "raylib.h ImageMipmaps"
-  c'imageMipmaps ::
-    Ptr Raylib.Types.Image -> IO ()
-
-imageMipmaps :: Raylib.Types.Image -> IO Raylib.Types.Image
-imageMipmaps image = with image (\i -> c'imageMipmaps i >> peek i)
-
-foreign import ccall safe "raylib.h &ImageMipmaps"
-  p'imageMipmaps ::
-    FunPtr (Ptr Raylib.Types.Image -> IO ())
-
-foreign import ccall safe "raylib.h ImageDither"
-  c'imageDither ::
-    Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> IO ()
-
-imageDither :: Raylib.Types.Image -> Int -> Int -> Int -> Int -> IO Raylib.Types.Image
-imageDither image rBpp gBpp bBpp aBpp = with image (\i -> c'imageDither i (fromIntegral rBpp) (fromIntegral gBpp) (fromIntegral bBpp) (fromIntegral aBpp) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDither"
-  p'imageDither ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h ImageFlipVertical"
-  c'imageFlipVertical ::
-    Ptr Raylib.Types.Image -> IO ()
-
-imageFlipVertical :: Raylib.Types.Image -> IO Raylib.Types.Image
-imageFlipVertical image = with image (\i -> c'imageFlipVertical i >> peek i)
-
-foreign import ccall safe "raylib.h &ImageFlipVertical"
-  p'imageFlipVertical ::
-    FunPtr (Ptr Raylib.Types.Image -> IO ())
-
-foreign import ccall safe "raylib.h ImageFlipHorizontal"
-  c'imageFlipHorizontal ::
-    Ptr Raylib.Types.Image -> IO ()
-
-imageFlipHorizontal :: Raylib.Types.Image -> IO Raylib.Types.Image
-imageFlipHorizontal image = with image (\i -> c'imageFlipHorizontal i >> peek i)
-
-foreign import ccall safe "raylib.h &ImageFlipHorizontal"
-  p'imageFlipHorizontal ::
-    FunPtr (Ptr Raylib.Types.Image -> IO ())
-
-foreign import ccall safe "raylib.h ImageRotateCW"
-  c'imageRotateCW ::
-    Ptr Raylib.Types.Image -> IO ()
-
-imageRotateCW :: Raylib.Types.Image -> IO Raylib.Types.Image
-imageRotateCW image = with image (\i -> c'imageRotateCW i >> peek i)
-
-foreign import ccall safe "raylib.h &ImageRotateCW"
-  p'imageRotateCW ::
-    FunPtr (Ptr Raylib.Types.Image -> IO ())
-
-foreign import ccall safe "raylib.h ImageRotateCCW"
-  c'imageRotateCCW ::
-    Ptr Raylib.Types.Image -> IO ()
-
-imageRotateCCW :: Raylib.Types.Image -> IO Raylib.Types.Image
-imageRotateCCW image = with image (\i -> c'imageRotateCCW i >> peek i)
-
-foreign import ccall safe "raylib.h &ImageRotateCCW"
-  p'imageRotateCCW ::
-    FunPtr (Ptr Raylib.Types.Image -> IO ())
-
-foreign import ccall safe "bindings.h ImageColorTint_" c'imageColorTint :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> IO ()
-
-imageColorTint :: Raylib.Types.Image -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageColorTint image color = with image (\i -> with color (c'imageColorTint i) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageColorTint"
-  p'imageColorTint ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "raylib.h ImageColorInvert"
-  c'imageColorInvert ::
-    Ptr Raylib.Types.Image -> IO ()
-
-imageColorInvert :: Raylib.Types.Image -> IO Raylib.Types.Image
-imageColorInvert image = with image (\i -> c'imageColorInvert i >> peek i)
-
-foreign import ccall safe "raylib.h &ImageColorInvert"
-  p'imageColorInvert ::
-    FunPtr (Ptr Raylib.Types.Image -> IO ())
-
-foreign import ccall safe "raylib.h ImageColorGrayscale"
-  c'imageColorGrayscale ::
-    Ptr Raylib.Types.Image -> IO ()
-
-imageColorGrayscale :: Raylib.Types.Image -> IO Raylib.Types.Image
-imageColorGrayscale image = with image (\i -> c'imageColorGrayscale i >> peek i)
-
-foreign import ccall safe "raylib.h &ImageColorGrayscale"
-  p'imageColorGrayscale ::
-    FunPtr (Ptr Raylib.Types.Image -> IO ())
-
-foreign import ccall safe "raylib.h ImageColorContrast"
-  c'imageColorContrast ::
-    Ptr Raylib.Types.Image -> CFloat -> IO ()
-
-imageColorContrast :: Raylib.Types.Image -> Float -> IO Raylib.Types.Image
-imageColorContrast image contrast = with image (\i -> c'imageColorContrast i (realToFrac contrast) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageColorContrast"
-  p'imageColorContrast ::
-    FunPtr (Ptr Raylib.Types.Image -> CFloat -> IO ())
-
-foreign import ccall safe "raylib.h ImageColorBrightness"
-  c'imageColorBrightness ::
-    Ptr Raylib.Types.Image -> CInt -> IO ()
-
-imageColorBrightness :: Raylib.Types.Image -> Int -> IO Raylib.Types.Image
-imageColorBrightness image brightness = with image (\i -> c'imageColorBrightness i (fromIntegral brightness) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageColorBrightness"
-  p'imageColorBrightness ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h ImageColorReplace_" c'imageColorReplace :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO ()
-
-imageColorReplace :: Raylib.Types.Image -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageColorReplace image color replace = with image (\i -> with color (with replace . c'imageColorReplace i) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageColorReplace"
-  p'imageColorReplace ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Color -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h LoadImageColors_" c'loadImageColors :: Ptr Raylib.Types.Image -> IO (Ptr Raylib.Types.Color)
-
-loadImageColors :: Raylib.Types.Image -> IO [Raylib.Types.Color]
-loadImageColors image =
-  with
-    image
-    ( \i -> do
-        colors <- c'loadImageColors i
-        colArray <- peekArray (fromIntegral $ Raylib.Types.image'width image * Raylib.Types.image'height image) colors
-        unloadImageColors colors
-        return colArray
-    )
-
-foreign import ccall safe "raylib.h &LoadImageColors"
-  p'loadImageColors ::
-    FunPtr (Raylib.Types.Image -> IO (Ptr Raylib.Types.Color))
-
-foreign import ccall safe "bindings.h LoadImagePalette_" c'loadImagePalette :: Ptr Raylib.Types.Image -> CInt -> Ptr CInt -> IO (Ptr Raylib.Types.Color)
-
-loadImagePalette :: Raylib.Types.Image -> Int -> IO [Raylib.Types.Color]
-loadImagePalette image maxPaletteSize =
-  with
-    image
-    ( \i -> do
-        (palette, num) <-
-          with
-            0
-            ( \size -> do
-                cols <- c'loadImagePalette i (fromIntegral maxPaletteSize) size
-                s <- peek size
-                return (cols, s)
-            )
-        colArray <- peekArray (fromIntegral num) palette
-        unloadImagePalette palette
-        return colArray
-    )
-
-foreign import ccall safe "raylib.h &LoadImagePalette"
-  p'loadImagePalette ::
-    FunPtr (Raylib.Types.Image -> CInt -> Ptr CInt -> IO (Ptr Raylib.Types.Color))
-
--- | NOTE: You usually won't need to use this. `loadImageColors` unloads the colors automatically. Only use this when you are using `c'loadImageColors` to load the colors.
-foreign import ccall safe "raylib.h UnloadImageColors"
-  unloadImageColors ::
-    Ptr Raylib.Types.Color -> IO ()
-
-foreign import ccall safe "raylib.h &UnloadImageColors"
-  p'unloadImageColors ::
-    FunPtr (Ptr Raylib.Types.Color -> IO ())
-
--- | NOTE: You usually won't need to use this. `loadImagePalette` unloads the colors automatically. Only use this when you are using `c'loadImagePalette` to load the colors.
-foreign import ccall safe "raylib.h UnloadImagePalette"
-  unloadImagePalette ::
-    Ptr Raylib.Types.Color -> IO ()
-
-foreign import ccall safe "raylib.h &UnloadImagePalette"
-  p'unloadImagePalette ::
-    FunPtr (Ptr Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h GetImageAlphaBorder_" c'getImageAlphaBorder :: Ptr Raylib.Types.Image -> CFloat -> IO (Ptr Raylib.Types.Rectangle)
-
-getImageAlphaBorder :: Raylib.Types.Image -> Float -> IO Raylib.Types.Rectangle
-getImageAlphaBorder image threshold = with image (\i -> c'getImageAlphaBorder i (realToFrac threshold)) >>= pop
-
-foreign import ccall safe "raylib.h &GetImageAlphaBorder"
-  p'getImageAlphaBorder ::
-    FunPtr (Raylib.Types.Image -> CFloat -> IO Raylib.Types.Rectangle)
-
-foreign import ccall safe "bindings.h GetImageColor_" c'getImageColor :: Ptr Raylib.Types.Image -> CInt -> CInt -> IO (Ptr Raylib.Types.Color)
-
-getImageColor :: Raylib.Types.Image -> Int -> Int -> IO Raylib.Types.Color
-getImageColor image x y = with image (\i -> c'getImageColor i (fromIntegral x) (fromIntegral y)) >>= pop
-
-foreign import ccall safe "raylib.h &GetImageColor"
-  p'getImageColor ::
-    FunPtr (Raylib.Types.Image -> CInt -> CInt -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h ImageClearBackground_" c'imageClearBackground :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> IO ()
-
-imageClearBackground :: Raylib.Types.Image -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageClearBackground image color = with image (\i -> with color (c'imageClearBackground i) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageClearBackground"
-  p'imageClearBackground ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawPixel_" c'imageDrawPixel :: Ptr Raylib.Types.Image -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawPixel :: Raylib.Types.Image -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawPixel image x y color = with image (\i -> with color (c'imageDrawPixel i (fromIntegral x) (fromIntegral y)) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawPixel"
-  p'imageDrawPixel ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawPixelV_" c'imageDrawPixelV :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawPixelV :: Raylib.Types.Image -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawPixelV image position color = with image (\i -> with position (with color . c'imageDrawPixelV i) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawPixelV"
-  p'imageDrawPixelV ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawLine_" c'imageDrawLine :: Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawLine :: Raylib.Types.Image -> Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawLine image startPosX startPosY endPosX endPosY color = with image (\i -> with color (c'imageDrawLine i (fromIntegral startPosX) (fromIntegral startPosY) (fromIntegral endPosX) (fromIntegral endPosY)) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawLine"
-  p'imageDrawLine ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawLineV_" c'imageDrawLineV :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawLineV :: Raylib.Types.Image -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawLineV image start end color = with image (\i -> with start (\s -> with end (with color . c'imageDrawLineV i s)) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawLineV"
-  p'imageDrawLineV ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawCircle_" c'imageDrawCircle :: Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawCircle :: Raylib.Types.Image -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawCircle image centerX centerY radius color = with image (\i -> with color (c'imageDrawCircle i (fromIntegral centerX) (fromIntegral centerY) (fromIntegral radius)) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawCircle"
-  p'imageDrawCircle ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawCircleV_" c'imageDrawCircleV :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawCircleV :: Raylib.Types.Image -> Raylib.Types.Vector2 -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawCircleV image center radius color = with image (\i -> with center (\c -> with color (c'imageDrawCircleV i c (fromIntegral radius))) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawCircleV"
-  p'imageDrawCircleV ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Vector2 -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawCircleLines_" c'imageDrawCircleLines :: Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawCircleLines :: Raylib.Types.Image -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawCircleLines image centerX centerY radius color = with image (\i -> with color (c'imageDrawCircleLines i (fromIntegral centerX) (fromIntegral centerY) (fromIntegral radius)) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawCircleLines"
-  p'imageDrawCircleLines ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Vector2 -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawCircleLinesV_" c'imageDrawCircleLinesV :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawCircleLinesV :: Raylib.Types.Image -> Raylib.Types.Vector2 -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawCircleLinesV image center radius color = with image (\i -> with center (\c -> with color (c'imageDrawCircleLinesV i c (fromIntegral radius))) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawCircleLinesV"
-  p'imageDrawCircleLinesV ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Vector2 -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawRectangle_" c'imageDrawRectangle :: Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawRectangle :: Raylib.Types.Image -> Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawRectangle image posX posY width height color = with image (\i -> with color (c'imageDrawRectangle i (fromIntegral posX) (fromIntegral posY) (fromIntegral width) (fromIntegral height)) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawRectangle"
-  p'imageDrawRectangle ::
-    FunPtr (Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawRectangleV_" c'imageDrawRectangleV :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawRectangleV :: Raylib.Types.Image -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawRectangleV image position size color = with image (\i -> with position (\p -> with size (with color . c'imageDrawRectangleV i p)) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawRectangleV"
-  p'imageDrawRectangleV ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawRectangleRec_" c'imageDrawRectangleRec :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawRectangleRec :: Raylib.Types.Image -> Raylib.Types.Rectangle -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawRectangleRec image rectangle color = with image (\i -> with rectangle (with color . c'imageDrawRectangleRec i) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawRectangleRec"
-  p'imageDrawRectangleRec ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Rectangle -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawRectangleLines_" c'imageDrawRectangleLines :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Rectangle -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawRectangleLines :: Raylib.Types.Image -> Raylib.Types.Rectangle -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawRectangleLines image rectangle thickness color = with image (\i -> with rectangle (\r -> with color (c'imageDrawRectangleLines i r (fromIntegral thickness))) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawRectangleLines"
-  p'imageDrawRectangleLines ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Rectangle -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDraw_" c'imageDraw :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Image -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Color -> IO ()
-
-imageDraw :: Raylib.Types.Image -> Raylib.Types.Image -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDraw image source srcRec dstRec tint = with image (\i -> with source (\s -> with srcRec (\sr -> with dstRec (with tint . c'imageDraw i s sr))) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDraw"
-  p'imageDraw ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Image -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawText_" c'imageDrawText :: Ptr Raylib.Types.Image -> CString -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawText :: Raylib.Types.Image -> String -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawText image text x y fontSize color = with image (\i -> withCString text (\t -> with color (c'imageDrawText i t (fromIntegral x) (fromIntegral y) (fromIntegral fontSize))) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawText"
-  p'imageDrawText ::
-    FunPtr (Ptr Raylib.Types.Image -> CString -> CInt -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h ImageDrawTextEx_" c'imageDrawTextEx :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Font -> CString -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-imageDrawTextEx :: Raylib.Types.Image -> Raylib.Types.Font -> String -> Raylib.Types.Vector2 -> Float -> Float -> Raylib.Types.Color -> IO Raylib.Types.Image
-imageDrawTextEx image font text position fontSize spacing tint = with image (\i -> with font (\f -> withCString text (\t -> with position (\p -> with tint (c'imageDrawTextEx i f t p (realToFrac fontSize) (realToFrac spacing))))) >> peek i)
-
-foreign import ccall safe "raylib.h &ImageDrawTextEx"
-  p'imageDrawTextEx ::
-    FunPtr (Ptr Raylib.Types.Image -> Raylib.Types.Font -> CString -> Raylib.Types.Vector2 -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h LoadTexture_" c'loadTexture :: CString -> IO (Ptr Raylib.Types.Texture)
-
-loadTexture :: String -> IO Raylib.Types.Texture
-loadTexture fileName = withCString fileName c'loadTexture >>= pop
-
-foreign import ccall safe "raylib.h &LoadTexture"
-  p'loadTexture ::
-    FunPtr (CString -> IO Raylib.Types.Texture)
-
-foreign import ccall safe "bindings.h LoadTextureFromImage_" c'loadTextureFromImage :: Ptr Raylib.Types.Image -> IO (Ptr Raylib.Types.Texture)
-
-loadTextureFromImage :: Raylib.Types.Image -> IO Raylib.Types.Texture
-loadTextureFromImage image = with image c'loadTextureFromImage >>= pop
-
-foreign import ccall safe "raylib.h &LoadTextureFromImage"
-  p'loadTextureFromImage ::
-    FunPtr (Raylib.Types.Image -> IO Raylib.Types.Texture)
-
-foreign import ccall safe "bindings.h LoadTextureCubemap_" c'loadTextureCubemap :: Ptr Raylib.Types.Image -> CInt -> IO (Ptr Raylib.Types.Texture)
-
-loadTextureCubemap :: Raylib.Types.Image -> CubemapLayout -> IO Raylib.Types.Texture
-loadTextureCubemap image layout = with image (\i -> c'loadTextureCubemap i (fromIntegral $ fromEnum layout)) >>= pop
-
-foreign import ccall safe "raylib.h &LoadTextureCubemap"
-  p'loadTextureCubemap ::
-    FunPtr (Raylib.Types.Image -> CInt -> IO Raylib.Types.Texture)
-
-foreign import ccall safe "bindings.h LoadRenderTexture_" c'loadRenderTexture :: CInt -> CInt -> IO (Ptr Raylib.Types.RenderTexture)
-
-loadRenderTexture :: Int -> Int -> IO Raylib.Types.RenderTexture
-loadRenderTexture width height = c'loadRenderTexture (fromIntegral width) (fromIntegral height) >>= pop
-
-foreign import ccall safe "raylib.h &LoadRenderTexture"
-  p'loadRenderTexture ::
-    FunPtr (CInt -> CInt -> IO Raylib.Types.RenderTexture)
-
-foreign import ccall safe "bindings.h UnloadTexture_" c'unloadTexture :: Ptr Raylib.Types.Texture -> IO ()
-
-unloadTexture :: Raylib.Types.Texture -> IO ()
-unloadTexture texture = with texture c'unloadTexture
-
-foreign import ccall safe "raylib.h &UnloadTexture"
-  p'unloadTexture ::
-    FunPtr (Raylib.Types.Texture -> IO ())
-
-foreign import ccall safe "bindings.h UnloadRenderTexture_" c'unloadRenderTexture :: Ptr Raylib.Types.RenderTexture -> IO ()
-
-unloadRenderTexture :: Raylib.Types.RenderTexture -> IO ()
-unloadRenderTexture target = with target c'unloadRenderTexture
-
-foreign import ccall safe "raylib.h &UnloadRenderTexture"
-  p'unloadRenderTexture ::
-    FunPtr (Raylib.Types.RenderTexture -> IO ())
-
-foreign import ccall safe "bindings.h UpdateTexture_" c'updateTexture :: Ptr Raylib.Types.Texture -> Ptr () -> IO ()
-
-updateTexture :: Raylib.Types.Texture -> Ptr () -> IO Raylib.Types.Texture
-updateTexture texture pixels = with texture (\t -> c'updateTexture t pixels >> peek t)
-
-foreign import ccall safe "raylib.h &UpdateTexture"
-  p'updateTexture ::
-    FunPtr (Raylib.Types.Texture -> Ptr () -> IO ())
-
-foreign import ccall safe "bindings.h UpdateTextureRec_" c'updateTextureRec :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr () -> IO ()
-
-updateTextureRec :: Raylib.Types.Texture -> Raylib.Types.Rectangle -> Ptr () -> IO Raylib.Types.Texture
-updateTextureRec texture rect pixels = with texture (\t -> with rect (\r -> c'updateTextureRec t r pixels) >> peek t)
-
-foreign import ccall safe "raylib.h &UpdateTextureRec"
-  p'updateTextureRec ::
-    FunPtr (Raylib.Types.Texture -> Raylib.Types.Rectangle -> Ptr () -> IO ())
-
-foreign import ccall safe "raylib.h GenTextureMipmaps"
-  c'genTextureMipmaps ::
-    Ptr Raylib.Types.Texture -> IO ()
-
-genTextureMipmaps :: Raylib.Types.Texture -> IO Raylib.Types.Texture
-genTextureMipmaps texture = with texture (\t -> c'genTextureMipmaps t >> peek t)
-
-foreign import ccall safe "raylib.h &GenTextureMipmaps"
-  p'genTextureMipmaps ::
-    FunPtr (Ptr Raylib.Types.Texture -> IO ())
-
-foreign import ccall safe "bindings.h SetTextureFilter_" c'setTextureFilter :: Ptr Raylib.Types.Texture -> CInt -> IO ()
-
-setTextureFilter :: Raylib.Types.Texture -> TextureFilter -> IO Raylib.Types.Texture
-setTextureFilter texture filterType = with texture (\t -> c'setTextureFilter t (fromIntegral $ fromEnum filterType) >> peek t)
-
-foreign import ccall safe "raylib.h &SetTextureFilter"
-  p'setTextureFilter ::
-    FunPtr (Raylib.Types.Texture -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h SetTextureWrap_" c'setTextureWrap :: Ptr Raylib.Types.Texture -> CInt -> IO ()
-
-setTextureWrap :: Raylib.Types.Texture -> TextureWrap -> IO Raylib.Types.Texture
-setTextureWrap texture wrap = with texture (\t -> c'setTextureWrap t (fromIntegral $ fromEnum wrap) >> peek t)
-
-foreign import ccall safe "raylib.h &SetTextureWrap"
-  p'setTextureWrap ::
-    FunPtr (Raylib.Types.Texture -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h DrawTexture_" c'drawTexture :: Ptr Raylib.Types.Texture -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawTexture :: Raylib.Types.Texture -> Int -> Int -> Raylib.Types.Color -> IO ()
-drawTexture texture x y tint = with texture (\t -> with tint (c'drawTexture t (fromIntegral x) (fromIntegral y)))
-
-foreign import ccall safe "raylib.h &DrawTexture"
-  p'drawTexture ::
-    FunPtr (Raylib.Types.Texture -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTextureV_" c'drawTextureV :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-drawTextureV :: Raylib.Types.Texture -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
-drawTextureV texture position color = with texture (\t -> with position (with color . c'drawTextureV t))
-
-foreign import ccall safe "raylib.h &DrawTextureV"
-  p'drawTextureV ::
-    FunPtr (Raylib.Types.Texture -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTextureEx_" c'drawTextureEx :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawTextureEx :: Raylib.Types.Texture -> Raylib.Types.Vector2 -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawTextureEx texture position rotation scale tint = with texture (\t -> with position (\p -> with tint (c'drawTextureEx t p (realToFrac rotation) (realToFrac scale))))
-
-foreign import ccall safe "raylib.h &DrawTextureEx"
-  p'drawTextureEx ::
-    FunPtr (Raylib.Types.Texture -> Raylib.Types.Vector2 -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTextureRec_" c'drawTextureRec :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-drawTextureRec :: Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
-drawTextureRec texture source position tint = with texture (\t -> with source (\s -> with position (with tint . c'drawTextureRec t s)))
-
-foreign import ccall safe "raylib.h &DrawTextureRec"
-  p'drawTextureRec ::
-    FunPtr (Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTexturePro_" c'drawTexturePro :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawTexturePro :: Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
-drawTexturePro texture source dest origin rotation tint = with texture (\t -> with source (\s -> with dest (\d -> with origin (\o -> with tint (c'drawTexturePro t s d o (realToFrac rotation))))))
-
-foreign import ccall safe "raylib.h &DrawTexturePro"
-  p'drawTexturePro ::
-    FunPtr (Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTextureNPatch_" c'drawTextureNPatch :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.NPatchInfo -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawTextureNPatch :: Raylib.Types.Texture -> Raylib.Types.NPatchInfo -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
-drawTextureNPatch texture nPatchInfo dest origin rotation tint = with texture (\t -> with nPatchInfo (\n -> with dest (\d -> with origin (\o -> with tint (c'drawTextureNPatch t n d o (realToFrac rotation))))))
-
-foreign import ccall safe "raylib.h &DrawTextureNPatch"
-  p'drawTextureNPatch ::
-    FunPtr (Raylib.Types.Texture -> Raylib.Types.NPatchInfo -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h Fade_" c'fade :: Ptr Raylib.Types.Color -> CFloat -> IO (Ptr Raylib.Types.Color)
-
-fade :: Raylib.Types.Color -> Float -> Raylib.Types.Color
-fade color alpha = unsafePerformIO $ with color (\c -> c'fade c (realToFrac alpha)) >>= pop
-
-foreign import ccall safe "raylib.h &Fade"
-  p'fade ::
-    FunPtr (Raylib.Types.Color -> CFloat -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h ColorToInt_" c'colorToInt :: Ptr Raylib.Types.Color -> IO CInt
-
-colorToInt :: Raylib.Types.Color -> Int
-colorToInt color = unsafePerformIO $ fromIntegral <$> with color c'colorToInt
-
-foreign import ccall safe "raylib.h &ColorToInt"
-  p'colorToInt ::
-    FunPtr (Raylib.Types.Color -> IO CInt)
-
-foreign import ccall safe "bindings.h ColorNormalize_" c'colorNormalize :: Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Vector4)
-
-colorNormalize :: Raylib.Types.Color -> Raylib.Types.Vector4
-colorNormalize color = unsafePerformIO $ with color c'colorNormalize >>= pop
-
-foreign import ccall safe "raylib.h &ColorNormalize"
-  p'colorNormalize ::
-    FunPtr (Raylib.Types.Color -> IO Raylib.Types.Vector4)
-
-foreign import ccall safe "bindings.h ColorFromNormalized_" c'colorFromNormalized :: Ptr Raylib.Types.Vector4 -> IO (Ptr Raylib.Types.Color)
-
-colorFromNormalized :: Raylib.Types.Vector4 -> Raylib.Types.Color
-colorFromNormalized normalized = unsafePerformIO $ with normalized c'colorFromNormalized >>= pop
-
-foreign import ccall safe "raylib.h &ColorFromNormalized"
-  p'colorFromNormalized ::
-    FunPtr (Raylib.Types.Vector4 -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h ColorToHSV_" c'colorToHSV :: Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Vector3)
-
-colorToHSV :: Raylib.Types.Color -> Raylib.Types.Vector3
-colorToHSV color = unsafePerformIO $ with color c'colorToHSV >>= pop
-
-foreign import ccall safe "raylib.h &ColorToHSV"
-  p'colorToHSV ::
-    FunPtr (Raylib.Types.Color -> IO Raylib.Types.Vector3)
-
-foreign import ccall safe "bindings.h ColorFromHSV_" c'colorFromHSV :: CFloat -> CFloat -> CFloat -> IO (Ptr Raylib.Types.Color)
-
-colorFromHSV :: Float -> Float -> Float -> Raylib.Types.Color
-colorFromHSV hue saturation value = unsafePerformIO $ c'colorFromHSV (realToFrac hue) (realToFrac saturation) (realToFrac value) >>= pop
-
-foreign import ccall safe "raylib.h &ColorFromHSV"
-  p'colorFromHSV ::
-    FunPtr (CFloat -> CFloat -> CFloat -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h ColorTint_" c'colorTint :: Ptr Color -> Ptr Color -> IO (Ptr Raylib.Types.Color)
-
-colorTint :: Color -> Color -> Raylib.Types.Color
-colorTint color tint = unsafePerformIO $ with color (with tint . c'colorTint) >>= pop
-
-foreign import ccall safe "raylib.h &ColorTint"
-  p'colorTint ::
-    FunPtr (Color -> Color -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h ColorBrightness_" c'colorBrightness :: Ptr Color -> CFloat -> IO (Ptr Raylib.Types.Color)
-
-colorBrightness :: Color -> Float -> Raylib.Types.Color
-colorBrightness color brightness = unsafePerformIO $ with color (\c -> c'colorBrightness c (realToFrac brightness)) >>= pop
-
-foreign import ccall safe "raylib.h &ColorBrightness"
-  p'colorBrightness ::
-    FunPtr (Color -> CFloat -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h ColorContrast_" c'colorContrast :: Ptr Color -> CFloat -> IO (Ptr Raylib.Types.Color)
-
-colorContrast :: Color -> Float -> Raylib.Types.Color
-colorContrast color contrast = unsafePerformIO $ with color (\c -> c'colorContrast c (realToFrac contrast)) >>= pop
-
-foreign import ccall safe "raylib.h &ColorContrast"
-  p'colorContrast ::
-    FunPtr (Color -> CFloat -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h ColorAlpha_" c'colorAlpha :: Ptr Raylib.Types.Color -> CFloat -> IO (Ptr Raylib.Types.Color)
-
-colorAlpha :: Raylib.Types.Color -> Float -> Raylib.Types.Color
-colorAlpha color alpha = unsafePerformIO $ with color (\c -> c'colorAlpha c (realToFrac alpha)) >>= pop
-
-foreign import ccall safe "raylib.h &ColorAlpha"
-  p'colorAlpha ::
-    FunPtr (Raylib.Types.Color -> CFloat -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h ColorAlphaBlend_" c'colorAlphaBlend :: Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Color)
-
-colorAlphaBlend :: Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color
-colorAlphaBlend dst src tint = unsafePerformIO $ with dst (\d -> with src (with tint . c'colorAlphaBlend d)) >>= pop
-
-foreign import ccall safe "raylib.h &ColorAlphaBlend"
-  p'colorAlphaBlend ::
-    FunPtr (Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h GetColor_" c'getColor :: CUInt -> IO (Ptr Raylib.Types.Color)
-
-getColor :: Integer -> Raylib.Types.Color
-getColor hexValue = unsafePerformIO $ c'getColor (fromIntegral hexValue) >>= pop
-
-foreign import ccall safe "raylib.h &GetColor"
-  p'getColor ::
-    FunPtr (CUInt -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h GetPixelColor_" c'getPixelColor :: Ptr () -> CInt -> IO (Ptr Raylib.Types.Color)
-
-getPixelColor :: Ptr () -> PixelFormat -> IO Raylib.Types.Color
-getPixelColor srcPtr format = c'getPixelColor srcPtr (fromIntegral $ fromEnum format) >>= pop
-
-foreign import ccall safe "raylib.h &GetPixelColor"
-  p'getPixelColor ::
-    FunPtr (Ptr () -> CInt -> IO Raylib.Types.Color)
-
-foreign import ccall safe "bindings.h SetPixelColor_" c'setPixelColor :: Ptr () -> Ptr Raylib.Types.Color -> CInt -> IO ()
-
-setPixelColor :: Ptr () -> Raylib.Types.Color -> PixelFormat -> IO ()
-setPixelColor dstPtr color format = with color (\c -> c'setPixelColor dstPtr c (fromIntegral $ fromEnum format))
-
-foreign import ccall safe "raylib.h &SetPixelColor"
-  p'setPixelColor ::
-    FunPtr (Ptr () -> Raylib.Types.Color -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h GetPixelDataSize"
-  c'getPixelDataSize ::
-    CInt -> CInt -> CInt -> IO CInt
-
-getPixelDataSize :: Int -> Int -> PixelFormat -> Int
-getPixelDataSize width height format = unsafePerformIO (fromIntegral <$> c'getPixelDataSize (fromIntegral width) (fromIntegral height) (fromIntegral $ fromEnum format))
-
-foreign import ccall safe "raylib.h &GetPixelDataSize"
-  p'getPixelDataSize ::
-    FunPtr (CInt -> CInt -> CInt -> IO CInt)
-
-foreign import ccall safe "bindings.h GetFontDefault_" c'getFontDefault :: IO (Ptr Raylib.Types.Font)
-
-getFontDefault :: IO Raylib.Types.Font
-getFontDefault = c'getFontDefault >>= pop
-
-foreign import ccall safe "raylib.h &GetFontDefault"
-  p'getFontDefault ::
-    FunPtr (IO Raylib.Types.Font)
-
-foreign import ccall safe "bindings.h LoadFont_" c'loadFont :: CString -> IO (Ptr Raylib.Types.Font)
-
-loadFont :: String -> IO Raylib.Types.Font
-loadFont fileName = withCString fileName c'loadFont >>= pop
-
-foreign import ccall safe "raylib.h &LoadFont"
-  p'loadFont ::
-    FunPtr (CString -> IO Raylib.Types.Font)
-
-foreign import ccall safe "bindings.h LoadFontEx_" c'loadFontEx :: CString -> CInt -> Ptr CInt -> CInt -> IO (Ptr Raylib.Types.Font)
-
-loadFontEx :: String -> Int -> [Int] -> Int -> IO Raylib.Types.Font
-loadFontEx fileName fontSize fontChars glyphCount = withCString fileName (\f -> withArray (map fromIntegral fontChars) (\c -> c'loadFontEx f (fromIntegral fontSize) c (fromIntegral glyphCount))) >>= pop
-
-foreign import ccall safe "raylib.h &LoadFontEx"
-  p'loadFontEx ::
-    FunPtr (CString -> CInt -> Ptr CInt -> CInt -> IO Raylib.Types.Font)
-
-foreign import ccall safe "bindings.h LoadFontFromImage_" c'loadFontFromImage :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> CInt -> IO (Ptr Raylib.Types.Font)
-
-loadFontFromImage :: Raylib.Types.Image -> Raylib.Types.Color -> Int -> IO Raylib.Types.Font
-loadFontFromImage image key firstChar = with image (\i -> with key (\k -> c'loadFontFromImage i k (fromIntegral firstChar))) >>= pop
-
-foreign import ccall safe "raylib.h &LoadFontFromImage"
-  p'loadFontFromImage ::
-    FunPtr (Raylib.Types.Image -> Raylib.Types.Color -> CInt -> IO Raylib.Types.Font)
-
-foreign import ccall safe "bindings.h LoadFontFromMemory_" c'loadFontFromMemory :: CString -> Ptr CUChar -> CInt -> CInt -> Ptr CInt -> CInt -> IO (Ptr Raylib.Types.Font)
-
-loadFontFromMemory :: String -> [Integer] -> Int -> [Int] -> Int -> IO Raylib.Types.Font
-loadFontFromMemory fileType fileData fontSize fontChars glyphCount = withCString fileType (\t -> withArrayLen (map fromIntegral fileData) (\size d -> withArray (map fromIntegral fontChars) (\c -> c'loadFontFromMemory t d (fromIntegral $ size * sizeOf (0 :: CUChar)) (fromIntegral fontSize) c (fromIntegral glyphCount)))) >>= pop
-
-foreign import ccall safe "raylib.h &LoadFontFromMemory"
-  p'loadFontFromMemory ::
-    FunPtr (CString -> Ptr CUChar -> CInt -> CInt -> Ptr CInt -> CInt -> IO Raylib.Types.Font)
-
-foreign import ccall safe "raylib.h LoadFontData"
-  c'loadFontData ::
-    Ptr CUChar -> CInt -> CInt -> Ptr CInt -> CInt -> CInt -> IO (Ptr Raylib.Types.GlyphInfo)
-
-loadFontData :: [Integer] -> Int -> [Int] -> Int -> FontType -> IO Raylib.Types.GlyphInfo
-loadFontData fileData fontSize fontChars glyphCount fontType = withArrayLen (map fromIntegral fileData) (\size d -> withArray (map fromIntegral fontChars) (\c -> c'loadFontData d (fromIntegral $ size * sizeOf (0 :: CUChar)) (fromIntegral fontSize) c (fromIntegral glyphCount) (fromIntegral $ fromEnum fontType))) >>= pop
-
-foreign import ccall safe "raylib.h &LoadFontData"
-  p'loadFontData ::
-    FunPtr (Ptr CUChar -> CInt -> CInt -> Ptr CInt -> CInt -> CInt -> IO (Ptr Raylib.Types.GlyphInfo))
-
-foreign import ccall safe "bindings.h GenImageFontAtlas_" c'genImageFontAtlas :: Ptr Raylib.Types.GlyphInfo -> Ptr (Ptr Raylib.Types.Rectangle) -> CInt -> CInt -> CInt -> CInt -> IO (Ptr Raylib.Types.Image)
-genImageFontAtlas :: [Raylib.Types.GlyphInfo] -> [[Raylib.Types.Rectangle]] -> Int -> Int -> Int -> Int -> IO Raylib.Types.Image
-genImageFontAtlas chars recs glyphCount fontSize padding packMethod = withArray chars (\c -> withArray2D recs (\r -> c'genImageFontAtlas c r (fromIntegral glyphCount) (fromIntegral fontSize) (fromIntegral padding) (fromIntegral packMethod))) >>= pop
-
-foreign import ccall safe "raylib.h &GenImageFontAtlas"
-  p'genImageFontAtlas ::
-    FunPtr (Ptr Raylib.Types.GlyphInfo -> Ptr (Ptr Raylib.Types.Rectangle) -> CInt -> CInt -> CInt -> CInt -> IO Raylib.Types.Image)
-
-foreign import ccall safe "raylib.h UnloadFontData"
-  c'unloadFontData ::
-    Ptr Raylib.Types.GlyphInfo -> CInt -> IO ()
-
-unloadFontData :: [Raylib.Types.GlyphInfo] -> IO ()
-unloadFontData glyphs = withArrayLen glyphs (\size g -> c'unloadFontData g (fromIntegral size))
-
-foreign import ccall safe "raylib.h &UnloadFontData"
-  p'unloadFontData ::
-    FunPtr (Ptr Raylib.Types.GlyphInfo -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h UnloadFont_" c'unloadFont :: Ptr Raylib.Types.Font -> IO ()
-
-unloadFont :: Raylib.Types.Font -> IO ()
-unloadFont font = with font c'unloadFont
-
-foreign import ccall safe "raylib.h &UnloadFont"
-  p'unloadFont ::
-    FunPtr (Raylib.Types.Font -> IO ())
-
-foreign import ccall safe "bindings.h ExportFontAsCode_" c'exportFontAsCode :: Ptr Raylib.Types.Font -> CString -> IO CBool
-
-exportFontAsCode :: Raylib.Types.Font -> String -> IO Bool
-exportFontAsCode font fileName = toBool <$> with font (withCString fileName . c'exportFontAsCode)
-
-foreign import ccall safe "raylib.h &ExportFontAsCode"
-  p'exportFontAsCode ::
-    FunPtr (Raylib.Types.Font -> CString -> IO CInt)
-
-foreign import ccall safe "raylib.h DrawFPS"
-  c'drawFPS ::
-    CInt -> CInt -> IO ()
-
-drawFPS :: Int -> Int -> IO ()
-drawFPS x y = c'drawFPS (fromIntegral x) (fromIntegral y)
-
-foreign import ccall safe "raylib.h &DrawFPS"
-  p'drawFPS ::
-    FunPtr (CInt -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h DrawText_" c'drawText :: CString -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawText :: String -> Int -> Int -> Int -> Raylib.Types.Color -> IO ()
-drawText text x y fontSize color = withCString text (\t -> with color (c'drawText t (fromIntegral x) (fromIntegral y) (fromIntegral fontSize)))
-
-foreign import ccall safe "raylib.h &DrawText"
-  p'drawText ::
-    FunPtr (CString -> CInt -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTextEx_" c'drawTextEx :: Ptr Raylib.Types.Font -> CString -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawTextEx :: Raylib.Types.Font -> String -> Raylib.Types.Vector2 -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawTextEx font text position fontSize spacing tint = with font (\f -> withCString text (\t -> with position (\p -> with tint (c'drawTextEx f t p (realToFrac fontSize) (realToFrac spacing)))))
-
-foreign import ccall safe "raylib.h &DrawTextEx"
-  p'drawTextEx ::
-    FunPtr (Raylib.Types.Font -> CString -> Raylib.Types.Vector2 -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTextPro_" c'drawTextPro :: Ptr Raylib.Types.Font -> CString -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawTextPro :: Raylib.Types.Font -> String -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawTextPro font text position origin rotation fontSize spacing tint = with font (\f -> withCString text (\t -> with position (\p -> with origin (\o -> with tint (c'drawTextPro f t p o (realToFrac rotation) (realToFrac fontSize) (realToFrac spacing))))))
-
-foreign import ccall safe "raylib.h &DrawTextPro"
-  p'drawTextPro ::
-    FunPtr (Raylib.Types.Font -> CString -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTextCodepoint_" c'drawTextCodepoint :: Ptr Raylib.Types.Font -> CInt -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawTextCodepoint :: Raylib.Types.Font -> Int -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
-drawTextCodepoint font codepoint position fontSize tint = with font (\f -> with position (\p -> with tint (c'drawTextCodepoint f (fromIntegral codepoint) p (realToFrac fontSize))))
-
-foreign import ccall safe "raylib.h &DrawTextCodepoint"
-  p'drawTextCodepoint ::
-    FunPtr (Raylib.Types.Font -> CInt -> Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTextCodepoints_" c'drawTextCodepoints :: Ptr Raylib.Types.Font -> Ptr CInt -> CInt -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawTextCodepoints :: Raylib.Types.Font -> [Int] -> Raylib.Types.Vector2 -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawTextCodepoints font codepoints position fontSize spacing tint = with font (\f -> withArrayLen (map fromIntegral codepoints) (\count cp -> with position (\p -> with tint (c'drawTextCodepoints f cp (fromIntegral count) p (realToFrac fontSize) (realToFrac spacing)))))
-
-foreign import ccall safe "raylib.h &DrawTextCodepoints"
-  p'drawTextCodepoints ::
-    FunPtr (Raylib.Types.Font -> Ptr CInt -> CInt -> Raylib.Types.Vector2 -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "raylib.h MeasureText"
-  c'measureText ::
-    CString -> CInt -> IO CInt
-
-measureText :: String -> Int -> IO Int
-measureText text fontSize = fromIntegral <$> withCString text (\t -> c'measureText t (fromIntegral fontSize))
-
-foreign import ccall safe "raylib.h &MeasureText"
-  p'measureText ::
-    FunPtr (CString -> CInt -> IO CInt)
-
-foreign import ccall safe "bindings.h MeasureTextEx_" c'measureTextEx :: Ptr Raylib.Types.Font -> CString -> CFloat -> CFloat -> IO (Ptr Raylib.Types.Vector2)
-
-measureTextEx :: Raylib.Types.Font -> String -> Float -> Float -> IO Raylib.Types.Vector2
-measureTextEx font text fontSize spacing = with font (\f -> withCString text (\t -> c'measureTextEx f t (realToFrac fontSize) (realToFrac spacing))) >>= pop
-
-foreign import ccall safe "raylib.h &MeasureTextEx"
-  p'measureTextEx ::
-    FunPtr (Raylib.Types.Font -> CString -> CFloat -> CFloat -> IO Raylib.Types.Vector2)
-
-foreign import ccall safe "bindings.h GetGlyphIndex_" c'getGlyphIndex :: Ptr Raylib.Types.Font -> CInt -> IO CInt
-
-getGlyphIndex :: Raylib.Types.Font -> Int -> IO Int
-getGlyphIndex font codepoint = fromIntegral <$> with font (\f -> c'getGlyphIndex f (fromIntegral codepoint))
-
-foreign import ccall safe "raylib.h &GetGlyphIndex"
-  p'getGlyphIndex ::
-    FunPtr (Raylib.Types.Font -> CInt -> IO CInt)
-
-foreign import ccall safe "bindings.h GetGlyphInfo_" c'getGlyphInfo :: Ptr Raylib.Types.Font -> CInt -> IO (Ptr Raylib.Types.GlyphInfo)
-
-getGlyphInfo :: Raylib.Types.Font -> Int -> IO Raylib.Types.GlyphInfo
-getGlyphInfo font codepoint = with font (\f -> c'getGlyphInfo f (fromIntegral codepoint)) >>= pop
-
-foreign import ccall safe "raylib.h &GetGlyphInfo"
-  p'getGlyphInfo ::
-    FunPtr (Raylib.Types.Font -> CInt -> IO Raylib.Types.GlyphInfo)
-
-foreign import ccall safe "bindings.h GetGlyphAtlasRec_" c'getGlyphAtlasRec :: Ptr Raylib.Types.Font -> CInt -> IO (Ptr Raylib.Types.Rectangle)
-
-getGlyphAtlasRec :: Raylib.Types.Font -> Int -> IO Raylib.Types.Rectangle
-getGlyphAtlasRec font codepoint = with font (\f -> c'getGlyphAtlasRec f (fromIntegral codepoint)) >>= pop
-
-foreign import ccall safe "raylib.h &GetGlyphAtlasRec"
-  p'getGlyphAtlasRec ::
-    FunPtr (Raylib.Types.Font -> CInt -> IO Raylib.Types.Rectangle)
-
-foreign import ccall safe "raylib.h LoadUTF8"
-  c'loadUTF8 ::
-    Ptr CInt -> CInt -> IO CString
-
-loadUTF8 :: [Integer] -> IO String
-loadUTF8 codepoints =
-  withArrayLen
-    (map fromIntegral codepoints)
-    ( \size c ->
-        c'loadUTF8 c (fromIntegral size)
-    )
-    >>= ( \s -> do
-            val <- peekCString s
-            unloadUTF8 s
-            return val
-        )
-
-foreign import ccall safe "raylib.h &LoadUTF8"
-  p'loadUTF8 ::
-    FunPtr (Ptr CInt -> CInt -> IO CString)
-
-foreign import ccall safe "raylib.h UnloadUTF8"
-  unloadUTF8 ::
-    CString -> IO ()
-
-foreign import ccall safe "raylib.h &UnloadUTF8"
-  p'unloadUTF8 ::
-    FunPtr (CString -> IO ())
-
-foreign import ccall safe "raylib.h LoadCodepoints"
-  c'loadCodepoints ::
-    CString -> Ptr CInt -> IO (Ptr CInt)
-
-loadCodepoints :: String -> IO [Int]
-loadCodepoints text =
-  withCString
-    text
-    ( \t ->
-        with
-          0
-          ( \n -> do
-              res <- c'loadCodepoints t n
-              num <- peek n
-              arr <- peekArray (fromIntegral num) res
-              unloadCodepoints res
-              return $ fromIntegral <$> arr
-          )
-    )
-
-foreign import ccall safe "raylib.h &LoadCodepoints"
-  p'loadCodepoints ::
-    FunPtr (CString -> Ptr CInt -> IO (Ptr CInt))
-
-foreign import ccall safe "raylib.h UnloadCodepoints"
-  unloadCodepoints ::
-    Ptr CInt -> IO ()
-
-foreign import ccall safe "raylib.h &UnloadCodepoints"
-  p'unloadCodepoints ::
-    FunPtr (Ptr CInt -> IO ())
-
-foreign import ccall safe "raylib.h GetCodepointCount"
-  c'getCodepointCount ::
-    CString -> IO CInt
-
-getCodepointCount :: String -> IO Int
-getCodepointCount text = fromIntegral <$> withCString text c'getCodepointCount
-
-foreign import ccall safe "raylib.h &GetCodepointCount"
-  p'getCodepointCount ::
-    FunPtr (CString -> IO CInt)
-
--- | Deprecated, use `getCodepointNext`
-foreign import ccall safe "raylib.h GetCodepoint"
-  getCodepoint ::
-    CString -> Ptr CInt -> IO CInt
-
-foreign import ccall safe "raylib.h &GetCodepoint"
-  p'getCodepoint ::
-    FunPtr (CString -> Ptr CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetCodepointNext"
-  c'getCodepointNext ::
-    CString -> Ptr CInt -> IO CInt
-
-getCodepointNext :: String -> IO (Int, Int)
-getCodepointNext text =
-  withCString
-    text
-    ( \t ->
-        with
-          0
-          ( \n ->
-              do
-                res <- c'getCodepointNext t n
-                num <- peek n
-                return (fromIntegral res, fromIntegral num)
-          )
-    )
-
-foreign import ccall safe "raylib.h &GetCodepointNext"
-  p'getCodepointNext ::
-    FunPtr (CString -> Ptr CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h GetCodepointPrevious"
-  c'getCodepointPrevious ::
-    CString -> Ptr CInt -> IO CInt
-
-getCodepointPrevious :: String -> IO (Int, Int)
-getCodepointPrevious text =
-  withCString
-    text
-    ( \t ->
-        with
-          0
-          ( \n ->
-              do
-                res <- c'getCodepointPrevious t n
-                num <- peek n
-                return (fromIntegral res, fromIntegral num)
-          )
-    )
-
-foreign import ccall safe "raylib.h &GetCodepointPrevious"
-  p'getCodepointPrevious ::
-    FunPtr (CString -> Ptr CInt -> IO CInt)
-
-foreign import ccall safe "raylib.h CodepointToUTF8"
-  c'codepointToUTF8 ::
-    CInt -> Ptr CInt -> IO CString
-
-codepointToUTF8 :: Int -> IO String
-codepointToUTF8 codepoint = with 0 (c'codepointToUTF8 $ fromIntegral codepoint) >>= peekCString
-
-foreign import ccall safe "raylib.h &CodepointToUTF8"
-  p'codepointToUTF8 ::
-    FunPtr (CInt -> Ptr CInt -> IO CString)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextCopy"
-  textCopy ::
-    CString -> CString -> IO CInt
-
-foreign import ccall safe "raylib.h &TextCopy"
-  p'textCopy ::
-    FunPtr (CString -> CString -> IO CInt)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextIsEqual"
-  textIsEqual ::
-    CString -> CString -> IO CInt
-
-foreign import ccall safe "raylib.h &TextIsEqual"
-  p'textIsEqual ::
-    FunPtr (CString -> CString -> IO CInt)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextLength"
-  textLength ::
-    CString -> IO CUInt
-
-foreign import ccall safe "raylib.h &TextLength"
-  p'textLength ::
-    FunPtr (CString -> IO CUInt)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextFormat"
-  textFormat ::
-    CString -> IO CString
-
-foreign import ccall safe "raylib.h &TextFormat"
-  p'textFormat ::
-    FunPtr (CString -> IO CString)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextSubtext"
-  textSubtext ::
-    CString -> CInt -> CInt -> IO CString
-
-foreign import ccall safe "raylib.h &TextSubtext"
-  p'textSubtext ::
-    FunPtr (CString -> CInt -> CInt -> IO CString)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextReplace"
-  textReplace ::
-    CString -> CString -> CString -> IO CString
-
-foreign import ccall safe "raylib.h &TextReplace"
-  p'textReplace ::
-    FunPtr (CString -> CString -> CString -> IO CString)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextInsert"
-  textInsert ::
-    CString -> CString -> CInt -> IO CString
-
-foreign import ccall safe "raylib.h &TextInsert"
-  p'textInsert ::
-    FunPtr (CString -> CString -> CInt -> IO CString)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextJoin"
-  textJoin ::
-    Ptr CString -> CInt -> CString -> IO CString
-
-foreign import ccall safe "raylib.h &TextJoin"
-  p'textJoin ::
-    FunPtr (Ptr CString -> CInt -> CString -> IO CString)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextSplit"
-  textSplit ::
-    CString -> CChar -> Ptr CInt -> IO (Ptr CString)
-
-foreign import ccall safe "raylib.h &TextSplit"
-  p'textSplit ::
-    FunPtr (CString -> CChar -> Ptr CInt -> IO (Ptr CString))
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextAppend"
-  textAppend ::
-    CString -> CString -> Ptr CInt -> IO ()
-
-foreign import ccall safe "raylib.h &TextAppend"
-  p'textAppend ::
-    FunPtr (CString -> CString -> Ptr CInt -> IO ())
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextFindIndex"
-  textFindIndex ::
-    CString -> CString -> IO CInt
-
-foreign import ccall safe "raylib.h &TextFindIndex"
-  p'textFindIndex ::
-    FunPtr (CString -> CString -> IO CInt)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextToUpper"
-  textToUpper ::
-    CString -> IO CString
-
-foreign import ccall safe "raylib.h &TextToUpper"
-  p'textToUpper ::
-    FunPtr (CString -> IO CString)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextToLower"
-  textToLower ::
-    CString -> IO CString
-
-foreign import ccall safe "raylib.h &TextToLower"
-  p'textToLower ::
-    FunPtr (CString -> IO CString)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextToPascal"
-  textToPascal ::
-    CString -> IO CString
-
-foreign import ccall safe "raylib.h &TextToPascal"
-  p'textToPascal ::
-    FunPtr (CString -> IO CString)
-
--- | Not required in Haskell
-foreign import ccall safe "raylib.h TextToInteger"
-  textToInteger ::
-    CString -> IO CInt
-
-foreign import ccall safe "raylib.h &TextToInteger"
-  p'textToInteger ::
-    FunPtr (CString -> IO CInt)
-
-foreign import ccall safe "bindings.h DrawLine3D_" c'drawLine3D :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
-
-drawLine3D :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
-drawLine3D start end color = with start (\s -> with end (with color . c'drawLine3D s))
-
-foreign import ccall safe "raylib.h &DrawLine3D"
-  p'drawLine3D ::
-    FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawPoint3D_" c'drawPoint3D :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
-
-drawPoint3D :: Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
-drawPoint3D point color = with point (with color . c'drawPoint3D)
-
-foreign import ccall safe "raylib.h &DrawPoint3D"
-  p'drawPoint3D ::
-    FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCircle3D_" c'drawCircle3D :: Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawCircle3D :: Raylib.Types.Vector3 -> Float -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Color -> IO ()
-drawCircle3D center radius rotationAxis rotationAngle color = with center (\c -> with rotationAxis (\r -> with color (c'drawCircle3D c (realToFrac radius) r (realToFrac rotationAngle))))
-
-foreign import ccall safe "raylib.h &DrawCircle3D"
-  p'drawCircle3D ::
-    FunPtr (Raylib.Types.Vector3 -> CFloat -> Raylib.Types.Vector3 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTriangle3D_" c'drawTriangle3D :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
-
-drawTriangle3D :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
-drawTriangle3D v1 v2 v3 color = with v1 (\p1 -> with v2 (\p2 -> with v3 (with color . c'drawTriangle3D p1 p2)))
-
-foreign import ccall safe "raylib.h &DrawTriangle3D"
-  p'drawTriangle3D ::
-    FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawTriangleStrip3D_" c'drawTriangleStrip3D :: Ptr Raylib.Types.Vector3 -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawTriangleStrip3D :: [Raylib.Types.Vector3] -> Int -> Raylib.Types.Color -> IO ()
-drawTriangleStrip3D points pointCount color = withArray points (\p -> with color (c'drawTriangleStrip3D p (fromIntegral pointCount)))
-
-foreign import ccall safe "raylib.h &DrawTriangleStrip3D"
-  p'drawTriangleStrip3D ::
-    FunPtr (Ptr Raylib.Types.Vector3 -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCube_" c'drawCube :: Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawCube :: Raylib.Types.Vector3 -> Float -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawCube position width height length color = with position (\p -> with color (c'drawCube p (realToFrac width) (realToFrac height) (realToFrac length)))
-
-foreign import ccall safe "raylib.h &DrawCube"
-  p'drawCube ::
-    FunPtr (Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCubeV_" c'drawCubeV :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
-
-drawCubeV :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
-drawCubeV position size color = with position (\p -> with size (with color . c'drawCubeV p))
-
-foreign import ccall safe "raylib.h &DrawCubeV"
-  p'drawCubeV ::
-    FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCubeWires_" c'drawCubeWires :: Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawCubeWires :: Raylib.Types.Vector3 -> Float -> Float -> Float -> Raylib.Types.Color -> IO ()
-drawCubeWires position width height length color = with position (\p -> with color (c'drawCubeWires p (realToFrac width) (realToFrac height) (realToFrac length)))
-
-foreign import ccall safe "raylib.h &DrawCubeWires"
-  p'drawCubeWires ::
-    FunPtr (Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCubeWiresV_" c'drawCubeWiresV :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
-
-drawCubeWiresV :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
-drawCubeWiresV position size color = with position (\p -> with size (with color . c'drawCubeWiresV p))
-
-foreign import ccall safe "raylib.h &DrawCubeWiresV"
-  p'drawCubeWiresV ::
-    FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawSphere_" c'drawSphere :: Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawSphere :: Raylib.Types.Vector3 -> Float -> Raylib.Types.Color -> IO ()
-drawSphere position radius color = with position (\p -> with color (c'drawSphere p (realToFrac radius)))
-
-foreign import ccall safe "raylib.h &DrawSphere"
-  p'drawSphere ::
-    FunPtr (Raylib.Types.Vector3 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawSphereEx_" c'drawSphereEx :: Ptr Raylib.Types.Vector3 -> CFloat -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawSphereEx :: Raylib.Types.Vector3 -> Float -> Int -> Int -> Raylib.Types.Color -> IO ()
-drawSphereEx position radius rings slices color = with position (\p -> with color (c'drawSphereEx p (realToFrac radius) (fromIntegral rings) (fromIntegral slices)))
-
-foreign import ccall safe "raylib.h &DrawSphereEx"
-  p'drawSphereEx ::
-    FunPtr (Raylib.Types.Vector3 -> CFloat -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawSphereWires_" c'drawSphereWires :: Ptr Raylib.Types.Vector3 -> CFloat -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawSphereWires :: Raylib.Types.Vector3 -> Float -> Int -> Int -> Raylib.Types.Color -> IO ()
-drawSphereWires position radius rings slices color = with position (\p -> with color (c'drawSphereWires p (realToFrac radius) (fromIntegral rings) (fromIntegral slices)))
-
-foreign import ccall safe "raylib.h &DrawSphereWires"
-  p'drawSphereWires ::
-    FunPtr (Raylib.Types.Vector3 -> CFloat -> CInt -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCylinder_" c'drawCylinder :: Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawCylinder :: Raylib.Types.Vector3 -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
-drawCylinder position radiusTop radiusBottom height slices color = with position (\p -> with color (c'drawCylinder p (realToFrac radiusTop) (realToFrac radiusBottom) (realToFrac height) (fromIntegral slices)))
-
-foreign import ccall safe "raylib.h &DrawCylinder"
-  p'drawCylinder ::
-    FunPtr (Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCylinderEx_" c'drawCylinderEx :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawCylinderEx :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
-drawCylinderEx start end startRadius endRadius sides color = with start (\s -> with end (\e -> with color (c'drawCylinderEx s e (realToFrac startRadius) (realToFrac endRadius) (fromIntegral sides))))
-
-foreign import ccall safe "raylib.h &DrawCylinderEx"
-  p'drawCylinderEx ::
-    FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> CFloat -> CFloat -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCylinderWires_" c'drawCylinderWires :: Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawCylinderWires :: Raylib.Types.Vector3 -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
-drawCylinderWires position radiusTop radiusBottom height slices color = with position (\p -> with color (c'drawCylinderWires p (realToFrac radiusTop) (realToFrac radiusBottom) (realToFrac height) (fromIntegral slices)))
-
-foreign import ccall safe "raylib.h &DrawCylinderWires"
-  p'drawCylinderWires ::
-    FunPtr (Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCylinderWiresEx_" c'drawCylinderWiresEx :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
-
-drawCylinderWiresEx :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
-drawCylinderWiresEx start end startRadius endRadius sides color = with start (\s -> with end (\e -> with color (c'drawCylinderWiresEx s e (realToFrac startRadius) (realToFrac endRadius) (fromIntegral sides))))
-
-foreign import ccall safe "raylib.h &DrawCylinderWiresEx"
-  p'drawCylinderWiresEx ::
-    FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> CFloat -> CFloat -> CInt -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCapsule_" c'drawCapsule :: Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()
-
-drawCapsule :: Vector3 -> Vector3 -> CFloat -> Int -> Int -> Color -> IO ()
-drawCapsule start end radius slices rings color = with start (\s -> with end (\e -> with color (c'drawCapsule s e (realToFrac radius) (fromIntegral slices) (fromIntegral rings))))
-
-foreign import ccall safe "raylib.h &DrawCapsule"
-  p'drawCapsule ::
-    FunPtr (Vector3 -> Vector3 -> CFloat -> CInt -> CInt -> Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawCapsuleWires_" c'drawCapsuleWires :: Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()
-
-drawCapsuleWires :: Vector3 -> Vector3 -> CFloat -> Int -> Int -> Color -> IO ()
-drawCapsuleWires start end radius slices rings color = with start (\s -> with end (\e -> with color (c'drawCapsuleWires s e (realToFrac radius) (fromIntegral slices) (fromIntegral rings))))
-
-foreign import ccall safe "raylib.h &DrawCapsuleWires"
-  p'drawCapsuleWires ::
-    FunPtr (Vector3 -> Vector3 -> CFloat -> CInt -> CInt -> Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawPlane_" c'drawPlane :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-drawPlane :: Raylib.Types.Vector3 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
-drawPlane center size color = with center (\c -> with size (with color . c'drawPlane c))
-
-foreign import ccall safe "raylib.h &DrawPlane"
-  p'drawPlane ::
-    FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawRay_" c'drawRay :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.Color -> IO ()
-
-drawRay :: Raylib.Types.Ray -> Raylib.Types.Color -> IO ()
-drawRay ray color = with ray (with color . c'drawRay)
-
-foreign import ccall safe "raylib.h &DrawRay"
-  p'drawRay ::
-    FunPtr (Raylib.Types.Ray -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "raylib.h DrawGrid"
-  c'drawGrid ::
-    CInt -> CFloat -> IO ()
-
-drawGrid :: Int -> Float -> IO ()
-drawGrid slices spacing = c'drawGrid (fromIntegral slices) (realToFrac spacing)
-
-foreign import ccall safe "raylib.h &DrawGrid"
-  p'drawGrid ::
-    FunPtr (CInt -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h LoadModel_" c'loadModel :: CString -> IO (Ptr Raylib.Types.Model)
-
-loadModel :: String -> IO Raylib.Types.Model
-loadModel fileName = withCString fileName c'loadModel >>= pop
-
-foreign import ccall safe "raylib.h &LoadModel"
-  p'loadModel ::
-    FunPtr (CString -> IO Raylib.Types.Model)
-
-foreign import ccall safe "bindings.h LoadModelFromMesh_" c'loadModelFromMesh :: Ptr Raylib.Types.Mesh -> IO (Ptr Raylib.Types.Model)
-
-loadModelFromMesh :: Raylib.Types.Mesh -> IO Raylib.Types.Model
-loadModelFromMesh mesh = with mesh c'loadModelFromMesh >>= pop
-
-foreign import ccall safe "raylib.h &LoadModelFromMesh"
-  p'loadModelFromMesh ::
-    FunPtr (Raylib.Types.Mesh -> IO Raylib.Types.Model)
-
-foreign import ccall safe "bindings.h UnloadModel_" c'unloadModel :: Ptr Raylib.Types.Model -> IO ()
-
-unloadModel :: Raylib.Types.Model -> IO ()
-unloadModel model = with model c'unloadModel
-
-foreign import ccall safe "raylib.h &UnloadModel"
-  p'unloadModel ::
-    FunPtr (Raylib.Types.Model -> IO ())
-
-foreign import ccall safe "bindings.h UnloadModelKeepMeshes_" c'unloadModelKeepMeshes :: Ptr Raylib.Types.Model -> IO ()
-
-unloadModelKeepMeshes :: Raylib.Types.Model -> IO ()
-unloadModelKeepMeshes model = with model c'unloadModelKeepMeshes
-
-foreign import ccall safe "raylib.h &UnloadModelKeepMeshes"
-  p'unloadModelKeepMeshes ::
-    FunPtr (Raylib.Types.Model -> IO ())
-
-foreign import ccall safe "bindings.h GetModelBoundingBox_" c'getModelBoundingBox :: Ptr Raylib.Types.Model -> IO (Ptr Raylib.Types.BoundingBox)
-
-getModelBoundingBox :: Raylib.Types.Model -> IO Raylib.Types.BoundingBox
-getModelBoundingBox model = with model c'getModelBoundingBox >>= pop
-
-foreign import ccall safe "raylib.h &GetModelBoundingBox"
-  p'getModelBoundingBox ::
-    FunPtr (Raylib.Types.Model -> IO Raylib.Types.BoundingBox)
-
-foreign import ccall safe "bindings.h DrawModel_" c'drawModel :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawModel :: Raylib.Types.Model -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Color -> IO ()
-drawModel model position scale tint = with model (\m -> with position (\p -> with tint (c'drawModel m p (realToFrac scale))))
-
-foreign import ccall safe "raylib.h &DrawModel"
-  p'drawModel ::
-    FunPtr (Raylib.Types.Model -> Raylib.Types.Vector3 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawModelEx_" c'drawModelEx :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
-
-drawModelEx :: Raylib.Types.Model -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
-drawModelEx model position rotationAxis rotationAngle scale tint = with model (\m -> with position (\p -> with rotationAxis (\r -> with scale (with tint . c'drawModelEx m p r (realToFrac rotationAngle)))))
-
-foreign import ccall safe "raylib.h &DrawModelEx"
-  p'drawModelEx ::
-    FunPtr (Raylib.Types.Model -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> CFloat -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawModelWires_" c'drawModelWires :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawModelWires :: Raylib.Types.Model -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Color -> IO ()
-drawModelWires model position scale tint = with model (\m -> with position (\p -> with tint (c'drawModelWires m p (realToFrac scale))))
-
-foreign import ccall safe "raylib.h &DrawModelWires"
-  p'drawModelWires ::
-    FunPtr (Raylib.Types.Model -> Raylib.Types.Vector3 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawModelWiresEx_" c'drawModelWiresEx :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
-
-drawModelWiresEx :: Raylib.Types.Model -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
-drawModelWiresEx model position rotationAxis rotationAngle scale tint = with model (\m -> with position (\p -> with rotationAxis (\r -> with scale (with tint . c'drawModelWiresEx m p r (realToFrac rotationAngle)))))
-
-foreign import ccall safe "raylib.h &DrawModelWiresEx"
-  p'drawModelWiresEx ::
-    FunPtr (Raylib.Types.Model -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> CFloat -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawBoundingBox_" c'drawBoundingBox :: Ptr Raylib.Types.BoundingBox -> Ptr Raylib.Types.Color -> IO ()
-
-drawBoundingBox :: Raylib.Types.BoundingBox -> Raylib.Types.Color -> IO ()
-drawBoundingBox box color = with box (with color . c'drawBoundingBox)
-
-foreign import ccall safe "raylib.h &DrawBoundingBox"
-  p'drawBoundingBox ::
-    FunPtr (Raylib.Types.BoundingBox -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawBillboard_" c'drawBillboard :: Ptr Raylib.Types.Camera3D -> Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawBillboard :: Raylib.Types.Camera3D -> Raylib.Types.Texture -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Color -> IO ()
-drawBillboard camera texture position size tint = with camera (\c -> with texture (\t -> with position (\p -> with tint (c'drawBillboard c t p (realToFrac size)))))
-
-foreign import ccall safe "raylib.h &DrawBillboard"
-  p'drawBillboard ::
-    FunPtr (Raylib.Types.Camera3D -> Raylib.Types.Texture -> Raylib.Types.Vector3 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawBillboardRec_" c'drawBillboardRec :: Ptr Raylib.Types.Camera3D -> Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
-
-drawBillboardRec :: Raylib.Types.Camera3D -> Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Vector3 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
-drawBillboardRec camera texture source position size tint = with camera (\c -> with texture (\t -> with source (\s -> with position (\p -> with size (with tint . c'drawBillboardRec c t s p)))))
-
-foreign import ccall safe "raylib.h &DrawBillboardRec"
-  p'drawBillboardRec ::
-    FunPtr (Raylib.Types.Camera3D -> Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Vector3 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "bindings.h DrawBillboardPro_" c'drawBillboardPro :: Ptr Raylib.Types.Camera3D -> Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
-
-drawBillboardPro :: Raylib.Types.Camera3D -> Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
-drawBillboardPro camera texture source position up size origin rotation tint = with camera (\c -> with texture (\t -> with source (\s -> with position (\p -> with up (\u -> with size (\sz -> with origin (\o -> with tint (c'drawBillboardPro c t s p u sz o (realToFrac rotation)))))))))
-
-foreign import ccall safe "raylib.h &DrawBillboardPro"
-  p'drawBillboardPro ::
-    FunPtr (Raylib.Types.Camera3D -> Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ())
-
-foreign import ccall safe "raylib.h UploadMesh"
-  c'uploadMesh ::
-    Ptr Raylib.Types.Mesh -> CInt -> IO ()
-
-uploadMesh :: Raylib.Types.Mesh -> Bool -> IO Raylib.Types.Mesh
-uploadMesh mesh dynamic = with mesh (\m -> c'uploadMesh m (fromBool dynamic) >> peek m)
-
-foreign import ccall safe "raylib.h &UploadMesh"
-  p'uploadMesh ::
-    FunPtr (Ptr Raylib.Types.Mesh -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h UpdateMeshBuffer_" c'updateMeshBuffer :: Ptr Raylib.Types.Mesh -> CInt -> Ptr () -> CInt -> CInt -> IO ()
-
-updateMeshBuffer :: Raylib.Types.Mesh -> Int -> Ptr () -> Int -> Int -> IO ()
-updateMeshBuffer mesh index dataValue dataSize offset = with mesh (\m -> c'updateMeshBuffer m (fromIntegral index) dataValue (fromIntegral dataSize) (fromIntegral offset))
-
-foreign import ccall safe "raylib.h &UpdateMeshBuffer"
-  p'updateMeshBuffer ::
-    FunPtr (Raylib.Types.Mesh -> CInt -> Ptr () -> CInt -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h UnloadMesh_" c'unloadMesh :: Ptr Raylib.Types.Mesh -> IO ()
-
-unloadMesh :: Raylib.Types.Mesh -> IO ()
-unloadMesh mesh = with mesh c'unloadMesh
-
-foreign import ccall safe "raylib.h &UnloadMesh"
-  p'unloadMesh ::
-    FunPtr (Raylib.Types.Mesh -> IO ())
-
-foreign import ccall safe "bindings.h DrawMesh_" c'drawMesh :: Ptr Raylib.Types.Mesh -> Ptr Raylib.Types.Material -> Ptr Raylib.Types.Matrix -> IO ()
-
-drawMesh :: Raylib.Types.Mesh -> Raylib.Types.Material -> Raylib.Types.Matrix -> IO ()
-drawMesh mesh material transform = with mesh (\m -> with material (with transform . c'drawMesh m))
-
-foreign import ccall safe "raylib.h &DrawMesh"
-  p'drawMesh ::
-    FunPtr (Raylib.Types.Mesh -> Raylib.Types.Material -> Raylib.Types.Matrix -> IO ())
-
-foreign import ccall safe "bindings.h DrawMeshInstanced_" c'drawMeshInstanced :: Ptr Raylib.Types.Mesh -> Ptr Raylib.Types.Material -> Ptr Raylib.Types.Matrix -> CInt -> IO ()
-
-drawMeshInstanced :: Raylib.Types.Mesh -> Raylib.Types.Material -> [Raylib.Types.Matrix] -> IO ()
-drawMeshInstanced mesh material transforms = with mesh (\m -> with material (\mat -> withArrayLen transforms (\size t -> c'drawMeshInstanced m mat t (fromIntegral size))))
-
-foreign import ccall safe "raylib.h &DrawMeshInstanced"
-  p'drawMeshInstanced ::
-    FunPtr (Raylib.Types.Mesh -> Raylib.Types.Material -> Ptr Raylib.Types.Matrix -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h ExportMesh_" c'exportMesh :: Ptr Raylib.Types.Mesh -> CString -> IO CBool
-
-exportMesh :: Raylib.Types.Mesh -> String -> IO Bool
-exportMesh mesh fileName = toBool <$> with mesh (withCString fileName . c'exportMesh)
-
-foreign import ccall safe "raylib.h &ExportMesh"
-  p'exportMesh ::
-    FunPtr (Raylib.Types.Mesh -> CString -> IO CInt)
-
-foreign import ccall safe "bindings.h GetMeshBoundingBox_" c'getMeshBoundingBox :: Ptr Raylib.Types.Mesh -> IO (Ptr Raylib.Types.BoundingBox)
-
-getMeshBoundingBox :: Raylib.Types.Mesh -> IO Raylib.Types.BoundingBox
-getMeshBoundingBox mesh = with mesh c'getMeshBoundingBox >>= pop
-
-foreign import ccall safe "raylib.h &GetMeshBoundingBox"
-  p'getMeshBoundingBox ::
-    FunPtr (Raylib.Types.Mesh -> IO Raylib.Types.BoundingBox)
-
-foreign import ccall safe "raylib.h GenMeshTangents"
-  c'genMeshTangents ::
-    Ptr Raylib.Types.Mesh -> IO ()
-
-genMeshTangents :: Raylib.Types.Mesh -> IO Raylib.Types.Mesh
-genMeshTangents mesh = with mesh (\m -> c'genMeshTangents m >> peek m)
-
-foreign import ccall safe "raylib.h &GenMeshTangents"
-  p'genMeshTangents ::
-    FunPtr (Ptr Raylib.Types.Mesh -> IO ())
-
-foreign import ccall safe "bindings.h GenMeshPoly_" c'genMeshPoly :: CInt -> CFloat -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshPoly :: Int -> Float -> IO Raylib.Types.Mesh
-genMeshPoly sides radius = c'genMeshPoly (fromIntegral sides) (realToFrac radius) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshPoly"
-  p'genMeshPoly ::
-    FunPtr (CInt -> CFloat -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "bindings.h GenMeshPlane_" c'genMeshPlane :: CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshPlane :: Float -> Float -> Int -> Int -> IO Raylib.Types.Mesh
-genMeshPlane width length resX resZ = c'genMeshPlane (realToFrac width) (realToFrac length) (fromIntegral resX) (fromIntegral resZ) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshPlane"
-  p'genMeshPlane ::
-    FunPtr (CFloat -> CFloat -> CInt -> CInt -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "bindings.h GenMeshCube_" c'genMeshCube :: CFloat -> CFloat -> CFloat -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshCube :: Float -> Float -> Float -> IO Raylib.Types.Mesh
-genMeshCube width height length = c'genMeshCube (realToFrac width) (realToFrac height) (realToFrac length) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshCube"
-  p'genMeshCube ::
-    FunPtr (CFloat -> CFloat -> CFloat -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "bindings.h GenMeshSphere_" c'genMeshSphere :: CFloat -> CInt -> CInt -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshSphere :: Float -> Int -> Int -> IO Raylib.Types.Mesh
-genMeshSphere radius rings slices = c'genMeshSphere (realToFrac radius) (fromIntegral rings) (fromIntegral slices) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshSphere"
-  p'genMeshSphere ::
-    FunPtr (CFloat -> CInt -> CInt -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "bindings.h GenMeshHemiSphere_" c'genMeshHemiSphere :: CFloat -> CInt -> CInt -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshHemiSphere :: Float -> Int -> Int -> IO Raylib.Types.Mesh
-genMeshHemiSphere radius rings slices = c'genMeshHemiSphere (realToFrac radius) (fromIntegral rings) (fromIntegral slices) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshHemiSphere"
-  p'genMeshHemiSphere ::
-    FunPtr (CFloat -> CInt -> CInt -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "bindings.h GenMeshCylinder_" c'genMeshCylinder :: CFloat -> CFloat -> CInt -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshCylinder :: Float -> Float -> Int -> IO Raylib.Types.Mesh
-genMeshCylinder radius height slices = c'genMeshCylinder (realToFrac radius) (realToFrac height) (fromIntegral slices) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshCylinder"
-  p'genMeshCylinder ::
-    FunPtr (CFloat -> CFloat -> CInt -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "bindings.h GenMeshCone_" c'genMeshCone :: CFloat -> CFloat -> CInt -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshCone :: Float -> Float -> Int -> IO Raylib.Types.Mesh
-genMeshCone radius height slices = c'genMeshCone (realToFrac radius) (realToFrac height) (fromIntegral slices) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshCone"
-  p'genMeshCone ::
-    FunPtr (CFloat -> CFloat -> CInt -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "bindings.h GenMeshTorus_" c'genMeshTorus :: CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshTorus :: Float -> Float -> Int -> Int -> IO Raylib.Types.Mesh
-genMeshTorus radius size radSeg sides = c'genMeshTorus (realToFrac radius) (realToFrac size) (fromIntegral radSeg) (fromIntegral sides) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshTorus"
-  p'genMeshTorus ::
-    FunPtr (CFloat -> CFloat -> CInt -> CInt -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "bindings.h GenMeshKnot_" c'genMeshKnot :: CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshKnot :: Float -> Float -> Int -> Int -> IO Raylib.Types.Mesh
-genMeshKnot radius size radSeg sides = c'genMeshKnot (realToFrac radius) (realToFrac size) (fromIntegral radSeg) (fromIntegral sides) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshKnot"
-  p'genMeshKnot ::
-    FunPtr (CFloat -> CFloat -> CInt -> CInt -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "bindings.h GenMeshHeightmap_" c'genMeshHeightmap :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector3 -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshHeightmap :: Raylib.Types.Image -> Raylib.Types.Vector3 -> IO Raylib.Types.Mesh
-genMeshHeightmap heightmap size = with heightmap (with size . c'genMeshHeightmap) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshHeightmap"
-  p'genMeshHeightmap ::
-    FunPtr (Raylib.Types.Image -> Raylib.Types.Vector3 -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "bindings.h GenMeshCubicmap_" c'genMeshCubicmap :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector3 -> IO (Ptr Raylib.Types.Mesh)
-
-genMeshCubicmap :: Raylib.Types.Image -> Raylib.Types.Vector3 -> IO Raylib.Types.Mesh
-genMeshCubicmap cubicmap cubeSize = with cubicmap (with cubeSize . c'genMeshCubicmap) >>= pop
-
-foreign import ccall safe "raylib.h &GenMeshCubicmap"
-  p'genMeshCubicmap ::
-    FunPtr (Raylib.Types.Image -> Raylib.Types.Vector3 -> IO Raylib.Types.Mesh)
-
-foreign import ccall safe "raylib.h LoadMaterials"
-  c'loadMaterials ::
-    CString -> Ptr CInt -> IO (Ptr Raylib.Types.Material)
-
-loadMaterials :: String -> IO [Raylib.Types.Material]
-loadMaterials fileName =
-  withCString
-    fileName
-    ( \f ->
-        with
-          0
-          ( \n -> do
-              ptr <- c'loadMaterials f n
-              num <- peek n
-              peekArray (fromIntegral num) ptr
-          )
-    )
-
-foreign import ccall safe "raylib.h &LoadMaterials"
-  p'loadMaterials ::
-    FunPtr (CString -> Ptr CInt -> IO (Ptr Raylib.Types.Material))
-
-foreign import ccall safe "bindings.h LoadMaterialDefault_" c'loadMaterialDefault :: IO (Ptr Raylib.Types.Material)
-
-loadMaterialDefault :: IO Raylib.Types.Material
-loadMaterialDefault = c'loadMaterialDefault >>= pop
-
-foreign import ccall safe "raylib.h &LoadMaterialDefault"
-  p'loadMaterialDefault ::
-    FunPtr (IO Raylib.Types.Material)
-
-foreign import ccall safe "bindings.h UnloadMaterial_" c'unloadMaterial :: Ptr Raylib.Types.Material -> IO ()
-
-unloadMaterial :: Raylib.Types.Material -> IO ()
-unloadMaterial material = with material c'unloadMaterial
-
-foreign import ccall safe "raylib.h &UnloadMaterial"
-  p'unloadMaterial ::
-    FunPtr (Raylib.Types.Material -> IO ())
-
-foreign import ccall safe "bindings.h SetMaterialTexture_" c'setMaterialTexture :: Ptr Raylib.Types.Material -> CInt -> Ptr Raylib.Types.Texture -> IO ()
-
-setMaterialTexture :: Raylib.Types.Material -> Int -> Raylib.Types.Texture -> IO Raylib.Types.Material
-setMaterialTexture material mapType texture = with material (\m -> with texture (c'setMaterialTexture m (fromIntegral mapType)) >> peek m)
-
-foreign import ccall safe "raylib.h &SetMaterialTexture"
-  p'setMaterialTexture ::
-    FunPtr (Ptr Raylib.Types.Material -> CInt -> Raylib.Types.Texture -> IO ())
-
-foreign import ccall safe "raylib.h SetModelMeshMaterial"
-  c'setModelMeshMaterial ::
-    Ptr Raylib.Types.Model -> CInt -> CInt -> IO ()
-
-setModelMeshMaterial :: Raylib.Types.Model -> Int -> Int -> IO Raylib.Types.Model
-setModelMeshMaterial model meshId materialId = with model (\m -> c'setModelMeshMaterial m (fromIntegral meshId) (fromIntegral materialId) >> peek m)
-
-foreign import ccall safe "raylib.h &SetModelMeshMaterial"
-  p'setModelMeshMaterial ::
-    FunPtr (Ptr Raylib.Types.Model -> CInt -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h LoadModelAnimations"
-  c'loadModelAnimations ::
-    CString -> Ptr CUInt -> IO (Ptr Raylib.Types.ModelAnimation)
-
-loadModelAnimations :: String -> IO [Raylib.Types.ModelAnimation]
-loadModelAnimations fileName =
-  withCString
-    fileName
-    ( \f ->
-        with
-          0
-          ( \n -> do
-              ptr <- c'loadModelAnimations f n
-              num <- peek n
-              peekArray (fromIntegral num) ptr
-          )
-    )
-
-foreign import ccall safe "raylib.h &LoadModelAnimations"
-  p'loadModelAnimations ::
-    FunPtr (CString -> Ptr CUInt -> IO (Ptr Raylib.Types.ModelAnimation))
-
-foreign import ccall safe "bindings.h UpdateModelAnimation_" c'updateModelAnimation :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.ModelAnimation -> CInt -> IO ()
-
-updateModelAnimation :: Raylib.Types.Model -> Raylib.Types.ModelAnimation -> Int -> IO ()
-updateModelAnimation model animation frame = with model (\m -> with animation (\a -> c'updateModelAnimation m a (fromIntegral frame)))
-
-foreign import ccall safe "raylib.h &UpdateModelAnimation"
-  p'updateModelAnimation ::
-    FunPtr (Raylib.Types.Model -> Raylib.Types.ModelAnimation -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h UnloadModelAnimation_" c'unloadModelAnimation :: Ptr Raylib.Types.ModelAnimation -> IO ()
-
-unloadModelAnimation :: ModelAnimation -> IO ()
-unloadModelAnimation animation = with animation c'unloadModelAnimation
-
-foreign import ccall safe "raylib.h &UnloadModelAnimation"
-  p'unloadModelAnimation ::
-    FunPtr (Raylib.Types.ModelAnimation -> IO ())
-
-foreign import ccall safe "raylib.h UnloadModelAnimations"
-  c'unloadModelAnimations ::
-    Ptr Raylib.Types.ModelAnimation -> CUInt -> IO ()
-
-unloadModelAnimations :: [ModelAnimation] -> IO ()
-unloadModelAnimations animations = withArrayLen animations (\num a -> c'unloadModelAnimations a (fromIntegral num))
-
-foreign import ccall safe "raylib.h &UnloadModelAnimations"
-  p'unloadModelAnimations ::
-    FunPtr (Ptr Raylib.Types.ModelAnimation -> CUInt -> IO ())
-
-foreign import ccall safe "bindings.h IsModelAnimationValid_" c'isModelAnimationValid :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.ModelAnimation -> IO CBool
-
-isModelAnimationValid :: Model -> ModelAnimation -> IO Bool
-isModelAnimationValid model animation = toBool <$> with model (with animation . c'isModelAnimationValid)
-
-foreign import ccall safe "raylib.h &IsModelAnimationValid"
-  p'isModelAnimationValid ::
-    FunPtr (Raylib.Types.Model -> Raylib.Types.ModelAnimation -> IO CInt)
-
-foreign import ccall safe "bindings.h CheckCollisionSpheres_" c'checkCollisionSpheres :: Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Vector3 -> CFloat -> IO CBool
-
-checkCollisionSpheres :: Vector3 -> Float -> Vector3 -> Float -> Bool
-checkCollisionSpheres center1 radius1 center2 radius2 = toBool $ unsafePerformIO (with center1 (\c1 -> with center2 (\c2 -> c'checkCollisionSpheres c1 (realToFrac radius1) c2 (realToFrac radius2))))
-
-foreign import ccall safe "raylib.h &CheckCollisionSpheres"
-  p'checkCollisionSpheres ::
-    FunPtr (Raylib.Types.Vector3 -> CFloat -> Raylib.Types.Vector3 -> CFloat -> IO CInt)
-
-foreign import ccall safe "bindings.h CheckCollisionBoxes_" c'checkCollisionBoxes :: Ptr Raylib.Types.BoundingBox -> Ptr Raylib.Types.BoundingBox -> IO CBool
-
-checkCollisionBoxes :: BoundingBox -> BoundingBox -> Bool
-checkCollisionBoxes box1 box2 = toBool $ unsafePerformIO (with box1 (with box2 . c'checkCollisionBoxes))
-
-foreign import ccall safe "raylib.h &CheckCollisionBoxes"
-  p'checkCollisionBoxes ::
-    FunPtr (Raylib.Types.BoundingBox -> Raylib.Types.BoundingBox -> IO CInt)
-
-foreign import ccall safe "bindings.h CheckCollisionBoxSphere_" c'checkCollisionBoxSphere :: Ptr Raylib.Types.BoundingBox -> Ptr Raylib.Types.Vector3 -> CFloat -> IO CBool
-
-checkCollisionBoxSphere :: BoundingBox -> Vector3 -> Float -> Bool
-checkCollisionBoxSphere box center radius = toBool $ unsafePerformIO (with box (\b -> with center (\c -> c'checkCollisionBoxSphere b c (realToFrac radius))))
-
-foreign import ccall safe "raylib.h &CheckCollisionBoxSphere"
-  p'checkCollisionBoxSphere ::
-    FunPtr (Raylib.Types.BoundingBox -> Raylib.Types.Vector3 -> CFloat -> IO CInt)
-
-foreign import ccall safe "bindings.h GetRayCollisionSphere_" c'getRayCollisionSphere :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.Vector3 -> CFloat -> IO (Ptr Raylib.Types.RayCollision)
-
-getRayCollisionSphere :: Ray -> Vector3 -> Float -> RayCollision
-getRayCollisionSphere ray center radius = unsafePerformIO $ with ray (\r -> with center (\c -> c'getRayCollisionSphere r c (realToFrac radius))) >>= pop
-
-foreign import ccall safe "raylib.h &GetRayCollisionSphere"
-  p'getRayCollisionSphere ::
-    FunPtr (Raylib.Types.Ray -> Raylib.Types.Vector3 -> CFloat -> IO Raylib.Types.RayCollision)
-
-foreign import ccall safe "bindings.h GetRayCollisionBox_" c'getRayCollisionBox :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.BoundingBox -> IO (Ptr Raylib.Types.RayCollision)
-
-getRayCollisionBox :: Ray -> BoundingBox -> RayCollision
-getRayCollisionBox ray box = unsafePerformIO $ with ray (with box . c'getRayCollisionBox) >>= pop
-
-foreign import ccall safe "raylib.h &GetRayCollisionBox"
-  p'getRayCollisionBox ::
-    FunPtr (Raylib.Types.Ray -> Raylib.Types.BoundingBox -> IO Raylib.Types.RayCollision)
-
-foreign import ccall safe "bindings.h GetRayCollisionMesh_" c'getRayCollisionMesh :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.Mesh -> Ptr Raylib.Types.Matrix -> IO (Ptr Raylib.Types.RayCollision)
-
-getRayCollisionMesh :: Ray -> Mesh -> Matrix -> RayCollision
-getRayCollisionMesh ray mesh transform = unsafePerformIO $ with ray (\r -> with mesh (with transform . c'getRayCollisionMesh r)) >>= pop
-
-foreign import ccall safe "raylib.h &GetRayCollisionMesh"
-  p'getRayCollisionMesh ::
-    FunPtr (Raylib.Types.Ray -> Raylib.Types.Mesh -> Raylib.Types.Matrix -> IO Raylib.Types.RayCollision)
-
-foreign import ccall safe "bindings.h GetRayCollisionTriangle_" c'getRayCollisionTriangle :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> IO (Ptr Raylib.Types.RayCollision)
-
-getRayCollisionTriangle :: Ray -> Vector3 -> Vector3 -> Vector3 -> RayCollision
-getRayCollisionTriangle ray v1 v2 v3 = unsafePerformIO $ with ray (\r -> with v1 (\p1 -> with v2 (with v3 . c'getRayCollisionTriangle r p1))) >>= pop
-
-foreign import ccall safe "raylib.h &GetRayCollisionTriangle"
-  p'getRayCollisionTriangle ::
-    FunPtr (Raylib.Types.Ray -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> IO Raylib.Types.RayCollision)
-
-foreign import ccall safe "bindings.h GetRayCollisionQuad_" c'getRayCollisionQuad :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> IO (Ptr Raylib.Types.RayCollision)
-
-getRayCollisionQuad :: Ray -> Vector3 -> Vector3 -> Vector3 -> Vector3 -> RayCollision
-getRayCollisionQuad ray v1 v2 v3 v4 = unsafePerformIO $ with ray (\r -> with v1 (\p1 -> with v2 (\p2 -> with v3 (with v4 . c'getRayCollisionQuad r p1 p2)))) >>= pop
-
-foreign import ccall safe "raylib.h &GetRayCollisionQuad"
-  p'getRayCollisionQuad ::
-    FunPtr (Raylib.Types.Ray -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> IO Raylib.Types.RayCollision)
-
-type AudioCallback = FunPtr (Ptr () -> CUInt -> IO ())
-
-foreign import ccall safe "wrapper"
-  mk'audioCallback ::
-    (Ptr () -> CUInt -> IO ()) -> IO AudioCallback
-
-foreign import ccall safe "dynamic"
-  mK'audioCallback ::
-    AudioCallback -> (Ptr () -> CUInt -> IO ())
-
-foreign import ccall safe "raylib.h InitAudioDevice"
-  initAudioDevice ::
-    IO ()
-
-foreign import ccall safe "raylib.h &InitAudioDevice"
-  p'initAudioDevice ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h CloseAudioDevice"
-  closeAudioDevice ::
-    IO ()
-
-foreign import ccall safe "raylib.h &CloseAudioDevice"
-  p'closeAudioDevice ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h IsAudioDeviceReady"
-  c'isAudioDeviceReady ::
-    IO CBool
-
-isAudioDeviceReady :: IO Bool
-isAudioDeviceReady = toBool <$> c'isAudioDeviceReady
-
-foreign import ccall safe "raylib.h &IsAudioDeviceReady"
-  p'isAudioDeviceReady ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "raylib.h SetMasterVolume"
-  c'setMasterVolume ::
-    CFloat -> IO ()
-
-setMasterVolume :: Float -> IO ()
-setMasterVolume volume = c'setMasterVolume (realToFrac volume)
-
-foreign import ccall safe "raylib.h &SetMasterVolume"
-  p'setMasterVolume ::
-    FunPtr (CFloat -> IO ())
-
-foreign import ccall safe "bindings.h LoadWave_" c'loadWave :: CString -> IO (Ptr Raylib.Types.Wave)
-
-loadWave :: String -> IO Wave
-loadWave fileName = withCString fileName c'loadWave >>= pop
-
-foreign import ccall safe "raylib.h &LoadWave"
-  p'loadWave ::
-    FunPtr (CString -> IO Raylib.Types.Wave)
-
-foreign import ccall safe "bindings.h LoadWaveFromMemory_" c'loadWaveFromMemory :: CString -> Ptr CUChar -> CInt -> IO (Ptr Raylib.Types.Wave)
-
-loadWaveFromMemory :: String -> [Integer] -> IO Wave
-loadWaveFromMemory fileType fileData = withCString fileType (\f -> withArrayLen (map fromIntegral fileData) (\size d -> c'loadWaveFromMemory f d (fromIntegral $ size * sizeOf (0 :: CUChar)))) >>= pop
-
-foreign import ccall safe "raylib.h &LoadWaveFromMemory"
-  p'loadWaveFromMemory ::
-    FunPtr (CString -> Ptr CUChar -> CInt -> IO Raylib.Types.Wave)
-
-foreign import ccall safe "bindings.h LoadSound_" c'loadSound :: CString -> IO (Ptr Raylib.Types.Sound)
-
-loadSound :: String -> IO Sound
-loadSound fileName = withCString fileName c'loadSound >>= pop
-
-foreign import ccall safe "raylib.h &LoadSound"
-  p'loadSound ::
-    FunPtr (CString -> IO Raylib.Types.Sound)
-
-foreign import ccall safe "bindings.h LoadSoundFromWave_" c'loadSoundFromWave :: Ptr Raylib.Types.Wave -> IO (Ptr Raylib.Types.Sound)
-
-loadSoundFromWave :: Wave -> IO Sound
-loadSoundFromWave wave = with wave c'loadSoundFromWave >>= pop
-
-foreign import ccall safe "raylib.h &LoadSoundFromWave"
-  p'loadSoundFromWave ::
-    FunPtr (Raylib.Types.Wave -> IO Raylib.Types.Sound)
-
-foreign import ccall safe "bindings.h UpdateSound_" c'updateSound :: Ptr Raylib.Types.Sound -> Ptr () -> CInt -> IO ()
-
-updateSound :: Sound -> Ptr () -> Int -> IO ()
-updateSound sound dataValue sampleCount = with sound (\s -> c'updateSound s dataValue (fromIntegral sampleCount))
-
-foreign import ccall safe "raylib.h &UpdateSound"
-  p'updateSound ::
-    FunPtr (Raylib.Types.Sound -> Ptr () -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h UnloadWave_" c'unloadWave :: Ptr Raylib.Types.Wave -> IO ()
-
-unloadWave :: Wave -> IO ()
-unloadWave wave = with wave c'unloadWave
-
-foreign import ccall safe "raylib.h &UnloadWave"
-  p'unloadWave ::
-    FunPtr (Raylib.Types.Wave -> IO ())
-
-foreign import ccall safe "bindings.h UnloadSound_" c'unloadSound :: Ptr Raylib.Types.Sound -> IO ()
-
-unloadSound :: Sound -> IO ()
-unloadSound sound = with sound c'unloadSound
-
-foreign import ccall safe "raylib.h &UnloadSound"
-  p'unloadSound ::
-    FunPtr (Raylib.Types.Sound -> IO ())
-
-foreign import ccall safe "bindings.h ExportWave_" c'exportWave :: Ptr Raylib.Types.Wave -> CString -> IO CBool
-
-exportWave :: Wave -> String -> IO Bool
-exportWave wave fileName = toBool <$> with wave (withCString fileName . c'exportWave)
-
-foreign import ccall safe "raylib.h &ExportWave"
-  p'exportWave ::
-    FunPtr (Raylib.Types.Wave -> CString -> IO CInt)
-
-foreign import ccall safe "bindings.h ExportWaveAsCode_" c'exportWaveAsCode :: Ptr Raylib.Types.Wave -> CString -> IO CBool
-
-exportWaveAsCode :: Wave -> String -> IO Bool
-exportWaveAsCode wave fileName = toBool <$> with wave (withCString fileName . c'exportWaveAsCode)
-
-foreign import ccall safe "raylib.h &ExportWaveAsCode"
-  p'exportWaveAsCode ::
-    FunPtr (Raylib.Types.Wave -> CString -> IO CInt)
-
-foreign import ccall safe "bindings.h PlaySound_" c'playSound :: Ptr Raylib.Types.Sound -> IO ()
-
-playSound :: Sound -> IO ()
-playSound sound = with sound c'playSound
-
-foreign import ccall safe "raylib.h &PlaySound"
-  p'playSound ::
-    FunPtr (Raylib.Types.Sound -> IO ())
-
-foreign import ccall safe "bindings.h StopSound_" c'stopSound :: Ptr Raylib.Types.Sound -> IO ()
-
-stopSound :: Sound -> IO ()
-stopSound sound = with sound c'stopSound
-
-foreign import ccall safe "raylib.h &StopSound"
-  p'stopSound ::
-    FunPtr (Raylib.Types.Sound -> IO ())
-
-foreign import ccall safe "bindings.h PauseSound_" c'pauseSound :: Ptr Raylib.Types.Sound -> IO ()
-
-pauseSound :: Sound -> IO ()
-pauseSound sound = with sound c'pauseSound
-
-foreign import ccall safe "raylib.h &PauseSound"
-  p'pauseSound ::
-    FunPtr (Raylib.Types.Sound -> IO ())
-
-foreign import ccall safe "bindings.h ResumeSound_" c'resumeSound :: Ptr Raylib.Types.Sound -> IO ()
-
-resumeSound :: Sound -> IO ()
-resumeSound sound = with sound c'resumeSound
-
-foreign import ccall safe "raylib.h &ResumeSound"
-  p'resumeSound ::
-    FunPtr (Raylib.Types.Sound -> IO ())
-
-foreign import ccall safe "bindings.h PlaySoundMulti_" c'playSoundMulti :: Ptr Raylib.Types.Sound -> IO ()
-
-playSoundMulti :: Sound -> IO ()
-playSoundMulti sound = with sound c'playSoundMulti
-
-foreign import ccall safe "raylib.h &PlaySoundMulti"
-  p'playSoundMulti ::
-    FunPtr (Raylib.Types.Sound -> IO ())
-
-foreign import ccall safe "raylib.h StopSoundMulti"
-  stopSoundMulti ::
-    IO ()
-
-foreign import ccall safe "raylib.h &StopSoundMulti"
-  p'stopSoundMulti ::
-    FunPtr (IO ())
-
-foreign import ccall safe "raylib.h GetSoundsPlaying"
-  c'getSoundsPlaying ::
-    IO CInt
-
-getSoundsPlaying :: IO Int
-getSoundsPlaying = fromIntegral <$> c'getSoundsPlaying
-
-foreign import ccall safe "raylib.h &GetSoundsPlaying"
-  p'getSoundsPlaying ::
-    FunPtr (IO CInt)
-
-foreign import ccall safe "bindings.h IsSoundPlaying_" c'isSoundPlaying :: Ptr Raylib.Types.Sound -> IO CBool
-
-isSoundPlaying :: Sound -> IO Bool
-isSoundPlaying sound = toBool <$> with sound c'isSoundPlaying
-
-foreign import ccall safe "raylib.h &IsSoundPlaying"
-  p'isSoundPlaying ::
-    FunPtr (Raylib.Types.Sound -> IO CInt)
-
-foreign import ccall safe "bindings.h SetSoundVolume_" c'setSoundVolume :: Ptr Raylib.Types.Sound -> CFloat -> IO ()
-
-setSoundVolume :: Sound -> Float -> IO ()
-setSoundVolume sound volume = with sound (\s -> c'setSoundVolume s (realToFrac volume))
-
-foreign import ccall safe "raylib.h &SetSoundVolume"
-  p'setSoundVolume ::
-    FunPtr (Raylib.Types.Sound -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h SetSoundPitch_" c'setSoundPitch :: Ptr Raylib.Types.Sound -> CFloat -> IO ()
-
-setSoundPitch :: Sound -> Float -> IO ()
-setSoundPitch sound pitch = with sound (\s -> c'setSoundPitch s (realToFrac pitch))
-
-foreign import ccall safe "raylib.h &SetSoundPitch"
-  p'setSoundPitch ::
-    FunPtr (Raylib.Types.Sound -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h SetSoundPan_" c'setSoundPan :: Ptr Raylib.Types.Sound -> CFloat -> IO ()
-
-setSoundPan :: Sound -> Float -> IO ()
-setSoundPan sound pan = with sound (\s -> c'setSoundPan s (realToFrac pan))
-
-foreign import ccall safe "raylib.h &SetSoundPan"
-  p'setSoundPan ::
-    FunPtr (Raylib.Types.Sound -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h WaveCopy_" c'waveCopy :: Ptr Raylib.Types.Wave -> IO (Ptr Raylib.Types.Wave)
-
-waveCopy :: Wave -> IO Wave
-waveCopy wave = with wave c'waveCopy >>= pop
-
-foreign import ccall safe "raylib.h &WaveCopy"
-  p'waveCopy ::
-    FunPtr (Raylib.Types.Wave -> IO Raylib.Types.Wave)
-
-foreign import ccall safe "raylib.h WaveCrop"
-  c'waveCrop ::
-    Ptr Raylib.Types.Wave -> CInt -> CInt -> IO ()
-
-waveCrop :: Wave -> Int -> Int -> IO Wave
-waveCrop wave initSample finalSample = do
-  new <- waveCopy wave
-  with new (\w -> c'waveCrop w (fromIntegral initSample) (fromIntegral finalSample) >> peek w)
-
-foreign import ccall safe "raylib.h &WaveCrop"
-  p'waveCrop ::
-    FunPtr (Ptr Raylib.Types.Wave -> CInt -> CInt -> IO ())
-
-foreign import ccall safe "raylib.h WaveFormat"
-  c'waveFormat ::
-    Ptr Raylib.Types.Wave -> CInt -> CInt -> CInt -> IO ()
-
-waveFormat :: Wave -> Int -> Int -> Int -> IO ()
-waveFormat wave sampleRate sampleSize channels = do
-  new <- waveCopy wave
-  with new (\n -> c'waveFormat n (fromIntegral sampleRate) (fromIntegral sampleSize) (fromIntegral channels))
-
-foreign import ccall safe "raylib.h &WaveFormat"
-  p'waveFormat ::
-    FunPtr (Ptr Raylib.Types.Wave -> CInt -> CInt -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h LoadWaveSamples_" c'loadWaveSamples :: Ptr Raylib.Types.Wave -> IO (Ptr CFloat)
-
-loadWaveSamples :: Wave -> IO [Float]
-loadWaveSamples wave =
-  with
-    wave
-    ( \w -> do
-        ptr <- c'loadWaveSamples w
-        arr <- peekArray (fromIntegral $ wave'frameCount wave * wave'channels wave) ptr
-        c'unloadWaveSamples ptr
-        return $ map realToFrac arr
-    )
-
-foreign import ccall safe "raylib.h &LoadWaveSamples"
-  p'loadWaveSamples ::
-    FunPtr (Raylib.Types.Wave -> IO (Ptr CFloat))
-
-foreign import ccall safe "raylib.h UnloadWaveSamples"
-  c'unloadWaveSamples ::
-    Ptr CFloat -> IO ()
-
-foreign import ccall safe "raylib.h &UnloadWaveSamples"
-  p'unloadWaveSamples ::
-    FunPtr (Ptr CFloat -> IO ())
-
-foreign import ccall safe "bindings.h LoadMusicStream_" c'loadMusicStream :: CString -> IO (Ptr Raylib.Types.Music)
-
-loadMusicStream :: String -> IO Music
-loadMusicStream fileName = withCString fileName c'loadMusicStream >>= pop
-
-foreign import ccall safe "raylib.h &LoadMusicStream"
-  p'loadMusicStream ::
-    FunPtr (CString -> IO Raylib.Types.Music)
-
-foreign import ccall safe "bindings.h LoadMusicStreamFromMemory_" c'loadMusicStreamFromMemory :: CString -> Ptr CUChar -> CInt -> IO (Ptr Raylib.Types.Music)
-
-loadMusicStreamFromMemory :: String -> [Integer] -> IO Music
-loadMusicStreamFromMemory fileType streamData = withCString fileType (\t -> withArrayLen (map fromIntegral streamData) (\size d -> c'loadMusicStreamFromMemory t d (fromIntegral $ size * sizeOf (0 :: CUChar)))) >>= pop
-
-foreign import ccall safe "raylib.h &LoadMusicStreamFromMemory"
-  p'loadMusicStreamFromMemory ::
-    FunPtr (CString -> Ptr CUChar -> CInt -> IO Raylib.Types.Music)
-
-foreign import ccall safe "bindings.h UnloadMusicStream_" c'unloadMusicStream :: Ptr Raylib.Types.Music -> IO ()
-
-unloadMusicStream :: Music -> IO ()
-unloadMusicStream music = with music c'unloadMusicStream
-
-foreign import ccall safe "raylib.h &UnloadMusicStream"
-  p'unloadMusicStream ::
-    FunPtr (Raylib.Types.Music -> IO ())
-
-foreign import ccall safe "bindings.h PlayMusicStream_" c'playMusicStream :: Ptr Raylib.Types.Music -> IO ()
-
-playMusicStream :: Music -> IO ()
-playMusicStream music = with music c'playMusicStream
-
-foreign import ccall safe "raylib.h &PlayMusicStream"
-  p'playMusicStream ::
-    FunPtr (Raylib.Types.Music -> IO ())
-
-foreign import ccall safe "bindings.h IsMusicStreamPlaying_" c'isMusicStreamPlaying :: Ptr Raylib.Types.Music -> IO CBool
-
-isMusicStreamPlaying :: Music -> IO Bool
-isMusicStreamPlaying music = toBool <$> with music c'isMusicStreamPlaying
-
-foreign import ccall safe "raylib.h &IsMusicStreamPlaying"
-  p'isMusicStreamPlaying ::
-    FunPtr (Raylib.Types.Music -> IO CInt)
-
-foreign import ccall safe "bindings.h UpdateMusicStream_" c'updateMusicStream :: Ptr Raylib.Types.Music -> IO ()
-
-updateMusicStream :: Music -> IO ()
-updateMusicStream music = with music c'updateMusicStream
-
-foreign import ccall safe "raylib.h &UpdateMusicStream"
-  p'updateMusicStream ::
-    FunPtr (Raylib.Types.Music -> IO ())
-
-foreign import ccall safe "bindings.h StopMusicStream_" c'stopMusicStream :: Ptr Raylib.Types.Music -> IO ()
-
-stopMusicStream :: Music -> IO ()
-stopMusicStream music = with music c'stopMusicStream
-
-foreign import ccall safe "raylib.h &StopMusicStream"
-  p'stopMusicStream ::
-    FunPtr (Raylib.Types.Music -> IO ())
-
-foreign import ccall safe "bindings.h PauseMusicStream_" c'pauseMusicStream :: Ptr Raylib.Types.Music -> IO ()
-
-pauseMusicStream :: Music -> IO ()
-pauseMusicStream music = with music c'pauseMusicStream
-
-foreign import ccall safe "raylib.h &PauseMusicStream"
-  p'pauseMusicStream ::
-    FunPtr (Raylib.Types.Music -> IO ())
-
-foreign import ccall safe "bindings.h ResumeMusicStream_" c'resumeMusicStream :: Ptr Raylib.Types.Music -> IO ()
-
-resumeMusicStream :: Music -> IO ()
-resumeMusicStream music = with music c'resumeMusicStream
-
-foreign import ccall safe "raylib.h &ResumeMusicStream"
-  p'resumeMusicStream ::
-    FunPtr (Raylib.Types.Music -> IO ())
-
-foreign import ccall safe "bindings.h SeekMusicStream_" c'seekMusicStream :: Ptr Raylib.Types.Music -> CFloat -> IO ()
-
-seekMusicStream :: Music -> Float -> IO ()
-seekMusicStream music position = with music (\m -> c'seekMusicStream m (realToFrac position))
-
-foreign import ccall safe "raylib.h &SeekMusicStream"
-  p'seekMusicStream ::
-    FunPtr (Raylib.Types.Music -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h SetMusicVolume_" c'setMusicVolume :: Ptr Raylib.Types.Music -> CFloat -> IO ()
-
-setMusicVolume :: Music -> Float -> IO ()
-setMusicVolume music volume = with music (\m -> c'setMusicVolume m (realToFrac volume))
-
-foreign import ccall safe "raylib.h &SetMusicVolume"
-  p'setMusicVolume ::
-    FunPtr (Raylib.Types.Music -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h SetMusicPitch_" c'setMusicPitch :: Ptr Raylib.Types.Music -> CFloat -> IO ()
-
-setMusicPitch :: Music -> Float -> IO ()
-setMusicPitch music pitch = with music (\m -> c'setMusicPitch m (realToFrac pitch))
-
-foreign import ccall safe "raylib.h &SetMusicPitch"
-  p'setMusicPitch ::
-    FunPtr (Raylib.Types.Music -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h SetMusicPan_" c'setMusicPan :: Ptr Raylib.Types.Music -> CFloat -> IO ()
-
-setMusicPan :: Music -> Float -> IO ()
-setMusicPan music pan = with music (\m -> c'setMusicPan m (realToFrac pan))
-
-foreign import ccall safe "raylib.h &SetMusicPan"
-  p'setMusicPan ::
-    FunPtr (Raylib.Types.Music -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h GetMusicTimeLength_" c'getMusicTimeLength :: Ptr Raylib.Types.Music -> IO CFloat
-
-getMusicTimeLength :: Music -> IO Float
-getMusicTimeLength music = realToFrac <$> with music c'getMusicTimeLength
-
-foreign import ccall safe "raylib.h &GetMusicTimeLength"
-  p'getMusicTimeLength ::
-    FunPtr (Raylib.Types.Music -> IO CFloat)
-
-foreign import ccall safe "bindings.h GetMusicTimePlayed_" c'getMusicTimePlayed :: Ptr Raylib.Types.Music -> IO CFloat
-
-getMusicTimePlayed :: Music -> IO Float
-getMusicTimePlayed music = realToFrac <$> with music c'getMusicTimePlayed
-
-foreign import ccall safe "raylib.h &GetMusicTimePlayed"
-  p'getMusicTimePlayed ::
-    FunPtr (Raylib.Types.Music -> IO CFloat)
-
-foreign import ccall safe "bindings.h LoadAudioStream_" c'loadAudioStream :: CUInt -> CUInt -> CUInt -> IO (Ptr Raylib.Types.AudioStream)
-
-loadAudioStream :: Integer -> Integer -> Integer -> IO AudioStream
-loadAudioStream sampleRate sampleSize channels = c'loadAudioStream (fromIntegral sampleRate) (fromIntegral sampleSize) (fromIntegral channels) >>= pop
-
-foreign import ccall safe "raylib.h &LoadAudioStream"
-  p'loadAudioStream ::
-    FunPtr (CUInt -> CUInt -> CUInt -> IO Raylib.Types.AudioStream)
-
-foreign import ccall safe "bindings.h UnloadAudioStream_" c'unloadAudioStream :: Ptr Raylib.Types.AudioStream -> IO ()
-
-unloadAudioStream :: AudioStream -> IO ()
-unloadAudioStream stream = with stream c'unloadAudioStream
-
-foreign import ccall safe "raylib.h &UnloadAudioStream"
-  p'unloadAudioStream ::
-    FunPtr (Raylib.Types.AudioStream -> IO ())
-
-foreign import ccall safe "bindings.h UpdateAudioStream_" c'updateAudioStream :: Ptr Raylib.Types.AudioStream -> Ptr () -> CInt -> IO ()
-
-updateAudioStream :: AudioStream -> Ptr () -> Int -> IO ()
-updateAudioStream stream value frameCount = with stream (\s -> c'updateAudioStream s value (fromIntegral frameCount))
-
-foreign import ccall safe "raylib.h &UpdateAudioStream"
-  p'updateAudioStream ::
-    FunPtr (Raylib.Types.AudioStream -> Ptr () -> CInt -> IO ())
-
-foreign import ccall safe "bindings.h IsAudioStreamProcessed_" c'isAudioStreamProcessed :: Ptr Raylib.Types.AudioStream -> IO CBool
-
-isAudioStreamProcessed :: AudioStream -> IO Bool
-isAudioStreamProcessed stream = toBool <$> with stream c'isAudioStreamProcessed
-
-foreign import ccall safe "raylib.h &IsAudioStreamProcessed"
-  p'isAudioStreamProcessed ::
-    FunPtr (Raylib.Types.AudioStream -> IO CInt)
-
-foreign import ccall safe "bindings.h PlayAudioStream_" c'playAudioStream :: Ptr Raylib.Types.AudioStream -> IO ()
-
-playAudioStream :: AudioStream -> IO ()
-playAudioStream stream = with stream c'playAudioStream
-
-foreign import ccall safe "raylib.h &PlayAudioStream"
-  p'playAudioStream ::
-    FunPtr (Raylib.Types.AudioStream -> IO ())
-
-foreign import ccall safe "bindings.h PauseAudioStream_" c'pauseAudioStream :: Ptr Raylib.Types.AudioStream -> IO ()
-
-pauseAudioStream :: AudioStream -> IO ()
-pauseAudioStream stream = with stream c'pauseAudioStream
-
-foreign import ccall safe "raylib.h &PauseAudioStream"
-  p'pauseAudioStream ::
-    FunPtr (Raylib.Types.AudioStream -> IO ())
-
-foreign import ccall safe "bindings.h ResumeAudioStream_" c'resumeAudioStream :: Ptr Raylib.Types.AudioStream -> IO ()
-
-resumeAudioStream :: AudioStream -> IO ()
-resumeAudioStream stream = with stream c'resumeAudioStream
-
-foreign import ccall safe "raylib.h &ResumeAudioStream"
-  p'resumeAudioStream ::
-    FunPtr (Raylib.Types.AudioStream -> IO ())
-
-foreign import ccall safe "bindings.h IsAudioStreamPlaying_" c'isAudioStreamPlaying :: Ptr Raylib.Types.AudioStream -> IO CBool
-
-isAudioStreamPlaying :: AudioStream -> IO Bool
-isAudioStreamPlaying stream = toBool <$> with stream c'isAudioStreamPlaying
-
-foreign import ccall safe "raylib.h &IsAudioStreamPlaying"
-  p'isAudioStreamPlaying ::
-    FunPtr (Raylib.Types.AudioStream -> IO CInt)
-
-foreign import ccall safe "bindings.h StopAudioStream_" c'stopAudioStream :: Ptr Raylib.Types.AudioStream -> IO ()
-
-stopAudioStream :: AudioStream -> IO ()
-stopAudioStream stream = with stream c'stopAudioStream
-
-foreign import ccall safe "raylib.h &StopAudioStream"
-  p'stopAudioStream ::
-    FunPtr (Raylib.Types.AudioStream -> IO ())
-
-foreign import ccall safe "bindings.h SetAudioStreamVolume_" c'setAudioStreamVolume :: Ptr Raylib.Types.AudioStream -> CFloat -> IO ()
-
-setAudioStreamVolume :: AudioStream -> Float -> IO ()
-setAudioStreamVolume stream volume = with stream (\s -> c'setAudioStreamVolume s (realToFrac volume))
-
-foreign import ccall safe "raylib.h &SetAudioStreamVolume"
-  p'setAudioStreamVolume ::
-    FunPtr (Raylib.Types.AudioStream -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h SetAudioStreamPitch_" c'setAudioStreamPitch :: Ptr Raylib.Types.AudioStream -> CFloat -> IO ()
-
-setAudioStreamPitch :: AudioStream -> Float -> IO ()
-setAudioStreamPitch stream pitch = with stream (\s -> c'setAudioStreamPitch s (realToFrac pitch))
-
-foreign import ccall safe "raylib.h &SetAudioStreamPitch"
-  p'setAudioStreamPitch ::
-    FunPtr (Raylib.Types.AudioStream -> CFloat -> IO ())
-
-foreign import ccall safe "bindings.h SetAudioStreamPan_" c'setAudioStreamPan :: Ptr Raylib.Types.AudioStream -> CFloat -> IO ()
-
-setAudioStreamPan :: AudioStream -> Float -> IO ()
-setAudioStreamPan stream pan = with stream (\s -> c'setAudioStreamPan s (realToFrac pan))
-
-foreign import ccall safe "raylib.h &SetAudioStreamPan"
-  p'setAudioStreamPan ::
-    FunPtr (Raylib.Types.AudioStream -> CFloat -> IO ())
-
-foreign import ccall safe "raylib.h SetAudioStreamBufferSizeDefault"
-  c'setAudioStreamBufferSizeDefault ::
-    CInt -> IO ()
-
-setAudioStreamBufferSizeDefault :: Int -> IO ()
-setAudioStreamBufferSizeDefault = setAudioStreamBufferSizeDefault . fromIntegral
-
-foreign import ccall safe "raylib.h &SetAudioStreamBufferSizeDefault"
-  p'setAudioStreamBufferSizeDefault ::
-    FunPtr (CInt -> IO ())
-
-foreign import ccall safe "bindings.h SetAudioStreamCallback_" c'setAudioStreamCallback :: Ptr Raylib.Types.AudioStream -> Ptr AudioCallback -> IO ()
-
-foreign import ccall safe "raylib.h &SetAudioStreamCallback"
-  p'setAudioStreamCallback ::
-    FunPtr (Raylib.Types.AudioStream -> AudioCallback -> IO ())
-
-foreign import ccall safe "bindings.h AttachAudioStreamProcessor_" c'attachAudioStreamProcessor :: Ptr Raylib.Types.AudioStream -> Ptr AudioCallback -> IO ()
-
-foreign import ccall safe "raylib.h &AttachAudioStreamProcessor"
-  p'attachAudioStreamProcessor ::
-    FunPtr (Raylib.Types.AudioStream -> AudioCallback -> IO ())
-
-foreign import ccall safe "bindings.h DetachAudioStreamProcessor_" c'detachAudioStreamProcessor :: Ptr Raylib.Types.AudioStream -> Ptr AudioCallback -> IO ()
-
-foreign import ccall safe "raylib.h &DetachAudioStreamProcessor"
-  p'detachAudioStreamProcessor ::
-    FunPtr (Raylib.Types.AudioStream -> AudioCallback -> IO ())
+ src/Raylib/Audio.hs view
@@ -0,0 +1,277 @@+{-# OPTIONS -Wall #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module Raylib.Audio where
+
+import Foreign
+  ( FunPtr,
+    Ptr,
+    Storable (peek, sizeOf),
+    peekArray,
+    toBool,
+    withArrayLen,
+  )
+import Foreign.C (CUChar, CUInt, withCString)
+import Raylib.Native
+  ( c'exportWave,
+    c'exportWaveAsCode,
+    c'getMusicTimeLength,
+    c'getMusicTimePlayed,
+    c'getSoundsPlaying,
+    c'isAudioDeviceReady,
+    c'isAudioStreamPlaying,
+    c'isAudioStreamProcessed,
+    c'isMusicStreamPlaying,
+    c'isSoundPlaying,
+    c'loadAudioStream,
+    c'loadMusicStream,
+    c'loadMusicStreamFromMemory,
+    c'loadSound,
+    c'loadSoundFromWave,
+    c'loadWave,
+    c'loadWaveFromMemory,
+    c'loadWaveSamples,
+    c'pauseAudioStream,
+    c'pauseMusicStream,
+    c'pauseSound,
+    c'playAudioStream,
+    c'playMusicStream,
+    c'playSound,
+    c'playSoundMulti,
+    c'resumeAudioStream,
+    c'resumeMusicStream,
+    c'resumeSound,
+    c'seekMusicStream,
+    c'setAudioStreamPan,
+    c'setAudioStreamPitch,
+    c'setAudioStreamVolume,
+    c'setMasterVolume,
+    c'setMusicPan,
+    c'setMusicPitch,
+    c'setMusicVolume,
+    c'setSoundPan,
+    c'setSoundPitch,
+    c'setSoundVolume,
+    c'stopAudioStream,
+    c'stopMusicStream,
+    c'stopSound,
+    c'unloadAudioStream,
+    c'unloadMusicStream,
+    c'unloadSound,
+    c'unloadWave,
+    c'unloadWaveSamples,
+    c'updateAudioStream,
+    c'updateMusicStream,
+    c'updateSound,
+    c'waveCopy,
+    c'waveCrop,
+    c'waveFormat, c'isWaveReady, c'isSoundReady, c'isMusicReady, c'isAudioStreamReady
+  )
+import Raylib.Types
+  ( AudioStream,
+    Music,
+    Sound,
+    Wave (wave'channels, wave'frameCount),
+  )
+import Raylib.Util
+  ( pop,
+    withFreeable,
+  )
+
+foreign import ccall safe "raylib.h InitAudioDevice"
+  initAudioDevice ::
+    IO ()
+
+foreign import ccall safe "raylib.h CloseAudioDevice"
+  closeAudioDevice ::
+    IO ()
+
+type AudioCallback = FunPtr (Ptr () -> CUInt -> IO ())
+
+-- TODO: redesign this
+isAudioDeviceReady :: IO Bool
+isAudioDeviceReady = toBool <$> c'isAudioDeviceReady
+
+setMasterVolume :: Float -> IO ()
+setMasterVolume volume = c'setMasterVolume (realToFrac volume)
+
+loadWave :: String -> IO Wave
+loadWave fileName = withCString fileName c'loadWave >>= pop
+
+loadWaveFromMemory :: String -> [Integer] -> IO Wave
+loadWaveFromMemory fileType fileData = withCString fileType (\f -> withArrayLen (map fromIntegral fileData) (\size d -> c'loadWaveFromMemory f d (fromIntegral $ size * sizeOf (0 :: CUChar)))) >>= pop
+
+loadSound :: String -> IO Sound
+loadSound fileName = withCString fileName c'loadSound >>= pop
+
+loadSoundFromWave :: Wave -> IO Sound
+loadSoundFromWave wave = withFreeable wave c'loadSoundFromWave >>= pop
+
+updateSound :: Sound -> Ptr () -> Int -> IO ()
+updateSound sound dataValue sampleCount = withFreeable sound (\s -> c'updateSound s dataValue (fromIntegral sampleCount))
+
+isWaveReady :: Wave -> IO Bool
+isWaveReady wave = toBool <$> withFreeable wave c'isWaveReady
+
+unloadWave :: Wave -> IO ()
+unloadWave wave = withFreeable wave c'unloadWave
+
+isSoundReady :: Sound -> IO Bool
+isSoundReady sound = toBool <$> withFreeable sound c'isSoundReady
+
+unloadSound :: Sound -> IO ()
+unloadSound sound = withFreeable sound c'unloadSound
+
+exportWave :: Wave -> String -> IO Bool
+exportWave wave fileName = toBool <$> withFreeable wave (withCString fileName . c'exportWave)
+
+exportWaveAsCode :: Wave -> String -> IO Bool
+exportWaveAsCode wave fileName = toBool <$> withFreeable wave (withCString fileName . c'exportWaveAsCode)
+
+playSound :: Sound -> IO ()
+playSound sound = withFreeable sound c'playSound
+
+stopSound :: Sound -> IO ()
+stopSound sound = withFreeable sound c'stopSound
+
+pauseSound :: Sound -> IO ()
+pauseSound sound = withFreeable sound c'pauseSound
+
+resumeSound :: Sound -> IO ()
+resumeSound sound = withFreeable sound c'resumeSound
+
+playSoundMulti :: Sound -> IO ()
+playSoundMulti sound = withFreeable sound c'playSoundMulti
+
+foreign import ccall safe "raylib.h StopSoundMulti"
+  stopSoundMulti ::
+    IO ()
+
+getSoundsPlaying :: IO Int
+getSoundsPlaying = fromIntegral <$> c'getSoundsPlaying
+
+isSoundPlaying :: Sound -> IO Bool
+isSoundPlaying sound = toBool <$> withFreeable sound c'isSoundPlaying
+
+setSoundVolume :: Sound -> Float -> IO ()
+setSoundVolume sound volume = withFreeable sound (\s -> c'setSoundVolume s (realToFrac volume))
+
+setSoundPitch :: Sound -> Float -> IO ()
+setSoundPitch sound pitch = withFreeable sound (\s -> c'setSoundPitch s (realToFrac pitch))
+
+setSoundPan :: Sound -> Float -> IO ()
+setSoundPan sound pan = withFreeable sound (\s -> c'setSoundPan s (realToFrac pan))
+
+waveCopy :: Wave -> IO Wave
+waveCopy wave = withFreeable wave c'waveCopy >>= pop
+
+waveCrop :: Wave -> Int -> Int -> IO Wave
+waveCrop wave initSample finalSample = do
+  new <- waveCopy wave
+  withFreeable new (\w -> c'waveCrop w (fromIntegral initSample) (fromIntegral finalSample) >> peek w)
+
+waveFormat :: Wave -> Int -> Int -> Int -> IO ()
+waveFormat wave sampleRate sampleSize channels = do
+  new <- waveCopy wave
+  withFreeable new (\n -> c'waveFormat n (fromIntegral sampleRate) (fromIntegral sampleSize) (fromIntegral channels))
+
+loadWaveSamples :: Wave -> IO [Float]
+loadWaveSamples wave =
+  withFreeable
+    wave
+    ( \w -> do
+        ptr <- c'loadWaveSamples w
+        arr <- peekArray (fromIntegral $ wave'frameCount wave * wave'channels wave) ptr
+        c'unloadWaveSamples ptr
+        return $ map realToFrac arr
+    )
+
+loadMusicStream :: String -> IO Music
+loadMusicStream fileName = withCString fileName c'loadMusicStream >>= pop
+
+loadMusicStreamFromMemory :: String -> [Integer] -> IO Music
+loadMusicStreamFromMemory fileType streamData = withCString fileType (\t -> withArrayLen (map fromIntegral streamData) (\size d -> c'loadMusicStreamFromMemory t d (fromIntegral $ size * sizeOf (0 :: CUChar)))) >>= pop
+
+isMusicReady :: Music -> IO Bool
+isMusicReady music = toBool <$> withFreeable music c'isMusicReady
+
+unloadMusicStream :: Music -> IO ()
+unloadMusicStream music = withFreeable music c'unloadMusicStream
+
+playMusicStream :: Music -> IO ()
+playMusicStream music = withFreeable music c'playMusicStream
+
+isMusicStreamPlaying :: Music -> IO Bool
+isMusicStreamPlaying music = toBool <$> withFreeable music c'isMusicStreamPlaying
+
+updateMusicStream :: Music -> IO ()
+updateMusicStream music = withFreeable music c'updateMusicStream
+
+stopMusicStream :: Music -> IO ()
+stopMusicStream music = withFreeable music c'stopMusicStream
+
+pauseMusicStream :: Music -> IO ()
+pauseMusicStream music = withFreeable music c'pauseMusicStream
+
+resumeMusicStream :: Music -> IO ()
+resumeMusicStream music = withFreeable music c'resumeMusicStream
+
+seekMusicStream :: Music -> Float -> IO ()
+seekMusicStream music position = withFreeable music (\m -> c'seekMusicStream m (realToFrac position))
+
+setMusicVolume :: Music -> Float -> IO ()
+setMusicVolume music volume = withFreeable music (\m -> c'setMusicVolume m (realToFrac volume))
+
+setMusicPitch :: Music -> Float -> IO ()
+setMusicPitch music pitch = withFreeable music (\m -> c'setMusicPitch m (realToFrac pitch))
+
+setMusicPan :: Music -> Float -> IO ()
+setMusicPan music pan = withFreeable music (\m -> c'setMusicPan m (realToFrac pan))
+
+getMusicTimeLength :: Music -> IO Float
+getMusicTimeLength music = realToFrac <$> withFreeable music c'getMusicTimeLength
+
+getMusicTimePlayed :: Music -> IO Float
+getMusicTimePlayed music = realToFrac <$> withFreeable music c'getMusicTimePlayed
+
+loadAudioStream :: Integer -> Integer -> Integer -> IO AudioStream
+loadAudioStream sampleRate sampleSize channels = c'loadAudioStream (fromIntegral sampleRate) (fromIntegral sampleSize) (fromIntegral channels) >>= pop
+
+isAudioStreamReady :: AudioStream -> IO Bool
+isAudioStreamReady stream = toBool <$> withFreeable stream c'isAudioStreamReady
+
+unloadAudioStream :: AudioStream -> IO ()
+unloadAudioStream stream = withFreeable stream c'unloadAudioStream
+
+updateAudioStream :: AudioStream -> Ptr () -> Int -> IO ()
+updateAudioStream stream value frameCount = withFreeable stream (\s -> c'updateAudioStream s value (fromIntegral frameCount))
+
+isAudioStreamProcessed :: AudioStream -> IO Bool
+isAudioStreamProcessed stream = toBool <$> withFreeable stream c'isAudioStreamProcessed
+
+playAudioStream :: AudioStream -> IO ()
+playAudioStream stream = withFreeable stream c'playAudioStream
+
+pauseAudioStream :: AudioStream -> IO ()
+pauseAudioStream stream = withFreeable stream c'pauseAudioStream
+
+resumeAudioStream :: AudioStream -> IO ()
+resumeAudioStream stream = withFreeable stream c'resumeAudioStream
+
+isAudioStreamPlaying :: AudioStream -> IO Bool
+isAudioStreamPlaying stream = toBool <$> withFreeable stream c'isAudioStreamPlaying
+
+stopAudioStream :: AudioStream -> IO ()
+stopAudioStream stream = withFreeable stream c'stopAudioStream
+
+setAudioStreamVolume :: AudioStream -> Float -> IO ()
+setAudioStreamVolume stream volume = withFreeable stream (\s -> c'setAudioStreamVolume s (realToFrac volume))
+
+setAudioStreamPitch :: AudioStream -> Float -> IO ()
+setAudioStreamPitch stream pitch = withFreeable stream (\s -> c'setAudioStreamPitch s (realToFrac pitch))
+
+setAudioStreamPan :: AudioStream -> Float -> IO ()
+setAudioStreamPan stream pan = withFreeable stream (\s -> c'setAudioStreamPan s (realToFrac pan))
+
+setAudioStreamBufferSizeDefault :: Int -> IO ()
+setAudioStreamBufferSizeDefault = setAudioStreamBufferSizeDefault . fromIntegral
+ src/Raylib/Core.hs view
@@ -0,0 +1,890 @@+{-# OPTIONS -Wall #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module Raylib.Core where
+
+import Foreign
+  ( Ptr,
+    Storable (peek, sizeOf),
+    castPtr,
+    fromBool,
+    peekArray,
+    toBool,
+    withArray,
+    withArrayLen,
+  )
+import Foreign.C
+  ( CInt (CInt),
+    CUChar,
+    CUInt (CUInt),
+    peekCString,
+    withCString,
+  )
+import Raylib.Native
+  ( c'beginBlendMode,
+    c'beginMode2D,
+    c'beginMode3D,
+    c'beginScissorMode,
+    c'beginShaderMode,
+    c'beginTextureMode,
+    c'beginVrStereoMode,
+    c'changeDirectory,
+    c'clearBackground,
+    c'clearWindowState,
+    c'compressData,
+    c'decodeDataBase64,
+    c'decompressData,
+    c'directoryExists,
+    c'encodeDataBase64,
+    c'exportDataAsCode,
+    c'fileExists,
+    c'getApplicationDirectory,
+    c'getCameraMatrix,
+    c'getCameraMatrix2D,
+    c'getCharPressed,
+    c'getClipboardText,
+    c'getCurrentMonitor,
+    c'getDirectoryPath,
+    c'getFPS,
+    c'getFileExtension,
+    c'getFileLength,
+    c'getFileModTime,
+    c'getFileName,
+    c'getFileNameWithoutExt,
+    c'getFrameTime,
+    c'getGamepadAxisCount,
+    c'getGamepadAxisMovement,
+    c'getGamepadButtonPressed,
+    c'getGamepadName,
+    c'getGestureDetected,
+    c'getGestureDragAngle,
+    c'getGestureDragVector,
+    c'getGestureHoldDuration,
+    c'getGesturePinchAngle,
+    c'getGesturePinchVector,
+    c'getKeyPressed,
+    c'getMonitorCount,
+    c'getMonitorHeight,
+    c'getMonitorName,
+    c'getMonitorPhysicalHeight,
+    c'getMonitorPhysicalWidth,
+    c'getMonitorPosition,
+    c'getMonitorRefreshRate,
+    c'getMonitorWidth,
+    c'getMouseDelta,
+    c'getMousePosition,
+    c'getMouseRay,
+    c'getMouseWheelMove,
+    c'getMouseWheelMoveV,
+    c'getMouseX,
+    c'getMouseY,
+    c'getPrevDirectoryPath,
+    c'getRandomValue,
+    c'getRenderHeight,
+    c'getRenderWidth,
+    c'getScreenHeight,
+    c'getScreenToWorld2D,
+    c'getScreenWidth,
+    c'getShaderLocation,
+    c'getShaderLocationAttrib,
+    c'getTime,
+    c'getTouchPointCount,
+    c'getTouchPointId,
+    c'getTouchPosition,
+    c'getTouchX,
+    c'getTouchY,
+    c'getWindowPosition,
+    c'getWindowScaleDPI,
+    c'getWorkingDirectory,
+    c'getWorldToScreen,
+    c'getWorldToScreen2D,
+    c'getWorldToScreenEx,
+    c'initWindow,
+    c'isCursorHidden,
+    c'isCursorOnScreen,
+    c'isFileDropped,
+    c'isFileExtension,
+    c'isGamepadAvailable,
+    c'isGamepadButtonDown,
+    c'isGamepadButtonPressed,
+    c'isGamepadButtonReleased,
+    c'isGamepadButtonUp,
+    c'isGestureDetected,
+    c'isKeyDown,
+    c'isKeyPressed,
+    c'isKeyReleased,
+    c'isKeyUp,
+    c'isMouseButtonDown,
+    c'isMouseButtonPressed,
+    c'isMouseButtonReleased,
+    c'isMouseButtonUp,
+    c'isPathFile,
+    c'isWindowFocused,
+    c'isWindowFullscreen,
+    c'isWindowHidden,
+    c'isWindowMaximized,
+    c'isWindowMinimized,
+    c'isWindowReady,
+    c'isWindowResized,
+    c'isWindowState,
+    c'loadDirectoryFiles,
+    c'loadDirectoryFilesEx,
+    c'loadDroppedFiles,
+    c'loadFileData,
+    c'loadFileText,
+    c'loadShader,
+    c'loadShaderFromMemory,
+    c'loadVrStereoConfig,
+    c'memAlloc,
+    c'memFree,
+    c'memRealloc,
+    c'openURL,
+    c'saveFileData,
+    c'saveFileText,
+    c'setCameraAltControl,
+    c'setCameraMode,
+    c'setCameraMoveControls,
+    c'setCameraPanControl,
+    c'setCameraSmoothZoomControl,
+    c'setClipboardText,
+    c'setConfigFlags,
+    c'setExitKey,
+    c'setGamepadMappings,
+    c'setGesturesEnabled,
+    c'setMouseCursor,
+    c'setMouseOffset,
+    c'setMousePosition,
+    c'setMouseScale,
+    c'setRandomSeed,
+    c'setShaderValue,
+    c'setShaderValueMatrix,
+    c'setShaderValueTexture,
+    c'setShaderValueV,
+    c'setTargetFPS,
+    c'setTraceLogLevel,
+    c'setWindowIcon,
+    c'setWindowMinSize,
+    c'setWindowMonitor,
+    c'setWindowOpacity,
+    c'setWindowPosition,
+    c'setWindowSize,
+    c'setWindowState,
+    c'setWindowTitle,
+    c'takeScreenshot,
+    c'traceLog,
+    c'unloadDirectoryFiles,
+    c'unloadDroppedFiles,
+    c'unloadFileData,
+    c'unloadFileText,
+    c'unloadShader,
+    c'unloadVrStereoConfig,
+    c'updateCamera,
+    c'waitTime,
+    c'windowShouldClose, c'isShaderReady
+  )
+import Raylib.Types
+  ( BlendMode,
+    Camera2D,
+    Camera3D,
+    CameraMode,
+    Color,
+    ConfigFlag,
+    FilePathList,
+    GamepadAxis,
+    GamepadButton,
+    Gesture,
+    Image,
+    KeyboardKey,
+    LoadFileDataCallback,
+    LoadFileTextCallback,
+    Matrix,
+    MouseButton,
+    MouseCursor,
+    Ray,
+    RenderTexture,
+    SaveFileDataCallback,
+    SaveFileTextCallback,
+    Shader,
+    ShaderUniformDataType,
+    Texture,
+    TraceLogLevel,
+    Vector2,
+    Vector3,
+    VrDeviceInfo,
+    VrStereoConfig,
+  )
+import Raylib.Util (configsToBitflag, pop, withFreeable, withMaybeCString)
+
+initWindow :: Int -> Int -> String -> IO ()
+initWindow width height title = withCString title $ c'initWindow (fromIntegral width) (fromIntegral height)
+
+windowShouldClose :: IO Bool
+windowShouldClose = toBool <$> c'windowShouldClose
+
+foreign import ccall safe "raylib.h CloseWindow"
+  closeWindow ::
+    IO ()
+
+isWindowReady :: IO Bool
+isWindowReady = toBool <$> c'isWindowReady
+
+isWindowFullscreen :: IO Bool
+isWindowFullscreen = toBool <$> c'isWindowFullscreen
+
+isWindowHidden :: IO Bool
+isWindowHidden = toBool <$> c'isWindowHidden
+
+isWindowMinimized :: IO Bool
+isWindowMinimized = toBool <$> c'isWindowMinimized
+
+isWindowMaximized :: IO Bool
+isWindowMaximized = toBool <$> c'isWindowMaximized
+
+isWindowFocused :: IO Bool
+isWindowFocused = toBool <$> c'isWindowFocused
+
+isWindowResized :: IO Bool
+isWindowResized = toBool <$> c'isWindowResized
+
+isWindowState :: [ConfigFlag] -> IO Bool
+isWindowState flags = toBool <$> c'isWindowState (fromIntegral $ configsToBitflag flags)
+
+setWindowState :: [ConfigFlag] -> IO ()
+setWindowState = c'setWindowState . fromIntegral . configsToBitflag
+
+clearWindowState :: [ConfigFlag] -> IO ()
+clearWindowState = c'clearWindowState . fromIntegral . configsToBitflag
+
+foreign import ccall safe "raylib.h ToggleFullscreen"
+  toggleFullscreen ::
+    IO ()
+
+foreign import ccall safe "raylib.h MaximizeWindow"
+  maximizeWindow ::
+    IO ()
+
+foreign import ccall safe "raylib.h MinimizeWindow"
+  minimizeWindow ::
+    IO ()
+
+foreign import ccall safe "raylib.h RestoreWindow"
+  restoreWindow ::
+    IO ()
+
+setWindowIcon :: Raylib.Types.Image -> IO ()
+setWindowIcon image = withFreeable image c'setWindowIcon
+
+setWindowTitle :: String -> IO ()
+setWindowTitle title = withCString title c'setWindowTitle
+
+setWindowPosition :: Int -> Int -> IO ()
+setWindowPosition x y = c'setWindowPosition (fromIntegral x) (fromIntegral y)
+
+setWindowMonitor :: Int -> IO ()
+setWindowMonitor = c'setWindowMonitor . fromIntegral
+
+setWindowMinSize :: Int -> Int -> IO ()
+setWindowMinSize x y = c'setWindowMinSize (fromIntegral x) (fromIntegral y)
+
+setWindowSize :: Int -> Int -> IO ()
+setWindowSize x y = c'setWindowSize (fromIntegral x) (fromIntegral y)
+
+setWindowOpacity :: Float -> IO ()
+setWindowOpacity opacity = c'setWindowOpacity $ realToFrac opacity
+
+foreign import ccall safe "raylib.h GetWindowHandle"
+  getWindowHandle ::
+    IO (Ptr ())
+
+getScreenWidth :: IO Int
+getScreenWidth = fromIntegral <$> c'getScreenWidth
+
+getScreenHeight :: IO Int
+getScreenHeight = fromIntegral <$> c'getScreenHeight
+
+getRenderWidth :: IO Int
+getRenderWidth = fromIntegral <$> c'getRenderWidth
+
+getRenderHeight :: IO Int
+getRenderHeight = fromIntegral <$> c'getRenderHeight
+
+getMonitorCount :: IO Int
+getMonitorCount = fromIntegral <$> c'getMonitorCount
+
+getCurrentMonitor :: IO Int
+getCurrentMonitor = fromIntegral <$> c'getCurrentMonitor
+
+getMonitorPosition :: Int -> IO Raylib.Types.Vector2
+getMonitorPosition monitor = c'getMonitorPosition (fromIntegral monitor) >>= pop
+
+getMonitorWidth :: Int -> IO Int
+getMonitorWidth monitor = fromIntegral <$> c'getMonitorWidth (fromIntegral monitor)
+
+getMonitorHeight :: Int -> IO Int
+getMonitorHeight monitor = fromIntegral <$> c'getMonitorHeight (fromIntegral monitor)
+
+getMonitorPhysicalWidth :: Int -> IO Int
+getMonitorPhysicalWidth monitor = fromIntegral <$> c'getMonitorPhysicalWidth (fromIntegral monitor)
+
+getMonitorPhysicalHeight :: Int -> IO Int
+getMonitorPhysicalHeight monitor = fromIntegral <$> c'getMonitorPhysicalHeight (fromIntegral monitor)
+
+getMonitorRefreshRate :: Int -> IO Int
+getMonitorRefreshRate monitor = fromIntegral <$> c'getMonitorRefreshRate (fromIntegral monitor)
+
+getWindowPosition :: IO Raylib.Types.Vector2
+getWindowPosition = c'getWindowPosition >>= pop
+
+getWindowScaleDPI :: IO Raylib.Types.Vector2
+getWindowScaleDPI = c'getWindowScaleDPI >>= pop
+
+getMonitorName :: Int -> IO String
+getMonitorName monitor = c'getMonitorName (fromIntegral monitor) >>= peekCString
+
+setClipboardText :: String -> IO ()
+setClipboardText text = withCString text c'setClipboardText
+
+getClipboardText :: IO String
+getClipboardText = c'getClipboardText >>= peekCString
+
+foreign import ccall safe "raylib.h EnableEventWaiting"
+  enableEventWaiting ::
+    IO ()
+
+foreign import ccall safe "raylib.h DisableEventWaiting"
+  disableEventWaiting ::
+    IO ()
+
+foreign import ccall safe "raylib.h SwapScreenBuffer"
+  swapScreenBuffer ::
+    IO ()
+
+foreign import ccall safe "raylib.h PollInputEvents"
+  pollInputEvents ::
+    IO ()
+
+waitTime :: Double -> IO ()
+waitTime seconds = c'waitTime $ realToFrac seconds
+
+foreign import ccall safe "raylib.h ShowCursor"
+  showCursor ::
+    IO ()
+
+foreign import ccall safe "raylib.h HideCursor"
+  hideCursor ::
+    IO ()
+
+isCursorHidden :: IO Bool
+isCursorHidden = toBool <$> c'isCursorHidden
+
+foreign import ccall safe "raylib.h EnableCursor"
+  enableCursor ::
+    IO ()
+
+foreign import ccall safe "raylib.h DisableCursor"
+  disableCursor ::
+    IO ()
+
+isCursorOnScreen :: IO Bool
+isCursorOnScreen = toBool <$> c'isCursorOnScreen
+
+clearBackground :: Raylib.Types.Color -> IO ()
+clearBackground color = withFreeable color c'clearBackground
+
+foreign import ccall safe "raylib.h BeginDrawing"
+  beginDrawing ::
+    IO ()
+
+foreign import ccall safe "raylib.h EndDrawing"
+  endDrawing ::
+    IO ()
+
+beginMode2D :: Raylib.Types.Camera2D -> IO ()
+beginMode2D camera = withFreeable camera c'beginMode2D
+
+foreign import ccall safe "raylib.h EndMode2D"
+  endMode2D ::
+    IO ()
+
+beginMode3D :: Raylib.Types.Camera3D -> IO ()
+beginMode3D camera = withFreeable camera c'beginMode3D
+
+foreign import ccall safe "raylib.h EndMode3D"
+  endMode3D ::
+    IO ()
+
+beginTextureMode :: Raylib.Types.RenderTexture -> IO ()
+beginTextureMode renderTexture = withFreeable renderTexture c'beginTextureMode
+
+foreign import ccall safe "raylib.h EndTextureMode"
+  endTextureMode ::
+    IO ()
+
+beginShaderMode :: Raylib.Types.Shader -> IO ()
+beginShaderMode shader = withFreeable shader c'beginShaderMode
+
+foreign import ccall safe "raylib.h EndShaderMode"
+  endShaderMode ::
+    IO ()
+
+beginBlendMode :: BlendMode -> IO ()
+beginBlendMode = c'beginBlendMode . fromIntegral . fromEnum
+
+foreign import ccall safe "raylib.h EndBlendMode"
+  endBlendMode ::
+    IO ()
+
+beginScissorMode :: Int -> Int -> Int -> Int -> IO ()
+beginScissorMode x y width height = c'beginScissorMode (fromIntegral x) (fromIntegral y) (fromIntegral width) (fromIntegral height)
+
+foreign import ccall safe "raylib.h EndScissorMode"
+  endScissorMode ::
+    IO ()
+
+beginVrStereoMode :: Raylib.Types.VrStereoConfig -> IO ()
+beginVrStereoMode config = withFreeable config c'beginVrStereoMode
+
+foreign import ccall safe "raylib.h EndVrStereoMode"
+  endVrStereoMode ::
+    IO ()
+
+loadVrStereoConfig :: Raylib.Types.VrDeviceInfo -> IO Raylib.Types.VrStereoConfig
+loadVrStereoConfig deviceInfo = withFreeable deviceInfo c'loadVrStereoConfig >>= pop
+
+unloadVrStereoConfig :: Raylib.Types.VrStereoConfig -> IO ()
+unloadVrStereoConfig config = withFreeable config c'unloadVrStereoConfig
+
+loadShader :: Maybe String -> Maybe String -> IO Raylib.Types.Shader
+loadShader vsFileName fsFileName =
+  withMaybeCString vsFileName (withMaybeCString fsFileName . c'loadShader) >>= pop
+
+loadShaderFromMemory :: Maybe String -> Maybe String -> IO Raylib.Types.Shader
+loadShaderFromMemory vsCode fsCode = withMaybeCString vsCode (withMaybeCString fsCode . c'loadShaderFromMemory) >>= pop
+
+isShaderReady :: Shader -> IO Bool
+isShaderReady shader = toBool <$> withFreeable shader c'isShaderReady
+
+getShaderLocation :: Raylib.Types.Shader -> String -> IO Int
+getShaderLocation shader uniformName = fromIntegral <$> withFreeable shader (withCString uniformName . c'getShaderLocation)
+
+getShaderLocationAttrib :: Raylib.Types.Shader -> String -> IO Int
+getShaderLocationAttrib shader attribName = fromIntegral <$> withFreeable shader (withCString attribName . c'getShaderLocationAttrib)
+
+setShaderValue :: Raylib.Types.Shader -> Int -> Ptr () -> ShaderUniformDataType -> IO ()
+setShaderValue shader locIndex value uniformType = withFreeable shader (\s -> c'setShaderValue s (fromIntegral locIndex) value (fromIntegral $ fromEnum uniformType))
+
+setShaderValueV :: Raylib.Types.Shader -> Int -> Ptr () -> ShaderUniformDataType -> Int -> IO ()
+setShaderValueV shader locIndex value uniformType count = withFreeable shader (\s -> c'setShaderValueV s (fromIntegral locIndex) value (fromIntegral $ fromEnum uniformType) (fromIntegral count))
+
+setShaderValueMatrix :: Raylib.Types.Shader -> Int -> Raylib.Types.Matrix -> IO ()
+setShaderValueMatrix shader locIndex mat = withFreeable shader (\s -> withFreeable mat (c'setShaderValueMatrix s (fromIntegral locIndex)))
+
+setShaderValueTexture :: Raylib.Types.Shader -> Int -> Raylib.Types.Texture -> IO ()
+setShaderValueTexture shader locIndex tex = withFreeable shader (\s -> withFreeable tex (c'setShaderValueTexture s (fromIntegral locIndex)))
+
+unloadShader :: Raylib.Types.Shader -> IO ()
+unloadShader shader = withFreeable shader c'unloadShader
+
+getMouseRay :: Raylib.Types.Vector2 -> Raylib.Types.Camera3D -> IO Raylib.Types.Ray
+getMouseRay mousePosition camera = withFreeable mousePosition (withFreeable camera . c'getMouseRay) >>= pop
+
+getCameraMatrix :: Raylib.Types.Camera3D -> IO Raylib.Types.Matrix
+getCameraMatrix camera = withFreeable camera c'getCameraMatrix >>= pop
+
+getCameraMatrix2D :: Raylib.Types.Camera2D -> IO Raylib.Types.Matrix
+getCameraMatrix2D camera = withFreeable camera c'getCameraMatrix2D >>= pop
+
+getWorldToScreen :: Raylib.Types.Vector3 -> Raylib.Types.Camera3D -> IO Raylib.Types.Vector2
+getWorldToScreen position camera = withFreeable position (withFreeable camera . c'getWorldToScreen) >>= pop
+
+getScreenToWorld2D :: Raylib.Types.Vector2 -> Raylib.Types.Camera2D -> IO Raylib.Types.Vector2
+getScreenToWorld2D position camera = withFreeable position (withFreeable camera . c'getScreenToWorld2D) >>= pop
+
+getWorldToScreenEx :: Raylib.Types.Vector3 -> Raylib.Types.Camera3D -> Int -> Int -> IO Raylib.Types.Vector2
+getWorldToScreenEx position camera width height = withFreeable position (\p -> withFreeable camera (\c -> c'getWorldToScreenEx p c (fromIntegral width) (fromIntegral height))) >>= pop
+
+getWorldToScreen2D :: Raylib.Types.Vector2 -> Raylib.Types.Camera2D -> IO Raylib.Types.Vector2
+getWorldToScreen2D position camera = withFreeable position (withFreeable camera . c'getWorldToScreen2D) >>= pop
+
+setTargetFPS :: Int -> IO ()
+setTargetFPS fps = c'setTargetFPS $ fromIntegral fps
+
+getFPS :: IO Int
+getFPS = fromIntegral <$> c'getFPS
+
+getFrameTime :: IO Float
+getFrameTime = realToFrac <$> c'getFrameTime
+
+getTime :: IO Double
+getTime = realToFrac <$> c'getTime
+
+getRandomValue :: Int -> Int -> IO Int
+getRandomValue minVal maxVal = fromIntegral <$> c'getRandomValue (fromIntegral minVal) (fromIntegral maxVal)
+
+setRandomSeed :: Integer -> IO ()
+setRandomSeed seed = c'setRandomSeed $ fromIntegral seed
+
+takeScreenshot :: String -> IO ()
+takeScreenshot fileName = withCString fileName c'takeScreenshot
+
+setConfigFlags :: [ConfigFlag] -> IO ()
+setConfigFlags flags = c'setConfigFlags $ fromIntegral $ configsToBitflag flags
+
+traceLog :: TraceLogLevel -> String -> IO ()
+traceLog logLevel text = withCString text $ c'traceLog $ fromIntegral $ fromEnum logLevel
+
+setTraceLogLevel :: TraceLogLevel -> IO ()
+setTraceLogLevel = c'setTraceLogLevel . fromIntegral . fromEnum
+
+memAlloc :: (Storable a) => Int -> IO (Ptr a)
+memAlloc size = castPtr <$> c'memAlloc (fromIntegral size)
+
+memRealloc :: (Storable a, Storable b) => Ptr a -> Int -> IO (Ptr b)
+memRealloc ptr size = castPtr <$> c'memRealloc (castPtr ptr) (fromIntegral size)
+
+memFree :: (Storable a) => Ptr a -> IO ()
+memFree = c'memFree . castPtr
+
+openURL :: String -> IO ()
+openURL url = withCString url c'openURL
+
+foreign import ccall safe "raylib.h SetLoadFileDataCallback"
+  setLoadFileDataCallback ::
+    LoadFileDataCallback -> IO ()
+
+foreign import ccall safe "raylib.h SetSaveFileDataCallback"
+  setSaveFileDataCallback ::
+    SaveFileDataCallback -> IO ()
+
+foreign import ccall safe "raylib.h SetLoadFileTextCallback"
+  setLoadFileTextCallback ::
+    LoadFileTextCallback -> IO ()
+
+foreign import ccall safe "raylib.h SetSaveFileTextCallback"
+  setSaveFileTextCallback ::
+    SaveFileTextCallback -> IO ()
+
+-- These functions use varargs so they can't be implemented through FFI
+-- foreign import ccall safe "raylib.h SetTraceLogCallback"
+--   SetTraceLogCallback ::
+--     TraceLogCallback -> IO ()
+-- foreign import ccall safe "raylib.h &SetTraceLogCallback"
+--   p'SetTraceLogCallback ::
+--     FunPtr (TraceLogCallback -> IO ())
+
+loadFileData :: String -> IO [Integer]
+loadFileData fileName =
+  withFreeable
+    0
+    ( \size -> do
+        withCString
+          fileName
+          ( \path -> do
+              ptr <- c'loadFileData path size
+              arrSize <- fromIntegral <$> peek size
+              arr <- peekArray arrSize ptr
+              c'unloadFileData ptr
+              return $ map fromIntegral arr
+          )
+    )
+
+saveFileData :: (Storable a) => String -> Ptr a -> Integer -> IO Bool
+saveFileData fileName contents bytesToWrite =
+  toBool <$> withCString fileName (\s -> c'saveFileData s (castPtr contents) (fromIntegral bytesToWrite))
+
+exportDataAsCode :: [Integer] -> Integer -> String -> IO Bool
+exportDataAsCode contents size fileName =
+  toBool <$> withArray (map fromInteger contents) (\c -> withCString fileName (c'exportDataAsCode c (fromIntegral size)))
+
+loadFileText :: String -> IO String
+loadFileText fileName = withCString fileName c'loadFileText >>= peekCString
+
+unloadFileText :: String -> IO ()
+unloadFileText text = withCString text c'unloadFileText
+
+saveFileText :: String -> String -> IO Bool
+saveFileText fileName text = toBool <$> withCString fileName (withCString text . c'saveFileText)
+
+fileExists :: String -> IO Bool
+fileExists fileName = toBool <$> withCString fileName c'fileExists
+
+directoryExists :: String -> IO Bool
+directoryExists dirPath = toBool <$> withCString dirPath c'directoryExists
+
+isFileExtension :: String -> String -> IO Bool
+isFileExtension fileName ext = toBool <$> withCString fileName (withCString ext . c'isFileExtension)
+
+getFileLength :: String -> IO Bool
+getFileLength fileName = toBool <$> withCString fileName c'getFileLength
+
+getFileExtension :: String -> IO String
+getFileExtension fileName = withCString fileName c'getFileExtension >>= peekCString
+
+getFileName :: String -> IO String
+getFileName filePath = withCString filePath c'getFileName >>= peekCString
+
+getFileNameWithoutExt :: String -> IO String
+getFileNameWithoutExt fileName = withCString fileName c'getFileNameWithoutExt >>= peekCString
+
+getDirectoryPath :: String -> IO String
+getDirectoryPath filePath = withCString filePath c'getDirectoryPath >>= peekCString
+
+getPrevDirectoryPath :: String -> IO String
+getPrevDirectoryPath dirPath = withCString dirPath c'getPrevDirectoryPath >>= peekCString
+
+getWorkingDirectory :: IO String
+getWorkingDirectory = c'getWorkingDirectory >>= peekCString
+
+getApplicationDirectory :: IO String
+getApplicationDirectory = c'getApplicationDirectory >>= peekCString
+
+changeDirectory :: String -> IO Bool
+changeDirectory dir = toBool <$> withCString dir c'changeDirectory
+
+isPathFile :: String -> IO Bool
+isPathFile path = toBool <$> withCString path c'isPathFile
+
+loadDirectoryFiles :: String -> IO Raylib.Types.FilePathList
+loadDirectoryFiles dirPath = withCString dirPath c'loadDirectoryFiles >>= pop
+
+loadDirectoryFilesEx :: String -> String -> Bool -> IO Raylib.Types.FilePathList
+loadDirectoryFilesEx basePath filterStr scanSubdirs =
+  withCString basePath (\b -> withCString filterStr (\f -> c'loadDirectoryFilesEx b f (fromBool scanSubdirs))) >>= pop
+
+unloadDirectoryFiles :: Raylib.Types.FilePathList -> IO ()
+unloadDirectoryFiles files = withFreeable files c'unloadDirectoryFiles
+
+isFileDropped :: IO Bool
+isFileDropped = toBool <$> c'isFileDropped
+
+loadDroppedFiles :: IO Raylib.Types.FilePathList
+loadDroppedFiles = c'loadDroppedFiles >>= pop
+
+unloadDroppedFiles :: Raylib.Types.FilePathList -> IO ()
+unloadDroppedFiles files = withFreeable files c'unloadDroppedFiles
+
+getFileModTime :: String -> IO Integer
+getFileModTime fileName = fromIntegral <$> withCString fileName c'getFileModTime
+
+compressData :: [Integer] -> IO [Integer]
+compressData contents = do
+  withArrayLen
+    (map fromIntegral contents)
+    ( \size c -> do
+        withFreeable
+          0
+          ( \ptr -> do
+              compressed <- c'compressData c (fromIntegral $ size * sizeOf (0 :: CUChar)) ptr
+              compressedSize <- fromIntegral <$> peek ptr
+              arr <- peekArray compressedSize compressed
+              return $ map fromIntegral arr
+          )
+    )
+
+decompressData :: [Integer] -> IO [Integer]
+decompressData compressedData = do
+  withArrayLen
+    (map fromIntegral compressedData)
+    ( \size c -> do
+        withFreeable
+          0
+          ( \ptr -> do
+              decompressed <- c'decompressData c (fromIntegral $ size * sizeOf (0 :: CUChar)) ptr
+              decompressedSize <- fromIntegral <$> peek ptr
+              arr <- peekArray decompressedSize decompressed
+              return $ map fromIntegral arr
+          )
+    )
+
+encodeDataBase64 :: [Integer] -> IO [Integer]
+encodeDataBase64 contents = do
+  withArrayLen
+    (map fromIntegral contents)
+    ( \size c -> do
+        withFreeable
+          0
+          ( \ptr -> do
+              encoded <- c'encodeDataBase64 c (fromIntegral $ size * sizeOf (0 :: CUChar)) ptr
+              encodedSize <- fromIntegral <$> peek ptr
+              arr <- peekArray encodedSize encoded
+              return $ map fromIntegral arr
+          )
+    )
+
+decodeDataBase64 :: [Integer] -> IO [Integer]
+decodeDataBase64 encodedData = do
+  withArray
+    (map fromIntegral encodedData)
+    ( \c -> do
+        withFreeable
+          0
+          ( \ptr -> do
+              decoded <- c'decodeDataBase64 c ptr
+              decodedSize <- fromIntegral <$> peek ptr
+              arr <- peekArray decodedSize decoded
+              return $ map fromIntegral arr
+          )
+    )
+
+isKeyPressed :: KeyboardKey -> IO Bool
+isKeyPressed key = toBool <$> c'isKeyPressed (fromIntegral $ fromEnum key)
+
+isKeyDown :: KeyboardKey -> IO Bool
+isKeyDown key = toBool <$> c'isKeyDown (fromIntegral $ fromEnum key)
+
+isKeyReleased :: KeyboardKey -> IO Bool
+isKeyReleased key = toBool <$> c'isKeyReleased (fromIntegral $ fromEnum key)
+
+isKeyUp :: KeyboardKey -> IO Bool
+isKeyUp key = toBool <$> c'isKeyUp (fromIntegral $ fromEnum key)
+
+setExitKey :: KeyboardKey -> IO ()
+setExitKey = c'setExitKey . fromIntegral . fromEnum
+
+getKeyPressed :: IO KeyboardKey
+getKeyPressed = toEnum . fromIntegral <$> c'getKeyPressed
+
+getCharPressed :: IO Int
+getCharPressed = fromIntegral <$> c'getCharPressed
+
+isGamepadAvailable :: Int -> IO Bool
+isGamepadAvailable gamepad = toBool <$> c'isGamepadAvailable (fromIntegral gamepad)
+
+getGamepadName :: Int -> IO String
+getGamepadName gamepad = c'getGamepadName (fromIntegral gamepad) >>= peekCString
+
+isGamepadButtonPressed :: Int -> GamepadButton -> IO Bool
+isGamepadButtonPressed gamepad button = toBool <$> c'isGamepadButtonPressed (fromIntegral gamepad) (fromIntegral $ fromEnum button)
+
+isGamepadButtonDown :: Int -> GamepadButton -> IO Bool
+isGamepadButtonDown gamepad button = toBool <$> c'isGamepadButtonDown (fromIntegral gamepad) (fromIntegral $ fromEnum button)
+
+isGamepadButtonReleased :: Int -> GamepadButton -> IO Bool
+isGamepadButtonReleased gamepad button = toBool <$> c'isGamepadButtonReleased (fromIntegral gamepad) (fromIntegral $ fromEnum button)
+
+isGamepadButtonUp :: Int -> GamepadButton -> IO Bool
+isGamepadButtonUp gamepad button = toBool <$> c'isGamepadButtonUp (fromIntegral gamepad) (fromIntegral $ fromEnum button)
+
+getGamepadButtonPressed :: IO GamepadButton
+getGamepadButtonPressed = toEnum . fromIntegral <$> c'getGamepadButtonPressed
+
+getGamepadAxisCount :: Int -> IO Int
+getGamepadAxisCount gamepad = fromIntegral <$> c'getGamepadAxisCount (fromIntegral gamepad)
+
+getGamepadAxisMovement :: Int -> GamepadAxis -> IO Float
+getGamepadAxisMovement gamepad axis = realToFrac <$> c'getGamepadAxisMovement (fromIntegral gamepad) (fromIntegral $ fromEnum axis)
+
+setGamepadMappings :: String -> IO Int
+setGamepadMappings mappings = fromIntegral <$> withCString mappings c'setGamepadMappings
+
+isMouseButtonPressed :: MouseButton -> IO Bool
+isMouseButtonPressed button = toBool <$> c'isMouseButtonPressed (fromIntegral $ fromEnum button)
+
+isMouseButtonDown :: MouseButton -> IO Bool
+isMouseButtonDown button = toBool <$> c'isMouseButtonDown (fromIntegral $ fromEnum button)
+
+isMouseButtonReleased :: MouseButton -> IO Bool
+isMouseButtonReleased button = toBool <$> c'isMouseButtonReleased (fromIntegral $ fromEnum button)
+
+isMouseButtonUp :: MouseButton -> IO Bool
+isMouseButtonUp button = toBool <$> c'isMouseButtonUp (fromIntegral $ fromEnum button)
+
+getMouseX :: IO Int
+getMouseX = fromIntegral <$> c'getMouseX
+
+getMouseY :: IO Int
+getMouseY = fromIntegral <$> c'getMouseY
+
+getMousePosition :: IO Raylib.Types.Vector2
+getMousePosition = c'getMousePosition >>= pop
+
+getMouseDelta :: IO Raylib.Types.Vector2
+getMouseDelta = c'getMouseDelta >>= pop
+
+setMousePosition :: Int -> Int -> IO ()
+setMousePosition x y = c'setMousePosition (fromIntegral x) (fromIntegral y)
+
+setMouseOffset :: Int -> Int -> IO ()
+setMouseOffset x y = c'setMouseOffset (fromIntegral x) (fromIntegral y)
+
+setMouseScale :: Float -> Float -> IO ()
+setMouseScale x y = c'setMouseScale (realToFrac x) (realToFrac y)
+
+getMouseWheelMove :: IO Float
+getMouseWheelMove = realToFrac <$> c'getMouseWheelMove
+
+getMouseWheelMoveV :: IO Raylib.Types.Vector2
+getMouseWheelMoveV = c'getMouseWheelMoveV >>= pop
+
+setMouseCursor :: MouseCursor -> IO ()
+setMouseCursor cursor = c'setMouseCursor . fromIntegral $ fromEnum cursor
+
+getTouchX :: IO Int
+getTouchX = fromIntegral <$> c'getTouchX
+
+getTouchY :: IO Int
+getTouchY = fromIntegral <$> c'getTouchY
+
+getTouchPosition :: Int -> IO Raylib.Types.Vector2
+getTouchPosition index = c'getTouchPosition (fromIntegral index) >>= pop
+
+getTouchPointId :: Int -> IO Int
+getTouchPointId index = fromIntegral <$> c'getTouchPointId (fromIntegral index)
+
+getTouchPointCount :: IO Int
+getTouchPointCount = fromIntegral <$> c'getTouchPointCount
+
+setGesturesEnabled :: [Gesture] -> IO ()
+setGesturesEnabled flags = c'setGesturesEnabled (fromIntegral $ configsToBitflag flags)
+
+isGestureDetected :: Gesture -> IO Bool
+isGestureDetected gesture = toBool <$> c'isGestureDetected (fromIntegral $ fromEnum gesture)
+
+getGestureDetected :: IO Gesture
+getGestureDetected = toEnum . fromIntegral <$> c'getGestureDetected
+
+getGestureHoldDuration :: IO Float
+getGestureHoldDuration = realToFrac <$> c'getGestureHoldDuration
+
+getGestureDragVector :: IO Raylib.Types.Vector2
+getGestureDragVector = c'getGestureDragVector >>= pop
+
+getGestureDragAngle :: IO Float
+getGestureDragAngle = realToFrac <$> c'getGestureDragAngle
+
+getGesturePinchVector :: IO Raylib.Types.Vector2
+getGesturePinchVector = c'getGesturePinchVector >>= pop
+
+getGesturePinchAngle :: IO Float
+getGesturePinchAngle = realToFrac <$> c'getGesturePinchAngle
+
+setCameraMode :: Raylib.Types.Camera3D -> CameraMode -> IO ()
+setCameraMode camera mode = withFreeable camera (\c -> c'setCameraMode c (fromIntegral $ fromEnum mode))
+
+updateCamera :: Raylib.Types.Camera3D -> IO Raylib.Types.Camera3D
+updateCamera camera =
+  withFreeable
+    camera
+    ( \c -> do
+        c'updateCamera c
+        peek c
+    )
+
+setCameraPanControl :: Int -> IO ()
+setCameraPanControl keyPan = c'setCameraPanControl $ fromIntegral keyPan
+
+setCameraAltControl :: Int -> IO ()
+setCameraAltControl keyAlt = c'setCameraAltControl $ fromIntegral keyAlt
+
+setCameraSmoothZoomControl :: Int -> IO ()
+setCameraSmoothZoomControl keySmoothZoom = c'setCameraSmoothZoomControl $ fromIntegral keySmoothZoom
+
+setCameraMoveControls :: Int -> Int -> Int -> Int -> Int -> Int -> IO ()
+setCameraMoveControls keyFront keyBack keyRight keyLeft keyUp keyDown =
+  c'setCameraMoveControls
+    (fromIntegral keyFront)
+    (fromIntegral keyBack)
+    (fromIntegral keyRight)
+    (fromIntegral keyLeft)
+    (fromIntegral keyUp)
+    (fromIntegral keyDown)
+ src/Raylib/Internal.hs view
@@ -0,0 +1,8 @@+{-# OPTIONS -Wall #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module Raylib.Internal (c'rlGetShaderIdDefault) where
+
+import Foreign.C (CInt(..))
+
+foreign import ccall safe "rlgl.h rlGetShaderIdDefault" c'rlGetShaderIdDefault :: IO CInt
+ src/Raylib/Models.hs view
@@ -0,0 +1,355 @@+{-# OPTIONS -Wall #-}
+
+module Raylib.Models where
+
+import Foreign
+  ( Ptr,
+    Storable (peek, poke),
+    fromBool,
+    peekArray,
+    toBool,
+    withArray,
+    withArrayLen, malloc
+  )
+import Foreign.C (CFloat, withCString)
+import GHC.IO (unsafePerformIO)
+import Raylib.Native
+  ( c'checkCollisionBoxSphere,
+    c'checkCollisionBoxes,
+    c'checkCollisionSpheres,
+    c'drawBillboard,
+    c'drawBillboardPro,
+    c'drawBillboardRec,
+    c'drawBoundingBox,
+    c'drawCapsule,
+    c'drawCapsuleWires,
+    c'drawCircle3D,
+    c'drawCube,
+    c'drawCubeV,
+    c'drawCubeWires,
+    c'drawCubeWiresV,
+    c'drawCylinder,
+    c'drawCylinderEx,
+    c'drawCylinderWires,
+    c'drawCylinderWiresEx,
+    c'drawGrid,
+    c'drawLine3D,
+    c'drawMesh,
+    c'drawMeshInstanced,
+    c'drawModel,
+    c'drawModelEx,
+    c'drawModelWires,
+    c'drawModelWiresEx,
+    c'drawPlane,
+    c'drawPoint3D,
+    c'drawRay,
+    c'drawSphere,
+    c'drawSphereEx,
+    c'drawSphereWires,
+    c'drawTriangle3D,
+    c'drawTriangleStrip3D,
+    c'exportMesh,
+    c'genMeshCone,
+    c'genMeshCube,
+    c'genMeshCubicmap,
+    c'genMeshCylinder,
+    c'genMeshHeightmap,
+    c'genMeshHemiSphere,
+    c'genMeshKnot,
+    c'genMeshPlane,
+    c'genMeshPoly,
+    c'genMeshSphere,
+    c'genMeshTangents,
+    c'genMeshTorus,
+    c'getMeshBoundingBox,
+    c'getModelBoundingBox,
+    c'getRayCollisionBox,
+    c'getRayCollisionMesh,
+    c'getRayCollisionQuad,
+    c'getRayCollisionSphere,
+    c'getRayCollisionTriangle,
+    c'isModelAnimationValid,
+    c'loadMaterialDefault,
+    c'loadMaterials,
+    c'loadModel,
+    c'loadModelAnimations,
+    c'loadModelFromMesh,
+    c'setMaterialTexture,
+    c'setModelMeshMaterial,
+    c'unloadMaterial,
+    c'unloadMesh,
+    c'unloadModel,
+    c'unloadModelAnimation,
+    c'unloadModelAnimations,
+    c'unloadModelKeepMeshes,
+    c'updateMeshBuffer,
+    c'updateModelAnimation,
+    c'uploadMesh, c'isModelReady, c'isMaterialReady
+  )
+import Raylib.Types
+  ( BoundingBox,
+    Camera3D,
+    Color,
+    Image,
+    Material,
+    Matrix,
+    Mesh,
+    Model,
+    ModelAnimation,
+    Ray,
+    RayCollision,
+    Rectangle,
+    Texture,
+    Vector2,
+    Vector3,
+  )
+import Raylib.Util
+  ( pop,
+    withFreeable,
+  )
+import Prelude hiding (length)
+
+drawLine3D :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
+drawLine3D start end color = withFreeable start (\s -> withFreeable end (withFreeable color . c'drawLine3D s))
+
+drawPoint3D :: Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
+drawPoint3D point color = withFreeable point (withFreeable color . c'drawPoint3D)
+
+drawCircle3D :: Raylib.Types.Vector3 -> Float -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Color -> IO ()
+drawCircle3D center radius rotationAxis rotationAngle color = withFreeable center (\c -> withFreeable rotationAxis (\r -> withFreeable color (c'drawCircle3D c (realToFrac radius) r (realToFrac rotationAngle))))
+
+drawTriangle3D :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
+drawTriangle3D v1 v2 v3 color = withFreeable v1 (\p1 -> withFreeable v2 (\p2 -> withFreeable v3 (withFreeable color . c'drawTriangle3D p1 p2)))
+
+drawTriangleStrip3D :: [Raylib.Types.Vector3] -> Int -> Raylib.Types.Color -> IO ()
+drawTriangleStrip3D points pointCount color = withArray points (\p -> withFreeable color (c'drawTriangleStrip3D p (fromIntegral pointCount)))
+
+drawCube :: Raylib.Types.Vector3 -> Float -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawCube position width height length color = withFreeable position (\p -> withFreeable color (c'drawCube p (realToFrac width) (realToFrac height) (realToFrac length)))
+
+drawCubeV :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
+drawCubeV position size color = withFreeable position (\p -> withFreeable size (withFreeable color . c'drawCubeV p))
+
+drawCubeWires :: Raylib.Types.Vector3 -> Float -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawCubeWires position width height length color = withFreeable position (\p -> withFreeable color (c'drawCubeWires p (realToFrac width) (realToFrac height) (realToFrac length)))
+
+drawCubeWiresV :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
+drawCubeWiresV position size color = withFreeable position (\p -> withFreeable size (withFreeable color . c'drawCubeWiresV p))
+
+drawSphere :: Raylib.Types.Vector3 -> Float -> Raylib.Types.Color -> IO ()
+drawSphere position radius color = withFreeable position (\p -> withFreeable color (c'drawSphere p (realToFrac radius)))
+
+drawSphereEx :: Raylib.Types.Vector3 -> Float -> Int -> Int -> Raylib.Types.Color -> IO ()
+drawSphereEx position radius rings slices color = withFreeable position (\p -> withFreeable color (c'drawSphereEx p (realToFrac radius) (fromIntegral rings) (fromIntegral slices)))
+
+drawSphereWires :: Raylib.Types.Vector3 -> Float -> Int -> Int -> Raylib.Types.Color -> IO ()
+drawSphereWires position radius rings slices color = withFreeable position (\p -> withFreeable color (c'drawSphereWires p (realToFrac radius) (fromIntegral rings) (fromIntegral slices)))
+
+drawCylinder :: Raylib.Types.Vector3 -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
+drawCylinder position radiusTop radiusBottom height slices color = withFreeable position (\p -> withFreeable color (c'drawCylinder p (realToFrac radiusTop) (realToFrac radiusBottom) (realToFrac height) (fromIntegral slices)))
+
+drawCylinderEx :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
+drawCylinderEx start end startRadius endRadius sides color = withFreeable start (\s -> withFreeable end (\e -> withFreeable color (c'drawCylinderEx s e (realToFrac startRadius) (realToFrac endRadius) (fromIntegral sides))))
+
+drawCylinderWires :: Raylib.Types.Vector3 -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
+drawCylinderWires position radiusTop radiusBottom height slices color = withFreeable position (\p -> withFreeable color (c'drawCylinderWires p (realToFrac radiusTop) (realToFrac radiusBottom) (realToFrac height) (fromIntegral slices)))
+
+drawCylinderWiresEx :: Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
+drawCylinderWiresEx start end startRadius endRadius sides color = withFreeable start (\s -> withFreeable end (\e -> withFreeable color (c'drawCylinderWiresEx s e (realToFrac startRadius) (realToFrac endRadius) (fromIntegral sides))))
+
+drawCapsule :: Vector3 -> Vector3 -> CFloat -> Int -> Int -> Color -> IO ()
+drawCapsule start end radius slices rings color = withFreeable start (\s -> withFreeable end (\e -> withFreeable color (c'drawCapsule s e (realToFrac radius) (fromIntegral slices) (fromIntegral rings))))
+
+drawCapsuleWires :: Vector3 -> Vector3 -> CFloat -> Int -> Int -> Color -> IO ()
+drawCapsuleWires start end radius slices rings color = withFreeable start (\s -> withFreeable end (\e -> withFreeable color (c'drawCapsuleWires s e (realToFrac radius) (fromIntegral slices) (fromIntegral rings))))
+
+drawPlane :: Raylib.Types.Vector3 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
+drawPlane center size color = withFreeable center (\c -> withFreeable size (withFreeable color . c'drawPlane c))
+
+drawRay :: Raylib.Types.Ray -> Raylib.Types.Color -> IO ()
+drawRay ray color = withFreeable ray (withFreeable color . c'drawRay)
+
+drawGrid :: Int -> Float -> IO ()
+drawGrid slices spacing = c'drawGrid (fromIntegral slices) (realToFrac spacing)
+
+loadModel :: String -> IO Raylib.Types.Model
+loadModel fileName = withCString fileName c'loadModel >>= pop
+
+loadModelFromMesh :: Raylib.Types.Mesh -> IO Raylib.Types.Model
+loadModelFromMesh mesh = do
+  ptr <- malloc
+  poke ptr mesh
+  model <- c'loadModelFromMesh ptr
+  pop model
+
+isModelReady :: Raylib.Types.Model -> IO Bool
+isModelReady model = toBool <$> withFreeable model c'isModelReady
+
+unloadModel :: Raylib.Types.Model -> IO ()
+unloadModel model = withFreeable model c'unloadModel
+
+unloadModelKeepMeshes :: Raylib.Types.Model -> IO ()
+unloadModelKeepMeshes model = withFreeable model c'unloadModelKeepMeshes
+
+getModelBoundingBox :: Raylib.Types.Model -> IO Raylib.Types.BoundingBox
+getModelBoundingBox model = withFreeable model c'getModelBoundingBox >>= pop
+
+drawModel :: Raylib.Types.Model -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Color -> IO ()
+drawModel model position scale tint = withFreeable model (\m -> withFreeable position (\p -> withFreeable tint (c'drawModel m p (realToFrac scale))))
+
+drawModelEx :: Raylib.Types.Model -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
+drawModelEx model position rotationAxis rotationAngle scale tint = withFreeable model (\m -> withFreeable position (\p -> withFreeable rotationAxis (\r -> withFreeable scale (withFreeable tint . c'drawModelEx m p r (realToFrac rotationAngle)))))
+
+drawModelWires :: Raylib.Types.Model -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Color -> IO ()
+drawModelWires model position scale tint = withFreeable model (\m -> withFreeable position (\p -> withFreeable tint (c'drawModelWires m p (realToFrac scale))))
+
+drawModelWiresEx :: Raylib.Types.Model -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Vector3 -> Raylib.Types.Color -> IO ()
+drawModelWiresEx model position rotationAxis rotationAngle scale tint = withFreeable model (\m -> withFreeable position (\p -> withFreeable rotationAxis (\r -> withFreeable scale (withFreeable tint . c'drawModelWiresEx m p r (realToFrac rotationAngle)))))
+
+drawBoundingBox :: Raylib.Types.BoundingBox -> Raylib.Types.Color -> IO ()
+drawBoundingBox box color = withFreeable box (withFreeable color . c'drawBoundingBox)
+
+drawBillboard :: Raylib.Types.Camera3D -> Raylib.Types.Texture -> Raylib.Types.Vector3 -> Float -> Raylib.Types.Color -> IO ()
+drawBillboard camera texture position size tint = withFreeable camera (\c -> withFreeable texture (\t -> withFreeable position (\p -> withFreeable tint (c'drawBillboard c t p (realToFrac size)))))
+
+drawBillboardRec :: Raylib.Types.Camera3D -> Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Vector3 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
+drawBillboardRec camera texture source position size tint = withFreeable camera (\c -> withFreeable texture (\t -> withFreeable source (\s -> withFreeable position (\p -> withFreeable size (withFreeable tint . c'drawBillboardRec c t s p)))))
+
+drawBillboardPro :: Raylib.Types.Camera3D -> Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
+drawBillboardPro camera texture source position up size origin rotation tint = withFreeable camera (\c -> withFreeable texture (\t -> withFreeable source (\s -> withFreeable position (\p -> withFreeable up (\u -> withFreeable size (\sz -> withFreeable origin (\o -> withFreeable tint (c'drawBillboardPro c t s p u sz o (realToFrac rotation)))))))))
+
+uploadMesh :: Raylib.Types.Mesh -> Bool -> IO Raylib.Types.Mesh
+uploadMesh mesh dynamic = withFreeable mesh (\m -> c'uploadMesh m (fromBool dynamic) >> peek m)
+
+updateMeshBuffer :: Raylib.Types.Mesh -> Int -> Ptr () -> Int -> Int -> IO ()
+updateMeshBuffer mesh index dataValue dataSize offset = withFreeable mesh (\m -> c'updateMeshBuffer m (fromIntegral index) dataValue (fromIntegral dataSize) (fromIntegral offset))
+
+unloadMesh :: Raylib.Types.Mesh -> IO ()
+unloadMesh mesh = withFreeable mesh c'unloadMesh
+
+drawMesh :: Raylib.Types.Mesh -> Raylib.Types.Material -> Raylib.Types.Matrix -> IO ()
+drawMesh mesh material transform = withFreeable mesh (\m -> withFreeable material (withFreeable transform . c'drawMesh m))
+
+drawMeshInstanced :: Raylib.Types.Mesh -> Raylib.Types.Material -> [Raylib.Types.Matrix] -> IO ()
+drawMeshInstanced mesh material transforms = withFreeable mesh (\m -> withFreeable material (\mat -> withArrayLen transforms (\size t -> c'drawMeshInstanced m mat t (fromIntegral size))))
+
+exportMesh :: Raylib.Types.Mesh -> String -> IO Bool
+exportMesh mesh fileName = toBool <$> withFreeable mesh (withCString fileName . c'exportMesh)
+
+getMeshBoundingBox :: Raylib.Types.Mesh -> IO Raylib.Types.BoundingBox
+getMeshBoundingBox mesh = withFreeable mesh c'getMeshBoundingBox >>= pop
+
+genMeshTangents :: Raylib.Types.Mesh -> IO Raylib.Types.Mesh
+genMeshTangents mesh = withFreeable mesh (\m -> c'genMeshTangents m >> peek m)
+
+genMeshPoly :: Int -> Float -> IO Raylib.Types.Mesh
+genMeshPoly sides radius = c'genMeshPoly (fromIntegral sides) (realToFrac radius) >>= pop
+
+genMeshPlane :: Float -> Float -> Int -> Int -> IO Raylib.Types.Mesh
+genMeshPlane width length resX resZ = c'genMeshPlane (realToFrac width) (realToFrac length) (fromIntegral resX) (fromIntegral resZ) >>= pop
+
+genMeshCube :: Float -> Float -> Float -> IO Raylib.Types.Mesh
+genMeshCube width height length = c'genMeshCube (realToFrac width) (realToFrac height) (realToFrac length) >>= pop
+
+genMeshSphere :: Float -> Int -> Int -> IO Raylib.Types.Mesh
+genMeshSphere radius rings slices = c'genMeshSphere (realToFrac radius) (fromIntegral rings) (fromIntegral slices) >>= pop
+
+genMeshHemiSphere :: Float -> Int -> Int -> IO Raylib.Types.Mesh
+genMeshHemiSphere radius rings slices = c'genMeshHemiSphere (realToFrac radius) (fromIntegral rings) (fromIntegral slices) >>= pop
+
+genMeshCylinder :: Float -> Float -> Int -> IO Raylib.Types.Mesh
+genMeshCylinder radius height slices = c'genMeshCylinder (realToFrac radius) (realToFrac height) (fromIntegral slices) >>= pop
+
+genMeshCone :: Float -> Float -> Int -> IO Raylib.Types.Mesh
+genMeshCone radius height slices = c'genMeshCone (realToFrac radius) (realToFrac height) (fromIntegral slices) >>= pop
+
+genMeshTorus :: Float -> Float -> Int -> Int -> IO Raylib.Types.Mesh
+genMeshTorus radius size radSeg sides = c'genMeshTorus (realToFrac radius) (realToFrac size) (fromIntegral radSeg) (fromIntegral sides) >>= pop
+
+genMeshKnot :: Float -> Float -> Int -> Int -> IO Raylib.Types.Mesh
+genMeshKnot radius size radSeg sides = c'genMeshKnot (realToFrac radius) (realToFrac size) (fromIntegral radSeg) (fromIntegral sides) >>= pop
+
+genMeshHeightmap :: Raylib.Types.Image -> Raylib.Types.Vector3 -> IO Raylib.Types.Mesh
+genMeshHeightmap heightmap size = withFreeable heightmap (withFreeable size . c'genMeshHeightmap) >>= pop
+
+genMeshCubicmap :: Raylib.Types.Image -> Raylib.Types.Vector3 -> IO Raylib.Types.Mesh
+genMeshCubicmap cubicmap cubeSize = withFreeable cubicmap (withFreeable cubeSize . c'genMeshCubicmap) >>= pop
+
+loadMaterials :: String -> IO [Raylib.Types.Material]
+loadMaterials fileName =
+  withCString
+    fileName
+    ( \f ->
+        withFreeable
+          0
+          ( \n -> do
+              ptr <- c'loadMaterials f n
+              num <- peek n
+              peekArray (fromIntegral num) ptr
+          )
+    )
+
+loadMaterialDefault :: IO Raylib.Types.Material
+loadMaterialDefault = c'loadMaterialDefault >>= pop
+
+isMaterialReady :: Raylib.Types.Material -> IO Bool
+isMaterialReady material = toBool <$> withFreeable material c'isMaterialReady
+
+unloadMaterial :: Raylib.Types.Material -> IO ()
+unloadMaterial material = withFreeable material c'unloadMaterial
+
+setMaterialTexture :: Raylib.Types.Material -> Int -> Raylib.Types.Texture -> IO Raylib.Types.Material
+setMaterialTexture material mapType texture = withFreeable material (\m -> withFreeable texture (c'setMaterialTexture m (fromIntegral mapType)) >> peek m)
+
+setModelMeshMaterial :: Raylib.Types.Model -> Int -> Int -> IO Raylib.Types.Model
+setModelMeshMaterial model meshId materialId = withFreeable model (\m -> c'setModelMeshMaterial m (fromIntegral meshId) (fromIntegral materialId) >> peek m)
+
+loadModelAnimations :: String -> IO [Raylib.Types.ModelAnimation]
+loadModelAnimations fileName =
+  withCString
+    fileName
+    ( \f ->
+        withFreeable
+          0
+          ( \n -> do
+              ptr <- c'loadModelAnimations f n
+              num <- peek n
+              peekArray (fromIntegral num) ptr
+          )
+    )
+
+updateModelAnimation :: Raylib.Types.Model -> Raylib.Types.ModelAnimation -> Int -> IO ()
+updateModelAnimation model animation frame = withFreeable model (\m -> withFreeable animation (\a -> c'updateModelAnimation m a (fromIntegral frame)))
+
+unloadModelAnimation :: ModelAnimation -> IO ()
+unloadModelAnimation animation = withFreeable animation c'unloadModelAnimation
+
+unloadModelAnimations :: [ModelAnimation] -> IO ()
+unloadModelAnimations animations = withArrayLen animations (\num a -> c'unloadModelAnimations a (fromIntegral num))
+
+isModelAnimationValid :: Model -> ModelAnimation -> IO Bool
+isModelAnimationValid model animation = toBool <$> withFreeable model (withFreeable animation . c'isModelAnimationValid)
+
+checkCollisionSpheres :: Vector3 -> Float -> Vector3 -> Float -> Bool
+checkCollisionSpheres center1 radius1 center2 radius2 = toBool $ unsafePerformIO (withFreeable center1 (\c1 -> withFreeable center2 (\c2 -> c'checkCollisionSpheres c1 (realToFrac radius1) c2 (realToFrac radius2))))
+
+checkCollisionBoxes :: BoundingBox -> BoundingBox -> Bool
+checkCollisionBoxes box1 box2 = toBool $ unsafePerformIO (withFreeable box1 (withFreeable box2 . c'checkCollisionBoxes))
+
+checkCollisionBoxSphere :: BoundingBox -> Vector3 -> Float -> Bool
+checkCollisionBoxSphere box center radius = toBool $ unsafePerformIO (withFreeable box (\b -> withFreeable center (\c -> c'checkCollisionBoxSphere b c (realToFrac radius))))
+
+getRayCollisionSphere :: Ray -> Vector3 -> Float -> RayCollision
+getRayCollisionSphere ray center radius = unsafePerformIO $ withFreeable ray (\r -> withFreeable center (\c -> c'getRayCollisionSphere r c (realToFrac radius))) >>= pop
+
+getRayCollisionBox :: Ray -> BoundingBox -> RayCollision
+getRayCollisionBox ray box = unsafePerformIO $ withFreeable ray (withFreeable box . c'getRayCollisionBox) >>= pop
+
+getRayCollisionMesh :: Ray -> Mesh -> Matrix -> RayCollision
+getRayCollisionMesh ray mesh transform = unsafePerformIO $ withFreeable ray (\r -> withFreeable mesh (withFreeable transform . c'getRayCollisionMesh r)) >>= pop
+
+getRayCollisionTriangle :: Ray -> Vector3 -> Vector3 -> Vector3 -> RayCollision
+getRayCollisionTriangle ray v1 v2 v3 = unsafePerformIO $ withFreeable ray (\r -> withFreeable v1 (\p1 -> withFreeable v2 (withFreeable v3 . c'getRayCollisionTriangle r p1))) >>= pop
+
+getRayCollisionQuad :: Ray -> Vector3 -> Vector3 -> Vector3 -> Vector3 -> RayCollision
+getRayCollisionQuad ray v1 v2 v3 v4 = unsafePerformIO $ withFreeable ray (\r -> withFreeable v1 (\p1 -> withFreeable v2 (\p2 -> withFreeable v3 (withFreeable v4 . c'getRayCollisionQuad r p1 p2)))) >>= pop
+ src/Raylib/Native.hs view
@@ -0,0 +1,1440 @@+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-# OPTIONS -Wall #-}
+
+module Raylib.Native where
+
+import Foreign (Ptr)
+import Foreign.C
+  ( CBool (..),
+    CDouble (..),
+    CFloat (..),
+    CInt (..),
+    CLong (..),
+    CString,
+    CUChar,
+    CUInt (..),
+  )
+import Raylib.Types
+  ( AudioCallback,
+    AudioStream,
+    BoundingBox,
+    Camera2D,
+    Camera3D,
+    Color,
+    FilePathList,
+    Font,
+    GlyphInfo,
+    Image,
+    LoadFileDataCallback,
+    LoadFileTextCallback,
+    Material,
+    Matrix,
+    Mesh,
+    Model,
+    ModelAnimation,
+    Music,
+    NPatchInfo,
+    Ray,
+    RayCollision,
+    Rectangle,
+    RenderTexture,
+    SaveFileDataCallback,
+    SaveFileTextCallback,
+    Shader,
+    Sound,
+    Texture,
+    Vector2,
+    Vector3,
+    Vector4,
+    VrDeviceInfo,
+    VrStereoConfig,
+    Wave,
+  )
+import Prelude hiding (length)
+
+-- foreign import ccall safe "wrapper"
+--   mk'TraceLogCallback ::
+--     (CInt -> CString -> __builtin_va_list -> IO ()) -> IO TraceLogCallback
+-- foreign import ccall safe "dynamic"
+--   mK'TraceLogCallback ::
+--     TraceLogCallback -> (CInt -> CString -> __builtin_va_list -> IO ())
+-- TODO: redesign this
+foreign import ccall safe "wrapper"
+  mk'loadFileDataCallback ::
+    (CString -> Ptr CUInt -> IO (Ptr CUChar)) -> IO LoadFileDataCallback
+
+foreign import ccall safe "dynamic"
+  mK'loadFileDataCallback ::
+    LoadFileDataCallback -> (CString -> Ptr CUInt -> IO (Ptr CUChar))
+
+foreign import ccall safe "wrapper"
+  mk'saveFileDataCallback ::
+    (CString -> Ptr () -> CUInt -> IO CInt) -> IO SaveFileDataCallback
+
+foreign import ccall safe "dynamic"
+  mK'saveFileDataCallback ::
+    SaveFileDataCallback -> (CString -> Ptr () -> CUInt -> IO CInt)
+
+foreign import ccall safe "wrapper"
+  mk'loadFileTextCallback ::
+    (CString -> IO CString) -> IO LoadFileTextCallback
+
+foreign import ccall safe "dynamic"
+  mK'loadFileTextCallback ::
+    LoadFileTextCallback -> (CString -> IO CString)
+
+foreign import ccall safe "wrapper"
+  mk'saveFileTextCallback ::
+    (CString -> CString -> IO CInt) -> IO SaveFileTextCallback
+
+foreign import ccall safe "dynamic"
+  mK'saveFileTextCallback ::
+    SaveFileTextCallback -> (CString -> CString -> IO CInt)
+
+foreign import ccall safe "raylib.h InitWindow"
+  c'initWindow ::
+    CInt -> CInt -> CString -> IO ()
+
+foreign import ccall safe "raylib.h WindowShouldClose"
+  c'windowShouldClose ::
+    IO CBool
+
+foreign import ccall safe "raylib.h IsWindowReady"
+  c'isWindowReady ::
+    IO CBool
+
+foreign import ccall safe "raylib.h IsWindowFullscreen"
+  c'isWindowFullscreen ::
+    IO CBool
+
+foreign import ccall safe "raylib.h IsWindowHidden"
+  c'isWindowHidden ::
+    IO CBool
+
+foreign import ccall safe "raylib.h IsWindowMinimized"
+  c'isWindowMinimized ::
+    IO CBool
+
+foreign import ccall safe "raylib.h IsWindowMaximized"
+  c'isWindowMaximized ::
+    IO CBool
+
+foreign import ccall safe "raylib.h IsWindowFocused"
+  c'isWindowFocused ::
+    IO CBool
+
+foreign import ccall safe "raylib.h IsWindowResized"
+  c'isWindowResized ::
+    IO CBool
+
+foreign import ccall safe "raylib.h IsWindowState"
+  c'isWindowState ::
+    CUInt -> IO CBool
+
+foreign import ccall safe "raylib.h SetWindowState"
+  c'setWindowState ::
+    CUInt -> IO ()
+
+foreign import ccall safe "raylib.h ClearWindowState"
+  c'clearWindowState ::
+    CUInt -> IO ()
+
+foreign import ccall safe "bindings.h SetWindowIcon_" c'setWindowIcon :: Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "raylib.h SetWindowTitle"
+  c'setWindowTitle ::
+    CString -> IO ()
+
+foreign import ccall safe "raylib.h SetWindowPosition"
+  c'setWindowPosition ::
+    CInt -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h SetWindowMonitor"
+  c'setWindowMonitor ::
+    CInt -> IO ()
+
+foreign import ccall safe "raylib.h SetWindowMinSize"
+  c'setWindowMinSize ::
+    CInt -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h SetWindowSize"
+  c'setWindowSize ::
+    CInt -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h SetWindowOpacity"
+  c'setWindowOpacity ::
+    CFloat -> IO ()
+
+foreign import ccall safe "raylib.h GetScreenWidth"
+  c'getScreenWidth ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetScreenHeight"
+  c'getScreenHeight ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetRenderWidth"
+  c'getRenderWidth ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetRenderHeight"
+  c'getRenderHeight ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetMonitorCount"
+  c'getMonitorCount ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetCurrentMonitor"
+  c'getCurrentMonitor ::
+    IO CInt
+
+foreign import ccall safe "bindings.h GetMonitorPosition_" c'getMonitorPosition :: CInt -> IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "raylib.h GetMonitorWidth"
+  c'getMonitorWidth ::
+    CInt -> IO CInt
+
+foreign import ccall safe "raylib.h GetMonitorHeight"
+  c'getMonitorHeight ::
+    CInt -> IO CInt
+
+foreign import ccall safe "raylib.h GetMonitorPhysicalWidth"
+  c'getMonitorPhysicalWidth ::
+    CInt -> IO CInt
+
+foreign import ccall safe "raylib.h GetMonitorPhysicalHeight"
+  c'getMonitorPhysicalHeight ::
+    CInt -> IO CInt
+
+foreign import ccall safe "raylib.h GetMonitorRefreshRate"
+  c'getMonitorRefreshRate ::
+    CInt -> IO CInt
+
+foreign import ccall safe "bindings.h GetWindowPosition_" c'getWindowPosition :: IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "bindings.h GetWindowScaleDPI_" c'getWindowScaleDPI :: IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "raylib.h GetMonitorName"
+  c'getMonitorName ::
+    CInt -> IO CString
+
+foreign import ccall safe "raylib.h SetClipboardText"
+  c'setClipboardText ::
+    CString -> IO ()
+
+foreign import ccall safe "raylib.h GetClipboardText"
+  c'getClipboardText ::
+    IO CString
+
+foreign import ccall safe "raylib.h WaitTime"
+  c'waitTime ::
+    CDouble -> IO ()
+
+foreign import ccall safe "raylib.h IsCursorHidden"
+  c'isCursorHidden ::
+    IO CBool
+
+foreign import ccall safe "raylib.h IsCursorOnScreen"
+  c'isCursorOnScreen ::
+    IO CBool
+
+foreign import ccall safe "bindings.h ClearBackground_" c'clearBackground :: Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h BeginMode2D_" c'beginMode2D :: Ptr Raylib.Types.Camera2D -> IO ()
+
+foreign import ccall safe "bindings.h BeginMode3D_" c'beginMode3D :: Ptr Raylib.Types.Camera3D -> IO ()
+
+foreign import ccall safe "bindings.h BeginTextureMode_" c'beginTextureMode :: Ptr Raylib.Types.RenderTexture -> IO ()
+
+foreign import ccall safe "bindings.h BeginShaderMode_" c'beginShaderMode :: Ptr Raylib.Types.Shader -> IO ()
+
+foreign import ccall safe "raylib.h BeginBlendMode"
+  c'beginBlendMode ::
+    CInt -> IO ()
+
+foreign import ccall safe "raylib.h BeginScissorMode"
+  c'beginScissorMode ::
+    CInt -> CInt -> CInt -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h BeginVrStereoMode_" c'beginVrStereoMode :: Ptr Raylib.Types.VrStereoConfig -> IO ()
+
+foreign import ccall safe "bindings.h LoadVrStereoConfig_" c'loadVrStereoConfig :: Ptr Raylib.Types.VrDeviceInfo -> IO (Ptr Raylib.Types.VrStereoConfig)
+
+foreign import ccall safe "bindings.h UnloadVrStereoConfig_" c'unloadVrStereoConfig :: Ptr Raylib.Types.VrStereoConfig -> IO ()
+
+foreign import ccall safe "bindings.h LoadShader_" c'loadShader :: CString -> CString -> IO (Ptr Raylib.Types.Shader)
+
+foreign import ccall safe "bindings.h LoadShaderFromMemory_" c'loadShaderFromMemory :: CString -> CString -> IO (Ptr Raylib.Types.Shader)
+
+foreign import ccall safe "bindings.h IsShaderReady_" c'isShaderReady :: Ptr Shader -> IO CBool
+
+foreign import ccall safe "bindings.h GetShaderLocation_" c'getShaderLocation :: Ptr Raylib.Types.Shader -> CString -> IO CInt
+
+foreign import ccall safe "bindings.h GetShaderLocationAttrib_" c'getShaderLocationAttrib :: Ptr Raylib.Types.Shader -> CString -> IO CInt
+
+foreign import ccall safe "bindings.h SetShaderValue_" c'setShaderValue :: Ptr Raylib.Types.Shader -> CInt -> Ptr () -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h SetShaderValueV_" c'setShaderValueV :: Ptr Raylib.Types.Shader -> CInt -> Ptr () -> CInt -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h SetShaderValueMatrix_" c'setShaderValueMatrix :: Ptr Raylib.Types.Shader -> CInt -> Ptr Raylib.Types.Matrix -> IO ()
+
+foreign import ccall safe "bindings.h SetShaderValueTexture_" c'setShaderValueTexture :: Ptr Raylib.Types.Shader -> CInt -> Ptr Raylib.Types.Texture -> IO ()
+
+foreign import ccall safe "bindings.h UnloadShader_" c'unloadShader :: Ptr Raylib.Types.Shader -> IO ()
+
+foreign import ccall safe "bindings.h GetMouseRay_" c'getMouseRay :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Camera3D -> IO (Ptr Raylib.Types.Ray)
+
+foreign import ccall safe "bindings.h GetCameraMatrix_" c'getCameraMatrix :: Ptr Raylib.Types.Camera3D -> IO (Ptr Raylib.Types.Matrix)
+
+foreign import ccall safe "bindings.h GetCameraMatrix2D_" c'getCameraMatrix2D :: Ptr Raylib.Types.Camera2D -> IO (Ptr Raylib.Types.Matrix)
+
+foreign import ccall safe "bindings.h GetWorldToScreen_" c'getWorldToScreen :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Camera3D -> IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "bindings.h GetScreenToWorld2D_" c'getScreenToWorld2D :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Camera2D -> IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "bindings.h GetWorldToScreenEx_" c'getWorldToScreenEx :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Camera3D -> CInt -> CInt -> IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "bindings.h GetWorldToScreen2D_" c'getWorldToScreen2D :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Camera2D -> IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "raylib.h SetTargetFPS"
+  c'setTargetFPS ::
+    CInt -> IO ()
+
+foreign import ccall safe "raylib.h GetFPS"
+  c'getFPS ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetFrameTime"
+  c'getFrameTime ::
+    IO CFloat
+
+foreign import ccall safe "raylib.h GetTime"
+  c'getTime ::
+    IO CDouble
+
+foreign import ccall safe "raylib.h GetRandomValue"
+  c'getRandomValue ::
+    CInt -> CInt -> IO CInt
+
+foreign import ccall safe "raylib.h SetRandomSeed"
+  c'setRandomSeed ::
+    CUInt -> IO ()
+
+foreign import ccall safe "raylib.h TakeScreenshot"
+  c'takeScreenshot ::
+    CString -> IO ()
+
+foreign import ccall safe "raylib.h SetConfigFlags"
+  c'setConfigFlags ::
+    CUInt -> IO ()
+
+foreign import ccall safe "raylib.h TraceLog"
+  c'traceLog ::
+    CInt -> CString -> IO () -- Uses varags, can't implement complete functionality
+
+foreign import ccall safe "raylib.h SetTraceLogLevel"
+  c'setTraceLogLevel ::
+    CInt -> IO ()
+
+foreign import ccall safe "raylib.h MemAlloc"
+  c'memAlloc ::
+    CInt -> IO (Ptr ())
+
+foreign import ccall safe "raylib.h MemRealloc"
+  c'memRealloc ::
+    Ptr () -> CInt -> IO (Ptr ())
+
+foreign import ccall safe "raylib.h MemFree"
+  c'memFree ::
+    Ptr () -> IO ()
+
+foreign import ccall safe "raylib.h OpenURL"
+  c'openURL ::
+    CString -> IO ()
+
+foreign import ccall safe "raylib.h LoadFileData"
+  c'loadFileData ::
+    CString -> Ptr CUInt -> IO (Ptr CUChar)
+
+foreign import ccall safe "raylib.h UnloadFileData"
+  c'unloadFileData ::
+    Ptr CUChar -> IO ()
+
+foreign import ccall safe "raylib.h SaveFileData"
+  c'saveFileData ::
+    CString -> Ptr () -> CUInt -> IO CBool
+
+foreign import ccall safe "raylib.h ExportDataAsCode"
+  c'exportDataAsCode ::
+    Ptr CUChar -> CUInt -> CString -> IO CBool
+
+foreign import ccall safe "raylib.h LoadFileText"
+  c'loadFileText ::
+    CString -> IO CString
+
+foreign import ccall safe "raylib.h UnloadFileText"
+  c'unloadFileText ::
+    CString -> IO ()
+
+foreign import ccall safe "raylib.h SaveFileText"
+  c'saveFileText ::
+    CString -> CString -> IO CBool
+
+foreign import ccall safe "raylib.h FileExists"
+  c'fileExists ::
+    CString -> IO CBool
+
+foreign import ccall safe "raylib.h DirectoryExists"
+  c'directoryExists ::
+    CString -> IO CBool
+
+foreign import ccall safe "raylib.h IsFileExtension"
+  c'isFileExtension ::
+    CString -> CString -> IO CBool
+
+foreign import ccall safe "raylib.h GetFileLength"
+  c'getFileLength ::
+    CString -> IO CBool
+
+foreign import ccall safe "raylib.h GetFileExtension"
+  c'getFileExtension ::
+    CString -> IO CString
+
+foreign import ccall safe "raylib.h GetFileName"
+  c'getFileName ::
+    CString -> IO CString
+
+foreign import ccall safe "raylib.h GetFileNameWithoutExt"
+  c'getFileNameWithoutExt ::
+    CString -> IO CString
+
+foreign import ccall safe "raylib.h GetDirectoryPath"
+  c'getDirectoryPath ::
+    CString -> IO CString
+
+foreign import ccall safe "raylib.h GetPrevDirectoryPath"
+  c'getPrevDirectoryPath ::
+    CString -> IO CString
+
+foreign import ccall safe "raylib.h GetWorkingDirectory"
+  c'getWorkingDirectory ::
+    IO CString
+
+foreign import ccall safe "raylib.h GetApplicationDirectory"
+  c'getApplicationDirectory ::
+    IO CString
+
+foreign import ccall safe "raylib.h ChangeDirectory"
+  c'changeDirectory ::
+    CString -> IO CBool
+
+foreign import ccall safe "raylib.h IsPathFile"
+  c'isPathFile ::
+    CString -> IO CBool
+
+foreign import ccall safe "bindings.h LoadDirectoryFiles_" c'loadDirectoryFiles :: CString -> IO (Ptr Raylib.Types.FilePathList)
+
+foreign import ccall safe "bindings.h LoadDirectoryFilesEx_" c'loadDirectoryFilesEx :: CString -> CString -> CInt -> IO (Ptr Raylib.Types.FilePathList)
+
+foreign import ccall safe "bindings.h UnloadDirectoryFiles_" c'unloadDirectoryFiles :: Ptr Raylib.Types.FilePathList -> IO ()
+
+foreign import ccall safe "raylib.h IsFileDropped"
+  c'isFileDropped ::
+    IO CBool
+
+foreign import ccall safe "bindings.h LoadDroppedFiles_" c'loadDroppedFiles :: IO (Ptr Raylib.Types.FilePathList)
+
+foreign import ccall safe "bindings.h UnloadDroppedFiles_" c'unloadDroppedFiles :: Ptr Raylib.Types.FilePathList -> IO ()
+
+foreign import ccall safe "raylib.h GetFileModTime"
+  c'getFileModTime ::
+    CString -> IO CLong
+
+foreign import ccall safe "raylib.h CompressData"
+  c'compressData ::
+    Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr CUChar)
+
+foreign import ccall safe "raylib.h DecompressData"
+  c'decompressData ::
+    Ptr CUChar -> CInt -> Ptr CInt -> IO (Ptr CUChar)
+
+foreign import ccall safe "raylib.h EncodeDataBase64"
+  c'encodeDataBase64 ::
+    Ptr CUChar -> CInt -> Ptr CInt -> IO CString
+
+foreign import ccall safe "raylib.h DecodeDataBase64"
+  c'decodeDataBase64 ::
+    Ptr CUChar -> Ptr CInt -> IO (Ptr CUChar)
+
+foreign import ccall safe "raylib.h IsKeyPressed"
+  c'isKeyPressed ::
+    CInt -> IO CBool
+
+foreign import ccall safe "raylib.h IsKeyDown"
+  c'isKeyDown ::
+    CInt -> IO CBool
+
+foreign import ccall safe "raylib.h IsKeyReleased"
+  c'isKeyReleased ::
+    CInt -> IO CBool
+
+foreign import ccall safe "raylib.h IsKeyUp"
+  c'isKeyUp ::
+    CInt -> IO CBool
+
+foreign import ccall safe "raylib.h SetExitKey"
+  c'setExitKey ::
+    CInt -> IO ()
+
+foreign import ccall safe "raylib.h GetKeyPressed"
+  c'getKeyPressed ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetCharPressed"
+  c'getCharPressed ::
+    IO CInt
+
+foreign import ccall safe "raylib.h IsGamepadAvailable"
+  c'isGamepadAvailable ::
+    CInt -> IO CBool
+
+foreign import ccall safe "raylib.h GetGamepadName"
+  c'getGamepadName ::
+    CInt -> IO CString
+
+foreign import ccall safe "raylib.h IsGamepadButtonPressed"
+  c'isGamepadButtonPressed ::
+    CInt -> CInt -> IO CBool
+
+foreign import ccall safe "raylib.h IsGamepadButtonDown"
+  c'isGamepadButtonDown ::
+    CInt -> CInt -> IO CBool
+
+foreign import ccall safe "raylib.h IsGamepadButtonReleased"
+  c'isGamepadButtonReleased ::
+    CInt -> CInt -> IO CBool
+
+foreign import ccall safe "raylib.h IsGamepadButtonUp"
+  c'isGamepadButtonUp ::
+    CInt -> CInt -> IO CBool
+
+foreign import ccall safe "raylib.h GetGamepadButtonPressed"
+  c'getGamepadButtonPressed ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetGamepadAxisCount"
+  c'getGamepadAxisCount ::
+    CInt -> IO CInt
+
+foreign import ccall safe "raylib.h GetGamepadAxisMovement"
+  c'getGamepadAxisMovement ::
+    CInt -> CInt -> IO CFloat
+
+foreign import ccall safe "raylib.h SetGamepadMappings"
+  c'setGamepadMappings ::
+    CString -> IO CInt
+
+foreign import ccall safe "raylib.h IsMouseButtonPressed"
+  c'isMouseButtonPressed ::
+    CInt -> IO CBool
+
+foreign import ccall safe "raylib.h IsMouseButtonDown"
+  c'isMouseButtonDown ::
+    CInt -> IO CBool
+
+foreign import ccall safe "raylib.h IsMouseButtonReleased"
+  c'isMouseButtonReleased ::
+    CInt -> IO CBool
+
+foreign import ccall safe "raylib.h IsMouseButtonUp"
+  c'isMouseButtonUp ::
+    CInt -> IO CBool
+
+foreign import ccall safe "raylib.h GetMouseX"
+  c'getMouseX ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetMouseY"
+  c'getMouseY ::
+    IO CInt
+
+foreign import ccall safe "bindings.h GetMousePosition_" c'getMousePosition :: IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "bindings.h GetMouseDelta_" c'getMouseDelta :: IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "raylib.h SetMousePosition"
+  c'setMousePosition ::
+    CInt -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h SetMouseOffset"
+  c'setMouseOffset ::
+    CInt -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h SetMouseScale"
+  c'setMouseScale ::
+    CFloat -> CFloat -> IO ()
+
+foreign import ccall safe "raylib.h GetMouseWheelMove"
+  c'getMouseWheelMove ::
+    IO CFloat
+
+foreign import ccall safe "bindings.h GetMouseWheelMoveV_" c'getMouseWheelMoveV :: IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "raylib.h SetMouseCursor"
+  c'setMouseCursor ::
+    CInt -> IO ()
+
+foreign import ccall safe "raylib.h GetTouchX"
+  c'getTouchX ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetTouchY"
+  c'getTouchY ::
+    IO CInt
+
+foreign import ccall safe "bindings.h GetTouchPosition_" c'getTouchPosition :: CInt -> IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "raylib.h GetTouchPointId"
+  c'getTouchPointId ::
+    CInt -> IO CInt
+
+foreign import ccall safe "raylib.h GetTouchPointCount"
+  c'getTouchPointCount ::
+    IO CInt
+
+foreign import ccall safe "raylib.h SetGesturesEnabled"
+  c'setGesturesEnabled ::
+    CUInt -> IO ()
+
+foreign import ccall safe "raylib.h IsGestureDetected"
+  c'isGestureDetected ::
+    CInt -> IO CBool
+
+foreign import ccall safe "raylib.h GetGestureDetected"
+  c'getGestureDetected ::
+    IO CInt
+
+foreign import ccall safe "raylib.h GetGestureHoldDuration"
+  c'getGestureHoldDuration ::
+    IO CFloat
+
+foreign import ccall safe "bindings.h GetGestureDragVector_" c'getGestureDragVector :: IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "raylib.h GetGestureDragAngle"
+  c'getGestureDragAngle ::
+    IO CFloat
+
+foreign import ccall safe "bindings.h GetGesturePinchVector_" c'getGesturePinchVector :: IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "raylib.h GetGesturePinchAngle"
+  c'getGesturePinchAngle ::
+    IO CFloat
+
+foreign import ccall safe "bindings.h SetCameraMode_" c'setCameraMode :: Ptr Raylib.Types.Camera3D -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h UpdateCamera"
+  c'updateCamera ::
+    Ptr Raylib.Types.Camera3D -> IO ()
+
+foreign import ccall safe "raylib.h SetCameraPanControl"
+  c'setCameraPanControl ::
+    CInt -> IO ()
+
+foreign import ccall safe "raylib.h SetCameraAltControl"
+  c'setCameraAltControl ::
+    CInt -> IO ()
+
+foreign import ccall safe "raylib.h SetCameraSmoothZoomControl"
+  c'setCameraSmoothZoomControl ::
+    CInt -> IO ()
+
+foreign import ccall safe "raylib.h SetCameraMoveControls"
+  c'setCameraMoveControls ::
+    CInt -> CInt -> CInt -> CInt -> CInt -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h SetShapesTexture_" c'setShapesTexture :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> IO ()
+
+foreign import ccall safe "bindings.h DrawPixel_" c'drawPixel :: CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawPixelV_" c'drawPixelV :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawLine_" c'drawLine :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawLineV_" c'drawLineV :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawLineEx_" c'drawLineEx :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawLineBezier_" c'drawLineBezier :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawLineBezierQuad_" c'drawLineBezierQuad :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawLineBezierCubic_" c'drawLineBezierCubic :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawLineStrip_" c'drawLineStrip :: Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCircle_" c'drawCircle :: CInt -> CInt -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCircleSector_" c'drawCircleSector :: Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCircleSectorLines_" c'drawCircleSectorLines :: Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCircleGradient_" c'drawCircleGradient :: CInt -> CInt -> CFloat -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCircleV_" c'drawCircleV :: Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCircleLines_" c'drawCircleLines :: CInt -> CInt -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawEllipse_" c'drawEllipse :: CInt -> CInt -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawEllipseLines_" c'drawEllipseLines :: CInt -> CInt -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRing_" c'drawRing :: Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRingLines_" c'drawRingLines :: Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectangle_" c'drawRectangle :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectangleV_" c'drawRectangleV :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectangleRec_" c'drawRectangleRec :: Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectanglePro_" c'drawRectanglePro :: Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectangleGradientV_" c'drawRectangleGradientV :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectangleGradientH_" c'drawRectangleGradientH :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectangleGradientEx_" c'drawRectangleGradientEx :: Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectangleLines_" c'drawRectangleLines :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectangleLinesEx_" c'drawRectangleLinesEx :: Ptr Raylib.Types.Rectangle -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectangleRounded_" c'drawRectangleRounded :: Ptr Raylib.Types.Rectangle -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRectangleRoundedLines_" c'drawRectangleRoundedLines :: Ptr Raylib.Types.Rectangle -> CFloat -> CInt -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTriangle_" c'drawTriangle :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTriangleLines_" c'drawTriangleLines :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTriangleFan_" c'drawTriangleFan :: Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTriangleStrip_" c'drawTriangleStrip :: Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawPoly_" c'drawPoly :: Ptr Raylib.Types.Vector2 -> CInt -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawPolyLines_" c'drawPolyLines :: Ptr Raylib.Types.Vector2 -> CInt -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawPolyLinesEx_" c'drawPolyLinesEx :: Ptr Raylib.Types.Vector2 -> CInt -> CFloat -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h CheckCollisionRecs_" c'checkCollisionRecs :: Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Rectangle -> IO CBool
+
+foreign import ccall safe "bindings.h CheckCollisionCircles_" c'checkCollisionCircles :: Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Vector2 -> CFloat -> IO CBool
+
+foreign import ccall safe "bindings.h CheckCollisionCircleRec_" c'checkCollisionCircleRec :: Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Rectangle -> IO CBool
+
+foreign import ccall safe "bindings.h CheckCollisionPointRec_" c'checkCollisionPointRec :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Rectangle -> IO CBool
+
+foreign import ccall safe "bindings.h CheckCollisionPointCircle_" c'checkCollisionPointCircle :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> IO CBool
+
+foreign import ccall safe "bindings.h CheckCollisionPointTriangle_" c'checkCollisionPointTriangle :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> IO CBool
+
+foreign import ccall safe "bindings.h CheckCollisionLines_" c'checkCollisionLines :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> IO CBool
+
+foreign import ccall safe "bindings.h CheckCollisionPointLine_" c'checkCollisionPointLine :: Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CInt -> IO CBool
+
+foreign import ccall safe "bindings.h GetCollisionRec_" c'getCollisionRec :: Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Rectangle -> IO (Ptr Raylib.Types.Rectangle)
+
+foreign import ccall safe "bindings.h LoadImage_" c'loadImage :: CString -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h LoadImageRaw_" c'loadImageRaw :: CString -> CInt -> CInt -> CInt -> CInt -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h LoadImageAnim_" c'loadImageAnim :: CString -> Ptr CInt -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h LoadImageFromMemory_" c'loadImageFromMemory :: CString -> Ptr CUChar -> CInt -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h LoadImageFromTexture_" c'loadImageFromTexture :: Ptr Raylib.Types.Texture -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h LoadImageFromScreen_" c'loadImageFromScreen :: IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h IsImageReady_" c'isImageReady :: Ptr Image -> IO CBool
+
+foreign import ccall safe "bindings.h UnloadImage_" c'unloadImage :: Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "bindings.h ExportImage_" c'exportImage :: Ptr Raylib.Types.Image -> CString -> IO CBool
+
+foreign import ccall safe "bindings.h ExportImageAsCode_" c'exportImageAsCode :: Ptr Raylib.Types.Image -> CString -> IO CBool
+
+foreign import ccall safe "bindings.h GenImageColor_" c'genImageColor :: CInt -> CInt -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h GenImageGradientV_" c'genImageGradientV :: CInt -> CInt -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h GenImageGradientH_" c'genImageGradientH :: CInt -> CInt -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h GenImageGradientRadial_" c'genImageGradientRadial :: CInt -> CInt -> CFloat -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h GenImageChecked_" c'genImageChecked :: CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h GenImageWhiteNoise_" c'genImageWhiteNoise :: CInt -> CInt -> CFloat -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h GenImagePerlinNoise_" c'genImagePerlinNoise :: CInt -> CInt -> CInt -> CInt -> CFloat -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h GenImageCellular_" c'genImageCellular :: CInt -> CInt -> CInt -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h GenImageText_" c'genImageText :: CInt -> CInt -> CString -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h ImageCopy_" c'imageCopy :: Ptr Raylib.Types.Image -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h ImageFromImage_" c'imageFromImage :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Rectangle -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h ImageText_" c'imageText :: CString -> CInt -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "bindings.h ImageTextEx_" c'imageTextEx :: Ptr Raylib.Types.Font -> CString -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "raylib.h ImageFormat"
+  c'imageFormat ::
+    Ptr Raylib.Types.Image -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h ImageToPOT_" c'imageToPOT :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageCrop_" c'imageCrop :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Rectangle -> IO ()
+
+foreign import ccall safe "raylib.h ImageAlphaCrop"
+  c'imageAlphaCrop ::
+    Ptr Raylib.Types.Image -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h ImageAlphaClear_" c'imageAlphaClear :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h ImageAlphaMask_" c'imageAlphaMask :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "raylib.h ImageAlphaPremultiply"
+  c'imageAlphaPremultiply ::
+    Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "raylib.h ImageBlurGaussian"
+  c'imageBlurGaussian ::
+    Ptr Raylib.Types.Image -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h ImageResize"
+  c'imageResize ::
+    Ptr Raylib.Types.Image -> CInt -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h ImageResizeNN"
+  c'imageResizeNN ::
+    Ptr Raylib.Types.Image -> CInt -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h ImageResizeCanvas_" c'imageResizeCanvas :: Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "raylib.h ImageMipmaps"
+  c'imageMipmaps ::
+    Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "raylib.h ImageDither"
+  c'imageDither ::
+    Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h ImageFlipVertical"
+  c'imageFlipVertical ::
+    Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "raylib.h ImageFlipHorizontal"
+  c'imageFlipHorizontal ::
+    Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "raylib.h ImageRotateCW"
+  c'imageRotateCW ::
+    Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "raylib.h ImageRotateCCW"
+  c'imageRotateCCW ::
+    Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "bindings.h ImageColorTint_" c'imageColorTint :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "raylib.h ImageColorInvert"
+  c'imageColorInvert ::
+    Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "raylib.h ImageColorGrayscale"
+  c'imageColorGrayscale ::
+    Ptr Raylib.Types.Image -> IO ()
+
+foreign import ccall safe "raylib.h ImageColorContrast"
+  c'imageColorContrast ::
+    Ptr Raylib.Types.Image -> CFloat -> IO ()
+
+foreign import ccall safe "raylib.h ImageColorBrightness"
+  c'imageColorBrightness ::
+    Ptr Raylib.Types.Image -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h ImageColorReplace_" c'imageColorReplace :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h LoadImageColors_" c'loadImageColors :: Ptr Raylib.Types.Image -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h LoadImagePalette_" c'loadImagePalette :: Ptr Raylib.Types.Image -> CInt -> Ptr CInt -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h GetImageAlphaBorder_" c'getImageAlphaBorder :: Ptr Raylib.Types.Image -> CFloat -> IO (Ptr Raylib.Types.Rectangle)
+
+foreign import ccall safe "bindings.h GetImageColor_" c'getImageColor :: Ptr Raylib.Types.Image -> CInt -> CInt -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h ImageClearBackground_" c'imageClearBackground :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawPixel_" c'imageDrawPixel :: Ptr Raylib.Types.Image -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawPixelV_" c'imageDrawPixelV :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawLine_" c'imageDrawLine :: Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawLineV_" c'imageDrawLineV :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawCircle_" c'imageDrawCircle :: Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawCircleV_" c'imageDrawCircleV :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawCircleLines_" c'imageDrawCircleLines :: Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawCircleLinesV_" c'imageDrawCircleLinesV :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawRectangle_" c'imageDrawRectangle :: Ptr Raylib.Types.Image -> CInt -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawRectangleV_" c'imageDrawRectangleV :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawRectangleRec_" c'imageDrawRectangleRec :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawRectangleLines_" c'imageDrawRectangleLines :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Rectangle -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDraw_" c'imageDraw :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Image -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawText_" c'imageDrawText :: Ptr Raylib.Types.Image -> CString -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h ImageDrawTextEx_" c'imageDrawTextEx :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Font -> CString -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h LoadTexture_" c'loadTexture :: CString -> IO (Ptr Raylib.Types.Texture)
+
+foreign import ccall safe "bindings.h LoadTextureFromImage_" c'loadTextureFromImage :: Ptr Raylib.Types.Image -> IO (Ptr Raylib.Types.Texture)
+
+foreign import ccall safe "bindings.h LoadTextureCubemap_" c'loadTextureCubemap :: Ptr Raylib.Types.Image -> CInt -> IO (Ptr Raylib.Types.Texture)
+
+foreign import ccall safe "bindings.h LoadRenderTexture_" c'loadRenderTexture :: CInt -> CInt -> IO (Ptr Raylib.Types.RenderTexture)
+
+foreign import ccall safe "bindings.h IsTextureReady_" c'isTextureReady :: Ptr Texture -> IO CBool
+
+foreign import ccall safe "bindings.h UnloadTexture_" c'unloadTexture :: Ptr Raylib.Types.Texture -> IO ()
+
+foreign import ccall safe "bindings.h IsRenderTextureReady_" c'isRenderTextureReady :: Ptr RenderTexture -> IO CBool
+
+foreign import ccall safe "bindings.h UnloadRenderTexture_" c'unloadRenderTexture :: Ptr Raylib.Types.RenderTexture -> IO ()
+
+foreign import ccall safe "bindings.h UpdateTexture_" c'updateTexture :: Ptr Raylib.Types.Texture -> Ptr () -> IO ()
+
+foreign import ccall safe "bindings.h UpdateTextureRec_" c'updateTextureRec :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr () -> IO ()
+
+foreign import ccall safe "raylib.h GenTextureMipmaps"
+  c'genTextureMipmaps ::
+    Ptr Raylib.Types.Texture -> IO ()
+
+foreign import ccall safe "bindings.h SetTextureFilter_" c'setTextureFilter :: Ptr Raylib.Types.Texture -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h SetTextureWrap_" c'setTextureWrap :: Ptr Raylib.Types.Texture -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h DrawTexture_" c'drawTexture :: Ptr Raylib.Types.Texture -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTextureV_" c'drawTextureV :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTextureEx_" c'drawTextureEx :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTextureRec_" c'drawTextureRec :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTexturePro_" c'drawTexturePro :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTextureNPatch_" c'drawTextureNPatch :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.NPatchInfo -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h Fade_" c'fade :: Ptr Raylib.Types.Color -> CFloat -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h ColorToInt_" c'colorToInt :: Ptr Raylib.Types.Color -> IO CInt
+
+foreign import ccall safe "bindings.h ColorNormalize_" c'colorNormalize :: Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Vector4)
+
+foreign import ccall safe "bindings.h ColorFromNormalized_" c'colorFromNormalized :: Ptr Raylib.Types.Vector4 -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h ColorToHSV_" c'colorToHSV :: Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Vector3)
+
+foreign import ccall safe "bindings.h ColorFromHSV_" c'colorFromHSV :: CFloat -> CFloat -> CFloat -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h ColorTint_" c'colorTint :: Ptr Color -> Ptr Color -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h ColorBrightness_" c'colorBrightness :: Ptr Color -> CFloat -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h ColorContrast_" c'colorContrast :: Ptr Color -> CFloat -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h ColorAlpha_" c'colorAlpha :: Ptr Raylib.Types.Color -> CFloat -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h ColorAlphaBlend_" c'colorAlphaBlend :: Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> Ptr Raylib.Types.Color -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h GetColor_" c'getColor :: CUInt -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h GetPixelColor_" c'getPixelColor :: Ptr () -> CInt -> IO (Ptr Raylib.Types.Color)
+
+foreign import ccall safe "bindings.h SetPixelColor_" c'setPixelColor :: Ptr () -> Ptr Raylib.Types.Color -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h GetFontDefault_" c'getFontDefault :: IO (Ptr Raylib.Types.Font)
+
+foreign import ccall safe "bindings.h LoadFont_" c'loadFont :: CString -> IO (Ptr Raylib.Types.Font)
+
+foreign import ccall safe "bindings.h LoadFontEx_" c'loadFontEx :: CString -> CInt -> Ptr CInt -> CInt -> IO (Ptr Raylib.Types.Font)
+
+foreign import ccall safe "bindings.h LoadFontFromImage_" c'loadFontFromImage :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Color -> CInt -> IO (Ptr Raylib.Types.Font)
+
+foreign import ccall safe "bindings.h LoadFontFromMemory_" c'loadFontFromMemory :: CString -> Ptr CUChar -> CInt -> CInt -> Ptr CInt -> CInt -> IO (Ptr Raylib.Types.Font)
+
+foreign import ccall safe "raylib.h LoadFontData"
+  c'loadFontData ::
+    Ptr CUChar -> CInt -> CInt -> Ptr CInt -> CInt -> CInt -> IO (Ptr Raylib.Types.GlyphInfo)
+
+foreign import ccall safe "bindings.h GenImageFontAtlas_" c'genImageFontAtlas :: Ptr Raylib.Types.GlyphInfo -> Ptr (Ptr Raylib.Types.Rectangle) -> CInt -> CInt -> CInt -> CInt -> IO (Ptr Raylib.Types.Image)
+
+foreign import ccall safe "raylib.h UnloadFontData"
+  c'unloadFontData ::
+    Ptr Raylib.Types.GlyphInfo -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h IsFontReady_" c'isFontReady :: Ptr Raylib.Types.Font -> IO CBool
+
+foreign import ccall safe "bindings.h UnloadFont_" c'unloadFont :: Ptr Raylib.Types.Font -> IO ()
+
+foreign import ccall safe "bindings.h ExportFontAsCode_" c'exportFontAsCode :: Ptr Raylib.Types.Font -> CString -> IO CBool
+
+foreign import ccall safe "raylib.h DrawFPS"
+  c'drawFPS ::
+    CInt -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h DrawText_" c'drawText :: CString -> CInt -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTextEx_" c'drawTextEx :: Ptr Raylib.Types.Font -> CString -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTextPro_" c'drawTextPro :: Ptr Raylib.Types.Font -> CString -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTextCodepoint_" c'drawTextCodepoint :: Ptr Raylib.Types.Font -> CInt -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTextCodepoints_" c'drawTextCodepoints :: Ptr Raylib.Types.Font -> Ptr CInt -> CInt -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "raylib.h MeasureText"
+  c'measureText ::
+    CString -> CInt -> IO CInt
+
+foreign import ccall safe "bindings.h MeasureTextEx_" c'measureTextEx :: Ptr Raylib.Types.Font -> CString -> CFloat -> CFloat -> IO (Ptr Raylib.Types.Vector2)
+
+foreign import ccall safe "bindings.h GetGlyphIndex_" c'getGlyphIndex :: Ptr Raylib.Types.Font -> CInt -> IO CInt
+
+foreign import ccall safe "bindings.h GetGlyphInfo_" c'getGlyphInfo :: Ptr Raylib.Types.Font -> CInt -> IO (Ptr Raylib.Types.GlyphInfo)
+
+foreign import ccall safe "bindings.h GetGlyphAtlasRec_" c'getGlyphAtlasRec :: Ptr Raylib.Types.Font -> CInt -> IO (Ptr Raylib.Types.Rectangle)
+
+foreign import ccall safe "raylib.h LoadUTF8"
+  c'loadUTF8 ::
+    Ptr CInt -> CInt -> IO CString
+
+foreign import ccall safe "raylib.h LoadCodepoints"
+  c'loadCodepoints ::
+    CString -> Ptr CInt -> IO (Ptr CInt)
+
+foreign import ccall safe "raylib.h GetCodepointCount"
+  c'getCodepointCount ::
+    CString -> IO CInt
+
+-- | Deprecated, use `getCodepointNext`
+-- foreign import ccall safe "raylib.h GetCodepoint"
+--   getCodepoint ::
+--     CString -> Ptr CInt -> IO CInt
+foreign import ccall safe "raylib.h GetCodepointNext"
+  c'getCodepointNext ::
+    CString -> Ptr CInt -> IO CInt
+
+foreign import ccall safe "raylib.h GetCodepointPrevious"
+  c'getCodepointPrevious ::
+    CString -> Ptr CInt -> IO CInt
+
+foreign import ccall safe "raylib.h CodepointToUTF8"
+  c'codepointToUTF8 ::
+    CInt -> Ptr CInt -> IO CString
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextCopy"
+--   textCopy ::
+--     CString -> CString -> IO CInt
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextIsEqual"
+--   textIsEqual ::
+--     CString -> CString -> IO CInt
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextLength"
+--   textLength ::
+--     CString -> IO CUInt
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextFormat"
+--   textFormat ::
+--     CString -> IO CString
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextSubtext"
+--   textSubtext ::
+--     CString -> CInt -> CInt -> IO CString
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextReplace"
+--   textReplace ::
+--     CString -> CString -> CString -> IO CString
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextInsert"
+--   textInsert ::
+--     CString -> CString -> CInt -> IO CString
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextJoin"
+--   textJoin ::
+--     Ptr CString -> CInt -> CString -> IO CString
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextSplit"
+--   textSplit ::
+--     CString -> CChar -> Ptr CInt -> IO (Ptr CString)
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextAppend"
+--   textAppend ::
+--     CString -> CString -> Ptr CInt -> IO ()
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextFindIndex"
+--   textFindIndex ::
+--     CString -> CString -> IO CInt
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextToUpper"
+--   textToUpper ::
+--     CString -> IO CString
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextToLower"
+--   textToLower ::
+--     CString -> IO CString
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextToPascal"
+--   textToPascal ::
+--     CString -> IO CString
+
+-- | Not required in Haskell
+-- foreign import ccall safe "raylib.h TextToInteger"
+--   textToInteger ::
+--     CString -> IO CInt
+foreign import ccall safe "bindings.h DrawLine3D_" c'drawLine3D :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawPoint3D_" c'drawPoint3D :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCircle3D_" c'drawCircle3D :: Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTriangle3D_" c'drawTriangle3D :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawTriangleStrip3D_" c'drawTriangleStrip3D :: Ptr Raylib.Types.Vector3 -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCube_" c'drawCube :: Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCubeV_" c'drawCubeV :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCubeWires_" c'drawCubeWires :: Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCubeWiresV_" c'drawCubeWiresV :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawSphere_" c'drawSphere :: Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawSphereEx_" c'drawSphereEx :: Ptr Raylib.Types.Vector3 -> CFloat -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawSphereWires_" c'drawSphereWires :: Ptr Raylib.Types.Vector3 -> CFloat -> CInt -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCylinder_" c'drawCylinder :: Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCylinderEx_" c'drawCylinderEx :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCylinderWires_" c'drawCylinderWires :: Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCylinderWiresEx_" c'drawCylinderWiresEx :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> CFloat -> CFloat -> CInt -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCapsule_" c'drawCapsule :: Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawCapsuleWires_" c'drawCapsuleWires :: Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawPlane_" c'drawPlane :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawRay_" c'drawRay :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "raylib.h DrawGrid"
+  c'drawGrid ::
+    CInt -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h LoadModel_" c'loadModel :: CString -> IO (Ptr Raylib.Types.Model)
+
+foreign import ccall safe "bindings.h LoadModelFromMesh_" c'loadModelFromMesh :: Ptr Raylib.Types.Mesh -> IO (Ptr Raylib.Types.Model)
+
+foreign import ccall safe "bindings.h IsModelReady_" c'isModelReady :: Ptr Raylib.Types.Model -> IO CBool
+
+foreign import ccall safe "bindings.h UnloadModel_" c'unloadModel :: Ptr Raylib.Types.Model -> IO ()
+
+foreign import ccall safe "bindings.h UnloadModelKeepMeshes_" c'unloadModelKeepMeshes :: Ptr Raylib.Types.Model -> IO ()
+
+foreign import ccall safe "bindings.h GetModelBoundingBox_" c'getModelBoundingBox :: Ptr Raylib.Types.Model -> IO (Ptr Raylib.Types.BoundingBox)
+
+foreign import ccall safe "bindings.h DrawModel_" c'drawModel :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawModelEx_" c'drawModelEx :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawModelWires_" c'drawModelWires :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawModelWiresEx_" c'drawModelWiresEx :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawBoundingBox_" c'drawBoundingBox :: Ptr Raylib.Types.BoundingBox -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawBillboard_" c'drawBillboard :: Ptr Raylib.Types.Camera3D -> Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawBillboardRec_" c'drawBillboardRec :: Ptr Raylib.Types.Camera3D -> Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "bindings.h DrawBillboardPro_" c'drawBillboardPro :: Ptr Raylib.Types.Camera3D -> Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "raylib.h UploadMesh"
+  c'uploadMesh ::
+    Ptr Raylib.Types.Mesh -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h UpdateMeshBuffer_" c'updateMeshBuffer :: Ptr Raylib.Types.Mesh -> CInt -> Ptr () -> CInt -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h UnloadMesh_" c'unloadMesh :: Ptr Raylib.Types.Mesh -> IO ()
+
+foreign import ccall safe "bindings.h DrawMesh_" c'drawMesh :: Ptr Raylib.Types.Mesh -> Ptr Raylib.Types.Material -> Ptr Raylib.Types.Matrix -> IO ()
+
+foreign import ccall safe "bindings.h DrawMeshInstanced_" c'drawMeshInstanced :: Ptr Raylib.Types.Mesh -> Ptr Raylib.Types.Material -> Ptr Raylib.Types.Matrix -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h ExportMesh_" c'exportMesh :: Ptr Raylib.Types.Mesh -> CString -> IO CBool
+
+foreign import ccall safe "bindings.h GetMeshBoundingBox_" c'getMeshBoundingBox :: Ptr Raylib.Types.Mesh -> IO (Ptr Raylib.Types.BoundingBox)
+
+foreign import ccall safe "raylib.h GenMeshTangents"
+  c'genMeshTangents ::
+    Ptr Raylib.Types.Mesh -> IO ()
+
+foreign import ccall safe "bindings.h GenMeshPoly_" c'genMeshPoly :: CInt -> CFloat -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "bindings.h GenMeshPlane_" c'genMeshPlane :: CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "bindings.h GenMeshCube_" c'genMeshCube :: CFloat -> CFloat -> CFloat -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "bindings.h GenMeshSphere_" c'genMeshSphere :: CFloat -> CInt -> CInt -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "bindings.h GenMeshHemiSphere_" c'genMeshHemiSphere :: CFloat -> CInt -> CInt -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "bindings.h GenMeshCylinder_" c'genMeshCylinder :: CFloat -> CFloat -> CInt -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "bindings.h GenMeshCone_" c'genMeshCone :: CFloat -> CFloat -> CInt -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "bindings.h GenMeshTorus_" c'genMeshTorus :: CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "bindings.h GenMeshKnot_" c'genMeshKnot :: CFloat -> CFloat -> CInt -> CInt -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "bindings.h GenMeshHeightmap_" c'genMeshHeightmap :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector3 -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "bindings.h GenMeshCubicmap_" c'genMeshCubicmap :: Ptr Raylib.Types.Image -> Ptr Raylib.Types.Vector3 -> IO (Ptr Raylib.Types.Mesh)
+
+foreign import ccall safe "raylib.h LoadMaterials"
+  c'loadMaterials ::
+    CString -> Ptr CInt -> IO (Ptr Raylib.Types.Material)
+
+foreign import ccall safe "bindings.h LoadMaterialDefault_" c'loadMaterialDefault :: IO (Ptr Raylib.Types.Material)
+
+foreign import ccall safe "bindings.h IsMaterialReady_" c'isMaterialReady :: Ptr Raylib.Types.Material -> IO CBool
+
+foreign import ccall safe "bindings.h UnloadMaterial_" c'unloadMaterial :: Ptr Raylib.Types.Material -> IO ()
+
+foreign import ccall safe "bindings.h SetMaterialTexture_" c'setMaterialTexture :: Ptr Raylib.Types.Material -> CInt -> Ptr Raylib.Types.Texture -> IO ()
+
+foreign import ccall safe "raylib.h SetModelMeshMaterial"
+  c'setModelMeshMaterial ::
+    Ptr Raylib.Types.Model -> CInt -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h LoadModelAnimations"
+  c'loadModelAnimations ::
+    CString -> Ptr CUInt -> IO (Ptr Raylib.Types.ModelAnimation)
+
+foreign import ccall safe "bindings.h UpdateModelAnimation_" c'updateModelAnimation :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.ModelAnimation -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h UnloadModelAnimation_" c'unloadModelAnimation :: Ptr Raylib.Types.ModelAnimation -> IO ()
+
+foreign import ccall safe "raylib.h UnloadModelAnimations"
+  c'unloadModelAnimations ::
+    Ptr Raylib.Types.ModelAnimation -> CUInt -> IO ()
+
+foreign import ccall safe "bindings.h IsModelAnimationValid_" c'isModelAnimationValid :: Ptr Raylib.Types.Model -> Ptr Raylib.Types.ModelAnimation -> IO CBool
+
+foreign import ccall safe "bindings.h CheckCollisionSpheres_" c'checkCollisionSpheres :: Ptr Raylib.Types.Vector3 -> CFloat -> Ptr Raylib.Types.Vector3 -> CFloat -> IO CBool
+
+foreign import ccall safe "bindings.h CheckCollisionBoxes_" c'checkCollisionBoxes :: Ptr Raylib.Types.BoundingBox -> Ptr Raylib.Types.BoundingBox -> IO CBool
+
+foreign import ccall safe "bindings.h CheckCollisionBoxSphere_" c'checkCollisionBoxSphere :: Ptr Raylib.Types.BoundingBox -> Ptr Raylib.Types.Vector3 -> CFloat -> IO CBool
+
+foreign import ccall safe "bindings.h GetRayCollisionSphere_" c'getRayCollisionSphere :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.Vector3 -> CFloat -> IO (Ptr Raylib.Types.RayCollision)
+
+foreign import ccall safe "bindings.h GetRayCollisionBox_" c'getRayCollisionBox :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.BoundingBox -> IO (Ptr Raylib.Types.RayCollision)
+
+foreign import ccall safe "bindings.h GetRayCollisionMesh_" c'getRayCollisionMesh :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.Mesh -> Ptr Raylib.Types.Matrix -> IO (Ptr Raylib.Types.RayCollision)
+
+foreign import ccall safe "bindings.h GetRayCollisionTriangle_" c'getRayCollisionTriangle :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> IO (Ptr Raylib.Types.RayCollision)
+
+foreign import ccall safe "bindings.h GetRayCollisionQuad_" c'getRayCollisionQuad :: Ptr Raylib.Types.Ray -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector3 -> IO (Ptr Raylib.Types.RayCollision)
+
+-- TODO: redesign this
+foreign import ccall safe "wrapper"
+  mk'audioCallback ::
+    (Ptr () -> CUInt -> IO ()) -> IO AudioCallback
+
+foreign import ccall safe "dynamic"
+  mK'audioCallback ::
+    AudioCallback -> (Ptr () -> CUInt -> IO ())
+
+foreign import ccall safe "raylib.h IsAudioDeviceReady"
+  c'isAudioDeviceReady ::
+    IO CBool
+
+foreign import ccall safe "raylib.h SetMasterVolume"
+  c'setMasterVolume ::
+    CFloat -> IO ()
+
+foreign import ccall safe "bindings.h LoadWave_" c'loadWave :: CString -> IO (Ptr Raylib.Types.Wave)
+
+foreign import ccall safe "bindings.h LoadWaveFromMemory_" c'loadWaveFromMemory :: CString -> Ptr CUChar -> CInt -> IO (Ptr Raylib.Types.Wave)
+
+foreign import ccall safe "bindings.h LoadSound_" c'loadSound :: CString -> IO (Ptr Raylib.Types.Sound)
+
+foreign import ccall safe "bindings.h LoadSoundFromWave_" c'loadSoundFromWave :: Ptr Raylib.Types.Wave -> IO (Ptr Raylib.Types.Sound)
+
+foreign import ccall safe "bindings.h UpdateSound_" c'updateSound :: Ptr Raylib.Types.Sound -> Ptr () -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h IsWaveReady_" c'isWaveReady :: Ptr Raylib.Types.Wave -> IO CBool
+
+foreign import ccall safe "bindings.h UnloadWave_" c'unloadWave :: Ptr Raylib.Types.Wave -> IO ()
+
+foreign import ccall safe "bindings.h IsSoundReady_" c'isSoundReady :: Ptr Raylib.Types.Sound -> IO CBool
+
+foreign import ccall safe "bindings.h UnloadSound_" c'unloadSound :: Ptr Raylib.Types.Sound -> IO ()
+
+foreign import ccall safe "bindings.h ExportWave_" c'exportWave :: Ptr Raylib.Types.Wave -> CString -> IO CBool
+
+foreign import ccall safe "bindings.h ExportWaveAsCode_" c'exportWaveAsCode :: Ptr Raylib.Types.Wave -> CString -> IO CBool
+
+foreign import ccall safe "bindings.h PlaySound_" c'playSound :: Ptr Raylib.Types.Sound -> IO ()
+
+foreign import ccall safe "bindings.h StopSound_" c'stopSound :: Ptr Raylib.Types.Sound -> IO ()
+
+foreign import ccall safe "bindings.h PauseSound_" c'pauseSound :: Ptr Raylib.Types.Sound -> IO ()
+
+foreign import ccall safe "bindings.h ResumeSound_" c'resumeSound :: Ptr Raylib.Types.Sound -> IO ()
+
+foreign import ccall safe "bindings.h PlaySoundMulti_" c'playSoundMulti :: Ptr Raylib.Types.Sound -> IO ()
+
+foreign import ccall safe "raylib.h GetSoundsPlaying"
+  c'getSoundsPlaying ::
+    IO CInt
+
+foreign import ccall safe "bindings.h IsSoundPlaying_" c'isSoundPlaying :: Ptr Raylib.Types.Sound -> IO CBool
+
+foreign import ccall safe "bindings.h SetSoundVolume_" c'setSoundVolume :: Ptr Raylib.Types.Sound -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h SetSoundPitch_" c'setSoundPitch :: Ptr Raylib.Types.Sound -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h SetSoundPan_" c'setSoundPan :: Ptr Raylib.Types.Sound -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h WaveCopy_" c'waveCopy :: Ptr Raylib.Types.Wave -> IO (Ptr Raylib.Types.Wave)
+
+foreign import ccall safe "raylib.h WaveCrop"
+  c'waveCrop ::
+    Ptr Raylib.Types.Wave -> CInt -> CInt -> IO ()
+
+foreign import ccall safe "raylib.h WaveFormat"
+  c'waveFormat ::
+    Ptr Raylib.Types.Wave -> CInt -> CInt -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h LoadWaveSamples_" c'loadWaveSamples :: Ptr Raylib.Types.Wave -> IO (Ptr CFloat)
+
+foreign import ccall safe "raylib.h UnloadWaveSamples"
+  c'unloadWaveSamples ::
+    Ptr CFloat -> IO ()
+
+foreign import ccall safe "bindings.h LoadMusicStream_" c'loadMusicStream :: CString -> IO (Ptr Raylib.Types.Music)
+
+foreign import ccall safe "bindings.h LoadMusicStreamFromMemory_" c'loadMusicStreamFromMemory :: CString -> Ptr CUChar -> CInt -> IO (Ptr Raylib.Types.Music)
+
+foreign import ccall safe "bindings.h IsMusicReady_" c'isMusicReady :: Ptr Raylib.Types.Music -> IO CBool
+
+foreign import ccall safe "bindings.h UnloadMusicStream_" c'unloadMusicStream :: Ptr Raylib.Types.Music -> IO ()
+
+foreign import ccall safe "bindings.h PlayMusicStream_" c'playMusicStream :: Ptr Raylib.Types.Music -> IO ()
+
+foreign import ccall safe "bindings.h IsMusicStreamPlaying_" c'isMusicStreamPlaying :: Ptr Raylib.Types.Music -> IO CBool
+
+foreign import ccall safe "bindings.h UpdateMusicStream_" c'updateMusicStream :: Ptr Raylib.Types.Music -> IO ()
+
+foreign import ccall safe "bindings.h StopMusicStream_" c'stopMusicStream :: Ptr Raylib.Types.Music -> IO ()
+
+foreign import ccall safe "bindings.h PauseMusicStream_" c'pauseMusicStream :: Ptr Raylib.Types.Music -> IO ()
+
+foreign import ccall safe "bindings.h ResumeMusicStream_" c'resumeMusicStream :: Ptr Raylib.Types.Music -> IO ()
+
+foreign import ccall safe "bindings.h SeekMusicStream_" c'seekMusicStream :: Ptr Raylib.Types.Music -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h SetMusicVolume_" c'setMusicVolume :: Ptr Raylib.Types.Music -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h SetMusicPitch_" c'setMusicPitch :: Ptr Raylib.Types.Music -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h SetMusicPan_" c'setMusicPan :: Ptr Raylib.Types.Music -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h GetMusicTimeLength_" c'getMusicTimeLength :: Ptr Raylib.Types.Music -> IO CFloat
+
+foreign import ccall safe "bindings.h GetMusicTimePlayed_" c'getMusicTimePlayed :: Ptr Raylib.Types.Music -> IO CFloat
+
+foreign import ccall safe "bindings.h LoadAudioStream_" c'loadAudioStream :: CUInt -> CUInt -> CUInt -> IO (Ptr Raylib.Types.AudioStream)
+
+foreign import ccall safe "bindings.h IsAudioStreamReady_" c'isAudioStreamReady :: Ptr Raylib.Types.AudioStream -> IO CBool
+
+foreign import ccall safe "bindings.h UnloadAudioStream_" c'unloadAudioStream :: Ptr Raylib.Types.AudioStream -> IO ()
+
+foreign import ccall safe "bindings.h UpdateAudioStream_" c'updateAudioStream :: Ptr Raylib.Types.AudioStream -> Ptr () -> CInt -> IO ()
+
+foreign import ccall safe "bindings.h IsAudioStreamProcessed_" c'isAudioStreamProcessed :: Ptr Raylib.Types.AudioStream -> IO CBool
+
+foreign import ccall safe "bindings.h PlayAudioStream_" c'playAudioStream :: Ptr Raylib.Types.AudioStream -> IO ()
+
+foreign import ccall safe "bindings.h PauseAudioStream_" c'pauseAudioStream :: Ptr Raylib.Types.AudioStream -> IO ()
+
+foreign import ccall safe "bindings.h ResumeAudioStream_" c'resumeAudioStream :: Ptr Raylib.Types.AudioStream -> IO ()
+
+foreign import ccall safe "bindings.h IsAudioStreamPlaying_" c'isAudioStreamPlaying :: Ptr Raylib.Types.AudioStream -> IO CBool
+
+foreign import ccall safe "bindings.h StopAudioStream_" c'stopAudioStream :: Ptr Raylib.Types.AudioStream -> IO ()
+
+foreign import ccall safe "bindings.h SetAudioStreamVolume_" c'setAudioStreamVolume :: Ptr Raylib.Types.AudioStream -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h SetAudioStreamPitch_" c'setAudioStreamPitch :: Ptr Raylib.Types.AudioStream -> CFloat -> IO ()
+
+foreign import ccall safe "bindings.h SetAudioStreamPan_" c'setAudioStreamPan :: Ptr Raylib.Types.AudioStream -> CFloat -> IO ()
+
+foreign import ccall safe "raylib.h SetAudioStreamBufferSizeDefault"
+  c'setAudioStreamBufferSizeDefault ::
+    CInt -> IO ()
+
+foreign import ccall safe "bindings.h SetAudioStreamCallback_" c'setAudioStreamCallback :: Ptr Raylib.Types.AudioStream -> Ptr AudioCallback -> IO ()
+
+foreign import ccall safe "bindings.h AttachAudioStreamProcessor_" c'attachAudioStreamProcessor :: Ptr Raylib.Types.AudioStream -> Ptr AudioCallback -> IO ()
+
+foreign import ccall safe "bindings.h DetachAudioStreamProcessor_" c'detachAudioStreamProcessor :: Ptr Raylib.Types.AudioStream -> Ptr AudioCallback -> IO ()
+ src/Raylib/Shapes.hs view
@@ -0,0 +1,354 @@+{-# OPTIONS -Wall #-}
+
+module Raylib.Shapes where
+
+import Data.List (genericLength)
+import Foreign (Storable (peek), toBool, withArray)
+import GHC.IO (unsafePerformIO)
+import Raylib.Native
+  ( c'checkCollisionCircleRec,
+    c'checkCollisionCircles,
+    c'checkCollisionLines,
+    c'checkCollisionPointCircle,
+    c'checkCollisionPointLine,
+    c'checkCollisionPointRec,
+    c'checkCollisionPointTriangle,
+    c'checkCollisionRecs,
+    c'drawCircle,
+    c'drawCircleGradient,
+    c'drawCircleLines,
+    c'drawCircleSector,
+    c'drawCircleSectorLines,
+    c'drawCircleV,
+    c'drawEllipse,
+    c'drawEllipseLines,
+    c'drawLine,
+    c'drawLineBezier,
+    c'drawLineBezierCubic,
+    c'drawLineBezierQuad,
+    c'drawLineEx,
+    c'drawLineStrip,
+    c'drawLineV,
+    c'drawPixel,
+    c'drawPixelV,
+    c'drawPoly,
+    c'drawPolyLines,
+    c'drawPolyLinesEx,
+    c'drawRectangle,
+    c'drawRectangleGradientEx,
+    c'drawRectangleGradientH,
+    c'drawRectangleGradientV,
+    c'drawRectangleLines,
+    c'drawRectangleLinesEx,
+    c'drawRectanglePro,
+    c'drawRectangleRec,
+    c'drawRectangleRounded,
+    c'drawRectangleRoundedLines,
+    c'drawRectangleV,
+    c'drawRing,
+    c'drawRingLines,
+    c'drawTriangle,
+    c'drawTriangleFan,
+    c'drawTriangleLines,
+    c'drawTriangleStrip,
+    c'getCollisionRec,
+    c'setShapesTexture,
+  )
+import Raylib.Types (Color, Rectangle, Texture, Vector2 (Vector2))
+import Raylib.Util (pop, withFreeable)
+
+setShapesTexture :: Raylib.Types.Texture -> Raylib.Types.Rectangle -> IO ()
+setShapesTexture tex source = withFreeable tex (withFreeable source . c'setShapesTexture)
+
+drawPixel :: Int -> Int -> Raylib.Types.Color -> IO ()
+drawPixel x y color = withFreeable color $ c'drawPixel (fromIntegral x) (fromIntegral y)
+
+drawPixelV :: Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
+drawPixelV position color = withFreeable position (withFreeable color . c'drawPixelV)
+
+drawLine :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO ()
+drawLine startX startY endX endY color =
+  withFreeable color $ c'drawLine (fromIntegral startX) (fromIntegral startY) (fromIntegral endX) (fromIntegral endY)
+
+drawLineV :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
+drawLineV start end color = withFreeable start (\s -> withFreeable end (withFreeable color . c'drawLineV s))
+
+drawLineEx :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
+drawLineEx start end thickness color =
+  withFreeable start (\s -> withFreeable end (\e -> withFreeable color (c'drawLineEx s e (realToFrac thickness))))
+
+drawLineBezier :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
+drawLineBezier start end thickness color =
+  withFreeable start (\s -> withFreeable end (\e -> withFreeable color (c'drawLineBezier s e (realToFrac thickness))))
+
+drawLineBezierQuad :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
+drawLineBezierQuad start end control thickness color =
+  withFreeable start (\s -> withFreeable end (\e -> withFreeable control (\c -> withFreeable color (c'drawLineBezierQuad s e c (realToFrac thickness)))))
+
+drawLineBezierCubic :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
+drawLineBezierCubic start end startControl endControl thickness color =
+  withFreeable
+    start
+    ( \s ->
+        withFreeable
+          end
+          ( \e ->
+              withFreeable
+                startControl
+                ( \sc ->
+                    withFreeable
+                      endControl
+                      ( \ec ->
+                          withFreeable
+                            color
+                            ( c'drawLineBezierCubic s e sc ec (realToFrac thickness)
+                            )
+                      )
+                )
+          )
+    )
+
+drawLineStrip :: [Raylib.Types.Vector2] -> Raylib.Types.Color -> IO ()
+drawLineStrip points color = withArray points (\p -> withFreeable color $ c'drawLineStrip p (genericLength points))
+
+drawCircle :: Int -> Int -> Float -> Raylib.Types.Color -> IO ()
+drawCircle centerX centerY radius color = withFreeable color (c'drawCircle (fromIntegral centerX) (fromIntegral centerY) (realToFrac radius))
+
+drawCircleSector :: Raylib.Types.Vector2 -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
+drawCircleSector center radius startAngle endAngle segments color =
+  withFreeable
+    center
+    ( \c ->
+        withFreeable
+          color
+          ( c'drawCircleSector c (realToFrac radius) (realToFrac startAngle) (realToFrac endAngle) (fromIntegral segments)
+          )
+    )
+
+drawCircleSectorLines :: Raylib.Types.Vector2 -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
+drawCircleSectorLines center radius startAngle endAngle segments color =
+  withFreeable
+    center
+    ( \c ->
+        withFreeable
+          color
+          ( c'drawCircleSectorLines c (realToFrac radius) (realToFrac startAngle) (realToFrac endAngle) (fromIntegral segments)
+          )
+    )
+
+drawCircleGradient :: Int -> Int -> Float -> Raylib.Types.Color -> Raylib.Types.Color -> IO ()
+drawCircleGradient centerX centerY radius color1 color2 =
+  withFreeable color1 (withFreeable color2 . c'drawCircleGradient (fromIntegral centerX) (fromIntegral centerY) (realToFrac radius))
+
+drawCircleV :: Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
+drawCircleV center radius color =
+  withFreeable center (\c -> withFreeable color (c'drawCircleV c (realToFrac radius)))
+
+drawCircleLines :: Int -> Int -> Float -> Raylib.Types.Color -> IO ()
+drawCircleLines centerX centerY radius color =
+  withFreeable color (c'drawCircleLines (fromIntegral centerX) (fromIntegral centerY) (realToFrac radius))
+
+drawEllipse :: Int -> Int -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawEllipse centerX centerY radiusH radiusV color =
+  withFreeable color (c'drawEllipse (fromIntegral centerX) (fromIntegral centerY) (realToFrac radiusH) (realToFrac radiusV))
+
+drawEllipseLines :: Int -> Int -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawEllipseLines centerX centerY radiusH radiusV color =
+  withFreeable color (c'drawEllipseLines (fromIntegral centerX) (fromIntegral centerY) (realToFrac radiusH) (realToFrac radiusV))
+
+drawRing :: Raylib.Types.Vector2 -> Float -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
+drawRing center innerRadius outerRadius startAngle endAngle segments color =
+  withFreeable
+    center
+    ( \c ->
+        withFreeable
+          color
+          ( c'drawRing
+              c
+              (realToFrac innerRadius)
+              (realToFrac outerRadius)
+              (realToFrac startAngle)
+              (realToFrac endAngle)
+              (fromIntegral segments)
+          )
+    )
+
+drawRingLines :: Raylib.Types.Vector2 -> Float -> Float -> Float -> Float -> Int -> Raylib.Types.Color -> IO ()
+drawRingLines center innerRadius outerRadius startAngle endAngle segments color =
+  withFreeable
+    center
+    ( \c ->
+        withFreeable
+          color
+          ( c'drawRingLines
+              c
+              (realToFrac innerRadius)
+              (realToFrac outerRadius)
+              (realToFrac startAngle)
+              (realToFrac endAngle)
+              (fromIntegral segments)
+          )
+    )
+
+drawRectangle :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO ()
+drawRectangle posX posY width height color =
+  withFreeable color (c'drawRectangle (fromIntegral posX) (fromIntegral posY) (fromIntegral width) (fromIntegral height))
+
+drawRectangleV :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
+drawRectangleV position size color = withFreeable position (\p -> withFreeable size (withFreeable color . c'drawRectangleV p))
+
+drawRectangleRec :: Raylib.Types.Rectangle -> Raylib.Types.Color -> IO ()
+drawRectangleRec rect color = withFreeable rect (withFreeable color . c'drawRectangleRec)
+
+drawRectanglePro :: Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
+drawRectanglePro rect origin rotation color =
+  withFreeable color (\c -> withFreeable rect (\r -> withFreeable origin (\o -> c'drawRectanglePro r o (realToFrac rotation) c)))
+
+drawRectangleGradientV :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> Raylib.Types.Color -> IO ()
+drawRectangleGradientV posX posY width height color1 color2 =
+  withFreeable
+    color1
+    ( withFreeable color2
+        . c'drawRectangleGradientV
+          (fromIntegral posX)
+          (fromIntegral posY)
+          (fromIntegral width)
+          (fromIntegral height)
+    )
+
+drawRectangleGradientH :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> Raylib.Types.Color -> IO ()
+drawRectangleGradientH posX posY width height color1 color2 =
+  withFreeable
+    color1
+    ( withFreeable color2
+        . c'drawRectangleGradientH
+          (fromIntegral posX)
+          (fromIntegral posY)
+          (fromIntegral width)
+          (fromIntegral height)
+    )
+
+drawRectangleGradientEx :: Raylib.Types.Rectangle -> Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color -> IO ()
+drawRectangleGradientEx rect col1 col2 col3 col4 =
+  withFreeable
+    rect
+    ( \r ->
+        withFreeable
+          col1
+          ( \c1 ->
+              withFreeable
+                col2
+                ( \c2 ->
+                    withFreeable col3 (withFreeable col4 . c'drawRectangleGradientEx r c1 c2)
+                )
+          )
+    )
+
+drawRectangleLines :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO ()
+drawRectangleLines posX posY width height color =
+  withFreeable color (c'drawRectangleLines (fromIntegral posX) (fromIntegral posY) (fromIntegral width) (fromIntegral height))
+
+drawRectangleLinesEx :: Raylib.Types.Rectangle -> Float -> Raylib.Types.Color -> IO ()
+drawRectangleLinesEx rect thickness color =
+  withFreeable color (\c -> withFreeable rect (\r -> c'drawRectangleLinesEx r (realToFrac thickness) c))
+
+drawRectangleRounded :: Raylib.Types.Rectangle -> Float -> Int -> Raylib.Types.Color -> IO ()
+drawRectangleRounded rect roundness segments color =
+  withFreeable rect (\r -> withFreeable color $ c'drawRectangleRounded r (realToFrac roundness) (fromIntegral segments))
+
+drawRectangleRoundedLines :: Raylib.Types.Rectangle -> Float -> Int -> Float -> Raylib.Types.Color -> IO ()
+drawRectangleRoundedLines rect roundness segments thickness color =
+  withFreeable rect (\r -> withFreeable color $ c'drawRectangleRoundedLines r (realToFrac roundness) (fromIntegral segments) (realToFrac thickness))
+
+drawTriangle :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
+drawTriangle v1 v2 v3 color =
+  withFreeable
+    v1
+    ( \p1 ->
+        withFreeable
+          v2
+          ( \p2 -> withFreeable v3 (withFreeable color . c'drawTriangle p1 p2)
+          )
+    )
+
+drawTriangleLines :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
+drawTriangleLines v1 v2 v3 color =
+  withFreeable
+    v1
+    ( \p1 ->
+        withFreeable
+          v2
+          ( \p2 -> withFreeable v3 (withFreeable color . c'drawTriangleLines p1 p2)
+          )
+    )
+
+drawTriangleFan :: [Raylib.Types.Vector2] -> Raylib.Types.Color -> IO ()
+drawTriangleFan points color = withArray points (\p -> withFreeable color $ c'drawTriangleFan p (genericLength points))
+
+drawTriangleStrip :: [Raylib.Types.Vector2] -> Raylib.Types.Color -> IO ()
+drawTriangleStrip points color =
+  withArray points (\p -> withFreeable color $ c'drawTriangleStrip p (genericLength points))
+
+drawPoly :: Raylib.Types.Vector2 -> Int -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawPoly center sides radius rotation color =
+  withFreeable center (\c -> withFreeable color $ c'drawPoly c (fromIntegral sides) (realToFrac radius) (realToFrac rotation))
+
+drawPolyLines :: Raylib.Types.Vector2 -> Int -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawPolyLines center sides radius rotation color =
+  withFreeable center (\c -> withFreeable color $ c'drawPolyLines c (fromIntegral sides) (realToFrac radius) (realToFrac rotation))
+
+drawPolyLinesEx :: Raylib.Types.Vector2 -> Int -> Float -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawPolyLinesEx center sides radius rotation thickness color =
+  withFreeable
+    center
+    ( \c ->
+        withFreeable color $
+          c'drawPolyLinesEx
+            c
+            (fromIntegral sides)
+            (realToFrac radius)
+            (realToFrac rotation)
+            (realToFrac thickness)
+    )
+
+checkCollisionRecs :: Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Bool
+checkCollisionRecs rec1 rec2 = unsafePerformIO $ toBool <$> withFreeable rec1 (withFreeable rec2 . c'checkCollisionRecs)
+
+checkCollisionCircles :: Raylib.Types.Vector2 -> Float -> Raylib.Types.Vector2 -> Float -> Bool
+checkCollisionCircles center1 radius1 center2 radius2 =
+  unsafePerformIO $ toBool <$> withFreeable center1 (\c1 -> withFreeable center2 (\c2 -> c'checkCollisionCircles c1 (realToFrac radius1) c2 (realToFrac radius2)))
+
+checkCollisionCircleRec :: Raylib.Types.Vector2 -> Float -> Raylib.Types.Rectangle -> Bool
+checkCollisionCircleRec center radius rect =
+  unsafePerformIO $ toBool <$> withFreeable center (\c -> withFreeable rect $ c'checkCollisionCircleRec c (realToFrac radius))
+
+checkCollisionPointRec :: Raylib.Types.Vector2 -> Raylib.Types.Rectangle -> Bool
+checkCollisionPointRec point rect =
+  unsafePerformIO $ toBool <$> withFreeable point (withFreeable rect . c'checkCollisionPointRec)
+
+checkCollisionPointCircle :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Bool
+checkCollisionPointCircle point center radius =
+  unsafePerformIO $ toBool <$> withFreeable point (\p -> withFreeable center (\c -> c'checkCollisionPointCircle p c (realToFrac radius)))
+
+checkCollisionPointTriangle :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Bool
+checkCollisionPointTriangle point p1 p2 p3 =
+  unsafePerformIO $ toBool <$> withFreeable point (\p -> withFreeable p1 (\ptr1 -> withFreeable p2 (withFreeable p3 . c'checkCollisionPointTriangle p ptr1)))
+
+-- | If a collision is found, returns @Just collisionPoint@, otherwise returns @Nothing@
+checkCollisionLines :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Maybe Raylib.Types.Vector2
+checkCollisionLines start1 end1 start2 end2 =
+  unsafePerformIO $
+    withFreeable
+      (Raylib.Types.Vector2 0 0)
+      ( \res -> do
+          foundCollision <- toBool <$> withFreeable start1 (\s1 -> withFreeable end1 (\e1 -> withFreeable start2 (\s2 -> withFreeable end2 (\e2 -> c'checkCollisionLines s1 e1 s2 e2 res))))
+          if foundCollision then Just <$> peek res else return Nothing
+      )
+
+checkCollisionPointLine :: Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Int -> Bool
+checkCollisionPointLine point p1 p2 threshold =
+  unsafePerformIO $ toBool <$> withFreeable point (\p -> withFreeable p1 (\ptr1 -> withFreeable p2 (\ptr2 -> c'checkCollisionPointLine p ptr1 ptr2 (fromIntegral threshold))))
+
+getCollisionRec :: Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle
+getCollisionRec rec1 rec2 =
+  unsafePerformIO $ withFreeable rec1 (withFreeable rec2 . c'getCollisionRec) >>= pop
+ src/Raylib/Text.hs view
@@ -0,0 +1,204 @@+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-# OPTIONS -Wall #-}
+
+module Raylib.Text where
+
+import Foreign
+  ( Ptr,
+    Storable (peek, sizeOf),
+    peekArray,
+    toBool,
+    withArray,
+    withArrayLen,
+  )
+import Foreign.C
+  ( CInt,
+    CString,
+    CUChar,
+    peekCString,
+    withCString,
+  )
+import Raylib.Native
+  ( c'codepointToUTF8,
+    c'drawFPS,
+    c'drawText,
+    c'drawTextCodepoint,
+    c'drawTextCodepoints,
+    c'drawTextEx,
+    c'drawTextPro,
+    c'exportFontAsCode,
+    c'genImageFontAtlas,
+    c'getCodepointCount,
+    c'getCodepointNext,
+    c'getCodepointPrevious,
+    c'getFontDefault,
+    c'getGlyphAtlasRec,
+    c'getGlyphIndex,
+    c'getGlyphInfo,
+    c'loadCodepoints,
+    c'loadFont,
+    c'loadFontData,
+    c'loadFontEx,
+    c'loadFontFromImage,
+    c'loadFontFromMemory,
+    c'loadUTF8,
+    c'measureText,
+    c'measureTextEx,
+    c'unloadFont,
+    c'unloadFontData, c'isFontReady
+  )
+import Raylib.Types
+  ( Color,
+    Font,
+    FontType,
+    GlyphInfo,
+    Image,
+    Rectangle,
+    Vector2,
+  )
+import Raylib.Util
+  ( pop,
+    withArray2D,
+    withFreeable,
+  )
+
+getFontDefault :: IO Raylib.Types.Font
+getFontDefault = c'getFontDefault >>= pop
+
+loadFont :: String -> IO Raylib.Types.Font
+loadFont fileName = withCString fileName c'loadFont >>= pop
+
+loadFontEx :: String -> Int -> [Int] -> Int -> IO Raylib.Types.Font
+loadFontEx fileName fontSize fontChars glyphCount = withCString fileName (\f -> withArray (map fromIntegral fontChars) (\c -> c'loadFontEx f (fromIntegral fontSize) c (fromIntegral glyphCount))) >>= pop
+
+loadFontFromImage :: Raylib.Types.Image -> Raylib.Types.Color -> Int -> IO Raylib.Types.Font
+loadFontFromImage image key firstChar = withFreeable image (\i -> withFreeable key (\k -> c'loadFontFromImage i k (fromIntegral firstChar))) >>= pop
+
+loadFontFromMemory :: String -> [Integer] -> Int -> [Int] -> Int -> IO Raylib.Types.Font
+loadFontFromMemory fileType fileData fontSize fontChars glyphCount = withCString fileType (\t -> withArrayLen (map fromIntegral fileData) (\size d -> withArray (map fromIntegral fontChars) (\c -> c'loadFontFromMemory t d (fromIntegral $ size * sizeOf (0 :: CUChar)) (fromIntegral fontSize) c (fromIntegral glyphCount)))) >>= pop
+
+loadFontData :: [Integer] -> Int -> [Int] -> Int -> FontType -> IO Raylib.Types.GlyphInfo
+loadFontData fileData fontSize fontChars glyphCount fontType = withArrayLen (map fromIntegral fileData) (\size d -> withArray (map fromIntegral fontChars) (\c -> c'loadFontData d (fromIntegral $ size * sizeOf (0 :: CUChar)) (fromIntegral fontSize) c (fromIntegral glyphCount) (fromIntegral $ fromEnum fontType))) >>= pop
+
+genImageFontAtlas :: [Raylib.Types.GlyphInfo] -> [[Raylib.Types.Rectangle]] -> Int -> Int -> Int -> Int -> IO Raylib.Types.Image
+genImageFontAtlas chars recs glyphCount fontSize padding packMethod = withArray chars (\c -> withArray2D recs (\r -> c'genImageFontAtlas c r (fromIntegral glyphCount) (fromIntegral fontSize) (fromIntegral padding) (fromIntegral packMethod))) >>= pop
+
+unloadFontData :: [Raylib.Types.GlyphInfo] -> IO ()
+unloadFontData glyphs = withArrayLen glyphs (\size g -> c'unloadFontData g (fromIntegral size))
+
+isFontReady :: Raylib.Types.Font -> IO Bool
+isFontReady font = toBool <$> withFreeable font c'isFontReady
+
+unloadFont :: Raylib.Types.Font -> IO ()
+unloadFont font = withFreeable font c'unloadFont
+
+exportFontAsCode :: Raylib.Types.Font -> String -> IO Bool
+exportFontAsCode font fileName = toBool <$> withFreeable font (withCString fileName . c'exportFontAsCode)
+
+drawFPS :: Int -> Int -> IO ()
+drawFPS x y = c'drawFPS (fromIntegral x) (fromIntegral y)
+
+drawText :: String -> Int -> Int -> Int -> Raylib.Types.Color -> IO ()
+drawText text x y fontSize color = withCString text (\t -> withFreeable color (c'drawText t (fromIntegral x) (fromIntegral y) (fromIntegral fontSize)))
+
+drawTextEx :: Raylib.Types.Font -> String -> Raylib.Types.Vector2 -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawTextEx font text position fontSize spacing tint = withFreeable font (\f -> withCString text (\t -> withFreeable position (\p -> withFreeable tint (c'drawTextEx f t p (realToFrac fontSize) (realToFrac spacing)))))
+
+drawTextPro :: Raylib.Types.Font -> String -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Float -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawTextPro font text position origin rotation fontSize spacing tint = withFreeable font (\f -> withCString text (\t -> withFreeable position (\p -> withFreeable origin (\o -> withFreeable tint (c'drawTextPro f t p o (realToFrac rotation) (realToFrac fontSize) (realToFrac spacing))))))
+
+drawTextCodepoint :: Raylib.Types.Font -> Int -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
+drawTextCodepoint font codepoint position fontSize tint = withFreeable font (\f -> withFreeable position (\p -> withFreeable tint (c'drawTextCodepoint f (fromIntegral codepoint) p (realToFrac fontSize))))
+
+drawTextCodepoints :: Raylib.Types.Font -> [Int] -> Raylib.Types.Vector2 -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawTextCodepoints font codepoints position fontSize spacing tint = withFreeable font (\f -> withArrayLen (map fromIntegral codepoints) (\count cp -> withFreeable position (\p -> withFreeable tint (c'drawTextCodepoints f cp (fromIntegral count) p (realToFrac fontSize) (realToFrac spacing)))))
+
+measureText :: String -> Int -> IO Int
+measureText text fontSize = fromIntegral <$> withCString text (\t -> c'measureText t (fromIntegral fontSize))
+
+measureTextEx :: Raylib.Types.Font -> String -> Float -> Float -> IO Raylib.Types.Vector2
+measureTextEx font text fontSize spacing = withFreeable font (\f -> withCString text (\t -> c'measureTextEx f t (realToFrac fontSize) (realToFrac spacing))) >>= pop
+
+getGlyphIndex :: Raylib.Types.Font -> Int -> IO Int
+getGlyphIndex font codepoint = fromIntegral <$> withFreeable font (\f -> c'getGlyphIndex f (fromIntegral codepoint))
+
+getGlyphInfo :: Raylib.Types.Font -> Int -> IO Raylib.Types.GlyphInfo
+getGlyphInfo font codepoint = withFreeable font (\f -> c'getGlyphInfo f (fromIntegral codepoint)) >>= pop
+
+getGlyphAtlasRec :: Raylib.Types.Font -> Int -> IO Raylib.Types.Rectangle
+getGlyphAtlasRec font codepoint = withFreeable font (\f -> c'getGlyphAtlasRec f (fromIntegral codepoint)) >>= pop
+
+loadUTF8 :: [Integer] -> IO String
+loadUTF8 codepoints =
+  withArrayLen
+    (map fromIntegral codepoints)
+    ( \size c ->
+        c'loadUTF8 c (fromIntegral size)
+    )
+    >>= ( \s -> do
+            val <- peekCString s
+            unloadUTF8 s
+            return val
+        )
+
+foreign import ccall safe "raylib.h UnloadUTF8"
+  unloadUTF8 ::
+    CString -> IO ()
+
+loadCodepoints :: String -> IO [Int]
+loadCodepoints text =
+  withCString
+    text
+    ( \t ->
+        withFreeable
+          0
+          ( \n -> do
+              res <- c'loadCodepoints t n
+              num <- peek n
+              arr <- peekArray (fromIntegral num) res
+              unloadCodepoints res
+              return $ fromIntegral <$> arr
+          )
+    )
+
+foreign import ccall safe "raylib.h UnloadCodepoints"
+  unloadCodepoints ::
+    Ptr CInt -> IO ()
+
+getCodepointCount :: String -> IO Int
+getCodepointCount text = fromIntegral <$> withCString text c'getCodepointCount
+
+-- | Deprecated, use `getCodepointNext`
+getCodepointNext :: String -> IO (Int, Int)
+getCodepointNext text =
+  withCString
+    text
+    ( \t ->
+        withFreeable
+          0
+          ( \n ->
+              do
+                res <- c'getCodepointNext t n
+                num <- peek n
+                return (fromIntegral res, fromIntegral num)
+          )
+    )
+
+getCodepointPrevious :: String -> IO (Int, Int)
+getCodepointPrevious text =
+  withCString
+    text
+    ( \t ->
+        withFreeable
+          0
+          ( \n ->
+              do
+                res <- c'getCodepointPrevious t n
+                num <- peek n
+                return (fromIntegral res, fromIntegral num)
+          )
+    )
+
+codepointToUTF8 :: Int -> IO String
+codepointToUTF8 codepoint = withFreeable 0 (c'codepointToUTF8 $ fromIntegral codepoint) >>= peekCString
+ src/Raylib/Textures.hs view
@@ -0,0 +1,487 @@+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-# OPTIONS -Wall #-}
+
+module Raylib.Textures where
+
+import Foreign
+  ( Ptr,
+    Storable (peek, sizeOf),
+    peekArray,
+    toBool,
+    withArrayLen,
+  )
+import Foreign.C (CUChar, withCString)
+import GHC.IO (unsafePerformIO)
+import Raylib.Native
+  ( c'colorAlpha,
+    c'colorAlphaBlend,
+    c'colorBrightness,
+    c'colorContrast,
+    c'colorFromHSV,
+    c'colorFromNormalized,
+    c'colorNormalize,
+    c'colorTint,
+    c'colorToHSV,
+    c'colorToInt,
+    c'drawTexture,
+    c'drawTextureEx,
+    c'drawTextureNPatch,
+    c'drawTexturePro,
+    c'drawTextureRec,
+    c'drawTextureV,
+    c'exportImage,
+    c'exportImageAsCode,
+    c'fade,
+    c'genImageCellular,
+    c'genImageChecked,
+    c'genImageColor,
+    c'genImageGradientH,
+    c'genImageGradientRadial,
+    c'genImageGradientV,
+    c'genImagePerlinNoise,
+    c'genImageText,
+    c'genImageWhiteNoise,
+    c'genTextureMipmaps,
+    c'getColor,
+    c'getImageAlphaBorder,
+    c'getImageColor,
+    c'getPixelColor,
+    c'imageAlphaClear,
+    c'imageAlphaCrop,
+    c'imageAlphaMask,
+    c'imageAlphaPremultiply,
+    c'imageBlurGaussian,
+    c'imageClearBackground,
+    c'imageColorBrightness,
+    c'imageColorContrast,
+    c'imageColorGrayscale,
+    c'imageColorInvert,
+    c'imageColorReplace,
+    c'imageColorTint,
+    c'imageCopy,
+    c'imageCrop,
+    c'imageDither,
+    c'imageDraw,
+    c'imageDrawCircle,
+    c'imageDrawCircleLines,
+    c'imageDrawCircleLinesV,
+    c'imageDrawCircleV,
+    c'imageDrawLine,
+    c'imageDrawLineV,
+    c'imageDrawPixel,
+    c'imageDrawPixelV,
+    c'imageDrawRectangle,
+    c'imageDrawRectangleLines,
+    c'imageDrawRectangleRec,
+    c'imageDrawRectangleV,
+    c'imageDrawText,
+    c'imageDrawTextEx,
+    c'imageFlipHorizontal,
+    c'imageFlipVertical,
+    c'imageFormat,
+    c'imageFromImage,
+    c'imageMipmaps,
+    c'imageResize,
+    c'imageResizeCanvas,
+    c'imageResizeNN,
+    c'imageRotateCCW,
+    c'imageRotateCW,
+    c'imageText,
+    c'imageTextEx,
+    c'imageToPOT,
+    c'loadImage,
+    c'loadImageAnim,
+    c'loadImageColors,
+    c'loadImageFromMemory,
+    c'loadImageFromScreen,
+    c'loadImageFromTexture,
+    c'loadImagePalette,
+    c'loadImageRaw,
+    c'loadRenderTexture,
+    c'loadTexture,
+    c'loadTextureCubemap,
+    c'loadTextureFromImage,
+    c'setPixelColor,
+    c'setTextureFilter,
+    c'setTextureWrap,
+    c'unloadImage,
+    c'unloadRenderTexture,
+    c'unloadTexture,
+    c'updateTexture,
+    c'updateTextureRec, c'isImageReady, c'isTextureReady, c'isRenderTextureReady
+  )
+import Raylib.Types
+  ( Color,
+    CubemapLayout,
+    Font,
+    Image (image'height, image'width),
+    NPatchInfo,
+    PixelFormat,
+    Rectangle,
+    RenderTexture,
+    Texture,
+    TextureFilter,
+    TextureWrap,
+    Vector2,
+    Vector3,
+    Vector4,
+  )
+import Raylib.Util
+  ( pop,
+    withFreeable,
+  )
+
+loadImage :: String -> IO Raylib.Types.Image
+loadImage fileName = withCString fileName c'loadImage >>= pop
+
+loadImageRaw :: String -> Int -> Int -> Int -> Int -> IO Raylib.Types.Image
+loadImageRaw fileName width height format headerSize =
+  withCString fileName (\str -> c'loadImageRaw str (fromIntegral width) (fromIntegral height) (fromIntegral $ fromEnum format) (fromIntegral headerSize)) >>= pop
+
+-- | Returns the final image and the framees in a tuple, e.g. @(img, 18)@
+loadImageAnim :: String -> IO (Raylib.Types.Image, Int)
+loadImageAnim fileName =
+  withFreeable
+    0
+    ( \frames ->
+        withCString
+          fileName
+          ( \fn -> do
+              img <- c'loadImageAnim fn frames >>= pop
+              frameNum <- fromIntegral <$> peek frames
+              return (img, frameNum)
+          )
+    )
+
+loadImageFromMemory :: String -> [Integer] -> IO Raylib.Types.Image
+loadImageFromMemory fileType fileData =
+  withCString fileType (\ft -> withArrayLen (map fromIntegral fileData) (\size fd -> c'loadImageFromMemory ft fd (fromIntegral $ size * sizeOf (0 :: CUChar)))) >>= pop
+
+loadImageFromTexture :: Raylib.Types.Texture -> IO Raylib.Types.Image
+loadImageFromTexture tex = withFreeable tex c'loadImageFromTexture >>= pop
+
+loadImageFromScreen :: IO Raylib.Types.Image
+loadImageFromScreen = c'loadImageFromScreen >>= pop
+
+isImageReady :: Image -> IO Bool
+isImageReady image = toBool <$> withFreeable image c'isImageReady
+
+unloadImage :: Raylib.Types.Image -> IO ()
+unloadImage image = withFreeable image c'unloadImage
+
+exportImage :: Raylib.Types.Image -> String -> IO Bool
+exportImage image fileName = toBool <$> withFreeable image (withCString fileName . c'exportImage)
+
+exportImageAsCode :: Raylib.Types.Image -> String -> IO Bool
+exportImageAsCode image fileName =
+  toBool <$> withFreeable image (withCString fileName . c'exportImageAsCode)
+
+genImageColor :: Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+genImageColor width height color =
+  withFreeable color (c'genImageColor (fromIntegral width) (fromIntegral height)) >>= pop
+
+genImageGradientV :: Int -> Int -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image
+genImageGradientV width height top bottom =
+  withFreeable top (withFreeable bottom . c'genImageGradientV (fromIntegral width) (fromIntegral height)) >>= pop
+
+genImageGradientH :: Int -> Int -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image
+genImageGradientH width height left right =
+  withFreeable left (withFreeable right . c'genImageGradientH (fromIntegral width) (fromIntegral height)) >>= pop
+
+genImageGradientRadial :: Int -> Int -> Float -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image
+genImageGradientRadial width height density inner outer =
+  withFreeable inner (withFreeable outer . c'genImageGradientRadial (fromIntegral width) (fromIntegral height) (realToFrac density)) >>= pop
+
+genImageChecked :: Int -> Int -> Int -> Int -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image
+genImageChecked width height checksX checksY col1 col2 =
+  withFreeable col1 (withFreeable col2 . c'genImageChecked (fromIntegral width) (fromIntegral height) (fromIntegral checksX) (fromIntegral checksY)) >>= pop
+
+genImageWhiteNoise :: Int -> Int -> Float -> IO Raylib.Types.Image
+genImageWhiteNoise width height factor =
+  c'genImageWhiteNoise (fromIntegral width) (fromIntegral height) (realToFrac factor) >>= pop
+
+genImagePerlinNoise :: Int -> Int -> Int -> Int -> Float -> IO Raylib.Types.Image
+genImagePerlinNoise width height offsetX offsetY scale = c'genImagePerlinNoise (fromIntegral width) (fromIntegral height) (fromIntegral offsetX) (fromIntegral offsetY) (realToFrac scale) >>= pop
+
+genImageCellular :: Int -> Int -> Int -> IO Raylib.Types.Image
+genImageCellular width height tileSize =
+  c'genImageCellular (fromIntegral width) (fromIntegral height) (fromIntegral tileSize) >>= pop
+
+genImageText :: Int -> Int -> String -> IO Raylib.Types.Image
+genImageText width height text =
+  withCString text (c'genImageText (fromIntegral width) (fromIntegral height)) >>= pop
+
+imageCopy :: Raylib.Types.Image -> IO Raylib.Types.Image
+imageCopy image = withFreeable image c'imageCopy >>= pop
+
+imageFromImage :: Raylib.Types.Image -> Raylib.Types.Rectangle -> IO Raylib.Types.Image
+imageFromImage image rect = withFreeable image (withFreeable rect . c'imageFromImage) >>= pop
+
+imageText :: String -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageText text fontSize color =
+  withCString text (\t -> withFreeable color $ c'imageText t (fromIntegral fontSize)) >>= pop
+
+imageTextEx :: Raylib.Types.Font -> String -> Float -> Float -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageTextEx font text fontSize spacing tint =
+  withFreeable font (\f -> withCString text (\t -> withFreeable tint $ c'imageTextEx f t (realToFrac fontSize) (realToFrac spacing))) >>= pop
+
+imageFormat :: Raylib.Types.Image -> PixelFormat -> IO Raylib.Types.Image
+imageFormat image newFormat =
+  withFreeable image (\i -> c'imageFormat i (fromIntegral $ fromEnum newFormat) >> peek i)
+
+imageToPOT :: Raylib.Types.Image -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageToPOT image color = withFreeable image (\i -> withFreeable color (c'imageToPOT i) >> peek i)
+
+imageCrop :: Raylib.Types.Image -> Raylib.Types.Rectangle -> IO Raylib.Types.Image
+imageCrop image crop = withFreeable image (\i -> withFreeable crop (c'imageCrop i) >> peek i)
+
+imageAlphaCrop :: Raylib.Types.Image -> Float -> IO Raylib.Types.Image
+imageAlphaCrop image threshold = withFreeable image (\i -> c'imageAlphaCrop i (realToFrac threshold) >> peek i)
+
+imageAlphaClear :: Raylib.Types.Image -> Raylib.Types.Color -> Float -> IO Raylib.Types.Image
+imageAlphaClear image color threshold = withFreeable image (\i -> withFreeable color (\c -> c'imageAlphaClear i c (realToFrac threshold) >> peek i))
+
+imageAlphaMask :: Raylib.Types.Image -> Raylib.Types.Image -> IO Raylib.Types.Image
+imageAlphaMask image alphaMask = withFreeable image (\i -> withFreeable alphaMask (c'imageAlphaMask i) >> peek i)
+
+imageAlphaPremultiply :: Raylib.Types.Image -> IO Raylib.Types.Image
+imageAlphaPremultiply image = withFreeable image (\i -> c'imageAlphaPremultiply i >> peek i)
+
+imageBlurGaussian :: Raylib.Types.Image -> Int -> IO Raylib.Types.Image
+imageBlurGaussian image blurSize = withFreeable image (\i -> c'imageBlurGaussian i (fromIntegral blurSize) >> peek i)
+
+imageResize :: Raylib.Types.Image -> Int -> Int -> IO Raylib.Types.Image
+imageResize image newWidth newHeight = withFreeable image (\i -> c'imageResize i (fromIntegral newWidth) (fromIntegral newHeight) >> peek i)
+
+imageResizeNN :: Raylib.Types.Image -> Int -> Int -> IO Raylib.Types.Image
+imageResizeNN image newWidth newHeight = withFreeable image (\i -> c'imageResizeNN i (fromIntegral newWidth) (fromIntegral newHeight) >> peek i)
+
+imageResizeCanvas :: Raylib.Types.Image -> Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageResizeCanvas image newWidth newHeight offsetX offsetY fill = withFreeable image (\i -> withFreeable fill (c'imageResizeCanvas i (fromIntegral newWidth) (fromIntegral newHeight) (fromIntegral offsetX) (fromIntegral offsetY)) >> peek i)
+
+imageMipmaps :: Raylib.Types.Image -> IO Raylib.Types.Image
+imageMipmaps image = withFreeable image (\i -> c'imageMipmaps i >> peek i)
+
+imageDither :: Raylib.Types.Image -> Int -> Int -> Int -> Int -> IO Raylib.Types.Image
+imageDither image rBpp gBpp bBpp aBpp = withFreeable image (\i -> c'imageDither i (fromIntegral rBpp) (fromIntegral gBpp) (fromIntegral bBpp) (fromIntegral aBpp) >> peek i)
+
+imageFlipVertical :: Raylib.Types.Image -> IO Raylib.Types.Image
+imageFlipVertical image = withFreeable image (\i -> c'imageFlipVertical i >> peek i)
+
+imageFlipHorizontal :: Raylib.Types.Image -> IO Raylib.Types.Image
+imageFlipHorizontal image = withFreeable image (\i -> c'imageFlipHorizontal i >> peek i)
+
+imageRotateCW :: Raylib.Types.Image -> IO Raylib.Types.Image
+imageRotateCW image = withFreeable image (\i -> c'imageRotateCW i >> peek i)
+
+imageRotateCCW :: Raylib.Types.Image -> IO Raylib.Types.Image
+imageRotateCCW image = withFreeable image (\i -> c'imageRotateCCW i >> peek i)
+
+imageColorTint :: Raylib.Types.Image -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageColorTint image color = withFreeable image (\i -> withFreeable color (c'imageColorTint i) >> peek i)
+
+imageColorInvert :: Raylib.Types.Image -> IO Raylib.Types.Image
+imageColorInvert image = withFreeable image (\i -> c'imageColorInvert i >> peek i)
+
+imageColorGrayscale :: Raylib.Types.Image -> IO Raylib.Types.Image
+imageColorGrayscale image = withFreeable image (\i -> c'imageColorGrayscale i >> peek i)
+
+imageColorContrast :: Raylib.Types.Image -> Float -> IO Raylib.Types.Image
+imageColorContrast image contrast = withFreeable image (\i -> c'imageColorContrast i (realToFrac contrast) >> peek i)
+
+imageColorBrightness :: Raylib.Types.Image -> Int -> IO Raylib.Types.Image
+imageColorBrightness image brightness = withFreeable image (\i -> c'imageColorBrightness i (fromIntegral brightness) >> peek i)
+
+imageColorReplace :: Raylib.Types.Image -> Raylib.Types.Color -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageColorReplace image color replace = withFreeable image (\i -> withFreeable color (withFreeable replace . c'imageColorReplace i) >> peek i)
+
+loadImageColors :: Raylib.Types.Image -> IO [Raylib.Types.Color]
+loadImageColors image =
+  withFreeable
+    image
+    ( \i -> do
+        colors <- c'loadImageColors i
+        colArray <- peekArray (fromIntegral $ Raylib.Types.image'width image * Raylib.Types.image'height image) colors
+        unloadImageColors colors
+        return colArray
+    )
+
+loadImagePalette :: Raylib.Types.Image -> Int -> IO [Raylib.Types.Color]
+loadImagePalette image maxPaletteSize =
+  withFreeable
+    image
+    ( \i -> do
+        (palette, num) <-
+          withFreeable
+            0
+            ( \size -> do
+                cols <- c'loadImagePalette i (fromIntegral maxPaletteSize) size
+                s <- peek size
+                return (cols, s)
+            )
+        colArray <- peekArray (fromIntegral num) palette
+        unloadImagePalette palette
+        return colArray
+    )
+
+foreign import ccall safe "raylib.h UnloadImageColors"
+  unloadImageColors ::
+    Ptr Raylib.Types.Color -> IO ()
+
+foreign import ccall safe "raylib.h UnloadImagePalette"
+  unloadImagePalette ::
+    Ptr Raylib.Types.Color -> IO ()
+
+getImageAlphaBorder :: Raylib.Types.Image -> Float -> IO Raylib.Types.Rectangle
+getImageAlphaBorder image threshold = withFreeable image (\i -> c'getImageAlphaBorder i (realToFrac threshold)) >>= pop
+
+getImageColor :: Raylib.Types.Image -> Int -> Int -> IO Raylib.Types.Color
+getImageColor image x y = withFreeable image (\i -> c'getImageColor i (fromIntegral x) (fromIntegral y)) >>= pop
+
+imageClearBackground :: Raylib.Types.Image -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageClearBackground image color = withFreeable image (\i -> withFreeable color (c'imageClearBackground i) >> peek i)
+
+imageDrawPixel :: Raylib.Types.Image -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawPixel image x y color = withFreeable image (\i -> withFreeable color (c'imageDrawPixel i (fromIntegral x) (fromIntegral y)) >> peek i)
+
+imageDrawPixelV :: Raylib.Types.Image -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawPixelV image position color = withFreeable image (\i -> withFreeable position (withFreeable color . c'imageDrawPixelV i) >> peek i)
+
+imageDrawLine :: Raylib.Types.Image -> Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawLine image startPosX startPosY endPosX endPosY color = withFreeable image (\i -> withFreeable color (c'imageDrawLine i (fromIntegral startPosX) (fromIntegral startPosY) (fromIntegral endPosX) (fromIntegral endPosY)) >> peek i)
+
+imageDrawLineV :: Raylib.Types.Image -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawLineV image start end color = withFreeable image (\i -> withFreeable start (\s -> withFreeable end (withFreeable color . c'imageDrawLineV i s)) >> peek i)
+
+imageDrawCircle :: Raylib.Types.Image -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawCircle image centerX centerY radius color = withFreeable image (\i -> withFreeable color (c'imageDrawCircle i (fromIntegral centerX) (fromIntegral centerY) (fromIntegral radius)) >> peek i)
+
+imageDrawCircleV :: Raylib.Types.Image -> Raylib.Types.Vector2 -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawCircleV image center radius color = withFreeable image (\i -> withFreeable center (\c -> withFreeable color (c'imageDrawCircleV i c (fromIntegral radius))) >> peek i)
+
+imageDrawCircleLines :: Raylib.Types.Image -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawCircleLines image centerX centerY radius color = withFreeable image (\i -> withFreeable color (c'imageDrawCircleLines i (fromIntegral centerX) (fromIntegral centerY) (fromIntegral radius)) >> peek i)
+
+imageDrawCircleLinesV :: Raylib.Types.Image -> Raylib.Types.Vector2 -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawCircleLinesV image center radius color = withFreeable image (\i -> withFreeable center (\c -> withFreeable color (c'imageDrawCircleLinesV i c (fromIntegral radius))) >> peek i)
+
+imageDrawRectangle :: Raylib.Types.Image -> Int -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawRectangle image posX posY width height color = withFreeable image (\i -> withFreeable color (c'imageDrawRectangle i (fromIntegral posX) (fromIntegral posY) (fromIntegral width) (fromIntegral height)) >> peek i)
+
+imageDrawRectangleV :: Raylib.Types.Image -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawRectangleV image position size color = withFreeable image (\i -> withFreeable position (\p -> withFreeable size (withFreeable color . c'imageDrawRectangleV i p)) >> peek i)
+
+imageDrawRectangleRec :: Raylib.Types.Image -> Raylib.Types.Rectangle -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawRectangleRec image rectangle color = withFreeable image (\i -> withFreeable rectangle (withFreeable color . c'imageDrawRectangleRec i) >> peek i)
+
+imageDrawRectangleLines :: Raylib.Types.Image -> Raylib.Types.Rectangle -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawRectangleLines image rectangle thickness color = withFreeable image (\i -> withFreeable rectangle (\r -> withFreeable color (c'imageDrawRectangleLines i r (fromIntegral thickness))) >> peek i)
+
+imageDraw :: Raylib.Types.Image -> Raylib.Types.Image -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDraw image source srcRec dstRec tint = withFreeable image (\i -> withFreeable source (\s -> withFreeable srcRec (\sr -> withFreeable dstRec (withFreeable tint . c'imageDraw i s sr))) >> peek i)
+
+imageDrawText :: Raylib.Types.Image -> String -> Int -> Int -> Int -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawText image text x y fontSize color = withFreeable image (\i -> withCString text (\t -> withFreeable color (c'imageDrawText i t (fromIntegral x) (fromIntegral y) (fromIntegral fontSize))) >> peek i)
+
+imageDrawTextEx :: Raylib.Types.Image -> Raylib.Types.Font -> String -> Raylib.Types.Vector2 -> Float -> Float -> Raylib.Types.Color -> IO Raylib.Types.Image
+imageDrawTextEx image font text position fontSize spacing tint = withFreeable image (\i -> withFreeable font (\f -> withCString text (\t -> withFreeable position (\p -> withFreeable tint (c'imageDrawTextEx i f t p (realToFrac fontSize) (realToFrac spacing))))) >> peek i)
+
+loadTexture :: String -> IO Raylib.Types.Texture
+loadTexture fileName = withCString fileName c'loadTexture >>= pop
+
+loadTextureFromImage :: Raylib.Types.Image -> IO Raylib.Types.Texture
+loadTextureFromImage image = withFreeable image c'loadTextureFromImage >>= pop
+
+loadTextureCubemap :: Raylib.Types.Image -> CubemapLayout -> IO Raylib.Types.Texture
+loadTextureCubemap image layout = withFreeable image (\i -> c'loadTextureCubemap i (fromIntegral $ fromEnum layout)) >>= pop
+
+loadRenderTexture :: Int -> Int -> IO Raylib.Types.RenderTexture
+loadRenderTexture width height = c'loadRenderTexture (fromIntegral width) (fromIntegral height) >>= pop
+
+isTextureReady :: Texture -> IO Bool
+isTextureReady texture = toBool <$> withFreeable texture c'isTextureReady
+
+unloadTexture :: Raylib.Types.Texture -> IO ()
+unloadTexture texture = withFreeable texture c'unloadTexture
+
+isRenderTextureReady :: RenderTexture -> IO Bool
+isRenderTextureReady renderTexture = toBool <$> withFreeable renderTexture c'isRenderTextureReady
+
+unloadRenderTexture :: Raylib.Types.RenderTexture -> IO ()
+unloadRenderTexture target = withFreeable target c'unloadRenderTexture
+
+updateTexture :: Raylib.Types.Texture -> Ptr () -> IO Raylib.Types.Texture
+updateTexture texture pixels = withFreeable texture (\t -> c'updateTexture t pixels >> peek t)
+
+updateTextureRec :: Raylib.Types.Texture -> Raylib.Types.Rectangle -> Ptr () -> IO Raylib.Types.Texture
+updateTextureRec texture rect pixels = withFreeable texture (\t -> withFreeable rect (\r -> c'updateTextureRec t r pixels) >> peek t)
+
+genTextureMipmaps :: Raylib.Types.Texture -> IO Raylib.Types.Texture
+genTextureMipmaps texture = withFreeable texture (\t -> c'genTextureMipmaps t >> peek t)
+
+setTextureFilter :: Raylib.Types.Texture -> TextureFilter -> IO Raylib.Types.Texture
+setTextureFilter texture filterType = withFreeable texture (\t -> c'setTextureFilter t (fromIntegral $ fromEnum filterType) >> peek t)
+
+setTextureWrap :: Raylib.Types.Texture -> TextureWrap -> IO Raylib.Types.Texture
+setTextureWrap texture wrap = withFreeable texture (\t -> c'setTextureWrap t (fromIntegral $ fromEnum wrap) >> peek t)
+
+drawTexture :: Raylib.Types.Texture -> Int -> Int -> Raylib.Types.Color -> IO ()
+drawTexture texture x y tint = withFreeable texture (\t -> withFreeable tint (c'drawTexture t (fromIntegral x) (fromIntegral y)))
+
+drawTextureV :: Raylib.Types.Texture -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
+drawTextureV texture position color = withFreeable texture (\t -> withFreeable position (withFreeable color . c'drawTextureV t))
+
+drawTextureEx :: Raylib.Types.Texture -> Raylib.Types.Vector2 -> Float -> Float -> Raylib.Types.Color -> IO ()
+drawTextureEx texture position rotation scale tint = withFreeable texture (\t -> withFreeable position (\p -> withFreeable tint (c'drawTextureEx t p (realToFrac rotation) (realToFrac scale))))
+
+drawTextureRec :: Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()
+drawTextureRec texture source position tint = withFreeable texture (\t -> withFreeable source (\s -> withFreeable position (withFreeable tint . c'drawTextureRec t s)))
+
+drawTexturePro :: Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
+drawTexturePro texture source dest origin rotation tint = withFreeable texture (\t -> withFreeable source (\s -> withFreeable dest (\d -> withFreeable origin (\o -> withFreeable tint (c'drawTexturePro t s d o (realToFrac rotation))))))
+
+drawTextureNPatch :: Raylib.Types.Texture -> Raylib.Types.NPatchInfo -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO ()
+drawTextureNPatch texture nPatchInfo dest origin rotation tint = withFreeable texture (\t -> withFreeable nPatchInfo (\n -> withFreeable dest (\d -> withFreeable origin (\o -> withFreeable tint (c'drawTextureNPatch t n d o (realToFrac rotation))))))
+
+fade :: Raylib.Types.Color -> Float -> Raylib.Types.Color
+fade color alpha = unsafePerformIO $ withFreeable color (\c -> c'fade c (realToFrac alpha)) >>= pop
+
+colorToInt :: Raylib.Types.Color -> Int
+colorToInt color = unsafePerformIO $ fromIntegral <$> withFreeable color c'colorToInt
+
+colorNormalize :: Raylib.Types.Color -> Raylib.Types.Vector4
+colorNormalize color = unsafePerformIO $ withFreeable color c'colorNormalize >>= pop
+
+colorFromNormalized :: Raylib.Types.Vector4 -> Raylib.Types.Color
+colorFromNormalized normalized = unsafePerformIO $ withFreeable normalized c'colorFromNormalized >>= pop
+
+colorToHSV :: Raylib.Types.Color -> Raylib.Types.Vector3
+colorToHSV color = unsafePerformIO $ withFreeable color c'colorToHSV >>= pop
+
+colorFromHSV :: Float -> Float -> Float -> Raylib.Types.Color
+colorFromHSV hue saturation value = unsafePerformIO $ c'colorFromHSV (realToFrac hue) (realToFrac saturation) (realToFrac value) >>= pop
+
+colorTint :: Color -> Color -> Raylib.Types.Color
+colorTint color tint = unsafePerformIO $ withFreeable color (withFreeable tint . c'colorTint) >>= pop
+
+colorBrightness :: Color -> Float -> Raylib.Types.Color
+colorBrightness color brightness = unsafePerformIO $ withFreeable color (\c -> c'colorBrightness c (realToFrac brightness)) >>= pop
+
+colorContrast :: Color -> Float -> Raylib.Types.Color
+colorContrast color contrast = unsafePerformIO $ withFreeable color (\c -> c'colorContrast c (realToFrac contrast)) >>= pop
+
+colorAlpha :: Raylib.Types.Color -> Float -> Raylib.Types.Color
+colorAlpha color alpha = unsafePerformIO $ withFreeable color (\c -> c'colorAlpha c (realToFrac alpha)) >>= pop
+
+colorAlphaBlend :: Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color -> Raylib.Types.Color
+colorAlphaBlend dst src tint = unsafePerformIO $ withFreeable dst (\d -> withFreeable src (withFreeable tint . c'colorAlphaBlend d)) >>= pop
+
+getColor :: Integer -> Raylib.Types.Color
+getColor hexValue = unsafePerformIO $ c'getColor (fromIntegral hexValue) >>= pop
+
+getPixelColor :: Ptr () -> PixelFormat -> IO Raylib.Types.Color
+getPixelColor srcPtr format = c'getPixelColor srcPtr (fromIntegral $ fromEnum format) >>= pop
+
+setPixelColor :: Ptr () -> Raylib.Types.Color -> PixelFormat -> IO ()
+setPixelColor dstPtr color format = withFreeable color (\c -> c'setPixelColor dstPtr c (fromIntegral $ fromEnum format))
src/Raylib/Types.hs view
@@ -1,2355 +1,1995 @@ {-# OPTIONS -Wall #-}
-module Raylib.Types where
-
--- This file includes Haskell counterparts to the structs defined in raylib
-
-import Foreign.C
-    ( CString, CChar, CUShort, CUInt, CInt, CUChar, CFloat, CBool )
-import Foreign
-    ( Ptr,
-      plusPtr,
-      pokeArray,
-      peekArray,
-      castPtr,
-      Storable(pokeByteOff, poke, peek, alignment, sizeOf, peekByteOff) )
-
-
-------------------------------------------------
--- Raylib enumerations -------------------------
-------------------------------------------------
-
-data ConfigFlag = VsyncHint              
-                 | FullscreenMode         
-                 | WindowResizable        
-                 | WindowUndecorated      
-                 | WindowHidden           
-                 | WindowMinimized        
-                 | WindowMaximized        
-                 | WindowUnfocused        
-                 | WindowTopmost          
-                 | WindowAlwaysRun        
-                 | WindowTransparent      
-                 | WindowHighdpi          
-                 | WindowMousePassthrough 
-                 | Msaa4xHint             
-                 | InterlacedHint         
-  deriving (Eq, Show)
-  
-instance Enum ConfigFlag where
-    fromEnum g = case g of 
-            VsyncHint              -> 64
-            FullscreenMode         -> 2
-            WindowResizable        -> 4
-            WindowUndecorated      -> 8
-            WindowHidden           -> 128
-            WindowMinimized        -> 512
-            WindowMaximized        -> 1024
-            WindowUnfocused        -> 2048
-            WindowTopmost          -> 4096
-            WindowAlwaysRun        -> 256
-            WindowTransparent      -> 16
-            WindowHighdpi          -> 8192
-            WindowMousePassthrough -> 16384
-            Msaa4xHint             -> 32
-            InterlacedHint         -> 65536
-    toEnum x = case x of 
-      64    -> VsyncHint              
-      2     -> FullscreenMode         
-      4     -> WindowResizable        
-      8     -> WindowUndecorated      
-      128   -> WindowHidden           
-      512   -> WindowMinimized        
-      1024  -> WindowMaximized        
-      2048  -> WindowUnfocused        
-      4096  -> WindowTopmost          
-      256   -> WindowAlwaysRun        
-      16    -> WindowTransparent      
-      8192  -> WindowHighdpi          
-      16384 -> WindowMousePassthrough 
-      32    -> Msaa4xHint             
-      65536 -> InterlacedHint         
-      n     -> error $ "Invalid value " ++ show n ++ " for `toEnum`."
-
-data TraceLogLevel = LogAll | LogTrace | LogDebug | LogInfo | LogWarning | LogError | LogFatal | LogNone 
-    deriving (Eq, Show,Enum)
-
-data KeyboardKey = KeyNull        
-                 | KeyApostrophe  
-                 | KeyComma       
-                 | KeyMinus       
-                 | KeyPeriod      
-                 | KeySlash       
-                 | KeyZero        
-                 | KeyOne         
-                 | KeyTwo         
-                 | KeyThree       
-                 | KeyFour        
-                 | KeyFive        
-                 | KeySix         
-                 | KeySeven       
-                 | KeyEight       
-                 | KeyNine        
-                 | KeySemicolon   
-                 | KeyEqual       
-                 | KeyA           
-                 | KeyB           
-                 | KeyC           
-                 | KeyD           
-                 | KeyE           
-                 | KeyF           
-                 | KeyG           
-                 | KeyH           
-                 | KeyI           
-                 | KeyJ           
-                 | KeyK           
-                 | KeyL           
-                 | KeyM           
-                 | KeyN           
-                 | KeyO           
-                 | KeyP           
-                 | KeyQ           
-                 | KeyR           
-                 | KeyS           
-                 | KeyT           
-                 | KeyU           
-                 | KeyV           
-                 | KeyW           
-                 | KeyX           
-                 | KeyY           
-                 | KeyZ           
-                 | KeyLeftBracket 
-                 | KeyBackslash   
-                 | KeyRightBracket
-                 | KeyGrave       
-                 | KeySpace       
-                 | KeyEscape      
-                 | KeyEnter       
-                 | KeyTab         
-                 | KeyBackspace   
-                 | KeyInsert      
-                 | KeyDelete      
-                 | KeyRight       
-                 | KeyLeft        
-                 | KeyDown        
-                 | KeyUp          
-                 | KeyPageUp      
-                 | KeyPageDown    
-                 | KeyHome        
-                 | KeyEnd         
-                 | KeyCapsLock    
-                 | KeyScrollLock  
-                 | KeyNumLock     
-                 | KeyPrintScreen 
-                 | KeyPause       
-                 | KeyF1          
-                 | KeyF2          
-                 | KeyF3          
-                 | KeyF4          
-                 | KeyF5          
-                 | KeyF6          
-                 | KeyF7          
-                 | KeyF8          
-                 | KeyF9          
-                 | KeyF10         
-                 | KeyF11         
-                 | KeyF12         
-                 | KeyLeftShift   
-                 | KeyLeftControl 
-                 | KeyLeftAlt     
-                 | KeyLeftSuper   
-                 | KeyRightShift  
-                 | KeyRightControl
-                 | KeyRightAlt    
-                 | KeyRightSuper  
-                 | KeyKbMenu      
-                 | KeyKp0         
-                 | KeyKp1         
-                 | KeyKp2         
-                 | KeyKp3         
-                 | KeyKp4         
-                 | KeyKp5         
-                 | KeyKp6         
-                 | KeyKp7         
-                 | KeyKp8         
-                 | KeyKp9         
-                 | KeyKpDecimal   
-                 | KeyKpDivide    
-                 | KeyKpMultiply  
-                 | KeyKpSubtract  
-                 | KeyKpAdd       
-                 | KeyKpEnter     
-                 | KeyKpEqual     
-                 | KeyBack        
-                 | KeyMenu        
-                 | KeyVolumeUp    
-                 | KeyVolumeDown  
-
-  deriving (Eq, Show)
-
-instance Enum KeyboardKey where
-    fromEnum k = case k of 
-        KeyNull         -> 0
-        KeyApostrophe   -> 39
-        KeyComma        -> 44
-        KeyMinus        -> 45
-        KeyPeriod       -> 46
-        KeySlash        -> 47
-        KeyZero         -> 48
-        KeyOne          -> 49
-        KeyTwo          -> 50
-        KeyThree        -> 51
-        KeyFour         -> 52
-        KeyFive         -> 53
-        KeySix          -> 54
-        KeySeven        -> 55
-        KeyEight        -> 56
-        KeyNine         -> 57
-        KeySemicolon    -> 59
-        KeyEqual        -> 61
-        KeyA            -> 65
-        KeyB            -> 66
-        KeyC            -> 67
-        KeyD            -> 68
-        KeyE            -> 69
-        KeyF            -> 70
-        KeyG            -> 71
-        KeyH            -> 72
-        KeyI            -> 73
-        KeyJ            -> 74
-        KeyK            -> 75
-        KeyL            -> 76
-        KeyM            -> 77
-        KeyN            -> 78
-        KeyO            -> 79
-        KeyP            -> 80
-        KeyQ            -> 81
-        KeyR            -> 82
-        KeyS            -> 83
-        KeyT            -> 84
-        KeyU            -> 85
-        KeyV            -> 86
-        KeyW            -> 87
-        KeyX            -> 88
-        KeyY            -> 89
-        KeyZ            -> 90
-        KeyLeftBracket  -> 91
-        KeyBackslash    -> 92
-        KeyRightBracket -> 93
-        KeyGrave        -> 96
-        KeySpace        -> 32
-        KeyEscape       -> 256
-        KeyEnter        -> 257
-        KeyTab          -> 258
-        KeyBackspace    -> 259
-        KeyInsert       -> 260
-        KeyDelete       -> 261
-        KeyRight        -> 262
-        KeyLeft         -> 263
-        KeyDown         -> 264
-        KeyUp           -> 265
-        KeyPageUp       -> 266
-        KeyPageDown     -> 267
-        KeyHome         -> 268
-        KeyEnd          -> 269
-        KeyCapsLock     -> 280
-        KeyScrollLock   -> 281
-        KeyNumLock      -> 282
-        KeyPrintScreen  -> 283
-        KeyPause        -> 284
-        KeyF1           -> 290
-        KeyF2           -> 291
-        KeyF3           -> 292
-        KeyF4           -> 293
-        KeyF5           -> 294
-        KeyF6           -> 295
-        KeyF7           -> 296
-        KeyF8           -> 297
-        KeyF9           -> 298
-        KeyF10          -> 299
-        KeyF11          -> 300
-        KeyF12          -> 301
-        KeyLeftShift    -> 340
-        KeyLeftControl  -> 341
-        KeyLeftAlt      -> 342
-        KeyLeftSuper    -> 343
-        KeyRightShift   -> 344
-        KeyRightControl -> 345
-        KeyRightAlt     -> 346
-        KeyRightSuper   -> 347
-        KeyKbMenu       -> 348
-        KeyKp0          -> 320
-        KeyKp1          -> 321
-        KeyKp2          -> 322
-        KeyKp3          -> 323
-        KeyKp4          -> 324
-        KeyKp5          -> 325
-        KeyKp6          -> 326
-        KeyKp7          -> 327
-        KeyKp8          -> 328
-        KeyKp9          -> 329
-        KeyKpDecimal    -> 330
-        KeyKpDivide     -> 331
-        KeyKpMultiply   -> 332
-        KeyKpSubtract   -> 333
-        KeyKpAdd        -> 334
-        KeyKpEnter      -> 335
-        KeyKpEqual      -> 336
-        -- Android buttons
-        KeyBack         -> 4
-        KeyMenu         -> 82
-        KeyVolumeUp     -> 24
-        KeyVolumeDown   -> 25
-
-    toEnum n = case n of 
-       0   -> KeyNull        
-       39  -> KeyApostrophe  
-       44  -> KeyComma       
-       45  -> KeyMinus       
-       46  -> KeyPeriod      
-       47  -> KeySlash       
-       48  -> KeyZero        
-       49  -> KeyOne         
-       50  -> KeyTwo         
-       51  -> KeyThree       
-       52  -> KeyFour        
-       53  -> KeyFive        
-       54  -> KeySix         
-       55  -> KeySeven       
-       56  -> KeyEight       
-       57  -> KeyNine        
-       59  -> KeySemicolon   
-       61  -> KeyEqual       
-       65  -> KeyA           
-       66  -> KeyB           
-       67  -> KeyC           
-       68  -> KeyD           
-       69  -> KeyE           
-       70  -> KeyF           
-       71  -> KeyG           
-       72  -> KeyH           
-       73  -> KeyI           
-       74  -> KeyJ           
-       75  -> KeyK           
-       76  -> KeyL           
-       77  -> KeyM           
-       78  -> KeyN           
-       79  -> KeyO           
-       80  -> KeyP           
-       81  -> KeyQ           
-       82  -> KeyR           
-       83  -> KeyS           
-       84  -> KeyT           
-       85  -> KeyU           
-       86  -> KeyV           
-       87  -> KeyW           
-       88  -> KeyX           
-       89  -> KeyY           
-       90  -> KeyZ           
-       91  -> KeyLeftBracket 
-       92  -> KeyBackslash   
-       93  -> KeyRightBracket
-       96  -> KeyGrave       
-       32  -> KeySpace       
-       256 -> KeyEscape      
-       257 -> KeyEnter       
-       258 -> KeyTab         
-       259 -> KeyBackspace   
-       260 -> KeyInsert      
-       261 -> KeyDelete      
-       262 -> KeyRight       
-       263 -> KeyLeft        
-       264 -> KeyDown        
-       265 -> KeyUp          
-       266 -> KeyPageUp      
-       267 -> KeyPageDown    
-       268 -> KeyHome        
-       269 -> KeyEnd         
-       280 -> KeyCapsLock    
-       281 -> KeyScrollLock  
-       282 -> KeyNumLock     
-       283 -> KeyPrintScreen 
-       284 -> KeyPause       
-       290 -> KeyF1          
-       291 -> KeyF2          
-       292 -> KeyF3          
-       293 -> KeyF4          
-       294 -> KeyF5          
-       295 -> KeyF6          
-       296 -> KeyF7          
-       297 -> KeyF8          
-       298 -> KeyF9          
-       299 -> KeyF10         
-       300 -> KeyF11         
-       301 -> KeyF12         
-       340 -> KeyLeftShift   
-       341 -> KeyLeftControl 
-       342 -> KeyLeftAlt     
-       343 -> KeyLeftSuper   
-       344 -> KeyRightShift  
-       345 -> KeyRightControl
-       346 -> KeyRightAlt    
-       347 -> KeyRightSuper  
-       348 -> KeyKbMenu      
-       320 -> KeyKp0         
-       321 -> KeyKp1         
-       322 -> KeyKp2         
-       323 -> KeyKp3         
-       324 -> KeyKp4         
-       325 -> KeyKp5         
-       326 -> KeyKp6         
-       327 -> KeyKp7         
-       328 -> KeyKp8         
-       329 -> KeyKp9         
-       330 -> KeyKpDecimal   
-       331 -> KeyKpDivide    
-       332 -> KeyKpMultiply  
-       333 -> KeyKpSubtract  
-       334 -> KeyKpAdd       
-       335 -> KeyKpEnter     
-       336 -> KeyKpEqual     
-       -- Android buttons
-       4   -> KeyBack        
-      --  82  -> KeyMenu        
-       24  -> KeyVolumeUp    
-       25  -> KeyVolumeDown  
-       x   -> error $ "Invalid value " ++ show x ++ " for `fromEnum`."
-
-data MouseButton
-  = MouseButtonLeft
-  | MouseButtonRight
-  | MouseButtonMiddle
-  | MouseButtonSide
-  | MouseButtonExtra
-  | MouseButtonForward
-  | MouseButtonBack
-  deriving (Eq, Show, Enum)
-
-data MouseCursor
-  = MouseCursorDefault
-  | MouseCursorArrow
-  | MouseCursorIbeam
-  | MouseCursorCrosshair
-  | MouseCursorPointingHand
-  | MouseCursorResizeEW
-  | MouseCursorResizeNS
-  | MouseCursorResizeNWSE
-  | MouseCursorResizeNESW
-  | MouseCursorResizeAll
-  | MouseCursorNotAllowed
- deriving (Eq, Show, Enum)
-
-data GamepadButton = GamepadButtonUnknown 
-                   | GamepadButtonUnknownLeftFaceUp 
-                   | GamepadButtonLeftFaceRight
-                   | GamepadButtonLeftFaceDown 
-                   | GamepadButtonLeftFaceLeft
-                   | GamepadButtonRightFaceUp
-                   | GamepadButtonRightFaceRight 
-                   | GamepadButtonRightFaceDown 
-                   | GamepadButtonRightFaceLeft
-                   | GamepadButtonLeftTrigger1
-                   | GamepadButtonLeftTrigger2 
-                   | GamepadButtonRightTrigger1 
-                   | GamepadButtonRightTrigger2
-                   | GamepadButtonMiddleLeft 
-                   | GamepadButtonMiddle 
-                   | GamepadButtonMiddleRight 
-                   | GamepadButtonLeftThumb 
-                   | GamepadButtonRightThumb 
-    deriving (Eq, Show, Enum)
-
-data GamepadAxis = GamepadAxisLeftX 
-                 | GamepadAxisLeftY
-                 | GamepadAxisRightX 
-                 | GamepadAxisRightY 
-                 | GamepadAxisLeftTrigger 
-                 | GamepadAxisRightTrigger 
-    deriving (Eq, Show, Enum)
-
-data MaterialMapIndex = MaterialMapAlbedo    
-                      | MaterialMapMetalness 
-                      | MaterialMapNormal    
-                      | MaterialMapRoughness 
-                      | MaterialMapOcclusion 
-                      | MaterialMapEmission  
-                      | MaterialMapHeight    
-                      | MaterialMapCubemap   
-                      | MaterialMapIrradiance
-                      | MaterialMapPrefilter 
-                      | MaterialMapBrdf      
-    deriving (Eq, Show, Enum)
-
-data ShaderLocationIndex = ShaderLocVertexPosition  
-                         | ShaderLocVertexTexcoord01
-                         | ShaderLocVertexTexcoord02
-                         | ShaderLocVertexNormal    
-                         | ShaderLocVertexTangent   
-                         | ShaderLocVertexColor     
-                         | ShaderLocMatrixMvp       
-                         | ShaderLocMatrixView      
-                         | ShaderLocMatrixProjection
-                         | ShaderLocMatrixModel     
-                         | ShaderLocMatrixNormal    
-                         | ShaderLocVectorView      
-                         | ShaderLocColorDiffuse    
-                         | ShaderLocColorSpecular   
-                         | ShaderLocColorAmbient    
-                         | ShaderLocMapAlbedo       
-                         | ShaderLocMapMetalness    
-                         | ShaderLocMapNormal       
-                         | ShaderLocMapRoughness    
-                         | ShaderLocMapOcclusion    
-                         | ShaderLocMapEmission     
-                         | ShaderLocMapHeight       
-                         | ShaderLocMapCubemap      
-                         | ShaderLocMapIrradiance   
-                         | ShaderLocMapPrefilter    
-                         | ShaderLocMapBrdf         
-    deriving (Eq, Show, Enum)
-
-data ShaderUniformDataType = ShaderUniformFloat    
-                           | ShaderUniformVec2     
-                           | ShaderUniformVec3      
-                           | ShaderUniformVec4      
-                           | ShaderUniformInt       
-                           | ShaderUniformIvec2     
-                           | ShaderUniformIvec3     
-                           | ShaderUniformIvec4     
-                           | ShaderUniformSampler2d 
-
-    deriving (Eq, Show, Enum)
-
--- I genuinely have no idea where this is used.
-data ShaderAttributeDataType = ShaderAttribFloat
-                             | ShaderAttribVec2 
-                             | ShaderAttribVec3
-                             | ShaderAttribVec4
-    deriving (Eq, Show, Enum)
-
-data PixelFormat = PixelFormatUncompressedGrayscale   
-                 | PixelFormatUncompressedGrayAlpha   
-                 | PixelFormatUncompressedR5G6B5      
-                 | PixelFormatUncompressedR8G8B8      
-                 | PixelFormatUncompressedR5G5B5A1    
-                 | PixelFormatUncompressedR4G4B4A4    
-                 | PixelFormatUncompressedR8G8B8A8    
-                 | PixelFormatUncompressedR32         
-                 | PixelFormatUncompressedR32G32B32   
-                 | PixelFormatUncompressedR32G32B32A32
-                 | PixelFormatCompressedDxt1Rgb       
-                 | PixelFormatCompressedDxt1Rgba      
-                 | PixelFormatCompressedDxt3Rgba      
-                 | PixelFormatCompressedDxt5Rgba      
-                 | PixelFormatCompressedEtc1Rgb       
-                 | PixelFormatCompressedEtc2Rgb       
-                 | PixelFormatCompressedEtc2EacRgba   
-                 | PixelFormatCompressedPvrtRgb       
-                 | PixelFormatCompressedPvrtRgba      
-                 | PixelFormatCompressedAstc4x4Rgba   
-                 | PixelFormatCompressedAstc8x8Rgba   
-    deriving (Eq, Show, Enum)
-
-instance Storable PixelFormat where
-  sizeOf _ = 4
-  alignment _ = 4
-  peek ptr = do
-    val <- peek (castPtr ptr)
-    return $ toEnum $ fromEnum (val :: CInt)
-  poke ptr v = poke (castPtr ptr) (toEnum $ fromEnum v :: CInt)
-
-data TextureFilter = TextureFilterPoint 
-                   | TextureFilterBilinear 
-                   | TextureFilterTrilinear 
-                   | TextureFilterAnisotropic4x
-                   | TextureFilterAnisotropic8x
-                   | TextureFilterAnisotropic16x
-    deriving Enum
-
-data TextureWrap = TextureWrapRepeat
-                 | TextureWrapClamp 
-                 | TextureWrapMirrorRepeat 
-                 | TextureWrapMirrorClamp
-        deriving Enum
-
-data CubemapLayout = CubemapLayoutAutoDetect 
-                   | CubemapLayoutLineVertical 
-                   | CubemapLayoutLineHorizontal 
-                   | CubemapLayoutCrossThreeByFour 
-                   | CubemapLayoutCrossThreeByThree
-                   | CubemapLayoutPanorama
-    deriving Enum
-
-data FontType = FontDefault | FontBitmap | FontSDF deriving Enum
-
-data BlendMode = BlendAlpha | BlendAdditive | BlendMultiplied | BlendAddColors | BlendSubtractColors | BlendAlphaPremultiply | BlendCustom | BlendCustomSeparate deriving Enum
-
-data Gesture
-  = GestureNone
-  | GestureTap
-  | GestureDoubleTap
-  | GestureHold
-  | GestureDrag
-  | GestureSwipeRight
-  | GestureSwipeLeft
-  | GestureSwipeUp
-  | GestureSwipeDown
-  | GesturePinchIn
-  | GesturePinchOut
-  deriving (Show)
-
--- NOTE: This is not the ideal solution, I need to make this unjanky
-instance Enum Gesture where
-  fromEnum n = case n of
-    GestureNone       -> 0
-    GestureTap        -> 1
-    GestureDoubleTap  -> 2
-    GestureHold       -> 4
-    GestureDrag       -> 8
-    GestureSwipeRight -> 16
-    GestureSwipeLeft  -> 32
-    GestureSwipeUp    -> 64
-    GestureSwipeDown  -> 128
-    GesturePinchIn    -> 256
-    GesturePinchOut   -> 512
-  toEnum n = case n of
-    0   -> GestureNone
-    1   -> GestureTap
-    2   -> GestureDoubleTap
-    4   -> GestureHold
-    8   -> GestureDrag
-    16  -> GestureSwipeRight
-    32  -> GestureSwipeLeft
-    64  -> GestureSwipeUp
-    128 -> GestureSwipeDown
-    256 -> GesturePinchIn
-    512 -> GesturePinchOut
-    _   -> error "Invalid input"
-
-data CameraMode
-  = CameraModeCustom
-  | CameraModeFree
-  | CameraModeOrbital
-  | CameraModeFirstPerson
-  | CameraModeThirdPerson
-  deriving (Enum)
-
-data CameraProjection = CameraPerspective | CameraOrthographic deriving (Eq, Show, Enum)
-
-instance Storable CameraProjection where
-  sizeOf _ = 4
-  alignment _ = 4
-  peek ptr = do
-    val <- peek (castPtr ptr)
-    return $ toEnum $ fromEnum (val :: CInt)
-  poke ptr v = poke (castPtr ptr) (toEnum $ fromEnum v :: CInt)
-
-data NPatchLayout = NPatchNinePatch | NPatchThreePatchVertical | NPatchThreePatchHorizontal deriving (Eq, Show, Enum)
-
-instance Storable NPatchLayout where
-  sizeOf _ = 4
-  alignment _ = 4
-  peek ptr = do
-    val <- peek (castPtr ptr)
-    return $ toEnum $ fromEnum (val :: CInt)
-  poke ptr v = poke (castPtr ptr) (toEnum $ fromEnum v :: CInt)
-
-
-------------------------------------------------
--- Raylib structures ---------------------------
-------------------------------------------------
-
-{- typedef struct Vector2 {
-            float x; float y;
-        } Vector2; -}
-data Vector2 = Vector2
-  { vector2'x :: CFloat,
-    vector2'y :: CFloat
-  }
-  deriving (Eq, Show)
-
-p'Vector2'x p = plusPtr p 0
-
-p'Vector2'x :: Ptr Vector2 -> Ptr CFloat
-
-p'Vector2'y p = plusPtr p 4
-
-p'Vector2'y :: Ptr Vector2 -> Ptr CFloat
-
-instance Storable Vector2 where
-  sizeOf _ = 8
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    return $ Vector2 v0 v1
-  poke _p (Vector2 v0 v1) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    return ()
-
-{- typedef struct Vector3 {
-            float x; float y; float z;
-        } Vector3; -}
-data Vector3 = Vector3
-  { vector3'x :: CFloat,
-    vector3'y :: CFloat,
-    vector3'z :: CFloat
-  }
-  deriving (Eq, Show)
-
-p'Vector3'x p = plusPtr p 0
-
-p'Vector3'x :: Ptr Vector3 -> Ptr CFloat
-
-p'Vector3'y p = plusPtr p 4
-
-p'Vector3'y :: Ptr Vector3 -> Ptr CFloat
-
-p'Vector3'z p = plusPtr p 8
-
-p'Vector3'z :: Ptr Vector3 -> Ptr CFloat
-
-instance Storable Vector3 where
-  sizeOf _ = 12
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    return $ Vector3 v0 v1 v2
-  poke _p (Vector3 v0 v1 v2) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    return ()
-
-{- typedef struct Vector4 {
-            float x; float y; float z; float w;
-        } Vector4; -}
-data Vector4 = Vector4
-  { vector4'x :: CFloat,
-    vector4'y :: CFloat,
-    vector4'z :: CFloat,
-    vector4'w :: CFloat
-  }
-  deriving (Eq, Show)
-
-p'Vector4'x p = plusPtr p 0
-
-p'Vector4'x :: Ptr Vector4 -> Ptr CFloat
-
-p'Vector4'y p = plusPtr p 4
-
-p'Vector4'y :: Ptr Vector4 -> Ptr CFloat
-
-p'Vector4'z p = plusPtr p 8
-
-p'Vector4'z :: Ptr Vector4 -> Ptr CFloat
-
-p'Vector4'w p = plusPtr p 12
-
-p'Vector4'w :: Ptr Vector4 -> Ptr CFloat
-
-instance Storable Vector4 where
-  sizeOf _ = 16
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    return $ Vector4 v0 v1 v2 v3
-  poke _p (Vector4 v0 v1 v2 v3) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    return ()
-
-{- typedef Vector4 Quaternion; -}
-type Quaternion = Vector4
-
-{- typedef struct Matrix {
-            float m0, m4, m8, m12;
-            float m1, m5, m9, m13;
-            float m2, m6, m10, m14;
-            float m3, m7, m11, m15;
-        } Matrix; -}
-data Matrix = Matrix
-  { matrix'm0 :: CFloat,
-    matrix'm4 :: CFloat,
-    matrix'm8 :: CFloat,
-    matrix'm12 :: CFloat,
-    matrix'm1 :: CFloat,
-    matrix'm5 :: CFloat,
-    matrix'm9 :: CFloat,
-    matrix'm13 :: CFloat,
-    matrix'm2 :: CFloat,
-    matrix'm6 :: CFloat,
-    matrix'm10 :: CFloat,
-    matrix'm14 :: CFloat,
-    matrix'm3 :: CFloat,
-    matrix'm7 :: CFloat,
-    matrix'm11 :: CFloat,
-    matrix'm15 :: CFloat
-  }
-  deriving (Eq, Show)
-
-p'Matrix'm0 p = plusPtr p 0
-
-p'Matrix'm0 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm4 p = plusPtr p 4
-
-p'Matrix'm4 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm8 p = plusPtr p 8
-
-p'Matrix'm8 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm12 p = plusPtr p 12
-
-p'Matrix'm12 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm1 p = plusPtr p 16
-
-p'Matrix'm1 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm5 p = plusPtr p 20
-
-p'Matrix'm5 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm9 p = plusPtr p 24
-
-p'Matrix'm9 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm13 p = plusPtr p 28
-
-p'Matrix'm13 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm2 p = plusPtr p 32
-
-p'Matrix'm2 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm6 p = plusPtr p 36
-
-p'Matrix'm6 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm10 p = plusPtr p 40
-
-p'Matrix'm10 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm14 p = plusPtr p 44
-
-p'Matrix'm14 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm3 p = plusPtr p 48
-
-p'Matrix'm3 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm7 p = plusPtr p 52
-
-p'Matrix'm7 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm11 p = plusPtr p 56
-
-p'Matrix'm11 :: Ptr Matrix -> Ptr CFloat
-
-p'Matrix'm15 p = plusPtr p 60
-
-p'Matrix'm15 :: Ptr Matrix -> Ptr CFloat
-
-instance Storable Matrix where
-  sizeOf _ = 64
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    v4 <- peekByteOff _p 16
-    v5 <- peekByteOff _p 20
-    v6 <- peekByteOff _p 24
-    v7 <- peekByteOff _p 28
-    v8 <- peekByteOff _p 32
-    v9 <- peekByteOff _p 36
-    v10 <- peekByteOff _p 40
-    v11 <- peekByteOff _p 44
-    v12 <- peekByteOff _p 48
-    v13 <- peekByteOff _p 52
-    v14 <- peekByteOff _p 56
-    v15 <- peekByteOff _p 60
-    return $ Matrix v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15
-  poke _p (Matrix v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    pokeByteOff _p 16 v4
-    pokeByteOff _p 20 v5
-    pokeByteOff _p 24 v6
-    pokeByteOff _p 28 v7
-    pokeByteOff _p 32 v8
-    pokeByteOff _p 36 v9
-    pokeByteOff _p 40 v10
-    pokeByteOff _p 44 v11
-    pokeByteOff _p 48 v12
-    pokeByteOff _p 52 v13
-    pokeByteOff _p 56 v14
-    pokeByteOff _p 60 v15
-    return ()
-
-{- typedef struct Color {
-            unsigned char r; unsigned char g; unsigned char b; unsigned char a;
-        } Color; -}
-data Color = Color
-  { color'r :: CUChar,
-    color'g :: CUChar,
-    color'b :: CUChar,
-    color'a :: CUChar
-  }
-  deriving (Eq, Show)
-
-p'Color'r p = plusPtr p 0
-
-p'Color'r :: Ptr Color -> Ptr CUChar
-
-p'Color'g p = plusPtr p 1
-
-p'Color'g :: Ptr Color -> Ptr CUChar
-
-p'Color'b p = plusPtr p 2
-
-p'Color'b :: Ptr Color -> Ptr CUChar
-
-p'Color'a p = plusPtr p 3
-
-p'Color'a :: Ptr Color -> Ptr CUChar
-
-instance Storable Color where
-  sizeOf _ = 4
-  alignment _ = 1
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 1
-    v2 <- peekByteOff _p 2
-    v3 <- peekByteOff _p 3
-    return $ Color v0 v1 v2 v3
-  poke _p (Color v0 v1 v2 v3) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 1 v1
-    pokeByteOff _p 2 v2
-    pokeByteOff _p 3 v3
-    return ()
-
-{- typedef struct Rectangle {
-            float x; float y; float width; float height;
-        } Rectangle; -}
-data Rectangle = Rectangle
-  { rectangle'x :: CFloat,
-    rectangle'y :: CFloat,
-    rectangle'width :: CFloat,
-    rectangle'height :: CFloat
-  }
-  deriving (Eq, Show)
-
-p'Rectangle'x p = plusPtr p 0
-
-p'Rectangle'x :: Ptr Rectangle -> Ptr CFloat
-
-p'Rectangle'y p = plusPtr p 4
-
-p'Rectangle'y :: Ptr Rectangle -> Ptr CFloat
-
-p'Rectangle'width p = plusPtr p 8
-
-p'Rectangle'width :: Ptr Rectangle -> Ptr CFloat
-
-p'Rectangle'height p = plusPtr p 12
-
-p'Rectangle'height :: Ptr Rectangle -> Ptr CFloat
-
-instance Storable Rectangle where
-  sizeOf _ = 16
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    return $ Rectangle v0 v1 v2 v3
-  poke _p (Rectangle v0 v1 v2 v3) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    return ()
-
-{- typedef struct Image {
-            void * data; int width; int height; int mipmaps; int format;
-        } Image; -}
-data Image = Image
-  { image'data :: Ptr (),
-    image'width :: CInt,
-    image'height :: CInt,
-    image'mipmaps :: CInt,
-    image'format :: PixelFormat
-  }
-  deriving (Eq, Show)
-
-p'Image'data p = plusPtr p 0
-
-p'Image'data :: Ptr Image -> Ptr (Ptr ())
-
-p'Image'width p = plusPtr p 4
-
-p'Image'width :: Ptr Image -> Ptr CInt
-
-p'Image'height p = plusPtr p 8
-
-p'Image'height :: Ptr Image -> Ptr CInt
-
-p'Image'mipmaps p = plusPtr p 12
-
-p'Image'mipmaps :: Ptr Image -> Ptr CInt
-
-p'Image'format p = plusPtr p 16
-
-p'Image'format :: Ptr Image -> Ptr CInt
-
-instance Storable Image where
-  sizeOf _ = 20
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    v4 <- peekByteOff _p 16
-    return $ Image v0 v1 v2 v3 v4
-  poke _p (Image v0 v1 v2 v3 v4) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    pokeByteOff _p 16 v4
-    return ()
-
-{- typedef struct Texture {
-            unsigned int id; int width; int height; int mipmaps; int format;
-        } Texture; -}
-data Texture = Texture
-  { texture'id :: CUInt,
-    texture'width :: CInt,
-    texture'height :: CInt,
-    texture'mipmaps :: CInt,
-    texture'format :: PixelFormat
-  }
-  deriving (Eq, Show)
-
-p'Texture'id p = plusPtr p 0
-
-p'Texture'id :: Ptr Texture -> Ptr CUInt
-
-p'Texture'width p = plusPtr p 4
-
-p'Texture'width :: Ptr Texture -> Ptr CInt
-
-p'Texture'height p = plusPtr p 8
-
-p'Texture'height :: Ptr Texture -> Ptr CInt
-
-p'Texture'mipmaps p = plusPtr p 12
-
-p'Texture'mipmaps :: Ptr Texture -> Ptr CInt
-
-p'Texture'format p = plusPtr p 16
-
-p'Texture'format :: Ptr Texture -> Ptr CInt
-
-instance Storable Texture where
-  sizeOf _ = 20
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    v4 <- peekByteOff _p 16
-    return $ Texture v0 v1 v2 v3 v4
-  poke _p (Texture v0 v1 v2 v3 v4) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    pokeByteOff _p 16 v4
-    return ()
-
-{- typedef Texture Texture2D; -}
-type Texture2D = Texture
-
-{- typedef Texture TextureCubemap; -}
-type TextureCubemap = Texture
-
-{- typedef struct RenderTexture {
-            unsigned int id; Texture texture; Texture depth;
-        } RenderTexture; -}
-data RenderTexture = RenderTexture
-  { rendertexture'id :: CUInt,
-    rendertexture'texture :: Texture,
-    rendertexture'depth :: Texture
-  }
-  deriving (Eq, Show)
-
-p'RenderTexture'id p = plusPtr p 0
-
-p'RenderTexture'id :: Ptr RenderTexture -> Ptr CUInt
-
-p'RenderTexture'texture p = plusPtr p 4
-
-p'RenderTexture'texture :: Ptr RenderTexture -> Ptr Texture
-
-p'RenderTexture'depth p = plusPtr p 24
-
-p'RenderTexture'depth :: Ptr RenderTexture -> Ptr Texture
-
-instance Storable RenderTexture where
-  sizeOf _ = 44
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 24
-    return $ RenderTexture v0 v1 v2
-  poke _p (RenderTexture v0 v1 v2) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 24 v2
-    return ()
-
-{- typedef RenderTexture RenderTexture2D; -}
-type RenderTexture2D = RenderTexture
-
-{- typedef struct NPatchInfo {
-            Rectangle source;
-            int left;
-            int top;
-            int right;
-            int bottom;
-            int layout;
-        } NPatchInfo; -}
-data NPatchInfo = NPatchInfo
-  { nPatchinfo'source :: Rectangle,
-    nPatchinfo'left :: CInt,
-    nPatchinfo'top :: CInt,
-    nPatchinfo'right :: CInt,
-    nPatchinfo'bottom :: CInt,
-    nPatchinfo'layout :: NPatchLayout
-  }
-  deriving (Eq, Show)
-
-p'NPatchInfo'source p = plusPtr p 0
-
-p'NPatchInfo'source :: Ptr NPatchInfo -> Ptr Rectangle
-
-p'NPatchInfo'left p = plusPtr p 16
-
-p'NPatchInfo'left :: Ptr NPatchInfo -> Ptr CInt
-
-p'NPatchInfo'top p = plusPtr p 20
-
-p'NPatchInfo'top :: Ptr NPatchInfo -> Ptr CInt
-
-p'NPatchInfo'right p = plusPtr p 24
-
-p'NPatchInfo'right :: Ptr NPatchInfo -> Ptr CInt
-
-p'NPatchInfo'bottom p = plusPtr p 28
-
-p'NPatchInfo'bottom :: Ptr NPatchInfo -> Ptr CInt
-
-p'NPatchInfo'layout p = plusPtr p 32
-
-p'NPatchInfo'layout :: Ptr NPatchInfo -> Ptr CInt
-
-instance Storable NPatchInfo where
-  sizeOf _ = 36
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 16
-    v2 <- peekByteOff _p 20
-    v3 <- peekByteOff _p 24
-    v4 <- peekByteOff _p 28
-    v5 <- peekByteOff _p 32
-    return $ NPatchInfo v0 v1 v2 v3 v4 v5
-  poke _p (NPatchInfo v0 v1 v2 v3 v4 v5) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 16 v1
-    pokeByteOff _p 20 v2
-    pokeByteOff _p 24 v3
-    pokeByteOff _p 28 v4
-    pokeByteOff _p 32 v5
-    return ()
-
-{- typedef struct GlyphInfo {
-            int value; int offsetX; int offsetY; int advanceX; Image image;
-        } GlyphInfo; -}
-data GlyphInfo = GlyphInfo
-  { glyphinfo'value :: CInt,
-    glyphInfo'offsetX :: CInt,
-    glyphInfo'offsetY :: CInt,
-    glyphInfo'advanceX :: CInt,
-    glyphinfo'image :: Image
-  }
-  deriving (Eq, Show)
-
-p'GlyphInfo'value p = plusPtr p 0
-
-p'GlyphInfo'value :: Ptr GlyphInfo -> Ptr CInt
-
-p'GlyphInfo'offsetX p = plusPtr p 4
-
-p'GlyphInfo'offsetX :: Ptr GlyphInfo -> Ptr CInt
-
-p'GlyphInfo'offsetY p = plusPtr p 8
-
-p'GlyphInfo'offsetY :: Ptr GlyphInfo -> Ptr CInt
-
-p'GlyphInfo'advanceX p = plusPtr p 12
-
-p'GlyphInfo'advanceX :: Ptr GlyphInfo -> Ptr CInt
-
-p'GlyphInfo'image p = plusPtr p 16
-
-p'GlyphInfo'image :: Ptr GlyphInfo -> Ptr Image
-
-instance Storable GlyphInfo where
-  sizeOf _ = 36
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    v4 <- peekByteOff _p 16
-    return $ GlyphInfo v0 v1 v2 v3 v4
-  poke _p (GlyphInfo v0 v1 v2 v3 v4) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    pokeByteOff _p 16 v4
-    return ()
-
-{- typedef struct Font {
-            int baseSize;
-            int glyphCount;
-            int glyphPadding;
-            Texture2D texture;
-            Rectangle * recs;
-            GlyphInfo * glyphs;
-        } Font; -}
-data Font = Font
-  { font'baseSize :: CInt,
-    font'glyphCount :: CInt,
-    font'glyphPadding :: CInt,
-    font'texture :: Texture,
-    font'recs :: Ptr Rectangle,
-    font'glyphs :: Ptr GlyphInfo
-  }
-  deriving (Eq, Show)
-
-p'Font'baseSize p = plusPtr p 0
-
-p'Font'baseSize :: Ptr Font -> Ptr CInt
-
-p'Font'glyphCount p = plusPtr p 4
-
-p'Font'glyphCount :: Ptr Font -> Ptr CInt
-
-p'Font'glyphPadding p = plusPtr p 8
-
-p'Font'glyphPadding :: Ptr Font -> Ptr CInt
-
-p'Font'texture p = plusPtr p 12
-
-p'Font'texture :: Ptr Font -> Ptr Texture
-
-p'Font'recs p = plusPtr p 32
-
-p'Font'recs :: Ptr Font -> Ptr (Ptr Rectangle)
-
-p'Font'glyphs p = plusPtr p 40
-
-p'Font'glyphs :: Ptr Font -> Ptr (Ptr GlyphInfo)
-
-instance Storable Font where
-  sizeOf _ = 48
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    v4 <- peekByteOff _p 32
-    v5 <- peekByteOff _p 40
-    return $ Font v0 v1 v2 v3 v4 v5
-  poke _p (Font v0 v1 v2 v3 v4 v5) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    pokeByteOff _p 32 v4
-    pokeByteOff _p 40 v5
-    return ()
-
-{- typedef struct Camera3D {
-            Vector3 position;
-            Vector3 target;
-            Vector3 up;
-            float fovy;
-            int projection;
-        } Camera3D; -}
-data Camera3D = Camera3D
-  { camera3D'position :: Vector3,
-    camera3D'target :: Vector3,
-    camera3D'up :: Vector3,
-    camera3D'fovy :: CFloat,
-    camera3D'projection :: CameraProjection
-  }
-  deriving (Eq, Show)
-
-p'Camera3D'position p = plusPtr p 0
-
-p'Camera3D'position :: Ptr Camera3D -> Ptr Vector3
-
-p'Camera3D'target p = plusPtr p 12
-
-p'Camera3D'target :: Ptr Camera3D -> Ptr Vector3
-
-p'Camera3D'up p = plusPtr p 24
-
-p'Camera3D'up :: Ptr Camera3D -> Ptr Vector3
-
-p'Camera3D'fovy p = plusPtr p 36
-
-p'Camera3D'fovy :: Ptr Camera3D -> Ptr CFloat
-
-p'Camera3D'projection p = plusPtr p 40
-
-p'Camera3D'projection :: Ptr Camera3D -> Ptr CInt
-
-instance Storable Camera3D where
-  sizeOf _ = 44
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 12
-    v2 <- peekByteOff _p 24
-    v3 <- peekByteOff _p 36
-    v4 <- peekByteOff _p 40
-    return $ Camera3D v0 v1 v2 v3 v4
-  poke _p (Camera3D v0 v1 v2 v3 v4) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 12 v1
-    pokeByteOff _p 24 v2
-    pokeByteOff _p 36 v3
-    pokeByteOff _p 40 v4
-    return ()
-
-{- typedef Camera3D Camera; -}
-type Camera = Camera3D
-
-{- typedef struct Camera2D {
-            Vector2 offset; Vector2 target; float rotation; float zoom;
-        } Camera2D; -}
-data Camera2D = Camera2D
-  { camera2D'offset :: Vector2,
-    camera2D'target :: Vector2,
-    camera2d'rotation :: CFloat,
-    camera2d'zoom :: CFloat
-  }
-  deriving (Eq, Show)
-
-p'Camera2D'offset p = plusPtr p 0
-
-p'Camera2D'offset :: Ptr Camera2D -> Ptr Vector2
-
-p'Camera2D'target p = plusPtr p 8
-
-p'Camera2D'target :: Ptr Camera2D -> Ptr Vector2
-
-p'Camera2D'rotation p = plusPtr p 16
-
-p'Camera2D'rotation :: Ptr Camera2D -> Ptr CFloat
-
-p'Camera2D'zoom p = plusPtr p 20
-
-p'Camera2D'zoom :: Ptr Camera2D -> Ptr CFloat
-
-instance Storable Camera2D where
-  sizeOf _ = 24
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 8
-    v2 <- peekByteOff _p 16
-    v3 <- peekByteOff _p 20
-    return $ Camera2D v0 v1 v2 v3
-  poke _p (Camera2D v0 v1 v2 v3) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 8 v1
-    pokeByteOff _p 16 v2
-    pokeByteOff _p 20 v3
-    return ()
-
-{- typedef struct Mesh {
-            int vertexCount;
-            int triangleCount;
-            float * vertices;
-            float * texcoords;
-            float * texcoords2;
-            float * normals;
-            float * tangents;
-            unsigned char * colors;
-            unsigned short * indices;
-            float * animVertices;
-            float * animNormals;
-            unsigned char * boneIds;
-            float * boneWeights;
-            unsigned int vaoId;
-            unsigned int * vboId;
-        } Mesh; -}
-data Mesh = Mesh
-  { mesh'vertexCount :: CInt,
-    mesh'triangleCount :: CInt,
-    mesh'vertices :: Ptr CFloat,
-    mesh'texcoords :: Ptr CFloat,
-    mesh'texcoords2 :: Ptr CFloat,
-    mesh'normals :: Ptr CFloat,
-    mesh'tangents :: Ptr CFloat,
-    mesh'colors :: Ptr CUChar,
-    mesh'indices :: Ptr CUShort,
-    mesh'animVertices :: Ptr CFloat,
-    mesh'animNormals :: Ptr CFloat,
-    mesh'boneIds :: Ptr CUChar,
-    mesh'boneWeights :: Ptr CFloat,
-    mesh'vaoId :: CUInt,
-    mesh'vboId :: Ptr CUInt
-  }
-  deriving (Eq, Show)
-
-p'Mesh'vertexCount p = plusPtr p 0
-
-p'Mesh'vertexCount :: Ptr Mesh -> Ptr CInt
-
-p'Mesh'triangleCount p = plusPtr p 4
-
-p'Mesh'triangleCount :: Ptr Mesh -> Ptr CInt
-
-p'Mesh'vertices p = plusPtr p 8
-
-p'Mesh'vertices :: Ptr Mesh -> Ptr (Ptr CFloat)
-
-p'Mesh'texcoords p = plusPtr p 12
-
-p'Mesh'texcoords :: Ptr Mesh -> Ptr (Ptr CFloat)
-
-p'Mesh'texcoords2 p = plusPtr p 16
-
-p'Mesh'texcoords2 :: Ptr Mesh -> Ptr (Ptr CFloat)
-
-p'Mesh'normals p = plusPtr p 20
-
-p'Mesh'normals :: Ptr Mesh -> Ptr (Ptr CFloat)
-
-p'Mesh'tangents p = plusPtr p 24
-
-p'Mesh'tangents :: Ptr Mesh -> Ptr (Ptr CFloat)
-
-p'Mesh'colors p = plusPtr p 28
-
-p'Mesh'colors :: Ptr Mesh -> Ptr (Ptr CUChar)
-
-p'Mesh'indices p = plusPtr p 32
-
-p'Mesh'indices :: Ptr Mesh -> Ptr (Ptr CUShort)
-
-p'Mesh'animVertices p = plusPtr p 36
-
-p'Mesh'animVertices :: Ptr Mesh -> Ptr (Ptr CFloat)
-
-p'Mesh'animNormals p = plusPtr p 40
-
-p'Mesh'animNormals :: Ptr Mesh -> Ptr (Ptr CFloat)
-
-p'Mesh'boneIds p = plusPtr p 44
-
-p'Mesh'boneIds :: Ptr Mesh -> Ptr (Ptr CUChar)
-
-p'Mesh'boneWeights p = plusPtr p 48
-
-p'Mesh'boneWeights :: Ptr Mesh -> Ptr (Ptr CFloat)
-
-p'Mesh'vaoId p = plusPtr p 52
-
-p'Mesh'vaoId :: Ptr Mesh -> Ptr CUInt
-
-p'Mesh'vboId p = plusPtr p 56
-
-p'Mesh'vboId :: Ptr Mesh -> Ptr (Ptr CUInt)
-
-instance Storable Mesh where
-  sizeOf _ = 60
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    v4 <- peekByteOff _p 16
-    v5 <- peekByteOff _p 20
-    v6 <- peekByteOff _p 24
-    v7 <- peekByteOff _p 28
-    v8 <- peekByteOff _p 32
-    v9 <- peekByteOff _p 36
-    v10 <- peekByteOff _p 40
-    v11 <- peekByteOff _p 44
-    v12 <- peekByteOff _p 48
-    v13 <- peekByteOff _p 52
-    v14 <- peekByteOff _p 56
-    return $ Mesh v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14
-  poke _p (Mesh v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    pokeByteOff _p 16 v4
-    pokeByteOff _p 20 v5
-    pokeByteOff _p 24 v6
-    pokeByteOff _p 28 v7
-    pokeByteOff _p 32 v8
-    pokeByteOff _p 36 v9
-    pokeByteOff _p 40 v10
-    pokeByteOff _p 44 v11
-    pokeByteOff _p 48 v12
-    pokeByteOff _p 52 v13
-    pokeByteOff _p 56 v14
-    return ()
-
-{- typedef struct Shader {
-            unsigned int id; int * locs;
-        } Shader; -}
-data Shader = Shader
-  { shader'id :: CUInt,
-    shader'locs :: Ptr CInt
-  }
-  deriving (Eq, Show)
-
-p'Shader'id p = plusPtr p 0
-
-p'Shader'id :: Ptr Shader -> Ptr CUInt
-
-p'Shader'locs p = plusPtr p 4
-
-p'Shader'locs :: Ptr Shader -> Ptr (Ptr CInt)
-
-instance Storable Shader where
-  sizeOf _ = 8
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    return $ Shader v0 v1
-  poke _p (Shader v0 v1) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    return ()
-
-{- typedef struct MaterialMap {
-            Texture2D texture; Color color; float value;
-        } MaterialMap; -}
-data MaterialMap = MaterialMap
-  { materialmap'texture :: Texture,
-    materialmap'color :: Color,
-    materialmap'value :: CFloat
-  }
-  deriving (Eq, Show)
-
-p'MaterialMap'texture p = plusPtr p 0
-
-p'MaterialMap'texture :: Ptr MaterialMap -> Ptr Texture
-
-p'MaterialMap'color p = plusPtr p 20
-
-p'MaterialMap'color :: Ptr MaterialMap -> Ptr Color
-
-p'MaterialMap'value p = plusPtr p 24
-
-p'MaterialMap'value :: Ptr MaterialMap -> Ptr CFloat
-
-instance Storable MaterialMap where
-  sizeOf _ = 28
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 20
-    v2 <- peekByteOff _p 24
-    return $ MaterialMap v0 v1 v2
-  poke _p (MaterialMap v0 v1 v2) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 20 v1
-    pokeByteOff _p 24 v2
-    return ()
-
-{- typedef struct Material {
-            Shader shader; MaterialMap * maps; float params[4];
-        } Material; -}
-data Material = Material
-  { material'shader :: Shader,
-    material'maps :: Ptr MaterialMap,
-    material'params :: [CFloat]
-  }
-  deriving (Eq, Show)
-
-p'Material'shader p = plusPtr p 0
-
-p'Material'shader :: Ptr Material -> Ptr Shader
-
-p'Material'maps p = plusPtr p 8
-
-p'Material'maps :: Ptr Material -> Ptr (Ptr MaterialMap)
-
-p'Material'params p = plusPtr p 12
-
-p'Material'params :: Ptr Material -> Ptr CFloat
-
-instance Storable Material where
-  sizeOf _ = 28
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 8
-    v2 <- let s2 = div 16 $ sizeOf (undefined :: CFloat) in peekArray s2 (plusPtr _p 12)
-    return $ Material v0 v1 v2
-  poke _p (Material v0 v1 v2) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 8 v1
-    let s2 = div 16 $ sizeOf (undefined :: CFloat)
-    pokeArray (plusPtr _p 12) (take s2 v2)
-    return ()
-
-{- typedef struct Transform {
-            Vector3 translation; Quaternion rotation; Vector3 scale;
-        } Transform; -}
-data Transform = Transform
-  { transform'translation :: Vector3,
-    transform'rotation :: Vector4,
-    transform'scale :: Vector3
-  }
-  deriving (Eq, Show)
-
-p'Transform'translation p = plusPtr p 0
-
-p'Transform'translation :: Ptr Transform -> Ptr Vector3
-
-p'Transform'rotation p = plusPtr p 12
-
-p'Transform'rotation :: Ptr Transform -> Ptr Vector4
-
-p'Transform'scale p = plusPtr p 28
-
-p'Transform'scale :: Ptr Transform -> Ptr Vector3
-
-instance Storable Transform where
-  sizeOf _ = 40
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 12
-    v2 <- peekByteOff _p 28
-    return $ Transform v0 v1 v2
-  poke _p (Transform v0 v1 v2) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 12 v1
-    pokeByteOff _p 28 v2
-    return ()
-
-{- typedef struct BoneInfo {
-            char name[32]; int parent;
-        } BoneInfo; -}
-data BoneInfo = BoneInfo
-  { boneInfo'name :: [CChar],
-    boneinfo'parent :: CInt
-  }
-  deriving (Eq, Show)
-
-p'BoneInfo'name p = plusPtr p 0
-
-p'BoneInfo'name :: Ptr BoneInfo -> Ptr CChar
-
-p'BoneInfo'parent p = plusPtr p 32
-
-p'BoneInfo'parent :: Ptr BoneInfo -> Ptr CInt
-
-instance Storable BoneInfo where
-  sizeOf _ = 36
-  alignment _ = 4
-  peek _p = do
-    v0 <- let s0 = div 32 $ sizeOf (undefined :: CChar) in peekArray s0 (plusPtr _p 0)
-    v1 <- peekByteOff _p 32
-    return $ BoneInfo v0 v1
-  poke _p (BoneInfo v0 v1) = do
-    let s0 = div 32 $ sizeOf (undefined :: CChar)
-    pokeArray (plusPtr _p 0) (take s0 v0)
-    pokeByteOff _p 32 v1
-    return ()
-
-{- typedef struct Model {
-            Matrix transform;
-            int meshCount;
-            int materialCount;
-            Mesh * meshes;
-            Material * materials;
-            int * meshMaterial;
-            int boneCount;
-            BoneInfo * bones;
-            Transform * bindPose;
-        } Model; -}
-data Model = Model
-  { model'transform :: Matrix,
-    model'meshCount :: CInt,
-    model'materialCount :: CInt,
-    model'meshes :: Ptr Mesh,
-    model'materials :: Ptr Material,
-    model'meshMaterial :: Ptr CInt,
-    model'boneCount :: CInt,
-    model'bones :: Ptr BoneInfo,
-    model'bindPose :: Ptr Transform
-  }
-  deriving (Eq, Show)
-
-p'Model'transform p = plusPtr p 0
-
-p'Model'transform :: Ptr Model -> Ptr Matrix
-
-p'Model'meshCount p = plusPtr p 64
-
-p'Model'meshCount :: Ptr Model -> Ptr CInt
-
-p'Model'materialCount p = plusPtr p 68
-
-p'Model'materialCount :: Ptr Model -> Ptr CInt
-
-p'Model'meshes p = plusPtr p 72
-
-p'Model'meshes :: Ptr Model -> Ptr (Ptr Mesh)
-
-p'Model'materials p = plusPtr p 76
-
-p'Model'materials :: Ptr Model -> Ptr (Ptr Material)
-
-p'Model'meshMaterial p = plusPtr p 80
-
-p'Model'meshMaterial :: Ptr Model -> Ptr (Ptr CInt)
-
-p'Model'boneCount p = plusPtr p 84
-
-p'Model'boneCount :: Ptr Model -> Ptr CInt
-
-p'Model'bones p = plusPtr p 88
-
-p'Model'bones :: Ptr Model -> Ptr (Ptr BoneInfo)
-
-p'Model'bindPose p = plusPtr p 92
-
-p'Model'bindPose :: Ptr Model -> Ptr (Ptr Transform)
-
-instance Storable Model where
-  sizeOf _ = 96
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 64
-    v2 <- peekByteOff _p 68
-    v3 <- peekByteOff _p 72
-    v4 <- peekByteOff _p 76
-    v5 <- peekByteOff _p 80
-    v6 <- peekByteOff _p 84
-    v7 <- peekByteOff _p 88
-    v8 <- peekByteOff _p 92
-    return $ Model v0 v1 v2 v3 v4 v5 v6 v7 v8
-  poke _p (Model v0 v1 v2 v3 v4 v5 v6 v7 v8) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 64 v1
-    pokeByteOff _p 68 v2
-    pokeByteOff _p 72 v3
-    pokeByteOff _p 76 v4
-    pokeByteOff _p 80 v5
-    pokeByteOff _p 84 v6
-    pokeByteOff _p 88 v7
-    pokeByteOff _p 92 v8
-    return ()
-
-{- typedef struct ModelAnimation {
-            int boneCount;
-            int frameCount;
-            BoneInfo * bones;
-            Transform * * framePoses;
-        } ModelAnimation; -}
-data ModelAnimation = ModelAnimation
-  { modelAnimation'boneCount :: CInt,
-    modelAnimation'frameCount :: CInt,
-    modelAnimation'bones :: Ptr BoneInfo,
-    modelAnimation'framePoses :: Ptr (Ptr Transform)
-  }
-  deriving (Eq, Show)
-
-p'ModelAnimation'boneCount p = plusPtr p 0
-
-p'ModelAnimation'boneCount :: Ptr ModelAnimation -> Ptr CInt
-
-p'ModelAnimation'frameCount p = plusPtr p 4
-
-p'ModelAnimation'frameCount :: Ptr ModelAnimation -> Ptr CInt
-
-p'ModelAnimation'bones p = plusPtr p 8
-
-p'ModelAnimation'bones :: Ptr ModelAnimation -> Ptr (Ptr BoneInfo)
-
-p'ModelAnimation'framePoses p = plusPtr p 12
-
-p'ModelAnimation'framePoses :: Ptr ModelAnimation -> Ptr (Ptr (Ptr Transform))
-
-instance Storable ModelAnimation where
-  sizeOf _ = 16
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    return $ ModelAnimation v0 v1 v2 v3
-  poke _p (ModelAnimation v0 v1 v2 v3) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    return ()
-
-{- typedef struct Ray {
-            Vector3 position; Vector3 direction;
-        } Ray; -}
-data Ray = Ray
-  { ray'position :: Vector3,
-    ray'direction :: Vector3
-  }
-  deriving (Eq, Show)
-
-p'Ray'position p = plusPtr p 0
-
-p'Ray'position :: Ptr Ray -> Ptr Vector3
-
-p'Ray'direction p = plusPtr p 12
-
-p'Ray'direction :: Ptr Ray -> Ptr Vector3
-
-instance Storable Ray where
-  sizeOf _ = 24
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 12
-    return $ Ray v0 v1
-  poke _p (Ray v0 v1) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 12 v1
-    return ()
-
-{- typedef struct RayCollision {
-            _Bool hit; float distance; Vector3 point; Vector3 normal;
-        } RayCollision; -}
-data RayCollision = RayCollision
-  { rayCollision'hit :: CBool,
-    rayCollision'distance :: CFloat,
-    rayCollision'point :: Vector3,
-    rayCollision'normal :: Vector3
-  }
-  deriving (Eq, Show)
-
-p'RayCollision'hit p = plusPtr p 0
-
-p'RayCollision'hit :: Ptr RayCollision -> Ptr CBool
-
-p'RayCollision'distance p = plusPtr p 4
-
-p'RayCollision'distance :: Ptr RayCollision -> Ptr CFloat
-
-p'RayCollision'point p = plusPtr p 8
-
-p'RayCollision'point :: Ptr RayCollision -> Ptr Vector3
-
-p'RayCollision'normal p = plusPtr p 20
-
-p'RayCollision'normal :: Ptr RayCollision -> Ptr Vector3
-
-instance Storable RayCollision where
-  sizeOf _ = 32
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 20
-    return $ RayCollision v0 v1 v2 v3
-  poke _p (RayCollision v0 v1 v2 v3) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 20 v3
-    return ()
-
-{- typedef struct BoundingBox {
-            Vector3 min; Vector3 max;
-        } BoundingBox; -}
-data BoundingBox = BoundingBox
-  { boundingBox'min :: Vector3,
-    boundingBox'max :: Vector3
-  }
-  deriving (Eq, Show)
-
-p'BoundingBox'min p = plusPtr p 0
-
-p'BoundingBox'min :: Ptr BoundingBox -> Ptr Vector3
-
-p'BoundingBox'max p = plusPtr p 12
-
-p'BoundingBox'max :: Ptr BoundingBox -> Ptr Vector3
-
-instance Storable BoundingBox where
-  sizeOf _ = 24
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 12
-    return $ BoundingBox v0 v1
-  poke _p (BoundingBox v0 v1) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 12 v1
-    return ()
-
-{- typedef struct Wave {
-            unsigned int frameCount;
-            unsigned int sampleRate;
-            unsigned int sampleSize;
-            unsigned int channels;
-            void * data;
-        } Wave; -}
-data Wave = Wave
-  { wave'frameCount :: CUInt,
-    wave'sampleRate :: CUInt,
-    wave'sampleSize :: CUInt,
-    wave'channels :: CUInt,
-    wave'data :: Ptr ()
-  }
-  deriving (Eq, Show)
-
-p'Wave'frameCount p = plusPtr p 0
-
-p'Wave'frameCount :: Ptr Wave -> Ptr CUInt
-
-p'Wave'sampleRate p = plusPtr p 4
-
-p'Wave'sampleRate :: Ptr Wave -> Ptr CUInt
-
-p'Wave'sampleSize p = plusPtr p 8
-
-p'Wave'sampleSize :: Ptr Wave -> Ptr CUInt
-
-p'Wave'channels p = plusPtr p 12
-
-p'Wave'channels :: Ptr Wave -> Ptr CUInt
-
-p'Wave'data p = plusPtr p 16
-
-p'Wave'data :: Ptr Wave -> Ptr (Ptr ())
-
-instance Storable Wave where
-  sizeOf _ = 20
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    v4 <- peekByteOff _p 16
-    return $ Wave v0 v1 v2 v3 v4
-  poke _p (Wave v0 v1 v2 v3 v4) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    pokeByteOff _p 16 v4
-    return ()
-
-{- typedef struct rAudioBuffer rAudioBuffer; -}
-data RAudioBuffer = RAudioBuffer
-
-{- typedef struct rAudioProcessor rAudioProcessor; -}
-data RAudioProcessor = RAudioProcessor
-
-{- typedef struct AudioStream {
-            rAudioBuffer * buffer;
-            rAudioProcessor * processor;
-            unsigned int sampleRate;
-            unsigned int sampleSize;
-            unsigned int channels;
-        } AudioStream; -}
-data AudioStream = AudioStream
-  { audioStream'buffer :: Ptr RAudioBuffer,
-    audioStream'processor :: Ptr RAudioProcessor,
-    audioStream'sampleRate :: CUInt,
-    audioStream'sampleSize :: CUInt,
-    audiostream'channels :: CUInt
-  }
-  deriving (Eq, Show)
-
-p'AudioStream'buffer p = plusPtr p 0
-
-p'AudioStream'buffer :: Ptr AudioStream -> Ptr (Ptr RAudioBuffer)
-
-p'AudioStream'processor p = plusPtr p 4
-
-p'AudioStream'processor :: Ptr AudioStream -> Ptr (Ptr rAudioProcessor)
-
-p'AudioStream'sampleRate p = plusPtr p 8
-
-p'AudioStream'sampleRate :: Ptr AudioStream -> Ptr CUInt
-
-p'AudioStream'sampleSize p = plusPtr p 12
-
-p'AudioStream'sampleSize :: Ptr AudioStream -> Ptr CUInt
-
-p'AudioStream'channels p = plusPtr p 16
-
-p'AudioStream'channels :: Ptr AudioStream -> Ptr CUInt
-
-instance Storable AudioStream where
-  sizeOf _ = 20
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    v4 <- peekByteOff _p 16
-    return $ AudioStream v0 v1 v2 v3 v4
-  poke _p (AudioStream v0 v1 v2 v3 v4) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    pokeByteOff _p 16 v4
-    return ()
-
-{- typedef struct Sound {
-            AudioStream stream; unsigned int frameCount;
-        } Sound; -}
-data Sound = Sound
-  { sound'stream :: AudioStream,
-    sound'frameCount :: CUInt
-  }
-  deriving (Eq, Show)
-
-p'Sound'stream p = plusPtr p 0
-
-p'Sound'stream :: Ptr Sound -> Ptr AudioStream
-
-p'Sound'frameCount p = plusPtr p 20
-
-p'Sound'frameCount :: Ptr Sound -> Ptr CUInt
-
-instance Storable Sound where
-  sizeOf _ = 24
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 20
-    return $ Sound v0 v1
-  poke _p (Sound v0 v1) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 20 v1
-    return ()
-
-{- typedef struct Music {
-            AudioStream stream;
-            unsigned int frameCount;
-            _Bool looping;
-            int ctxType;
-            void * ctxData;
-        } Music; -}
-data Music = Music
-  { musistream :: AudioStream,
-    musiframeCount :: CUInt,
-    musilooping :: CInt,
-    musictxType :: CInt,
-    musictxData :: Ptr ()
-  }
-  deriving (Eq, Show)
-
-p'Musistream p = plusPtr p 0
-
-p'Musistream :: Ptr Music -> Ptr AudioStream
-
-p'MusiframeCount p = plusPtr p 20
-
-p'MusiframeCount :: Ptr Music -> Ptr CUInt
-
-p'Musilooping p = plusPtr p 24
-
-p'Musilooping :: Ptr Music -> Ptr CInt
-
-p'MusictxType p = plusPtr p 28
-
-p'MusictxType :: Ptr Music -> Ptr CInt
-
-p'MusictxData p = plusPtr p 32
-
-p'MusictxData :: Ptr Music -> Ptr (Ptr ())
-
-instance Storable Music where
-  sizeOf _ = 36
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 20
-    v2 <- peekByteOff _p 24
-    v3 <- peekByteOff _p 28
-    v4 <- peekByteOff _p 32
-    return $ Music v0 v1 v2 v3 v4
-  poke _p (Music v0 v1 v2 v3 v4) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 20 v1
-    pokeByteOff _p 24 v2
-    pokeByteOff _p 28 v3
-    pokeByteOff _p 32 v4
-    return ()
-
-{- typedef struct VrDeviceInfo {
-            int hResolution;
-            int vResolution;
-            float hScreenSize;
-            float vScreenSize;
-            float vScreenCenter;
-            float eyeToScreenDistance;
-            float lensSeparationDistance;
-            float interpupillaryDistance;
-            float lensDistortionValues[4];
-            float chromaAbCorrection[4];
-        } VrDeviceInfo; -}
-data VrDeviceInfo = VrDeviceInfo
-  { vrDeviceInfo'hResolution :: CInt,
-    vrDeviceInfo'vResolution :: CInt,
-    vrDeviceInfo'hScreenSize :: CFloat,
-    vrDeviceInfo'vScreenSize :: CFloat,
-    vrDeviceInfo'vScreenCenter :: CFloat,
-    vrDeviceInfo'eyeToScreenDistance :: CFloat,
-    vrDeviceInfo'lensSeparationDistance :: CFloat,
-    vrDeviceInfo'interpupillaryDistance :: CFloat,
-    vrDeviceInfo'lensDistortionValues :: [CFloat],
-    vrDeviceInfo'chromaAbCorrection :: [CFloat]
-  }
-  deriving (Eq, Show)
-
-p'VrDeviceInfo'hResolution p = plusPtr p 0
-
-p'VrDeviceInfo'hResolution :: Ptr VrDeviceInfo -> Ptr CInt
-
-p'VrDeviceInfo'vResolution p = plusPtr p 4
-
-p'VrDeviceInfo'vResolution :: Ptr VrDeviceInfo -> Ptr CInt
-
-p'VrDeviceInfo'hScreenSize p = plusPtr p 8
-
-p'VrDeviceInfo'hScreenSize :: Ptr VrDeviceInfo -> Ptr CFloat
-
-p'VrDeviceInfo'vScreenSize p = plusPtr p 12
-
-p'VrDeviceInfo'vScreenSize :: Ptr VrDeviceInfo -> Ptr CFloat
-
-p'VrDeviceInfo'vScreenCenter p = plusPtr p 16
-
-p'VrDeviceInfo'vScreenCenter :: Ptr VrDeviceInfo -> Ptr CFloat
-
-p'VrDeviceInfo'eyeToScreenDistance p = plusPtr p 20
-
-p'VrDeviceInfo'eyeToScreenDistance :: Ptr VrDeviceInfo -> Ptr CFloat
-
-p'VrDeviceInfo'lensSeparationDistance p = plusPtr p 24
-
-p'VrDeviceInfo'lensSeparationDistance :: Ptr VrDeviceInfo -> Ptr CFloat
-
-p'VrDeviceInfo'interpupillaryDistance p = plusPtr p 28
-
-p'VrDeviceInfo'interpupillaryDistance :: Ptr VrDeviceInfo -> Ptr CFloat
-
-p'VrDeviceInfo'lensDistortionValues p = plusPtr p 32
-
-p'VrDeviceInfo'lensDistortionValues :: Ptr VrDeviceInfo -> Ptr CFloat
-
-p'VrDeviceInfo'chromaAbCorrection p = plusPtr p 48
-
-p'VrDeviceInfo'chromaAbCorrection :: Ptr VrDeviceInfo -> Ptr CFloat
-
-instance Storable VrDeviceInfo where
-  sizeOf _ = 64
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    v3 <- peekByteOff _p 12
-    v4 <- peekByteOff _p 16
-    v5 <- peekByteOff _p 20
-    v6 <- peekByteOff _p 24
-    v7 <- peekByteOff _p 28
-    v8 <- let s8 = div 16 $ sizeOf (undefined :: CFloat) in peekArray s8 (plusPtr _p 32)
-    v9 <- let s9 = div 16 $ sizeOf (undefined :: CFloat) in peekArray s9 (plusPtr _p 48)
-    return $ VrDeviceInfo v0 v1 v2 v3 v4 v5 v6 v7 v8 v9
-  poke _p (VrDeviceInfo v0 v1 v2 v3 v4 v5 v6 v7 v8 v9) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    pokeByteOff _p 12 v3
-    pokeByteOff _p 16 v4
-    pokeByteOff _p 20 v5
-    pokeByteOff _p 24 v6
-    pokeByteOff _p 28 v7
-    let s8 = div 16 $ sizeOf (undefined :: CFloat)
-    pokeArray (plusPtr _p 32) (take s8 v8)
-    let s9 = div 16 $ sizeOf (undefined :: CFloat)
-    pokeArray (plusPtr _p 48) (take s9 v9)
-    return ()
-
-{- typedef struct VrStereoConfig {
-            Matrix projection[2];
-            Matrix viewOffset[2];
-            float leftLensCenter[2];
-            float rightLensCenter[2];
-            float leftScreenCenter[2];
-            float rightScreenCenter[2];
-            float scale[2];
-            float scaleIn[2];
-        } VrStereoConfig; -}
-data VrStereoConfig = VrStereoConfig
-  { vrStereoConfig'projection :: [Matrix],
-    vrStereoConfig'viewOffset :: [Matrix],
-    vrStereoConfig'leftLensCenter :: [CFloat],
-    vrStereoConfig'rightLensCenter :: [CFloat],
-    vrStereoConfig'leftScreenCenter :: [CFloat],
-    vrStereoConfig'rightScreenCenter :: [CFloat],
-    vrStereoConfig'scale :: [CFloat],
-    vrStereoConfig'scaleIn :: [CFloat]
-  }
-  deriving (Eq, Show)
-
-p'VrStereoConfig'projection p = plusPtr p 0
-
-p'VrStereoConfig'projection :: Ptr VrStereoConfig -> Ptr Matrix
-
-p'VrStereoConfig'viewOffset p = plusPtr p 128
-
-p'VrStereoConfig'viewOffset :: Ptr VrStereoConfig -> Ptr Matrix
-
-p'VrStereoConfig'leftLensCenter p = plusPtr p 256
-
-p'VrStereoConfig'leftLensCenter :: Ptr VrStereoConfig -> Ptr CFloat
-
-p'VrStereoConfig'rightLensCenter p = plusPtr p 264
-
-p'VrStereoConfig'rightLensCenter :: Ptr VrStereoConfig -> Ptr CFloat
-
-p'VrStereoConfig'leftScreenCenter p = plusPtr p 272
-
-p'VrStereoConfig'leftScreenCenter :: Ptr VrStereoConfig -> Ptr CFloat
-
-p'VrStereoConfig'rightScreenCenter p = plusPtr p 280
-
-p'VrStereoConfig'rightScreenCenter :: Ptr VrStereoConfig -> Ptr CFloat
-
-p'VrStereoConfig'scale p = plusPtr p 288
-
-p'VrStereoConfig'scale :: Ptr VrStereoConfig -> Ptr CFloat
-
-p'VrStereoConfig'scaleIn p = plusPtr p 296
-
-p'VrStereoConfig'scaleIn :: Ptr VrStereoConfig -> Ptr CFloat
-
-instance Storable VrStereoConfig where
-  sizeOf _ = 304
-  alignment _ = 4
-  peek _p = do
-    v0 <- let s0 = div 128 $ sizeOf (undefined :: Matrix) in peekArray s0 (plusPtr _p 0)
-    v1 <- let s1 = div 128 $ sizeOf (undefined :: Matrix) in peekArray s1 (plusPtr _p 128)
-    v2 <- let s2 = div 8 $ sizeOf (undefined :: CFloat) in peekArray s2 (plusPtr _p 256)
-    v3 <- let s3 = div 8 $ sizeOf (undefined :: CFloat) in peekArray s3 (plusPtr _p 264)
-    v4 <- let s4 = div 8 $ sizeOf (undefined :: CFloat) in peekArray s4 (plusPtr _p 272)
-    v5 <- let s5 = div 8 $ sizeOf (undefined :: CFloat) in peekArray s5 (plusPtr _p 280)
-    v6 <- let s6 = div 8 $ sizeOf (undefined :: CFloat) in peekArray s6 (plusPtr _p 288)
-    v7 <- let s7 = div 8 $ sizeOf (undefined :: CFloat) in peekArray s7 (plusPtr _p 296)
-    return $ VrStereoConfig v0 v1 v2 v3 v4 v5 v6 v7
-  poke _p (VrStereoConfig v0 v1 v2 v3 v4 v5 v6 v7) = do
-    let s0 = div 128 $ sizeOf (undefined :: Matrix)
-    pokeArray (plusPtr _p 0) (take s0 v0)
-    let s1 = div 128 $ sizeOf (undefined :: Matrix)
-    pokeArray (plusPtr _p 128) (take s1 v1)
-    let s2 = div 8 $ sizeOf (undefined :: CFloat)
-    pokeArray (plusPtr _p 256) (take s2 v2)
-    let s3 = div 8 $ sizeOf (undefined :: CFloat)
-    pokeArray (plusPtr _p 264) (take s3 v3)
-    let s4 = div 8 $ sizeOf (undefined :: CFloat)
-    pokeArray (plusPtr _p 272) (take s4 v4)
-    let s5 = div 8 $ sizeOf (undefined :: CFloat)
-    pokeArray (plusPtr _p 280) (take s5 v5)
-    let s6 = div 8 $ sizeOf (undefined :: CFloat)
-    pokeArray (plusPtr _p 288) (take s6 v6)
-    let s7 = div 8 $ sizeOf (undefined :: CFloat)
-    pokeArray (plusPtr _p 296) (take s7 v7)
-    return ()
-
-{- typedef struct FilePathList {
-            unsigned int capacity; unsigned int count; char * * paths;
-        } FilePathList; -}
-data FilePathList = FilePathList
-  { filePathlist'capacity :: CUInt,
-    filePathlist'count :: CUInt,
-    filePathList'paths :: Ptr CString
-  }
-  deriving (Eq, Show)
-
-p'FilePathList'capacity p = plusPtr p 0
-
-p'FilePathList'capacity :: Ptr FilePathList -> Ptr CUInt
-
-p'FilePathList'count p = plusPtr p 4
-
-p'FilePathList'count :: Ptr FilePathList -> Ptr CUInt
-
-p'FilePathList'paths p = plusPtr p 8
-
-p'FilePathList'paths :: Ptr FilePathList -> Ptr (Ptr CString)
-
-instance Storable FilePathList where
-  sizeOf _ = 12
-  alignment _ = 4
-  peek _p = do
-    v0 <- peekByteOff _p 0
-    v1 <- peekByteOff _p 4
-    v2 <- peekByteOff _p 8
-    return $ FilePathList v0 v1 v2
-  poke _p (FilePathList v0 v1 v2) = do
-    pokeByteOff _p 0 v0
-    pokeByteOff _p 4 v1
-    pokeByteOff _p 8 v2
-    return ()
+{-# LANGUAGE DeriveAnyClass #-}
+
+module Raylib.Types where
+
+-- This file includes Haskell counterparts to the structs defined in raylib
+
+-- This file includes Haskell counterparts to the structs defined in raylib
+
+import Control.Monad (forM_, unless)
+import Foreign
+  ( FunPtr,
+    Ptr,
+    Storable (alignment, peek, peekByteOff, poke, pokeByteOff, sizeOf),
+    Word16,
+    Word8,
+    castPtr,
+    fromBool,
+    malloc,
+    newArray,
+    newForeignPtr,
+    nullFunPtr,
+    nullPtr,
+    peekArray,
+    toBool,
+    withForeignPtr,
+  )
+import Foreign.C
+  ( CBool,
+    CChar,
+    CFloat,
+    CInt (..),
+    CShort,
+    CString,
+    CUChar,
+    CUInt,
+    CUShort,
+    castCharToCChar,
+    newCString,
+    peekCString,
+  )
+import Foreign.C.String (castCCharToChar)
+import GHC.IO (unsafePerformIO)
+import Raylib.Internal (c'rlGetShaderIdDefault)
+import Raylib.Util (Freeable (rlFreeDependents), c'free, freeMaybePtr, newMaybeArray, p'free, peekMaybeArray, peekStaticArray, peekStaticArrayOff, pokeMaybeOff, pokeStaticArray, pokeStaticArrayOff, rightPad, rlFreeArray)
+
+-- Necessary functions
+foreign import ccall safe "raylib.h GetPixelDataSize"
+  c'getPixelDataSize ::
+    CInt -> CInt -> CInt -> IO CInt
+
+getPixelDataSize :: Int -> Int -> PixelFormat -> Int
+getPixelDataSize width height format = unsafePerformIO (fromIntegral <$> c'getPixelDataSize (fromIntegral width) (fromIntegral height) (fromIntegral $ fromEnum format))
+
+foreign import ccall safe "raylib.h &GetPixelDataSize"
+  p'getPixelDataSize ::
+    FunPtr (CInt -> CInt -> CInt -> IO CInt)
+
+------------------------------------------------
+-- Raylib enumerations -------------------------
+------------------------------------------------
+
+data ConfigFlag
+  = VsyncHint
+  | FullscreenMode
+  | WindowResizable
+  | WindowUndecorated
+  | WindowHidden
+  | WindowMinimized
+  | WindowMaximized
+  | WindowUnfocused
+  | WindowTopmost
+  | WindowAlwaysRun
+  | WindowTransparent
+  | WindowHighdpi
+  | WindowMousePassthrough
+  | Msaa4xHint
+  | InterlacedHint
+  deriving (Eq, Show, Freeable)
+
+instance Enum ConfigFlag where
+  fromEnum g = case g of
+    VsyncHint -> 64
+    FullscreenMode -> 2
+    WindowResizable -> 4
+    WindowUndecorated -> 8
+    WindowHidden -> 128
+    WindowMinimized -> 512
+    WindowMaximized -> 1024
+    WindowUnfocused -> 2048
+    WindowTopmost -> 4096
+    WindowAlwaysRun -> 256
+    WindowTransparent -> 16
+    WindowHighdpi -> 8192
+    WindowMousePassthrough -> 16384
+    Msaa4xHint -> 32
+    InterlacedHint -> 65536
+  toEnum x = case x of
+    64 -> VsyncHint
+    2 -> FullscreenMode
+    4 -> WindowResizable
+    8 -> WindowUndecorated
+    128 -> WindowHidden
+    512 -> WindowMinimized
+    1024 -> WindowMaximized
+    2048 -> WindowUnfocused
+    4096 -> WindowTopmost
+    256 -> WindowAlwaysRun
+    16 -> WindowTransparent
+    8192 -> WindowHighdpi
+    16384 -> WindowMousePassthrough
+    32 -> Msaa4xHint
+    65536 -> InterlacedHint
+    n -> error $ "(ConfigFlag.toEnum) Invalid value: " ++ show n
+
+data TraceLogLevel = LogAll | LogTrace | LogDebug | LogInfo | LogWarning | LogError | LogFatal | LogNone
+  deriving (Eq, Show, Enum)
+
+data KeyboardKey
+  = KeyNull
+  | KeyApostrophe
+  | KeyComma
+  | KeyMinus
+  | KeyPeriod
+  | KeySlash
+  | KeyZero
+  | KeyOne
+  | KeyTwo
+  | KeyThree
+  | KeyFour
+  | KeyFive
+  | KeySix
+  | KeySeven
+  | KeyEight
+  | KeyNine
+  | KeySemicolon
+  | KeyEqual
+  | KeyA
+  | KeyB
+  | KeyC
+  | KeyD
+  | KeyE
+  | KeyF
+  | KeyG
+  | KeyH
+  | KeyI
+  | KeyJ
+  | KeyK
+  | KeyL
+  | KeyM
+  | KeyN
+  | KeyO
+  | KeyP
+  | KeyQ
+  | KeyR
+  | KeyS
+  | KeyT
+  | KeyU
+  | KeyV
+  | KeyW
+  | KeyX
+  | KeyY
+  | KeyZ
+  | KeyLeftBracket
+  | KeyBackslash
+  | KeyRightBracket
+  | KeyGrave
+  | KeySpace
+  | KeyEscape
+  | KeyEnter
+  | KeyTab
+  | KeyBackspace
+  | KeyInsert
+  | KeyDelete
+  | KeyRight
+  | KeyLeft
+  | KeyDown
+  | KeyUp
+  | KeyPageUp
+  | KeyPageDown
+  | KeyHome
+  | KeyEnd
+  | KeyCapsLock
+  | KeyScrollLock
+  | KeyNumLock
+  | KeyPrintScreen
+  | KeyPause
+  | KeyF1
+  | KeyF2
+  | KeyF3
+  | KeyF4
+  | KeyF5
+  | KeyF6
+  | KeyF7
+  | KeyF8
+  | KeyF9
+  | KeyF10
+  | KeyF11
+  | KeyF12
+  | KeyLeftShift
+  | KeyLeftControl
+  | KeyLeftAlt
+  | KeyLeftSuper
+  | KeyRightShift
+  | KeyRightControl
+  | KeyRightAlt
+  | KeyRightSuper
+  | KeyKbMenu
+  | KeyKp0
+  | KeyKp1
+  | KeyKp2
+  | KeyKp3
+  | KeyKp4
+  | KeyKp5
+  | KeyKp6
+  | KeyKp7
+  | KeyKp8
+  | KeyKp9
+  | KeyKpDecimal
+  | KeyKpDivide
+  | KeyKpMultiply
+  | KeyKpSubtract
+  | KeyKpAdd
+  | KeyKpEnter
+  | KeyKpEqual
+  | KeyBack
+  | KeyMenu
+  | KeyVolumeUp
+  | KeyVolumeDown
+  deriving (Eq, Show)
+
+instance Enum KeyboardKey where
+  fromEnum k = case k of
+    KeyNull -> 0
+    KeyApostrophe -> 39
+    KeyComma -> 44
+    KeyMinus -> 45
+    KeyPeriod -> 46
+    KeySlash -> 47
+    KeyZero -> 48
+    KeyOne -> 49
+    KeyTwo -> 50
+    KeyThree -> 51
+    KeyFour -> 52
+    KeyFive -> 53
+    KeySix -> 54
+    KeySeven -> 55
+    KeyEight -> 56
+    KeyNine -> 57
+    KeySemicolon -> 59
+    KeyEqual -> 61
+    KeyA -> 65
+    KeyB -> 66
+    KeyC -> 67
+    KeyD -> 68
+    KeyE -> 69
+    KeyF -> 70
+    KeyG -> 71
+    KeyH -> 72
+    KeyI -> 73
+    KeyJ -> 74
+    KeyK -> 75
+    KeyL -> 76
+    KeyM -> 77
+    KeyN -> 78
+    KeyO -> 79
+    KeyP -> 80
+    KeyQ -> 81
+    KeyR -> 82
+    KeyS -> 83
+    KeyT -> 84
+    KeyU -> 85
+    KeyV -> 86
+    KeyW -> 87
+    KeyX -> 88
+    KeyY -> 89
+    KeyZ -> 90
+    KeyLeftBracket -> 91
+    KeyBackslash -> 92
+    KeyRightBracket -> 93
+    KeyGrave -> 96
+    KeySpace -> 32
+    KeyEscape -> 256
+    KeyEnter -> 257
+    KeyTab -> 258
+    KeyBackspace -> 259
+    KeyInsert -> 260
+    KeyDelete -> 261
+    KeyRight -> 262
+    KeyLeft -> 263
+    KeyDown -> 264
+    KeyUp -> 265
+    KeyPageUp -> 266
+    KeyPageDown -> 267
+    KeyHome -> 268
+    KeyEnd -> 269
+    KeyCapsLock -> 280
+    KeyScrollLock -> 281
+    KeyNumLock -> 282
+    KeyPrintScreen -> 283
+    KeyPause -> 284
+    KeyF1 -> 290
+    KeyF2 -> 291
+    KeyF3 -> 292
+    KeyF4 -> 293
+    KeyF5 -> 294
+    KeyF6 -> 295
+    KeyF7 -> 296
+    KeyF8 -> 297
+    KeyF9 -> 298
+    KeyF10 -> 299
+    KeyF11 -> 300
+    KeyF12 -> 301
+    KeyLeftShift -> 340
+    KeyLeftControl -> 341
+    KeyLeftAlt -> 342
+    KeyLeftSuper -> 343
+    KeyRightShift -> 344
+    KeyRightControl -> 345
+    KeyRightAlt -> 346
+    KeyRightSuper -> 347
+    KeyKbMenu -> 348
+    KeyKp0 -> 320
+    KeyKp1 -> 321
+    KeyKp2 -> 322
+    KeyKp3 -> 323
+    KeyKp4 -> 324
+    KeyKp5 -> 325
+    KeyKp6 -> 326
+    KeyKp7 -> 327
+    KeyKp8 -> 328
+    KeyKp9 -> 329
+    KeyKpDecimal -> 330
+    KeyKpDivide -> 331
+    KeyKpMultiply -> 332
+    KeyKpSubtract -> 333
+    KeyKpAdd -> 334
+    KeyKpEnter -> 335
+    KeyKpEqual -> 336
+    -- Android buttons
+    KeyBack -> 4
+    KeyMenu -> 82
+    KeyVolumeUp -> 24
+    KeyVolumeDown -> 25
+
+  toEnum n = case n of
+    0 -> KeyNull
+    39 -> KeyApostrophe
+    44 -> KeyComma
+    45 -> KeyMinus
+    46 -> KeyPeriod
+    47 -> KeySlash
+    48 -> KeyZero
+    49 -> KeyOne
+    50 -> KeyTwo
+    51 -> KeyThree
+    52 -> KeyFour
+    53 -> KeyFive
+    54 -> KeySix
+    55 -> KeySeven
+    56 -> KeyEight
+    57 -> KeyNine
+    59 -> KeySemicolon
+    61 -> KeyEqual
+    65 -> KeyA
+    66 -> KeyB
+    67 -> KeyC
+    68 -> KeyD
+    69 -> KeyE
+    70 -> KeyF
+    71 -> KeyG
+    72 -> KeyH
+    73 -> KeyI
+    74 -> KeyJ
+    75 -> KeyK
+    76 -> KeyL
+    77 -> KeyM
+    78 -> KeyN
+    79 -> KeyO
+    80 -> KeyP
+    81 -> KeyQ
+    82 -> KeyR
+    83 -> KeyS
+    84 -> KeyT
+    85 -> KeyU
+    86 -> KeyV
+    87 -> KeyW
+    88 -> KeyX
+    89 -> KeyY
+    90 -> KeyZ
+    91 -> KeyLeftBracket
+    92 -> KeyBackslash
+    93 -> KeyRightBracket
+    96 -> KeyGrave
+    32 -> KeySpace
+    256 -> KeyEscape
+    257 -> KeyEnter
+    258 -> KeyTab
+    259 -> KeyBackspace
+    260 -> KeyInsert
+    261 -> KeyDelete
+    262 -> KeyRight
+    263 -> KeyLeft
+    264 -> KeyDown
+    265 -> KeyUp
+    266 -> KeyPageUp
+    267 -> KeyPageDown
+    268 -> KeyHome
+    269 -> KeyEnd
+    280 -> KeyCapsLock
+    281 -> KeyScrollLock
+    282 -> KeyNumLock
+    283 -> KeyPrintScreen
+    284 -> KeyPause
+    290 -> KeyF1
+    291 -> KeyF2
+    292 -> KeyF3
+    293 -> KeyF4
+    294 -> KeyF5
+    295 -> KeyF6
+    296 -> KeyF7
+    297 -> KeyF8
+    298 -> KeyF9
+    299 -> KeyF10
+    300 -> KeyF11
+    301 -> KeyF12
+    340 -> KeyLeftShift
+    341 -> KeyLeftControl
+    342 -> KeyLeftAlt
+    343 -> KeyLeftSuper
+    344 -> KeyRightShift
+    345 -> KeyRightControl
+    346 -> KeyRightAlt
+    347 -> KeyRightSuper
+    348 -> KeyKbMenu
+    320 -> KeyKp0
+    321 -> KeyKp1
+    322 -> KeyKp2
+    323 -> KeyKp3
+    324 -> KeyKp4
+    325 -> KeyKp5
+    326 -> KeyKp6
+    327 -> KeyKp7
+    328 -> KeyKp8
+    329 -> KeyKp9
+    330 -> KeyKpDecimal
+    331 -> KeyKpDivide
+    332 -> KeyKpMultiply
+    333 -> KeyKpSubtract
+    334 -> KeyKpAdd
+    335 -> KeyKpEnter
+    336 -> KeyKpEqual
+    -- Android buttons
+    4 -> KeyBack
+    --  82  -> KeyMenu
+    24 -> KeyVolumeUp
+    25 -> KeyVolumeDown
+    x -> error $ "(KeyboardKey.toEnum) Invalid value: " ++ show x
+
+data MouseButton
+  = MouseButtonLeft
+  | MouseButtonRight
+  | MouseButtonMiddle
+  | MouseButtonSide
+  | MouseButtonExtra
+  | MouseButtonForward
+  | MouseButtonBack
+  deriving (Eq, Show, Enum)
+
+data MouseCursor
+  = MouseCursorDefault
+  | MouseCursorArrow
+  | MouseCursorIbeam
+  | MouseCursorCrosshair
+  | MouseCursorPointingHand
+  | MouseCursorResizeEW
+  | MouseCursorResizeNS
+  | MouseCursorResizeNWSE
+  | MouseCursorResizeNESW
+  | MouseCursorResizeAll
+  | MouseCursorNotAllowed
+  deriving (Eq, Show, Enum)
+
+data GamepadButton
+  = GamepadButtonUnknown
+  | GamepadButtonUnknownLeftFaceUp
+  | GamepadButtonLeftFaceRight
+  | GamepadButtonLeftFaceDown
+  | GamepadButtonLeftFaceLeft
+  | GamepadButtonRightFaceUp
+  | GamepadButtonRightFaceRight
+  | GamepadButtonRightFaceDown
+  | GamepadButtonRightFaceLeft
+  | GamepadButtonLeftTrigger1
+  | GamepadButtonLeftTrigger2
+  | GamepadButtonRightTrigger1
+  | GamepadButtonRightTrigger2
+  | GamepadButtonMiddleLeft
+  | GamepadButtonMiddle
+  | GamepadButtonMiddleRight
+  | GamepadButtonLeftThumb
+  | GamepadButtonRightThumb
+  deriving (Eq, Show, Enum)
+
+data GamepadAxis
+  = GamepadAxisLeftX
+  | GamepadAxisLeftY
+  | GamepadAxisRightX
+  | GamepadAxisRightY
+  | GamepadAxisLeftTrigger
+  | GamepadAxisRightTrigger
+  deriving (Eq, Show, Enum)
+
+data MaterialMapIndex
+  = MaterialMapAlbedo
+  | MaterialMapMetalness
+  | MaterialMapNormal
+  | MaterialMapRoughness
+  | MaterialMapOcclusion
+  | MaterialMapEmission
+  | MaterialMapHeight
+  | MaterialMapCubemap
+  | MaterialMapIrradiance
+  | MaterialMapPrefilter
+  | MaterialMapBrdf
+  deriving (Eq, Show, Enum)
+
+data ShaderLocationIndex
+  = ShaderLocVertexPosition
+  | ShaderLocVertexTexcoord01
+  | ShaderLocVertexTexcoord02
+  | ShaderLocVertexNormal
+  | ShaderLocVertexTangent
+  | ShaderLocVertexColor
+  | ShaderLocMatrixMvp
+  | ShaderLocMatrixView
+  | ShaderLocMatrixProjection
+  | ShaderLocMatrixModel
+  | ShaderLocMatrixNormal
+  | ShaderLocVectorView
+  | ShaderLocColorDiffuse
+  | ShaderLocColorSpecular
+  | ShaderLocColorAmbient
+  | ShaderLocMapAlbedo
+  | ShaderLocMapMetalness
+  | ShaderLocMapNormal
+  | ShaderLocMapRoughness
+  | ShaderLocMapOcclusion
+  | ShaderLocMapEmission
+  | ShaderLocMapHeight
+  | ShaderLocMapCubemap
+  | ShaderLocMapIrradiance
+  | ShaderLocMapPrefilter
+  | ShaderLocMapBrdf
+  deriving (Eq, Show, Enum)
+
+data ShaderUniformDataType
+  = ShaderUniformFloat
+  | ShaderUniformVec2
+  | ShaderUniformVec3
+  | ShaderUniformVec4
+  | ShaderUniformInt
+  | ShaderUniformIvec2
+  | ShaderUniformIvec3
+  | ShaderUniformIvec4
+  | ShaderUniformSampler2d
+  deriving (Eq, Show, Enum)
+
+-- I genuinely have no idea where this is used.
+data ShaderAttributeDataType
+  = ShaderAttribFloat
+  | ShaderAttribVec2
+  | ShaderAttribVec3
+  | ShaderAttribVec4
+  deriving (Eq, Show, Enum)
+
+data PixelFormat
+  = PixelFormatUnset
+  | PixelFormatUncompressedGrayscale
+  | PixelFormatUncompressedGrayAlpha
+  | PixelFormatUncompressedR5G6B5
+  | PixelFormatUncompressedR8G8B8
+  | PixelFormatUncompressedR5G5B5A1
+  | PixelFormatUncompressedR4G4B4A4
+  | PixelFormatUncompressedR8G8B8A8
+  | PixelFormatUncompressedR32
+  | PixelFormatUncompressedR32G32B32
+  | PixelFormatUncompressedR32G32B32A32
+  | PixelFormatCompressedDxt1Rgb
+  | PixelFormatCompressedDxt1Rgba
+  | PixelFormatCompressedDxt3Rgba
+  | PixelFormatCompressedDxt5Rgba
+  | PixelFormatCompressedEtc1Rgb
+  | PixelFormatCompressedEtc2Rgb
+  | PixelFormatCompressedEtc2EacRgba
+  | PixelFormatCompressedPvrtRgb
+  | PixelFormatCompressedPvrtRgba
+  | PixelFormatCompressedAstc4x4Rgba
+  | PixelFormatCompressedAstc8x8Rgba
+  deriving (Eq, Show)
+
+instance Storable PixelFormat where
+  sizeOf _ = 4
+  alignment _ = 4
+  peek ptr = do
+    val <- peek (castPtr ptr :: Ptr CInt)
+    return (toEnum $ fromIntegral val)
+  poke ptr v = do
+    poke (castPtr ptr) (fromIntegral (fromEnum v) :: CInt)
+
+instance Enum PixelFormat where
+  fromEnum n = case n of
+    PixelFormatUnset -> 0
+    PixelFormatUncompressedGrayscale -> 1
+    PixelFormatUncompressedGrayAlpha -> 2
+    PixelFormatUncompressedR5G6B5 -> 3
+    PixelFormatUncompressedR8G8B8 -> 4
+    PixelFormatUncompressedR5G5B5A1 -> 5
+    PixelFormatUncompressedR4G4B4A4 -> 6
+    PixelFormatUncompressedR8G8B8A8 -> 7
+    PixelFormatUncompressedR32 -> 8
+    PixelFormatUncompressedR32G32B32 -> 9
+    PixelFormatUncompressedR32G32B32A32 -> 10
+    PixelFormatCompressedDxt1Rgb -> 11
+    PixelFormatCompressedDxt1Rgba -> 12
+    PixelFormatCompressedDxt3Rgba -> 13
+    PixelFormatCompressedDxt5Rgba -> 14
+    PixelFormatCompressedEtc1Rgb -> 15
+    PixelFormatCompressedEtc2Rgb -> 16
+    PixelFormatCompressedEtc2EacRgba -> 17
+    PixelFormatCompressedPvrtRgb -> 18
+    PixelFormatCompressedPvrtRgba -> 19
+    PixelFormatCompressedAstc4x4Rgba -> 20
+    PixelFormatCompressedAstc8x8Rgba -> 21
+
+  toEnum n = case n of
+    0 -> PixelFormatUnset
+    1 -> PixelFormatUncompressedGrayscale
+    2 -> PixelFormatUncompressedGrayAlpha
+    3 -> PixelFormatUncompressedR5G6B5
+    4 -> PixelFormatUncompressedR8G8B8
+    5 -> PixelFormatUncompressedR5G5B5A1
+    6 -> PixelFormatUncompressedR4G4B4A4
+    7 -> PixelFormatUncompressedR8G8B8A8
+    8 -> PixelFormatUncompressedR32
+    9 -> PixelFormatUncompressedR32G32B32
+    10 -> PixelFormatUncompressedR32G32B32A32
+    11 -> PixelFormatCompressedDxt1Rgb
+    12 -> PixelFormatCompressedDxt1Rgba
+    13 -> PixelFormatCompressedDxt3Rgba
+    14 -> PixelFormatCompressedDxt5Rgba
+    15 -> PixelFormatCompressedEtc1Rgb
+    16 -> PixelFormatCompressedEtc2Rgb
+    17 -> PixelFormatCompressedEtc2EacRgba
+    18 -> PixelFormatCompressedPvrtRgb
+    19 -> PixelFormatCompressedPvrtRgba
+    20 -> PixelFormatCompressedAstc4x4Rgba
+    21 -> PixelFormatCompressedAstc8x8Rgba
+    _ -> error $ "(PixelFormat.toEnum) Invalid value: " ++ show n
+
+data TextureFilter
+  = TextureFilterPoint
+  | TextureFilterBilinear
+  | TextureFilterTrilinear
+  | TextureFilterAnisotropic4x
+  | TextureFilterAnisotropic8x
+  | TextureFilterAnisotropic16x
+  deriving (Enum)
+
+data TextureWrap
+  = TextureWrapRepeat
+  | TextureWrapClamp
+  | TextureWrapMirrorRepeat
+  | TextureWrapMirrorClamp
+  deriving (Enum)
+
+data CubemapLayout
+  = CubemapLayoutAutoDetect
+  | CubemapLayoutLineVertical
+  | CubemapLayoutLineHorizontal
+  | CubemapLayoutCrossThreeByFour
+  | CubemapLayoutCrossThreeByThree
+  | CubemapLayoutPanorama
+  deriving (Enum)
+
+data FontType = FontDefault | FontBitmap | FontSDF deriving (Enum)
+
+data BlendMode
+  = BlendAlpha
+  | BlendAdditive
+  | BlendMultiplied
+  | BlendAddColors
+  | BlendSubtractColors
+  | BlendAlphaPremultiply
+  | BlendCustom
+  | BlendCustomSeparate
+  deriving (Enum)
+
+data Gesture
+  = GestureNone
+  | GestureTap
+  | GestureDoubleTap
+  | GestureHold
+  | GestureDrag
+  | GestureSwipeRight
+  | GestureSwipeLeft
+  | GestureSwipeUp
+  | GestureSwipeDown
+  | GesturePinchIn
+  | GesturePinchOut
+  deriving (Show)
+
+-- NOTE: This is not the ideal solution, I need to make this unjanky
+instance Enum Gesture where
+  fromEnum n = case n of
+    GestureNone -> 0
+    GestureTap -> 1
+    GestureDoubleTap -> 2
+    GestureHold -> 4
+    GestureDrag -> 8
+    GestureSwipeRight -> 16
+    GestureSwipeLeft -> 32
+    GestureSwipeUp -> 64
+    GestureSwipeDown -> 128
+    GesturePinchIn -> 256
+    GesturePinchOut -> 512
+  toEnum n = case n of
+    0 -> GestureNone
+    1 -> GestureTap
+    2 -> GestureDoubleTap
+    4 -> GestureHold
+    8 -> GestureDrag
+    16 -> GestureSwipeRight
+    32 -> GestureSwipeLeft
+    64 -> GestureSwipeUp
+    128 -> GestureSwipeDown
+    256 -> GesturePinchIn
+    512 -> GesturePinchOut
+    _ -> error $ "(Gesture.toEnum) Invalid value: " ++ show n
+
+data CameraMode
+  = CameraModeCustom
+  | CameraModeFree
+  | CameraModeOrbital
+  | CameraModeFirstPerson
+  | CameraModeThirdPerson
+  deriving (Enum)
+
+data CameraProjection = CameraPerspective | CameraOrthographic deriving (Eq, Show, Enum)
+
+instance Storable CameraProjection where
+  sizeOf _ = 4
+  alignment _ = 4
+  peek ptr = do
+    val <- peek (castPtr ptr)
+    return (toEnum $ fromEnum (val :: CInt))
+  poke ptr v = poke (castPtr ptr) (fromIntegral (fromEnum v) :: CInt)
+
+data NPatchLayout = NPatchNinePatch | NPatchThreePatchVertical | NPatchThreePatchHorizontal deriving (Eq, Show, Enum)
+
+instance Storable NPatchLayout where
+  sizeOf _ = 4
+  alignment _ = 4
+  peek ptr = do
+    val <- peek (castPtr ptr)
+    return $ toEnum $ fromEnum (val :: CInt)
+  poke ptr v = poke (castPtr ptr) (fromIntegral (fromEnum v) :: CInt)
+
+data MusicContextType
+  = MusicAudioNone
+  | MusicAudioWAV
+  | MusicAudioOGG
+  | MusicAudioFLAC
+  | MusicAudioMP3
+  | MusicAudioQOA
+  | MusicModuleXM
+  | MusicModuleMOD
+  deriving (Eq, Show, Enum)
+
+instance Storable MusicContextType where
+  sizeOf _ = 4
+  alignment _ = 4
+  peek ptr = do
+    val <- peek (castPtr ptr)
+    return $ toEnum $ fromEnum (val :: CInt)
+  poke ptr v = poke (castPtr ptr) (fromIntegral (fromEnum v) :: CInt)
+
+------------------------------------------------
+-- Raylib structures ---------------------------
+------------------------------------------------
+
+data Vector2 = Vector2
+  { vector2'x :: Float,
+    vector2'y :: Float
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Vector2 where
+  sizeOf _ = 8
+  alignment _ = 4
+  peek _p = do
+    x <- realToFrac <$> (peekByteOff _p 0 :: IO CFloat)
+    y <- realToFrac <$> (peekByteOff _p 4 :: IO CFloat)
+    return $ Vector2 x y
+  poke _p (Vector2 x y) = do
+    pokeByteOff _p 0 (realToFrac x :: CFloat)
+    pokeByteOff _p 4 (realToFrac y :: CFloat)
+    return ()
+
+data Vector3 = Vector3
+  { vector3'x :: Float,
+    vector3'y :: Float,
+    vector3'z :: Float
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Vector3 where
+  sizeOf _ = 12
+  alignment _ = 4
+  peek _p = do
+    x <- realToFrac <$> (peekByteOff _p 0 :: IO CFloat)
+    y <- realToFrac <$> (peekByteOff _p 4 :: IO CFloat)
+    z <- realToFrac <$> (peekByteOff _p 8 :: IO CFloat)
+    return $ Vector3 x y z
+  poke _p (Vector3 x y z) = do
+    pokeByteOff _p 0 (realToFrac x :: CFloat)
+    pokeByteOff _p 4 (realToFrac y :: CFloat)
+    pokeByteOff _p 8 (realToFrac z :: CFloat)
+    return ()
+
+data Vector4 = Vector4
+  { vector4'x :: Float,
+    vector4'y :: Float,
+    vector4'z :: Float,
+    vector4'w :: Float
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Vector4 where
+  sizeOf _ = 16
+  alignment _ = 4
+  peek _p = do
+    x <- realToFrac <$> (peekByteOff _p 0 :: IO CFloat)
+    y <- realToFrac <$> (peekByteOff _p 4 :: IO CFloat)
+    z <- realToFrac <$> (peekByteOff _p 8 :: IO CFloat)
+    w <- realToFrac <$> (peekByteOff _p 12 :: IO CFloat)
+    return $ Vector4 x y z w
+  poke _p (Vector4 x y z w) = do
+    pokeByteOff _p 0 (realToFrac x :: CFloat)
+    pokeByteOff _p 4 (realToFrac y :: CFloat)
+    pokeByteOff _p 8 (realToFrac z :: CFloat)
+    pokeByteOff _p 12 (realToFrac w :: CFloat)
+    return ()
+
+type Quaternion = Vector4
+
+data Matrix = Matrix
+  { matrix'm0 :: Float,
+    matrix'm4 :: Float,
+    matrix'm8 :: Float,
+    matrix'm12 :: Float,
+    matrix'm1 :: Float,
+    matrix'm5 :: Float,
+    matrix'm9 :: Float,
+    matrix'm13 :: Float,
+    matrix'm2 :: Float,
+    matrix'm6 :: Float,
+    matrix'm10 :: Float,
+    matrix'm14 :: Float,
+    matrix'm3 :: Float,
+    matrix'm7 :: Float,
+    matrix'm11 :: Float,
+    matrix'm15 :: Float
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Matrix where
+  sizeOf _ = 64
+  alignment _ = 4
+  peek _p = do
+    m0 <- realToFrac <$> (peekByteOff _p 0 :: IO CFloat)
+    m4 <- realToFrac <$> (peekByteOff _p 4 :: IO CFloat)
+    m8 <- realToFrac <$> (peekByteOff _p 8 :: IO CFloat)
+    m12 <- realToFrac <$> (peekByteOff _p 12 :: IO CFloat)
+    m1 <- realToFrac <$> (peekByteOff _p 16 :: IO CFloat)
+    m5 <- realToFrac <$> (peekByteOff _p 20 :: IO CFloat)
+    m9 <- realToFrac <$> (peekByteOff _p 24 :: IO CFloat)
+    m13 <- realToFrac <$> (peekByteOff _p 28 :: IO CFloat)
+    m2 <- realToFrac <$> (peekByteOff _p 32 :: IO CFloat)
+    m6 <- realToFrac <$> (peekByteOff _p 36 :: IO CFloat)
+    m10 <- realToFrac <$> (peekByteOff _p 40 :: IO CFloat)
+    m14 <- realToFrac <$> (peekByteOff _p 44 :: IO CFloat)
+    m3 <- realToFrac <$> (peekByteOff _p 48 :: IO CFloat)
+    m7 <- realToFrac <$> (peekByteOff _p 52 :: IO CFloat)
+    m11 <- realToFrac <$> (peekByteOff _p 56 :: IO CFloat)
+    m15 <- realToFrac <$> (peekByteOff _p 60 :: IO CFloat)
+    return $ Matrix m0 m4 m8 m12 m1 m5 m9 m13 m2 m6 m10 m14 m3 m7 m11 m15
+  poke _p (Matrix m0 m4 m8 m12 m1 m5 m9 m13 m2 m6 m10 m14 m3 m7 m11 m15) = do
+    pokeByteOff _p 0 (realToFrac m0 :: CFloat)
+    pokeByteOff _p 4 (realToFrac m4 :: CFloat)
+    pokeByteOff _p 8 (realToFrac m8 :: CFloat)
+    pokeByteOff _p 12 (realToFrac m12 :: CFloat)
+    pokeByteOff _p 16 (realToFrac m1 :: CFloat)
+    pokeByteOff _p 20 (realToFrac m5 :: CFloat)
+    pokeByteOff _p 24 (realToFrac m9 :: CFloat)
+    pokeByteOff _p 28 (realToFrac m13 :: CFloat)
+    pokeByteOff _p 32 (realToFrac m2 :: CFloat)
+    pokeByteOff _p 36 (realToFrac m6 :: CFloat)
+    pokeByteOff _p 40 (realToFrac m10 :: CFloat)
+    pokeByteOff _p 44 (realToFrac m14 :: CFloat)
+    pokeByteOff _p 48 (realToFrac m3 :: CFloat)
+    pokeByteOff _p 52 (realToFrac m7 :: CFloat)
+    pokeByteOff _p 56 (realToFrac m11 :: CFloat)
+    pokeByteOff _p 60 (realToFrac m15 :: CFloat)
+    return ()
+
+data Color = Color
+  { color'r :: Word8,
+    color'g :: Word8,
+    color'b :: Word8,
+    color'a :: Word8
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Color where
+  sizeOf _ = 4
+  alignment _ = 1
+  peek _p = do
+    r <- fromIntegral <$> (peekByteOff _p 0 :: IO CUChar)
+    g <- fromIntegral <$> (peekByteOff _p 1 :: IO CUChar)
+    b <- fromIntegral <$> (peekByteOff _p 2 :: IO CUChar)
+    a <- fromIntegral <$> (peekByteOff _p 3 :: IO CUChar)
+    return $ Color r g b a
+  poke _p (Color r g b a) = do
+    pokeByteOff _p 0 (fromIntegral r :: CUChar)
+    pokeByteOff _p 1 (fromIntegral g :: CUChar)
+    pokeByteOff _p 2 (fromIntegral b :: CUChar)
+    pokeByteOff _p 3 (fromIntegral a :: CUChar)
+    return ()
+
+data Rectangle = Rectangle
+  { rectangle'x :: Float,
+    rectangle'y :: Float,
+    rectangle'width :: Float,
+    rectangle'height :: Float
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Rectangle where
+  sizeOf _ = 16
+  alignment _ = 4
+  peek _p = do
+    x <- realToFrac <$> (peekByteOff _p 0 :: IO CFloat)
+    y <- realToFrac <$> (peekByteOff _p 4 :: IO CFloat)
+    width <- realToFrac <$> (peekByteOff _p 8 :: IO CFloat)
+    height <- realToFrac <$> (peekByteOff _p 12 :: IO CFloat)
+    return $ Rectangle x y width height
+  poke _p (Rectangle x y width height) = do
+    pokeByteOff _p 0 (realToFrac x :: CFloat)
+    pokeByteOff _p 4 (realToFrac y :: CFloat)
+    pokeByteOff _p 8 (realToFrac width :: CFloat)
+    pokeByteOff _p 12 (realToFrac height :: CFloat)
+    return ()
+
+data Image = Image
+  { image'data :: [Word8],
+    image'width :: Int,
+    image'height :: Int,
+    image'mipmaps :: Int,
+    image'format :: PixelFormat
+  }
+  deriving (Eq, Show)
+
+instance Storable Image where
+  sizeOf _ = 24
+  alignment _ = 4
+  peek _p = do
+    width <- fromIntegral <$> (peekByteOff _p 8 :: IO CInt)
+    height <- fromIntegral <$> (peekByteOff _p 12 :: IO CInt)
+    mipmaps <- fromIntegral <$> (peekByteOff _p 16 :: IO CInt)
+    format <- peekByteOff _p 20
+    ptr <- (peekByteOff _p 0 :: IO (Ptr CUChar))
+    arr <- peekArray (getPixelDataSize width height format) ptr
+    return $ Image (map fromIntegral arr) width height mipmaps format
+  poke _p (Image arr width height mipmaps format) = do
+    pokeByteOff _p 0 =<< newArray (map fromIntegral arr :: [CUChar])
+    pokeByteOff _p 8 (fromIntegral width :: CInt)
+    pokeByteOff _p 12 (fromIntegral height :: CInt)
+    pokeByteOff _p 16 (fromIntegral mipmaps :: CInt)
+    pokeByteOff _p 20 format
+    return ()
+
+instance Freeable Image where
+  rlFreeDependents _ ptr = do
+    dataPtr <- (peekByteOff ptr 0 :: IO (Ptr CUChar))
+    c'free $ castPtr dataPtr
+
+data Texture = Texture
+  { texture'id :: Integer,
+    texture'width :: Int,
+    texture'height :: Int,
+    texture'mipmaps :: Int,
+    texture'format :: PixelFormat
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Texture where
+  sizeOf _ = 20
+  alignment _ = 4
+  peek _p = do
+    tId <- fromIntegral <$> (peekByteOff _p 0 :: IO CUInt)
+    width <- fromIntegral <$> (peekByteOff _p 4 :: IO CInt)
+    height <- fromIntegral <$> (peekByteOff _p 8 :: IO CInt)
+    mipmaps <- fromIntegral <$> (peekByteOff _p 12 :: IO CInt)
+    format <- peekByteOff _p 16
+    return $ Texture tId width height mipmaps format
+  poke _p (Texture tId width height mipmaps format) = do
+    pokeByteOff _p 0 (fromIntegral tId :: CUInt)
+    pokeByteOff _p 4 (fromIntegral width :: CInt)
+    pokeByteOff _p 8 (fromIntegral height :: CInt)
+    pokeByteOff _p 12 (fromIntegral mipmaps :: CInt)
+    pokeByteOff _p 16 format
+    return ()
+
+type Texture2D = Texture
+
+type TextureCubemap = Texture
+
+data RenderTexture = RenderTexture
+  { rendertexture'id :: Integer,
+    rendertexture'texture :: Texture,
+    rendertexture'depth :: Texture
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable RenderTexture where
+  sizeOf _ = 44
+  alignment _ = 4
+  peek _p = do
+    rtId <- fromIntegral <$> (peekByteOff _p 0 :: IO CUInt)
+    texture <- peekByteOff _p 4
+    depth <- peekByteOff _p 24
+    return $ RenderTexture rtId texture depth
+  poke _p (RenderTexture rtId texture depth) = do
+    pokeByteOff _p 0 (fromIntegral rtId :: CUInt)
+    pokeByteOff _p 4 texture
+    pokeByteOff _p 24 depth
+    return ()
+
+type RenderTexture2D = RenderTexture
+
+data NPatchInfo = NPatchInfo
+  { nPatchinfo'source :: Rectangle,
+    nPatchinfo'left :: Int,
+    nPatchinfo'top :: Int,
+    nPatchinfo'right :: Int,
+    nPatchinfo'bottom :: Int,
+    nPatchinfo'layout :: NPatchLayout
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable NPatchInfo where
+  sizeOf _ = 36
+  alignment _ = 4
+  peek _p = do
+    source <- peekByteOff _p 0
+    left <- fromIntegral <$> (peekByteOff _p 16 :: IO CInt)
+    top <- fromIntegral <$> (peekByteOff _p 20 :: IO CInt)
+    right <- fromIntegral <$> (peekByteOff _p 24 :: IO CInt)
+    bottom <- fromIntegral <$> (peekByteOff _p 28 :: IO CInt)
+    layout <- peekByteOff _p 32
+    return $ NPatchInfo source left right top bottom layout
+  poke _p (NPatchInfo source left right top bottom layout) = do
+    pokeByteOff _p 0 source
+    pokeByteOff _p 16 (fromIntegral left :: CInt)
+    pokeByteOff _p 20 (fromIntegral right :: CInt)
+    pokeByteOff _p 24 (fromIntegral top :: CInt)
+    pokeByteOff _p 28 (fromIntegral bottom :: CInt)
+    pokeByteOff _p 32 layout
+    return ()
+
+data GlyphInfo = GlyphInfo
+  { glyphinfo'value :: Int,
+    glyphInfo'offsetX :: Int,
+    glyphInfo'offsetY :: Int,
+    glyphInfo'advanceX :: Int,
+    glyphinfo'image :: Image
+  }
+  deriving (Eq, Show)
+
+instance Storable GlyphInfo where
+  sizeOf _ = 40
+  alignment _ = 4
+  peek _p = do
+    value <- fromIntegral <$> (peekByteOff _p 0 :: IO CInt)
+    offsetX <- fromIntegral <$> (peekByteOff _p 4 :: IO CInt)
+    offsetY <- fromIntegral <$> (peekByteOff _p 8 :: IO CInt)
+    advanceX <- fromIntegral <$> (peekByteOff _p 12 :: IO CInt)
+    image <- peekByteOff _p 16
+    return $ GlyphInfo value offsetX offsetY advanceX image
+  poke _p (GlyphInfo value offsetX offsetY advanceX image) = do
+    pokeByteOff _p 0 (fromIntegral value :: CInt)
+    pokeByteOff _p 4 (fromIntegral offsetX :: CInt)
+    pokeByteOff _p 8 (fromIntegral offsetY :: CInt)
+    pokeByteOff _p 12 (fromIntegral advanceX :: CInt)
+    pokeByteOff _p 16 image
+    return ()
+
+instance Freeable GlyphInfo where
+  rlFreeDependents _ ptr = do
+    dataPtr <- (peekByteOff ptr 16 :: IO (Ptr CUChar))
+    c'free $ castPtr dataPtr
+
+data Font = Font
+  { font'baseSize :: Int,
+    font'glyphCount :: Int,
+    font'glyphPadding :: Int,
+    font'texture :: Texture,
+    font'recs :: [Rectangle],
+    font'glyphs :: [GlyphInfo]
+  }
+  deriving (Eq, Show)
+
+instance Storable Font where
+  sizeOf _ = 48
+  alignment _ = 4
+  peek _p = do
+    baseSize <- fromIntegral <$> (peekByteOff _p 0 :: IO CInt)
+    glyphCount <- fromIntegral <$> (peekByteOff _p 4 :: IO CInt)
+    glyphPadding <- fromIntegral <$> (peekByteOff _p 8 :: IO CInt)
+    texture <- peekByteOff _p 12
+    recPtr <- (peekByteOff _p 32 :: IO (Ptr Rectangle))
+    recs <- peekArray glyphCount recPtr
+    glyphPtr <- (peekByteOff _p 40 :: IO (Ptr GlyphInfo))
+    glyphs <- peekArray glyphCount glyphPtr
+    return $ Font baseSize glyphCount glyphPadding texture recs glyphs
+  poke _p (Font baseSize glyphCount glyphPadding texture recs glyphs) = do
+    pokeByteOff _p 0 (fromIntegral baseSize :: CInt)
+    pokeByteOff _p 4 (fromIntegral glyphCount :: CInt)
+    pokeByteOff _p 8 (fromIntegral glyphPadding :: CInt)
+    pokeByteOff _p 12 texture
+    pokeByteOff _p 32 =<< newArray recs
+    pokeByteOff _p 40 =<< newArray glyphs
+    return ()
+
+instance Freeable Font where
+  rlFreeDependents val ptr = do
+    recsPtr <- (peekByteOff ptr 32 :: IO (Ptr Rectangle))
+    c'free $ castPtr recsPtr
+    glyphsPtr <- (peekByteOff ptr 40 :: IO (Ptr GlyphInfo))
+    rlFreeArray (font'glyphs val) glyphsPtr
+
+data Camera3D = Camera3D
+  { camera3D'position :: Vector3,
+    camera3D'target :: Vector3,
+    camera3D'up :: Vector3,
+    camera3D'fovy :: Float,
+    camera3D'projection :: CameraProjection
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Camera3D where
+  sizeOf _ = 44
+  alignment _ = 4
+  peek _p = do
+    position <- peekByteOff _p 0
+    target <- peekByteOff _p 12
+    up <- peekByteOff _p 24
+    fovy <- realToFrac <$> (peekByteOff _p 36 :: IO CFloat)
+    projection <- peekByteOff _p 40
+    return $ Camera3D position target up fovy projection
+  poke _p (Camera3D position target up fovy projection) = do
+    pokeByteOff _p 0 position
+    pokeByteOff _p 12 target
+    pokeByteOff _p 24 up
+    pokeByteOff _p 36 (realToFrac fovy :: CFloat)
+    pokeByteOff _p 40 projection
+    return ()
+
+type Camera = Camera3D
+
+data Camera2D = Camera2D
+  { camera2D'offset :: Vector2,
+    camera2D'target :: Vector2,
+    camera2d'rotation :: Float,
+    camera2d'zoom :: Float
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Camera2D where
+  sizeOf _ = 24
+  alignment _ = 4
+  peek _p = do
+    offset <- peekByteOff _p 0
+    target <- peekByteOff _p 8
+    rotation <- realToFrac <$> (peekByteOff _p 16 :: IO CFloat)
+    zoom <- realToFrac <$> (peekByteOff _p 20 :: IO CFloat)
+    return $ Camera2D offset target rotation zoom
+  poke _p (Camera2D offset target rotation zoom) = do
+    pokeByteOff _p 0 offset
+    pokeByteOff _p 8 target
+    pokeByteOff _p 16 (realToFrac rotation :: CFloat)
+    pokeByteOff _p 20 (realToFrac zoom :: CFloat)
+    return ()
+
+data Mesh = Mesh
+  { mesh'vertexCount :: Int,
+    mesh'triangleCount :: Int,
+    mesh'vertices :: [Vector3],
+    mesh'texcoords :: [Vector2],
+    mesh'texcoords2 :: Maybe [Vector2],
+    mesh'normals :: [Vector3],
+    mesh'tangents :: Maybe [Vector4],
+    mesh'colors :: Maybe [Color],
+    mesh'indices :: Maybe [Word16],
+    mesh'animVertices :: Maybe [Vector3],
+    mesh'animNormals :: Maybe [Vector3],
+    mesh'boneIds :: Maybe [Word8],
+    mesh'boneWeights :: Maybe [Float],
+    mesh'vaoId :: Integer,
+    mesh'vboId :: [Integer]
+  }
+  deriving (Eq, Show)
+
+instance Storable Mesh where
+  sizeOf _ = 112
+  alignment _ = 8
+  peek _p = do
+    vertexCount <- fromIntegral <$> (peekByteOff _p 0 :: IO CInt)
+    triangleCount <- fromIntegral <$> (peekByteOff _p 4 :: IO CInt)
+    verticesPtr <- (peekByteOff _p 8 :: IO (Ptr Vector3))
+    vertices <- peekArray vertexCount verticesPtr
+    texcoordsPtr <- (peekByteOff _p 16 :: IO (Ptr Vector2))
+    texcoords <- peekArray vertexCount texcoordsPtr
+    texcoords2Ptr <- (peekByteOff _p 24 :: IO (Ptr Vector2))
+    texcoords2 <- peekMaybeArray vertexCount texcoords2Ptr
+    normalsPtr <- (peekByteOff _p 32 :: IO (Ptr Vector3))
+    normals <- peekArray vertexCount normalsPtr
+    tangentsPtr <- (peekByteOff _p 40 :: IO (Ptr Vector4))
+    tangents <- peekMaybeArray vertexCount tangentsPtr
+    colorsPtr <- (peekByteOff _p 48 :: IO (Ptr Color))
+    colors <- peekMaybeArray vertexCount colorsPtr
+    indicesPtr <- (peekByteOff _p 56 :: IO (Ptr CUShort))
+    indices <- (\m -> map fromIntegral <$> m) <$> peekMaybeArray vertexCount indicesPtr
+    animVerticesPtr <- (peekByteOff _p 64 :: IO (Ptr Vector3))
+    animVertices <- peekMaybeArray vertexCount animVerticesPtr
+    animNormalsPtr <- (peekByteOff _p 72 :: IO (Ptr Vector3))
+    animNormals <- peekMaybeArray vertexCount animNormalsPtr
+    boneIdsPtr <- (peekByteOff _p 80 :: IO (Ptr CUChar))
+    boneIds <- (\m -> map fromIntegral <$> m) <$> peekMaybeArray (vertexCount * 4) boneIdsPtr
+    boneWeightsPtr <- (peekByteOff _p 88 :: IO (Ptr Float))
+    boneWeights <- peekMaybeArray (vertexCount * 4) boneWeightsPtr
+    vaoId <- fromIntegral <$> (peekByteOff _p 96 :: IO CUInt)
+    vboIdPtr <- (peekByteOff _p 104 :: IO (Ptr CUInt))
+    vboId <- map fromIntegral <$> peekArray 7 vboIdPtr
+    return $ Mesh vertexCount triangleCount vertices texcoords texcoords2 normals tangents colors indices animVertices animNormals boneIds boneWeights vaoId vboId
+  poke _p (Mesh vertexCount triangleCount vertices texcoords texcoords2 normals tangents colors indices animVertices animNormals boneIds boneWeights vaoId vboId) = do
+    pokeByteOff _p 0 (fromIntegral vertexCount :: CInt)
+    pokeByteOff _p 4 (fromIntegral triangleCount :: CInt)
+    pokeByteOff _p 8 =<< newArray vertices
+    pokeByteOff _p 16 =<< newArray texcoords
+    newMaybeArray texcoords2 >>= pokeByteOff _p 24
+    pokeByteOff _p 32 =<< newArray normals
+    newMaybeArray tangents >>= pokeByteOff _p 40
+    newMaybeArray colors >>= pokeByteOff _p 48
+    newMaybeArray ((\m -> map fromIntegral m :: [CUShort]) <$> indices) >>= pokeByteOff _p 56
+    newMaybeArray animVertices >>= pokeByteOff _p 64
+    newMaybeArray animNormals >>= pokeByteOff _p 72
+    newMaybeArray ((\m -> map fromIntegral m :: [CUChar]) <$> boneIds) >>= pokeByteOff _p 80
+    newMaybeArray boneWeights >>= pokeByteOff _p 88
+    pokeByteOff _p 96 (fromIntegral vaoId :: CUInt)
+    pokeByteOff _p 104 =<< newArray (map fromIntegral vboId :: [CUInt])
+    return ()
+
+instance Freeable Mesh where
+  rlFreeDependents _ ptr = do
+    verticesPtr <- (peekByteOff ptr 8 :: IO (Ptr Float))
+    c'free $ castPtr verticesPtr
+    texcoordsPtr <- (peekByteOff ptr 16 :: IO (Ptr Vector2))
+    c'free $ castPtr texcoordsPtr
+    texcoords2Ptr <- (peekByteOff ptr 24 :: IO (Ptr Vector2))
+    freeMaybePtr $ castPtr texcoords2Ptr
+    normalsPtr <- (peekByteOff ptr 32 :: IO (Ptr Vector3))
+    c'free $ castPtr normalsPtr
+    tangentsPtr <- (peekByteOff ptr 40 :: IO (Ptr Vector4))
+    freeMaybePtr $ castPtr tangentsPtr
+    colorsPtr <- (peekByteOff ptr 48 :: IO (Ptr Color))
+    freeMaybePtr $ castPtr colorsPtr
+    indicesPtr <- (peekByteOff ptr 56 :: IO (Ptr CUShort))
+    freeMaybePtr $ castPtr indicesPtr
+    animVerticesPtr <- (peekByteOff ptr 64 :: IO (Ptr Vector3))
+    freeMaybePtr $ castPtr animVerticesPtr
+    animNormalsPtr <- (peekByteOff ptr 72 :: IO (Ptr Vector3))
+    freeMaybePtr $ castPtr animNormalsPtr
+    boneIdsPtr <- (peekByteOff ptr 80 :: IO (Ptr CUChar))
+    freeMaybePtr $ castPtr boneIdsPtr
+    boneWeightsPtr <- (peekByteOff ptr 88 :: IO (Ptr Float))
+    freeMaybePtr $ castPtr boneWeightsPtr
+    vboIdPtr <- (peekByteOff ptr 104 :: IO (Ptr CUInt))
+    c'free $ castPtr vboIdPtr
+
+data Shader = Shader
+  { shader'id :: Integer,
+    shader'locs :: [Int]
+  }
+  deriving (Eq, Show)
+
+instance Storable Shader where
+  sizeOf _ = 16
+  alignment _ = 8
+  peek _p = do
+    sId <- fromIntegral <$> (peekByteOff _p 0 :: IO CUInt)
+    locsPtr <- (peekByteOff _p 8 :: IO (Ptr CInt))
+    locs <- map fromIntegral <$> peekArray 32 locsPtr
+    return $ Shader sId locs
+  poke _p (Shader sId locs) = do
+    pokeByteOff _p 0 (fromIntegral sId :: CUInt)
+    defaultShaderId <- c'rlGetShaderIdDefault
+    locsArr <- newArray (map fromIntegral locs :: [CInt])
+    if sId == fromIntegral defaultShaderId
+      then do
+        locsPtr <- newForeignPtr p'free locsArr
+        withForeignPtr locsPtr $ pokeByteOff _p 8
+      else pokeByteOff _p 8 locsArr
+    return ()
+
+instance Freeable Shader where
+  rlFreeDependents val ptr = do
+    defaultShaderId <- c'rlGetShaderIdDefault
+    unless
+      (shader'id val == fromIntegral defaultShaderId)
+      ( do
+          locsPtr <- (peekByteOff ptr 8 :: IO (Ptr CInt))
+          c'free $ castPtr locsPtr
+      )
+
+data MaterialMap = MaterialMap
+  { materialmap'texture :: Texture,
+    materialmap'color :: Color,
+    materialmap'value :: Float
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable MaterialMap where
+  sizeOf _ = 28
+  alignment _ = 4
+  peek _p = do
+    texture <- peekByteOff _p 0
+    color <- peekByteOff _p 20
+    value <- realToFrac <$> (peekByteOff _p 24 :: IO CFloat)
+    return $ MaterialMap texture color value
+  poke _p (MaterialMap texture color value) = do
+    pokeByteOff _p 0 texture
+    pokeByteOff _p 20 color
+    pokeByteOff _p 24 (realToFrac value :: CFloat)
+    return ()
+
+data Material = Material
+  { material'shader :: Shader,
+    material'maps :: [MaterialMap],
+    material'params :: [Float]
+  }
+  deriving (Eq, Show)
+
+instance Storable Material where
+  sizeOf _ = 40
+  alignment _ = 8
+  peek _p = do
+    shader <- peekByteOff _p 0
+    mapsPtr <- (peekByteOff _p 16 :: IO (Ptr MaterialMap))
+    maps <- peekArray 12 mapsPtr
+    params <- map realToFrac <$> peekStaticArrayOff 4 (castPtr _p :: Ptr CFloat) 24
+    return $ Material shader maps params
+  poke _p (Material shader maps params) = do
+    pokeByteOff _p 0 shader
+    pokeByteOff _p 16 =<< newArray maps
+    pokeStaticArrayOff (castPtr _p :: Ptr CFloat) 24 (map realToFrac params :: [CFloat])
+    return ()
+
+instance Freeable Material where
+  rlFreeDependents val ptr = do
+    rlFreeDependents (material'shader val) (castPtr ptr :: Ptr Shader)
+    mapsPtr <- (peekByteOff ptr 16 :: IO (Ptr MaterialMap))
+    rlFreeArray (material'maps val) mapsPtr
+
+data Transform = Transform
+  { transform'translation :: Vector3,
+    transform'rotation :: Quaternion,
+    transform'scale :: Vector3
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Transform where
+  sizeOf _ = 40
+  alignment _ = 4
+  peek _p = do
+    translation <- peekByteOff _p 0
+    rotation <- peekByteOff _p 12
+    scale <- peekByteOff _p 28
+    return $ Transform translation rotation scale
+  poke _p (Transform translation rotation scale) = do
+    pokeByteOff _p 0 translation
+    pokeByteOff _p 12 rotation
+    pokeByteOff _p 28 scale
+    return ()
+
+data BoneInfo = BoneInfo
+  { boneInfo'name :: String,
+    boneinfo'parent :: Int
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable BoneInfo where
+  sizeOf _ = 36
+  alignment _ = 4
+  peek _p = do
+    name <- map castCCharToChar . takeWhile (/= 0) <$> peekStaticArray 32 (castPtr _p :: Ptr CChar)
+    parent <- fromIntegral <$> (peekByteOff _p 32 :: IO CInt)
+    return $ BoneInfo name parent
+  poke _p (BoneInfo name parent) = do
+    pokeStaticArray (castPtr _p :: Ptr CChar) (rightPad 32 0 $ map castCharToCChar name)
+    pokeByteOff _p 32 (fromIntegral parent :: CInt)
+    return ()
+
+data Model = Model
+  { model'transform :: Matrix,
+    model'meshCount :: Int,
+    model'materialCount :: Int,
+    model'meshes :: [Mesh],
+    model'materials :: [Material],
+    model'meshMaterial :: [Int],
+    model'boneCount :: Int,
+    model'bones :: Maybe [BoneInfo],
+    model'bindPose :: Maybe [Transform]
+  }
+  deriving (Eq, Show)
+
+instance Storable Model where
+  sizeOf _ = 120
+  alignment _ = 4
+  peek _p = do
+    transform <- peekByteOff _p 0
+    meshCount <- fromIntegral <$> (peekByteOff _p 64 :: IO CInt)
+    materialCount <- fromIntegral <$> (peekByteOff _p 68 :: IO CInt)
+    meshesPtr <- (peekByteOff _p 72 :: IO (Ptr Mesh))
+    meshes <- peekArray meshCount meshesPtr
+    materialsPtr <- (peekByteOff _p 80 :: IO (Ptr Material))
+    materials <- peekArray materialCount materialsPtr
+    meshMaterialPtr <- (peekByteOff _p 88 :: IO (Ptr CInt))
+    meshMaterial <- map fromIntegral <$> peekArray meshCount meshMaterialPtr
+    boneCount <- fromIntegral <$> (peekByteOff _p 96 :: IO CInt)
+    bonesPtr <- (peekByteOff _p 104 :: IO (Ptr BoneInfo))
+    bones <- peekMaybeArray boneCount bonesPtr
+    bindPosePtr <- (peekByteOff _p 112 :: IO (Ptr Transform))
+    bindPose <- peekMaybeArray boneCount bindPosePtr
+    return $ Model transform meshCount materialCount meshes materials meshMaterial boneCount bones bindPose
+  poke _p (Model transform meshCount materialCount meshes materials meshMaterial boneCount bones bindPose) = do
+    pokeByteOff _p 0 transform
+    pokeByteOff _p 64 (fromIntegral meshCount :: CInt)
+    pokeByteOff _p 68 (fromIntegral materialCount :: CInt)
+    pokeByteOff _p 72 =<< newArray meshes
+    pokeByteOff _p 80 =<< newArray materials
+    pokeByteOff _p 88 =<< newArray (map fromIntegral meshMaterial :: [CInt])
+    pokeByteOff _p 96 (fromIntegral boneCount :: CInt)
+    newMaybeArray bones >>= pokeByteOff _p 104
+    newMaybeArray bindPose >>= pokeByteOff _p 112
+    return ()
+
+instance Freeable Model where
+  rlFreeDependents val ptr = do
+    meshesPtr <- (peekByteOff ptr 72 :: IO (Ptr Mesh))
+    rlFreeArray (model'meshes val) meshesPtr
+    materialsPtr <- (peekByteOff ptr 80 :: IO (Ptr Material))
+    rlFreeArray (model'materials val) materialsPtr
+    meshMaterialPtr <- (peekByteOff ptr 88 :: IO (Ptr CInt))
+    c'free $ castPtr meshMaterialPtr
+    bonesPtr <- (peekByteOff ptr 104 :: IO (Ptr BoneInfo))
+    freeMaybePtr $ castPtr bonesPtr
+    bindPosePtr <- (peekByteOff ptr 112 :: IO (Ptr Transform))
+    freeMaybePtr $ castPtr bindPosePtr
+
+data ModelAnimation = ModelAnimation
+  { modelAnimation'boneCount :: Int,
+    modelAnimation'frameCount :: Int,
+    modelAnimation'bones :: [BoneInfo],
+    modelAnimation'framePoses :: [[Transform]]
+  }
+  deriving (Eq, Show)
+
+instance Storable ModelAnimation where
+  sizeOf _ = 24
+  alignment _ = 4
+  peek _p = do
+    boneCount <- fromIntegral <$> (peekByteOff _p 0 :: IO CInt)
+    frameCount <- fromIntegral <$> (peekByteOff _p 4 :: IO CInt)
+    bonesPtr <- (peekByteOff _p 8 :: IO (Ptr BoneInfo))
+    bones <- peekArray boneCount bonesPtr
+    framePosesPtr <- (peekByteOff _p 16 :: IO (Ptr (Ptr Transform)))
+    framePosesPtrArr <- peekArray frameCount framePosesPtr
+    framePoses <- mapM (peekArray boneCount) framePosesPtrArr
+    return $ ModelAnimation boneCount frameCount bones framePoses
+  poke _p (ModelAnimation boneCount frameCount bones framePoses) = do
+    pokeByteOff _p 0 (fromIntegral boneCount :: CInt)
+    pokeByteOff _p 4 (fromIntegral frameCount :: CInt)
+    pokeByteOff _p 8 =<< newArray bones
+    mapM newArray framePoses >>= newArray >>= pokeByteOff _p 16
+    return ()
+
+instance Freeable ModelAnimation where
+  rlFreeDependents val ptr = do
+    bonesPtr <- (peekByteOff ptr 8 :: IO (Ptr BoneInfo))
+    c'free $ castPtr bonesPtr
+    framePosesPtr <- (peekByteOff ptr 16 :: IO (Ptr (Ptr Transform)))
+    framePosesPtrArr <- peekArray (modelAnimation'frameCount val) framePosesPtr
+    forM_ framePosesPtrArr (c'free . castPtr)
+    c'free $ castPtr framePosesPtr
+
+data Ray = Ray
+  { ray'position :: Vector3,
+    ray'direction :: Vector3
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Ray where
+  sizeOf _ = 24
+  alignment _ = 4
+  peek _p = do
+    position <- peekByteOff _p 0
+    direction <- peekByteOff _p 12
+    return $ Ray position direction
+  poke _p (Ray position direction) = do
+    pokeByteOff _p 0 position
+    pokeByteOff _p 12 direction
+    return ()
+
+data RayCollision = RayCollision
+  { rayCollision'hit :: Bool,
+    rayCollision'distance :: Float,
+    rayCollision'point :: Vector3,
+    rayCollision'normal :: Vector3
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable RayCollision where
+  sizeOf _ = 32
+  alignment _ = 4
+  peek _p = do
+    hit <- toBool <$> (peekByteOff _p 0 :: IO CBool)
+    distance <- realToFrac <$> (peekByteOff _p 4 :: IO CFloat)
+    point <- peekByteOff _p 8
+    normal <- peekByteOff _p 20
+    return $ RayCollision hit distance point normal
+  poke _p (RayCollision hit distance point normal) = do
+    pokeByteOff _p 0 (fromBool hit :: CInt)
+    pokeByteOff _p 4 (realToFrac distance :: CFloat)
+    pokeByteOff _p 8 point
+    pokeByteOff _p 20 normal
+    return ()
+
+data BoundingBox = BoundingBox
+  { boundingBox'min :: Vector3,
+    boundingBox'max :: Vector3
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable BoundingBox where
+  sizeOf _ = 24
+  alignment _ = 4
+  peek _p = do
+    bMin <- peekByteOff _p 0
+    bMax <- peekByteOff _p 12
+    return $ BoundingBox bMin bMax
+  poke _p (BoundingBox bMin bMax) = do
+    pokeByteOff _p 0 bMin
+    pokeByteOff _p 12 bMax
+    return ()
+
+data Wave = Wave
+  { wave'frameCount :: Integer,
+    wave'sampleRate :: Integer,
+    wave'sampleSize :: Integer,
+    wave'channels :: Integer,
+    wave'data :: [Int]
+  }
+  deriving (Eq, Show)
+
+instance Storable Wave where
+  sizeOf _ = 24
+  alignment _ = 4
+  peek _p = do
+    frameCount <- fromIntegral <$> (peekByteOff _p 0 :: IO CUInt)
+    sampleRate <- fromIntegral <$> (peekByteOff _p 4 :: IO CUInt)
+    sampleSize <- fromIntegral <$> (peekByteOff _p 8 :: IO CUInt)
+    channels <- fromIntegral <$> (peekByteOff _p 12 :: IO CUInt)
+    wDataPtr <- (peekByteOff _p 16 :: IO (Ptr CShort))
+    wData <- map fromIntegral <$> peekArray (fromInteger $ frameCount * channels) wDataPtr
+    return $ Wave frameCount sampleRate sampleSize channels wData
+  poke _p (Wave frameCount sampleRate sampleSize channels wData) = do
+    pokeByteOff _p 0 (fromIntegral frameCount :: CUInt)
+    pokeByteOff _p 4 (fromIntegral sampleRate :: CUInt)
+    pokeByteOff _p 8 (fromIntegral sampleSize :: CUInt)
+    pokeByteOff _p 12 (fromIntegral channels :: CUInt)
+    pokeByteOff _p 16 =<< newArray (map fromIntegral wData :: [CShort])
+    return ()
+
+instance Freeable Wave where
+  rlFreeDependents _ ptr = do
+    dataPtr <- peekByteOff ptr 16 :: IO (Ptr CShort)
+    c'free $ castPtr dataPtr
+
+-- These types don't work perfectly right now, I need to fix them later on.
+-- They are currently used as `Ptr`s because peeking/poking them every time
+-- an audio function is called doesn't work properly (they are stored in a
+-- linked list in C, which makes it very difficult to properly peek/poke them)
+data RAudioBuffer = RAudioBuffer
+  { rAudioBuffer'converter :: [Int], -- Implemented as an array of 39 integers because binding the entire `ma_data_converter` type is too painful
+    rAudioBuffer'callback :: AudioCallback,
+    rAudioBuffer'processor :: Maybe RAudioProcessor,
+    rAudioBuffer'volume :: Float,
+    rAudioBuffer'pitch :: Float,
+    rAudioBuffer'pan :: Float,
+    rAudioBuffer'playing :: Bool,
+    rAudioBuffer'paused :: Bool,
+    rAudioBuffer'looping :: Bool,
+    rAudioBuffer'usage :: Int,
+    rAudioBuffer'isSubBufferProcessed :: [Bool],
+    rAudioBuffer'sizeInFrames :: Integer,
+    rAudioBuffer'frameCursorPos :: Integer,
+    rAudioBuffer'framesProcessed :: Integer,
+    rAudioBuffer'data :: [Word8],
+    rAudioBuffer'next :: Maybe RAudioBuffer,
+    rAudioBuffer'prev :: Maybe RAudioBuffer
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable RAudioBuffer where
+  sizeOf _ = 392
+  alignment _ = 8
+  peek _p = do
+    base <- loadBase _p
+    nextPtr <- peekByteOff _p 376
+    next <- loadNext nextPtr
+    prevPtr <- peekByteOff _p 384
+    prev <- loadPrev prevPtr
+    return $
+      let p =
+            base
+              ((\a -> a {rAudioBuffer'prev = Just p}) <$> next)
+              ((\a -> a {rAudioBuffer'next = Just p}) <$> prev)
+       in p
+    where
+      getBytesPerSample = ([0, 1, 2, 3, 4, 4] !!)
+      loadBase ptr = do
+        converter <- map fromIntegral <$> (peekStaticArray 39 (castPtr ptr) :: IO [CInt])
+        callback <- peekByteOff ptr 312
+        pPtr <- peekByteOff ptr 320 :: IO (Ptr RAudioProcessor)
+        processor <- if pPtr == nullPtr then return Nothing else Just <$> peek pPtr
+
+        volume <- realToFrac <$> (peekByteOff ptr 328 :: IO CFloat)
+        pitch <- realToFrac <$> (peekByteOff ptr 332 :: IO CFloat)
+        pan <- realToFrac <$> (peekByteOff ptr 336 :: IO CFloat)
+
+        playing <- toBool <$> (peekByteOff ptr 340 :: IO CBool)
+        paused <- toBool <$> (peekByteOff ptr 341 :: IO CBool)
+        looping <- toBool <$> (peekByteOff ptr 342 :: IO CBool)
+        usage <- fromIntegral <$> (peekByteOff ptr 344 :: IO CInt)
+
+        isSubBufferProcessed <- map toBool <$> peekStaticArrayOff 2 (castPtr ptr :: Ptr CBool) 348
+        sizeInFrames <- fromIntegral <$> (peekByteOff ptr 352 :: IO CUInt)
+        frameCursorPos <- fromIntegral <$> (peekByteOff ptr 356 :: IO CUInt)
+        framesProcessed <- fromIntegral <$> (peekByteOff ptr 360 :: IO CUInt)
+
+        bData <- map fromIntegral <$> (peekArray (fromIntegral $ sizeInFrames * 2 * getBytesPerSample (head converter)) =<< (peekByteOff ptr 368 :: IO (Ptr CUChar)))
+
+        return $ RAudioBuffer converter callback processor volume pitch pan playing paused looping usage isSubBufferProcessed sizeInFrames frameCursorPos framesProcessed bData
+      loadNext ptr =
+        if ptr == nullPtr
+          then return Nothing
+          else do
+            base <- loadBase ptr
+            nextPtr <- peekByteOff ptr 376
+            next <- loadNext nextPtr
+            let p = base ((\a -> a {rAudioBuffer'prev = Just p}) <$> next) Nothing
+             in return (Just p)
+
+      loadPrev ptr =
+        if ptr == nullPtr
+          then return Nothing
+          else do
+            base <- loadBase ptr
+            prevPtr <- peekByteOff ptr 384
+            prev <- loadPrev prevPtr
+            let p = base Nothing ((\a -> a {rAudioBuffer'next = Just p}) <$> prev)
+             in return (Just p)
+  poke _p a = do
+    pokeBase _p a
+    pokeNext _p $ rAudioBuffer'next a
+    pokePrev _p $ rAudioBuffer'prev a
+    return ()
+    where
+      pokeBase ptr (RAudioBuffer converter callback processor volume pitch pan playing paused looping usage isSubBufferProcessed sizeInFrames frameCursorPos framesProcessed bData _ _) = do
+        pokeStaticArray (castPtr ptr) (map fromIntegral converter :: [CInt])
+        pokeByteOff ptr 312 callback
+        pokeMaybeOff (castPtr ptr) 320 processor
+
+        pokeByteOff ptr 328 (realToFrac volume :: CFloat)
+        pokeByteOff ptr 332 (realToFrac pitch :: CFloat)
+        pokeByteOff ptr 336 (realToFrac pan :: CFloat)
+
+        pokeByteOff ptr 340 (fromBool playing :: CBool)
+        pokeByteOff ptr 341 (fromBool paused :: CBool)
+        pokeByteOff ptr 342 (fromBool looping :: CBool)
+        pokeByteOff ptr 344 (fromIntegral usage :: CInt)
+
+        pokeStaticArrayOff (castPtr ptr) 348 (map fromBool isSubBufferProcessed :: [CBool])
+        pokeByteOff ptr 352 (fromIntegral sizeInFrames :: CUInt)
+        pokeByteOff ptr 356 (fromIntegral frameCursorPos :: CUInt)
+        pokeByteOff ptr 360 (fromIntegral framesProcessed :: CUInt)
+
+        pokeByteOff ptr 368 =<< newArray (map fromIntegral bData :: [CUChar])
+
+        return ()
+      pokeNext basePtr pNext =
+        case pNext of
+          Nothing -> pokeByteOff basePtr 376 nullPtr
+          Just val -> do
+            nextPtr <- malloc
+            pokeBase nextPtr val
+            pokeNext nextPtr (rAudioBuffer'next val)
+            pokeByteOff nextPtr 384 basePtr
+            pokeByteOff basePtr 376 nextPtr
+      pokePrev basePtr pPrev =
+        case pPrev of
+          Nothing -> pokeByteOff basePtr 384 nullPtr
+          Just val -> do
+            prevPtr <- malloc
+            pokeBase prevPtr val
+            pokeByteOff prevPtr 376 basePtr
+            pokePrev prevPtr (rAudioBuffer'prev val)
+            pokeByteOff basePtr 384 prevPtr
+
+data RAudioProcessor = RAudioProcessor
+  { rAudioProcessor'process :: Maybe AudioCallback,
+    rAudioProcessor'next :: Maybe RAudioProcessor,
+    rAudioProcessor'prev :: Maybe RAudioProcessor
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable RAudioProcessor where
+  sizeOf _ = 24
+  alignment _ = 8
+  peek _p = do
+    process <- loadProcess _p
+    nextPtr <- peekByteOff _p 8
+    next <- loadNext nextPtr
+    prevPtr <- peekByteOff _p 16
+    prev <- loadPrev prevPtr
+    return $ let p = RAudioProcessor process ((\a -> a {rAudioProcessor'prev = Just p}) <$> next) ((\a -> a {rAudioProcessor'next = Just p}) <$> prev) in p
+    where
+      loadProcess ptr = do
+        funPtr <- peekByteOff ptr 0
+        if funPtr == nullFunPtr then return Nothing else return (Just funPtr)
+      loadNext ptr =
+        if ptr == nullPtr
+          then return Nothing
+          else do
+            process <- loadProcess ptr
+            nextPtr <- peekByteOff ptr 8
+            next <- loadNext nextPtr
+            let p = RAudioProcessor process ((\a -> a {rAudioProcessor'prev = Just p}) <$> next) Nothing
+             in return (Just p)
+
+      loadPrev ptr =
+        if ptr == nullPtr
+          then return Nothing
+          else do
+            process <- loadProcess ptr
+            prevPtr <- peekByteOff ptr 16
+            prev <- loadPrev prevPtr
+            let p = RAudioProcessor process Nothing ((\a -> a {rAudioProcessor'next = Just p}) <$> prev)
+             in return (Just p)
+  poke _p (RAudioProcessor process next prev) = do
+    pokeMaybeOff (castPtr _p) 0 process
+    pokeNext (castPtr _p) next
+    pokePrev (castPtr _p) prev
+    return ()
+    where
+      pokeNext basePtr pNext =
+        case pNext of
+          Nothing -> pokeByteOff basePtr 8 nullPtr
+          Just val -> do
+            nextPtr <- malloc
+            pokeMaybeOff nextPtr 0 (rAudioProcessor'process val)
+            pokeNext nextPtr (rAudioProcessor'next val)
+            pokeByteOff nextPtr 16 basePtr
+            pokeByteOff basePtr 8 nextPtr
+      pokePrev basePtr pPrev =
+        case pPrev of
+          Nothing -> pokeByteOff basePtr 16 nullPtr
+          Just val -> do
+            prevPtr <- malloc
+            pokeMaybeOff prevPtr 0 (rAudioProcessor'process val)
+            pokeByteOff prevPtr 8 basePtr
+            pokePrev prevPtr (rAudioProcessor'prev val)
+            pokeByteOff basePtr 16 prevPtr
+
+data AudioStream = AudioStream
+  { audioStream'buffer :: Ptr RAudioBuffer, -- TODO: Convert these into ForeignPtrs to make them automatically unload
+    audioStream'processor :: Ptr RAudioProcessor,
+    audioStream'sampleRate :: Integer,
+    audioStream'sampleSize :: Integer,
+    audiostream'channels :: Integer
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable AudioStream where
+  sizeOf _ = 32
+  alignment _ = 8
+  peek _p = do
+    buffer <- peekByteOff _p 0
+    processor <- peekByteOff _p 8
+    sampleRate <- fromIntegral <$> (peekByteOff _p 16 :: IO CUInt)
+    sampleSize <- fromIntegral <$> (peekByteOff _p 20 :: IO CUInt)
+    channels <- fromIntegral <$> (peekByteOff _p 24 :: IO CUInt)
+    return $ AudioStream buffer processor sampleRate sampleSize channels
+  poke _p (AudioStream buffer processor sampleRate sampleSize channels) = do
+    pokeByteOff _p 0 buffer
+    pokeByteOff _p 8 processor
+    pokeByteOff _p 16 (fromIntegral sampleRate :: CUInt)
+    pokeByteOff _p 20 (fromIntegral sampleSize :: CUInt)
+    pokeByteOff _p 24 (fromIntegral channels :: CUInt)
+    return ()
+
+data Sound = Sound
+  { sound'stream :: AudioStream,
+    sound'frameCount :: Integer
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Sound where
+  sizeOf _ = 40
+  alignment _ = 8
+  peek _p = do
+    stream <- peekByteOff _p 0
+    frameCount <- fromIntegral <$> (peekByteOff _p 32 :: IO CUInt)
+    return $ Sound stream frameCount
+  poke _p (Sound stream frameCount) = do
+    pokeByteOff _p 0 stream
+    pokeByteOff _p 32 (fromIntegral frameCount :: CUInt)
+    return ()
+
+data Music = Music
+  { music'stream :: AudioStream,
+    music'frameCount :: Integer,
+    music'looping :: Bool,
+    music'ctxType :: MusicContextType,
+    music'ctxData :: Ptr () -- TODO: Convert this into a ForeignPtr to make it automatically unload
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable Music where
+  sizeOf _ = 56
+  alignment _ = 4
+  peek _p = do
+    stream <- peekByteOff _p 0
+    frameCount <- fromIntegral <$> (peekByteOff _p 32 :: IO CUInt)
+    looping <- toBool <$> (peekByteOff _p 36 :: IO CBool)
+    ctxType <- peekByteOff _p 40
+    ctxData <- peekByteOff _p 48
+    return $ Music stream frameCount looping ctxType ctxData
+  poke _p (Music stream frameCount looping ctxType ctxData) = do
+    pokeByteOff _p 0 stream
+    pokeByteOff _p 32 (fromIntegral frameCount :: CUInt)
+    pokeByteOff _p 36 (fromBool looping :: CInt)
+    pokeByteOff _p 40 ctxType
+    pokeByteOff _p 48 ctxData
+    return ()
+
+data VrDeviceInfo = VrDeviceInfo
+  { vrDeviceInfo'hResolution :: Int,
+    vrDeviceInfo'vResolution :: Int,
+    vrDeviceInfo'hScreenSize :: Float,
+    vrDeviceInfo'vScreenSize :: Float,
+    vrDeviceInfo'vScreenCenter :: Float,
+    vrDeviceInfo'eyeToScreenDistance :: Float,
+    vrDeviceInfo'lensSeparationDistance :: Float,
+    vrDeviceInfo'interpupillaryDistance :: Float,
+    vrDeviceInfo'lensDistortionValues :: [Float],
+    vrDeviceInfo'chromaAbCorrection :: [Float]
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable VrDeviceInfo where
+  sizeOf _ = 64
+  alignment _ = 4
+  peek _p = do
+    hResolution <- fromIntegral <$> (peekByteOff _p 0 :: IO CInt)
+    vResolution <- fromIntegral <$> (peekByteOff _p 4 :: IO CInt)
+    hScreenSize <- realToFrac <$> (peekByteOff _p 8 :: IO CFloat)
+    vScreenSize <- realToFrac <$> (peekByteOff _p 12 :: IO CFloat)
+    vScreenCenter <- realToFrac <$> (peekByteOff _p 16 :: IO CFloat)
+    eyeToScreenDistance <- realToFrac <$> (peekByteOff _p 20 :: IO CFloat)
+    lensSeparationDistance <- realToFrac <$> (peekByteOff _p 24 :: IO CFloat)
+    interpupillaryDistance <- realToFrac <$> (peekByteOff _p 28 :: IO CFloat)
+    lensDistortionValues <- map realToFrac <$> (peekStaticArrayOff 4 (castPtr _p) 32 :: IO [CFloat])
+    chromaAbCorrection <- map realToFrac <$> (peekStaticArrayOff 4 (castPtr _p) 48 :: IO [CFloat])
+    return $ VrDeviceInfo hResolution vResolution hScreenSize vScreenSize vScreenCenter eyeToScreenDistance lensSeparationDistance interpupillaryDistance lensDistortionValues chromaAbCorrection
+  poke _p (VrDeviceInfo hResolution vResolution hScreenSize vScreenSize vScreenCenter eyeToScreenDistance lensSeparationDistance interpupillaryDistance lensDistortionValues chromaAbCorrection) = do
+    pokeByteOff _p 0 (fromIntegral hResolution :: CInt)
+    pokeByteOff _p 4 (fromIntegral vResolution :: CInt)
+    pokeByteOff _p 8 (realToFrac hScreenSize :: CFloat)
+    pokeByteOff _p 12 (realToFrac vScreenSize :: CFloat)
+    pokeByteOff _p 16 (realToFrac vScreenCenter :: CFloat)
+    pokeByteOff _p 20 (realToFrac eyeToScreenDistance :: CFloat)
+    pokeByteOff _p 24 (realToFrac lensSeparationDistance :: CFloat)
+    pokeByteOff _p 28 (realToFrac interpupillaryDistance :: CFloat)
+    pokeStaticArrayOff (castPtr _p) 32 (map realToFrac lensDistortionValues :: [CFloat])
+    pokeStaticArrayOff (castPtr _p) 48 (map realToFrac chromaAbCorrection :: [CFloat])
+    return ()
+
+data VrStereoConfig = VrStereoConfig
+  { vrStereoConfig'projection :: [Matrix],
+    vrStereoConfig'viewOffset :: [Matrix],
+    vrStereoConfig'leftLensCenter :: [Float],
+    vrStereoConfig'rightLensCenter :: [Float],
+    vrStereoConfig'leftScreenCenter :: [Float],
+    vrStereoConfig'rightScreenCenter :: [Float],
+    vrStereoConfig'scale :: [Float],
+    vrStereoConfig'scaleIn :: [Float]
+  }
+  deriving (Eq, Show, Freeable)
+
+instance Storable VrStereoConfig where
+  sizeOf _ = 304
+  alignment _ = 4
+  peek _p = do
+    projection <- peekStaticArrayOff 2 (castPtr _p) 0
+    viewOffset <- peekStaticArrayOff 2 (castPtr _p) 128
+    leftLensCenter <- map realToFrac <$> (peekStaticArrayOff 2 (castPtr _p) 256 :: IO [CFloat])
+    rightLensCenter <- map realToFrac <$> (peekStaticArrayOff 2 (castPtr _p) 264 :: IO [CFloat])
+    leftScreenCenter <- map realToFrac <$> (peekStaticArrayOff 2 (castPtr _p) 272 :: IO [CFloat])
+    rightScreenCenter <- map realToFrac <$> (peekStaticArrayOff 2 (castPtr _p) 280 :: IO [CFloat])
+    scale <- map realToFrac <$> (peekStaticArrayOff 2 (castPtr _p) 288 :: IO [CFloat])
+    scaleIn <- map realToFrac <$> (peekStaticArrayOff 2 (castPtr _p) 296 :: IO [CFloat])
+    return $ VrStereoConfig projection viewOffset leftLensCenter rightLensCenter leftScreenCenter rightScreenCenter scale scaleIn
+  poke _p (VrStereoConfig projection viewOffset leftLensCenter rightLensCenter leftScreenCenter rightScreenCenter scale scaleIn) = do
+    pokeStaticArrayOff (castPtr _p) 0 projection
+    pokeStaticArrayOff (castPtr _p) 128 viewOffset
+    pokeStaticArrayOff (castPtr _p) 256 (map realToFrac leftLensCenter :: [CFloat])
+    pokeStaticArrayOff (castPtr _p) 264 (map realToFrac rightLensCenter :: [CFloat])
+    pokeStaticArrayOff (castPtr _p) 272 (map realToFrac leftScreenCenter :: [CFloat])
+    pokeStaticArrayOff (castPtr _p) 280 (map realToFrac rightScreenCenter :: [CFloat])
+    pokeStaticArrayOff (castPtr _p) 288 (map realToFrac scale :: [CFloat])
+    pokeStaticArrayOff (castPtr _p) 296 (map realToFrac scaleIn :: [CFloat])
+    return ()
+
+data FilePathList = FilePathList
+  { filePathlist'capacity :: Integer,
+    filePathList'paths :: [String]
+  }
+  deriving (Eq, Show)
+
+instance Storable FilePathList where
+  sizeOf _ = 16
+  alignment _ = 4
+  peek _p = do
+    capacity <- fromIntegral <$> (peekByteOff _p 0 :: IO CUInt)
+    count <- fromIntegral <$> (peekByteOff _p 4 :: IO CUInt)
+    pathsPtr <- (peekByteOff _p 8 :: IO (Ptr CString))
+    pathsCStrings <- peekArray count pathsPtr
+    paths <- mapM peekCString pathsCStrings
+    return $ FilePathList capacity paths
+  poke _p (FilePathList capacity paths) = do
+    pokeByteOff _p 0 (fromIntegral capacity :: CUInt)
+    pokeByteOff _p 4 (fromIntegral (length paths) :: CUInt)
+    pathsCStrings <- mapM newCString paths
+    pokeByteOff _p 8 =<< newArray pathsCStrings
+    return ()
+
+instance Freeable FilePathList where
+  rlFreeDependents val ptr = do
+    pathsPtr <- (peekByteOff ptr 8 :: IO (Ptr CString))
+    pathsCStrings <- peekArray (length $ filePathList'paths val) pathsPtr
+    mapM_ (c'free . castPtr) pathsCStrings
+    c'free $ castPtr pathsPtr
+
+type LoadFileDataCallback = FunPtr (CString -> Ptr CUInt -> IO (Ptr CUChar))
+
+type SaveFileDataCallback = FunPtr (CString -> Ptr () -> CUInt -> IO CInt)
+
+type LoadFileTextCallback = FunPtr (CString -> IO CString)
+
+type SaveFileTextCallback = FunPtr (CString -> CString -> IO CInt)
+
+type AudioCallback = FunPtr (Ptr () -> CUInt -> IO ())
src/Raylib/Util.hs view
@@ -1,45 +1,129 @@ {-# OPTIONS -Wall #-}
-module Raylib.Util (c'free, pop, popCArray, withArray2D, configsToBitflag, withMaybe, withMaybeCString) where
 
-import Foreign (Ptr, Storable (peek), castPtr, newArray, free, peekArray, with, nullPtr)
-import Control.Monad (forM_)
+module Raylib.Util (c'free, p'free, freeMaybePtr, Freeable (..), rlFreeArray, pop, popCArray, withFreeable, withArray2D, configsToBitflag, withMaybe, withMaybeCString, peekMaybe, peekMaybeOff, pokeMaybe, pokeMaybeOff, peekMaybeArray, newMaybeArray, peekStaticArray, peekStaticArrayOff, pokeStaticArray, pokeStaticArrayOff, rightPad) where
+
+import Control.Monad (forM_, unless)
 import Data.Bits ((.|.))
-import Foreign.C (CString, withCString)
+import Foreign (Ptr, Storable (peek, peekByteOff, poke, sizeOf), castPtr, free, malloc, newArray, nullPtr, peekArray, plusPtr, with, FunPtr)
+import Foreign.C (CInt, CString, CUInt, withCString)
+
 -- Internal utility functions
 
 foreign import ccall "stdlib.h free" c'free :: Ptr () -> IO ()
+foreign import ccall "stdlib.h &free" p'free :: FunPtr (Ptr a -> IO ())
 
-pop :: (Storable a) => Ptr a -> IO a
+freeMaybePtr :: Ptr () -> IO ()
+freeMaybePtr ptr = unless (ptr == nullPtr) (c'free ptr)
+
+class Freeable a where
+  rlFreeDependents :: a -> Ptr a -> IO ()
+  rlFreeDependents _ _ = return ()
+
+  rlFree :: a -> Ptr a -> IO ()
+  rlFree val ptr = rlFreeDependents val ptr >> c'free (castPtr ptr)
+
+instance Freeable CInt
+
+instance Freeable CUInt
+
+rlFreeArray :: (Freeable a,Show a, Storable a) => [a] -> Ptr a -> IO ()
+rlFreeArray arr ptr = do
+  forM_
+    [0 .. length arr - 1]
+    ( \i -> do
+        let val = arr !! i in rlFreeDependents val (plusPtr ptr (i * sizeOf val))
+    )
+  c'free $ castPtr ptr
+
+pop :: (Freeable a, Storable a) => Ptr a -> IO a
 pop ptr = do
-    val <- peek ptr
-    c'free $ castPtr ptr
-    return val
+  val <- peek ptr
+  rlFree val ptr
+  return val
 
-popCArray :: (Storable a) => Int -> Ptr a -> IO [a]
+popCArray :: (Freeable a, Storable a) => Int -> Ptr a -> IO [a]
 popCArray count ptr = do
-    str <- peekArray count ptr
-    c'free $ castPtr ptr
-    return str
+  str <- peekArray count ptr
+  c'free $ castPtr ptr
+  return str
 
+withFreeable :: (Freeable a, Storable a) => a -> (Ptr a -> IO b) -> IO b
+withFreeable val f = do
+  ptr <- malloc
+  poke ptr val
+  result <- f ptr
+  rlFree val ptr
+  return result
+
 withArray2D :: (Storable a) => [[a]] -> (Ptr (Ptr a) -> IO b) -> IO b
 withArray2D arr func = do
-    arrays <- mapM newArray arr
-    ptr <- newArray arrays
-    res <- func ptr
-    forM_ arrays free
-    free ptr
-    return res
+  arrays <- mapM newArray arr
+  ptr <- newArray arrays
+  res <- func ptr
+  forM_ arrays free
+  free ptr
+  return res
 
 configsToBitflag :: (Enum a) => [a] -> Integer
 configsToBitflag = fromIntegral . foldr folder (toEnum 0)
-    where folder a b = fromEnum a .|. b
+  where
+    folder a b = fromEnum a .|. b
 
 withMaybe :: (Storable a) => Maybe a -> (Ptr a -> IO b) -> IO b
 withMaybe a f = case a of
-    (Just val) -> with val f
-    Nothing    -> f nullPtr
+  (Just val) -> with val f
+  Nothing -> f nullPtr
 
 withMaybeCString :: Maybe String -> (CString -> IO b) -> IO b
 withMaybeCString a f = case a of
-    (Just val) -> withCString val f
-    Nothing    -> f nullPtr+  (Just val) -> withCString val f
+  Nothing -> f nullPtr
+
+peekMaybe :: (Storable a) => Ptr (Ptr a) -> IO (Maybe a)
+peekMaybe ptr = do
+  ref <- peek ptr
+  if ref == nullPtr then return Nothing else Just <$> peek ref
+
+peekMaybeOff :: (Storable a) => Ptr (Ptr a) -> Int -> IO (Maybe a)
+peekMaybeOff ptr off = do
+  ref <- peekByteOff ptr off
+  if ref == nullPtr then return Nothing else Just <$> peek ref
+
+pokeMaybe :: (Storable a) => Ptr (Ptr a) -> Maybe a -> IO ()
+pokeMaybe ptr val = case val of
+  Nothing -> poke ptr nullPtr
+  Just a -> with a $ poke ptr
+
+pokeMaybeOff :: (Storable a) => Ptr (Ptr a) -> Int -> Maybe a -> IO ()
+pokeMaybeOff ptr off = pokeMaybe (plusPtr ptr off)
+
+peekMaybeArray :: (Storable a) => Int -> Ptr a -> IO (Maybe [a])
+peekMaybeArray size ptr = if ptr == nullPtr then return Nothing else Just <$> peekArray size ptr
+
+newMaybeArray :: (Storable a) => Maybe [a] -> IO (Ptr a)
+newMaybeArray a = case a of
+  (Just arr) -> newArray arr
+  Nothing -> return nullPtr
+
+peekStaticArray :: (Storable a) => Int -> Ptr a -> IO [a]
+peekStaticArray size ptr = reverse <$> helper size ptr []
+  where
+    helper s p a =
+      if s == 0
+        then return a
+        else do
+          val <- peek p
+          helper (s - 1) (plusPtr p (sizeOf val)) (val : a)
+
+peekStaticArrayOff :: (Storable a) => Int -> Ptr a -> Int -> IO [a]
+peekStaticArrayOff size ptr off = peekStaticArray size (plusPtr ptr off)
+
+pokeStaticArray :: (Storable a) => Ptr a -> [a] -> IO ()
+pokeStaticArray _ [] = return ()
+pokeStaticArray ptr (x : xs) = poke ptr x >> pokeStaticArray (plusPtr ptr $ sizeOf x) xs
+
+pokeStaticArrayOff :: (Storable a) => Ptr a -> Int -> [a] -> IO ()
+pokeStaticArrayOff ptr off = pokeStaticArray (plusPtr ptr off)
+
+rightPad :: Int -> a -> [a] -> [a]
+rightPad size val arr = take size $ arr ++ repeat val