Browse Source

Embed the SDL2 libraries into `vendor:sdl2`

gingerBill 4 years ago
parent
commit
36cb1f868b
74 changed files with 6396 additions and 3 deletions
  1. 5 3
      build.bat
  2. BIN
      vendor/sdl2/SDL2.dll
  3. BIN
      vendor/sdl2/SDL2.lib
  4. 66 0
      vendor/sdl2/image/LICENSE.jpeg.txt
  5. 137 0
      vendor/sdl2/image/LICENSE.png.txt
  6. 25 0
      vendor/sdl2/image/LICENSE.tiff.txt
  7. 34 0
      vendor/sdl2/image/LICENSE.webp.txt
  8. 35 0
      vendor/sdl2/image/LICENSE.zlib.txt
  9. 20 0
      vendor/sdl2/image/README.txt
  10. BIN
      vendor/sdl2/image/SDL2_image.dll
  11. BIN
      vendor/sdl2/image/SDL2_image.lib
  12. BIN
      vendor/sdl2/image/libjpeg-9.dll
  13. BIN
      vendor/sdl2/image/libpng16-16.dll
  14. BIN
      vendor/sdl2/image/libtiff-5.dll
  15. BIN
      vendor/sdl2/image/libwebp-7.dll
  16. 122 0
      vendor/sdl2/image/sdl_image.odin
  17. BIN
      vendor/sdl2/image/zlib1.dll
  18. 32 0
      vendor/sdl2/mixer/LICENSE.FLAC.txt
  19. 5 0
      vendor/sdl2/mixer/LICENSE.modplug.txt
  20. 776 0
      vendor/sdl2/mixer/LICENSE.mpg123.txt
  21. 32 0
      vendor/sdl2/mixer/LICENSE.ogg-vorbis.txt
  22. 48 0
      vendor/sdl2/mixer/LICENSE.opus.txt
  23. 32 0
      vendor/sdl2/mixer/LICENSE.opusfile.txt
  24. BIN
      vendor/sdl2/mixer/SDL2_mixer.dll
  25. BIN
      vendor/sdl2/mixer/SDL2_mixer.lib
  26. BIN
      vendor/sdl2/mixer/libFLAC-8.dll
  27. BIN
      vendor/sdl2/mixer/libmodplug-1.dll
  28. BIN
      vendor/sdl2/mixer/libmpg123-0.dll
  29. BIN
      vendor/sdl2/mixer/libogg-0.dll
  30. BIN
      vendor/sdl2/mixer/libopus-0.dll
  31. BIN
      vendor/sdl2/mixer/libopusfile-0.dll
  32. BIN
      vendor/sdl2/mixer/libvorbis-0.dll
  33. BIN
      vendor/sdl2/mixer/libvorbisfile-3.dll
  34. 221 0
      vendor/sdl2/mixer/sdl_mixer.odin
  35. BIN
      vendor/sdl2/net/SDL2_net.dll
  36. BIN
      vendor/sdl2/net/SDL2_net.lib
  37. 191 0
      vendor/sdl2/net/sdl_net.odin
  38. 317 0
      vendor/sdl2/sdl2.odin
  39. 242 0
      vendor/sdl2/sdl_audio.odin
  40. 65 0
      vendor/sdl2/sdl_blendmode.odin
  41. 44 0
      vendor/sdl2/sdl_cpuinfo.odin
  42. 501 0
      vendor/sdl2/sdl_events.odin
  43. 141 0
      vendor/sdl2/sdl_gamecontroller.odin
  44. 262 0
      vendor/sdl2/sdl_gesture_haptic.odin
  45. 149 0
      vendor/sdl2/sdl_hints.odin
  46. 109 0
      vendor/sdl2/sdl_joystick.odin
  47. 54 0
      vendor/sdl2/sdl_keyboard.odin
  48. 330 0
      vendor/sdl2/sdl_keycode.odin
  49. 77 0
      vendor/sdl2/sdl_log.odin
  50. 76 0
      vendor/sdl2/sdl_messagebox.odin
  51. 18 0
      vendor/sdl2/sdl_metal.odin
  52. 64 0
      vendor/sdl2/sdl_mouse.odin
  53. 44 0
      vendor/sdl2/sdl_mutex.odin
  54. 237 0
      vendor/sdl2/sdl_pixels.odin
  55. 50 0
      vendor/sdl2/sdl_rect.odin
  56. 143 0
      vendor/sdl2/sdl_render.odin
  57. 108 0
      vendor/sdl2/sdl_rwops.odin
  58. 277 0
      vendor/sdl2/sdl_scancode.odin
  59. 163 0
      vendor/sdl2/sdl_stdinc.odin
  60. 111 0
      vendor/sdl2/sdl_surface.odin
  61. 125 0
      vendor/sdl2/sdl_system.odin
  62. 108 0
      vendor/sdl2/sdl_syswm.odin
  63. 38 0
      vendor/sdl2/sdl_thread.odin
  64. 25 0
      vendor/sdl2/sdl_timer.odin
  65. 37 0
      vendor/sdl2/sdl_touch.odin
  66. 306 0
      vendor/sdl2/sdl_video.odin
  67. 24 0
      vendor/sdl2/sdl_vulkan.odin
  68. 173 0
      vendor/sdl2/ttf/LICENSE.freetype.txt
  69. 31 0
      vendor/sdl2/ttf/LICENSE.zlib.txt
  70. BIN
      vendor/sdl2/ttf/SDL2_ttf.dll
  71. BIN
      vendor/sdl2/ttf/SDL2_ttf.lib
  72. BIN
      vendor/sdl2/ttf/libfreetype-6.dll
  73. 166 0
      vendor/sdl2/ttf/sdl_ttf.odin
  74. BIN
      vendor/sdl2/ttf/zlib1.dll

+ 5 - 3
build.bat

@@ -68,10 +68,12 @@ set linker_settings=%libs% %linker_flags%
 del *.pdb > NUL 2> NUL
 del *.pdb > NUL 2> NUL
 del *.ilk > NUL 2> NUL
 del *.ilk > NUL 2> NUL
 
 
-cl %compiler_settings% "src\main.cpp" "src\libtommath.cpp" /link %linker_settings% -OUT:%exe_name%
+rem cl %compiler_settings% "src\main.cpp" "src\libtommath.cpp" /link %linker_settings% -OUT:%exe_name%
+cl %compiler_settings% "src\main.cpp" "src\libtommath.cpp" /link %linker_settings% -OUT:%exe_name% ^
+	&& odin run examples/demo -vet
 
 
-if %errorlevel% neq 0 goto end_of_build
-if %release_mode% EQU 0 odin run examples/demo/demo.odin
+rem if %errorlevel% neq 0 goto end_of_build
+rem if %release_mode% EQU 0 odin check examples/all
 
 
 del *.obj > NUL 2> NUL
 del *.obj > NUL 2> NUL
 
 

BIN
vendor/sdl2/SDL2.dll


BIN
vendor/sdl2/SDL2.lib


+ 66 - 0
vendor/sdl2/image/LICENSE.jpeg.txt

@@ -0,0 +1,66 @@
+The source code to this library used with SDL_image can be found here:
+https://hg.libsdl.org/SDL_image/file/default/external
+---
+
+LEGAL ISSUES
+============
+
+In plain English:
+
+1. We don't promise that this software works.  (But if you find any bugs,
+   please let us know!)
+2. You can use this software for whatever you want.  You don't have to pay us.
+3. You may not pretend that you wrote this software.  If you use it in a
+   program, you must acknowledge somewhere in your documentation that
+   you've used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose.  This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-2016, Thomas G. Lane, Guido Vollbeding.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library.  If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it.  This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+The Unix configuration script "configure" was produced with GNU Autoconf.
+It is copyright by the Free Software Foundation but is freely distributable.
+The same holds for its supporting scripts (config.guess, config.sub,
+ltmain.sh).  Another support script, install-sh, is copyright by X Consortium
+but is also freely distributable.
+
+The IJG distribution formerly included code to read and write GIF files.
+To avoid entanglement with the Unisys LZW patent (now expired), GIF reading
+support has been removed altogether, and the GIF writer has been simplified
+to produce "uncompressed GIFs".  This technique does not use the LZW
+algorithm; the resulting GIF files are larger than usual, but are readable
+by all standard GIF decoders.

+ 137 - 0
vendor/sdl2/image/LICENSE.png.txt

@@ -0,0 +1,137 @@
+The source code to this library used with SDL_image can be found here:
+https://hg.libsdl.org/SDL_image/file/default/external
+---
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+=========================================
+
+PNG Reference Library License version 2
+---------------------------------------
+
+ * Copyright (c) 1995-2019 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2019 Cosmin Truta.
+ * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * Copyright (c) 1996-1997 Andreas Dilger.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+
+The software is supplied "as is", without warranty of any kind,
+express or implied, including, without limitation, the warranties
+of merchantability, fitness for a particular purpose, title, and
+non-infringement.  In no event shall the Copyright owners, or
+anyone distributing the software, be liable for any damages or
+other liability, whether in contract, tort or otherwise, arising
+from, out of, or in connection with the software, or the use or
+other dealings in the software, even if advised of the possibility
+of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute
+this software, or portions hereof, for any purpose, without fee,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you
+    must not claim that you wrote the original software.  If you
+    use this software in a product, an acknowledgment in the product
+    documentation would be appreciated, but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must
+    not be misrepresented as being the original software.
+
+ 3. This Copyright notice may not be removed or altered from any
+    source or altered source distribution.
+
+
+PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+-----------------------------------------------------------------------
+
+libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
+Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
+derived from libpng-1.0.6, and are distributed according to the same
+disclaimer and license as libpng-1.0.6 with the following individuals
+added to the list of Contributing Authors:
+
+    Simon-Pierre Cadieux
+    Eric S. Raymond
+    Mans Rullgard
+    Cosmin Truta
+    Gilles Vollant
+    James Yu
+    Mandar Sahastrabuddhe
+    Google Inc.
+    Vadim Barkov
+
+and with the following additions to the disclaimer:
+
+    There is no warranty against interference with your enjoyment of
+    the library or against infringement.  There is no warranty that our
+    efforts or the library will fulfill any of your particular purposes
+    or needs.  This library is provided with all faults, and the entire
+    risk of satisfactory quality, performance, accuracy, and effort is
+    with the user.
+
+Some files in the "contrib" directory and some configure-generated
+files that are distributed with libpng have other copyright owners, and
+are released under other open source licenses.
+
+libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
+libpng-0.96, and are distributed according to the same disclaimer and
+license as libpng-0.96, with the following individuals added to the
+list of Contributing Authors:
+
+    Tom Lane
+    Glenn Randers-Pehrson
+    Willem van Schaik
+
+libpng versions 0.89, June 1996, through 0.96, May 1997, are
+Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
+and are distributed according to the same disclaimer and license as
+libpng-0.88, with the following individuals added to the list of
+Contributing Authors:
+
+    John Bowler
+    Kevin Bracey
+    Sam Bushell
+    Magnus Holmgren
+    Greg Roelofs
+    Tom Tanner
+
+Some files in the "scripts" directory have other copyright owners,
+but are released under this license.
+
+libpng versions 0.5, May 1995, through 0.88, January 1996, are
+Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+
+For the purposes of this copyright and license, "Contributing Authors"
+is defined as the following set of individuals:
+
+    Andreas Dilger
+    Dave Martindale
+    Guy Eric Schalnat
+    Paul Schmidt
+    Tim Wegner
+
+The PNG Reference Library is supplied "AS IS".  The Contributing
+Authors and Group 42, Inc. disclaim all warranties, expressed or
+implied, including, without limitation, the warranties of
+merchantability and of fitness for any purpose.  The Contributing
+Authors and Group 42, Inc. assume no liability for direct, indirect,
+incidental, special, exemplary, or consequential damages, which may
+result from the use of the PNG Reference Library, even if advised of
+the possibility of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, without fee, subject
+to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented.
+
+ 2. Altered versions must be plainly marked as such and must not
+    be misrepresented as being the original source.
+
+ 3. This Copyright notice may not be removed or altered from any
+    source or altered source distribution.
+
+The Contributing Authors and Group 42, Inc. specifically permit,
+without fee, and encourage the use of this source code as a component
+to supporting the PNG file format in commercial products.  If you use
+this source code in a product, acknowledgment is not required but would
+be appreciated.

+ 25 - 0
vendor/sdl2/image/LICENSE.tiff.txt

@@ -0,0 +1,25 @@
+The source code to this library used with SDL_image can be found here:
+https://hg.libsdl.org/SDL_image/file/default/external
+---
+
+Copyright (c) 1988-1997 Sam Leffler
+Copyright (c) 1991-1997 Silicon Graphics, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software and 
+its documentation for any purpose is hereby granted without fee, provided
+that (i) the above copyright notices and this permission notice appear in
+all copies of the software and related documentation, and (ii) the names of
+Sam Leffler and Silicon Graphics may not be used in any advertising or
+publicity relating to the software without the specific, prior written
+permission of Sam Leffler and Silicon Graphics.
+
+THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
+EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
+WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
+
+IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
+LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+OF THIS SOFTWARE.

+ 34 - 0
vendor/sdl2/image/LICENSE.webp.txt

@@ -0,0 +1,34 @@
+The source code to this library used with SDL_image can be found here:
+https://hg.libsdl.org/SDL_image/file/default/external
+---
+
+Copyright (c) 2010, Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  * Neither the name of Google nor the names of its contributors may
+    be used to endorse or promote products derived from this software
+    without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+

+ 35 - 0
vendor/sdl2/image/LICENSE.zlib.txt

@@ -0,0 +1,35 @@
+The source code to this library used with SDL_image can be found here:
+https://hg.libsdl.org/SDL_image/file/default/external
+---
+
+Copyright notice:
+
+ (C) 1995-2017 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  [email protected]          [email protected]
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign.  The sources are provided for free but without
+warranty of any kind.  The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes.  Please read
+the FAQ for more information on the distribution of modified source versions.

+ 20 - 0
vendor/sdl2/image/README.txt

@@ -0,0 +1,20 @@
+This library is distributed under the terms of the zlib license:
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+The source is available from the SDL website:
+http://www.libsdl.org/projects/SDL_image

BIN
vendor/sdl2/image/SDL2_image.dll


BIN
vendor/sdl2/image/SDL2_image.lib


BIN
vendor/sdl2/image/libjpeg-9.dll


BIN
vendor/sdl2/image/libpng16-16.dll


BIN
vendor/sdl2/image/libtiff-5.dll


BIN
vendor/sdl2/image/libwebp-7.dll


+ 122 - 0
vendor/sdl2/image/sdl_image.odin

@@ -0,0 +1,122 @@
+package sdl2_image
+
+import "core:c"
+import SDL ".."
+
+when ODIN_OS == "windows" do foreign import lib "SDL2_image.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2_image"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2_image"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2_image"
+
+bool :: SDL.bool;
+
+MAJOR_VERSION :: 2;
+MINOR_VERSION :: 0;
+PATCHLEVEL    :: 5;
+
+@(default_calling_convention="c", link_prefix="IMG_")
+foreign lib {
+	Linked_Version :: proc() -> ^SDL.version ---
+}
+
+InitFlag :: enum c.int {
+	JPG  = 0,
+	PNG  = 1,
+	TIF  = 2,
+	WEBP = 3,
+}
+
+InitFlags :: distinct bit_set[InitFlag; c.int];
+
+INIT_JPG  :: InitFlags{.JPG};
+INIT_PNG  :: InitFlags{.PNG};
+INIT_TIF  :: InitFlags{.TIF};
+INIT_WEBP :: InitFlags{.WEBP};
+
+/* Animated image support
+   Currently only animated GIFs are supported.
+ */
+Animation :: struct {
+	w, h:   c.int,
+	count:  c.int,
+	frames: [^]^SDL.Surface,
+	delays: [^]c.int,
+}
+
+/* We'll use SDL for reporting errors */
+SetError :: SDL.SetError;
+GetError :: SDL.GetError;
+
+@(default_calling_convention="c", link_prefix="IMG_")
+foreign lib {
+	Init :: proc(flags: InitFlags) -> c.int ---
+	Quit :: proc() ---
+
+	/* Load an image from an SDL data source.
+	   The 'type' may be one of: "BMP", "GIF", "PNG", etc.
+	   If the image format supports a transparent pixel, SDL will set the
+	   colorkey for the surface.  You can enable RLE acceleration on the
+	   surface afterwards by calling:
+	    SDL_SetColorKey(image, SDL_RLEACCEL, image->format->colorkey);
+	 */
+	LoadTyped_RW :: proc(src: ^SDL.RWops, freesrc: bool, type: cstring) -> ^SDL.Surface ---
+	/* Convenience functions */
+	Load    :: proc(file: cstring) -> ^SDL.Surface ---
+	Load_RW :: proc(src: ^SDL.RWops, freesrc: bool) -> ^SDL.Surface ---
+
+	/* Load an image directly into a render texture. */
+	LoadTexture          :: proc(renderer: ^SDL.Renderer, file: cstring) -> ^SDL.Texture ---
+	LoadTexture_RW       :: proc(renderer: ^SDL.Renderer, src: ^SDL.RWops, freesrc: bool) -> ^SDL.Texture ---
+	LoadTextureTyped_RW  :: proc(renderer: ^SDL.Renderer, src: ^SDL.RWops, freesrc: bool, type: cstring) -> ^SDL.Texture ---
+
+	/* Functions to detect a file type, given a seekable source */
+	isICO  :: proc(src: ^SDL.RWops) -> bool ---
+	isCUR  :: proc(src: ^SDL.RWops) -> bool ---
+	isBMP  :: proc(src: ^SDL.RWops) -> bool ---
+	isGIF  :: proc(src: ^SDL.RWops) -> bool ---
+	isJPG  :: proc(src: ^SDL.RWops) -> bool ---
+	isLBM  :: proc(src: ^SDL.RWops) -> bool ---
+	isPCX  :: proc(src: ^SDL.RWops) -> bool ---
+	isPNG  :: proc(src: ^SDL.RWops) -> bool ---
+	isPNM  :: proc(src: ^SDL.RWops) -> bool ---
+	isSVG  :: proc(src: ^SDL.RWops) -> bool ---
+	isTIF  :: proc(src: ^SDL.RWops) -> bool ---
+	isXCF  :: proc(src: ^SDL.RWops) -> bool ---
+	isXPM  :: proc(src: ^SDL.RWops) -> bool ---
+	isXV   :: proc(src: ^SDL.RWops) -> bool ---
+	isWEBP :: proc(src: ^SDL.RWops) -> bool ---
+
+	/* Individual loading functions */
+	LoadICO_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadCUR_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadBMP_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadGIF_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadJPG_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadLBM_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadPCX_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadPNG_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadPNM_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadSVG_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadTGA_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadTIF_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadXCF_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadXPM_RW  :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadXV_RW   :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+	LoadWEBP_RW :: proc(src: ^SDL.RWops) -> ^SDL.Surface ---
+
+	ReadXPMFromArray :: proc(xpm: [^]cstring) -> ^SDL.Surface ---
+
+	/* Individual saving functions */
+	SavePNG    :: proc(surface: ^SDL.Surface, file: cstring) -> c.int ---
+	SavePNG_RW :: proc(surface: ^SDL.Surface, dst: ^SDL.RWops, freedst: bool) -> c.int ---
+	SaveJPG    :: proc(surface: ^SDL.Surface, file: cstring, quality: c.int) -> c.int ---
+	SaveJPG_RW :: proc(surface: ^SDL.Surface, dst: ^SDL.RWops, freedst: bool, quality: c.int) -> c.int ---
+
+	LoadAnimation         :: proc(file: cstring) -> ^Animation ---
+	LoadAnimation_RW      :: proc(src: ^SDL.RWops, freesrc: bool) -> ^Animation ---
+	LoadAnimationTyped_RW :: proc(src: ^SDL.RWops, freesrc: bool, type: cstring) -> ^Animation ---
+	FreeAnimation         :: proc(anim: ^Animation) ---
+
+	/* Individual loading functions */
+	LoadGIFAnimation_RW :: proc(src: ^SDL.RWops) -> ^Animation ---
+}

BIN
vendor/sdl2/image/zlib1.dll


+ 32 - 0
vendor/sdl2/mixer/LICENSE.FLAC.txt

@@ -0,0 +1,32 @@
+The source code to this library used with SDL_mixer can be found here:
+https://hg.libsdl.org/SDL_mixer/file/default/external
+---
+
+Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007  Josh Coalson
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 5 - 0
vendor/sdl2/mixer/LICENSE.modplug.txt

@@ -0,0 +1,5 @@
+The source code to this library used with SDL_mixer can be found here:
+https://hg.libsdl.org/SDL_mixer/file/default/external
+---
+
+ModPlug-XMMS and libmodplug are now in the public domain.

+ 776 - 0
vendor/sdl2/mixer/LICENSE.mpg123.txt

@@ -0,0 +1,776 @@
+The source code to this library used with SDL_mixer can be found here:
+https://hg.libsdl.org/SDL_mixer/file/default/external
+---
+
+This is the file that contains the terms of use, copying, etc. for the mpg123 distribution package.
+
+Main message, to include in "About ..." boxes, etc:
+
+	Copyright (c) 1995-2013 by Michael Hipp and others,
+	free software under the terms of the LGPL v2.1
+
+There is an attempt to cover the actual list of authors in the AUTHORS file.
+Project maintainer since 2006 is Thomas Orgis and many people have contributed
+since the Michael Hipp era, but he stays the initial source and it would
+be impractical to count them all individually, so it's "and others".
+Source files contain the phrase "the mpg123 project" to the same effect
+in their license boilerplate; especially those that were added after
+maintainership changed. The person mainly responsible for the first version
+is usually named in the phrase "initially written by ...".
+
+All files in the distribution that don't carry a license note on their own are
+licensed under the terms of the LGPL 2.1; exceptions may apply, especially to
+files not in the official distribution but in the revision control repository.
+
+The formal license text follows.
+
+=======================
+1. The LGPL version 2.1
+=======================
+
+
+  GNU LESSER GENERAL PUBLIC LICENSE
+       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+     END OF TERMS AND CONDITIONS
+
+
+====================
+2. The GPL version 2
+====================
+
+
+   GNU GENERAL PUBLIC LICENSE
+       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+     END OF TERMS AND CONDITIONS

+ 32 - 0
vendor/sdl2/mixer/LICENSE.ogg-vorbis.txt

@@ -0,0 +1,32 @@
+The source code to this library used with SDL_mixer can be found here:
+https://hg.libsdl.org/SDL_image/file/default/external
+---
+
+Copyright (c) 2002-2008 Xiph.org Foundation
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 48 - 0
vendor/sdl2/mixer/LICENSE.opus.txt

@@ -0,0 +1,48 @@
+The source code to this library used with SDL_mixer can be found here:
+https://hg.libsdl.org/SDL_mixer/file/default/external
+---
+
+Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic,
+                    Jean-Marc Valin, Timothy B. Terriberry,
+                    CSIRO, Gregory Maxwell, Mark Borgerding,
+                    Erik de Castro Lopo
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of Internet Society, IETF or IETF Trust, nor the 
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Opus is subject to the royalty-free patent licenses which are
+specified at:
+
+Xiph.Org Foundation:
+https://datatracker.ietf.org/ipr/1524/
+
+Microsoft Corporation:
+https://datatracker.ietf.org/ipr/1914/
+
+Broadcom Corporation:
+https://datatracker.ietf.org/ipr/1526/

+ 32 - 0
vendor/sdl2/mixer/LICENSE.opusfile.txt

@@ -0,0 +1,32 @@
+The source code to this library used with SDL_mixer can be found here:
+https://hg.libsdl.org/SDL_mixer/file/default/external
+---
+
+Copyright (c) 1994-2013 Xiph.Org Foundation and contributors
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.Org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

BIN
vendor/sdl2/mixer/SDL2_mixer.dll


BIN
vendor/sdl2/mixer/SDL2_mixer.lib


BIN
vendor/sdl2/mixer/libFLAC-8.dll


BIN
vendor/sdl2/mixer/libmodplug-1.dll


BIN
vendor/sdl2/mixer/libmpg123-0.dll


BIN
vendor/sdl2/mixer/libogg-0.dll


BIN
vendor/sdl2/mixer/libopus-0.dll


BIN
vendor/sdl2/mixer/libopusfile-0.dll


BIN
vendor/sdl2/mixer/libvorbis-0.dll


BIN
vendor/sdl2/mixer/libvorbisfile-3.dll


+ 221 - 0
vendor/sdl2/mixer/sdl_mixer.odin

@@ -0,0 +1,221 @@
+package sdl2_mixer
+
+import "core:c"
+import SDL ".."
+
+when ODIN_OS == "windows" do foreign import lib "SDL2_mixer.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2_mixer"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2_mixer"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2_mixer"
+
+
+MAJOR_VERSION :: 2;
+MINOR_VERSION :: 0;
+PATCHLEVEL    :: 4;
+
+CHANNELS :: 8;
+
+
+bool :: SDL.bool;
+
+
+InitFlag :: enum c.int {
+	FLAC   = 0,
+	MOD    = 1,
+	MP3    = 3,
+	OGG    = 4,
+	MID    = 5,
+	OPUS   = 6,
+}
+
+InitFlags :: distinct bit_set[InitFlag; c.int];
+
+INIT_FLAC :: InitFlags{.FLAC};
+INIT_MOD  :: InitFlags{.MOD};
+INIT_MP3  :: InitFlags{.MP3};
+INIT_OGG  :: InitFlags{.OGG};
+INIT_MID  :: InitFlags{.MID};
+INIT_OPUS :: InitFlags{.OPUS};
+
+DEFAULT_FREQUENCY :: 44100;
+DEFAULT_FORMAT :: SDL.AUDIO_S16SYS;
+DEFAULT_CHANNELS :: 2;
+MAX_VOLUME :: SDL.MIX_MAXVOLUME;
+
+Chunk :: struct {
+	allocated: c.int,
+	abuf:      [^]u8,
+	alen:      u32,
+	volume:    u8,  /* Per-sample volume, 0-128 */
+}
+
+Fading :: enum c.int {
+	NO_FADING,
+	FADING_OUT,
+	FADING_IN,
+}
+
+NO_FADING  :: Fading.NO_FADING;
+FADING_OUT :: Fading.FADING_OUT;
+FADING_IN  :: Fading.FADING_IN;
+
+MusicType :: enum c.int {
+	NONE,
+	CMD,
+	WAV,
+	MOD,
+	MID,
+	OGG,
+	MP3,
+	MP3_MAD_UNUSED,
+	FLAC,
+	MODPLUG_UNUSED,
+	OPUS,
+}
+
+MUS_NONE           :: MusicType.NONE;
+MUS_CMD            :: MusicType.CMD;
+MUS_WAV            :: MusicType.WAV;
+MUS_MOD            :: MusicType.MOD;
+MUS_MID            :: MusicType.MID;
+MUS_OGG            :: MusicType.OGG;
+MUS_MP3            :: MusicType.MP3;
+MUS_MP3_MAD_UNUSED :: MusicType.MP3_MAD_UNUSED;
+MUS_FLAC           :: MusicType.FLAC;
+MUS_MODPLUG_UNUSED :: MusicType.MODPLUG_UNUSED;
+MUS_OPUS           :: MusicType.OPUS;
+
+Music :: struct {};
+
+
+
+/* We'll use SDL for reporting errors */
+SetError   :: SDL.SetError;
+GetError   :: SDL.GetError;
+ClearError :: SDL.ClearError;
+
+Mix_LoadWAV :: #force_inline proc "c" (file: cstring) -> ^Chunk {
+	return LoadWAV_RW(SDL.RWFromFile(file, "rb"), true);
+}
+
+
+MixFunc :: proc "c" (udata: rawptr, stream: [^]u8, len: c.int);
+
+@(default_calling_convention="c", link_prefix="Mix_")
+foreign lib {
+	Linked_Version :: proc() -> ^SDL.version ---
+
+	Init :: proc(flags: InitFlags) -> c.int ---
+	Quit :: proc() ---
+
+	OpenAudio            :: proc(frequency: c.int, format: u16, channels: c.int, chunksize: c.int) -> c.int ---
+	OpenAudioDevice      :: proc(frequency: c.int, format: u16, channels: c.int, chunksize: c.int, device: cstring, allowed_changed: c.int) -> c.int ---
+	AllocateChannels     :: proc(numchans: c.int) -> c.int ---
+	QuerySpec            :: proc(frequency: ^c.int, format: ^u16, channels: ^c.int) -> c.int ---
+	LoadWAV_RW           :: proc(src: ^SDL.RWops, freesrc: bool) -> ^Chunk ---
+	LoadMUS              :: proc(file: cstring) -> ^Music ---
+	LoadMUS_RW           :: proc(src: ^SDL.RWops, freesrc: bool) -> ^Music ---
+	LoadMUSType_RW       :: proc(src: ^SDL.RWops, type: MusicType, freesrc: bool) -> ^Music ---
+	QuickLoad_WAV        :: proc(mem: [^]u8) -> ^Chunk ---
+	QuickLoad_RAW        :: proc(mem: [^]u8, len: u32) -> ^Chunk ---
+	FreeChunk            :: proc(chunk: ^Chunk) ---
+	FreeMusic            :: proc(music: ^Music) ---
+	GetNumChunkDecoders  :: proc() -> c.int ---
+	GetChunkDecoder      :: proc(index: c.int) -> cstring ---
+	HasChunkDecoder      :: proc(name: cstring) -> bool ---
+	GetNumMusicDecoders  :: proc() -> c.int ---
+	GetMusicDecoder      :: proc(index: c.int) -> cstring ---
+	HasMusicDecoder      :: proc(name: cstring) -> bool ---
+	GetMusicType         :: proc(music: ^Music) -> MusicType ---
+	GetMusicTitle        :: proc(music: ^Music) -> cstring ---
+	GetMusicTitleTag     :: proc(music: ^Music) -> cstring ---
+	GetMusicArtistTag    :: proc(music: ^Music) -> cstring ---
+	GetMusicAlbumTag     :: proc(music: ^Music) -> cstring ---
+	GetMusicCopyrightTag :: proc(music: ^Music) -> cstring ---
+
+	SetPostMix           :: proc(mix_func: MixFunc, arg: rawptr) ---
+	HookMusic            :: proc(mix_func: MixFunc, arg: rawptr) ---
+	HookMusicFinished    :: proc(music_finished: proc "c" ()) ---
+	GetMusicHookData     :: proc() -> rawptr ---
+
+	ChannelFinished      :: proc(channel_finished: proc "c" (channel: c.int)) ---
+}
+
+CHANNEL_POST :: -2;
+
+EffectFunc_t :: proc "c" (chan: c.int, stream: rawptr, len: c.int, udata: rawptr);
+EffectDone_t :: proc "c" (chan: c.int, udata: rawptr);
+
+EFFECTSMAXSPEED :: "MIX_EFFECTSMAXSPEED";
+
+PlayChannel :: #force_inline proc "c" (channel: c.int, chunk: ^Chunk, loops: c.int) -> c.int {
+	return PlayChannelTimed(channel, chunk, loops, -1);
+}
+FadeInChannel :: #force_inline proc "c" (channel: c.int, chunk: ^Chunk, loops: c.int, ms: c.int) -> c.int {
+	return FadeInChannelTimed(channel, chunk, loops, ms, -1);
+}
+
+
+@(default_calling_convention="c", link_prefix="Mix_")
+foreign lib {
+	RegisterEffect        :: proc(chan: c.int, f: EffectFunc_t, d: EffectDone_t, arg: rawptr) -> c.int ---
+	UnregisterEffect      :: proc(channel: c.int, f: EffectFunc_t) -> c.int ---
+	UnregisterAllEffects  :: proc(channel: c.int) -> c.int ---
+
+	SetPanning            :: proc(channel: c.int, left, right: u8) -> c.int ---
+	SetPosition           :: proc(channel: c.int, angle: i16, distance: u8) -> c.int ---
+	SetDistance           :: proc(channel: c.int, distance: u8) -> c.int ---
+	SetReverseStereo      :: proc(channel: c.int, flip: bool) -> c.int ---
+	ReserveChannels       :: proc(num: c.int) -> c.int ---
+	GroupChannel          :: proc(which: c.int, tag: c.int) -> c.int ---
+	GroupChannels         :: proc(from, to: c.int, tag: c.int) -> c.int ---
+	GroupAvailable        :: proc(tag: c.int) -> c.int ---
+	GroupCount            :: proc(tag: c.int) -> c.int ---
+	GroupOldest           :: proc(tag: c.int) -> c.int ---
+	GroupNewer            :: proc(tag: c.int) -> c.int ---
+	PlayChannelTimed      :: proc(channel: c.int, chunk: ^Chunk, loops: c.int, ticks: c.int) -> c.int ---
+	PlayMusic             :: proc(music: ^Music, loops: c.int) -> c.int ---
+	FadeInMusic           :: proc(music: ^Music, loops: c.int, ms: c.int) -> c.int ---
+	FadeInMusicPos        :: proc(music: ^Music, loops: c.int, ms: c.int, position: f64) -> c.int ---
+	FadeInChannelTimed    :: proc(channel: c.int, chunk: ^Chunk, loops: c.int, ms: c.int, ticks: c.int) -> c.int ---
+	Volume                :: proc(channel: c.int, volume: c.int) -> c.int ---
+	VolumeChunk           :: proc(chunk: ^Chunk, volume: c.int) -> c.int ---
+	VolumeMusic           :: proc(volume: c.int) -> c.int ---
+	GetMusicVolume        :: proc(music: ^Music) -> c.int ---
+	HaltChannel           :: proc(channel: c.int) -> c.int ---
+	HaltGroup             :: proc(tag: c.int) -> c.int ---
+	HaltMusic             :: proc() -> c.int ---
+	ExpireChannel         :: proc(channel: c.int, ticks: c.int) -> c.int ---
+	FadeOutChannel        :: proc(which: c.int, ms: c.int) -> c.int ---
+	FadeOutGroup          :: proc(tag: c.int, ms: c.int) -> c.int ---
+	FadeOutMusic          :: proc(ms: c.int) -> c.int ---
+	FadingMusic           :: proc() -> Fading ---
+	FadingChannel         :: proc(which: c.int) -> Fading ---
+	Pause                 :: proc(channel: c.int) ---
+	Resume                :: proc(channel: c.int) ---
+	Paused                :: proc(channel: c.int) -> c.int ---
+	PauseMusic            :: proc() ---
+	ResumeMusic           :: proc() ---
+	RewindMusic           :: proc() ---
+	PausedMusic           :: proc() -> c.int ---
+	ModMusicJumpToOrder   :: proc(order: c.int) -> c.int ---
+	SetMusicPosition      :: proc(position: f64) -> c.int ---
+	GetMusicPosition      :: proc(music: ^Music) -> f64 ---
+	MusicDuration         :: proc(music: ^Music) -> f64 ---
+	GetMusicLoopStartTime :: proc(music: ^Music) -> f64 ---
+	GetMusicLoopEndTime   :: proc(music: ^Music) -> f64 ---
+	GetMusicLoopLengthTime:: proc(music: ^Music) -> f64 ---
+	Playing               :: proc(channel: c.int) -> c.int ---
+	PlayingMusic          :: proc() -> c.int ---
+	SetMusicCMD           :: proc(command: cstring) -> c.int ---
+	SetSynchroValue       :: proc(value: c.int) -> c.int ---
+	GetSynchroValue       :: proc() -> c.int ---
+	SetSoundFonts         :: proc(paths: cstring) -> c.int ---
+	GetSoundFonts         :: proc() -> cstring ---
+	EachSoundFont         :: proc(function : proc "c" (cstring, rawptr) -> c.int, data: rawptr) -> c.int ---
+	SetTimidityCfg        :: proc(path: cstring) -> c.int ---
+	GetTimidityCfg        :: proc() -> cstring ---
+	GetChunk              :: proc(channel: c.int) -> ^Chunk ---
+	CloseAudio            :: proc() ---
+}
+

BIN
vendor/sdl2/net/SDL2_net.dll


BIN
vendor/sdl2/net/SDL2_net.lib


+ 191 - 0
vendor/sdl2/net/sdl_net.odin

@@ -0,0 +1,191 @@
+package sdl2_net
+
+import "core:c"
+import SDL ".."
+
+when ODIN_OS == "windows" do foreign import lib "SDL2_net.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2_net"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2_net"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2_net"
+
+bool :: SDL.bool;
+
+MAJOR_VERSION :: 2;
+MINOR_VERSION :: 0;
+PATCHLEVEL    :: 1;
+
+IPaddress :: struct {
+	host: u32,            /* 32-bit IPv4 host address */
+	port: u16,            /* 16-bit protocol port */
+}
+
+INADDR_ANY       :: 0x00000000;
+INADDR_NONE      :: 0xFFFFFFFF;
+INADDR_LOOPBACK  :: 0x7f000001;
+INADDR_BROADCAST :: 0xFFFFFFFF;
+
+
+@(default_calling_convention="c", link_prefix="SDLNet_")
+foreign lib {
+	Linked_Version :: proc() -> ^SDL.version ---
+
+	Init :: proc() -> c.int ---
+	Quit :: proc() ---
+
+	ResolveHost       :: proc(address: ^IPaddress, host: cstring, port: u16) -> c.int ---
+	ResolveIP         :: proc(ip: ^IPaddress) -> cstring ---
+	GetLocalAddresses :: proc(addresses: ^IPaddress, maxcount: c.int) -> c.int ---
+}
+
+
+/***********************************************************************/
+/* TCP network API                                                     */
+/***********************************************************************/
+
+TCPsocket :: distinct rawptr;
+
+@(default_calling_convention="c", link_prefix="SDLNet_")
+foreign lib {
+	TCP_Open           :: proc(ip: ^IPaddress) -> TCPsocket ---
+	TCP_Accept         :: proc(server: TCPsocket) -> TCPsocket ---
+	TCP_GetPeerAddress :: proc(sock: TCPsocket) -> ^IPaddress ---
+	TCP_Send           :: proc(sock: TCPsocket, data: rawptr, len: c.int) -> c.int ---
+	TCP_Recv           :: proc(sock: TCPsocket, data: rawptr, maxlen: c.int) -> c.int ---
+	TCP_Close          :: proc(sock: TCPsocket) ---
+}
+
+
+/* The maximum channels on a a UDP socket */
+MAX_UDPCHANNELS  :: 32;
+/* The maximum addresses bound to a single UDP socket channel */
+MAX_UDPADDRESSES :: 4;
+
+UDPsocket :: distinct rawptr;
+UDPpacket :: struct {
+	channel: c.int,     /* The src/dst channel of the packet */
+	data:    [^]u8,     /* The packet data */
+	len:     c.int,     /* The length of the packet data */
+	maxlen:  c.int,     /* The size of the data buffer */
+	status:  c.int,     /* packet status after sending */
+	address: IPaddress, /* The source/dest address of an incoming/outgoing packet */
+}
+
+
+/***********************************************************************/
+/* UDP network API                                                     */
+/***********************************************************************/
+
+@(default_calling_convention="c", link_prefix="SDLNet_")
+foreign lib {
+	AllocPacket  :: proc(size: c.int) -> ^UDPpacket ---
+	ResizePacket :: proc(packet: ^UDPpacket, newsize: c.int) -> c.int ---
+	FreePacket   :: proc(packet: ^UDPpacket) ---
+
+	AllocPacketV :: proc(howmany: c.int, size: c.int) -> [^]^UDPpacket ---
+	FreePacketV  :: proc(packetV: [^]^UDPpacket) ---
+
+
+	UDP_Open           :: proc(port: u16) -> UDPsocket ---
+	UDP_SetPacketLoss  :: proc(sock: UDPsocket, percent: c.int) ---
+	UDP_Bind           :: proc(sock: UDPsocket, channel: c.int, address: ^IPaddress) -> c.int ---
+	UDP_Unbind         :: proc(sock: UDPsocket, channel: c.int) ---
+	UDP_GetPeerAddress :: proc(sock: UDPsocket, channel: c.int) -> IPaddress ---
+	UDP_SendV          :: proc(sock: UDPsocket, packets: [^]^UDPpacket, npackets: c.int) -> c.int ---
+	UDP_Send           :: proc(sock: UDPsocket, channel: c.int, packet: ^UDPpacket) -> c.int ---
+	UDP_RecvV          :: proc(sock: UDPsocket, packets: [^]^UDPpacket) -> c.int ---
+	UDP_Recv           :: proc(sock: UDPsocket, packet: ^UDPpacket) -> c.int ---
+	UDP_Close          :: proc(sock: UDPsocket) ---
+}
+
+AllocPacketSlice :: proc "c" (howmany: c.int, size: c.int) -> []^UDPpacket {
+	if packets := AllocPacketV(howmany, size); packets != nil {
+		return packets[:howmany];
+	}
+	return nil;
+}
+FreePacketSlice :: proc "c" (packets: []^UDPpacket) {
+	FreePacketV(raw_data(packets));
+}
+
+UDP_SendSlice :: proc "c" (sock: UDPsocket, packets: []^UDPpacket) -> c.int {
+	return UDP_SendV(sock, raw_data(packets), c.int(len(packets)));
+}
+
+
+/***********************************************************************/
+/* Hooks for checking sockets for available data                       */
+/***********************************************************************/
+
+SocketSet :: distinct rawptr;
+
+/* Any network socket can be safely cast to this socket type */
+GenericSocket :: ^struct { ready: c.int };
+
+TCP_AddSocket :: #force_inline proc "c" (set: SocketSet, sock: TCPsocket) -> c.int {
+	return AddSocket(set, (GenericSocket)(sock));
+}
+UDP_AddSocket :: #force_inline proc "c" (set: SocketSet, sock: UDPsocket) -> c.int {
+	return AddSocket(set, (GenericSocket)(sock));
+}
+TCP_DelSocket :: #force_inline proc "c" (set: SocketSet, sock: TCPsocket) -> c.int {
+	return DelSocket(set, (GenericSocket)(sock));
+}
+UDP_DelSocket :: #force_inline proc "c" (set: SocketSet, sock: UDPsocket) -> c.int {
+	return DelSocket(set, (GenericSocket)(sock));
+}
+
+SocketReady :: #force_inline proc "c" (sock: rawptr) -> bool {
+	s := (GenericSocket)(sock);
+	return bool(s != nil && s.ready != 0);
+}
+
+
+@(default_calling_convention="c", link_prefix="SDLNet_")
+foreign lib {
+	AllocSocketSet :: proc(maxsockets: c.int) -> SocketSet ---
+	AddSocket      :: proc(set: SocketSet, sock: GenericSocket) -> c.int ---
+	DelSocket      :: proc(set: SocketSet, sock: GenericSocket) -> c.int ---
+	CheckSockets   :: proc(set: SocketSet, timeout: u32) -> c.int ---
+	FreeSocketSet  :: proc(set: SocketSet) ---
+}
+
+
+/***********************************************************************/
+/* Error reporting functions                                           */
+/***********************************************************************/
+
+@(default_calling_convention="c", link_prefix="SDLNet_")
+foreign lib {
+	SetError :: proc(fmt: cstring, #c_vararg args: ..any) ---
+	GetError :: proc() -> cstring ---
+}
+
+
+/***********************************************************************/
+/* Inline functions to read/write network data                         */
+/***********************************************************************/
+
+/* Write a 16/32-bit value to network packet buffer */
+Write16 :: #force_inline proc "c" (value: u16, areap: rawptr) {
+	area := (^[2]u8)(areap);
+	area[0] = u8((value >>  8) & 0xFF);
+	area[1] = u8( value        & 0xFF);
+}
+Write32 :: #force_inline proc "c" (value: u32, areap: rawptr) {
+	area := (^[4]u8)(areap);
+	area[0] = u8((value >> 24) & 0xFF);
+	area[1] = u8((value >> 16) & 0xFF);
+	area[2] = u8((value >>  8) & 0xFF);
+	area[3] = u8( value        & 0xFF);
+}
+
+/* Read a 16/32-bit value from network packet buffer */
+Read16 :: #force_inline proc "c" (areap: rawptr) -> u16 {
+	area := (^[2]u8)(areap);
+	return u16(area[0])<<8 | u16(area[1]);
+}
+
+Read32 :: #force_inline proc "c" (areap: rawptr) -> u32 {
+	area := (^[4]u8)(areap);
+	return u32(area[0])<<24 | u32(area[1])<<16 | u32(area[2])<<8 | u32(area[3]);
+}

+ 317 - 0
vendor/sdl2/sdl2.odin

@@ -0,0 +1,317 @@
+package sdl2
+
+/*
+	Simple DirectMedia Layer
+	Copyright (C) 1997-2017 Sam Lantinga <[email protected]>
+
+	This software is provided 'as-is', without any express or implied
+	warranty.  In no event will the authors be held liable for any damages
+	arising from the use of this software.
+
+	Permission is granted to anyone to use this software for any purpose,
+	including commercial applications, and to alter it and redistribute it
+	freely, subject to the following restrictions:
+
+	1. The origin of this software must not be misrepresented; you must not
+	  claim that you wrote the original software. If you use this software
+	  in a product, an acknowledgment in the product documentation would be
+	  appreciated but is not required.
+	2. Altered source versions must be plainly marked as such, and must not be
+	  misrepresented as being the original software.
+	3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+import "core:c"
+import "core:intrinsics"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+version :: struct {
+	major: u8,        /**< major version */
+	minor: u8,        /**< minor version */
+	patch: u8,        /**< update version */
+};
+
+MAJOR_VERSION   :: 2;
+MINOR_VERSION   :: 0;
+PATCHLEVEL      :: 16;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetVersion  :: proc(ver: ^version) ---
+	GetRevision :: proc() -> cstring ---
+
+}
+
+InitFlag :: enum u32 {
+	TIMER          =  0x00,
+	AUDIO          =  0x04,
+	VIDEO          =  0x05,
+	JOYSTICK       =  0x09,
+	HAPTIC         =  0x0c,
+	GAMECONTROLLER =  0x0d,
+	EVENTS         =  0x0e,
+	SENSOR         =  0x0f,
+	NOPARACHUTE    =  0x14,
+}
+
+InitFlags :: bit_set[InitFlag; u32];
+
+INIT_TIMER          :: InitFlags{.TIMER};
+INIT_AUDIO          :: InitFlags{.AUDIO};
+INIT_VIDEO          :: InitFlags{.VIDEO};           /**< INIT_VIDEO implies INIT_EVENTS */
+INIT_JOYSTICK       :: InitFlags{.JOYSTICK};        /**< INIT_JOYSTICK implies INIT_EVENTS */
+INIT_HAPTIC         :: InitFlags{.HAPTIC};
+INIT_GAMECONTROLLER :: InitFlags{.GAMECONTROLLER};  /**< INIT_GAMECONTROLLER implies INIT_JOYSTICK */
+INIT_EVENTS         :: InitFlags{.EVENTS};
+INIT_SENSOR         :: InitFlags{.SENSOR};
+INIT_NOPARACHUTE    :: InitFlags{.NOPARACHUTE};     /**< compatibility; this flag is ignored. */
+INIT_EVERYTHING :: InitFlags{.TIMER, .AUDIO, .VIDEO, .EVENTS, .JOYSTICK, .HAPTIC, .GAMECONTROLLER, .SENSOR};
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	Init          :: proc(flags: InitFlags) -> c.int     ---
+	InitSubSystem :: proc(flags: InitFlags) -> c.int     ---
+	QuitSubSystem :: proc(flags: InitFlags)              ---
+	WasInit       :: proc(flags: InitFlags) -> InitFlags ---
+	Quit          :: proc() ---
+}
+
+
+
+// Atomic
+// NOTE: Prefer the intrinsics built into Odin 'package intrinsics'
+SpinLock :: distinct c.int;
+atomic_t :: struct { value: c.int };
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	AtomicTryLock                :: proc(lock: ^SpinLock) -> bool ---
+	AtomicLock                   :: proc(lock: ^SpinLock) ---
+	AtomicUnlock                 :: proc(lock: ^SpinLock) ---
+	MemoryBarrierReleaseFunction :: proc() ---
+	MemoryBarrierAcquireFunction :: proc() ---
+	AtomicCAS                    :: proc(a: ^atomic_t, oldval, newval: c.int) -> bool ---
+	AtomicSet                    :: proc(a: ^atomic_t, v: c.int) -> c.int ---
+	AtomicGet                    :: proc(a: ^atomic_t) -> c.int ---
+	AtomicAdd                    :: proc(a: ^atomic_t, v: c.int) -> c.int ---
+	AtomicCASPtr                 :: proc(a: ^rawptr, oldval, newval: rawptr) -> bool ---
+	AtomicSetPtr                 :: proc(a: ^rawptr, v: rawptr) -> rawptr ---
+	AtomicGetPtr                 :: proc(a: ^rawptr) -> rawptr ---
+}
+
+
+// Bits
+MostSignificantBitIndex32 :: #force_inline proc "c" (x: u32) -> c.int {
+	return c.int(intrinsics.count_leading_zeros(x));
+}
+
+HasExactlyOneBitSet32 :: #force_inline proc "c" (x: u32) -> bool {
+	return intrinsics.count_ones(x) == 1;
+}
+
+// Clipboard
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	SetClipboardText :: proc(text: cstring) -> c.int ---
+	GetClipboardText :: proc() -> cstring ---
+	HasClipboardText :: proc() -> bool ---
+}
+
+
+// Error
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	SetError    :: proc(fmt: cstring, #c_vararg args: ..any) -> c.int ---
+	GetError    :: proc() -> cstring ---
+	GetErrorMsg :: proc(errstr: [^]u8, maxlen: c.int) -> cstring ---
+	ClearError  :: proc() ---
+}
+
+GetErrorString :: proc "c" () -> string {
+	return string(GetError());
+}
+GetErrorMsgString :: proc "c" (buf: []u8) -> string {
+	cstr := GetErrorMsg(raw_data(buf), c.int(len(buf)));
+	return string(cstr);
+}
+
+
+/**
+ *  \name Internal error functions
+ *
+ *  \internal
+ *  Private error reporting function - used internally.
+ */
+OutOfMemory       :: #force_inline proc "c" ()               -> c.int { return Error(.ENOMEM) }
+Unsupported       :: #force_inline proc "c" ()               -> c.int { return Error(.UNSUPPORTED) }
+InvalidParamError :: #force_inline proc "c" (param: cstring) -> c.int { return SetError("Parameter '%s' is invalid", param) }
+
+errorcode :: enum c.int {
+	ENOMEM,
+	EFREAD,
+	EFWRITE,
+	EFSEEK,
+	UNSUPPORTED,
+	LASTERROR,
+}
+
+/* SDL_Error() unconditionally returns -1. */
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	Error :: proc(code: errorcode) -> c.int ---
+}
+
+
+// Filesystem
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetBasePath :: proc() -> cstring ---
+	GetPrefPath :: proc(org, app: cstring) -> cstring ---
+}
+
+
+// loadso
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	LoadObject   :: proc(sofile: cstring) -> rawptr ---
+	LoadFunction :: proc(handle: rawptr, name: cstring) -> rawptr ---
+	UnloadObject :: proc(handle: rawptr) ---
+}
+
+
+// locale
+
+
+Locale :: struct {
+	language: cstring, /**< A language name, like "en" for English. */
+	country:  cstring, /**< A country, like "US" for America. Can be NULL. */
+}
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetPreferredLocales :: proc() -> ^Locale ---
+}
+
+// misc
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	SDL_OpenURL :: proc(url: rawptr) -> c.int ---
+}
+
+// platform
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetPlatform :: proc() -> cstring ---
+}
+
+// power
+
+PowerState :: enum c.int {
+	UNKNOWN,      /**< cannot determine power status */
+	ON_BATTERY,   /**< Not plugged in, running on the battery */
+	NO_BATTERY,   /**< Plugged in, no battery available */
+	CHARGING,     /**< Plugged in, charging battery */
+	CHARGED,      /**< Plugged in, battery charged */
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetPowerInfo :: proc(secs: ^c.int, pct: ^c.int) -> PowerState ---
+}
+
+// quit
+
+QuitRequested :: #force_inline proc "c" () -> bool {
+        PumpEvents();
+        return bool(PeepEvents(nil, 0, .PEEKEVENT, .QUIT, .QUIT) > 0);
+}
+
+
+// sensor
+
+Sensor :: struct {};
+
+SensorID :: distinct i32;
+
+SensorType :: enum c.int {
+	INVALID = -1,    /**< Returned for an invalid sensor */
+	UNKNOWN,         /**< Unknown sensor type */
+	ACCEL,           /**< Accelerometer */
+	GYRO,            /**< Gyroscope */
+}
+
+STANDARD_GRAVITY :: 9.80665;
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	LockSensors                    :: proc() ---
+	UnlockSensors                  :: proc() ---
+	NumSensors                     :: proc() -> c.int ---
+	SensorGetDeviceName            :: proc(device_index: c.int) -> cstring ---
+	SensorGetDeviceType            :: proc(device_index: c.int) -> SensorType ---
+	SensorGetDeviceNonPortableType :: proc(device_index: c.int) -> c.int ---
+	SensorGetDeviceInstanceID      :: proc(device_index: c.int) -> SensorID ---
+	SensorOpen                     :: proc(device_index: c.int) -> ^Sensor ---
+	SensorFromInstanceID           :: proc(instance_id: SensorID) -> ^Sensor ---
+	SensorGetName                  :: proc(sensor: ^Sensor) -> cstring ---
+	SensorGetType                  :: proc(sensor: ^Sensor) -> SensorType ---
+	SensorGetNonPortableType       :: proc(sensor: ^Sensor) -> c.int ---
+	SensorGetInstanceID            :: proc(sensor: ^Sensor) -> SensorID ---
+	SensorGetData                  :: proc(sensor: ^Sensor, data: [^]f32, num_values: c.int) -> c.int ---
+	SensorClose                    :: proc(sensor: ^Sensor) ---
+	SensorUpdate                   :: proc() ---
+}
+
+
+// shape
+
+NONSHAPEABLE_WINDOW    :: -1;
+INVALID_SHAPE_ARGUMENT :: -2;
+WINDOW_LACKS_SHAPE     :: -3;
+
+WindowShapeModeEnum :: enum c.int {
+	/** \brief The default mode, a binarized alpha cutoff of 1. */
+	Default,
+	/** \brief A binarized alpha cutoff with a given integer value. */
+	BinarizeAlpha,
+	/** \brief A binarized alpha cutoff with a given integer value, but with the opposite comparison. */
+	ReverseBinarizeAlpha,
+	/** \brief A color key is applied. */
+	ColorKey,
+}
+
+SDL_SHAPEMODEALPHA :: #force_inline proc "c" (mode: WindowShapeModeEnum) -> bool {
+	return bool(mode == .Default || mode == .BinarizeAlpha || mode == .ReverseBinarizeAlpha);
+}
+
+
+WindowShapeParams :: struct #raw_union {
+	binarizationCutoff: u8,
+	colorKey:           Color,
+}
+
+WindowShapeMode :: struct {
+	mode:       WindowShapeModeEnum,
+	parameters: WindowShapeParams,
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	CreateShapedWindow  :: proc(title: cstring, x, y, w, h: c.uint, flags: WindowFlags) -> ^Window ---
+	IsShapedWindow      :: proc(window: ^Window) -> bool ---
+	SetWindowShape      :: proc(window: ^Window, shape: ^Surface, shape_mode: ^WindowShapeMode) -> c.int ---
+	GetShapedWindowMode :: proc(window: ^Window, shape_mode: ^WindowShapeMode) -> c.int ---
+}

+ 242 - 0
vendor/sdl2/sdl_audio.odin

@@ -0,0 +1,242 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+/**
+ *  \brief Audio format flags.
+ *
+ *  These are what the 16 bits in SDL_AudioFormat currently mean...
+ *  (Unspecified bits are always zero).
+ *
+ *  \verbatim
+    ++-----------------------sample is signed if set
+    ||
+    ||       ++-----------sample is bigendian if set
+    ||       ||
+    ||       ||          ++---sample is float if set
+    ||       ||          ||
+    ||       ||          || +---sample bit size---+
+    ||       ||          || |                     |
+    15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+    \endverbatim
+ *
+ *  There are macros in SDL 2.0 and later to query these bits.
+ */
+AudioFormat :: distinct u16;
+
+
+AUDIO_MASK_BITSIZE       :: 0xFF;
+AUDIO_MASK_DATATYPE      :: 1<<8;
+AUDIO_MASK_ENDIAN        :: 1<<12;
+AUDIO_MASK_SIGNED        :: 1<<15;
+AUDIO_BITSIZE        :: #force_inline proc "c" (x: AudioFormat) -> u8   { return u8(x & AUDIO_MASK_BITSIZE)                       }
+AUDIO_ISFLOAT        :: #force_inline proc "c" (x: AudioFormat) -> bool { return (x & AUDIO_MASK_DATATYPE) == AUDIO_MASK_DATATYPE }
+AUDIO_ISBIGENDIAN    :: #force_inline proc "c" (x: AudioFormat) -> bool { return (x & AUDIO_MASK_ENDIAN) == AUDIO_MASK_ENDIAN     }
+AUDIO_ISSIGNED       :: #force_inline proc "c" (x: AudioFormat) -> bool { return (x & AUDIO_MASK_SIGNED) == AUDIO_MASK_SIGNED     }
+AUDIO_ISINT          :: #force_inline proc "c" (x: AudioFormat) -> bool { return !AUDIO_ISFLOAT(x)                                }
+AUDIO_ISLITTLEENDIAN :: #force_inline proc "c" (x: AudioFormat) -> bool { return !AUDIO_ISBIGENDIAN(x)                            }
+AUDIO_ISUNSIGNED     :: #force_inline proc "c" (x: AudioFormat) -> bool { return !AUDIO_ISSIGNED(x)                               }
+
+AUDIO_U8        :: 0x0008;  /**< Unsigned 8-bit samples */
+AUDIO_S8        :: 0x8008;  /**< Signed 8-bit samples */
+AUDIO_U16LSB    :: 0x0010;  /**< Unsigned 16-bit samples */
+AUDIO_S16LSB    :: 0x8010;  /**< Signed 16-bit samples */
+AUDIO_U16MSB    :: 0x1010;  /**< As above, but big-endian byte order */
+AUDIO_S16MSB    :: 0x9010;  /**< As above, but big-endian byte order */
+AUDIO_U16       :: AUDIO_U16LSB;
+AUDIO_S16       :: AUDIO_S16LSB;
+
+AUDIO_S32LSB    :: 0x8020;  /**< 32-bit integer samples */
+AUDIO_S32MSB    :: 0x9020;  /**< As above, but big-endian byte order */
+AUDIO_S32       :: AUDIO_S32LSB;
+
+AUDIO_F32LSB    :: 0x8120;  /**< 32-bit floating point samples */
+AUDIO_F32MSB    :: 0x9120;  /**< As above, but big-endian byte order */
+AUDIO_F32       :: AUDIO_F32LSB;
+
+when ODIN_ENDIAN == "little"  {
+	AUDIO_U16SYS :: AUDIO_U16LSB;
+	AUDIO_S16SYS :: AUDIO_S16LSB;
+	AUDIO_S32SYS :: AUDIO_S32LSB;
+	AUDIO_F32SYS :: AUDIO_F32LSB;
+} else {
+	AUDIO_U16SYS :: AUDIO_U16MSB;
+	AUDIO_S16SYS :: AUDIO_S16MSB;
+	AUDIO_S32SYS :: AUDIO_S32MSB;
+	AUDIO_F32SYS :: AUDIO_F32MSB;
+}
+
+
+AUDIO_ALLOW_FREQUENCY_CHANGE    :: 0x00000001;
+AUDIO_ALLOW_FORMAT_CHANGE       :: 0x00000002;
+AUDIO_ALLOW_CHANNELS_CHANGE     :: 0x00000004;
+AUDIO_ALLOW_SAMPLES_CHANGE      :: 0x00000008;
+AUDIO_ALLOW_ANY_CHANGE          :: AUDIO_ALLOW_FREQUENCY_CHANGE|AUDIO_ALLOW_FORMAT_CHANGE|AUDIO_ALLOW_CHANNELS_CHANGE|AUDIO_ALLOW_SAMPLES_CHANGE;
+
+AudioCallback :: proc "c" (userdata: rawptr, stream: [^]u8, len: c.int);
+
+/**
+ *  The calculated values in this structure are calculated by SDL_OpenAudio().
+ *
+ *  For multi-channel audio, the default SDL channel mapping is:
+ *  2:  FL FR                       (stereo)
+ *  3:  FL FR LFE                   (2.1 surround)
+ *  4:  FL FR BL BR                 (quad)
+ *  5:  FL FR FC BL BR              (quad + center)
+ *  6:  FL FR FC LFE SL SR          (5.1 surround - last two can also be BL BR)
+ *  7:  FL FR FC LFE BC SL SR       (6.1 surround)
+ *  8:  FL FR FC LFE BL BR SL SR    (7.1 surround)
+ */
+AudioSpec :: struct {
+	freq:     c.int,         /**< DSP frequency -- samples per second */
+	format:   AudioFormat,   /**< Audio data format */
+	channels: u8,            /**< Number of channels: 1 mono, 2 stereo */
+	silence:  u8,            /**< Audio buffer silence value (calculated) */
+	samples:  u16,           /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
+	padding:  u16,           /**< Necessary for some compile environments */
+	size:     u32,           /**< Audio buffer size in bytes (calculated) */
+	callback: AudioCallback, /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
+	userdata: rawptr,        /**< Userdata passed to callback (ignored for NULL callbacks). */
+}
+
+
+AudioFilter :: proc "c" (cvt: ^AudioCVT, format: AudioFormat);
+
+AUDIOCVT_MAX_FILTERS :: 9;
+
+AudioCVT :: struct #packed {
+	needed:       c.int,       /**< Set to 1 if conversion possible */
+	src_format:   AudioFormat, /**< Source audio format */
+	dst_format:   AudioFormat, /**< Target audio format */
+	rate_incr:    f64,         /**< Rate conversion increment */
+	buf:          [^]u8,       /**< Buffer to hold entire audio data */
+	len:          c.int,       /**< Length of original audio buffer */
+	len_cvt:      c.int,       /**< Length of converted audio buffer */
+	len_mult:     c.int,       /**< buffer must be len*len_mult big */
+	len_ratio:    f64,         /**< Given len, final size is len*len_ratio */
+	filters:      [AUDIOCVT_MAX_FILTERS + 1]AudioFilter, /**< NULL-terminated list of filter functions */
+	filter_index: c.int,       /**< Current audio conversion function */
+}
+
+
+
+AudioDeviceID :: distinct u32;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetNumAudioDrivers :: proc() -> c.int ---
+	GetAudioDriver     :: proc(index: c.int) -> cstring ---
+
+	AudioInit :: proc(driver_name: cstring) -> c.int ---
+	AudioQuit :: proc() ---
+
+	GetCurrentAudioDriver :: proc() -> cstring ---
+
+	OpenAudio :: proc(desired, obtained: ^AudioSpec) -> c.int ---
+
+	GetNumAudioDevices :: proc(iscapture: bool) -> c.int ---
+
+	GetAudioDeviceName :: proc(index: c.int, iscapture: bool) -> cstring ---
+	GetAudioDeviceSpec :: proc(index: c.int, iscapture: bool, spec: ^AudioSpec) -> c.int ---
+
+	OpenAudioDevice :: proc(device: cstring,
+	                        iscapture: bool,
+	                        desired: ^AudioSpec,
+	                        obtained: ^AudioSpec,
+	                        allowed_changes: bool) -> AudioDeviceID ---
+}
+
+
+
+AudioStatus :: enum c.int {
+	STOPPED = 0,
+	PLAYING,
+	PAUSED,
+}
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetAudioStatus :: proc() -> AudioStatus ---
+	GetAudioDeviceStatus :: proc(dev: AudioDeviceID) -> AudioStatus --- /* Audio State */
+}
+
+
+/* this is opaque to the outside world. */
+AudioStream :: struct {};
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	PauseAudio       :: proc(pause_on: bool) ---
+	PauseAudioDevice :: proc(dev: AudioDeviceID, pause_on: bool) --- /* Pause audio functions */
+}
+
+
+/**
+ *  Loads a WAV from a file.
+ *  Compatibility convenience function.
+ */
+LoadWAV :: #force_inline proc "c" (file: cstring, spec: ^AudioSpec, audio_buf: ^[^]u8, audio_len: ^u32) -> ^AudioSpec {
+	return LoadWAV_RW(RWFromFile(file, "rb"), true, spec, audio_buf, audio_len);
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	LoadWAV_RW :: proc(src: ^RWops, freesrc: bool, spec: ^AudioSpec, audio_buf: ^[^]u8, audio_len: ^u32) -> ^AudioSpec ---
+	FreeWAV    :: proc(audio_buf: [^]u8) ---
+}
+
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	BuildAudioCVT :: proc(cvt:          ^AudioCVT,
+	                      src_format:   AudioFormat,
+	                      src_channels: u8,
+	                      src_rate:     c.int,
+	                      dst_format:   AudioFormat,
+	                      dst_channels: u8,
+	                      dst_rate:     c.int) -> c.int ---
+
+	ConvertAudio :: proc(cvt: ^AudioCVT) -> c.int ---
+
+	NewAudioStream :: proc(src_format:   AudioFormat,
+	                       src_channels: u8,
+	                       src_rate:     c.int,
+	                       dst_format:   AudioFormat,
+	                       dst_channels: u8,
+	                       dst_rate:     c.int) -> ^AudioStream ---
+
+	AudioStreamPut :: proc(stream: ^AudioStream, buf: rawptr, len: c.int) -> c.int ---
+	AudioStreamGet :: proc(stream: ^AudioStream, buf: rawptr, len: c.int) -> c.int ---
+
+	AudioStreamAvailable :: proc(stream: ^AudioStream) -> c.int ---
+	AudioStreamFlush     :: proc(stream: ^AudioStream) -> c.int ---
+	AudioStreamClear     :: proc(stream: ^AudioStream) ---
+	FreeAudioStream      :: proc(stream: ^AudioStream) ---
+
+}
+
+
+MIX_MAXVOLUME :: 128;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	MixAudio           :: proc(dst: [^]u8, src: [^]u8, len: u32, volume: c.int)                      ---
+	MixAudioFormat     :: proc(dst: [^]u8, src: [^]u8, format: AudioFormat, len: u32, volume: c.int) ---
+	QueueAudio         :: proc(dev: AudioDeviceID, data: rawptr, len: u32) -> c.int              ---
+	DequeueAudio       :: proc(dev: AudioDeviceID, data: rawptr, len: u32) -> u32                ---
+	GetQueuedAudioSize :: proc(dev: AudioDeviceID) -> u32                                        ---
+	ClearQueuedAudio   :: proc(dev: AudioDeviceID)                                               ---
+
+	LockAudio         :: proc()                   ---
+	LockAudioDevice   :: proc(dev: AudioDeviceID) ---
+	UnlockAudio       :: proc()                   ---
+	UnlockAudioDevice :: proc(dev: AudioDeviceID) --- /* Audio lock functions */
+
+	CloseAudio       :: proc() ---
+	CloseAudioDevice :: proc(dev: AudioDeviceID) ---
+}

+ 65 - 0
vendor/sdl2/sdl_blendmode.odin

@@ -0,0 +1,65 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+/**
+ *  \brief The blend mode used in SDL_RenderCopy() and drawing operations.
+ */
+BlendMode :: enum c.int {
+	NONE = 0x00000000,     /**< no blending
+	                        dstRGBA = srcRGBA */
+	BLEND = 0x00000001,    /**< alpha blending
+	                        dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
+	                        dstA = srcA + (dstA * (1-srcA)) */
+	ADD = 0x00000002,      /**< additive blending
+	                        dstRGB = (srcRGB * srcA) + dstRGB
+	                        dstA = dstA */
+	MOD = 0x00000004,      /**< color modulate
+	                        dstRGB = srcRGB * dstRGB
+	                        dstA = dstA */
+	MUL = 0x00000008,      /**< color multiply
+	                        dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
+	                        dstA = (srcA * dstA) + (dstA * (1-srcA)) */
+	INVALID = 0x7FFFFFFF,
+
+	/* Additional custom blend modes can be returned by ComposeCustomBlendMode() */
+}
+
+/**
+ *  \brief The blend operation used when combining source and destination pixel components
+ */
+BlendOperation :: enum c.int {
+	ADD              = 0x1,  /**< dst + src: supported by all renderers */
+	SUBTRACT         = 0x2,  /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
+	REV_SUBTRACT     = 0x3,  /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+	MINIMUM          = 0x4,  /**< min(dst, src) : supported by D3D11 */
+	MAXIMUM          = 0x5,  /**< max(dst, src) : supported by D3D11 */
+}
+
+/**
+ *  \brief The normalized factor used to multiply pixel components
+ */
+BlendFactor :: enum c.int  {
+	ZERO                = 0x1,  /**< 0, 0, 0, 0 */
+	ONE                 = 0x2,  /**< 1, 1, 1, 1 */
+	SRC_COLOR           = 0x3,  /**< srcR, srcG, srcB, srcA */
+	ONE_MINUS_SRC_COLOR = 0x4,  /**< 1-srcR, 1-srcG, 1-srcB, 1-srcA */
+	SRC_ALPHA           = 0x5,  /**< srcA, srcA, srcA, srcA */
+	ONE_MINUS_SRC_ALPHA = 0x6,  /**< 1-srcA, 1-srcA, 1-srcA, 1-srcA */
+	DST_COLOR           = 0x7,  /**< dstR, dstG, dstB, dstA */
+	ONE_MINUS_DST_COLOR = 0x8,  /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */
+	DST_ALPHA           = 0x9,  /**< dstA, dstA, dstA, dstA */
+	ONE_MINUS_DST_ALPHA = 0xA,  /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */
+}
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	ComposeCustomBlendMode :: proc(srcColorFactor, dstColorFactor: BlendFactor, colorOperation: BlendOperation,
+	                               srcAlphaFactor, dstAlphaFactor: BlendFactor, alphaOperation: BlendOperation) -> BlendMode ---
+}

+ 44 - 0
vendor/sdl2/sdl_cpuinfo.odin

@@ -0,0 +1,44 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+/* This is a guess for the cacheline size used for padding.
+ * Most x86 processors have a 64 byte cache line.
+ * The 64-bit PowerPC processors have a 128 byte cache line.
+ * We'll use the larger value to be generally safe.
+ */
+CACHELINE_SIZE :: 128;
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetCPUCount         :: proc() -> c.int ---
+	GetCPUCacheLineSize :: proc() -> c.int ---
+
+	HasRDTSC            :: proc() -> bool  ---
+	HasAltiVec          :: proc() -> bool  ---
+	HasMMX              :: proc() -> bool  ---
+	Has3DNow            :: proc() -> bool  ---
+	HasSSE              :: proc() -> bool  ---
+	HasSSE2             :: proc() -> bool  ---
+	HasSSE3             :: proc() -> bool  ---
+	HasSSE41            :: proc() -> bool  ---
+	HasSSE42            :: proc() -> bool  ---
+	HasAVX              :: proc() -> bool  ---
+	HasAVX2             :: proc() -> bool  ---
+	HasAVX512F          :: proc() -> bool  ---
+	HasARMSIMD          :: proc() -> bool  ---
+	HasNEON             :: proc() -> bool  ---
+
+	GetSystemRAM        :: proc() -> c.int ---
+
+	SIMDGetAlignment    :: proc() -> c.size_t ---
+	SIMDAlloc           :: proc(len: c.size_t) -> rawptr ---
+	SIMDRealloc         :: proc(mem: rawptr, len: c.size_t) -> rawptr ---
+	SIMDFree            :: proc(ptr: rawptr) ---
+}

+ 501 - 0
vendor/sdl2/sdl_events.odin

@@ -0,0 +1,501 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+RELEASED :: 0;
+PRESSED  :: 1;
+
+EventType :: enum u32 {
+	FIRSTEVENT     = 0,     /**< Unused (do not remove) */
+
+	/* Application events */
+	QUIT           = 0x100, /**< User-requested quit */
+
+	/* These application events have special meaning on iOS, see README-ios.md for details */
+	APP_TERMINATING,        /**< The application is being terminated by the OS
+	                             Called on iOS in applicationWillTerminate()
+	                             Called on Android in onDestroy()
+	                        */
+	APP_LOWMEMORY,          /**< The application is low on memory, free memory if possible.
+	                             Called on iOS in applicationDidReceiveMemoryWarning()
+	                             Called on Android in onLowMemory()
+	                        */
+	APP_WILLENTERBACKGROUND, /**< The application is about to enter the background
+	                             Called on iOS in applicationWillResignActive()
+	                             Called on Android in onPause()
+	                        */
+	APP_DIDENTERBACKGROUND, /**< The application did enter the background and may not get CPU for some time
+	                             Called on iOS in applicationDidEnterBackground()
+	                             Called on Android in onPause()
+	                        */
+	APP_WILLENTERFOREGROUND, /**< The application is about to enter the foreground
+	                             Called on iOS in applicationWillEnterForeground()
+	                             Called on Android in onResume()
+	                        */
+	APP_DIDENTERFOREGROUND, /**< The application is now interactive
+	                             Called on iOS in applicationDidBecomeActive()
+	                             Called on Android in onResume()
+	                        */
+
+	LOCALECHANGED,  /**< The user's locale preferences have changed. */
+
+	/* Display events */
+	DISPLAYEVENT   = 0x150,  /**< Display state change */
+
+	/* Window events */
+	WINDOWEVENT    = 0x200, /**< Window state change */
+	SYSWMEVENT,             /**< System specific event */
+
+	/* Keyboard events */
+	KEYDOWN        = 0x300, /**< Key pressed */
+	KEYUP,                  /**< Key released */
+	TEXTEDITING,            /**< Keyboard text editing (composition) */
+	TEXTINPUT,              /**< Keyboard text input */
+	KEYMAPCHANGED,          /**< Keymap changed due to a system event such as an
+	                             input language or keyboard layout change.
+	                        */
+
+	/* Mouse events */
+	MOUSEMOTION    = 0x400, /**< Mouse moved */
+	MOUSEBUTTONDOWN,        /**< Mouse button pressed */
+	MOUSEBUTTONUP,          /**< Mouse button released */
+	MOUSEWHEEL,             /**< Mouse wheel motion */
+
+	/* Joystick events */
+	JOYAXISMOTION  = 0x600, /**< Joystick axis motion */
+	JOYBALLMOTION,          /**< Joystick trackball motion */
+	JOYHATMOTION,           /**< Joystick hat position change */
+	JOYBUTTONDOWN,          /**< Joystick button pressed */
+	JOYBUTTONUP,            /**< Joystick button released */
+	JOYDEVICEADDED,         /**< A new joystick has been inserted into the system */
+	JOYDEVICEREMOVED,       /**< An opened joystick has been removed */
+
+	/* Game controller events */
+	CONTROLLERAXISMOTION  = 0x650, /**< Game controller axis motion */
+	CONTROLLERBUTTONDOWN,          /**< Game controller button pressed */
+	CONTROLLERBUTTONUP,            /**< Game controller button released */
+	CONTROLLERDEVICEADDED,         /**< A new Game controller has been inserted into the system */
+	CONTROLLERDEVICEREMOVED,       /**< An opened Game controller has been removed */
+	CONTROLLERDEVICEREMAPPED,      /**< The controller mapping was updated */
+	CONTROLLERTOUCHPADDOWN,        /**< Game controller touchpad was touched */
+	CONTROLLERTOUCHPADMOTION,      /**< Game controller touchpad finger was moved */
+	CONTROLLERTOUCHPADUP,          /**< Game controller touchpad finger was lifted */
+	CONTROLLERSENSORUPDATE,        /**< Game controller sensor was updated */
+
+	/* Touch events */
+	FINGERDOWN      = 0x700,
+	FINGERUP,
+	FINGERMOTION,
+
+	/* Gesture events */
+	DOLLARGESTURE   = 0x800,
+	DOLLARRECORD,
+	MULTIGESTURE,
+
+	/* Clipboard events */
+	CLIPBOARDUPDATE = 0x900, /**< The clipboard changed */
+
+	/* Drag and drop events */
+	DROPFILE        = 0x1000, /**< The system requests a file open */
+	DROPTEXT,                 /**< text/plain drag-and-drop event */
+	DROPBEGIN,                /**< A new set of drops is beginning (NULL filename) */
+	DROPCOMPLETE,             /**< Current set of drops is now complete (NULL filename) */
+
+	/* Audio hotplug events */
+	AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
+	AUDIODEVICEREMOVED,        /**< An audio device has been removed. */
+
+	/* Sensor events */
+	SENSORUPDATE = 0x1200,     /**< A sensor was updated */
+
+	/* Render events */
+	RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
+	RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
+
+	/** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use,
+	*  and should be allocated with SDL_RegisterEvents()
+	*/
+	USEREVENT    = 0x8000,
+
+	/**
+	*  This last event is only for bounding internal arrays
+	*/
+	LASTEVENT    = 0xFFFF,
+}
+
+CommonEvent :: struct {
+	type: EventType,
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+}
+
+DisplayEvent :: struct {
+	type: EventType,           /**< ::SDL_DISPLAYEVENT */
+	timestamp: u32,            /**< In milliseconds, populated using SDL_GetTicks() */
+	display:   u32,            /**< The associated display index */
+	event:     DisplayEventID, /**< ::SDL_DisplayEventID */
+	_:  u8,
+	_:  u8,
+	_:  u8,
+	data1:     i32,  /**< event dependent data */
+}
+
+WindowEvent :: struct {
+	type: EventType,          /**< ::SDL_WINDOWEVENT */
+	timestamp: u32,           /**< In milliseconds, populated using SDL_GetTicks() */
+	windowID:  u32,           /**< The associated window */
+	event:     WindowEventID, /**< ::SDL_WindowEventID */
+	_:  u8,
+	_:  u8,
+	_:  u8,
+	data1:     i32,  /**< event dependent data */
+	data2:     i32,  /**< event dependent data */
+}
+
+KeyboardEvent :: struct {
+	type: EventType,  /**< ::SDL_KEYDOWN or ::SDL_KEYUP */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	windowID:  u32,   /**< The window with keyboard focus, if any */
+	state:     u8,    /**< ::SDL_PRESSED or ::SDL_RELEASED */
+	repeat:    u8,    /**< Non-zero if this is a key repeat */
+	_: u8,
+	_: u8,
+	keysym: Keysym,   /**< The key that was pressed or released */
+}
+
+TEXTEDITINGEVENT_TEXT_SIZE :: 32;
+TextEditingEvent :: struct {
+	type: EventType,                                /**< ::SDL_TEXTEDITING */
+    	timestamp: u32,                           /**< In milliseconds, populated using SDL_GetTicks() */
+    	windowID: u32,                            /**< The window with keyboard focus, if any */
+    	text: [TEXTEDITINGEVENT_TEXT_SIZE]u8,  /**< The editing text */
+	start: i32,                               /**< The start cursor of selected editing text */
+	length: i32,                              /**< The length of selected editing text */
+}
+
+
+TEXTINPUTEVENT_TEXT_SIZE :: 32;
+TextInputEvent :: struct {
+	type: EventType,                              /**< ::SDL_TEXTINPUT */
+	timestamp: u32,                         /**< In milliseconds, populated using SDL_GetTicks() */
+	windowID: u32,                          /**< The window with keyboard focus, if any */
+    	text: [TEXTINPUTEVENT_TEXT_SIZE]u8,  /**< The input text */
+}
+
+MouseMotionEvent :: struct {
+	type: EventType, /**< ::SDL_MOUSEMOTION */
+	timestamp: u32,  /**< In milliseconds, populated using SDL_GetTicks() */
+	windowID:  u32,  /**< The window with mouse focus, if any */
+	which:     u32,  /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+	state:     u32,  /**< The current button state */
+	x:         i32,  /**< X coordinate, relative to window */
+	y:         i32,  /**< Y coordinate, relative to window */
+	xrel:      i32,  /**< The relative motion in the X direction */
+	yrel:      i32,  /**< The relative motion in the Y direction */
+}
+
+MouseButtonEvent :: struct {
+	type: EventType,        /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	windowID: u32,    /**< The window with mouse focus, if any */
+	which: u32,       /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+	button: u8,       /**< The mouse button index */
+	state: u8,        /**< ::SDL_PRESSED or ::SDL_RELEASED */
+	clicks: u8,       /**< 1 for single-click, 2 for double-click, etc. */
+	_: u8,
+	x: i32,           /**< X coordinate, relative to window */
+	y: i32,           /**< Y coordinate, relative to window */
+}
+
+MouseWheelEvent :: struct {
+	type: EventType,        /**< ::SDL_MOUSEWHEEL */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	windowID: u32,    /**< The window with mouse focus, if any */
+	which: u32,       /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+	x: i32,           /**< The amount scrolled horizontally, positive to the right and negative to the left */
+	y: i32,           /**< The amount scrolled vertically, positive away from the user and negative toward the user */
+	direction: u32,   /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
+}
+
+JoyAxisEvent :: struct {
+	type: EventType,        /**< ::SDL_JOYAXISMOTION */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which: JoystickID, /**< The joystick instance id */
+	axis: u8,         /**< The joystick axis index */
+	_: u8,
+	_: u8,
+	_: u8,
+	value: i16,       /**< The axis value (range: -32768 to 32767) */
+	_: u16,
+}
+
+JoyBallEvent :: struct {
+	type: EventType,        /**< ::SDL_JOYBALLMOTION */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which: JoystickID, /**< The joystick instance id */
+	ball: u8,         /**< The joystick trackball index */
+	_: u8,
+	_: u8,
+	_: u8,
+	xrel: i16,        /**< The relative motion in the X direction */
+	yrel: i16,        /**< The relative motion in the Y direction */
+}
+
+JoyHatEvent :: struct {
+	type: EventType,        /**< ::SDL_JOYHATMOTION */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which: JoystickID, /**< The joystick instance id */
+	hat: u8,          /**< The joystick hat index */
+	value: u8,        /**< The hat position value.
+	                 *   \sa ::SDL_HAT_LEFTUP ::SDL_HAT_UP ::SDL_HAT_RIGHTUP
+	                 *   \sa ::SDL_HAT_LEFT ::SDL_HAT_CENTERED ::SDL_HAT_RIGHT
+	                 *   \sa ::SDL_HAT_LEFTDOWN ::SDL_HAT_DOWN ::SDL_HAT_RIGHTDOWN
+	                 *
+	                 *   Note that zero means the POV is centered.
+	                 */
+	_: u8,
+	_: u8,
+}
+
+JoyButtonEvent :: struct {
+	type: EventType,        /**< ::SDL_JOYBUTTONDOWN or ::SDL_JOYBUTTONUP */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which: JoystickID, /**< The joystick instance id */
+	button: u8,       /**< The joystick button index */
+	state: u8,        /**< ::SDL_PRESSED or ::SDL_RELEASED */
+	_: u8,
+	_: u8,
+}
+
+JoyDeviceEvent :: struct {
+	type: EventType,        /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which: i32,       /**< The joystick device index for the ADDED event, instance id for the REMOVED event */
+}
+
+
+ControllerAxisEvent :: struct {
+	type: EventType,        /**< ::SDL_CONTROLLERAXISMOTION */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which:     JoystickID, /**< The joystick instance id */
+	axis:      u8,         /**< The controller axis (SDL_GameControllerAxis) */
+	_:         u8,
+	_:         u8,
+	_:         u8,
+	value:     i16,       /**< The axis value (range: -32768 to 32767) */
+	_:  u16,
+}
+
+
+ControllerButtonEvent :: struct {
+	type: EventType,        /**< ::SDL_CONTROLLERBUTTONDOWN or ::SDL_CONTROLLERBUTTONUP */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which: JoystickID, /**< The joystick instance id */
+	button: u8,       /**< The controller button (SDL_GameControllerButton) */
+	state: u8,        /**< ::SDL_PRESSED or ::SDL_RELEASED */
+	_: u8,
+	_: u8,
+}
+
+
+ControllerDeviceEvent :: struct {
+	type: EventType,        /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which:     i32,       /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
+}
+
+ControllerTouchpadEvent :: struct {
+	type: EventType,        /**< ::SDL_CONTROLLERTOUCHPADDOWN or ::SDL_CONTROLLERTOUCHPADMOTION or ::SDL_CONTROLLERTOUCHPADUP */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which:     JoystickID, /**< The joystick instance id */
+	touchpad:  i32,    /**< The index of the touchpad */
+	finger:    i32,      /**< The index of the finger on the touchpad */
+	x:         f32,            /**< Normalized in the range 0...1 with 0 being on the left */
+	y:         f32,            /**< Normalized in the range 0...1 with 0 being at the top */
+	pressure:  f32,     /**< Normalized in the range 0...1 */
+}
+
+ControllerSensorEvent :: struct {
+	type: EventType,        /**< ::SDL_CONTROLLERSENSORUPDATE */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which:     JoystickID, /**< The joystick instance id */
+	sensor:    i32,      /**< The type of the sensor, one of the values of ::SDL_SensorType */
+	data:      [3]f32,      /**< Up to 3 values from the sensor, as defined in SDL_sensor.h */
+}
+
+AudioDeviceEvent :: struct {
+	type: EventType,        /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which:     u32,       /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */
+	iscapture: u8,    /**< zero if an output device, non-zero if a capture device. */
+	_:         u8,
+	_:         u8,
+	_:         u8,
+}
+
+
+TouchFingerEvent :: struct {
+	type: EventType,    /**< ::SDL_FINGERMOTION or ::SDL_FINGERDOWN or ::SDL_FINGERUP */
+	timestamp: u32,     /**< In milliseconds, populated using SDL_GetTicks() */
+	touchId:   TouchID, /**< The touch device id */
+	fingerId:  FingerID,
+	x:         f32,     /**< Normalized in the range 0...1 */
+	y:         f32,     /**< Normalized in the range 0...1 */
+	dx:        f32,     /**< Normalized in the range -1...1 */
+	dy:        f32,     /**< Normalized in the range -1...1 */
+	pressure:  f32,     /**< Normalized in the range 0...1 */
+	windowID:  u32,     /**< The window underneath the finger, if any */
+}
+
+
+MultiGestureEvent :: struct {
+	type: EventType,     /**< ::SDL_MULTIGESTURE */
+	timestamp:  u32,     /**< In milliseconds, populated using SDL_GetTicks() */
+	touchId:    TouchID, /**< The touch device id */
+	dTheta:     f32,
+	dDist:      f32,
+	x:          f32,
+	y:          f32,
+	numFingers: u16,
+	padding:    u16,
+}
+
+
+/**
+ * \brief Dollar Gesture Event (event.dgesture.*)
+ */
+DollarGestureEvent :: struct {
+	type: EventType,       /**< ::SDL_DOLLARGESTURE or ::SDL_DOLLARRECORD */
+	timestamp:  u32,       /**< In milliseconds, populated using SDL_GetTicks() */
+	touchId:    TouchID,   /**< The touch device id */
+	gestureId:  GestureID,
+	numFingers: u32,
+	error:      f32,
+	x:          f32,       /**< Normalized center of gesture */
+	y:          f32,       /**< Normalized center of gesture */
+}
+
+
+DropEvent :: struct {
+	type: EventType,        /**< ::SDL_DROPBEGIN or ::SDL_DROPFILE or ::SDL_DROPTEXT or ::SDL_DROPCOMPLETE */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	file:      cstring,         /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */
+	windowID:  u32,    /**< The window that was dropped on, if any */
+}
+
+
+SensorEvent :: struct {
+	type: EventType,        /**< ::SDL_SENSORUPDATE */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+	which:     i32,       /**< The instance ID of the sensor */
+	data:      [6]f32,      /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */
+}
+
+QuitEvent :: struct {
+	type: EventType,        /**< ::SDL_QUIT */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+}
+
+OSEvent :: struct {
+	type: EventType,        /**< ::SDL_QUIT */
+	timestamp: u32,   /**< In milliseconds, populated using SDL_GetTicks() */
+}
+
+UserEvent :: struct {
+	type: EventType,   /**< ::SDL_USEREVENT through ::SDL_LASTEVENT-1 */
+	timestamp: u32,    /**< In milliseconds, populated using SDL_GetTicks() */
+	windowID:  u32,    /**< The associated window if any */
+	code:      i32,    /**< User defined event code */
+	data1:     rawptr, /**< User defined data pointer */
+	data2:     rawptr, /**< User defined data pointer */
+}
+
+
+SysWMEvent :: struct {
+	type: EventType,     /**< ::SDL_SYSWMEVENT */
+	timestamp: u32,      /**< In milliseconds, populated using SDL_GetTicks() */
+	msg:      ^SysWMmsg, /**< driver dependent data, defined in SDL_syswm.h */
+}
+
+Event :: struct #raw_union {
+	type:      EventType,               /**< Event type, shared with all events */
+	common:    CommonEvent,             /**< Common event data */
+	display:   DisplayEvent,            /**< Display event data */
+	window:    WindowEvent,             /**< Window event data */
+	key:       KeyboardEvent,           /**< Keyboard event data */
+	edit:      TextEditingEvent,        /**< Text editing event data */
+	text:      TextInputEvent,          /**< Text input event data */
+	motion:    MouseMotionEvent,        /**< Mouse motion event data */
+	button:    MouseButtonEvent,        /**< Mouse button event data */
+	wheel:     MouseWheelEvent,         /**< Mouse wheel event data */
+	jaxis:     JoyAxisEvent,            /**< Joystick axis event data */
+	jball:     JoyBallEvent,            /**< Joystick ball event data */
+	jhat:      JoyHatEvent,             /**< Joystick hat event data */
+	jbutton:   JoyButtonEvent,          /**< Joystick button event data */
+	jdevice:   JoyDeviceEvent,          /**< Joystick device change event data */
+	caxis:     ControllerAxisEvent,     /**< Game Controller axis event data */
+	cbutton:   ControllerButtonEvent,   /**< Game Controller button event data */
+	cdevice:   ControllerDeviceEvent,   /**< Game Controller device event data */
+	ctouchpad: ControllerTouchpadEvent, /**< Game Controller touchpad event data */
+	csensor:   ControllerSensorEvent,   /**< Game Controller sensor event data */
+	adevice:   AudioDeviceEvent,        /**< Audio device event data */
+	sensor:    SensorEvent,             /**< Sensor event data */
+	quit:      QuitEvent,               /**< Quit request event data */
+	user:      UserEvent,               /**< Custom event data */
+	syswm:     SysWMEvent,              /**< System dependent window event data */
+	tfinger:   TouchFingerEvent,        /**< Touch finger event data */
+	mgesture:  MultiGestureEvent,       /**< Gesture event data */
+	dgesture:  DollarGestureEvent,      /**< Gesture event data */
+	drop:      DropEvent,               /**< Drag and drop event data */
+
+	padding: [56 when size_of(rawptr) <= 8 else 64 when size_of(rawptr) == 16 else 3 * size_of(rawptr)]u8,
+}
+
+
+
+/* Make sure we haven't broken binary compatibility */
+#assert(size_of(Event) == size_of(Event{}.padding));
+
+
+
+eventaction :: enum c.int {
+	ADDEVENT,
+	PEEKEVENT,
+	GETEVENT,
+}
+
+EventFilter :: proc "c" (userdata: rawptr, event: ^Event) -> c.int;
+
+QUERY   :: -1;
+IGNORE  ::  0;
+DISABLE ::  0;
+ENABLE  ::  1;
+
+
+GetEventState :: #force_inline proc "c" (type: EventType) -> u8 { return EventState(type, QUERY) }
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	PumpEvents       :: proc() ---
+	PeepEvents       :: proc(event: ^Event, numevents: c.int, action: eventaction, minType, maxType: EventType) -> c.int ---
+	HasEvent         :: proc(type: EventType) -> bool ---
+	HasEvents        :: proc(minType, maxType: EventType) -> bool ---
+	FlushEvent       :: proc(type: EventType) ---
+	FlushEvents      :: proc(minType, maxType: EventType) ---
+	PollEvent        :: proc(event: ^Event) -> c.int ---
+	WaitEvent        :: proc(event: ^Event) -> c.int ---
+	WaitEventTimeout :: proc(event: ^Event, timeout: c.int) -> c.int ---
+	PushEvent        :: proc(event: ^Event) -> c.int ---
+	SetEventFilter   :: proc(filter: EventFilter, userdata: rawptr) ---
+	GetEventFilter   :: proc(filter: ^EventFilter, userdata: ^rawptr) -> bool ---
+	AddEventWatch    :: proc(filter: EventFilter, userdata: rawptr) ---
+	DelEventWatch    :: proc(filter: EventFilter, userdata: rawptr) ---
+	FilterEvents     :: proc(filter: EventFilter, userdata: rawptr) ---
+	EventState       :: proc(type: EventType, state: c.int) -> u8 ---
+	RegisterEvents   :: proc(numevents: c.int) -> u32 ---
+}

+ 141 - 0
vendor/sdl2/sdl_gamecontroller.odin

@@ -0,0 +1,141 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+GameController :: struct {};
+
+GameControllerType :: enum c.int {
+	UNKNOWN = 0,
+	XBOX360,
+	XBOXONE,
+	PS3,
+	PS4,
+	NINTENDO_SWITCH_PRO,
+	VIRTUAL,
+	PS5,
+	AMAZON_LUNA,
+	GOOGLE_STADIA,
+}
+
+GameControllerBindType :: enum c.int {
+	NONE = 0,
+	BUTTON,
+	AXIS,
+	HAT,
+}
+
+GameControllerButtonBind :: struct {
+	bindType: GameControllerBindType,
+	value: struct #raw_union {
+		button: c.int,
+		axis:   c.int,
+		hat: struct {
+			hat:      c.int,
+			hat_mask: c.int,
+		},
+	},
+}
+
+GameControllerAxis :: enum c.int {
+	INVALID = -1,
+	LEFTX,
+	LEFTY,
+	RIGHTX,
+	RIGHTY,
+	TRIGGERLEFT,
+	TRIGGERRIGHT,
+	MAX,
+}
+
+GameControllerButton :: enum c.int {
+    	INVALID = -1,
+    	A,
+    	B,
+    	X,
+    	Y,
+    	BACK,
+    	GUIDE,
+    	START,
+    	LEFTSTICK,
+    	RIGHTSTICK,
+    	LEFTSHOULDER,
+    	RIGHTSHOULDER,
+    	DPAD_UP,
+    	DPAD_DOWN,
+    	DPAD_LEFT,
+    	DPAD_RIGHT,
+    	MISC1,    /* Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button */
+    	PADDLE1,  /* Xbox Elite paddle P1 */
+    	PADDLE2,  /* Xbox Elite paddle P3 */
+    	PADDLE3,  /* Xbox Elite paddle P2 */
+    	PADDLE4,  /* Xbox Elite paddle P4 */
+    	TOUCHPAD, /* PS4/PS5 touchpad button */
+    	MAX,
+}
+
+
+GameControllerAddMappingsFromFile :: #force_inline proc "c" (file: cstring) -> c.int {
+	return GameControllerAddMappingsFromRW(RWFromFile(file, "rb"), true);
+}
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GameControllerAddMappingsFromRW     :: proc(rw: ^RWops, freerw: bool) -> c.int ---
+
+	GameControllerAddMapping            :: proc(mappingString: cstring) -> c.int ---
+	GameControllerNumMappings           :: proc() -> c.int ---
+	GameControllerMappingForIndex       :: proc(mapping_index: c.int) -> cstring  ---
+	GameControllerMappingForGUID        :: proc(guid: JoystickGUID) -> cstring  ---
+	GameControllerMapping               :: proc(gamecontroller: ^GameController) -> cstring  ---
+	IsGameController                    :: proc(joystick_index: c.int) -> bool ---
+	GameControllerNameForIndex          :: proc(joystick_index: c.int) -> cstring ---
+	GameControllerTypeForIndex          :: proc(joystick_index: c.int) -> GameControllerType ---
+	GameControllerMappingForDeviceIndex :: proc(joystick_index: c.int) -> cstring ---
+	GameControllerOpen                  :: proc(joystick_index: c.int)   -> ^GameController ---
+	GameControllerFromInstanceID        :: proc(joyid: JoystickID) -> ^GameController ---
+	GameControllerFromPlayerIndex       :: proc(player_index: c.int)     -> ^GameController ---
+	GameControllerName                  :: proc(gamecontroller: ^GameController) -> cstring  ---
+	GameControllerGetType               :: proc(gamecontroller: ^GameController) -> GameControllerType ---
+	GameControllerGetPlayerIndex        :: proc(gamecontroller: ^GameController) -> c.int ---
+	GameControllerSetPlayerIndex        :: proc(gamecontroller: ^GameController, player_index: c.int) ---
+	GameControllerGetVendor             :: proc(gamecontroller: ^GameController) -> u16 ---
+	GameControllerGetProduct            :: proc(gamecontroller: ^GameController) -> u16 ---
+	GameControllerGetProductVersion     :: proc(gamecontroller: ^GameController) -> u16 ---
+	GameControllerGetSerial             :: proc(gamecontroller: ^GameController) -> cstring ---
+	GameControllerGetAttached           :: proc(gamecontroller: ^GameController) -> bool ---
+	GameControllerGetJoystick           :: proc(gamecontroller: ^GameController) -> ^Joystick ---
+	GameControllerEventState            :: proc(state: c.int) -> c.int ---
+	GameControllerUpdate                :: proc() ---
+
+	GameControllerGetAxisFromString     :: proc(str: cstring) -> GameControllerAxis ---
+	GameControllerGetStringForAxis      :: proc(axis: GameControllerAxis) -> cstring ---
+	GameControllerGetBindForAxis        :: proc(gamecontroller: ^GameController, axis: GameControllerAxis)  -> GameControllerButtonBind---
+	GameControllerHasAxis               :: proc(gamecontroller: ^GameController, axis: GameControllerAxis) -> bool ---
+	GameControllerGetAxis               :: proc(gamecontroller: ^GameController, axis: GameControllerAxis)  -> i16 ---
+
+	GameControllerGetButtonFromString   :: proc(str: cstring) -> GameControllerButton ---
+	GameControllerGetStringForButton    :: proc(button: GameControllerButton) -> cstring ---
+	GameControllerGetBindForButton      :: proc(gamecontroller: ^GameController, button: GameControllerButton) -> GameControllerButtonBind ---
+	GameControllerHasButton             :: proc(gamecontroller: ^GameController, button: GameControllerButton) -> bool ---
+	GameControllerGetButton             :: proc(gamecontroller: ^GameController, button: GameControllerButton) -> u8 ---
+	GameControllerGetNumTouchpads       :: proc(gamecontroller: ^GameController) -> c.int ---
+	GameControllerGetNumTouchpadFingers :: proc(gamecontroller: ^GameController, touchpad: c.int) -> c.int ---
+	GameControllerGetTouchpadFinger     :: proc(gamecontroller: ^GameController, touchpad: c.int, finger: c.int, state: ^u8, x, y: ^f32, pressure: ^f32) -> c.int ---
+	GameControllerHasSensor             :: proc(gamecontroller: ^GameController, type: SensorType) -> bool ---
+	GameControllerSetSensorEnabled      :: proc(gamecontroller: ^GameController, type: SensorType, enabled: bool) -> c.int ---
+	GameControllerIsSensorEnabled       :: proc(gamecontroller: ^GameController, type: SensorType) -> bool ---
+	GameControllerGetSensorDataRate     :: proc(gamecontroller: ^GameController, type: SensorType) -> f32 ---
+	GameControllerGetSensorData         :: proc(gamecontroller: ^GameController, type: SensorType, data: ^f32, num_values: c.int) -> c.int ---
+	GameControllerRumble                :: proc(gamecontroller: ^GameController, low_frequency_rumble, high_frequency_rumble: u16, duration_ms: u32) -> c.int ---
+	GameControllerRumbleTriggers        :: proc(gamecontroller: ^GameController, left_rumble, right_rumble: u16, duration_ms: u32) -> c.int ---
+	GameControllerHasLED                :: proc(gamecontroller: ^GameController) -> bool ---
+	GameControllerSetLED                :: proc(gamecontroller: ^GameController, red, green, blue: u8) -> c.int ---
+	GameControllerSendEffect            :: proc(gamecontroller: ^GameController, data: rawptr, size: c.int) -> c.int ---
+	GameControllerClose                 :: proc(gamecontroller: ^GameController) ---
+}

+ 262 - 0
vendor/sdl2/sdl_gesture_haptic.odin

@@ -0,0 +1,262 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+// Gesture
+
+GestureID :: distinct i64;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	RecordGesture          :: proc(touchId: ^TouchID)                 -> c.int ---
+	SaveAllDollarTemplates :: proc(dst: ^RWops)                       -> c.int ---
+	SaveDollarTemplate     :: proc(gestureId: GestureID, dst: ^RWops) -> c.int ---
+	LoadDollarTemplates    :: proc(touchId: ^TouchID, src: ^RWops)    -> c.int ---
+}
+
+// Haptic
+
+Haptic :: struct {};
+
+
+HapticType :: enum u16 {
+	CONSTANT      = 1<<0,
+	SINE          = 1<<1,
+	LEFTRIGHT     = 1<<2,
+	TRIANGLE      = 1<<3,
+	SAWTOOTHUP    = 1<<4,
+	SAWTOOTHDOWN  = 1<<5,
+	RAMP          = 1<<6,
+	SPRING        = 1<<7,
+	DAMPER        = 1<<8,
+	INERTIA       = 1<<9,
+	FRICTION      = 1<<10,
+	CUSTOM        = 1<<11,
+	GAIN          = 1<<12,
+	AUTOCENTER    = 1<<13,
+	STATUS        = 1<<14,
+	PAUSE         = 1<<15,
+}
+HAPTIC_CONSTANT      :: HapticType.CONSTANT;
+HAPTIC_SINE          :: HapticType.SINE;
+HAPTIC_LEFTRIGHT     :: HapticType.LEFTRIGHT;
+HAPTIC_TRIANGLE      :: HapticType.TRIANGLE;
+HAPTIC_SAWTOOTHUP    :: HapticType.SAWTOOTHUP;
+HAPTIC_SAWTOOTHDOWN  :: HapticType.SAWTOOTHDOWN;
+HAPTIC_RAMP          :: HapticType.RAMP;
+HAPTIC_SPRING        :: HapticType.SPRING;
+HAPTIC_DAMPER        :: HapticType.DAMPER;
+HAPTIC_INERTIA       :: HapticType.INERTIA;
+HAPTIC_FRICTION      :: HapticType.FRICTION;
+HAPTIC_CUSTOM        :: HapticType.CUSTOM;
+HAPTIC_GAIN          :: HapticType.GAIN;
+HAPTIC_AUTOCENTER    :: HapticType.AUTOCENTER;
+HAPTIC_STATUS        :: HapticType.STATUS;
+HAPTIC_PAUSE         :: HapticType.PAUSE;
+
+HapticDirectionType :: enum u8 {
+	POLAR         = 0,
+	CARTESIAN     = 1,
+	SPHERICAL     = 2,
+	STEERING_AXIS = 3,
+}
+
+HAPTIC_POLAR         :: HapticDirectionType.POLAR;
+HAPTIC_CARTESIAN     :: HapticDirectionType.CARTESIAN;
+HAPTIC_SPHERICAL     :: HapticDirectionType.SPHERICAL;
+HAPTIC_STEERING_AXIS :: HapticDirectionType.STEERING_AXIS;
+
+HAPTIC_INFINITY :: 4294967295;
+
+HapticDirection :: struct {
+	type: HapticDirectionType, /**< The type of encoding. */
+	dir:  [3]i32,              /**< The encoded direction. */
+}
+
+HapticConstant :: struct {
+	/* Header */
+	type:          HapticType,      /**< ::SDL_HAPTIC_CONSTANT */
+	direction:     HapticDirection, /**< Direction of the effect. */
+
+	/* Replay */
+	length:        u32,             /**< Duration of the effect. */
+	delay:         u16,             /**< Delay before starting the effect. */
+
+	/* Trigger */
+	button:        u16,             /**< Button that triggers the effect. */
+	interval:      u16,             /**< How soon it can be triggered again after button. */
+
+	/* Constant */
+	level:         i16,             /**< Strength of the constant effect. */
+
+	/* Envelope */
+	attack_length: u16,             /**< Duration of the attack. */
+	attack_level:  u16,             /**< Level at the start of the attack. */
+	fade_length:   u16,             /**< Duration of the fade. */
+	fade_level:    u16,             /**< Level at the end of the fade. */
+}
+
+HapticPeriodic :: struct {
+	/* Header */
+	type: HapticType,  /**< ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_LEFTRIGHT,
+	                        ::SDL_HAPTIC_TRIANGLE, ::SDL_HAPTIC_SAWTOOTHUP or
+	                        ::SDL_HAPTIC_SAWTOOTHDOWN */
+	direction: HapticDirection,  /**< Direction of the effect. */
+
+	/* Replay */
+	length: u32,                 /**< Duration of the effect. */
+	delay:  u16,                 /**< Delay before starting the effect. */
+
+	/* Trigger */
+	button:   u16,               /**< Button that triggers the effect. */
+	interval: u16,               /**< How soon it can be triggered again after button. */
+
+	/* Periodic */
+	period:    u16,              /**< Period of the wave. */
+	magnitude: i16,              /**< Peak value; if negative, equivalent to 180 degrees extra phase shift. */
+	offset:    i16,              /**< Mean value of the wave. */
+	phase:     u16,              /**< Positive phase shift given by hundredth of a degree. */
+
+	/* Envelope */
+	attack_length: u16,          /**< Duration of the attack. */
+	attack_level:  u16,          /**< Level at the start of the attack. */
+	fade_length:   u16,          /**< Duration of the fade. */
+	fade_level:    u16,          /**< Level at the end of the fade. */
+}
+
+HapticCondition :: struct {
+	/* Header */
+	type: HapticType,   /**< ::SDL_HAPTIC_SPRING, ::SDL_HAPTIC_DAMPER,
+	                         ::SDL_HAPTIC_INERTIA or ::SDL_HAPTIC_FRICTION */
+	direction: HapticDirection, /**< Direction of the effect - Not used ATM. */
+
+	/* Replay */
+	length: u32,         /**< Duration of the effect. */
+	delay:  u16,         /**< Delay before starting the effect. */
+
+	/* Trigger */
+	button:   u16,       /**< Button that triggers the effect. */
+	interval: u16,       /**< How soon it can be triggered again after button. */
+
+	/* Condition */
+	right_sat:   [3]u16, /**< Level when joystick is to the positive side; max 0xFFFF. */
+	left_sat:    [3]u16, /**< Level when joystick is to the negative side; max 0xFFFF. */
+	right_coeff: [3]i16, /**< How fast to increase the force towards the positive side. */
+	left_coeff:  [3]i16, /**< How fast to increase the force towards the negative side. */
+	deadband:    [3]u16, /**< Size of the dead zone; max 0xFFFF: whole axis-range when 0-centered. */
+	center:      [3]i16, /**< Position of the dead zone. */
+}
+
+HapticRamp :: struct {
+	/* Header */
+	type: HapticType,            /**< ::SDL_HAPTIC_RAMP */
+	direction: HapticDirection,  /**< Direction of the effect. */
+
+	/* Replay */
+	length: u32,        /**< Duration of the effect. */
+	delay:  u16,        /**< Delay before starting the effect. */
+
+	/* Trigger */
+	button:   u16,      /**< Button that triggers the effect. */
+	interval: u16,      /**< How soon it can be triggered again after button. */
+
+	/* Ramp */
+	start: i16,         /**< Beginning strength level. */
+	end:   i16,         /**< Ending strength level. */
+
+	/* Envelope */
+	attack_length: u16, /**< Duration of the attack. */
+	attack_level:  u16, /**< Level at the start of the attack. */
+	fade_length:   u16, /**< Duration of the fade. */
+	fade_level:    u16, /**< Level at the end of the fade. */
+}
+
+HapticLeftRight :: struct {
+	/* Header */
+	type: HapticType,            /**< ::SDL_HAPTIC_LEFTRIGHT */
+
+	/* Replay */
+	length: u32,          /**< Duration of the effect in milliseconds. */
+
+	/* Rumble */
+	large_magnitude: u16, /**< Control of the large controller motor. */
+	small_magnitude: u16, /**< Control of the small controller motor. */
+}
+
+
+HapticCustom :: struct {
+	/* Header */
+	type: HapticType,           /**< ::SDL_HAPTIC_CUSTOM */
+	direction: HapticDirection, /**< Direction of the effect. */
+
+	/* Replay */
+	length:        u32,  /**< Duration of the effect. */
+	delay:         u16,  /**< Delay before starting the effect. */
+
+	/* Trigger */
+	button:        u16,  /**< Button that triggers the effect. */
+	interval:      u16,  /**< How soon it can be triggered again after button. */
+
+	/* Custom */
+	channels:      u8,     /**< Axes to use, minimum of one. */
+	period:        u16,    /**< Sample periods. */
+	samples:       u16,    /**< Amount of samples. */
+	data:          [^]u16, /**< Should contain channels*samples items. */
+
+	/* Envelope */
+	attack_length: u16,  /**< Duration of the attack. */
+	attack_level:  u16,  /**< Level at the start of the attack. */
+	fade_length:   u16,  /**< Duration of the fade. */
+	fade_level:    u16,  /**< Level at the end of the fade. */
+}
+
+HapticEffect :: struct #raw_union {
+	/* Common for all force feedback effects */
+	type:      HapticType,      /**< Effect type. */
+	constant:  HapticConstant,  /**< Constant effect. */
+	periodic:  HapticPeriodic,  /**< Periodic effect. */
+	condition: HapticCondition, /**< Condition effect. */
+	ramp:      HapticRamp,      /**< Ramp effect. */
+	leftright: HapticLeftRight, /**< Left/Right effect. */
+	custom:    HapticCustom,    /**< Custom effect. */
+}
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	NumHaptics              :: proc() -> c.int ---
+	HapticName              :: proc(device_index: c.int) -> cstring ---
+	HapticOpen              :: proc(device_index: c.int) -> ^Haptic ---
+	HapticOpened            :: proc(device_index: c.int) -> c.int ---
+	HapticIndex             :: proc(haptic: ^Haptic) -> c.int ---
+	MouseIsHaptic           :: proc() -> c.int ---
+	HapticOpenFromMouse     :: proc() -> ^Haptic ---
+	JoystickIsHaptic        :: proc(joystick: ^Joystick) -> c.int ---
+	HapticOpenFromJoystick  :: proc(joystick: ^Joystick) -> ^Haptic ---
+	HapticClose             :: proc(haptic: ^Haptic) ---
+	HapticNumEffects        :: proc(haptic: ^Haptic) -> c.int ---
+	HapticNumEffectsPlaying :: proc(haptic: ^Haptic) -> c.int ---
+	HapticQuery             :: proc(haptic: ^Haptic) -> c.uint ---
+	HapticNumAxes           :: proc(haptic: ^Haptic) -> c.int ---
+	HapticEffectSupported   :: proc(haptic: ^Haptic, effect: ^HapticEffect) -> c.int ---
+	HapticNewEffect         :: proc(haptic: ^Haptic, effect: ^HapticEffect) -> c.int ---
+	HapticUpdateEffect      :: proc(haptic: ^Haptic, effect: c.int, data: ^HapticEffect) -> c.int ---
+	HapticRunEffect         :: proc(haptic: ^Haptic, effect: c.int, iterations: u32) -> c.int ---
+	HapticStopEffect        :: proc(haptic: ^Haptic, effect: c.int) -> c.int ---
+	HapticDestroyEffect     :: proc(haptic: ^Haptic, effect: c.int) ---
+	HapticGetEffectStatus   :: proc(haptic: ^Haptic, effect: c.int) -> c.int ---
+	HapticSetGain           :: proc(haptic: ^Haptic, gain: c.int) -> c.int ---
+	HapticSetAutocenter     :: proc(haptic: ^Haptic, autocenter: c.int) -> c.int ---
+	HapticPause             :: proc(haptic: ^Haptic) -> c.int ---
+	HapticUnpause           :: proc(haptic: ^Haptic) -> c.int ---
+	HapticStopAll           :: proc(haptic: ^Haptic) -> c.int ---
+	HapticRumbleSupported   :: proc(haptic: ^Haptic) -> c.int ---
+	HapticRumbleInit        :: proc(haptic: ^Haptic) -> c.int ---
+	HapticRumblePlay        :: proc(haptic: ^Haptic, strength: f32, length: u32) -> c.int ---
+	HapticRumbleStop        :: proc(haptic: ^Haptic) -> c.int ---
+}

+ 149 - 0
vendor/sdl2/sdl_hints.odin

@@ -0,0 +1,149 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+HINT_ACCELEROMETER_AS_JOYSTICK                :: "SDL_ACCELEROMETER_AS_JOYSTICK";
+HINT_ALLOW_ALT_TAB_WHILE_GRABBED              :: "SDL_ALLOW_ALT_TAB_WHILE_GRABBED";
+HINT_ALLOW_TOPMOST                            :: "SDL_ALLOW_TOPMOST";
+HINT_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION  :: "SDL_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION";
+HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION :: "SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION";
+HINT_ANDROID_BLOCK_ON_PAUSE                   :: "SDL_ANDROID_BLOCK_ON_PAUSE";
+HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO        :: "SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO";
+HINT_ANDROID_TRAP_BACK_BUTTON                 :: "SDL_ANDROID_TRAP_BACK_BUTTON";
+HINT_APPLE_TV_CONTROLLER_UI_EVENTS            :: "SDL_APPLE_TV_CONTROLLER_UI_EVENTS";
+HINT_APPLE_TV_REMOTE_ALLOW_ROTATION           :: "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION";
+HINT_AUDIO_CATEGORY                           :: "SDL_AUDIO_CATEGORY";
+HINT_AUDIO_DEVICE_APP_NAME                    :: "SDL_AUDIO_DEVICE_APP_NAME";
+HINT_AUDIO_DEVICE_STREAM_NAME                 :: "SDL_AUDIO_DEVICE_STREAM_NAME";
+HINT_AUDIO_DEVICE_STREAM_ROLE                 :: "SDL_AUDIO_DEVICE_STREAM_ROLE";
+HINT_AUDIO_RESAMPLING_MODE                    :: "SDL_AUDIO_RESAMPLING_MODE";
+HINT_AUTO_UPDATE_JOYSTICKS                    :: "SDL_AUTO_UPDATE_JOYSTICKS";
+HINT_AUTO_UPDATE_SENSORS                      :: "SDL_AUTO_UPDATE_SENSORS";
+HINT_BMP_SAVE_LEGACY_FORMAT                   :: "SDL_BMP_SAVE_LEGACY_FORMAT";
+HINT_DISPLAY_USABLE_BOUNDS                    :: "SDL_DISPLAY_USABLE_BOUNDS";
+HINT_EMSCRIPTEN_ASYNCIFY                      :: "SDL_EMSCRIPTEN_ASYNCIFY";
+HINT_EMSCRIPTEN_KEYBOARD_ELEMENT              :: "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT";
+HINT_ENABLE_STEAM_CONTROLLERS                 :: "SDL_ENABLE_STEAM_CONTROLLERS";
+HINT_EVENT_LOGGING                            :: "SDL_EVENT_LOGGING";
+HINT_FRAMEBUFFER_ACCELERATION                 :: "SDL_FRAMEBUFFER_ACCELERATION";
+HINT_GAMECONTROLLERCONFIG                     :: "SDL_GAMECONTROLLERCONFIG";
+HINT_GAMECONTROLLERCONFIG_FILE                :: "SDL_GAMECONTROLLERCONFIG_FILE";
+HINT_GAMECONTROLLERTYPE                       :: "SDL_GAMECONTROLLERTYPE";
+HINT_GAMECONTROLLER_IGNORE_DEVICES            :: "SDL_GAMECONTROLLER_IGNORE_DEVICES";
+HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT     :: "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT";
+HINT_GAMECONTROLLER_USE_BUTTON_LABELS         :: "SDL_GAMECONTROLLER_USE_BUTTON_LABELS";
+HINT_GRAB_KEYBOARD                            :: "SDL_GRAB_KEYBOARD";
+HINT_IDLE_TIMER_DISABLED                      :: "SDL_IOS_IDLE_TIMER_DISABLED";
+HINT_IME_INTERNAL_EDITING                     :: "SDL_IME_INTERNAL_EDITING";
+HINT_IOS_HIDE_HOME_INDICATOR                  :: "SDL_IOS_HIDE_HOME_INDICATOR";
+HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS         :: "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS";
+HINT_JOYSTICK_HIDAPI                          :: "SDL_JOYSTICK_HIDAPI";
+HINT_JOYSTICK_HIDAPI_GAMECUBE                 :: "SDL_JOYSTICK_HIDAPI_GAMECUBE";
+HINT_JOYSTICK_HIDAPI_JOY_CONS                 :: "SDL_JOYSTICK_HIDAPI_JOY_CONS";
+HINT_JOYSTICK_HIDAPI_LUNA                     :: "SDL_JOYSTICK_HIDAPI_LUNA";
+HINT_JOYSTICK_HIDAPI_PS4                      :: "SDL_JOYSTICK_HIDAPI_PS4";
+HINT_JOYSTICK_HIDAPI_PS4_RUMBLE               :: "SDL_JOYSTICK_HIDAPI_PS4_RUMBLE";
+HINT_JOYSTICK_HIDAPI_PS5                      :: "SDL_JOYSTICK_HIDAPI_PS5";
+HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED           :: "SDL_JOYSTICK_HIDAPI_PS5_PLAYER_LED";
+HINT_JOYSTICK_HIDAPI_PS5_RUMBLE               :: "SDL_JOYSTICK_HIDAPI_PS5_RUMBLE";
+HINT_JOYSTICK_HIDAPI_STADIA                   :: "SDL_JOYSTICK_HIDAPI_STADIA";
+HINT_JOYSTICK_HIDAPI_STEAM                    :: "SDL_JOYSTICK_HIDAPI_STEAM";
+HINT_JOYSTICK_HIDAPI_SWITCH                   :: "SDL_JOYSTICK_HIDAPI_SWITCH";
+HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED          :: "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED";
+HINT_JOYSTICK_HIDAPI_XBOX                     :: "SDL_JOYSTICK_HIDAPI_XBOX";
+HINT_JOYSTICK_RAWINPUT                        :: "SDL_JOYSTICK_RAWINPUT";
+HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT       :: "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT";
+HINT_JOYSTICK_THREAD                          :: "SDL_JOYSTICK_THREAD";
+HINT_KMSDRM_REQUIRE_DRM_MASTER                :: "SDL_KMSDRM_REQUIRE_DRM_MASTER";
+HINT_LINUX_JOYSTICK_DEADZONES                 :: "SDL_LINUX_JOYSTICK_DEADZONES";
+HINT_MAC_BACKGROUND_APP                       :: "SDL_MAC_BACKGROUND_APP";
+HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK       :: "SDL_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK";
+HINT_MOUSE_DOUBLE_CLICK_RADIUS                :: "SDL_MOUSE_DOUBLE_CLICK_RADIUS";
+HINT_MOUSE_DOUBLE_CLICK_TIME                  :: "SDL_MOUSE_DOUBLE_CLICK_TIME";
+HINT_MOUSE_FOCUS_CLICKTHROUGH                 :: "SDL_MOUSE_FOCUS_CLICKTHROUGH";
+HINT_MOUSE_NORMAL_SPEED_SCALE                 :: "SDL_MOUSE_NORMAL_SPEED_SCALE";
+HINT_MOUSE_RELATIVE_MODE_WARP                 :: "SDL_MOUSE_RELATIVE_MODE_WARP";
+HINT_MOUSE_RELATIVE_SCALING                   :: "SDL_MOUSE_RELATIVE_SCALING";
+HINT_MOUSE_RELATIVE_SPEED_SCALE               :: "SDL_MOUSE_RELATIVE_SPEED_SCALE";
+HINT_MOUSE_TOUCH_EVENTS                       :: "SDL_MOUSE_TOUCH_EVENTS";
+HINT_NO_SIGNAL_HANDLERS                       :: "SDL_NO_SIGNAL_HANDLERS";
+HINT_OPENGL_ES_DRIVER                         :: "SDL_OPENGL_ES_DRIVER";
+HINT_ORIENTATIONS                             :: "SDL_IOS_ORIENTATIONS";
+HINT_PREFERRED_LOCALES                        :: "SDL_PREFERRED_LOCALES";
+HINT_QTWAYLAND_CONTENT_ORIENTATION            :: "SDL_QTWAYLAND_CONTENT_ORIENTATION";
+HINT_QTWAYLAND_WINDOW_FLAGS                   :: "SDL_QTWAYLAND_WINDOW_FLAGS";
+HINT_RENDER_BATCHING                          :: "SDL_RENDER_BATCHING";
+HINT_RENDER_DIRECT3D11_DEBUG                  :: "SDL_RENDER_DIRECT3D11_DEBUG";
+HINT_RENDER_DIRECT3D_THREADSAFE               :: "SDL_RENDER_DIRECT3D_THREADSAFE";
+HINT_RENDER_DRIVER                            :: "SDL_RENDER_DRIVER";
+HINT_RENDER_LOGICAL_SIZE_MODE                 :: "SDL_RENDER_LOGICAL_SIZE_MODE";
+HINT_RENDER_OPENGL_SHADERS                    :: "SDL_RENDER_OPENGL_SHADERS";
+HINT_RENDER_SCALE_QUALITY                     :: "SDL_RENDER_SCALE_QUALITY";
+HINT_RENDER_VSYNC                             :: "SDL_RENDER_VSYNC";
+HINT_RETURN_KEY_HIDES_IME                     :: "SDL_RETURN_KEY_HIDES_IME";
+HINT_RPI_VIDEO_LAYER                          :: "SDL_RPI_VIDEO_LAYER";
+HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL      :: "SDL_THREAD_FORCE_REALTIME_TIME_CRITICAL";
+HINT_THREAD_PRIORITY_POLICY                   :: "SDL_THREAD_PRIORITY_POLICY";
+HINT_THREAD_STACK_SIZE                        :: "SDL_THREAD_STACK_SIZE";
+HINT_TIMER_RESOLUTION                         :: "SDL_TIMER_RESOLUTION";
+HINT_TOUCH_MOUSE_EVENTS                       :: "SDL_TOUCH_MOUSE_EVENTS";
+HINT_TV_REMOTE_AS_JOYSTICK                    :: "SDL_TV_REMOTE_AS_JOYSTICK";
+HINT_VIDEO_ALLOW_SCREENSAVER                  :: "SDL_VIDEO_ALLOW_SCREENSAVER";
+HINT_VIDEO_DOUBLE_BUFFER                      :: "SDL_VIDEO_DOUBLE_BUFFER";
+HINT_VIDEO_EXTERNAL_CONTEXT                   :: "SDL_VIDEO_EXTERNAL_CONTEXT";
+HINT_VIDEO_HIGHDPI_DISABLED                   :: "SDL_VIDEO_HIGHDPI_DISABLED";
+HINT_VIDEO_MAC_FULLSCREEN_SPACES              :: "SDL_VIDEO_MAC_FULLSCREEN_SPACES";
+HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS             :: "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS";
+HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR             :: "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR";
+HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT          :: "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT";
+HINT_VIDEO_WIN_D3DCOMPILER                    :: "SDL_VIDEO_WIN_D3DCOMPILER";
+HINT_VIDEO_X11_FORCE_EGL                      :: "SDL_VIDEO_X11_FORCE_EGL";
+HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR       :: "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR";
+HINT_VIDEO_X11_NET_WM_PING                    :: "SDL_VIDEO_X11_NET_WM_PING";
+HINT_VIDEO_X11_WINDOW_VISUALID                :: "SDL_VIDEO_X11_WINDOW_VISUALID";
+HINT_VIDEO_X11_XINERAMA                       :: "SDL_VIDEO_X11_XINERAMA";
+HINT_VIDEO_X11_XRANDR                         :: "SDL_VIDEO_X11_XRANDR";
+HINT_VIDEO_X11_XVIDMODE                       :: "SDL_VIDEO_X11_XVIDMODE";
+HINT_WAVE_FACT_CHUNK                          :: "SDL_WAVE_FACT_CHUNK";
+HINT_WAVE_RIFF_CHUNK_SIZE                     :: "SDL_WAVE_RIFF_CHUNK_SIZE";
+HINT_WAVE_TRUNCATION                          :: "SDL_WAVE_TRUNCATION";
+HINT_WINDOWS_DISABLE_THREAD_NAMING            :: "SDL_WINDOWS_DISABLE_THREAD_NAMING";
+HINT_WINDOWS_ENABLE_MESSAGELOOP               :: "SDL_WINDOWS_ENABLE_MESSAGELOOP";
+HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS    :: "SDL_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS";
+HINT_WINDOWS_FORCE_SEMAPHORE_KERNEL           :: "SDL_WINDOWS_FORCE_SEMAPHORE_KERNEL";
+HINT_WINDOWS_INTRESOURCE_ICON                 :: "SDL_WINDOWS_INTRESOURCE_ICON";
+HINT_WINDOWS_INTRESOURCE_ICON_SMALL           :: "SDL_WINDOWS_INTRESOURCE_ICON_SMALL";
+HINT_WINDOWS_NO_CLOSE_ON_ALT_F4               :: "SDL_WINDOWS_NO_CLOSE_ON_ALT_F4";
+HINT_WINDOWS_USE_D3D9EX                       :: "SDL_WINDOWS_USE_D3D9EX";
+HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN  :: "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN";
+HINT_WINRT_HANDLE_BACK_BUTTON                 :: "SDL_WINRT_HANDLE_BACK_BUTTON";
+HINT_WINRT_PRIVACY_POLICY_LABEL               :: "SDL_WINRT_PRIVACY_POLICY_LABEL";
+HINT_WINRT_PRIVACY_POLICY_URL                 :: "SDL_WINRT_PRIVACY_POLICY_URL";
+HINT_X11_FORCE_OVERRIDE_REDIRECT              :: "SDL_X11_FORCE_OVERRIDE_REDIRECT";
+HINT_XINPUT_ENABLED                           :: "SDL_XINPUT_ENABLED";
+HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING          :: "SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING";
+HINT_AUDIO_INCLUDE_MONITORS                   :: "SDL_AUDIO_INCLUDE_MONITORS";
+
+HintPriority :: enum c.int {
+	DEFAULT,
+	NORMAL,
+	OVERRIDE,
+}
+
+HintCallback :: proc "c" (userdata: rawptr, name, oldValue, newValue: cstring);
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	SetHintWithPriority :: proc(name, value: cstring, priority: HintPriority) -> bool ---
+	SetHint             :: proc(name, value: cstring) -> bool ---
+	GetHint             :: proc(name: cstring) -> cstring ---
+	GetHintBoolean      :: proc(name: cstring, default_value: bool) -> bool ---
+	AddHintCallback     :: proc(name: cstring, callback: HintCallback, userdata: rawptr) ---
+	DelHintCallback     :: proc(name: cstring, callback: HintCallback, userdata: rawptr) ---
+	ClearHints          :: proc() ---
+}

+ 109 - 0
vendor/sdl2/sdl_joystick.odin

@@ -0,0 +1,109 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+Joystick :: struct {};
+
+JoystickGUID :: struct {
+	data: [16]u8,
+}
+
+JoystickID :: distinct i32;
+
+JoystickType :: enum c.int {
+	UNKNOWN,
+	GAMECONTROLLER,
+	WHEEL,
+	ARCADE_STICK,
+	FLIGHT_STICK,
+	DANCE_PAD,
+	GUITAR,
+	DRUM_KIT,
+	ARCADE_PAD,
+	THROTTLE,
+}
+
+JoystickPowerLevel :: enum c.int {
+	UNKNOWN = -1,
+	EMPTY,   /* <= 5% */
+	LOW,     /* <= 20% */
+	MEDIUM,  /* <= 70% */
+	FULL,    /* <= 100% */
+	WIRED,
+	MAX,
+}
+
+IPHONE_MAX_GFORCE :: 5.0;
+
+JOYSTICK_AXIS_MAX :: +32767;
+JOYSTICK_AXIS_MIN :: -32768;
+
+HAT_CENTERED  :: 0x00;
+HAT_UP        :: 0x01;
+HAT_RIGHT     :: 0x02;
+HAT_DOWN      :: 0x04;
+HAT_LEFT      :: 0x08;
+HAT_RIGHTUP   :: HAT_RIGHT|HAT_UP;
+HAT_RIGHTDOWN :: HAT_RIGHT|HAT_DOWN;
+HAT_LEFTUP    :: HAT_LEFT|HAT_UP;
+HAT_LEFTDOWN  :: HAT_LEFT|HAT_DOWN;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	LockJoysticks                   :: proc() ---
+	UnlockJoysticks                 :: proc() ---
+	NumJoysticks                    :: proc() -> c.int ---
+	JoystickNameForIndex            :: proc(device_index: c.int) -> cstring ---
+	JoystickGetDevicePlayerIndex    :: proc(device_index: c.int) -> c.int ---
+	JoystickGetDeviceGUID           :: proc(device_index: c.int) -> JoystickGUID ---
+	JoystickGetDeviceVendor         :: proc(device_index: c.int) -> u16 ---
+	JoystickGetDeviceProduct        :: proc(device_index: c.int) -> u16 ---
+	JoystickGetDeviceProductVersion :: proc(device_index: c.int) -> u16 ---
+	JoystickGetDeviceType           :: proc(device_index: c.int) -> JoystickType ---
+	JoystickGetDeviceInstanceID     :: proc(device_index: c.int) -> JoystickID ---
+	JoystickOpen                    :: proc(device_index: c.int) -> ^Joystick ---
+	JoystickFromInstanceID          :: proc(instance_id: JoystickID ) -> ^Joystick ---
+	JoystickFromPlayerIndex         :: proc(player_index: c.int) -> ^Joystick ---
+	JoystickAttachVirtual           :: proc(type: JoystickType, naxes, nbuttons, nhats: c.int) -> c.int ---
+	JoystickDetachVirtual           :: proc(device_index: c.int) -> c.int ---
+	JoystickIsVirtual               :: proc(device_index: c.int) -> bool ---
+	JoystickSetVirtualAxis          :: proc(joystick: ^Joystick, axis: c.int, value: i16) -> c.int ---
+	JoystickSetVirtualButton        :: proc(joystick: ^Joystick, button: c.int, value: u8) -> c.int ---
+	JoystickSetVirtualHat           :: proc(joystick: ^Joystick, hat: c.int, value: u8) -> c.int ---
+	JoystickName                    :: proc(joystick: ^Joystick) -> cstring ---
+	JoystickGetPlayerIndex          :: proc(joystick: ^Joystick) -> c.int ---
+	JoystickSetPlayerIndex          :: proc(joystick: ^Joystick, player_index: c.int) ---
+	JoystickGetGUID                 :: proc(joystick: ^Joystick) -> JoystickGUID ---
+	JoystickGetVendor               :: proc(joystick: ^Joystick) -> u16 ---
+	JoystickGetProduct              :: proc(joystick: ^Joystick) -> u16 ---
+	JoystickGetProductVersion       :: proc(joystick: ^Joystick) -> u16 ---
+	JoystickGetSerial               :: proc(joystick: ^Joystick) -> cstring ---
+	JoystickGetType                 :: proc(joystick: ^Joystick) -> JoystickType ---
+	JoystickGetGUIDString           :: proc(guid: JoystickGUID, pszGUID: [^]u8, cbGUID: c.int) ---
+	JoystickGetGUIDFromString       :: proc(pchGUID: cstring) -> JoystickGUID ---
+	JoystickGetAttached             :: proc(joystick: ^Joystick) -> bool ---
+	JoystickInstanceID              :: proc(joystick: ^Joystick) -> JoystickID ---
+	JoystickNumAxes                 :: proc(joystick: ^Joystick) -> c.int ---
+	JoystickNumBalls                :: proc(joystick: ^Joystick) -> c.int ---
+	JoystickNumHats                 :: proc(joystick: ^Joystick) -> c.int ---
+	JoystickNumButtons              :: proc(joystick: ^Joystick) -> c.int ---
+	JoystickUpdate                  :: proc() ---
+	JoystickEventState              :: proc(state: c.int) -> c.int ---
+	JoystickGetAxis                 :: proc(joystick: ^Joystick, axis: c.int) -> i64 ---
+	JoystickGetAxisInitialState     :: proc(joystick: ^Joystick, axis: c.int, state: ^i16) -> bool ---
+	JoystickGetHat                  :: proc(joystick: ^Joystick, hat: c.int) -> u8 ---
+	JoystickGetBall                 :: proc(joystick: ^Joystick, ball: c.int, dx, dy: ^c.int) -> c.int ---
+	JoystickGetButton               :: proc(joystick: ^Joystick, button: c.int) -> u8 ---
+	JoystickRumble                  :: proc(joystick: ^Joystick, low_frequency_rumble, high_frequency_rumble: u16, duration_ms: u32) -> c.int ---
+	JoystickRumbleTriggers          :: proc(joystick: ^Joystick, left_rumble, right_rumble: u16, duration_ms: u32) -> c.int ---
+	JoystickHasLED                  :: proc(joystick: ^Joystick) -> bool ---
+	JoystickSetLED                  :: proc(joystick: ^Joystick, red, green, blue: u8) -> c.int ---
+	JoystickSendEffect              :: proc(joystick: ^Joystick, data: rawptr, size: c.int) -> c.int ---
+	JoystickClose                   :: proc(joystick: ^Joystick) ---
+	JoystickCurrentPowerLevel       :: proc(joystick: ^Joystick) -> JoystickPowerLevel ---
+}

+ 54 - 0
vendor/sdl2/sdl_keyboard.odin

@@ -0,0 +1,54 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+Keysym :: struct {
+	scancode: Scancode, /**< SDL physical key code - see ::SDL_Scancode for details */
+	sym:      KeyCode,  /**< SDL virtual key code - see ::SDL_KeyCode for details */
+	mod:      Keymod,   /**< current key modifiers */
+	unused:   u32,
+}
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetKeyboardFocus        :: proc() -> ^Window ---
+	GetKeyboardState        :: proc(numkeys: ^c.int) -> [^]u8 ---
+	GetKeyFromScancode      :: proc(scancode: Scancode) -> KeyCode ---
+	GetScancodeFromKey      :: proc(key: KeyCode) -> Scancode ---
+	GetScancodeName         :: proc(scancode: Scancode) -> cstring ---
+	GetScancodeFromName     :: proc(name: cstring) -> Scancode ---
+	GetKeyName              :: proc(key: KeyCode) -> cstring ---
+	GetKeyFromName          :: proc(name: cstring) -> KeyCode ---
+	StartTextInput          :: proc() ---
+	IsTextInputActive       :: proc() -> bool ---
+	StopTextInput           :: proc() ---
+	SetTextInputRect        :: proc(rect: ^Rect) ---
+	HasScreenKeyboardSupport:: proc() -> bool ---
+	IsScreenKeyboardShown   :: proc(window: ^Window) -> bool ---
+}
+
+GetKeyboardStateAsSlice :: proc "c" () -> []u8 {
+	numkeys: c.int;
+	keys := GetKeyboardState(&numkeys);
+	if keys != nil {
+		return keys[:numkeys];
+	}
+	return nil;
+}
+
+GetModState :: #force_inline proc "c" () -> Keymod { return transmute(Keymod)u16(SDL_GetModState()) }
+SetModState :: #force_inline proc "c" (modstate: Keymod) { SDL_SetModState(c.int(transmute(u16)modstate)) }
+
+@(default_calling_convention="c")
+@(private="file")
+foreign lib {
+	SDL_GetModState :: proc() -> c.int ---
+	SDL_SetModState :: proc(modstate: c.int) ---
+}
+

+ 330 - 0
vendor/sdl2/sdl_keycode.odin

@@ -0,0 +1,330 @@
+package sdl2
+
+
+SCANCODE_MASK :: 1<<30;
+SCANCODE_TO_KEYCODE :: #force_inline proc "c" (X: Scancode) -> KeyCode {
+	return KeyCode(i32(X) | SCANCODE_MASK);
+}
+
+KeyCode :: enum i32 {
+	UNKNOWN = 0,
+
+	RETURN = '\r',
+	ESCAPE = '\x1B',
+	BACKSPACE = '\b',
+	TAB = '\t',
+	SPACE = ' ',
+	EXCLAIM = '!',
+	QUOTEDBL = '"',
+	HASH = '#',
+	PERCENT = '%',
+	DOLLAR = '$',
+	AMPERSAND = '&',
+	QUOTE = '\'',
+	LEFTPAREN = '(',
+	RIGHTPAREN = ')',
+	ASTERISK = '*',
+	PLUS = '+',
+	COMMA = ',',
+	MINUS = '-',
+	PERIOD = '.',
+	SLASH = '/',
+	NUM0 = '0',
+	NUM1 = '1',
+	NUM2 = '2',
+	NUM3 = '3',
+	NUM4 = '4',
+	NUM5 = '5',
+	NUM6 = '6',
+	NUM7 = '7',
+	NUM8 = '8',
+	NUM9 = '9',
+	COLON = ':',
+	SEMICOLON = ';',
+	LESS = '<',
+	EQUALS = '=',
+	GREATER = '>',
+	QUESTION = '?',
+	AT = '@',
+
+	/*
+	   Skip uppercase letters
+	 */
+
+	LEFTBRACKET = '[',
+	BACKSLASH = '\\',
+	RIGHTBRACKET = ']',
+	CARET = '^',
+	UNDERSCORE = '_',
+	BACKQUOTE = '`',
+	a = 'a',
+	b = 'b',
+	c = 'c',
+	d = 'd',
+	e = 'e',
+	f = 'f',
+	g = 'g',
+	h = 'h',
+	i = 'i',
+	j = 'j',
+	k = 'k',
+	l = 'l',
+	m = 'm',
+	n = 'n',
+	o = 'o',
+	p = 'p',
+	q = 'q',
+	r = 'r',
+	s = 's',
+	t = 't',
+	u = 'u',
+	v = 'v',
+	w = 'w',
+	x = 'x',
+	y = 'y',
+	z = 'z',
+
+	A = a,
+	B = b,
+	C = c,
+	D = d,
+	E = e,
+	F = f,
+	G = g,
+	H = h,
+	I = i,
+	J = j,
+	K = k,
+	L = l,
+	M = m,
+	N = n,
+	O = o,
+	P = p,
+	Q = q,
+	R = r,
+	S = s,
+	T = t,
+	U = u,
+	V = v,
+	W = w,
+	X = x,
+	Y = y,
+	Z = z,
+
+	CAPSLOCK = auto_cast (Scancode.CAPSLOCK|SCANCODE_MASK),
+
+	F1 = auto_cast (Scancode.F1|SCANCODE_MASK),
+	F2 = auto_cast (Scancode.F2|SCANCODE_MASK),
+	F3 = auto_cast (Scancode.F3|SCANCODE_MASK),
+	F4 = auto_cast (Scancode.F4|SCANCODE_MASK),
+	F5 = auto_cast (Scancode.F5|SCANCODE_MASK),
+	F6 = auto_cast (Scancode.F6|SCANCODE_MASK),
+	F7 = auto_cast (Scancode.F7|SCANCODE_MASK),
+	F8 = auto_cast (Scancode.F8|SCANCODE_MASK),
+	F9 = auto_cast (Scancode.F9|SCANCODE_MASK),
+	F10 = auto_cast (Scancode.F10|SCANCODE_MASK),
+	F11 = auto_cast (Scancode.F11|SCANCODE_MASK),
+	F12 = auto_cast (Scancode.F12|SCANCODE_MASK),
+
+	PRINTSCREEN = auto_cast (Scancode.PRINTSCREEN|SCANCODE_MASK),
+	SCROLLLOCK = auto_cast (Scancode.SCROLLLOCK|SCANCODE_MASK),
+	PAUSE = auto_cast (Scancode.PAUSE|SCANCODE_MASK),
+	INSERT = auto_cast (Scancode.INSERT|SCANCODE_MASK),
+	HOME = auto_cast (Scancode.HOME|SCANCODE_MASK),
+	PAGEUP = auto_cast (Scancode.PAGEUP|SCANCODE_MASK),
+	DELETE = '\x7F',
+	END = auto_cast (Scancode.END|SCANCODE_MASK),
+	PAGEDOWN = auto_cast (Scancode.PAGEDOWN|SCANCODE_MASK),
+	RIGHT = auto_cast (Scancode.RIGHT|SCANCODE_MASK),
+	LEFT = auto_cast (Scancode.LEFT|SCANCODE_MASK),
+	DOWN = auto_cast (Scancode.DOWN|SCANCODE_MASK),
+	UP = auto_cast (Scancode.UP|SCANCODE_MASK),
+
+	NUMLOCKCLEAR = auto_cast (Scancode.NUMLOCKCLEAR|SCANCODE_MASK),
+	KP_DIVIDE = auto_cast (Scancode.KP_DIVIDE|SCANCODE_MASK),
+	KP_MULTIPLY = auto_cast (Scancode.KP_MULTIPLY|SCANCODE_MASK),
+	KP_MINUS = auto_cast (Scancode.KP_MINUS|SCANCODE_MASK),
+	KP_PLUS = auto_cast (Scancode.KP_PLUS|SCANCODE_MASK),
+	KP_ENTER = auto_cast (Scancode.KP_ENTER|SCANCODE_MASK),
+	KP_1 = auto_cast (Scancode.KP_1|SCANCODE_MASK),
+	KP_2 = auto_cast (Scancode.KP_2|SCANCODE_MASK),
+	KP_3 = auto_cast (Scancode.KP_3|SCANCODE_MASK),
+	KP_4 = auto_cast (Scancode.KP_4|SCANCODE_MASK),
+	KP_5 = auto_cast (Scancode.KP_5|SCANCODE_MASK),
+	KP_6 = auto_cast (Scancode.KP_6|SCANCODE_MASK),
+	KP_7 = auto_cast (Scancode.KP_7|SCANCODE_MASK),
+	KP_8 = auto_cast (Scancode.KP_8|SCANCODE_MASK),
+	KP_9 = auto_cast (Scancode.KP_9|SCANCODE_MASK),
+	KP_0 = auto_cast (Scancode.KP_0|SCANCODE_MASK),
+	KP_PERIOD = auto_cast (Scancode.KP_PERIOD|SCANCODE_MASK),
+
+	APPLICATION = auto_cast (Scancode.APPLICATION|SCANCODE_MASK),
+	POWER = auto_cast (Scancode.POWER|SCANCODE_MASK),
+	KP_EQUALS = auto_cast (Scancode.KP_EQUALS|SCANCODE_MASK),
+	F13 = auto_cast (Scancode.F13|SCANCODE_MASK),
+	F14 = auto_cast (Scancode.F14|SCANCODE_MASK),
+	F15 = auto_cast (Scancode.F15|SCANCODE_MASK),
+	F16 = auto_cast (Scancode.F16|SCANCODE_MASK),
+	F17 = auto_cast (Scancode.F17|SCANCODE_MASK),
+	F18 = auto_cast (Scancode.F18|SCANCODE_MASK),
+	F19 = auto_cast (Scancode.F19|SCANCODE_MASK),
+	F20 = auto_cast (Scancode.F20|SCANCODE_MASK),
+	F21 = auto_cast (Scancode.F21|SCANCODE_MASK),
+	F22 = auto_cast (Scancode.F22|SCANCODE_MASK),
+	F23 = auto_cast (Scancode.F23|SCANCODE_MASK),
+	F24 = auto_cast (Scancode.F24|SCANCODE_MASK),
+	EXECUTE = auto_cast (Scancode.EXECUTE|SCANCODE_MASK),
+	HELP = auto_cast (Scancode.HELP|SCANCODE_MASK),
+	MENU = auto_cast (Scancode.MENU|SCANCODE_MASK),
+	SELECT = auto_cast (Scancode.SELECT|SCANCODE_MASK),
+	STOP = auto_cast (Scancode.STOP|SCANCODE_MASK),
+	AGAIN = auto_cast (Scancode.AGAIN|SCANCODE_MASK),
+	UNDO = auto_cast (Scancode.UNDO|SCANCODE_MASK),
+	CUT = auto_cast (Scancode.CUT|SCANCODE_MASK),
+	COPY = auto_cast (Scancode.COPY|SCANCODE_MASK),
+	PASTE = auto_cast (Scancode.PASTE|SCANCODE_MASK),
+	FIND = auto_cast (Scancode.FIND|SCANCODE_MASK),
+	MUTE = auto_cast (Scancode.MUTE|SCANCODE_MASK),
+	VOLUMEUP = auto_cast (Scancode.VOLUMEUP|SCANCODE_MASK),
+	VOLUMEDOWN = auto_cast (Scancode.VOLUMEDOWN|SCANCODE_MASK),
+	KP_COMMA = auto_cast (Scancode.KP_COMMA|SCANCODE_MASK),
+	KP_EQUALSAS400 = auto_cast (Scancode.KP_EQUALSAS400|SCANCODE_MASK),
+
+	ALTERASE = auto_cast (Scancode.ALTERASE|SCANCODE_MASK),
+	SYSREQ = auto_cast (Scancode.SYSREQ|SCANCODE_MASK),
+	CANCEL = auto_cast (Scancode.CANCEL|SCANCODE_MASK),
+	CLEAR = auto_cast (Scancode.CLEAR|SCANCODE_MASK),
+	PRIOR = auto_cast (Scancode.PRIOR|SCANCODE_MASK),
+	RETURN2 = auto_cast (Scancode.RETURN2|SCANCODE_MASK),
+	SEPARATOR = auto_cast (Scancode.SEPARATOR|SCANCODE_MASK),
+	OUT = auto_cast (Scancode.OUT|SCANCODE_MASK),
+	OPER = auto_cast (Scancode.OPER|SCANCODE_MASK),
+	CLEARAGAIN = auto_cast (Scancode.CLEARAGAIN|SCANCODE_MASK),
+	CRSEL = auto_cast (Scancode.CRSEL|SCANCODE_MASK),
+	EXSEL = auto_cast (Scancode.EXSEL|SCANCODE_MASK),
+
+	KP_00 = auto_cast (Scancode.KP_00|SCANCODE_MASK),
+	KP_000 = auto_cast (Scancode.KP_000|SCANCODE_MASK),
+	THOUSANDSSEPARATOR = auto_cast (Scancode.THOUSANDSSEPARATOR|SCANCODE_MASK),
+	DECIMALSEPARATOR = auto_cast (Scancode.DECIMALSEPARATOR|SCANCODE_MASK),
+	CURRENCYUNIT = auto_cast (Scancode.CURRENCYUNIT|SCANCODE_MASK),
+	CURRENCYSUBUNIT = auto_cast (Scancode.CURRENCYSUBUNIT|SCANCODE_MASK),
+	KP_LEFTPAREN = auto_cast (Scancode.KP_LEFTPAREN|SCANCODE_MASK),
+	KP_RIGHTPAREN = auto_cast (Scancode.KP_RIGHTPAREN|SCANCODE_MASK),
+	KP_LEFTBRACE = auto_cast (Scancode.KP_LEFTBRACE|SCANCODE_MASK),
+	KP_RIGHTBRACE = auto_cast (Scancode.KP_RIGHTBRACE|SCANCODE_MASK),
+	KP_TAB = auto_cast (Scancode.KP_TAB|SCANCODE_MASK),
+	KP_BACKSPACE = auto_cast (Scancode.KP_BACKSPACE|SCANCODE_MASK),
+	KP_A = auto_cast (Scancode.KP_A|SCANCODE_MASK),
+	KP_B = auto_cast (Scancode.KP_B|SCANCODE_MASK),
+	KP_C = auto_cast (Scancode.KP_C|SCANCODE_MASK),
+	KP_D = auto_cast (Scancode.KP_D|SCANCODE_MASK),
+	KP_E = auto_cast (Scancode.KP_E|SCANCODE_MASK),
+	KP_F = auto_cast (Scancode.KP_F|SCANCODE_MASK),
+	KP_XOR = auto_cast (Scancode.KP_XOR|SCANCODE_MASK),
+	KP_POWER = auto_cast (Scancode.KP_POWER|SCANCODE_MASK),
+	KP_PERCENT = auto_cast (Scancode.KP_PERCENT|SCANCODE_MASK),
+	KP_LESS = auto_cast (Scancode.KP_LESS|SCANCODE_MASK),
+	KP_GREATER = auto_cast (Scancode.KP_GREATER|SCANCODE_MASK),
+	KP_AMPERSAND = auto_cast (Scancode.KP_AMPERSAND|SCANCODE_MASK),
+	KP_DBLAMPERSAND = auto_cast (Scancode.KP_DBLAMPERSAND|SCANCODE_MASK),
+	KP_VERTICALBAR = auto_cast (Scancode.KP_VERTICALBAR|SCANCODE_MASK),
+	KP_DBLVERTICALBAR = auto_cast (Scancode.KP_DBLVERTICALBAR|SCANCODE_MASK),
+	KP_COLON = auto_cast (Scancode.KP_COLON|SCANCODE_MASK),
+	KP_HASH = auto_cast (Scancode.KP_HASH|SCANCODE_MASK),
+	KP_SPACE = auto_cast (Scancode.KP_SPACE|SCANCODE_MASK),
+	KP_AT = auto_cast (Scancode.KP_AT|SCANCODE_MASK),
+	KP_EXCLAM = auto_cast (Scancode.KP_EXCLAM|SCANCODE_MASK),
+	KP_MEMSTORE = auto_cast (Scancode.KP_MEMSTORE|SCANCODE_MASK),
+	KP_MEMRECALL = auto_cast (Scancode.KP_MEMRECALL|SCANCODE_MASK),
+	KP_MEMCLEAR = auto_cast (Scancode.KP_MEMCLEAR|SCANCODE_MASK),
+	KP_MEMADD = auto_cast (Scancode.KP_MEMADD|SCANCODE_MASK),
+	KP_MEMSUBTRACT = auto_cast (Scancode.KP_MEMSUBTRACT|SCANCODE_MASK),
+	KP_MEMMULTIPLY = auto_cast (Scancode.KP_MEMMULTIPLY|SCANCODE_MASK),
+	KP_MEMDIVIDE = auto_cast (Scancode.KP_MEMDIVIDE|SCANCODE_MASK),
+	KP_PLUSMINUS = auto_cast (Scancode.KP_PLUSMINUS|SCANCODE_MASK),
+	KP_CLEAR = auto_cast (Scancode.KP_CLEAR|SCANCODE_MASK),
+	KP_CLEARENTRY = auto_cast (Scancode.KP_CLEARENTRY|SCANCODE_MASK),
+	KP_BINARY = auto_cast (Scancode.KP_BINARY|SCANCODE_MASK),
+	KP_OCTAL = auto_cast (Scancode.KP_OCTAL|SCANCODE_MASK),
+	KP_DECIMAL = auto_cast (Scancode.KP_DECIMAL|SCANCODE_MASK),
+	KP_HEXADECIMAL = auto_cast (Scancode.KP_HEXADECIMAL|SCANCODE_MASK),
+
+	LCTRL = auto_cast (Scancode.LCTRL|SCANCODE_MASK),
+	LSHIFT = auto_cast (Scancode.LSHIFT|SCANCODE_MASK),
+	LALT = auto_cast (Scancode.LALT|SCANCODE_MASK),
+	LGUI = auto_cast (Scancode.LGUI|SCANCODE_MASK),
+	RCTRL = auto_cast (Scancode.RCTRL|SCANCODE_MASK),
+	RSHIFT = auto_cast (Scancode.RSHIFT|SCANCODE_MASK),
+	RALT = auto_cast (Scancode.RALT|SCANCODE_MASK),
+	RGUI = auto_cast (Scancode.RGUI|SCANCODE_MASK),
+
+	MODE = auto_cast (Scancode.MODE|SCANCODE_MASK),
+
+	AUDIONEXT = auto_cast (Scancode.AUDIONEXT|SCANCODE_MASK),
+	AUDIOPREV = auto_cast (Scancode.AUDIOPREV|SCANCODE_MASK),
+	AUDIOSTOP = auto_cast (Scancode.AUDIOSTOP|SCANCODE_MASK),
+	AUDIOPLAY = auto_cast (Scancode.AUDIOPLAY|SCANCODE_MASK),
+	AUDIOMUTE = auto_cast (Scancode.AUDIOMUTE|SCANCODE_MASK),
+	MEDIASELECT = auto_cast (Scancode.MEDIASELECT|SCANCODE_MASK),
+	WWW = auto_cast (Scancode.WWW|SCANCODE_MASK),
+	MAIL = auto_cast (Scancode.MAIL|SCANCODE_MASK),
+	CALCULATOR = auto_cast (Scancode.CALCULATOR|SCANCODE_MASK),
+	COMPUTER = auto_cast (Scancode.COMPUTER|SCANCODE_MASK),
+	AC_SEARCH = auto_cast (Scancode.AC_SEARCH|SCANCODE_MASK),
+	AC_HOME = auto_cast (Scancode.AC_HOME|SCANCODE_MASK),
+	AC_BACK = auto_cast (Scancode.AC_BACK|SCANCODE_MASK),
+	AC_FORWARD = auto_cast (Scancode.AC_FORWARD|SCANCODE_MASK),
+	AC_STOP = auto_cast (Scancode.AC_STOP|SCANCODE_MASK),
+	AC_REFRESH = auto_cast (Scancode.AC_REFRESH|SCANCODE_MASK),
+	AC_BOOKMARKS = auto_cast (Scancode.AC_BOOKMARKS|SCANCODE_MASK),
+
+	BRIGHTNESSDOWN = auto_cast (Scancode.BRIGHTNESSDOWN|SCANCODE_MASK),
+	BRIGHTNESSUP = auto_cast (Scancode.BRIGHTNESSUP|SCANCODE_MASK),
+	DISPLAYSWITCH = auto_cast (Scancode.DISPLAYSWITCH|SCANCODE_MASK),
+	KBDILLUMTOGGLE = auto_cast (Scancode.KBDILLUMTOGGLE|SCANCODE_MASK),
+	KBDILLUMDOWN = auto_cast (Scancode.KBDILLUMDOWN|SCANCODE_MASK),
+	KBDILLUMUP = auto_cast (Scancode.KBDILLUMUP|SCANCODE_MASK),
+	EJECT = auto_cast (Scancode.EJECT|SCANCODE_MASK),
+	SLEEP = auto_cast (Scancode.SLEEP|SCANCODE_MASK),
+	APP1 = auto_cast (Scancode.APP1|SCANCODE_MASK),
+	APP2 = auto_cast (Scancode.APP2|SCANCODE_MASK),
+
+	AUDIOREWIND = auto_cast (Scancode.AUDIOREWIND|SCANCODE_MASK),
+	AUDIOFASTFORWARD = auto_cast (Scancode.AUDIOFASTFORWARD|SCANCODE_MASK),
+}
+
+KeymodFlag :: enum u16 {
+	LSHIFT   = 0x0,
+	RSHIFT   = 0x1,
+	LCTRL    = 0x6,
+	RCTRL    = 0x7,
+	LALT     = 0x8,
+	RALT     = 0x9,
+	LGUI     = 0xa,
+	RGUI     = 0xb,
+	NUM      = 0xc,
+	CAPS     = 0xd,
+	MODE     = 0xe,
+	RESERVED = 0xf,
+}
+
+Keymod :: distinct bit_set[KeymodFlag; u16];
+
+KMOD_NONE     :: Keymod{};
+KMOD_LSHIFT   :: Keymod{.LSHIFT};
+KMOD_RSHIFT   :: Keymod{.RSHIFT};
+KMOD_LCTRL    :: Keymod{.LCTRL};
+KMOD_RCTRL    :: Keymod{.RCTRL};
+KMOD_LALT     :: Keymod{.LALT};
+KMOD_RALT     :: Keymod{.RALT};
+KMOD_LGUI     :: Keymod{.LGUI};
+KMOD_RGUI     :: Keymod{.RGUI};
+KMOD_NUM      :: Keymod{.NUM};
+KMOD_CAPS     :: Keymod{.CAPS};
+KMOD_MODE     :: Keymod{.MODE};
+KMOD_RESERVED :: Keymod{.RESERVED};
+KMOD_CTRL     :: Keymod{.LCTRL, .RCTRL};
+KMOD_SHIFT    :: Keymod{.LSHIFT, .RSHIFT};
+KMOD_ALT      :: Keymod{.LALT, .RALT};
+KMOD_GUI      :: Keymod{.LGUI, .RGUI};

+ 77 - 0
vendor/sdl2/sdl_log.odin

@@ -0,0 +1,77 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+MAX_LOG_MESSAGE :: 4096;
+
+LogCategory :: enum c.int {
+	APPLICATION,
+	ERROR,
+	ASSERT,
+	SYSTEM,
+	AUDIO,
+	VIDEO,
+	RENDER,
+	INPUT,
+	TEST,
+
+	/* Reserved for future SDL library use */
+	RESERVED1,
+	RESERVED2,
+	RESERVED3,
+	RESERVED4,
+	RESERVED5,
+	RESERVED6,
+	RESERVED7,
+	RESERVED8,
+	RESERVED9,
+	RESERVED10,
+
+	/* Beyond this point is reserved for application use, e.g.
+	enum {
+		MYAPP_CATEGORY_AWESOME1 = SDL_LOG_CATEGORY_CUSTOM,
+		MYAPP_CATEGORY_AWESOME2,
+		MYAPP_CATEGORY_AWESOME3,
+		...
+	};
+	*/
+	CUSTOM,
+}
+
+LogPriority :: enum c.int {
+	DEFAULT = 0, // CUSTOM ONE
+	VERBOSE = 1,
+	DEBUG,
+	INFO,
+	WARN,
+	ERROR,
+	CRITICAL,
+	NUM,
+}
+
+LogOutputFunction :: proc "c" (userdata: rawptr, category: LogCategory, priority: LogPriority, message: cstring);
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	LogSetAllPriority    :: proc(priority: LogPriority) ---
+	LogSetPriority       :: proc(category: c.int, priority: LogPriority) ---
+	LogGetPriority       :: proc(category: c.int) -> LogPriority ---
+	LogResetPriorities   :: proc() ---
+	Log                  :: proc(fmt: cstring, #c_vararg args: ..any) ---
+	LogVerbose           :: proc(category: c.int, fmt: cstring, #c_vararg args: ..any) ---
+	LogDebug             :: proc(category: c.int, fmt: cstring, #c_vararg args: ..any) ---
+	LogInfo              :: proc(category: c.int, fmt: cstring, #c_vararg args: ..any) ---
+	LogWarn              :: proc(category: c.int, fmt: cstring, #c_vararg args: ..any) ---
+	LogError             :: proc(category: c.int, fmt: cstring, #c_vararg args: ..any) ---
+	LogCritical          :: proc(category: c.int, fmt: cstring, #c_vararg args: ..any) ---
+	LogMessage           :: proc(category: c.int, priority: LogPriority, fmt: cstring, #c_vararg args: ..any) ---
+	// LogMessageV          :: proc(category: c.int, priority: LogPriority, fmt: cstring, ap: va_list) ---
+	LogGetOutputFunction :: proc(callback: ^LogOutputFunction, userdata: ^rawptr) ---
+	LogSetOutputFunction :: proc(callback: LogOutputFunction, userdata: rawptr) ---
+}

+ 76 - 0
vendor/sdl2/sdl_messagebox.odin

@@ -0,0 +1,76 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+MessageBoxFlag :: enum u32 {
+	_ = 0,
+	ERROR                 = 4,   /**< error dialog */
+	WARNING               = 5,   /**< warning dialog */
+	INFORMATION           = 6,   /**< informational dialog */
+	BUTTONS_LEFT_TO_RIGHT = 7,   /**< buttons placed left to right */
+	BUTTONS_RIGHT_TO_LEFT = 8,   /**< buttons placed right to left */
+}
+
+
+MessageBoxFlags :: distinct bit_set[MessageBoxFlag; u32];
+
+MESSAGEBOX_ERROR                 :: MessageBoxFlags{.ERROR};
+MESSAGEBOX_WARNING               :: MessageBoxFlags{.WARNING};
+MESSAGEBOX_INFORMATION           :: MessageBoxFlags{.INFORMATION};
+MESSAGEBOX_BUTTONS_LEFT_TO_RIGHT :: MessageBoxFlags{.BUTTONS_LEFT_TO_RIGHT};
+MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT :: MessageBoxFlags{.BUTTONS_RIGHT_TO_LEFT};
+
+MessageBoxButtonFlag :: enum u32 {
+	RETURNKEY_DEFAULT = 0,  /**< Marks the default button when return is hit */
+	ESCAPEKEY_DEFAULT = 1,  /**< Marks the default button when escape is hit */
+}
+MessageBoxButtonFlags :: distinct bit_set[MessageBoxButtonFlag; u32];
+
+MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT :: MessageBoxButtonFlags{.RETURNKEY_DEFAULT};
+MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT :: MessageBoxButtonFlags{.ESCAPEKEY_DEFAULT};
+
+MessageBoxButtonData :: struct {
+	flags:    MessageBoxButtonFlags, /**< ::SDL_MessageBoxButtonFlags */
+	buttonid: c.int,                 /**< User defined button id (value returned via SDL_ShowMessageBox) */
+	text:     cstring,               /**< The UTF-8 button text */
+}
+
+MessageBoxColor :: struct {
+	r, g, b: u8,
+}
+
+MessageBoxColorType :: enum c.int {
+	BACKGROUND,
+	TEXT,
+	BUTTON_BORDER,
+	BUTTON_BACKGROUND,
+	BUTTON_SELECTED,
+}
+
+MessageBoxColorScheme :: struct {
+	colors: [MessageBoxColorType]MessageBoxColor,
+}
+
+MessageBoxData :: struct {
+	flags:  MessageBoxFlags, /**< ::SDL_MessageBoxFlags */
+	window: ^Window,         /**< Parent window, can be NULL */
+	title:   cstring,        /**< UTF-8 title */
+	message: cstring,        /**< UTF-8 message text */
+
+	numbuttons: c.int,
+	buttons:    ^MessageBoxButtonData,
+
+	colorScheme: ^MessageBoxColorScheme,   /**< ::SDL_MessageBoxColorScheme, can be NULL to use system settings */
+}
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	ShowMessageBox       :: proc(messageboxdata: ^MessageBoxData, buttonid: ^c.int) -> c.int ---
+	ShowSimpleMessageBox :: proc(flags: MessageBoxFlags, title: cstring, message: cstring, window: ^Window) -> c.int ---
+}

+ 18 - 0
vendor/sdl2/sdl_metal.odin

@@ -0,0 +1,18 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+MetalView :: distinct rawptr;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	Metal_CreateView      :: proc(window: ^Window) -> MetalView ---
+	Metal_DestroyView     :: proc(view: MetalView) ---
+	Metal_GetLayer        :: proc(view: MetalView) -> rawptr ---
+	Metal_GetDrawableSize :: proc(window: ^Window, w, h: ^c.int) ---
+}

+ 64 - 0
vendor/sdl2/sdl_mouse.odin

@@ -0,0 +1,64 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+Cursor :: struct {};
+
+BUTTON :: #force_inline proc "c" (X: c.int) -> c.int { return 1 << u32(X-1) }
+BUTTON_LEFT     :: 1;
+BUTTON_MIDDLE   :: 2;
+BUTTON_RIGHT    :: 3;
+BUTTON_X1       :: 4;
+BUTTON_X2       :: 5;
+BUTTON_LMASK    :: 1<<(BUTTON_LEFT-1);
+BUTTON_MMASK    :: 1<<(BUTTON_MIDDLE-1);
+BUTTON_RMASK    :: 1<<(BUTTON_RIGHT-1);
+BUTTON_X1MASK   :: 1<<(BUTTON_X1-1);
+BUTTON_X2MASK   :: 1<<(BUTTON_X2-1);
+
+SystemCursor :: enum c.int {
+	ARROW,     /**< Arrow */
+	IBEAM,     /**< I-beam */
+	WAIT,      /**< Wait */
+	CROSSHAIR, /**< Crosshair */
+	WAITARROW, /**< Small wait cursor (or Wait if not available) */
+	SIZENWSE,  /**< Double arrow pointing northwest and southeast */
+	SIZENESW,  /**< Double arrow pointing northeast and southwest */
+	SIZEWE,    /**< Double arrow pointing west and east */
+	SIZENS,    /**< Double arrow pointing north and south */
+	SIZEALL,   /**< Four pointed arrow pointing north, south, east, and west */
+	NO,        /**< Slashed circle or crossbones */
+	HAND,      /**< Hand */
+	NUM_SYSTEM_CURSORS,
+}
+
+SDL_MouseWheelDirection :: enum c.int {
+	NORMAL,    /**< The scroll direction is normal */
+	FLIPPED,   /**< The scroll direction is flipped / natural */
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetMouseFocus         :: proc() -> ^Window ---
+	GetMouseState         :: proc(x, y: ^c.int) -> u32 ---
+	GetGlobalMouseState   :: proc(x, y: ^c.int) -> u32 ---
+	GetRelativeMouseState :: proc(x, y: ^c.int) -> u32 ---
+	WarpMouseInWindow     :: proc(window: ^Window, x, y: c.int) ---
+	WarpMouseGlobal       :: proc(x, y: c.int) -> c.int ---
+	SetRelativeMouseMode  :: proc(enabled: bool) -> c.int ---
+	CaptureMouse          :: proc(enabled: bool) -> c.int ---
+	GetRelativeMouseMode  :: proc() -> bool ---
+	CreateCursor          :: proc(data: [^]u8, mask: [^]u8, w, h, hot_x, hot_y: c.int) -> ^Cursor ---
+	CreateColorCursor     :: proc(surface: ^Surface, hot_x, hot_y: c.int) -> ^Cursor ---
+	CreateSystemCursor    :: proc(id: SystemCursor) -> ^Cursor ---
+	SetCursor             :: proc(cursor: ^Cursor) ---
+	GetCursor             :: proc() -> ^Cursor ---
+	GetDefaultCursor      :: proc() -> ^Cursor ---
+	FreeCursor            :: proc(cursor: ^Cursor) ---
+	ShowCursor            :: proc(toggle: c.int) -> c.int ---
+}

+ 44 - 0
vendor/sdl2/sdl_mutex.odin

@@ -0,0 +1,44 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+MUTEX_TIMEDOUT :: 1;
+MUTEX_MAXWAIT  :: ~u32(0);
+
+mutex :: struct {};
+
+semaphore :: struct {};
+sem :: semaphore;
+
+cond :: struct {};
+
+mutexP :: LockMutex;
+mutexV :: UnlockMutex;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	CreateMutex  :: proc() -> ^mutex ---
+	LockMutex    :: proc(m: ^mutex) -> c.int ---
+	TryLockMutex :: proc(m: ^mutex) -> c.int ---
+	UnlockMutex  :: proc(m: ^mutex) -> c.int ---
+	DestroyMutex :: proc(m: ^mutex) ---
+
+	CreateSemaphore  :: proc(initial_value: u32) -> ^sem ---
+	DestroySemaphore :: proc(s: ^sem) ---
+	SemWait          :: proc(s: ^sem) -> c.int ---
+	SemTryWait       :: proc(s: ^sem) -> c.int ---
+	SemWaitTimeout   :: proc(s: ^sem, ms: u32) -> c.int ---
+	SemValue         :: proc(s: ^sem) -> u32 ---
+
+	CreateCond      :: proc() -> ^cond ---
+	DestroyCond     :: proc(cv: ^cond) ---
+	CondSignal      :: proc(cv: ^cond) -> c.int ---
+	CondBroadcast   :: proc(cv: ^cond) -> c.int ---
+	CondWait        :: proc(cv: ^cond, m: ^mutex) -> c.int ---
+	CondWaitTimeout :: proc(cv: ^cond, m: ^mutex, ms: u32) -> c.int ---
+}

+ 237 - 0
vendor/sdl2/sdl_pixels.odin

@@ -0,0 +1,237 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+ALPHA_OPAQUE      :: 255;
+ALPHA_TRANSPARENT ::   0;
+
+PIXELTYPE_UNKNOWN  ::  0;
+PIXELTYPE_INDEX1   ::  1;
+PIXELTYPE_INDEX4   ::  2;
+PIXELTYPE_INDEX8   ::  3;
+PIXELTYPE_PACKED8  ::  4;
+PIXELTYPE_PACKED16 ::  5;
+PIXELTYPE_PACKED32 ::  6;
+PIXELTYPE_ARRAYU8  ::  7;
+PIXELTYPE_ARRAYU16 ::  8;
+PIXELTYPE_ARRAYU32 ::  9;
+PIXELTYPE_ARRAYF16 :: 10;
+PIXELTYPE_ARRAYF3  :: 11;
+
+BITMAPORDER_NONE :: 0;
+BITMAPORDER_4321 :: 1;
+BITMAPORDER_1234 :: 2;
+
+PACKEDORDER_NONE :: 0;
+PACKEDORDER_XRGB :: 1;
+PACKEDORDER_RGBX :: 2;
+PACKEDORDER_ARGB :: 3;
+PACKEDORDER_RGBA :: 4;
+PACKEDORDER_XBGR :: 5;
+PACKEDORDER_BGRX :: 6;
+PACKEDORDER_ABGR :: 7;
+PACKEDORDER_BGRA :: 8;
+
+/** Array component order, low byte -> high byte. */
+/* !!! FIXME: in 2.1, make these not overlap differently with
+   !!! FIXME:  SDL_PACKEDORDER_*, so we can simplify SDL_ISPIXELFORMAT_ALPHA */
+ARRAYORDER_NONE :: 0;
+ARRAYORDER_RGB  :: 1;
+ARRAYORDER_RGBA :: 2;
+ARRAYORDER_ARGB :: 3;
+ARRAYORDER_BGR  :: 4;
+ARRAYORDER_BGRA :: 5;
+ARRAYORDER_ABG  :: 6;
+
+PACKEDLAYOUT_NONE    :: 0;
+PACKEDLAYOUT_332     :: 1;
+PACKEDLAYOUT_4444    :: 2;
+PACKEDLAYOUT_1555    :: 3;
+PACKEDLAYOUT_5551    :: 4;
+PACKEDLAYOUT_565     :: 5;
+PACKEDLAYOUT_8888    :: 6;
+PACKEDLAYOUT_2101010 :: 7;
+PACKEDLAYOUT_101010  :: 8;
+
+
+
+DEFINE_PIXELFOURCC :: FOURCC;
+
+DEFINE_PIXELFORMAT :: #force_inline proc "c" (type: u8, order: u8, layout, bits, bytes: u8) -> u32 {
+	return (1 << 28) | (u32(type) << 24) | (u32(order) << 20) | (u32(layout) << 16) | (u32(bits) << 8) | (u32(bytes) << 0);
+}
+
+
+// #define SDL_PIXELFLAG(X)    (((X) >> 28) & 0x0F)
+// #define SDL_PIXELTYPE(X)    (((X) >> 24) & 0x0F)
+// #define SDL_PIXELORDER(X)   (((X) >> 20) & 0x0F)
+// #define SDL_PIXELLAYOUT(X)  (((X) >> 16) & 0x0F)
+// #define SDL_BITSPERPIXEL(X) (((X) >> 8) & 0xFF)
+// #define SDL_BYTESPERPIXEL(X) \
+//     (SDL_ISPIXELFORMAT_FOURCC(X) ? \
+//         ((((X) == SDL_PIXELFORMAT_YUY2) || \
+//           ((X) == SDL_PIXELFORMAT_UYVY) || \
+//           ((X) == SDL_PIXELFORMAT_YVYU)) ? 2 : 1) : (((X) >> 0) & 0xFF))
+
+// #define SDL_ISPIXELFORMAT_INDEXED(format)   \
+//     (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+//      ((SDL_PIXELTYPE(format) == PIXELTYPE_INDEX1) || \
+//       (SDL_PIXELTYPE(format) == PIXELTYPE_INDEX4) || \
+//       (SDL_PIXELTYPE(format) == PIXELTYPE_INDEX8)))
+
+// #define SDL_ISPIXELFORMAT_PACKED(format) \
+//     (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+//      ((SDL_PIXELTYPE(format) == PIXELTYPE_PACKED8) || \
+//       (SDL_PIXELTYPE(format) == PIXELTYPE_PACKED16) || \
+//       (SDL_PIXELTYPE(format) == PIXELTYPE_PACKED32)))
+
+// #define SDL_ISPIXELFORMAT_ARRAY(format) \
+//     (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+//      ((SDL_PIXELTYPE(format) == PIXELTYPE_ARRAYU8) || \
+//       (SDL_PIXELTYPE(format) == PIXELTYPE_ARRAYU16) || \
+//       (SDL_PIXELTYPE(format) == PIXELTYPE_ARRAYU32) || \
+//       (SDL_PIXELTYPE(format) == PIXELTYPE_ARRAYF16) || \
+//       (SDL_PIXELTYPE(format) == PIXELTYPE_ARRAYF32)))
+
+// #define SDL_ISPIXELFORMAT_ALPHA(format)   \
+//     ((SDL_ISPIXELFORMAT_PACKED(format) && \
+//      ((SDL_PIXELORDER(format) == SDL_PACKEDORDER_ARGB) || \
+//       (SDL_PIXELORDER(format) == SDL_PACKEDORDER_RGBA) || \
+//       (SDL_PIXELORDER(format) == SDL_PACKEDORDER_ABGR) || \
+//       (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA))) || \
+//     (SDL_ISPIXELFORMAT_ARRAY(format) && \
+//      ((SDL_PIXELORDER(format) == SDL_ARRAYORDER_ARGB) || \
+//       (SDL_PIXELORDER(format) == SDL_ARRAYORDER_RGBA) || \
+//       (SDL_PIXELORDER(format) == SDL_ARRAYORDER_ABGR) || \
+//       (SDL_PIXELORDER(format) == SDL_ARRAYORDER_BGRA))))
+
+// /* The flag is set to 1 because 0x1? is not in the printable ASCII range */
+// #define SDL_ISPIXELFORMAT_FOURCC(format)    \
+//     ((format) && (SDL_PIXELFLAG(format) != 1))
+
+
+PixelFormatEnum :: enum u32 {
+	UNKNOWN = 0,
+	INDEX1LSB   = 1<<28 | PIXELTYPE_INDEX1<<24   | BITMAPORDER_4321<<20 | 0<<16 | 1<<8 | 0<<0,
+	INDEX1MSB   = 1<<28 | PIXELTYPE_INDEX1<<24   | BITMAPORDER_1234<<20 | 0<<16 | 1<<8 | 0<<0,
+	INDEX4LSB   = 1<<28 | PIXELTYPE_INDEX4<<24   | BITMAPORDER_4321<<20 | 0<<16 | 4<<8 | 0<<0,
+	INDEX4MSB   = 1<<28 | PIXELTYPE_INDEX4<<24   | BITMAPORDER_1234<<20 | 0<<16 | 4<<8 | 0<<0,
+	INDEX8      = 1<<28 | PIXELTYPE_INDEX8<<24   | 0<<20                | 0<<16 | 8<<8 | 1<<0,
+	RGB332      = 1<<28 | PIXELTYPE_PACKED8<<24  | PACKEDORDER_XRGB<<20 | PACKEDLAYOUT_332<<16  | 8<<8  | 1<<0,
+	XRGB4444    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_XRGB<<20 | PACKEDLAYOUT_4444<<16 | 12<<8 | 2<<0,
+	RGB444      = XRGB4444,
+	XBGR4444    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_XBGR<<20 | PACKEDLAYOUT_4444<<16 | 12<<8 | 2<<0,
+	BGR444      = XBGR4444,
+	XRGB1555    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_XRGB<<20 | PACKEDLAYOUT_1555<<16 | 15<<8 | 2<<0,
+	RGB555      = XRGB1555,
+	XBGR1555    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_XBGR<<20 | PACKEDLAYOUT_1555<<16 | 15<<8 | 2<<0,
+	BGR555      = XBGR1555,
+	ARGB4444    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_ARGB<<20 | PACKEDLAYOUT_4444<<16 | 16<<8 | 2<<0,
+	RGBA4444    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_RGBA<<20 | PACKEDLAYOUT_4444<<16 | 16<<8 | 2<<0,
+	ABGR4444    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_ABGR<<20 | PACKEDLAYOUT_4444<<16 | 16<<8 | 2<<0,
+	BGRA4444    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_BGRA<<20 | PACKEDLAYOUT_4444<<16 | 16<<8 | 2<<0,
+	ARGB1555    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_ARGB<<20 | PACKEDLAYOUT_1555<<16 | 16<<8 | 2<<0,
+	RGBA5551    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_RGBA<<20 | PACKEDLAYOUT_5551<<16 | 16<<8 | 2<<0,
+	ABGR1555    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_ABGR<<20 | PACKEDLAYOUT_1555<<16 | 16<<8 | 2<<0,
+	BGRA5551    = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_BGRA<<20 | PACKEDLAYOUT_5551<<16 | 16<<8 | 2<<0,
+	RGB565      = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_XRGB<<20 | PACKEDLAYOUT_565<<16  | 16<<8 | 2<<0,
+	BGR565      = 1<<28 | PIXELTYPE_PACKED16<<24 | PACKEDORDER_XBGR<<20 | PACKEDLAYOUT_565<<16  | 16<<8 | 2<<0,
+	RGB24       = 1<<28 | PIXELTYPE_ARRAYU8<<24  | ARRAYORDER_RGB<<20   | 0<<16 | 24<<8 | 3<<0,
+	BGR24       = 1<<28 | PIXELTYPE_ARRAYU8<<24  | ARRAYORDER_BGR<<20   | 0<<16 | 24<<8 | 3<<0,
+	XRGB8888    = 1<<28 | PIXELTYPE_PACKED32<<24 | PACKEDORDER_XRGB<<20 | PACKEDLAYOUT_8888<<16 | 24<<8 | 4<<0,
+	RGB888      = XRGB8888,
+	RGBX8888    = 1<<28 | PIXELTYPE_PACKED32<<24 | PACKEDORDER_RGBX<<20 | PACKEDLAYOUT_8888<<16 | 24<<8 | 4<<0,
+	XBGR8888    = 1<<28 | PIXELTYPE_PACKED32<<24 | PACKEDORDER_XBGR<<20 | PACKEDLAYOUT_8888<<16 | 24<<8 | 4<<0,
+	BGR888      = XBGR8888,
+	BGRX8888    = 1<<28 | PIXELTYPE_PACKED32<<24 | PACKEDORDER_BGRX<<20 | PACKEDLAYOUT_8888<<16 | 24<<8 | 4<<0,
+	ARGB8888    = 1<<28 | PIXELTYPE_PACKED32<<24 | PACKEDORDER_ARGB<<20 | PACKEDLAYOUT_8888<<16 | 32<<8 | 4<<0,
+	RGBA8888    = 1<<28 | PIXELTYPE_PACKED32<<24 | PACKEDORDER_RGBA<<20 | PACKEDLAYOUT_8888<<16 | 32<<8 | 4<<0,
+	ABGR8888    = 1<<28 | PIXELTYPE_PACKED32<<24 | PACKEDORDER_ABGR<<20 | PACKEDLAYOUT_8888<<16 | 32<<8 | 4<<0,
+	BGRA8888    = 1<<28 | PIXELTYPE_PACKED32<<24 | PACKEDORDER_BGRA<<20 | PACKEDLAYOUT_8888<<16 | 32<<8 | 4<<0,
+	ARGB2101010 = 1<<28 | PIXELTYPE_PACKED32<<24 | PACKEDORDER_ARGB<<20 | PACKEDLAYOUT_2101010<<16 | 32<<8 | 4<<0,
+
+	/* Aliases for RGBA byte arrays of color data, for the current platform */
+	RGBA32 = RGBA8888 when ODIN_ENDIAN == "big" else ABGR8888,
+	ARGB32 = ARGB8888 when ODIN_ENDIAN == "big" else BGRA8888,
+	BGRA32 = BGRA8888 when ODIN_ENDIAN == "big" else ARGB8888,
+	ABGR32 = ABGR8888 when ODIN_ENDIAN == "big" else RGBA8888,
+
+	YV12 =      /**< Planar mode: Y + V + U  (3 planes) */
+		'Y'<<24 | 'V'<<16 | '1'<<8 | '2'<<0,
+	IYUV =      /**< Planar mode: Y + U + V  (3 planes) */
+		'I'<<24 | 'Y'<<16 | 'U'<<8 | 'V'<<0,
+	YUY2 =      /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */
+		'Y'<<24 | 'U'<<16 | 'Y'<<8 | '2'<<0,
+	UYVY =      /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
+		'U'<<24 | 'Y'<<16 | 'V'<<8 | 'Y'<<0,
+	YVYU =      /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
+		'Y'<<24 | 'V'<<16 | 'Y'<<8 | 'U'<<0,
+	NV12 =      /**< Planar mode: Y + U/V interleaved  (2 planes) */
+		'N'<<24 | 'V'<<16 | '1'<<8 | '2'<<0,
+	NV21 =      /**< Planar mode: Y + V/U interleaved  (2 planes) */
+		'N'<<24 | 'V'<<16 | '2'<<8 | '1'<<0,
+	EXTERNAL_OES =      /**< Android video texture format */
+		'O'<<24 | 'E'<<16 | 'S'<<8 | ' '<<0,
+}
+
+
+Colour :: Color;
+Color :: struct {
+	r: u8,
+	g: u8,
+	b: u8,
+	a: u8,
+}
+
+Palette :: struct {
+	ncolors:  c.int,
+	colors:   ^Color,
+	version:  u32,
+	refcount: c.int,
+}
+
+
+PixelFormat :: struct {
+	format:        u32,
+	palette:       ^Palette,
+	BitsPerPixel:  u8,
+	BytesPerPixel: u8,
+	padding:       [2]u8,
+	Rmask:         u32,
+	Gmask:         u32,
+	Bmask:         u32,
+	Amask:         u32,
+	Rloss:         u8,
+	Gloss:         u8,
+	Bloss:         u8,
+	Aloss:         u8,
+	Rshift:        u8,
+	Gshift:        u8,
+	Bshift:        u8,
+	Ashift:        u8,
+	refcount:      c.int,
+	next:          ^PixelFormat,
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetPixelFormatName     :: proc(format: u32) -> cstring ---
+	PixelFormatEnumToMasks :: proc(format: u32, bpp: ^c.int, Rmask, Gmask, Bmask, Amask: ^u32) -> bool ---
+	MasksToPixelFormatEnum :: proc(bpp: c.int, Rmask, Gmask, Bmask, Amask: u32) -> u32 ---
+	AllocFormat            :: proc(pixel_format: u32) -> ^PixelFormat ---
+	FreeFormat             :: proc(format: ^PixelFormat) ---
+	AllocPalette           :: proc(ncolors: c.int) -> ^Palette ---
+	SetPixelFormatPalette  :: proc(format: ^PixelFormat, palette: ^Palette) -> c.int ---
+	SetPaletteColors       :: proc(palette: ^Palette, colors: [^]Color, firstcolor, ncolors: c.int) -> c.int ---
+	FreePalette            :: proc(palette: ^Palette) ---
+	MapRGB                 :: proc(format: ^PixelFormat, r, g, b: u8) -> u32 ---
+	MapRGBA                :: proc(format: ^PixelFormat, r, g, b, a: u8) -> u32 ---
+	GetRGB                 :: proc(pixel: u32, format: ^PixelFormat, r, g, b: ^u8) ---
+	GetRGBA                :: proc(pixel: u32, format: ^PixelFormat, r, g, b, a: ^u8) ---
+	CalculateGammaRamp     :: proc(gamma: f32, ramp: ^[256]u16) ---
+}

+ 50 - 0
vendor/sdl2/sdl_rect.odin

@@ -0,0 +1,50 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+Point :: struct {
+	x: c.int,
+	y: c.int,
+}
+
+FPoint :: struct {
+	x: f32,
+	y: f32,
+}
+
+
+Rect :: struct {
+	x, y: c.int,
+	w, h: c.int,
+}
+
+FRect :: struct {
+	x, y: f32,
+	w, h: f32,
+}
+
+PointInRect :: proc(p, r: ^Rect) -> bool {
+	return bool((p.x >= r.x) && (p.x < (r.x + r.w)) && (p.y >= r.y) && (p.y < (r.y + r.h)));
+}
+
+RectEmpty :: proc(r: ^Rect) -> bool {
+	return bool(r == nil|| r.w <= 0 || r.h <= 0);
+}
+
+RectEquals :: proc(a, b: ^Rect) -> bool {
+	return a != nil && b != nil && a^ == b^;
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	HasIntersection      :: proc(A, B: ^Rect) -> bool ---
+	IntersectRect        :: proc(A, B: ^Rect, result: ^Rect) -> bool ---
+	UnionRect            :: proc(A, B: ^Rect, result: ^Rect) ---
+	EnclosePoints        :: proc(points: [^]Point, count: c.int, clip: ^Rect, result: ^Rect) -> bool ---
+	IntersectRectAndLine :: proc(rect: ^Rect, X1, Y1, X2, Y2: ^c.int) -> bool ---
+}

+ 143 - 0
vendor/sdl2/sdl_render.odin

@@ -0,0 +1,143 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+RendererFlag :: enum u32 {
+	SOFTWARE      = 0, /**< The renderer is a software fallback */
+	ACCELERATED   = 1, /**< The renderer uses hardware acceleration */
+	PRESENTVSYNC  = 2, /**< Present is synchronized with the refresh rate */
+	TARGETTEXTURE = 3, /**< The renderer supports rendering to texture */
+}
+
+RendererFlags :: distinct bit_set[RendererFlag; u32];
+
+RENDERER_SOFTWARE      :: RendererFlags{.SOFTWARE};
+RENDERER_ACCELERATED   :: RendererFlags{.ACCELERATED};
+RENDERER_PRESENTVSYNC  :: RendererFlags{.PRESENTVSYNC};
+RENDERER_TARGETTEXTURE :: RendererFlags{.TARGETTEXTURE};
+
+RendererInfo :: struct {
+	name:                cstring,       /**< The name of the renderer */
+	flags:               RendererFlags, /**< Supported ::SDL_RendererFlags */
+	num_texture_formats: u32,           /**< The number of available texture formats */
+	texture_formats:     [16]u32,       /**< The available texture formats */
+	max_texture_width:   c.int,         /**< The maximum texture width */
+	max_texture_height:  c.int,         /**< The maximum texture height */
+}
+
+/**
+ * The scaling mode for a texture.
+ */
+ScaleMode :: enum c.int {
+	Nearest, /**< nearest pixel sampling */
+	Linear,  /**< linear filtering */
+	Best,    /**< anisotropic filtering */
+}
+
+/**
+ * The access pattern allowed for a texture.
+ */
+TextureAccess :: enum c.int {
+	STATIC,    /**< Changes rarely, not lockable */
+	STREAMING, /**< Changes frequently, lockable */
+	TARGET,    /**< Texture can be used as a render target */
+}
+
+SDL_TEXTUREMODULATE_NONE  :: 0x00000000; /**< No modulation */
+SDL_TEXTUREMODULATE_COLOR :: 0x00000001; /**< srcC = srcC * color */
+SDL_TEXTUREMODULATE_ALPHA :: 0x00000002; /**< srcA = srcA * alpha */
+
+/**
+ * Flip constants for SDL_RenderCopyEx
+ */
+RendererFlip :: enum c.int {
+	NONE       = 0x00000000,    /**< Do not flip */
+	HORIZONTAL = 0x00000001,    /**< flip horizontally */
+	VERTICAL   = 0x00000002,    /**< flip vertically */
+}
+
+Renderer :: struct {};
+
+Texture :: struct {};
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetNumRenderDrivers          :: proc() -> c.int ---
+	GetRenderDriverInfo          :: proc(index: c.int, info: ^RendererInfo) -> c.int ---
+	CreateWindowAndRenderer      :: proc(width, height: c.int, window_flags: WindowFlags, window: ^^Window, renderer: ^^Renderer) -> c.int ---
+	CreateRenderer               :: proc(window:  ^Window, index: c.int, flags: RendererFlags) -> ^Renderer ---
+	CreateSoftwareRenderer       :: proc(surface:  ^Surface) -> ^Renderer ---
+	GetRenderer                  :: proc(window:   ^Window) -> ^Renderer ---
+	GetRendererInfo              :: proc(renderer: ^Renderer, info: ^RendererInfo) -> c.int ---
+	GetRendererOutputSize        :: proc(renderer: ^Renderer, w, h: ^c.int) -> c.int ---
+	CreateTexture                :: proc(renderer: ^Renderer, format: u32, access: TextureAccess, w, h: c.int) -> ^Texture ---
+	CreateTextureFromSurface     :: proc(renderer: ^Renderer, surface: ^Surface) -> ^Texture ---
+	QueryTexture                 :: proc(texture:  ^Texture, format: ^u32, access, w, h: ^c.int) -> c.int ---
+	SetTextureColorMod           :: proc(texture:  ^Texture, r, g, b: u8) -> c.int ---
+	GetTextureColorMod           :: proc(texture:  ^Texture, r, g, b: ^u8) -> c.int ---
+	SetTextureAlphaMod           :: proc(texture:  ^Texture, alpha: u8) -> c.int ---
+	GetTextureAlphaMod           :: proc(texture:  ^Texture, alpha: ^u8) -> c.int ---
+	SetTextureBlendMode          :: proc(texture:  ^Texture, blendMode: BlendMode) -> c.int ---
+	GetTextureBlendMode          :: proc(texture:  ^Texture, blendMode: ^BlendMode) -> c.int ---
+	SetTextureScaleMode          :: proc(texture:  ^Texture, scaleMode: ScaleMode) -> c.int ---
+	GetTextureScaleMode          :: proc(texture:  ^Texture, scaleMode: ^ScaleMode) -> c.int ---
+	UpdateTexture                :: proc(texture:  ^Texture, rect: ^Rect, pixels: rawptr, pitch: c.int) -> c.int ---
+	UpdateYUVTexture             :: proc(texture:  ^Texture, rect: ^Rect, Yplane: ^u8, Ypitch: c.int, Uplane: ^u8, Upitch: c.int, Vplane: ^u8, Vpitch: c.int) -> c.int ---
+	UpdateNVTexture              :: proc(texture:  ^Texture, rect: ^Rect, Yplane: ^u8, Ypitch: c.int, UVplane: ^u8, UVpitch: c.int) -> c.int ---
+	LockTexture                  :: proc(texture:  ^Texture, rect: ^Rect, pixels: ^rawptr, pitch: ^c.int) -> c.int ---
+	LockTextureToSurface         :: proc(texture:  ^Texture, rect: ^Rect, surface: ^^Surface) -> c.int ---
+	UnlockTexture                :: proc(texture:  ^Texture) ---
+	RenderTargetSupported        :: proc(renderer: ^PixelFormatEnum) -> bool ---
+	SetRenderTarget              :: proc(renderer: ^PixelFormatEnum, texture: ^Texture) -> c.int ---
+	GetRenderTarget              :: proc(renderer: ^PixelFormatEnum) -> ^Texture ---
+	RenderSetLogicalSize         :: proc(renderer: ^Renderer, w, h: c.int) -> c.int ---
+	RenderGetLogicalSize         :: proc(renderer: ^Renderer, w, h: ^c.int) ---
+	RenderSetIntegerScale        :: proc(renderer: ^Renderer, enable: bool) -> c.int ---
+	RenderGetIntegerScale        :: proc(renderer: ^Renderer) -> bool ---
+	RenderSetViewport            :: proc(renderer: ^Renderer, rect: ^Rect) -> c.int ---
+	RenderGetViewport            :: proc(renderer: ^Renderer, rect: ^Rect) ---
+	RenderSetClipRect            :: proc(renderer: ^Renderer, rect: ^Rect) -> c.int ---
+	RenderGetClipRect            :: proc(renderer: ^Renderer, rect: ^Rect) ---
+	RenderIsClipEnabled          :: proc(renderer: ^Renderer) -> bool ---
+	RenderSetScale               :: proc(renderer: ^Renderer, scaleX, scaleY: f32) -> c.int ---
+	RenderGetScale               :: proc(renderer: ^Renderer, scaleX, scaleY: ^f32) ---
+	SetRenderDrawColor           :: proc(renderer: ^Renderer, r, g, b, a: u8) -> c.int ---
+	GetRenderDrawColor           :: proc(renderer: ^Renderer, r, g, b, a: ^u8) -> c.int ---
+	SetRenderDrawBlendMode       :: proc(renderer: ^Renderer, blendMode: BlendMode) -> c.int ---
+	GetRenderDrawBlendMode       :: proc(renderer: ^Renderer, blendMode: ^BlendMode) -> c.int ---
+	RenderClear                  :: proc(renderer: ^Renderer) -> c.int ---
+	RenderDrawPoint              :: proc(renderer: ^Renderer, x, y: c.int) -> c.int ---
+	RenderDrawPoints             :: proc(renderer: ^Renderer, points: [^]Point, count: c.int) -> c.int ---
+	RenderDrawLine               :: proc(renderer: ^Renderer, x1, y1, x2, y2: c.int) -> c.int ---
+	RenderDrawLines              :: proc(renderer: ^Renderer, points: [^]Point, count: c.int) -> c.int ---
+	RenderDrawRect               :: proc(renderer: ^Renderer, rect: ^Rect) -> c.int ---
+	RenderDrawRects              :: proc(renderer: ^Renderer, rect: ^Rect, count: c.int) -> c.int ---
+	RenderFillRect               :: proc(renderer: ^Renderer, rect: ^Rect) -> c.int ---
+	RenderFillRects              :: proc(renderer: ^Renderer, rects: [^]Rect, count: c.int) -> c.int ---
+	RenderCopy                   :: proc(renderer: ^Renderer, texture: ^Texture, srcrect: ^Rect, dstrect: ^Rect) -> c.int ---
+	RenderCopyEx                 :: proc(renderer: ^Renderer, texture: ^Texture, srcrect: ^Rect, dstrect: ^Rect, angle: f64, center: ^Point, flip: RendererFlip) -> c.int ---
+	RenderDrawPointF             :: proc(renderer: ^Renderer, x, y: f32) -> c.int ---
+	RenderDrawPointsF            :: proc(renderer: ^Renderer, points: [^]FPoint, count: c.int) -> c.int ---
+	RenderDrawLineF              :: proc(renderer: ^Renderer, x1, y1, x2, y2: f32) -> c.int ---
+	RenderDrawLinesF             :: proc(renderer: ^Renderer, points: [^]FPoint, count: c.int) -> c.int ---
+	RenderDrawRectF              :: proc(renderer: ^Renderer, rect: ^FRect) -> c.int ---
+	RenderDrawRectsF             :: proc(renderer: ^Renderer, rects: [^]FRect, count: c.int) -> c.int ---
+	RenderFillRectF              :: proc(renderer: ^Renderer, rect: ^FRect) -> c.int ---
+	RenderFillRectsF             :: proc(renderer: ^Renderer, rects: [^]FRect, count: c.int) -> c.int ---
+	RenderCopyF                  :: proc(renderer: ^Renderer, texture: ^Texture, srcrect: ^Rect, dstrect: ^FRect) -> c.int ---
+	RenderCopyExF                :: proc(renderer: ^Renderer, texture: ^Texture, srcrect: ^Rect, dstrect: ^FRect, angle: f64, center: ^FPoint, flip: RendererFlip) -> c.int ---
+	RenderReadPixels             :: proc(renderer: ^Renderer, rect: ^Rect, format: u32, pixels: rawptr, pitch: c.int) -> c.int ---
+	RenderPresent                :: proc(renderer: ^Renderer) ---
+	DestroyTexture               :: proc(texture:  ^Texture) ---
+	DestroyRenderer              :: proc(renderer: ^Renderer) ---
+	RenderFlush                  :: proc(renderer: ^Renderer) -> c.int ---
+	GL_BindTexture               :: proc(texture:  ^Texture, texw, texh: ^f32) -> c.int ---
+	GL_UnbindTexture             :: proc(texture:  ^Texture) -> c.int ---
+	RenderGetMetalLayer          :: proc(renderer: ^Renderer) -> rawptr ---
+	RenderGetMetalCommandEncoder :: proc(renderer: ^Renderer) -> rawptr ---
+}

+ 108 - 0
vendor/sdl2/sdl_rwops.odin

@@ -0,0 +1,108 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+/* RWops Types */
+RWOPS_UNKNOWN   :: 0; /**< Unknown stream type */
+RWOPS_WINFILE   :: 1; /**< Win32 file */
+RWOPS_STDFILE   :: 2; /**< Stdio file */
+RWOPS_JNIFILE   :: 3; /**< Android asset */
+RWOPS_MEMORY    :: 4; /**< Memory stream */
+RWOPS_MEMORY_RO :: 5; /**< Read-Only memory stream */
+RWOPS_VITAFILE  :: 6; /**< Vita file */
+
+
+/**
+ * This is the read/write operation structure -- very basic.
+ */
+RWops :: struct {
+	size:  proc "c" (ctx: ^RWops) -> i64,
+	seek:  proc "c" (ctx: ^RWops, offset: i64, whence: c.int) -> i64,
+	read:  proc "c" (ctx: ^RWops, ptr: rawptr, size: c.size_t, maxnum: c.size_t) -> c.size_t,
+	write: proc "c" (ctx: ^RWops, ptr: rawptr, size: c.size_t, num: c.size_t) -> c.size_t,
+	close: proc "c" (ctx: ^RWops) -> c.int,
+
+	type: u32,
+	hidden: struct #raw_union {
+		androidio: struct {
+			asset: rawptr,
+		},
+		windowsio: struct {
+			append: bool,
+			h: rawptr,
+			buffer: struct {
+				data: rawptr,
+				size: c.size_t,
+				left: c.size_t,
+			},
+		},
+		vitaio: struct {
+			h: c.int,
+			buffer: struct {
+				data: rawptr,
+				size: c.size_t,
+				left: c.size_t,
+			},
+		},
+		stdio: struct {
+			autoclose: bool,
+			fp: rawptr,
+		},
+		mem: struct {
+			base: ^u8,
+			here: ^u8,
+			stop: ^u8,
+		},
+		unknown: struct {
+			data1: rawptr,
+			data2: rawptr,
+		},
+	},
+}
+
+
+SEEK_SET :: 0; /**< Seek from the beginning of data */
+SEEK_CUR :: 1; /**< Seek relative to current read point */
+SEEK_END :: 2; /**< Seek relative to the end of data */
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	RWFromFile     :: proc(file: cstring, mode: cstring) -> ^RWops ---
+	RWFromFP       :: proc(fp: rawptr, autoclose: bool) -> ^RWops ---
+	RWFromMem      :: proc(mem: rawptr, size: c.int) -> ^RWops ---
+	RWFromConstMem :: proc(mem: rawptr, size: c.int) -> ^RWops ---
+
+	AllocRW :: proc() -> ^RWops ---
+	FreeRW  :: proc(area: ^RWops) ---
+
+	RWsize  :: proc(ctx: ^RWops) -> i64 ---
+	RWseek  :: proc(ctx: ^RWops, offset: i64, whence: c.int) -> i64 ---
+	RWtell  :: proc(ctx: ^RWops) -> i64 ---
+	RWread  :: proc(ctx: ^RWops, ptr: rawptr, size: c.size_t, maxnum: c.size_t) -> c.size_t ---
+	RWwrite :: proc(ctx: ^RWops, size: c.size_t, num: c.size_t) -> c.size_t ---
+	RWclose :: proc(ctx: ^RWops) -> c.int ---
+
+	LoadFile_RW :: proc(src: ^RWops, datasize: c.size_t, freesrc: bool) -> rawptr ---
+	LoadFile    :: proc(file: rawptr, datasize: c.size_t) -> rawptr ---
+
+	ReadU8   :: proc(src: ^RWops) -> u8 ---
+	ReadLE16 :: proc(src: ^RWops) -> u16 ---
+	ReadBE16 :: proc(src: ^RWops) -> u16 ---
+	ReadLE32 :: proc(src: ^RWops) -> u32 ---
+	ReadBE32 :: proc(src: ^RWops) -> u32 ---
+	ReadLE64 :: proc(src: ^RWops) -> u64 ---
+	ReadBE64 :: proc(src: ^RWops) -> u64 ---
+
+	WriteU8   :: proc(dst: ^RWops, value: ^u8) -> c.size_t ---
+	WriteLE16 :: proc(dst: ^RWops, value: ^u16) -> c.size_t ---
+	WriteBE16 :: proc(dst: ^RWops, value: ^u16) -> c.size_t ---
+	WriteLE32 :: proc(dst: ^RWops, value: ^u32) -> c.size_t ---
+	WriteBE32 :: proc(dst: ^RWops, value: ^u32) -> c.size_t ---
+	WriteLE64 :: proc(dst: ^RWops, value: ^u64) -> c.size_t ---
+	WriteBE64 :: proc(dst: ^RWops, value: ^u64) -> c.size_t ---
+}

+ 277 - 0
vendor/sdl2/sdl_scancode.odin

@@ -0,0 +1,277 @@
+package sdl2
+
+import "core:c"
+
+Scancode :: enum c.int {
+        UNKNOWN = 0,
+
+        A = 4,
+        B = 5,
+        C = 6,
+        D = 7,
+        E = 8,
+        F = 9,
+        G = 10,
+        H = 11,
+        I = 12,
+        J = 13,
+        K = 14,
+        L = 15,
+        M = 16,
+        N = 17,
+        O = 18,
+        P = 19,
+        Q = 20,
+        R = 21,
+        S = 22,
+        T = 23,
+        U = 24,
+        V = 25,
+        W = 26,
+        X = 27,
+        Y = 28,
+        Z = 29,
+
+        NUM1 = 30,
+        NUM2 = 31,
+        NUM3 = 32,
+        NUM4 = 33,
+        NUM5 = 34,
+        NUM6 = 35,
+        NUM7 = 36,
+        NUM8 = 37,
+        NUM9 = 38,
+        NUM0 = 39,
+
+        RETURN = 40,
+        ESCAPE = 41,
+        BACKSPACE = 42,
+        TAB = 43,
+        SPACE = 44,
+
+        MINUS = 45,
+        EQUALS = 46,
+        LEFTBRACKET = 47,
+        RIGHTBRACKET = 48,
+        BACKSLASH = 49,
+        NONUSHASH = 50,
+        SEMICOLON = 51,
+        APOSTROPHE = 52,
+        GRAVE = 53,
+        COMMA = 54,
+        PERIOD = 55,
+        SLASH = 56,
+
+        CAPSLOCK = 57,
+
+        F1 = 58,
+        F2 = 59,
+        F3 = 60,
+        F4 = 61,
+        F5 = 62,
+        F6 = 63,
+        F7 = 64,
+        F8 = 65,
+        F9 = 66,
+        F10 = 67,
+        F11 = 68,
+        F12 = 69,
+
+        PRINTSCREEN = 70,
+        SCROLLLOCK = 71,
+        PAUSE = 72,
+        INSERT = 73,
+        HOME = 74,
+        PAGEUP = 75,
+        DELETE = 76,
+        END = 77,
+        PAGEDOWN = 78,
+        RIGHT = 79,
+        LEFT = 80,
+        DOWN = 81,
+        UP = 82,
+
+        NUMLOCKCLEAR = 83,
+        KP_DIVIDE = 84,
+        KP_MULTIPLY = 85,
+        KP_MINUS = 86,
+        KP_PLUS = 87,
+        KP_ENTER = 88,
+        KP_1 = 89,
+        KP_2 = 90,
+        KP_3 = 91,
+        KP_4 = 92,
+        KP_5 = 93,
+        KP_6 = 94,
+        KP_7 = 95,
+        KP_8 = 96,
+        KP_9 = 97,
+        KP_0 = 98,
+        KP_PERIOD = 99,
+
+        NONUSBACKSLASH = 100,
+        APPLICATION = 101,
+        POWER = 102,
+        KP_EQUALS = 103,
+        F13 = 104,
+        F14 = 105,
+        F15 = 106,
+        F16 = 107,
+        F17 = 108,
+        F18 = 109,
+        F19 = 110,
+        F20 = 111,
+        F21 = 112,
+        F22 = 113,
+        F23 = 114,
+        F24 = 115,
+        EXECUTE = 116,
+        HELP = 117,
+        MENU = 118,
+        SELECT = 119,
+        STOP = 120,
+        AGAIN = 121,
+        UNDO = 122,
+        CUT = 123,
+        COPY = 124,
+        PASTE = 125,
+        FIND = 126,
+        MUTE = 127,
+        VOLUMEUP = 128,
+        VOLUMEDOWN = 129,
+        /* not sure whether there's a reason to enable these */
+        /*     LOCKINGCAPSLOCK = 130,  */
+        /*     LOCKINGNUMLOCK = 131, */
+        /*     LOCKINGSCROLLLOCK = 132, */
+        KP_COMMA = 133,
+        KP_EQUALSAS400 = 134,
+
+        INTERNATIONAL1 = 135,
+        INTERNATIONAL2 = 136,
+        INTERNATIONAL3 = 137,
+        INTERNATIONAL4 = 138,
+        INTERNATIONAL5 = 139,
+        INTERNATIONAL6 = 140,
+        INTERNATIONAL7 = 141,
+        INTERNATIONAL8 = 142,
+        INTERNATIONAL9 = 143,
+        LANG1 = 144,
+        LANG2 = 145,
+        LANG3 = 146,
+        LANG4 = 147,
+        LANG5 = 148,
+        LANG6 = 149,
+        LANG7 = 150,
+        LANG8 = 151,
+        LANG9 = 152,
+
+        ALTERASE = 153,
+        SYSREQ = 154,
+        CANCEL = 155,
+        CLEAR = 156,
+        PRIOR = 157,
+        RETURN2 = 158,
+        SEPARATOR = 159,
+        OUT = 160,
+        OPER = 161,
+        CLEARAGAIN = 162,
+        CRSEL = 163,
+        EXSEL = 164,
+
+        KP_00 = 176,
+        KP_000 = 177,
+        THOUSANDSSEPARATOR = 178,
+        DECIMALSEPARATOR = 179,
+        CURRENCYUNIT = 180,
+        CURRENCYSUBUNIT = 181,
+        KP_LEFTPAREN = 182,
+        KP_RIGHTPAREN = 183,
+        KP_LEFTBRACE = 184,
+        KP_RIGHTBRACE = 185,
+        KP_TAB = 186,
+        KP_BACKSPACE = 187,
+        KP_A = 188,
+        KP_B = 189,
+        KP_C = 190,
+        KP_D = 191,
+        KP_E = 192,
+        KP_F = 193,
+        KP_XOR = 194,
+        KP_POWER = 195,
+        KP_PERCENT = 196,
+        KP_LESS = 197,
+        KP_GREATER = 198,
+        KP_AMPERSAND = 199,
+        KP_DBLAMPERSAND = 200,
+        KP_VERTICALBAR = 201,
+        KP_DBLVERTICALBAR = 202,
+        KP_COLON = 203,
+        KP_HASH = 204,
+        KP_SPACE = 205,
+        KP_AT = 206,
+        KP_EXCLAM = 207,
+        KP_MEMSTORE = 208,
+        KP_MEMRECALL = 209,
+        KP_MEMCLEAR = 210,
+        KP_MEMADD = 211,
+        KP_MEMSUBTRACT = 212,
+        KP_MEMMULTIPLY = 213,
+        KP_MEMDIVIDE = 214,
+        KP_PLUSMINUS = 215,
+        KP_CLEAR = 216,
+        KP_CLEARENTRY = 217,
+        KP_BINARY = 218,
+        KP_OCTAL = 219,
+        KP_DECIMAL = 220,
+        KP_HEXADECIMAL = 221,
+
+        LCTRL = 224,
+        LSHIFT = 225,
+        LALT = 226,
+        LGUI = 227,
+        RCTRL = 228,
+        RSHIFT = 229,
+        RALT = 230,
+        RGUI = 231,
+
+        MODE = 257,
+
+        AUDIONEXT = 258,
+        AUDIOPREV = 259,
+        AUDIOSTOP = 260,
+        AUDIOPLAY = 261,
+        AUDIOMUTE = 262,
+        MEDIASELECT = 263,
+        WWW = 264,
+        MAIL = 265,
+        CALCULATOR = 266,
+        COMPUTER = 267,
+        AC_SEARCH = 268,
+        AC_HOME = 269,
+        AC_BACK = 270,
+        AC_FORWARD = 271,
+        AC_STOP = 272,
+        AC_REFRESH = 273,
+        AC_BOOKMARKS = 274,
+
+
+        BRIGHTNESSDOWN = 275,
+        BRIGHTNESSUP = 276,
+        DISPLAYSWITCH = 277,
+        KBDILLUMTOGGLE = 278,
+        KBDILLUMDOWN = 279,
+        KBDILLUMUP = 280,
+        EJECT = 281,
+        SLEEP = 282,
+
+        APP1 = 283,
+        APP2 = 284,
+
+        AUDIOREWIND = 285,
+        AUDIOFASTFORWARD = 286,
+
+        NUM_SCANCODES = 512,
+}
+
+NUM_SCANCODES :: 512;
+

+ 163 - 0
vendor/sdl2/sdl_stdinc.odin

@@ -0,0 +1,163 @@
+package sdl2
+
+import "core:c"
+import "core:intrinsics"
+import "core:runtime"
+_, _ :: intrinsics, runtime;
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+bool :: distinct b32;
+#assert(size_of(bool) == size_of(c.int));
+
+FOURCC :: #force_inline proc "c" (A, B, C, D: u8) -> u32 {
+	return u32(A) << 0 | u32(B) << 8 | u32(C) << 16 | u32(D) << 24;
+}
+
+
+stack_alloc :: proc "c" ($T: typeid, #any_int count: int) -> ^T {
+	return (^T)(intrinsics.alloca(size_of(T)*count));
+}
+stack_make :: proc "c" ($T: typeid/[]$E, #any_int count: int) -> T {
+	ptr := (^T)(intrinsics.alloca(size_of(T)*count));
+	return transmute(T)runtime.Raw_Slice{ptr, count};
+}
+stack_free :: proc "c" (ptr: rawptr) {}
+
+
+malloc_func  :: proc "c" (size: c.size_t) -> rawptr;
+calloc_func  :: proc "c" (nmemb, size: c.size_t) -> rawptr;
+realloc_func :: proc "c" (mem: rawptr, size: c.size_t) -> rawptr;
+free_func    :: proc "c" (mem: rawptr);
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	malloc   :: proc(size: c.size_t)              -> rawptr ---
+	calloc   :: proc(nmemb, size: c.size_t)       -> rawptr ---
+	realloc  :: proc(mem: rawptr, size: c.size_t) -> rawptr ---
+	free     :: proc(mem: rawptr) ---
+
+	GetMemoryFunctions :: proc(malloc_func:  ^malloc_func,
+	                           calloc_func:  ^calloc_func,
+	                           realloc_func: ^realloc_func,
+	                           free_func:    ^free_func) ---
+
+	SetMemoryFunctions :: proc(malloc_func:  malloc_func,
+	                           calloc_func:  calloc_func,
+	                           realloc_func: realloc_func,
+	                           free_func:    free_func) -> c.int ---
+
+	GetNumAllocations :: proc() -> c.int ---
+
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	getenv :: proc(name: cstring) -> cstring ---
+	setenv :: proc(name, value: cstring, overwrite: c.int) -> c.int ---
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	isalpha  :: proc(x: rune) -> bool ---
+	isalnum  :: proc(x: rune) -> bool ---
+	isblank  :: proc(x: rune) -> bool ---
+	iscntrl  :: proc(x: rune) -> bool ---
+	isdigit  :: proc(x: rune) -> bool ---
+	isxdigit :: proc(x: rune) -> bool ---
+	ispunct  :: proc(x: rune) -> bool ---
+	isspace  :: proc(x: rune) -> bool ---
+	isupper  :: proc(x: rune) -> bool ---
+	islower  :: proc(x: rune) -> bool ---
+	isprint  :: proc(x: rune) -> bool ---
+	isgraph  :: proc(x: rune) -> bool ---
+	toupper  :: proc(x: rune) -> bool ---
+	tolower  :: proc(x: rune) -> bool ---
+
+	crc32 :: proc(crc: u32, data: rawptr, len: c.size_t) -> u32 ---
+}
+
+
+M_PI :: 3.14159265358979323846264338327950288;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	acos      :: proc(x: f64)           -> f64 ---
+	acosf     :: proc(x: f32)           -> f32 ---
+	asin      :: proc(x: f64)           -> f64 ---
+	asinf     :: proc(x: f32)           -> f32 ---
+	atan      :: proc(x: f64)           -> f64 ---
+	atanf     :: proc(x: f32)           -> f32 ---
+	atan2     :: proc(x, y: f64)        -> f64 ---
+	atan2f    :: proc(x, y: f32)        -> f32 ---
+	ceil      :: proc(x: f64)           -> f64 ---
+	ceilf     :: proc(x: f32)           -> f32 ---
+	copysign  :: proc(x, y: f64)        -> f64 ---
+	copysignf :: proc(x, y: f32)        -> f32 ---
+	cos       :: proc(x: f64)           -> f64 ---
+	cosf      :: proc(x: f32)           -> f32 ---
+	exp       :: proc(x: f64)           -> f64 ---
+	expf      :: proc(x: f32)           -> f32 ---
+	fabs      :: proc(x: f64)           -> f64 ---
+	fabsf     :: proc(x: f32)           -> f32 ---
+	floor     :: proc(x: f64)           -> f64 ---
+	floorf    :: proc(x: f32)           -> f32 ---
+	trunc     :: proc(x: f64)           -> f64 ---
+	truncf    :: proc(x: f32)           -> f32 ---
+	fmod      :: proc(x, y: f64)        -> f64 ---
+	fmodf     :: proc(x, y: f32)        -> f32 ---
+	log       :: proc(x: f64)           -> f64 ---
+	logf      :: proc(x: f32)           -> f32 ---
+	log10     :: proc(x: f64)           -> f64 ---
+	log10f    :: proc(x: f32)           -> f32 ---
+	pow       :: proc(x, y: f64)        -> f64 ---
+	powf      :: proc(x, y: f32)        -> f32 ---
+	round     :: proc(x: f64)           -> f64 ---
+	roundf    :: proc(x: f32)           -> f32 ---
+	lround    :: proc(x: f64)           -> c.long ---
+	lroundf   :: proc(x: f32)           -> c.long ---
+	scalbn    :: proc(x: f64, n: c.int) -> f64 ---
+	scalbnf   :: proc(x: f32, n: c.int) -> f32 ---
+	sin       :: proc(x: f64)           -> f64 ---
+	sinf      :: proc(x: f32)           -> f32 ---
+	sqrt      :: proc(x: f64)           -> f64 ---
+	sqrtf     :: proc(x: f32)           -> f32 ---
+	tan       :: proc(x: f64)           -> f64 ---
+	tanf      :: proc(x: f32)           -> f32 ---
+}
+
+/* The SDL implementation of iconv() returns these error codes */
+ICONV_ERROR  :: ~c.size_t(0); // (size_t)-1
+ICONV_E2BIG  :: ~c.size_t(1); // (size_t)-2
+ICONV_EILSEQ :: ~c.size_t(2); // (size_t)-3
+ICONV_EINVAL :: ~c.size_t(3); // (size_t)-4
+
+/* SDL_iconv_* are now always real symbols/types, not macros or inlined. */
+iconv_t :: distinct rawptr;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	iconv_open   :: proc(tocode, fromcode: cstring) -> iconv_t ---
+	iconv_close  :: proc(cd: iconv_t) -> c.int ---
+	iconv        :: proc(cd: iconv_t, inbuf: ^cstring, inbytesleft: ^c.size_t, outbuf: ^[^]u8, outbytesleft: ^c.size_t) -> c.size_t ---
+	iconv_string :: proc(tocode, fromcode, inbuf: cstring, inbytesleft: c.size_t) -> [^]u8 ---
+}
+
+iconv_utf8_locale :: proc "c" (s: string) -> cstring {
+	return cast(cstring)iconv_string("", "UTF-8", cstring(raw_data(s)), len(s)+1);
+}
+
+iconv_utf8_utf16 :: iconv_utf8_ucs2;
+iconv_utf8_ucs2 :: proc "c" (s: string) -> [^]u16 {
+	return cast([^]u16)iconv_string("UCS-2-INTERNAL", "UTF-8", cstring(raw_data(s)), len(s)+1);
+}
+
+#assert(size_of(rune) == size_of(c.int));
+
+iconv_utf8_utf32 :: iconv_utf8_ucs4;
+iconv_utf8_ucs4 :: proc "c" (s: string) -> [^]rune {
+	return cast([^]rune)iconv_string("UCS-4-INTERNAL", "UTF-8", cstring(raw_data(s)), len(s)+1);
+}

+ 111 - 0
vendor/sdl2/sdl_surface.odin

@@ -0,0 +1,111 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+SWSURFACE       :: 0;           /**< Just here for compatibility */
+PREALLOC        :: 0x00000001;  /**< Surface uses preallocated memory */
+RLEACCEL        :: 0x00000002;  /**< Surface is RLE encoded */
+DONTFREE        :: 0x00000004;  /**< Surface is referenced internally */
+SIMD_ALIGNED    :: 0x00000008;  /**< Surface uses aligned memory */
+
+MUSTLOCK :: #force_inline proc "c" (surface: ^Surface) -> bool {
+	return bool(surface.flags & RLEACCEL != 0);
+}
+
+BlitMap :: struct {};
+
+Surface :: struct {
+	flags:  u32,                 /**< Read-only */
+	format: ^PixelFormat,        /**< Read-only */
+	w, h:   c.int,               /**< Read-only */
+	pitch:  c.int,               /**< Read-only */
+	pixels: rawptr,              /**< Read-write */
+
+	/** Application data associated with the surface */
+	userdata: rawptr,            /**< Read-write */
+
+	/** information needed for surfaces requiring locks */
+	locked: c.int,               /**< Read-only */
+
+	/** list of BlitMap that hold a reference to this surface */
+	list_blitmap: rawptr,        /**< Private */
+
+	/** clipping information */
+	clip_rect: Rect,             /**< Read-only */
+
+	/** info for fast blit mapping to other surfaces */
+	blitmap: ^BlitMap,           /**< Private */
+
+	/** Reference count -- used when freeing surface */
+	refcount: c.int,             /**< Read-mostly */
+}
+
+blit :: proc "c" (src: ^Surface, srcrect: ^Rect, dst: ^Surface, dstrect: ^Rect) -> c.int;
+
+
+YUV_CONVERSION_MODE :: enum c.int {
+	JPEG,        /**< Full range JPEG */
+	BT601,       /**< BT.601 (the default) */
+	BT709,       /**< BT.709 */
+	AUTOMATIC,   /**< BT.601 for SD content, BT.709 for HD content */
+}
+
+
+LoadBMP :: #force_inline proc "c" (file: cstring) -> ^Surface {
+	return LoadBMP_RW(RWFromFile(file, "rb"), true);
+}
+
+SaveBMP :: #force_inline proc "c" (surface: ^Surface, file: cstring) -> c.int {
+	return SaveBMP_RW(surface, RWFromFile(file, "wb"), true);
+}
+
+BlitSurface :: UpperBlit;
+BlitScaled  :: UpperBlitScaled;
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	CreateRGBSurface                  :: proc(flags: u32, width, height, depth: c.int, Rmask, Gmask, Bmask, Amask: u32) -> ^Surface ---
+	CreateRGBSurfaceWithFormat        :: proc(flags: u32, width, height, depth: c.int, format: u32) -> ^Surface ---
+	CreateRGBSurfaceFrom              :: proc(pixels: rawptr, width, height, depth, pitch: c.int, Rmask, Gmask, Bmask, Amask: u32) -> ^Surface ---
+	CreateRGBSurfaceWithFormatFrom    :: proc(pixels: rawptr, width, height, depth, pitch: c.int, format: u32) -> ^Surface ---
+	FreeSurface                       :: proc(surface: ^Surface) ---
+	SetSurfacePalette                 :: proc(surface: ^Surface, palette: ^Palette) -> c.int ---
+	LockSurface                       :: proc(surface: ^Surface) -> c.int ---
+	UnlockSurface                     :: proc(surface: ^Surface) ---
+	LoadBMP_RW                        :: proc(src: ^RWops, freesrc: bool) -> ^Surface ---
+	SaveBMP_RW                        :: proc(surface: ^Surface, dst: ^RWops, freedst: bool) -> c.int ---
+	SetSurfaceRLE                     :: proc(surface: ^Surface, flag: c.int) -> c.int ---
+	HasSurfaceRLE                     :: proc(surface: ^Surface) -> bool ---
+	SetColorKey                       :: proc(surface: ^Surface, flag: c.int, key: u32) -> c.int ---
+	HasColorKey                       :: proc(surface: ^Surface) -> bool ---
+	GetColorKey                       :: proc(surface: ^Surface, key: ^u32) -> c.int ---
+	SetSurfaceColorMod                :: proc(surface: ^Surface, r, g, b: u8) -> c.int ---
+	GetSurfaceColorMod                :: proc(surface: ^Surface, r, g, b: ^u8) -> c.int ---
+	SetSurfaceAlphaMod                :: proc(surface: ^Surface, alpha: u8) -> c.int ---
+	GetSurfaceAlphaMod                :: proc(surface: ^Surface, alpha: ^u8) -> c.int ---
+	SetSurfaceBlendMode               :: proc(surface: ^Surface, blendMode: BlendMode) -> c.int ---
+	GetSurfaceBlendMode               :: proc(surface: ^Surface, blendMode: ^BlendMode) -> c.int ---
+	SetClipRect                       :: proc(surface: ^Surface, rect: ^Rect) -> bool ---
+	GetClipRect                       :: proc(surface: ^Surface, rect: ^Rect) ---
+	DuplicateSurface                  :: proc(surface: ^Surface) -> ^Surface ---
+	ConvertSurface                    :: proc(src: ^Surface, fmt: ^PixelFormat, flags: u32) -> ^Surface ---
+	ConvertSurfaceFormat              :: proc(src: ^Surface, pixel_format: u32, flags: u32) -> ^Surface ---
+	ConvertPixels                     :: proc(width, height: c.int, src_format: u32, src: rawptr, src_pitch: c.int, dst_format: u32, dst: rawptr, dst_pitch: c.int) -> c.int ---
+	FillRect                          :: proc(dst: ^Surface, rect: ^Rect, color: u32) -> c.int ---
+	FillRects                         :: proc(dst: ^Surface, rects: [^]Rect, count: c.int, color: u32) -> c.int ---
+	UpperBlit                         :: proc(src: ^Surface, srcrect: ^Rect, dst: ^Surface, dstrect: ^Rect) -> c.int ---
+	LowerBlit                         :: proc(src: ^Surface, srcrect: ^Rect, dst: ^Surface, dstrect: ^Rect) -> c.int ---
+	SoftStretch                       :: proc(src: ^Surface, srcrect: ^Rect, dst: ^Surface, dstrect: ^Rect) -> c.int ---
+	SoftStretchLinear                 :: proc(src: ^Surface, srcrect: ^Rect, dst: ^Surface, dstrect: ^Rect) -> c.int ---
+	UpperBlitScaled                   :: proc(src: ^Surface, srcrect: ^Rect, dst: ^Surface, dstrect: ^Rect) -> c.int ---
+	LowerBlitScaled                   :: proc(src: ^Surface, srcrect: ^Rect, dst: ^Surface, dstrect: ^Rect) -> c.int ---
+	SetYUVConversionMode              :: proc(mode: YUV_CONVERSION_MODE) ---
+	GetYUVConversionMode              :: proc() -> YUV_CONVERSION_MODE ---
+	GetYUVConversionModeForResolution :: proc(width, height: c.int) -> YUV_CONVERSION_MODE ---
+}

+ 125 - 0
vendor/sdl2/sdl_system.odin

@@ -0,0 +1,125 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+// General
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	IsTablet :: proc() -> bool ---
+
+	/* Functions used by iOS application delegates to notify SDL about state changes */
+	OnApplicationWillTerminate                 :: proc() ---
+	OnApplicationDidReceiveMemoryWarning       :: proc() ---
+	OnApplicationWillResignActive              :: proc() ---
+	OnApplicationDidEnterBackground            :: proc() ---
+	OnApplicationWillEnterForeground           :: proc() ---
+	OnApplicationDidBecomeActive               :: proc() ---
+	// iPhoneOS
+	OnApplicationDidChangeStatusBarOrientation :: proc() ---
+}
+
+
+// Windows & WinRT
+
+WindowsMessageHook :: proc "c" (userdata: rawptr, hWnd: rawptr, message: c.uint, wParam: u64, lParam: i64);
+
+IDirect3DDevice9 :: struct {};
+ID3D11Device     :: struct {};
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	SetWindowsMessageHook    :: proc(callback: WindowsMessageHook, userdata: rawptr) ---
+	Direct3D9GetAdapterIndex :: proc(displayIndex: c.int) -> c.int ---
+	RenderGetD3D9Device      :: proc(renderer: ^Renderer) -> ^IDirect3DDevice9 ---
+	RenderGetD3D11Device     :: proc(renderer: ^Renderer) -> ^ID3D11Device ---
+	DXGIGetOutputInfo        :: proc(displayIndex: c.int, adapterIndex: ^c.int, outputIndex: ^c.int) -> bool ---
+}
+
+
+WinRT_Path :: enum c.int {
+	/** \brief The installed app's root directory.
+	Files here are likely to be read-only. */
+	INSTALLED_LOCATION,
+
+	/** \brief The app's local data store.  Files may be written here */
+	LOCAL_FOLDER,
+
+	/** \brief The app's roaming data store.  Unsupported on Windows Phone.
+	Files written here may be copied to other machines via a network
+	connection.
+	*/
+	ROAMING_FOLDER,
+
+	/** \brief The app's temporary data store.  Unsupported on Windows Phone.
+	Files written here may be deleted at any time. */
+	TEMP_FOLDER,
+}
+
+
+WinRT_DeviceFamily :: enum {
+	/** \brief Unknown family  */
+	UNKNOWN,
+
+	/** \brief Desktop family*/
+	DESKTOP,
+
+	/** \brief Mobile family (for example smartphone) */
+	MOBILE,
+
+	/** \brief XBox family */
+	XBOX,
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	WinRTGetFSPathUNICODE :: proc(pathType: WinRT_Path) -> ^u16 ---
+	WinRTGetFSPathUTF8    :: proc(pathType: WinRT_Path) -> cstring ---
+	WinRTGetDeviceFamily  :: proc() -> WinRT_DeviceFamily ---
+}
+
+
+// Linux
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	LinuxSetThreadPriority :: proc(threadID: i64, priority: c.int) -> c.int ---
+}
+
+
+// iOS
+iOSSetAnimationCallback :: iPhoneSetAnimationCallback;
+iOSSetEventPump         :: iPhoneSetEventPump;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	iPhoneSetAnimationCallback :: proc(window: ^Window, interval: c.int, callback: proc "c" (rawptr), callbackParam: rawptr) -> c.int ---
+	iPhoneSetEventPump :: proc(enabled: bool) ---
+}
+
+
+
+// Android
+
+ANDROID_EXTERNAL_STORAGE_READ  :: 0x01;
+ANDROID_EXTERNAL_STORAGE_WRITE :: 0x02;
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	AndroidGetJNIEnv               :: proc() -> rawptr ---
+	AndroidGetActivity             :: proc() -> rawptr ---
+	GetAndroidSDKVersion           :: proc() -> c.int ---
+	IsAndroidTV                    :: proc() -> bool ---
+	IsChromebook                   :: proc() -> bool ---
+	IsDeXMode                      :: proc() -> bool ---
+	AndroidBackButton              :: proc() ---
+	AndroidGetInternalStoragePath  :: proc() -> cstring ---
+	AndroidGetExternalStorageState :: proc() -> c.int ---
+	AndroidGetExternalStoragePath  :: proc() -> cstring ---
+	AndroidRequestPermission       :: proc(permission: cstring) -> bool ---
+	AndroidShowToast               :: proc(message: cstring, duration, gravity, xoffset, yoffset: c.int) -> c.int ---
+}

+ 108 - 0
vendor/sdl2/sdl_syswm.odin

@@ -0,0 +1,108 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+SYSWM_TYPE :: enum c.int {
+	UNKNOWN,
+	WINDOWS,
+	X11,
+	DIRECTFB,
+	COCOA,
+	UIKIT,
+	WAYLAND,
+	MIR,  /* no longer available, left for API/ABI compatibility. Remove in 2.1! */
+	WINRT,
+	ANDROID,
+	VIVANTE,
+	OS2,
+	HAIKU,
+	KMSDRM,
+}
+
+XEvent :: struct {
+	type: c.int,
+	pad: [24]c.long,
+}
+
+SysWMmsg :: struct {
+	version: version,
+	subsystem: SYSWM_TYPE,
+	msg: struct #raw_union {
+		win: struct {
+			hwnd:   rawptr, /**< The window for the message */
+			msg:    u32,    /**< The type of message */
+			wParam: uint,   /**< WORD message parameter */
+			lParam: int,    /**< LONG message parameter */
+		},
+		x11: struct {
+			event: XEvent,
+		},
+		cocoa: struct {
+			dummy: c.int,
+		},
+		uikit: struct {
+			dummy: c.int,
+		},
+		dummy: c.int,
+	},
+}
+
+/**
+ *  The custom window manager information structure.
+ *
+ *  When this structure is returned, it holds information about which
+ *  low level system it is using, and will be one of SYSWM_TYPE.
+ */
+SysWMinfo :: struct {
+	version:   version,
+	subsystem: SYSWM_TYPE,
+	info: struct #raw_union {
+		win: struct {
+			window:    rawptr,
+			hdc:       rawptr,
+			hinstance: rawptr,
+		},
+		winrt: struct {
+			window: rawptr, /**< The WinRT CoreWindow */
+		},
+		x11: struct {
+			display: rawptr,
+			window: uintptr, /**< The X11 window */
+		},
+		cocoa: struct {
+			window: rawptr,                     /**< The Cocoa window */
+		},
+		uikit: struct {
+			window: rawptr,          /**< The UIKit window */
+			framebuffer: u32,        /**< The GL view's Framebuffer Object. It must be bound when rendering to the screen using GL. */
+			colorbuffer: u32,        /**< The GL view's color Renderbuffer Object. It must be bound when SDL_GL_SwapWindow is called. */
+			resolveFramebuffer: u32, /**< The Framebuffer Object which holds the resolve color Renderbuffer, when MSAA is used. */
+		},
+		wl: struct {
+			display:       rawptr, /**< Wayland display */
+			surface:       rawptr, /**< Wayland surface */
+			shell_surface: rawptr, /**< DEPRECATED Wayland shell_surface (window manager handle) */
+			egl_window:    rawptr, /**< Wayland EGL window (native window) */
+			xdg_surface:   rawptr, /**< Wayland xdg surface (window manager handle) */
+		},
+		mir: struct {
+			connection: rawptr,  /**< Mir display server connection */
+			surface:    rawptr,  /**< Mir surface */
+		},
+		android: struct {
+			window:  rawptr,
+			surface: rawptr,
+		},
+		dummy: [64]u8,
+	},
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetWindowWMInfo :: proc(window: ^Window, info: ^SysWMinfo) -> bool ---
+}

+ 38 - 0
vendor/sdl2/sdl_thread.odin

@@ -0,0 +1,38 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+Thread :: struct {};
+
+threadID :: distinct c.ulong;
+TLSID :: distinct c.uint;
+
+ThreadPriority :: enum c.int {
+	LOW,
+	NORMAL,
+	HIGH,
+	TIME_CRITICAL,
+}
+
+ThreadFunction :: proc "c" (data: rawptr) -> c.int;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	CreateThread              :: proc(fn: ThreadFunction, name: cstring, data: rawptr) -> ^Thread ---
+	CreateThreadWithStackSize :: proc(fn: ThreadFunction, name: cstring, stacksize: c.size_t, data: rawptr) -> ^Thread ---
+	GetThreadName             :: proc(thread: ^Thread) -> cstring ---
+	ThreadID                  :: proc() -> threadID ---
+	GetThreadID               :: proc(thread: ^Thread) -> threadID ---
+	SetThreadPriority         :: proc(priority: ThreadPriority) -> c.int ---
+	WaitThread                :: proc(thread: ^Thread, status: ^c.int) ---
+	DetachThread              :: proc(thread: ^Thread) ---
+	TLSCreate                 :: proc() -> TLSID ---
+	TLSGet                    :: proc(id: TLSID) -> rawptr ---
+	TLSSet                    :: proc(id: TLSID, value: rawptr, destructor: proc "c" (rawptr)) -> c.int ---
+	TLSCleanup                :: proc() ---
+}

+ 25 - 0
vendor/sdl2/sdl_timer.odin

@@ -0,0 +1,25 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+TimerCallback :: proc "c" (interval: u32, param: rawptr) -> u32;
+TimerID :: distinct c.int;
+
+TICKS_PASSED :: #force_inline proc "c" (A, B: u32) -> bool {
+	return bool(i32(B) - i32(A) <= 0);
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetTicks                :: proc() -> u32 ---
+	GetPerformanceCounter   :: proc() -> u64 ---
+	GetPerformanceFrequency :: proc() -> u64 ---
+	Delay                   :: proc(ms: u32) ---
+	AddTimer                :: proc(interval: u32, callback: TimerCallback, param: rawptr) -> TimerID ---
+	RemoveTimer             :: proc(id: TimerID) -> bool ---
+}

+ 37 - 0
vendor/sdl2/sdl_touch.odin

@@ -0,0 +1,37 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+TouchID  :: distinct i64;
+FingerID :: distinct i64;
+
+TouchDeviceType :: enum c.int {
+	INVALID = -1,
+	DIRECT,            /* touch screen with window-relative coordinates */
+	INDIRECT_ABSOLUTE, /* trackpad with absolute device coordinates */
+	INDIRECT_RELATIVE, /* trackpad with screen cursor-relative coordinates */
+}
+
+Finger :: struct {
+    id: FingerID,
+    x:        f32,
+    y:        f32,
+    pressure: f32,
+}
+
+TOUCH_MOUSEID  :: ~u32(0);
+MOUSE_TOUCH_ID :: TouchID(-1);
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetNumTouchDevices :: proc() -> c.int ---
+	GetTouchDevice     :: proc(index: c.int) -> TouchID ---
+	GetTouchDeviceType :: proc(touchID: TouchID) -> TouchDeviceType ---
+	GetNumTouchFingers :: proc(touchID: TouchID) -> c.int ---
+	GetTouchFinger     :: proc(touchID: TouchID, index: c.int) -> ^Finger ---
+}

+ 306 - 0
vendor/sdl2/sdl_video.odin

@@ -0,0 +1,306 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+DisplayMode :: struct {
+	format:       u32,    /**< pixel format */
+	w:            c.int,  /**< width, in screen coordinates */
+	h:            c.int,  /**< height, in screen coordinates */
+	refresh_rate: c.int,  /**< refresh rate (or zero for unspecified) */
+	driverdata:   rawptr, /**< driver-specific data, initialize to 0 */
+}
+
+Window :: struct {};
+
+WindowFlag :: enum u32 {
+	FULLSCREEN    = 0,       /**< fullscreen window */
+	OPENGL        = 1,       /**< window usable with OpenGL context */
+	SHOWN         = 2,       /**< window is visible */
+	HIDDEN        = 3,       /**< window is not visible */
+	BORDERLESS    = 4,       /**< no window decoration */
+	RESIZABLE     = 5,       /**< window can be resized */
+	MINIMIZED     = 6,       /**< window is minimized */
+	MAXIMIZED     = 7,       /**< window is maximized */
+	MOUSE_GRABBED = 8,       /**< window has grabbed mouse input */
+	INPUT_FOCUS   = 9,       /**< window has input focus */
+	MOUSE_FOCUS   = 10,      /**< window has mouse focus */
+	_INTERNAL_FULLSCREEN_DESKTOP = 12,
+	FOREIGN       = 11,      /**< window not created by SDL */
+	ALLOW_HIGHDPI = 13,      /**< window should be created in high-DPI mode if supported.
+	                                             On macOS NSHighResolutionCapable must be set true in the
+	                                             application's Info.plist for this to have any effect. */
+	MOUSE_CAPTURE    = 14,   /**< window has mouse captured (unrelated to MOUSE_GRABBED) */
+	ALWAYS_ON_TOP    = 15,   /**< window should always be above others */
+	SKIP_TASKBAR     = 16,   /**< window should not be added to the taskbar */
+	UTILITY          = 17,   /**< window should be treated as a utility window */
+	TOOLTIP          = 18,   /**< window should be treated as a tooltip */
+	POPUP_MENU       = 19,   /**< window should be treated as a popup menu */
+	KEYBOARD_GRABBED = 20,   /**< window has grabbed keyboard input */
+	VULKAN           = 28,   /**< window usable for Vulkan surface */
+	METAL            = 29,   /**< window usable for Metal view */
+
+	INPUT_GRABBED = MOUSE_GRABBED, /**< equivalent to SDL_WINDOW_MOUSE_GRABBED for compatibility */
+}
+WindowFlags :: distinct bit_set[WindowFlag; u32];
+
+
+WINDOW_FULLSCREEN         :: WindowFlags{.FULLSCREEN};
+WINDOW_OPENGL             :: WindowFlags{.OPENGL};
+WINDOW_SHOWN              :: WindowFlags{.SHOWN};
+WINDOW_HIDDEN             :: WindowFlags{.HIDDEN};
+WINDOW_BORDERLESS         :: WindowFlags{.BORDERLESS};
+WINDOW_RESIZABLE          :: WindowFlags{.RESIZABLE};
+WINDOW_MINIMIZED          :: WindowFlags{.MINIMIZED};
+WINDOW_MAXIMIZED          :: WindowFlags{.MAXIMIZED};
+WINDOW_MOUSE_GRABBED      :: WindowFlags{.MOUSE_GRABBED};
+WINDOW_INPUT_FOCUS        :: WindowFlags{.INPUT_FOCUS};
+WINDOW_MOUSE_FOCUS        :: WindowFlags{.MOUSE_FOCUS};
+WINDOW_FULLSCREEN_DESKTOP :: WindowFlags{.FULLSCREEN, ._INTERNAL_FULLSCREEN_DESKTOP};
+WINDOW_FOREIGN            :: WindowFlags{.FOREIGN};
+WINDOW_ALLOW_HIGHDPI      :: WindowFlags{.ALLOW_HIGHDPI};
+WINDOW_MOUSE_CAPTURE      :: WindowFlags{.MOUSE_CAPTURE};
+WINDOW_ALWAYS_ON_TOP      :: WindowFlags{.ALWAYS_ON_TOP};
+WINDOW_SKIP_TASKBAR       :: WindowFlags{.SKIP_TASKBAR};
+WINDOW_UTILITY            :: WindowFlags{.UTILITY};
+WINDOW_TOOLTIP            :: WindowFlags{.TOOLTIP};
+WINDOW_POPUP_MENU         :: WindowFlags{.POPUP_MENU};
+WINDOW_KEYBOARD_GRABBED   :: WindowFlags{.KEYBOARD_GRABBED};
+WINDOW_VULKAN             :: WindowFlags{.VULKAN};
+WINDOW_METAL              :: WindowFlags{.METAL};
+WINDOW_INPUT_GRABBED      :: WindowFlags{.INPUT_GRABBED};
+
+
+WINDOWPOS_UNDEFINED_MASK :: 0x1FFF0000;
+WINDOWPOS_UNDEFINED_DISPLAY :: #force_inline proc "c" (X: c.int) -> c.int { return WINDOWPOS_UNDEFINED_MASK|X }
+WINDOWPOS_UNDEFINED :: WINDOWPOS_UNDEFINED_MASK|0;
+WINDOWPOS_ISUNDEFINED :: #force_inline proc "c" (X: c.int) -> bool {
+	return u32(X)&0xFFFF0000 == WINDOWPOS_UNDEFINED_MASK;
+}
+
+WINDOWPOS_CENTERED_MASK :: 0x2FFF0000;
+WINDOWPOS_CENTERED_DISPLAY :: #force_inline proc "c" (X: c.int) -> c.int { return WINDOWPOS_CENTERED_MASK|X }
+WINDOWPOS_CENTERED :: WINDOWPOS_CENTERED_MASK|0;
+WINDOWPOS_ISCENTERED :: #force_inline proc "c" (X: c.int) -> bool {
+	return u32(X)&0xFFFF0000 == WINDOWPOS_CENTERED_MASK;
+}
+
+
+WindowEventID :: enum u8 {
+	NONE,           /**< Never used */
+	SHOWN,          /**< Window has been shown */
+	HIDDEN,         /**< Window has been hidden */
+	EXPOSED,        /**< Window has been exposed and should be
+	                                 redrawn */
+	MOVED,          /**< Window has been moved to data1, data2
+	                             */
+	RESIZED,        /**< Window has been resized to data1xdata2 */
+	SIZE_CHANGED,   /**< The window size has changed, either as
+	                                 a result of an API call or through the
+	                                 system or user changing the window size. */
+	MINIMIZED,      /**< Window has been minimized */
+	MAXIMIZED,      /**< Window has been maximized */
+	RESTORED,       /**< Window has been restored to normal size
+	                                 and position */
+	ENTER,          /**< Window has gained mouse focus */
+	LEAVE,          /**< Window has lost mouse focus */
+	FOCUS_GAINED,   /**< Window has gained keyboard focus */
+	FOCUS_LOST,     /**< Window has lost keyboard focus */
+	CLOSE,          /**< The window manager requests that the window be closed */
+	TAKE_FOCUS,     /**< Window is being offered a focus (should SetWindowInputFocus() on itself or a subwindow, or ignore) */
+	HIT_TEST,       /**< Window had a hit test that wasn't SDL_HITTEST_NORMAL. */
+}
+
+DisplayEventID :: enum u8 {
+	NONE,          /**< Never used */
+	ORIENTATION,   /**< Display orientation has changed to data1 */
+	CONNECTED,     /**< Display has been added to the system */
+	DISCONNECTED,  /**< Display has been removed from the system */
+}
+
+DisplayOrientation :: enum c.int {
+	UNKNOWN,            /**< The display orientation can't be determined */
+	LANDSCAPE,          /**< The display is in landscape mode, with the right side up, relative to portrait mode */
+	LANDSCAPE_FLIPPED,  /**< The display is in landscape mode, with the left side up, relative to portrait mode */
+	PORTRAIT,           /**< The display is in portrait mode */
+	PORTRAIT_FLIPPED,   /**< The display is in portrait mode, upside down */
+}
+
+FlashOperation :: enum c.int {
+	CANCEL,                   /**< Cancel any window flash state */
+	BRIEFLY,                  /**< Flash the window briefly to get attention */
+	UNTIL_FOCUSED,            /**< Flash the window until it gets focus */
+}
+
+GLContext :: distinct rawptr;
+
+GLattr :: enum c.int {
+	RED_SIZE,
+	GREEN_SIZE,
+	BLUE_SIZE,
+	ALPHA_SIZE,
+	BUFFER_SIZE,
+	DOUBLEBUFFER,
+	DEPTH_SIZE,
+	STENCIL_SIZE,
+	ACCUM_RED_SIZE,
+	ACCUM_GREEN_SIZE,
+	ACCUM_BLUE_SIZE,
+	ACCUM_ALPHA_SIZE,
+	STEREO,
+	MULTISAMPLEBUFFERS,
+	MULTISAMPLESAMPLES,
+	ACCELERATED_VISUAL,
+	RETAINED_BACKING,
+	CONTEXT_MAJOR_VERSION,
+	CONTEXT_MINOR_VERSION,
+	CONTEXT_EGL,
+	CONTEXT_FLAGS,
+	CONTEXT_PROFILE_MASK,
+	SHARE_WITH_CURRENT_CONTEXT,
+	FRAMEBUFFER_SRGB_CAPABLE,
+	CONTEXT_RELEASE_BEHAVIOR,
+	CONTEXT_RESET_NOTIFICATION,
+	CONTEXT_NO_ERROR,
+}
+
+GLprofile :: enum c.int {
+	CORE           = 0x0001,
+	COMPATIBILITY  = 0x0002,
+	ES             = 0x0004, /**< GLX_CONTEXT_ES2_PROFILE_BIT_EXT */
+}
+
+GLcontextFlag :: enum c.int {
+	DEBUG_FLAG              = 0x0001,
+	FORWARD_COMPATIBLE_FLAG = 0x0002,
+	ROBUST_ACCESS_FLAG      = 0x0004,
+	RESET_ISOLATION_FLAG    = 0x0008,
+}
+
+GLcontextReleaseFlag :: enum c.int {
+	NONE   = 0x0000,
+	FLUSH  = 0x0001,
+}
+
+GLContextResetNotification :: enum c.int {
+	NO_NOTIFICATION = 0x0000,
+	LOSE_CONTEXT    = 0x0001,
+}
+
+
+HitTestResult :: enum c.int {
+	NORMAL,  /**< Region is normal. No special properties. */
+	DRAGGABLE,  /**< Region can drag entire window. */
+	RESIZE_TOPLEFT,
+	RESIZE_TOP,
+	RESIZE_TOPRIGHT,
+	RESIZE_RIGHT,
+	RESIZE_BOTTOMRIGHT,
+	RESIZE_BOTTOM,
+	RESIZE_BOTTOMLEFT,
+	RESIZE_LEFT,
+}
+
+HitTest :: proc "c" (win: ^Window, area: ^Point, data: rawptr) -> HitTestResult;
+
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GetNumVideoDrivers       :: proc() -> c.int ---
+	GetVideoDriver           :: proc(index: c.int) -> cstring ---
+	VideoInit                :: proc(driver_name: cstring) -> c.int ---
+	VideoQuit                :: proc() ---
+	GetCurrentVideoDriver    :: proc() -> cstring ---
+	GetNumVideoDisplays      :: proc() -> c.int ---
+	GetDisplayName           :: proc(displayIndex: c.int) -> cstring ---
+	GetDisplayBounds         :: proc(displayIndex: c.int, rect: ^Rect) -> c.int ---
+	GetDisplayUsableBounds   :: proc(displayIndex: c.int, rect: ^Rect) -> c.int ---
+	GetDisplayDPI            :: proc(displayIndex: c.int, ddpi, hdpi, vdpi: ^f32) -> c.int ---
+	GetDisplayOrientation    :: proc(displayIndex: c.int) -> DisplayOrientation ---
+	GetNumDisplayModes       :: proc(displayIndex: c.int) -> c.int ---
+	GetDisplayMode           :: proc(displayIndex: c.int, modeIndex: c.int, mode: ^DisplayMode) -> c.int ---
+	GetDesktopDisplayMode    :: proc(displayIndex: c.int, mode: ^DisplayMode) -> c.int ---
+	GetCurrentDisplayMode    :: proc(displayIndex: c.int, mode: ^DisplayMode) -> c.int ---
+	GetClosestDisplayMode    :: proc(displayIndex: c.int, mode, closest: ^DisplayMode) -> ^DisplayMode ---
+	GetWindowDisplayIndex    :: proc(window: ^Window) -> c.int ---
+	SetWindowDisplayMode     :: proc(window: ^Window, mode: ^DisplayMode) -> c.int ---
+	GetWindowDisplayMode     :: proc(window: ^Window, mode: ^DisplayMode) -> c.int ---
+	GetWindowPixelFormat     :: proc(window: ^Window) -> u32 ---
+	CreateWindow             :: proc(title: cstring, x, y, w, h: c.int, flags: WindowFlags) -> ^Window ---
+	CreateWindowFrom         :: proc(data: rawptr) -> ^Window ---
+	GetWindowID              :: proc(window: ^Window) -> u32 ---
+	GetWindowFromID          :: proc(id: u32) -> ^Window ---
+	GetWindowFlags           :: proc(window: ^Window) -> u32 ---
+	SetWindowTitle           :: proc(window: ^Window,  title: cstring) ---
+	GetWindowTitle           :: proc(window: ^Window) -> cstring ---
+	SetWindowIcon            :: proc(window: ^Window, icon: ^Surface) ---
+	SetWindowData            :: proc(window: ^Window, name: cstring, userdata: rawptr) -> rawptr ---
+	GetWindowData            :: proc(window: ^Window, name: cstring) -> rawptr ---
+	SetWindowPosition        :: proc(window: ^Window, x, y: c.int) ---
+	GetWindowPosition        :: proc(window: ^Window, x, y: ^c.int) ---
+	SetWindowSize            :: proc(window: ^Window, w, h: c.int) ---
+	GetWindowSize            :: proc(window: ^Window, w, h: ^c.int) ---
+	GetWindowBordersSize     :: proc(window: ^Window, top, left, bottom, right: ^c.int) -> c.int ---
+	SetWindowMinimumSize     :: proc(window: ^Window, min_w, min_h: c.int) ---
+	GetWindowMinimumSize     :: proc(window: ^Window, w, h: ^c.int) ---
+	SetWindowMaximumSize     :: proc(window: ^Window, max_w, max_h: c.int) ---
+	GetWindowMaximumSize     :: proc(window: ^Window, w, h: ^c.int) ---
+	SetWindowBordered        :: proc(window: ^Window, bordered:  bool) ---
+	SetWindowResizable       :: proc(window: ^Window, resizable: bool) ---
+	SetWindowAlwaysOnTop     :: proc(window: ^Window, on_top:    bool) ---
+	ShowWindow               :: proc(window: ^Window) ---
+	HideWindow               :: proc(window: ^Window) ---
+	RaiseWindow              :: proc(window: ^Window) ---
+	MaximizeWindow           :: proc(window: ^Window) ---
+	MinimizeWindow           :: proc(window: ^Window) ---
+	RestoreWindow            :: proc(window: ^Window) ---
+	SetWindowFullscreen      :: proc(window: ^Window, flags: WindowFlags) -> c.int ---
+	GetWindowSurface         :: proc(window: ^Window) -> ^Surface ---
+	UpdateWindowSurface      :: proc(window: ^Window) -> c.int ---
+	UpdateWindowSurfaceRects :: proc(window: ^Window, rects: [^]Rect, numrects: c.int) -> c.int ---
+	SetWindowGrab            :: proc(window: ^Window, grabbed: bool) ---
+	SetWindowKeyboardGrab    :: proc(window: ^Window, grabbed: bool) ---
+	SetWindowMouseGrab       :: proc(window: ^Window, grabbed: bool) ---
+	GetWindowGrab            :: proc(window: ^Window) -> bool ---
+	GetWindowKeyboardGrab    :: proc(window: ^Window) -> bool ---
+	GetWindowMouseGrab       :: proc(window: ^Window) -> bool ---
+	GetGrabbedWindow         :: proc() -> ^Window ---
+	SetWindowBrightness      :: proc(window: ^Window, brightness: f32) -> c.int ---
+	GetWindowBrightness      :: proc(window: ^Window) -> f32 ---
+	SetWindowOpacity         :: proc(window: ^Window, opacity: f32) -> c.int ---
+	GetWindowOpacity         :: proc(window: ^Window, out_opacity: ^f32) -> c.int ---
+	SetWindowModalFor        :: proc(modal_window, parent_window: ^Window) -> c.int ---
+	SetWindowInputFocus      :: proc(window: ^Window) -> c.int ---
+	SetWindowGammaRamp       :: proc(window: ^Window, red, green, blue: ^u16) -> c.int ---
+	GetWindowGammaRamp       :: proc(window: ^Window, red, green, blue: ^u16) -> c.int ---
+	SetWindowHitTest         :: proc(window: ^Window, callback: HitTest, callback_data: rawptr) -> c.int ---
+	FlashWindow              :: proc(window: ^Window, operation: FlashOperation) -> c.int ---
+	DestroyWindow            :: proc(window: ^Window) ---
+	IsScreenSaverEnabled     :: proc() -> bool ---
+	EnableScreenSaver        :: proc() ---
+	DisableScreenSaver       :: proc() ---
+}
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	GL_LoadLibrary           :: proc(path: cstring) -> c.int ---
+	GL_GetProcAddress        :: proc(procedure: cstring) -> rawptr ---
+	GL_UnloadLibrary         :: proc() ---
+	GL_ExtensionSupported    :: proc(extension: cstring) -> bool ---
+	GL_ResetAttributes       :: proc() ---
+	GL_SetAttribute          :: proc(attr: GLattr, value: c.int) -> c.int ---
+	GL_GetAttribute          :: proc(attr: GLattr, value: ^c.int) -> c.int ---
+	GL_CreateContext         :: proc(window: ^Window) -> GLContext ---
+	GL_MakeCurrent           :: proc(window: ^Window, ctx: GLContext) -> c.int ---
+	GL_GetCurrentWindow      :: proc() -> ^Window ---
+	GL_GetCurrentContext     :: proc() -> GLContext ---
+	GL_GetDrawableSize       :: proc(window: ^Window, w, h: ^c.int) ---
+	GL_SetSwapInterval       :: proc(interval: c.int) -> c.int ---
+	GL_GetSwapInterval       :: proc() -> c.int ---
+	GL_SwapWindow            :: proc(window: ^Window) ---
+	GL_DeleteContext         :: proc(ctx: GLContext) ---
+}

+ 24 - 0
vendor/sdl2/sdl_vulkan.odin

@@ -0,0 +1,24 @@
+package sdl2
+
+import "core:c"
+
+when ODIN_OS == "windows" do foreign import lib "SDL2.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2"
+
+VkInstance   :: distinct u64;
+VkSurfaceKHR :: distinct u64;
+
+vulkanInstance :: VkInstance;
+vulkanSurface  :: VkSurfaceKHR;
+
+@(default_calling_convention="c", link_prefix="SDL_")
+foreign lib {
+	Vulkan_LoadLibrary              :: proc(path: cstring) -> c.int ---
+	Vulkan_GetVkGetInstanceProcAddr :: proc() -> rawptr ---
+	Vulkan_UnloadLibrary            :: proc() ---
+	Vulkan_GetInstanceExtensions    :: proc(window: ^Window, pCount: ^c.uint, pNames: ^cstring) -> bool ---
+	Vulkan_CreateSurface            :: proc(window: ^Window, instance: VkInstance, surface: ^VkSurfaceKHR) -> bool ---
+	Vulkan_GetDrawableSize          :: proc(window: ^Window, w, h: ^c.int) ---
+}

+ 173 - 0
vendor/sdl2/ttf/LICENSE.freetype.txt

@@ -0,0 +1,173 @@
+The source code to this library used with SDL_ttf can be found here:
+https://hg.libsdl.org/SDL_ttf/file/default/external
+---
+
+                    The FreeType Project LICENSE
+                    ----------------------------
+
+                            2006-Jan-27
+
+                    Copyright 1996-2002, 2006 by
+          David Turner, Robert Wilhelm, and Werner Lemberg
+
+
+
+Introduction
+============
+
+  The FreeType  Project is distributed in  several archive packages;
+  some of them may contain, in addition to the FreeType font engine,
+  various tools and  contributions which rely on, or  relate to, the
+  FreeType Project.
+
+  This  license applies  to all  files found  in such  packages, and
+  which do not  fall under their own explicit  license.  The license
+  affects  thus  the  FreeType   font  engine,  the  test  programs,
+  documentation and makefiles, at the very least.
+
+  This  license   was  inspired  by  the  BSD,   Artistic,  and  IJG
+  (Independent JPEG  Group) licenses, which  all encourage inclusion
+  and  use of  free  software in  commercial  and freeware  products
+  alike.  As a consequence, its main points are that:
+
+    o We don't promise that this software works. However, we will be
+      interested in any kind of bug reports. (`as is' distribution)
+
+    o You can  use this software for whatever you  want, in parts or
+      full form, without having to pay us. (`royalty-free' usage)
+
+    o You may not pretend that  you wrote this software.  If you use
+      it, or  only parts of it,  in a program,  you must acknowledge
+      somewhere  in  your  documentation  that  you  have  used  the
+      FreeType code. (`credits')
+
+  We  specifically  permit  and  encourage  the  inclusion  of  this
+  software, with  or without modifications,  in commercial products.
+  We  disclaim  all warranties  covering  The  FreeType Project  and
+  assume no liability related to The FreeType Project.
+
+
+  Finally,  many  people  asked  us  for  a  preferred  form  for  a
+  credit/disclaimer to use in compliance with this license.  We thus
+  encourage you to use the following text:
+
+   """
+    Portions of this software are copyright © <year> The FreeType
+    Project (www.freetype.org).  All rights reserved.
+   """
+
+  Please replace <year> with the value from the FreeType version you
+  actually use.
+
+
+Legal Terms
+===========
+
+0. Definitions
+--------------
+
+  Throughout this license,  the terms `package', `FreeType Project',
+  and  `FreeType  archive' refer  to  the  set  of files  originally
+  distributed  by the  authors  (David Turner,  Robert Wilhelm,  and
+  Werner Lemberg) as the `FreeType Project', be they named as alpha,
+  beta or final release.
+
+  `You' refers to  the licensee, or person using  the project, where
+  `using' is a generic term including compiling the project's source
+  code as  well as linking it  to form a  `program' or `executable'.
+  This  program is  referred to  as  `a program  using the  FreeType
+  engine'.
+
+  This  license applies  to all  files distributed  in  the original
+  FreeType  Project,   including  all  source   code,  binaries  and
+  documentation,  unless  otherwise  stated   in  the  file  in  its
+  original, unmodified form as  distributed in the original archive.
+  If you are  unsure whether or not a particular  file is covered by
+  this license, you must contact us to verify this.
+
+  The FreeType  Project is copyright (C) 1996-2000  by David Turner,
+  Robert Wilhelm, and Werner Lemberg.  All rights reserved except as
+  specified below.
+
+1. No Warranty
+--------------
+
+  THE FREETYPE PROJECT  IS PROVIDED `AS IS' WITHOUT  WARRANTY OF ANY
+  KIND, EITHER  EXPRESS OR IMPLIED,  INCLUDING, BUT NOT  LIMITED TO,
+  WARRANTIES  OF  MERCHANTABILITY   AND  FITNESS  FOR  A  PARTICULAR
+  PURPOSE.  IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE  FOR ANY DAMAGES CAUSED  BY THE USE OR  THE INABILITY TO
+  USE, OF THE FREETYPE PROJECT.
+
+2. Redistribution
+-----------------
+
+  This  license  grants  a  worldwide, royalty-free,  perpetual  and
+  irrevocable right  and license to use,  execute, perform, compile,
+  display,  copy,   create  derivative  works   of,  distribute  and
+  sublicense the  FreeType Project (in  both source and  object code
+  forms)  and  derivative works  thereof  for  any  purpose; and  to
+  authorize others  to exercise  some or all  of the  rights granted
+  herein, subject to the following conditions:
+
+    o Redistribution of  source code  must retain this  license file
+      (`FTL.TXT') unaltered; any  additions, deletions or changes to
+      the original  files must be clearly  indicated in accompanying
+      documentation.   The  copyright   notices  of  the  unaltered,
+      original  files must  be  preserved in  all  copies of  source
+      files.
+
+    o Redistribution in binary form must provide a  disclaimer  that
+      states  that  the software is based in part of the work of the
+      FreeType Team,  in  the  distribution  documentation.  We also
+      encourage you to put an URL to the FreeType web page  in  your
+      documentation, though this isn't mandatory.
+
+  These conditions  apply to any  software derived from or  based on
+  the FreeType Project,  not just the unmodified files.   If you use
+  our work, you  must acknowledge us.  However, no  fee need be paid
+  to us.
+
+3. Advertising
+--------------
+
+  Neither the  FreeType authors and  contributors nor you  shall use
+  the name of the  other for commercial, advertising, or promotional
+  purposes without specific prior written permission.
+
+  We suggest,  but do not require, that  you use one or  more of the
+  following phrases to refer  to this software in your documentation
+  or advertising  materials: `FreeType Project',  `FreeType Engine',
+  `FreeType library', or `FreeType Distribution'.
+
+  As  you have  not signed  this license,  you are  not  required to
+  accept  it.   However,  as  the FreeType  Project  is  copyrighted
+  material, only  this license, or  another one contracted  with the
+  authors, grants you  the right to use, distribute,  and modify it.
+  Therefore,  by  using,  distributing,  or modifying  the  FreeType
+  Project, you indicate that you understand and accept all the terms
+  of this license.
+
+4. Contacts
+-----------
+
+  There are two mailing lists related to FreeType:
+
+    o [email protected]
+
+      Discusses general use and applications of FreeType, as well as
+      future and  wanted additions to the  library and distribution.
+      If  you are looking  for support,  start in  this list  if you
+      haven't found anything to help you in the documentation.
+
+    o [email protected]
+
+      Discusses bugs,  as well  as engine internals,  design issues,
+      specific licenses, porting, etc.
+
+  Our home page can be found at
+
+    https://www.freetype.org
+
+
+--- end of FTL.TXT ---

+ 31 - 0
vendor/sdl2/ttf/LICENSE.zlib.txt

@@ -0,0 +1,31 @@
+The source code to this library used with SDL_ttf can be found here:
+https://hg.libsdl.org/SDL_image/file/default/external
+---
+
+Copyright notice:
+
+ (C) 1995-2010 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  [email protected]          [email protected]
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign.  The sources are provided for free but without
+warranty of any kind.  The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.

BIN
vendor/sdl2/ttf/SDL2_ttf.dll


BIN
vendor/sdl2/ttf/SDL2_ttf.lib


BIN
vendor/sdl2/ttf/libfreetype-6.dll


+ 166 - 0
vendor/sdl2/ttf/sdl_ttf.odin

@@ -0,0 +1,166 @@
+package sdl2_ttf
+
+import "core:c"
+import SDL ".."
+
+when ODIN_OS == "windows" do foreign import lib "SDL2_ttf.lib"
+when ODIN_OS == "linux"   do foreign import lib "system:SDL2_ttf"
+when ODIN_OS == "darwin"  do foreign import lib "system:SDL2_ttf"
+when ODIN_OS == "freebsd" do foreign import lib "system:SDL2_ttf"
+
+bool :: SDL.bool;
+
+#assert(size_of(rune) == size_of(u32));
+
+MAJOR_VERSION :: 2;
+MINOR_VERSION :: 0;
+PATCHLEVEL    :: 15;
+
+UNICODE_BOM_NATIVE  :: 0xFEFF;
+UNICODE_BOM_SWAPPED :: 0xFFFE;
+
+Font :: struct {};
+
+StyleFlag :: enum c.int {
+	BOLD          = 0,
+	ITALIC        = 1,
+	UNDERLINE     = 2,
+	STRIKETHROUGH = 3,
+}
+
+Style :: distinct bit_set[StyleFlag; c.int];
+
+STYLE_NORMAL        :: Style{};
+STYLE_BOLD          :: Style{.BOLD};
+STYLE_ITALIC        :: Style{.ITALIC};
+STYLE_UNDERLINE     :: Style{.UNDERLINE};
+STYLE_STRIKETHROUGH :: Style{.STRIKETHROUGH};
+
+Hinting :: enum c.int {
+	NORMAL         = 0,
+	LIGHT          = 1,
+	MONO           = 2,
+	NONE           = 3,
+	LIGHT_SUBPIXEL = 4,
+}
+
+HINTING_NORMAL         :: Hinting.NORMAL;
+HINTING_LIGHT          :: Hinting.LIGHT;
+HINTING_MONO           :: Hinting.MONO;
+HINTING_NONE           :: Hinting.NONE;
+HINTING_LIGHT_SUBPIXEL :: Hinting.LIGHT_SUBPIXEL;
+
+/* We'll use SDL for reporting errors */
+SetError :: SDL.SetError;
+GetError :: SDL.GetError;
+
+/* For compatibility with previous versions, here are the old functions */
+RenderText :: #force_inline proc "c" (font: ^Font, text: cstring, fg, bg: SDL.Color) -> ^SDL.Surface {
+	return RenderText_Shaded(font, text, fg, bg);
+}
+RenderUTF8 :: #force_inline proc "c" (font: ^Font, text: cstring, fg, bg: SDL.Color) -> ^SDL.Surface {
+	return RenderUTF8_Shaded(font, text, fg, bg);
+}
+RenderUNICODE :: #force_inline proc "c" (font: ^Font, text: [^]u16, fg, bg: SDL.Color)  -> ^SDL.Surface {
+	return RenderUNICODE_Shaded(font, text, fg, bg);
+}
+
+@(default_calling_convention="c", link_prefix="TTF_")
+foreign lib {
+	Linked_Version :: proc() -> ^SDL.version ---
+
+	Init :: proc() -> c.int ---
+	Quit :: proc() ---
+	WasInit :: proc() -> c.int ---
+
+	OpenFont           :: proc(file: cstring, ptsize: c.int) -> ^Font ---
+	OpenFontIndex      :: proc(file: cstring, ptsize: c.int, index: c.long) -> ^Font ---
+	OpenFontRW         :: proc(src: ^SDL.RWops, freesrc: bool, ptsize: c.int) -> ^Font ---
+	OpenFontIndexRW    :: proc(src: ^SDL.RWops, freesrc: bool, ptsize: c.int, index: c.long) -> ^Font ---
+
+	OpenFontDPI        :: proc(file: cstring, ptsize: c.int, hdpi, vdpi: c.uint) -> ^Font ---
+	OpenFontIndexDPI   :: proc(file: cstring, ptsize: c.int, index: c.long, hdpi, vdpi: c.uint) -> ^Font ---
+	OpenFontDPIRW      :: proc(src: ^SDL.RWops, freesrc: bool, ptsize: c.int, hdpi, vdpi: c.uint) -> ^Font ---
+	OpenFontIndexDPIRW :: proc(src: ^SDL.RWops, freesrc: bool, ptsize: c.int, index: c.long, hdpi, vdpi: c.uint) -> ^Font ---
+
+	SetFontSize    :: proc(font: ^Font, ptsize: c.int) -> c.int ---
+	SetFontSizeDPI :: proc(font: ^Font, ptsize: c.int, hdpi, vdpi: c.uint) -> c.int ---
+
+	GetFontStyle   :: proc(font: ^Font) -> Style ---
+	SetFontStyle   :: proc(font: ^Font, style: Style) ---
+	GetFontOutline :: proc(font: ^Font) -> c.int ---
+	SetFontOutline :: proc(font: ^Font, outline: c.int) ---
+
+	GetFontHinting :: proc(font: ^Font) -> Hinting ---
+	SetFontHinting :: proc(font: ^Font, hinting: Hinting) ---
+
+	FontHeight           :: proc(font: ^Font) -> c.int ---
+	FontAscent           :: proc(font: ^Font) -> c.int ---
+	FontDescent          :: proc(font: ^Font) -> c.int ---
+	FontLineSkip         :: proc(font: ^Font) -> c.int ---
+	GetFontKerning       :: proc(font: ^Font) -> c.int ---
+	SetFontKerning       :: proc(font: ^Font, allowed: bool) ---
+	FontFaces            :: proc(font: ^Font) -> c.long ---
+	FontFaceIsFixedWidth :: proc(font: ^Font) -> c.int ---
+	FontFaceFamilyName   :: proc(font: ^Font) -> cstring ---
+	FontFaceStyleName    :: proc(font: ^Font) -> cstring ---
+
+	GlyphIsProvided   :: proc(font: ^Font, ch: u16) -> c.int ---
+	GlyphIsProvided32 :: proc(font: ^Font, ch: rune) -> c.int ---
+	GlyphMetrics      :: proc(font: ^Font, ch: u16, minx, maxx, miny, maxy: ^c.int, advance: ^c.int) -> c.int ---
+	GlyphMetrics32    :: proc(font: ^Font, ch: rune, minx, maxx, miny, maxy: ^c.int, advance: ^c.int) -> c.int ---
+
+	SizeText    :: proc(font: ^Font, text: cstring, w, h: ^c.int) -> c.int ---
+	SizeUTF8    :: proc(font: ^Font, text: cstring, w, h: ^c.int) -> c.int ---
+	SizeUNICODE :: proc(font: ^Font, text: [^]u16, w, h: ^c.int) -> c.int ---
+
+	MeasureText    :: proc(font: ^Font, text: cstring, measure_width: c.int, extent: ^c.int, count: ^c.int) -> c.int ---
+	MeasureUTF8    :: proc(font: ^Font, text: cstring, measure_width: c.int, extent: ^c.int, count: ^c.int) -> c.int ---
+	MeasureUNICODE :: proc(font: ^Font, text: [^]u16,  measure_width: c.int, extent: ^c.int, count: ^c.int) -> c.int ---
+
+	RenderText_Solid    :: proc(font: ^Font, text: cstring, fg: SDL.Color) -> ^SDL.Surface ---
+	RenderUTF8_Solid    :: proc(font: ^Font, text: cstring, fg: SDL.Color) -> ^SDL.Surface ---
+	RenderUNICODE_Solid :: proc(font: ^Font, text: [^]u16,  fg: SDL.Color) -> ^SDL.Surface ---
+
+	RenderText_Solid_Wrapped    :: proc(font: ^Font, text: cstring, fg: SDL.Color, wrapLength: u32) -> ^SDL.Surface ---
+	RenderUTF8_Solid_Wrapped    :: proc(font: ^Font, text: cstring, fg: SDL.Color, wrapLength: u32) -> ^SDL.Surface ---
+	RenderUNICODE_Solid_Wrapped :: proc(font: ^Font, text: [^]u16,  fg: SDL.Color, wrapLength: u32) -> ^SDL.Surface ---
+
+	RenderGlyph_Solid   :: proc(font: ^Font, ch: u16, fg: SDL.Color) -> ^SDL.Surface ---
+	RenderGlyph32_Solid :: proc(font: ^Font, ch: rune, fg: SDL.Color) -> ^SDL.Surface ---
+
+	RenderText_Shaded    :: proc(font: ^Font, text: cstring, fg, bg: SDL.Color) -> ^SDL.Surface ---
+	RenderUTF8_Shaded    :: proc(font: ^Font, text: cstring, fg, bg: SDL.Color) -> ^SDL.Surface ---
+	RenderUNICODE_Shaded :: proc(font: ^Font, text: [^]u16,  fg, bg: SDL.Color) -> ^SDL.Surface ---
+
+	RenderText_Shaded_Wrapped    :: proc(font: ^Font, text: cstring, fg, bg: SDL.Color, wrapLength: u32) -> ^SDL.Surface ---
+	RenderUTF8_Shaded_Wrapped    :: proc(font: ^Font, text: cstring, fg, bg: SDL.Color, wrapLength: u32) -> ^SDL.Surface ---
+	RenderUNICODE_Shaded_Wrapped :: proc(font: ^Font, text: [^]u16,  fg, bg: SDL.Color, wrapLength: u32) -> ^SDL.Surface ---
+
+	RenderGlyph_Shaded   :: proc(font: ^Font, ch: u16,  fg, bg: SDL.Color) -> ^SDL.Surface ---
+	RenderGlyph32_Shaded :: proc(font: ^Font, ch: rune, fg, bg: SDL.Color) -> ^SDL.Surface ---
+
+	RenderText_Blended    :: proc(font: ^Font, text: cstring, fg: SDL.Color) -> ^SDL.Surface ---
+	RenderUTF8_Blended    :: proc(font: ^Font, text: cstring, fg: SDL.Color) -> ^SDL.Surface ---
+	RenderUNICODE_Blended :: proc(font: ^Font, text: [^]u16,  fg: SDL.Color) -> ^SDL.Surface ---
+
+
+	RenderText_Blended_Wrapped    :: proc(font: ^Font, text: cstring, fg: SDL.Color, wrapLength: u32) -> ^SDL.Surface ---
+	RenderUTF8_Blended_Wrapped    :: proc(font: ^Font, text: cstring, fg: SDL.Color, wrapLength: u32) -> ^SDL.Surface ---
+	RenderUNICODE_Blended_Wrapped :: proc(font: ^Font, text: [^]u16,  fg: SDL.Color, wrapLength: u32) -> ^SDL.Surface ---
+
+	RenderGlyph_Blended   :: proc(font: ^Font, ch: u16, fg: SDL.Color) -> ^SDL.Surface ---
+	RenderGlyph32_Blended :: proc(font: ^Font, ch: rune, fg: SDL.Color) -> ^SDL.Surface ---
+
+
+	SetDirection :: proc(direction: c.int /* hb_direction_t */) -> c.int ---
+	SetScript    :: proc(script:    c.int /* hb_script_t    */) -> c.int ---
+
+	CloseFont :: proc(font: ^Font) ---
+
+	GetFontKerningSizeGlyphs   :: proc(font: ^Font, previous_ch, ch: u16) -> c.int ---
+	GetFontKerningSizeGlyphs32 :: proc(font: ^Font, previous_ch, ch: rune) -> c.int ---
+
+	SetFontSDF :: proc(font: ^Font, on_off: bool) -> c.int ---
+	GetFontSDF :: proc(font: ^Font) -> bool ---
+}

BIN
vendor/sdl2/ttf/zlib1.dll