Explorar el Código

add TextureRect.

Ethosa hace 5 años
padre
commit
04b202d57c

+ 0 - 1
README.md

@@ -17,7 +17,6 @@
 
 # Features
 - Godot-like node system.
-- All operations with changing coordinates use `float` instead of `int`, e.g. ```node.move(17.98278, 0.87127)```
 
 # F.A.Q
 *Q*: Where I can see examples?  

+ 0 - 1
nodesnim.nimble

@@ -8,4 +8,3 @@ srcDir = "src"
 
 [Deps]
 Requires: "nim >= 1.0.0"
-Requires: "sdl2"

+ 5 - 3
src/nodesnim.nim

@@ -12,17 +12,19 @@ import
   nodesnim/core/color,
   nodesnim/core/exceptions,
   nodesnim/core/input,
+  nodesnim/core/image,
 
   nodesnim/nodes/node,
   nodesnim/nodes/scene,
   nodesnim/nodes/canvas,
 
   nodesnim/nodescontrol/control,
-  nodesnim/nodescontrol/color_rect
+  nodesnim/nodescontrol/color_rect,
+  nodesnim/nodescontrol/texture_rect
 
 export
   opengl, glut,
   window, environment,
-  vector2, rect2, enums, anchor, color, exceptions, input,
+  vector2, rect2, enums, anchor, color, exceptions, input, image,
   node, scene, canvas,
-  control, color_rect
+  control, color_rect, texture_rect

+ 27 - 0
src/nodesnim/core/image.nim

@@ -0,0 +1,27 @@
+# author: Ethosa
+import
+  ../thirdparty/opengl,
+  ../thirdparty/sdl2,
+  ../thirdparty/sdl2/image
+
+
+discard image.init()
+
+
+proc load*(file: cstring): Gluint =
+  var
+    surface = image.load(file)
+    textureid: Gluint
+
+  # OpenGL:
+  glGenTextures(1, textureid.addr)
+  glBindTexture(GL_TEXTURE_2D, textureid)
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
+
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB.GLint, surface.w,  surface.h, 0, GL_RGB, GL_UNSIGNED_BYTE, surface.pixels)
+  glBindTexture(GL_TEXTURE_2D, 0)
+  surface.freeSurface()
+  return textureid

+ 1 - 2
src/nodesnim/nodescontrol/control.nim

@@ -66,7 +66,7 @@ method draw*(self: ControlPtr, w, h: GLfloat) =
   if self.pressed:
     self.press(last_event.x, last_event.y)
 
-method getGlobalMousePosition*(self: ControlPtr): Vector2Ref {.base.} =
+method getGlobalMousePosition*(self: ControlPtr): Vector2Ref {.base, inline.} =
   Vector2Ref(x: last_event.x, y: last_event.y)
 
 method handle*(self: ControlPtr, event: InputEvent, mouse_on: var NodePtr) =
@@ -99,4 +99,3 @@ method handle*(self: ControlPtr, event: InputEvent, mouse_on: var NodePtr) =
   if not mouse_pressed and self.pressed:
     self.pressed = false
     self.release(event.x, event.y)
-

+ 62 - 0
src/nodesnim/nodescontrol/texture_rect.nim

@@ -0,0 +1,62 @@
+# author: Ethosa
+import
+  ../thirdparty/opengl,
+
+  ../core/vector2,
+  ../core/rect2,
+  ../core/anchor,
+  ../core/input,
+  ../core/image,
+  ../core/color,
+
+  ../nodes/node,
+  control
+
+
+type
+  TextureRectObj* = object of ControlPtr
+    texture*: Gluint
+    modulate*: ColorRef
+  TextureRectPtr* = ptr TextureRectObj
+
+
+proc TextureRect*(name: string, variable: var TextureRectObj): TextureRectPtr =
+  nodepattern(TextureRectObj)
+  controlpattern()
+  variable.rect_size.x = 40
+  variable.rect_size.y = 40
+  variable.texture = 0
+  variable.modulate = Color(1, 1, 1)
+
+proc TextureRect*(obj: var TextureRectObj): TextureRectPtr {.inline.} =
+  TextureRect("TextureRect", obj)
+
+
+method draw*(self: TextureRectPtr, w, h: GLfloat) =
+  self.calcGlobalPosition()
+  let
+    x = -w/2 + self.global_position.x
+    y = h/2 - self.global_position.y
+
+  if self.texture > 0:
+    glEnable(GL_TEXTURE_2D)
+    glBindTexture(GL_TEXTURE_2D, self.texture)
+
+    glBegin(GL_QUADS)
+    glTexCoord2f(0, 0)
+    glVertex2f(x, y)
+    glTexCoord2f(0, 1)
+    glVertex2f(x, y - self.rect_size.y)
+    glTexCoord2f(1, 1)
+    glVertex2f(x + self.rect_size.x, y - self.rect_size.y)
+    glTexCoord2f(1, 0)
+    glVertex2f(x + self.rect_size.x, y)
+    glEnd()
+    glDisable(GL_TEXTURE_2D)
+
+  # Press
+  if self.pressed:
+    self.press(last_event.x, last_event.y)
+
+method loadTexture*(self: TextureRectPtr, file: cstring) {.base.} =
+  self.texture = load(file)

+ 1853 - 0
src/nodesnim/thirdparty/sdl2.nim

@@ -0,0 +1,1853 @@
+import macros
+
+import strutils
+export strutils.`%`
+
+
+# Add for people running sdl 2.0.0
+{. deadCodeElim: on .}
+
+{.push warning[user]: off}
+when defined(SDL_Static):
+  static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2."
+
+else:
+  when defined(windows):
+    const LibName* = "SDL2.dll"
+  elif defined(macosx):
+    const LibName* = "libSDL2.dylib"
+  elif defined(openbsd):
+    const LibName* = "libSDL2.so.0.6"
+  else:
+    const LibName* = "libSDL2.so"
+
+{.pop.}
+
+include sdl2/private/keycodes
+
+const
+  SDL_TEXTEDITINGEVENT_TEXT_SIZE* = 32
+  SDL_TEXTINPUTEVENT_TEXT_SIZE* = 32
+type
+
+  WindowEventID* {.size: sizeof(byte).} = enum
+    WindowEvent_None = 0, WindowEvent_Shown, WindowEvent_Hidden, WindowEvent_Exposed,
+    WindowEvent_Moved, WindowEvent_Resized, WindowEvent_SizeChanged, WindowEvent_Minimized,
+    WindowEvent_Maximized, WindowEvent_Restored, WindowEvent_Enter, WindowEvent_Leave,
+    WindowEvent_FocusGained, WindowEvent_FocusLost, WindowEvent_Close,
+    WindowEvent_TakeFocus, WindowEvent_HitTest
+
+  EventType* {.size: sizeof(uint32).} = enum
+    QuitEvent = 0x100, AppTerminating, AppLowMemory, AppWillEnterBackground,
+    AppDidEnterBackground, AppWillEnterForeground, AppDidEnterForeground,
+    DisplayEvent = 0x150,
+    WindowEvent = 0x200, SysWMEvent,
+    KeyDown = 0x300, KeyUp, TextEditing, TextInput, KeymapChanged,
+    MouseMotion = 0x400, MouseButtonDown, MouseButtonUp, MouseWheel,
+    JoyAxisMotion = 0x600, JoyBallMotion, JoyHatMotion, JoyButtonDown,
+    JoyButtonUp, JoyDeviceAdded, JoyDeviceRemoved,
+    ControllerAxisMotion = 0x650, ControllerButtonDown, ControllerButtonUp,
+    ControllerDeviceAdded, ControllerDeviceRemoved, ControllerDeviceRemapped,
+    FingerDown = 0x700, FingerUp, FingerMotion,
+    DollarGesture = 0x800, DollarRecord, MultiGesture,
+    ClipboardUpdate = 0x900,
+    DropFile = 0x1000,  DropText, DropBegin, DropComplete,
+    AudioDeviceAdded = 0x1100, AudioDeviceRemoved = 0x1101,
+    SensorUpdate = 0x1200,
+    RenderTargetsReset = 0x2000, RenderDeviceReset,
+    UserEvent = 0x8000, UserEvent1, UserEvent2, UserEvent3, UserEvent4, UserEvent5,
+    LastEvent = 0xFFFF,
+
+
+  Event* = object
+    kind*: EventType
+    padding: array[56-sizeof(EventType), byte]
+
+  QuitEventPtr* = ptr QuitEventObj
+  QuitEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+  WindowEventPtr* = ptr WindowEventObj
+  WindowEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    windowID*: uint32
+    event*: WindowEventID
+    pad*: array[56-13, byte]
+  KeyboardEventPtr* = ptr KeyboardEventObj
+  KeyboardEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    windowID*: uint32
+    state*: uint8
+    repeat*: bool
+    keysym*: KeySym
+    pad*: array[24, byte]
+  TextEditingEventPtr* = ptr TextEditingEventObj
+  TextEditingEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    windowID*: uint32
+    text*: array[SDL_TEXTEDITINGEVENT_TEXT_SIZE, char]
+    start*,length*: int32
+    pad*: array[8, byte]
+  TextInputEventPtr* = ptr TextInputEventObj
+  TextInputEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    windowID*: uint32
+    text*: array[SDL_TEXTINPUTEVENT_TEXT_SIZE,char]
+    pad*: array[24, byte]
+  MouseMotionEventPtr* = ptr MouseMotionEventObj
+  MouseMotionEventObj* =  object
+    kind*: EventType
+    timestamp*,windowID*: uint32
+    which*: uint32
+    state*: uint32
+    x*,y*, xrel*,yrel*: int32
+    pad*: array[20, byte]
+  MouseButtonEventPtr* = ptr MouseButtonEventObj
+  MouseButtonEventObj* = object
+    kind*: EventType
+    timestamp*,windowID*: uint32
+    which*: uint32
+    button*: uint8
+    state*: uint8
+    clicks*: uint8
+    x*,y*: cint
+    pad*: array[28, byte]
+  MouseWheelEventPtr* = ptr MouseWheelEventObj
+  MouseWheelEventObj* = object
+    kind*: EventType
+    timestamp*,windowID*: uint32
+    which*: uint32
+    x*,y*: cint
+    direction*: MouseWheelDirection
+  JoyAxisEventPtr* = ptr JoyAxisEventObj
+  JoyAxisEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    which*: int32
+    axis*: uint8
+    pad1,pad2,pad3: uint8
+    value*: int16
+  JoyBallEventPtr* = ptr JoyBallEventObj
+  JoyBallEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    which*: int32
+    ball*, pad1,pad2,pad3: uint8
+    xrel*,yrel*: int16
+  JoyHatEventPtr* = ptr JoyHatEventObj
+  JoyHatEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    which*: int32
+    hat*,value*: uint8
+  JoyButtonEventPtr* = ptr JoyButtonEventObj
+  JoyButtonEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    which*: int32
+    button*,state*: uint8
+  JoyDeviceEventPtr* = ptr JoyDeviceEventObj
+  JoyDeviceEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    which*: int32
+  ControllerAxisEventPtr* = ptr ControllerAxisEventObj
+  ControllerAxisEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    which*: int32
+    axis*, pad1,pad2,pad3: uint8
+    value*: int16
+  ControllerButtonEventPtr* = ptr ControllerButtonEventObj
+  ControllerButtonEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    which*: int32
+    button*,state*: uint8
+  ControllerDeviceEventPtr* = ptr ControllerDeviceEventObj
+  ControllerDeviceEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    which*: int32
+
+  TouchID* = int64
+  FingerID* = int64
+
+  TouchFingerEventPtr* = ptr TouchFingerEventObj
+  TouchFingerEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    touchID*: TouchID
+    fingerID*: FingerID
+    x*,y*,dx*,dy*,pressure*: cfloat
+    pad*: array[24, byte]
+  MultiGestureEventPtr* = ptr MultiGestureEventObj
+  MultiGestureEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    touchID*: TouchID
+    dTheta*,dDist*,x*,y*: cfloat
+    numFingers*: uint16
+
+  Finger* = object
+    id*: FingerID
+    x*,y*: cfloat
+    pressure*: cfloat
+
+  GestureID = int64
+  DollarGestureEventPtr* = ptr DollarGestureEventObj
+  DollarGestureEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    touchID*: TouchID
+    gestureID*: GestureID
+    numFingers*: uint32
+    error*, x*, y*: float
+  DropEventPtr* = ptr DropEventObj
+  DropEventObj* = object
+    kind*: EventType
+    timestamp*: uint32
+    file*: cstring
+  UserEventPtr* = ptr UserEventObj
+  UserEventObj* = object
+    kind*: EventType
+    timestamp*,windowID*: uint32
+    code*: int32
+    data1*,data2*: pointer
+
+  Eventaction* {.size: sizeof(cint).} = enum
+    SDL_ADDEVENT, SDL_PEEKEVENT, SDL_GETEVENT
+  EventFilter* = proc (userdata: pointer; event: ptr Event): Bool32 {.cdecl.}
+
+
+  SDL_Return* {.size: sizeof(cint).} = enum SdlError = -1, SdlSuccess = 0 ##\
+    ## Return value for many SDL functions. Any function that returns like this \
+    ## should also be discardable
+  Bool32* {.size: sizeof(cint).} = enum False32 = 0, True32 = 1 ##\
+    ## SDL_bool
+  KeyState* {.size: sizeof(byte).} = enum KeyReleased = 0, KeyPressed
+
+  KeySym* {.pure.} = object
+    scancode*: ScanCode
+    sym*: cint ##Keycode
+    modstate*: int16
+    unicode*: cint
+
+  Point* = tuple[x, y: cint]
+  Rect* = tuple[x, y: cint, w, h: cint]
+
+  GLattr*{.size: sizeof(cint).} = enum
+    SDL_GL_RED_SIZE,
+    SDL_GL_GREEN_SIZE,
+    SDL_GL_BLUE_SIZE,
+    SDL_GL_ALPHA_SIZE,
+    SDL_GL_BUFFER_SIZE,
+    SDL_GL_DOUBLEBUFFER,
+    SDL_GL_DEPTH_SIZE,
+    SDL_GL_STENCIL_SIZE,
+    SDL_GL_ACCUM_RED_SIZE,
+    SDL_GL_ACCUM_GREEN_SIZE,
+    SDL_GL_ACCUM_BLUE_SIZE,
+    SDL_GL_ACCUM_ALPHA_SIZE,
+    SDL_GL_STEREO,
+    SDL_GL_MULTISAMPLEBUFFERS,
+    SDL_GL_MULTISAMPLESAMPLES,
+    SDL_GL_ACCELERATED_VISUAL,
+    SDL_GL_RETAINED_BACKING,
+    SDL_GL_CONTEXT_MAJOR_VERSION,
+    SDL_GL_CONTEXT_MINOR_VERSION,
+    SDL_GL_CONTEXT_EGL,
+    SDL_GL_CONTEXT_FLAGS,
+    SDL_GL_CONTEXT_PROFILE_MASK,
+    SDL_GL_SHARE_WITH_CURRENT_CONTEXT,
+    SDL_GL_FRAMEBUFFER_SRGB_CAPABLE,
+    SDL_GL_CONTEXT_RELEASE_BEHAVIOR,
+    SDL_GL_CONTEXT_RESET_NOTIFICATION,
+    SDL_GL_CONTEXT_NO_ERROR
+
+  MouseWheelDirection* {.size: sizeof(uint32).} = enum
+    SDL_MOUSEWHEEL_NORMAL,
+    SDL_MOUSEWHEEL_FLIPPED
+
+const
+  # GLprofile enum.
+  SDL_GL_CONTEXT_PROFILE_CORE*:          cint = 0x0001
+  SDL_GL_CONTEXT_PROFILE_COMPATIBILITY*: cint = 0x0002
+  SDL_GL_CONTEXT_PROFILE_ES*:            cint = 0x0004
+
+  # GLcontextFlag enum.
+  SDL_GL_CONTEXT_DEBUG_FLAG*:              cint = 0x0001
+  SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG*: cint = 0x0002
+  SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG*:      cint = 0x0004
+  SDL_GL_CONTEXT_RESET_ISOLATION_FLAG*:    cint = 0x0008
+
+  # GLcontextRelease enum.
+  SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE*:  cint  = 0x0000
+  SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH*: cint  = 0x0001
+
+type
+  DisplayMode* = object
+    format*: cuint
+    w*,h*,refresh_rate*: cint
+    driverData*: pointer
+
+  WindowPtr* = ptr object
+  RendererPtr* = ptr object
+  TexturePtr* = ptr object
+  CursorPtr* = ptr object
+
+  GlContextPtr* = ptr object
+
+  SDL_Version* = object
+    major*, minor*, patch*: uint8
+
+  RendererInfoPtr* = ptr RendererInfo
+  RendererInfo* {.pure, final.} = object
+    name*: cstring          #*< The name of the renderer
+    flags*: uint32          #*< Supported ::SDL_RendererFlags
+    num_texture_formats*: uint32 #*< The number of available texture formats
+    texture_formats*: array[0..16 - 1, uint32] #*< The available texture formats
+    max_texture_width*: cint #*< The maximimum texture width
+    max_texture_height*: cint #*< The maximimum texture height
+
+  TextureAccess* {.size: sizeof(cint).} = enum
+    SDL_TEXTUREACCESS_STATIC, SDL_TEXTUREACCESS_STREAMING, SDL_TEXTUREACCESS_TARGET
+  TextureModulate*{.size:sizeof(cint).} = enum
+    SDL_TEXTUREMODULATE_NONE, SDL_TEXTUREMODULATE_COLOR, SDL_TEXTUREMODULATE_ALPHA
+  RendererFlip* = cint
+  SysWMType* {.size: sizeof(cint).}=enum
+    SysWM_Unknown, SysWM_Windows, SysWM_X11, SysWM_DirectFB,
+    SysWM_Cocoa, SysWM_UIkit, SysWM_Wayland, SysWM_Mir, SysWM_WinRT, SysWM_Android, SysWM_Vivante
+  WMinfo* = object
+    version*: SDL_Version
+    subsystem*: SysWMType
+    padding*: array[64, byte] ## if the low-level stuff is important to you check \
+      ## SDL_syswm.h and cast padding to the right type
+
+const ## WindowFlags
+    SDL_WINDOW_FULLSCREEN*:cuint = 0x00000001#         /**< fullscreen window */
+    SDL_WINDOW_OPENGL*:cuint = 0x00000002#             /**< window usable with OpenGL context */
+    SDL_WINDOW_SHOWN*:cuint = 0x00000004#              /**< window is visible */
+    SDL_WINDOW_HIDDEN*:cuint = 0x00000008#             /**< window is not visible */
+    SDL_WINDOW_BORDERLESS*:cuint = 0x00000010#         /**< no window decoration */
+    SDL_WINDOW_RESIZABLE*:cuint = 0x00000020#          /**< window can be resized */
+    SDL_WINDOW_MINIMIZED*:cuint = 0x00000040#          /**< window is minimized */
+    SDL_WINDOW_MAXIMIZED*:cuint = 0x00000080#          /**< window is maximized */
+    SDL_WINDOW_INPUT_GRABBED*:cuint = 0x00000100#      /**< window has grabbed input focus */
+    SDL_WINDOW_INPUT_FOCUS*:cuint = 0x00000200#        /**< window has input focus */
+    SDL_WINDOW_MOUSE_FOCUS*:cuint = 0x00000400#        /**< window has mouse focus */
+    SDL_WINDOW_FULLSCREEN_DESKTOP*:cuint = ( SDL_WINDOW_FULLSCREEN or 0x00001000 )
+    SDL_WINDOW_FOREIGN*:cuint = 0x00000800#             /**< window not created by SDL */
+    SDL_WINDOW_ALLOW_HIGHDPI*:cuint = 0x00002000#       /**< window should be created in high-DPI mode if supported */
+    SDL_WINDOW_MOUSE_CAPTURE*:cuint = 0x00004000#       /**< window has mouse captured (unrelated to INPUT_GRABBED) */
+    SDL_WINDOW_VULKAN*:cuint = 0x10000000#              /**< window usable for Vulkan surface */
+    SDL_FLIP_NONE*: cint = 0x00000000 # Do not flip
+    SDL_FLIP_HORIZONTAL*: cint = 0x00000001 # flip horizontally
+    SDL_FLIP_VERTICAL*: cint = 0x00000002 # flip vertically
+
+
+converter toBool*(some: Bool32): bool = bool(some)
+converter toBool*(some: SDL_Return): bool = some == SdlSuccess
+converter toCint*(some: TextureAccess): cint = some.cint
+
+## pixel format flags
+const
+  SDL_ALPHA_OPAQUE* = 255
+  SDL_ALPHA_TRANSPARENT* = 0
+# @}
+#* Pixel type.
+const
+  SDL_PIXELTYPE_UNKNOWN* = 0
+  SDL_PIXELTYPE_INDEX1* = 1
+  SDL_PIXELTYPE_INDEX4* = 2
+  SDL_PIXELTYPE_INDEX8* = 3
+  SDL_PIXELTYPE_PACKED8* = 4
+  SDL_PIXELTYPE_PACKED16* = 5
+  SDL_PIXELTYPE_PACKED32* = 6
+  SDL_PIXELTYPE_ARRAYU8* = 7
+  SDL_PIXELTYPE_ARRAYU16* = 8
+  SDL_PIXELTYPE_ARRAYU32* = 9
+  SDL_PIXELTYPE_ARRAYF16* = 10
+  SDL_PIXELTYPE_ARRAYF32* = 11
+#* Bitmap pixel order, high bit -> low bit.
+const
+  SDL_BITMAPORDER_NONE* = 0
+  SDL_BITMAPORDER_4321* = 1
+  SDL_BITMAPORDER_1234* = 2
+#* Packed component order, high bit -> low bit.
+const
+  SDL_PACKEDORDER_NONE* = 0
+  SDL_PACKEDORDER_XRGB* = 1
+  SDL_PACKEDORDER_RGBX* = 2
+  SDL_PACKEDORDER_ARGB* = 3
+  SDL_PACKEDORDER_RGBA* = 4
+  SDL_PACKEDORDER_XBGR* = 5
+  SDL_PACKEDORDER_BGRX* = 6
+  SDL_PACKEDORDER_ABGR* = 7
+  SDL_PACKEDORDER_BGRA* = 8
+#* Array component order, low byte -> high byte.
+const
+  SDL_ARRAYORDER_NONE* = 0
+  SDL_ARRAYORDER_RGB* = 1
+  SDL_ARRAYORDER_RGBA* = 2
+  SDL_ARRAYORDER_ARGB* = 3
+  SDL_ARRAYORDER_BGR* = 4
+  SDL_ARRAYORDER_BGRA* = 5
+  SDL_ARRAYORDER_ABGR* = 6
+#* Packed component layout.
+const
+  SDL_PACKEDLAYOUT_NONE* = 0
+  SDL_PACKEDLAYOUT_332* = 1
+  SDL_PACKEDLAYOUT_4444* = 2
+  SDL_PACKEDLAYOUT_1555* = 3
+  SDL_PACKEDLAYOUT_5551* = 4
+  SDL_PACKEDLAYOUT_565* = 5
+  SDL_PACKEDLAYOUT_8888* = 6
+  SDL_PACKEDLAYOUT_2101010* = 7
+  SDL_PACKEDLAYOUT_1010102* = 8
+
+# /* Define a four character code as a Uint32 */
+# #define SDL_FOURCC(A, B, C, D) \
+#     ((SDL_static_cast(Uint32, SDL_static_cast(Uint8, (A))) << 0) | \
+#      (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (B))) << 8) | \
+#      (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (C))) << 16) | \
+#      (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (D))) << 24))
+template SDL_FOURCC (a,b,c,d: uint8): uint32 =
+  uint32(a) or (uint32(b) shl 8) or (uint32(c) shl 16) or (uint32(d) shl 24)
+
+template SDL_DEFINE_PIXELFOURCC*(A, B, C, D: char): uint32 =
+  SDL_FOURCC(A.uint8, B.uint8, C.uint8, D.uint8)
+
+template SDL_DEFINE_PIXELFORMAT*(`type`, order, layout, bits, bytes: int): uint32 =
+  uint32((1 shl 28) or ((`type`) shl 24) or ((order) shl 20) or ((layout) shl 16) or
+      ((bits) shl 8) or ((bytes) shl 0))
+
+template SDL_PIXELFLAG*(X: uint32): int =
+  int(((X) shr 28) and 0x0000000F)
+
+template SDL_PIXELTYPE*(X: uint32): int =
+  int(((X) shr 24) and 0x0000000F)
+
+template SDL_PIXELORDER*(X: uint32): int =
+  int(((X) shr 20) and 0x0000000F)
+
+template SDL_PIXELLAYOUT*(X: uint32): int =
+  int(((X) shr 16) and 0x0000000F)
+
+template SDL_BITSPERPIXEL*(X: uint32): int =
+  int(((X) shr 8) and 0x000000FF)
+
+template SDL_BYTESPERPIXEL*(X: uint32): int =
+  int(if SDL_ISPIXELFORMAT_FOURCC(X): (if (((X) == SDL_PIXELFORMAT_YUY2) or
+      ((X) == SDL_PIXELFORMAT_UYVY) or ((X) == SDL_PIXELFORMAT_YVYU)): 2 else: 1) else: (
+      ((X) shr 0) and 0x000000FF))
+
+template SDL_ISPIXELFORMAT_INDEXED*(format: uint32): bool =
+  (not SDL_ISPIXELFORMAT_FOURCC(format) and
+      ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) or
+      (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) or
+      (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8)))
+
+template SDL_ISPIXELFORMAT_ALPHA*(format: uint32): bool =
+  (not SDL_ISPIXELFORMAT_FOURCC(format) and
+      ((SDL_PIXELORDER(format) == SDL_PACKEDORDER_ARGB) or
+      (SDL_PIXELORDER(format) == SDL_PACKEDORDER_RGBA) or
+      (SDL_PIXELORDER(format) == SDL_PACKEDORDER_ABGR) or
+      (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA)))
+
+# The flag is set to 1 because 0x1? is not in the printable ASCII range
+template SDL_ISPIXELFORMAT_FOURCC*(format: uint32): bool =
+  ((format != 0) and (SDL_PIXELFLAG(format) != 1))
+
+# Note: If you modify this list, update SDL_GetPixelFormatName()
+const
+  SDL_PIXELFORMAT_UNKNOWN* = 0
+  SDL_PIXELFORMAT_INDEX1LSB* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1,
+      SDL_BITMAPORDER_4321, 0, 1, 0)
+  SDL_PIXELFORMAT_INDEX1MSB* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1,
+      SDL_BITMAPORDER_1234, 0, 1, 0)
+  SDL_PIXELFORMAT_INDEX4LSB* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4,
+      SDL_BITMAPORDER_4321, 0, 4, 0)
+  SDL_PIXELFORMAT_INDEX4MSB* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4,
+      SDL_BITMAPORDER_1234, 0, 4, 0)
+  SDL_PIXELFORMAT_INDEX8* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX8, 0, 0,
+      8, 1)
+  SDL_PIXELFORMAT_RGB332* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED8,
+      SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_332, 8, 1)
+  SDL_PIXELFORMAT_RGB444* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_4444, 12, 2)
+  SDL_PIXELFORMAT_RGB555* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_1555, 15, 2)
+  SDL_PIXELFORMAT_BGR555* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_1555, 15, 2)
+  SDL_PIXELFORMAT_ARGB4444* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_4444, 16, 2)
+  SDL_PIXELFORMAT_RGBA4444* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_RGBA, SDL_PACKEDLAYOUT_4444, 16, 2)
+  SDL_PIXELFORMAT_ABGR4444* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_ABGR, SDL_PACKEDLAYOUT_4444, 16, 2)
+  SDL_PIXELFORMAT_BGRA4444* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_BGRA, SDL_PACKEDLAYOUT_4444, 16, 2)
+  SDL_PIXELFORMAT_ARGB1555* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_1555, 16, 2)
+  SDL_PIXELFORMAT_RGBA5551* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_RGBA, SDL_PACKEDLAYOUT_5551, 16, 2)
+  SDL_PIXELFORMAT_ABGR1555* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_ABGR, SDL_PACKEDLAYOUT_1555, 16, 2)
+  SDL_PIXELFORMAT_BGRA5551* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_BGRA, SDL_PACKEDLAYOUT_5551, 16, 2)
+  SDL_PIXELFORMAT_RGB565* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_565, 16, 2)
+  SDL_PIXELFORMAT_BGR565* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16,
+      SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_565, 16, 2)
+  SDL_PIXELFORMAT_RGB24* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8,
+      SDL_ARRAYORDER_RGB, 0, 24, 3)
+  SDL_PIXELFORMAT_BGR24* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8,
+      SDL_ARRAYORDER_BGR, 0, 24, 3)
+  SDL_PIXELFORMAT_RGB888* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32,
+      SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_8888, 24, 4)
+  SDL_PIXELFORMAT_RGBX8888* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32,
+      SDL_PACKEDORDER_RGBX, SDL_PACKEDLAYOUT_8888, 24, 4)
+  SDL_PIXELFORMAT_BGR888* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32,
+      SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_8888, 24, 4)
+  SDL_PIXELFORMAT_BGRX8888* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32,
+      SDL_PACKEDORDER_BGRX, SDL_PACKEDLAYOUT_8888, 24, 4)
+  SDL_PIXELFORMAT_ARGB8888* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32,
+      SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_8888, 32, 4)
+  SDL_PIXELFORMAT_RGBA8888* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32,
+      SDL_PACKEDORDER_RGBA, SDL_PACKEDLAYOUT_8888, 32, 4)
+  SDL_PIXELFORMAT_ABGR8888* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32,
+      SDL_PACKEDORDER_ABGR, SDL_PACKEDLAYOUT_8888, 32, 4)
+  SDL_PIXELFORMAT_BGRA8888* = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32,
+      SDL_PACKEDORDER_BGRA, SDL_PACKEDLAYOUT_8888, 32, 4)
+  SDL_PIXELFORMAT_ARGB2101010* = SDL_DEFINE_PIXELFORMAT(
+      SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_2101010,
+      32, 4)
+  SDL_PIXELFORMAT_YV12* = SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2') #*< Planar mode: Y + V + U  (3 planes)
+  SDL_PIXELFORMAT_IYUV* = SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V') #*< Planar mode: Y + U + V  (3 planes)
+  SDL_PIXELFORMAT_YUY2* = SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2') #*< Packed mode: Y0+U0+Y1+V0 (1 plane)
+  SDL_PIXELFORMAT_UYVY* = SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y') #*< Packed mode: U0+Y0+V0+Y1 (1 plane)
+  SDL_PIXELFORMAT_YVYU* = SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U') #*< Packed mode: Y0+V0+Y1+U0 (1 plane)
+
+
+type
+  Color* {.pure, final.} = tuple[
+    r: uint8,
+    g: uint8,
+    b: uint8,
+    a: uint8]
+
+  Palette* {.pure, final.} = object
+    ncolors*: cint
+    colors*: ptr Color
+    version*: uint32
+    refcount*: cint
+
+  PixelFormat* {.pure, final.} = object
+    format*: uint32
+    palette*: ptr Palette
+    BitsPerPixel*: uint8
+    BytesPerPixel*: uint8
+    padding*: array[0..2 - 1, uint8]
+    Rmask*: uint32
+    Gmask*: uint32
+    Bmask*: uint32
+    Amask*: uint32
+    Rloss*: uint8
+    Gloss*: uint8
+    Bloss*: uint8
+    Aloss*: uint8
+    Rshift*: uint8
+    Gshift*: uint8
+    Bshift*: uint8
+    Ashift*: uint8
+    refcount*: cint
+    next*: ptr PixelFormat
+
+  BlitMapPtr*{.pure.} = ptr object ##couldnt find SDL_BlitMap ?
+
+  SurfacePtr* = ptr Surface
+  Surface* {.pure, final.} = object
+    flags*: uint32          #*< Read-only
+    format*: ptr PixelFormat #*< Read-only
+    w*, h*, pitch*: int32   #*< Read-only
+    pixels*: pointer        #*< Read-write
+    userdata*: pointer      #*< Read-write
+    locked*: int32          #*< Read-only   ## see if this should be Bool32
+    lock_data*: pointer     #*< Read-only
+    clip_rect*: Rect       #*< Read-only
+    map: BlitMapPtr           #*< Private
+    refcount*: cint         #*< Read-mostly
+
+  BlendMode* {.size: sizeof(cint).} = enum
+      BlendMode_None = 0x00000000, #*< No blending
+      BlendMode_Blend = 0x00000001, #*< dst = (src * A) + (dst * (1-A))
+      BlendMode_Add  = 0x00000002, #*< dst = (src * A) + dst
+      BlendMode_Mod  = 0x00000004 #*< dst = src * dst
+  BlitFunction* = proc(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr;
+    dstrect: ptr Rect): cint{.cdecl.}
+
+  TimerCallback* = proc (interval: uint32; param: pointer): uint32{.cdecl.}
+  TimerID* = cint
+
+const ##RendererFlags
+  Renderer_Software*: cint = 0x00000001
+  Renderer_Accelerated*: cint = 0x00000002
+  Renderer_PresentVsync*: cint = 0x00000004
+  Renderer_TargetTexture*: cint = 0x00000008
+
+const  ## These are the currently supported flags for the ::SDL_surface.
+  SDL_SWSURFACE* = 0        #*< Just here for compatibility
+  SDL_PREALLOC* = 0x00000001 #*< Surface uses preallocated memory
+  SDL_RLEACCEL* = 0x00000002 #*< Surface is RLE encoded
+  SDL_DONTFREE* = 0x00000004 #*< Surface is referenced internally
+
+template SDL_MUSTLOCK*(some: SurfacePtr): bool = (some.flags and SDL_RLEACCEL) != 0
+
+
+
+const
+  INIT_TIMER*       = 0x00000001
+  INIT_AUDIO*       = 0x00000010
+  INIT_VIDEO*       = 0x00000020
+  INIT_JOYSTICK*    = 0x00000200
+  INIT_HAPTIC*      = 0x00001000
+  INIT_GAMECONTROLLER* = 0x00002000
+  INIT_EVENTS*      = 0x00004000
+  INIT_NOPARACHUTE* = 0x00100000
+  INIT_EVERYTHING*  = 0x0000FFFF
+
+const SDL_WINDOWPOS_UNDEFINED_MASK* = 0x1FFF0000
+template SDL_WINDOWPOS_UNDEFINED_DISPLAY*(X: cint): untyped = cint(SDL_WINDOWPOS_UNDEFINED_MASK or X)
+const SDL_WINDOWPOS_UNDEFINED*: cint = SDL_WINDOWPOS_UNDEFINED_DISPLAY(0)
+template SDL_WINDOWPOS_ISUNDEFINED*(X: cint): bool = (((X) and 0xFFFF0000) == SDL_WINDOWPOS_UNDEFINED_MASK)
+
+const SDL_WINDOWPOS_CENTERED_MASK* = 0x2FFF0000
+template SDL_WINDOWPOS_CENTERED_DISPLAY*(X: cint): cint = cint(SDL_WINDOWPOS_CENTERED_MASK or X)
+const SDL_WINDOWPOS_CENTERED*: cint = SDL_WINDOWPOS_CENTERED_DISPLAY(0)
+template SDL_WINDOWPOS_ISCENTERED*(X: cint): bool = (((X) and 0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK)
+
+template evConv(name, name2, ptype: untyped; valid: openarray[EventType]): untyped =
+  proc `name`* (event: Event): ptype =
+    assert event.kind in valid
+    return cast[ptype](unsafeAddr event)
+  proc `name2`* (event: Event): ptype =
+    assert event.kind in valid
+    return cast[ptype](unsafeAddr event)
+
+evConv(evWindow, window, WindowEventPtr, [WindowEvent])
+evConv(evKeyboard, key, KeyboardEventPtr, [KeyDown, KeyUP])
+evConv(evTextEditing, edit, TextEditingEventPtr, [TextEditing])
+evConv(evTextInput, text, TextInputEventPtr, [TextInput])
+
+evConv(evMouseMotion, motion, MouseMotionEventPtr, [MouseMotion])
+evConv(evMouseButton, button, MouseButtonEventPtr, [MouseButtonDown, MouseButtonUp])
+evConv(evMouseWheel, wheel, MouseWheelEventPtr, [MouseWheel])
+
+evConv(EvJoyAxis, jaxis, JoyAxisEventPtr, [JoyAxisMotion])
+evConv(EvJoyBall, jball, JoyBallEventPtr, [JoyBallMotion])
+evConv(EvJoyHat, jhat, JoyHatEventPtr, [JoyHatMotion])
+evConv(EvJoyButton, jbutton, JoyButtonEventPtr, [JoyButtonDown, JoyButtonUp])
+evConv(EvJoyDevice, jdevice, JoyDeviceEventPtr, [JoyDeviceAdded, JoyDeviceRemoved])
+
+evConv(EvControllerAxis, caxis, ControllerAxisEventPtr, [ControllerAxisMotion])
+evConv(EvControllerButton, cbutton, ControllerButtonEventPtr, [ControllerButtonDown, ControllerButtonUp])
+evConv(EvControllerDevice, cdevice, ControllerDeviceEventPtr, [ControllerDeviceAdded, ControllerDeviceRemoved])
+
+evConv(EvTouchFinger, tfinger, TouchFingerEventPtr, [FingerMotion, FingerDown, FingerUp])
+evConv(EvMultiGesture, mgesture, MultiGestureEventPtr, [MultiGesture])
+evConv(EvDollarGesture, dgesture, DollarGestureEventPtr, [DollarGesture])
+
+evConv(evDropFile, drop, DropEventPtr, [DropFile])
+evConv(evQuit, quit, QuitEventPtr, [QuitEvent])
+
+evConv(evUser, user, UserEventPtr, [UserEvent, UserEvent1, UserEvent2, UserEvent3, UserEvent4, UserEvent5])
+#evConv(EvSysWM, syswm, SysWMEventPtr, {SysWMEvent})
+
+const ## SDL_MessageBox flags. If supported will display warning icon, etc.
+  SDL_MESSAGEBOX_ERROR* = 0x00000010 #*< error dialog
+  SDL_MESSAGEBOX_WARNING* = 0x00000020 #*< warning dialog
+  SDL_MESSAGEBOX_INFORMATION* = 0x00000040 #*< informational dialog
+
+  ## Flags for SDL_MessageBoxButtonData.
+  SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT* = 0x00000001 #*< Marks the default button when return is hit
+  SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT* = 0x00000002 #*< Marks the default button when escape is hit
+
+type
+  MessageBoxColor* {.pure, final.} = object
+    r*: uint8
+    g*: uint8
+    b*: uint8
+
+  MessageBoxColorType* = enum
+    SDL_MESSAGEBOX_COLOR_BACKGROUND, SDL_MESSAGEBOX_COLOR_TEXT,
+    SDL_MESSAGEBOX_COLOR_BUTTON_BORDER,
+    SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND,
+    SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED, SDL_MESSAGEBOX_COLOR_MAX
+  MessageBoxColorScheme* {.pure, final.} = object
+    colors*: array[MessageBoxColorType, MessageBoxColor]
+
+
+  MessageBoxButtonData* {.pure, final.} = object
+    flags*: cint         #*< ::SDL_MessageBoxButtonFlags
+    buttonid*: cint         #*< User defined button id (value returned via SDL_MessageBox)
+    text*: cstring          #*< The UTF-8 button text
+
+  MessageBoxData* {.pure, final.} = object
+    flags*: cint          #*< ::SDL_MessageBoxFlags
+    window*: WindowPtr #*< Parent window, can be NULL
+    title*, message*: cstring         #*< UTF-8 title and message text
+    numbuttons*: cint
+    buttons*: ptr MessageBoxButtonData
+    colorScheme*: ptr MessageBoxColorScheme #*< ::SDL_MessageBoxColorScheme, can be NULL to use system settings
+
+  RWopsPtr* = ptr RWops
+  RWops* {.pure, final.} = object
+    size*: proc (context: RWopsPtr): int64 {.cdecl, tags: [], raises: [].}
+    seek*: proc (context: RWopsPtr; offset: int64; whence: cint): int64 {.cdecl, tags: [], raises: [].}
+    read*: proc (context: RWopsPtr; destination: pointer; size, maxnum: csize_t): csize_t {.cdecl, tags: [ReadIOEffect], raises: [].}
+    write*: proc (context: RWopsPtr; source: pointer; size: csize_t;
+                  num: csize_t): csize_t {.cdecl, tags: [WriteIOEffect], raises: [].}
+    close*: proc (context: RWopsPtr): cint {.cdecl, tags: [WriteIOEffect].}
+    kind*: cint
+    mem*: Mem
+  Mem*{.final.} = object
+    base*: ptr byte
+    here*: ptr byte
+    stop*: ptr byte
+
+# SDL_system.h
+type VoidCallback* = proc(arg:pointer):void{.cdecl.}
+const SDL_ANDROID_EXTERNAL_STORAGE_READ*  = cint(0x01)
+const SDL_ANDROID_EXTERNAL_STORAGE_WRITE* = cint(0x02)
+
+when not defined(SDL_Static):
+  {.push callConv: cdecl, dynlib: LibName.}
+
+
+## functions whose names have been shortened by elision of a type name
+proc getWMInfo*(window: WindowPtr; info: var WMInfo): Bool32 {.
+  importc: "SDL_GetWindowWMInfo".}
+
+proc setLogicalSize*(renderer: RendererPtr; w, h: cint): cint {.
+  importc: "SDL_RenderSetLogicalSize".}
+
+proc getLogicalSize*(renderer: RendererPtr; w, h: var cint) {.
+  importc: "SDL_RenderGetLogicalSize".}
+
+
+proc setDrawColor*(renderer: RendererPtr; r, g, b: uint8, a = 255'u8): SDL_Return {.
+  importc: "SDL_SetRenderDrawColor", discardable.}
+
+proc setDrawColor*(renderer: RendererPtr; c: Color) =
+  setDrawColor(renderer, c.r, c.g, c.b, c.a)
+
+proc getDrawColor*(renderer: RendererPtr; r, g, b, a: var uint8): SDL_Return {.
+  importc: "SDL_GetRenderDrawColor", discardable.}
+proc setDrawBlendMode*(renderer: RendererPtr; blendMode: BlendMode): SDL_Return {.
+  importc: "SDL_SetRenderDrawBlendMode", discardable.}
+proc getDrawBlendMode*(renderer: RendererPtr;
+  blendMode: var BlendMode): SDL_Return {.
+  importc: "SDL_GetRenderDrawBlendMode", discardable.}
+
+
+proc destroy*(texture: TexturePtr) {.importc: "SDL_DestroyTexture".}
+proc destroy*(renderer: RendererPtr) {.importc: "SDL_DestroyRenderer".}
+#proc destroy* (texture: TexturePtr) {.inline.} = texture.destroyTexture
+#proc destroy* (renderer: RendererPtr) {.inline.} = renderer.destroyRenderer
+
+proc getDisplayIndex*(window: WindowPtr): cint {.importc: "SDL_GetWindowDisplayIndex".}
+#*
+proc setDisplayMode*(window: WindowPtr;
+  mode: ptr DisplayMode): SDL_Return {.importc: "SDL_SetWindowDisplayMode".}
+#*
+proc getDisplayMode*(window: WindowPtr; mode: var DisplayMode): cint  {.
+  importc: "SDL_GetWindowDisplayMode".}
+#*
+proc getPixelFormat*(window: WindowPtr): uint32 {.importc: "SDL_GetWindowPixelFormat".}
+
+#*
+#   \brief Get the numeric ID of a window, for logging purposes.
+#
+proc getID*(window: WindowPtr): uint32 {.importc: "SDL_GetWindowID".}
+
+#*
+#   \brief Get the window flags.
+#
+proc getFlags*(window: WindowPtr): uint32 {.importc: "SDL_GetWindowFlags".}
+#*
+#   \brief Set the title of a window, in UTF-8 format.
+#
+#   \sa SDL_GetWindowTitle()
+#
+proc setTitle*(window: WindowPtr; title: cstring) {.importc: "SDL_SetWindowTitle".}
+#*
+#   \brief Get the title of a window, in UTF-8 format.
+#
+#   \sa SDL_SetWindowTitle()
+#
+proc getTitle*(window: WindowPtr): cstring {.importc: "SDL_GetWindowTitle".}
+#*
+#   \brief Set the icon for a window.
+#
+#   \param icon The icon for the window.
+#
+proc setIcon*(window: WindowPtr; icon: SurfacePtr) {.importc: "SDL_SetWindowIcon".}
+#*
+proc setData*(window: WindowPtr; name: cstring;
+  userdata: pointer): pointer {.importc: "SDL_SetWindowData".}
+#*
+proc getData*(window: WindowPtr; name: cstring): pointer {.importc: "SDL_GetWindowData".}
+#*
+proc setPosition*(window: WindowPtr; x, y: cint) {.importc: "SDL_SetWindowPosition".}
+proc getPosition*(window: WindowPtr; x, y: var cint)  {.importc: "SDL_GetWindowPosition".}
+#*
+proc setSize*(window: WindowPtr; w, h: cint)  {.importc: "SDL_SetWindowSize".}
+proc getSize*(window: WindowPtr; w, h: var cint) {.importc: "SDL_GetWindowSize".}
+
+proc setBordered*(window: WindowPtr; bordered: Bool32) {.importc: "SDL_SetWindowBordered".}
+
+
+proc setFullscreen*(window: WindowPtr; fullscreen: uint32): SDL_Return {.importc: "SDL_SetWindowFullscreen".}
+proc getSurface*(window: WindowPtr): SurfacePtr {.importc: "SDL_GetWindowSurface".}
+
+proc updateSurface*(window: WindowPtr): SDL_Return  {.importc: "SDL_UpdateWindowSurface".}
+proc updateSurfaceRects*(window: WindowPtr; rects: ptr Rect;
+  numrects: cint): SDL_Return  {.importc: "SDL_UpdateWindowSurfaceRects".}
+#*
+proc setGrab*(window: WindowPtr; grabbed: Bool32) {.importc: "SDL_SetWindowGrab".}
+proc getGrab*(window: WindowPtr): Bool32 {.importc: "SDL_GetWindowGrab".}
+proc setBrightness*(window: WindowPtr; brightness: cfloat): SDL_Return {.importc: "SDL_SetWindowBrightness".}
+
+proc getBrightness*(window: WindowPtr): cfloat {.importc: "SDL_GetWindowBrightness".}
+
+proc setGammaRamp*(window: WindowPtr;
+  red, green, blue: ptr uint16): SDL_Return {.importc: "SDL_SetWindowGammaRamp".}
+#*
+#   \brief Get the gamma ramp for a window.
+#
+#   \param red   A pointer to a 256 element array of 16-bit quantities to hold
+#                the translation table for the red channel, or NULL.
+#   \param green A pointer to a 256 element array of 16-bit quantities to hold
+#                the translation table for the green channel, or NULL.
+#   \param blue  A pointer to a 256 element array of 16-bit quantities to hold
+#                the translation table for the blue channel, or NULL.
+#
+#   \return 0 on success, or -1 if gamma ramps are unsupported.
+#
+#   \sa SDL_SetWindowGammaRamp()
+#
+proc getGammaRamp*(window: WindowPtr; red: ptr uint16;
+                  green: ptr uint16; blue: ptr uint16): cint {.importc: "SDL_GetWindowGammaRamp".}
+
+
+proc init*(flags: cint): SDL_Return {.discardable,
+  importc: "SDL_Init".}
+#
+#   This function initializes specific SDL subsystems
+#
+proc initSubSystem*(flags: uint32):cint {.
+  importc: "SDL_InitSubSystem".}
+
+#
+#   This function cleans up specific SDL subsystems
+#
+proc quitSubSystem*(flags: uint32) {.
+  importc: "SDL_QuitSubSystem".}
+
+#
+#   This function returns a mask of the specified subsystems which have
+#   previously been initialized.
+#
+#   If \c flags is 0, it returns a mask of all initialized subsystems.
+#
+proc wasInit*(flags: uint32): uint32 {.
+  importc: "SDL_WasInit".}
+
+proc quit*() {.
+  importc: "SDL_Quit".}
+
+proc getPlatform*(): cstring {.
+  importc: "SDL_GetPlatform".}
+
+proc getVersion*(ver: var SDL_Version) {.
+  importc: "SDL_GetVersion".}
+proc getRevision*(): cstring {.
+  importc: "SDL_GetRevision".}
+proc getRevisionNumber*(): cint {.
+  importc: "SDL_GetRevisionNumber".}
+proc getBasePath*(): cstring {.
+  importc: "SDL_GetBasePath".}
+proc getPrefPath*(org, app: cstring): cstring {.
+  importc: "SDL_GetPrefPath".}
+
+
+proc getNumRenderDrivers*(): cint {.
+  importc: "SDL_GetNumRenderDriver".}
+proc getRenderDriverInfo*(index: cint; info: var RendererInfo): SDL_Return {.
+  importc: "SDL_GetRenderDriverInfo".}
+proc createWindowAndRenderer*(width, height: cint; window_flags: uint32;
+  window: var WindowPtr; renderer: var RendererPtr): SDL_Return {.
+  importc: "SDL_CreateWindowAndRenderer".}
+
+proc createRenderer*(window: WindowPtr; index: cint; flags: cint): RendererPtr {.
+  importc: "SDL_CreateRenderer".}
+proc createSoftwareRenderer*(surface: SurfacePtr): RendererPtr {.
+  importc: "SDL_CreateSoftwareRenderer".}
+proc getRenderer*(window: WindowPtr): RendererPtr {.
+  importc: "SDL_GetRenderer".}
+proc getRendererInfo*(renderer: RendererPtr; info: RendererInfoPtr): cint {.
+  importc: "SDL_GetRendererInfo".}
+proc getRendererOutputSize*(renderer: RendererPtr, w: ptr cint, h: ptr cint): cint {.
+  importc: "SDL_GetRendererOutputSize".}
+
+proc createTexture*(renderer: RendererPtr; format: uint32;
+  access, w, h: cint): TexturePtr {.
+  importc: "SDL_CreateTexture".}
+
+proc createTextureFromSurface*(renderer: RendererPtr; surface: SurfacePtr): TexturePtr {.
+  importc: "SDL_CreateTextureFromSurface".}
+proc createTexture*(renderer: RendererPtr; surface: SurfacePtr): TexturePtr {.
+  inline.} = renderer.createTextureFromSurface(surface)
+
+proc queryTexture*(texture: TexturePtr; format: ptr uint32;
+  access, w, h: ptr cint): SDL_Return {.discardable,
+  importc: "SDL_QueryTexture".}
+
+proc setTextureColorMod*(texture: TexturePtr; r, g, b: uint8): SDL_Return {.
+  importc: "SDL_SetTextureColorMod".}
+
+proc getTextureColorMod*(texture: TexturePtr; r, g, b: var uint8): SDL_Return {.
+  importc: "SDL_GetTextureColorMod".}
+
+proc setTextureAlphaMod*(texture: TexturePtr; alpha: uint8): SDL_Return {.
+  importc: "SDL_SetTextureAlphaMod", discardable.}
+
+proc getTextureAlphaMod*(texture: TexturePtr; alpha: var uint8): SDL_Return {.
+  importc: "SDL_GetTextureAlphaMod", discardable.}
+
+proc setTextureBlendMode*(texture: TexturePtr; blendMode: BlendMode): SDL_Return {.
+  importc: "SDL_SetTextureBlendMode", discardable.}
+
+proc getTextureBlendMode*(texture: TexturePtr;
+  blendMode: var BlendMode): SDL_Return {.importc: "SDL_GetTextureBlendMode", discardable.}
+
+proc updateTexture*(texture: TexturePtr; rect: ptr Rect; pixels: pointer;
+  pitch: cint): SDL_Return {.importc: "SDL_UpdateTexture", discardable.}
+
+proc lockTexture*(texture: TexturePtr; rect: ptr Rect; pixels: ptr pointer;
+  pitch: ptr cint): SDL_Return {.importc: "SDL_LockTexture", discardable.}
+
+proc unlockTexture*(texture: TexturePtr) {.importc: "SDL_UnlockTexture".}
+
+proc renderTargetSupported*(renderer: RendererPtr): Bool32 {.
+  importc: "SDL_RenderTargetSupported".}
+
+proc setRenderTarget*(renderer: RendererPtr; texture: TexturePtr): SDL_Return {.discardable,
+  importc: "SDL_SetRenderTarget".}
+#*
+#
+proc getRenderTarget*(renderer: RendererPtr): TexturePtr {.
+  importc: "SDL_GetRenderTarget".}
+
+
+
+
+#*
+#   \brief Set the drawing area for rendering on the current target.
+#
+#   \param rect The rectangle representing the drawing area, or NULL to set the viewport to the entire target.
+#
+#   The x,y of the viewport rect represents the origin for rendering.
+#
+#   \note When the window is resized, the current viewport is automatically
+#         centered within the new window size.
+#
+#   \sa SDL_RenderGetViewport()
+#   \sa SDL_RenderSetLogicalSize()
+#
+proc setViewport*(renderer: RendererPtr; rect: ptr Rect): SDL_Return {.
+  importc: "SDL_RenderSetViewport", discardable.}
+proc getViewport*(renderer: RendererPtr; rect: var Rect) {.
+  importc: "SDL_RenderGetViewport".}
+
+proc setScale*(renderer: RendererPtr; scaleX, scaleY: cfloat): SDL_Return {.
+  importc: "SDL_RenderSetScale", discardable.}
+proc getScale*(renderer: RendererPtr; scaleX, scaleY: var cfloat) {.
+  importc: "SDL_RenderGetScale".}
+proc drawPoint*(renderer: RendererPtr; x, y: cint): SDL_Return {.
+  importc: "SDL_RenderDrawPoint", discardable.}
+#*
+proc drawPoints*(renderer: RendererPtr; points: ptr Point;
+  count: cint): SDL_Return {.importc: "SDL_RenderDrawPoints", discardable.}
+
+proc drawLine*(renderer: RendererPtr;
+  x1, y1, x2, y2: cint): SDL_Return {.
+  importc: "SDL_RenderDrawLine", discardable.}
+#*
+proc drawLines*(renderer: RendererPtr; points: ptr Point;
+  count: cint): SDL_Return {.importc: "SDL_RenderDrawLines", discardable.}
+
+proc drawRect*(renderer: RendererPtr; rect: var Rect): SDL_Return{.
+  importc: "SDL_RenderDrawRect", discardable.}
+proc drawRect*(renderer: RendererPtr; rect: ptr Rect = nil): SDL_Return{.
+  importc: "SDL_RenderDrawRect", discardable.}
+
+proc drawRects*(renderer: RendererPtr; rects: ptr Rect;
+  count: cint): SDL_Return {.importc: "SDL_RenderDrawRects".}
+proc fillRect*(renderer: RendererPtr; rect: var Rect): SDL_Return {.
+  importc: "SDL_RenderFillRect", discardable.}
+proc fillRect*(renderer: RendererPtr; rect: ptr Rect = nil): SDL_Return {.
+  importc: "SDL_RenderFillRect", discardable.}
+#*
+proc fillRects*(renderer: RendererPtr; rects: ptr Rect;
+  count: cint): SDL_Return {.importc: "SDL_RenderFillRects", discardable.}
+
+proc copy*(renderer: RendererPtr; texture: TexturePtr;
+                     srcrect, dstrect: ptr Rect): SDL_Return {.
+  importc: "SDL_RenderCopy", discardable.}
+
+proc copyEx*(renderer: RendererPtr; texture: TexturePtr;
+             srcrect, dstrect: var Rect; angle: cdouble; center: ptr Point;
+             flip: RendererFlip = SDL_FLIP_NONE): SDL_Return {.
+             importc: "SDL_RenderCopyEx", discardable.}
+proc copyEx*(renderer: RendererPtr; texture: TexturePtr;
+             srcrect, dstrect: ptr Rect; angle: cdouble; center: ptr Point;
+             flip: RendererFlip = SDL_FLIP_NONE): SDL_Return {.
+             importc: "SDL_RenderCopyEx", discardable.}
+
+proc clear*(renderer: RendererPtr): cint {.
+  importc: "SDL_RenderClear", discardable.}
+
+proc readPixels*(renderer: RendererPtr; rect: var Rect; format: cint;
+  pixels: pointer; pitch: cint): cint {.importc: "SDL_RenderReadPixels".}
+proc readPixels*(renderer: RendererPtr; rect: ptr Rect; format: cint;
+  pixels: pointer; pitch: cint): cint {.importc: "SDL_RenderReadPixels".}
+proc present*(renderer: RendererPtr) {.importc: "SDL_RenderPresent".}
+
+
+
+proc glBindTexture*(texture: TexturePtr; texw, texh: var cfloat): cint {.
+  importc: "SDL_GL_BindTexture".}
+proc glUnbindTexture*(texture: TexturePtr) {.
+  importc: "SDL_GL_UnbindTexture".}
+
+proc createRGBSurface*(flags: cint; width, height, depth: cint;
+  Rmask, Gmask, BMask, Amask: uint32): SurfacePtr {.
+  importc: "SDL_CreateRGBSurface".}
+proc createRGBSurfaceFrom*(pixels: pointer; width, height, depth, pitch: cint;
+  Rmask, Gmask, Bmask, Amask: uint32): SurfacePtr {.
+  importc: "SDL_CreateRGBSurfaceFrom".}
+
+proc freeSurface*(surface: SurfacePtr) {.
+  importc: "SDL_FreeSurface".}
+
+proc setSurfacePalette*(surface: SurfacePtr; palette: ptr Palette): cint {.
+  importc:"SDL_SetSurfacePalette".}
+#*
+#   \brief Sets up a surface for directly accessing the pixels.
+#
+#   Between calls to SDL_LockSurface() / SDL_UnlockSurface(), you can write
+#   to and read from \c surface->pixels, using the pixel format stored in
+#   \c surface->format.  Once you are done accessing the surface, you should
+#   use SDL_UnlockSurface() to release it.
+#
+#   Not all surfaces require locking.  If SDL_MUSTLOCK(surface) evaluates
+#   to 0, then you can read and write to the surface at any time, and the
+#   pixel format of the surface will not change.
+#
+#   No operating system or library calls should be made between lock/unlock
+#   pairs, as critical system locks may be held during this time.
+#
+#   SDL_LockSurface() returns 0, or -1 if the surface couldn't be locked.
+#
+#   \sa SDL_UnlockSurface()
+#
+proc lockSurface*(surface: SurfacePtr): cint {.importc: "SDL_LockSurface".}
+#* \sa SDL_LockSurface()
+proc unlockSurface*(surface: SurfacePtr) {.importc: "SDL_UnlockSurface".}
+#*
+#   Load a surface from a seekable SDL data stream (memory or file).
+#
+#   If \c freesrc is non-zero, the stream will be closed after being read.
+#
+#   The new surface should be freed with SDL_FreeSurface().
+#
+#   \return the new surface, or NULL if there was an error.
+#
+proc loadBMP_RW*(src: RWopsPtr; freesrc: cint): SurfacePtr {.
+  importc: "SDL_LoadBMP_RW".}
+
+
+
+proc rwFromFile*(file: cstring; mode: cstring): RWopsPtr {.importc: "SDL_RWFromFile".}
+proc rwFromFP*(fp: File; autoclose: Bool32): RWopsPtr {.importc: "SDL_RWFromFP".}
+proc rwFromMem*(mem: pointer; size: cint): RWopsPtr {.importc: "SDL_RWFromMem".}
+proc rwFromConstMem*(mem: pointer; size: cint): RWopsPtr {.importc: "SDL_RWFromConstMem".}
+
+proc allocRW* : RWopsPtr {.importc: "SDL_AllocRW".}
+proc freeRW* (area: RWopsPtr) {.importc: "SDL_FreeRW".}
+
+
+#*
+#   Load a surface from a file.
+#
+#   Convenience macro.
+#
+#*
+proc saveBMP_RW*(surface: SurfacePtr; dst: RWopsPtr;
+                 freedst: cint): SDL_Return {.importc: "SDL_SaveBMP_RW".}
+
+proc setSurfaceRLE*(surface: SurfacePtr; flag: cint): cint {.
+  importc:"SDL_SetSurfaceRLE".}
+proc setColorKey*(surface: SurfacePtr; flag: cint; key: uint32): cint {.
+  importc: "SDL_SetColorKey".}
+
+proc getColorKey*(surface: SurfacePtr; key: var uint32): cint {.
+  importc: "SDL_GetColorKey".}
+proc setSurfaceColorMod*(surface: SurfacePtr; r, g, b: uint8): cint {.
+  importc: "SDL_SetSurfaceColorMod".}
+
+proc getSurfaceColorMod*(surface: SurfacePtr; r, g, b: var uint8): cint {.
+  importc: "SDL_GetSurfaceColorMod".}
+
+proc setSurfaceAlphaMod*(surface: SurfacePtr; alpha: uint8): cint {.
+  importc: "SDL_SetSurfaceAlphaMod".}
+proc getSurfaceAlphaMod*(surface: SurfacePtr; alpha: var uint8): cint {.
+  importc: "SDL_GetSurfaceAlphaMod".}
+
+proc setSurfaceBlendMode*(surface: SurfacePtr; blendMode: BlendMode): cint {.
+  importc: "SDL_SetSurfaceBlendMode".}
+proc getSurfaceBlendMode*(surface: SurfacePtr; blendMode: ptr BlendMode): cint {.
+  importc: "SDL_GetSurfaceBlendMode".}
+
+proc setClipRect*(surface: SurfacePtr; rect: ptr Rect): Bool32 {.
+  importc: "SDL_SetClipRect".}
+proc getClipRect*(surface: SurfacePtr; rect: ptr Rect) {.
+  importc: "SDL_GetClipRect".}
+
+proc setClipRect*(renderer: RendererPtr; rect: ptr Rect): cint {.
+  importc: "SDL_RenderSetClipRect".}
+proc getClipRect*(renderer: RendererPtr; rect: ptr Rect): cint {.
+  importc: "SDL_RenderGetClipRect".}
+proc isClipEnabled*(renderer: RendererPtr): cint {.
+  importc: "SDL_RenderIsClipEnabled".}
+
+proc convertSurface*(src: SurfacePtr; fmt: ptr PixelFormat;
+  flags: cint): SurfacePtr {.importc: "SDL_ConvertSurface".}
+proc convertSurfaceFormat*(src: SurfacePtr; pixel_format,
+  flags: uint32): SurfacePtr {.importc: "SDL_ConvertSurfaceFormat".}
+
+proc convertPixels*(width, height: cint; src_format: uint32; src: pointer;
+  src_pitch: cint; dst_format: uint32; dst: pointer; dst_pitch: cint): cint {.
+  importc: "SDL_ConvertPixels".}
+#*
+#   Performs a fast fill of the given rectangle with \c color.
+#
+#   If \c rect is NULL, the whole surface will be filled with \c color.
+#
+#   The color should be a pixel of the format used by the surface, and
+#   can be generated by the SDL_MapRGB() function.
+#
+#   \return 0 on success, or -1 on error.
+#
+proc fillRect*(dst: SurfacePtr; rect: ptr Rect; color: uint32): SDL_Return {.
+  importc: "SDL_FillRect", discardable.}
+proc fillRects*(dst: SurfacePtr; rects: ptr Rect; count: cint;
+                    color: uint32): cint {.importc: "SDL_FillRects".}
+
+proc upperBlit*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr;
+  dstrect: ptr Rect): SDL_Return {.importc: "SDL_UpperBlit".}
+
+proc lowerBlit*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr;
+  dstrect: ptr Rect): SDL_Return {.importc: "SDL_LowerBlit".}
+
+proc softStretch*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr;
+  dstrect: ptr Rect): SDL_Return {.importc: "SDL_SoftStretch".}
+
+
+proc upperBlitScaled*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr;
+  dstrect: ptr Rect): SDL_Return {.importc: "SDL_UpperBlitScaled".}
+proc lowerBlitScaled*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr;
+  dstrect: ptr Rect): SDL_Return {.importc: "SDL_LowerBlitScaled".}
+
+
+
+proc readU8*(src: RWopsPtr): uint8 {.importc: "SDL_ReadU8".}
+proc readLE16*(src: RWopsPtr): uint16 {.importc: "SDL_ReadLE16".}
+proc readBE16*(src: RWopsPtr): uint16 {.importc: "SDL_ReadBE16".}
+proc readLE32*(src: RWopsPtr): uint32 {.importc: "SDL_ReadLE32".}
+proc readBE32*(src: RWopsPtr): uint32 {.importc: "SDL_ReadBE32".}
+proc readLE64*(src: RWopsPtr): uint64 {.importc: "SDL_ReadLE64".}
+proc readBE64*(src: RWopsPtr): uint64 {.importc: "SDL_ReadBE64".}
+proc writeU8*(dst: RWopsPtr; value: uint8): csize_t {.importc: "SDL_WriteU8".}
+proc writeLE16*(dst: RWopsPtr; value: uint16): csize_t {.importc: "SDL_WriteLE16".}
+proc writeBE16*(dst: RWopsPtr; value: uint16): csize_t {.importc: "SDL_WriteBE16".}
+proc writeLE32*(dst: RWopsPtr; value: uint32): csize_t {.importc: "SDL_WriteLE32".}
+proc writeBE32*(dst: RWopsPtr; value: uint32): csize_t {.importc: "SDL_WriteBE32".}
+proc writeLE64*(dst: RWopsPtr; value: uint64): csize_t {.importc: "SDL_WriteLE64".}
+proc writeBE64*(dst: RWopsPtr; value: uint64): csize_t {.importc: "SDL_WriteBE64".}
+
+proc showMessageBox*(messageboxdata: ptr MessageBoxData;
+  buttonid: var cint): cint {.importc: "SDL_ShowMessageBox".}
+
+proc showSimpleMessageBox*(flags: uint32; title, message: cstring;
+  window: WindowPtr): cint {.importc: "SDL_ShowSimpleMessageBox".}
+  #   \return 0 on success, -1 on error
+
+
+
+
+
+proc getNumVideoDrivers*(): cint {.importc: "SDL_GetNumVideoDrivers".}
+proc getVideoDriver*(index: cint): cstring {.importc: "SDL_GetVideoDriver".}
+proc videoInit*(driver_name: cstring): SDL_Return {.importc: "SDL_VideoInit".}
+proc videoQuit*() {.importc: "SDL_VideoQuit".}
+proc getCurrentVideoDriver*(): cstring {.importc: "SDL_GetCurrentVideoDriver".}
+proc getNumVideoDisplays*(): cint {.importc: "SDL_GetNumVideoDisplays".}
+
+proc getDisplayBounds*(displayIndex: cint; rect: var Rect): SDL_Return {.
+  importc: "SDL_GetDisplayBounds".}
+proc getNumDisplayModes*(displayIndex: cint): cint {.importc: "SDL_GetNumDisplayModes".}
+#*
+proc getDisplayMode*(displayIndex: cint; modeIndex: cint;
+  mode: var DisplayMode): SDL_Return {.importc: "SDL_GetDisplayMode".}
+
+proc getDesktopDisplayMode*(displayIndex: cint;
+  mode: var DisplayMode): SDL_Return {.importc: "SDL_GetDesktopDisplayMode".}
+proc getCurrentDisplayMode*(displayIndex: cint;
+  mode: var DisplayMode): SDL_Return {.importc: "SDL_GetCurrentDisplayMode".}
+
+proc getClosestDisplayMode*(displayIndex: cint; mode: ptr DisplayMode;
+                                closest: ptr DisplayMode): ptr DisplayMode {.importc: "SDL_GetClosestDisplayMode".}
+proc getDisplayDPI*(displayIndex: cint;
+  ddpi, hdpi, vdpi: ptr cfloat): SDL_Return {.importc: "SDL_GetDisplayDPI".}
+#*
+#*
+proc createWindow*(title: cstring; x, y, w, h: cint;
+                   flags: uint32): WindowPtr  {.importc: "SDL_CreateWindow".}
+#*
+proc createWindowFrom*(data: pointer): WindowPtr {.importc: "SDL_CreateWindowFrom".}
+
+#*
+#   \brief Get a window from a stored ID, or NULL if it doesn't exist.
+#
+proc getWindowFromID*(id: uint32): WindowPtr {.importc: "SDL_GetWindowFromID".}
+
+
+
+
+#
+proc showWindow*(window: WindowPtr) {.importc: "SDL_ShowWindow".}
+proc hideWindow*(window: WindowPtr) {.importc: "SDL_HideWindow".}
+#*
+proc raiseWindow*(window: WindowPtr) {.importc: "SDL_RaiseWindow".}
+proc maximizeWindow*(window: WindowPtr) {.importc: "SDL_MaximizeWindow".}
+proc minimizeWindow*(window: WindowPtr) {.importc: "SDL_MinimizeWindow".}
+#*
+#
+proc restoreWindow*(window: WindowPtr) {.importc: "SDL_RestoreWindow".}
+
+proc destroyWindow*(window: WindowPtr) {.importc: "SDL_DestroyWindow".}
+
+proc isScreenSaverEnabled*(): Bool32 {.importc: "SDL_IsScreenSaverEnabled".}
+proc enableScreenSaver*() {.importc: "SDL_EnableScreenSaver".}
+proc disableScreenSaver*() {.importc: "SDL_DisableScreenSaver".}
+
+
+proc getTicks*(): uint32 {.importc: "SDL_GetTicks".}
+proc getPerformanceCounter*(): uint64 {.importc: "SDL_GetPerformanceCounter".}
+proc getPerformanceFrequency*(): uint64 {.importc: "SDL_GetPerformanceFrequency".}
+proc delay*(ms: uint32) {.importc: "SDL_Delay".}
+#*
+#  \brief Add a new timer to the pool of timers already running.
+#
+#  \return A timer ID, or NULL when an error occurs.
+#
+proc addTimer*(interval: uint32; callback: TimerCallback;
+      param: pointer): TimerID {.importc: "SDL_AddTimer".}
+#*
+#  \brief Remove a timer knowing its ID.
+#
+#  \return A boolean value indicating success or failure.
+#
+#  \warning It is not safe to remove a timer multiple times.
+#
+proc removeTimer*(id: TimerID): Bool32 {.importc: "SDL_RemoveTimer".}
+
+
+#*
+#   \name OpenGL support functions
+#
+#@{
+#*
+#   \brief Dynamically load an OpenGL library.
+#
+#   \param path The platform dependent OpenGL library name, or NULL to open the
+#               default OpenGL library.
+#
+#   \return 0 on success, or -1 if the library couldn't be loaded.
+#
+#   This should be done after initializing the video driver, but before
+#   creating any OpenGL windows.  If no OpenGL library is loaded, the default
+#   library will be loaded upon creation of the first OpenGL window.
+#
+#   \note If you do this, you need to retrieve all of the GL functions used in
+#         your program from the dynamic library using SDL_GL_GetProcAddress().
+#
+#   \sa SDL_GL_GetProcAddress()
+#   \sa SDL_GL_UnloadLibrary()
+#
+#extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path);
+proc glLoadLibrary* (path: cstring): SDL_Return {.discardable,
+  importc: "SDL_GL_LoadLibrary".}
+#extern DECLSPEC void *SDLCALL SDL_GL_GetProcAddress(const char *proc);
+proc glGetProcAddress* (procedure: cstring): pointer {.
+  importc: "SDL_GL_GetProcAddress".}
+#extern DECLSPEC void SDLCALL SDL_GL_UnloadLibrary(void);
+proc glUnloadLibrary* {.
+  importc: "SDL_GL_UnloadLibrary".}
+#extern DECLSPEC SDL_bool SDLCALL SDL_GL_ExtensionSupported(const char
+#                                                          *extension);
+proc glExtensionSupported* (extension: cstring): bool {.
+  importc: "SDL_GL_ExtensionSupported".}
+
+#extern DECLSPEC int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value);
+proc glSetAttribute* (attr: GLattr; value: cint): cint {.
+  importc: "SDL_GL_SetAttribute".}
+#extern DECLSPEC int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int *value);
+proc glGetAttribute* (attr: GLattr; value: var cint): cint {.
+  importc: "SDL_GL_GetAttribute".}
+
+
+proc glCreateContext*(window: WindowPtr): GlContextPtr {.
+  importc: "SDL_GL_CreateContext".}
+  ## Create an OpenGL context for use with an OpenGL window, and make it current.
+proc glMakeCurrent* (window: WindowPtr; context: GlContextPtr): cint {.
+  importc: "SDL_GL_MakeCurrent".}
+
+proc glGetCurrentWindow* : WindowPtr {.
+  importc: "SDL_GL_GetCurrentWindow".}
+proc glGetCurrentContext*: GlContextPtr {.
+  importc: "SDL_GL_GetCurrentContext".}
+
+proc glGetDrawableSize* (window: WindowPtr; w,h: var cint) {.
+  importc: "SDL_GL_GetDrawableSize".}
+
+proc glSetSwapInterval* (interval: cint): cint {.
+  importc: "SDL_GL_SetSwapInterval".}
+proc glGetSwapInterval* : cint {.
+  importc: "SDL_GL_GetSwapInterval".}
+
+proc glSwapWindow*(window: WindowPtr) {.
+  importc: "SDL_GL_SwapWindow".}
+  ## Swap the OpenGL buffers for a window, if double-buffering is supported.
+
+proc glDeleteContext* (context: GlContextPtr) {.
+  importc: "SDL_GL_DeleteContext".}
+
+
+##SDL_vulkan.h
+type VkHandle = int64
+type VkNonDispatchableHandle = int64
+
+# Skipped using Vk prefix to stop any potential name clashes with the Vulkan library
+type VulkanInstance* = VkHandle
+type VulkanSurface* = VkNonDispatchableHandle
+
+#extern DECLSPEC int SDLCALL SDL_Vulkan_LoadLibrary(const char *path);
+proc vulkanLoadLibrary*(path: cstring):cint {.
+  importc: "SDL_Vulkan_LoadLibrary".}
+
+#extern DECLSPEC void *SDLCALL SDL_Vulkan_GetVkGetInstanceProcAddr(void);
+proc vulkanGetVkGetInstanceProcAddr*(): pointer {.
+  importc: "SDL_Vulkan_GetVkGetInstanceProcAddr".}
+
+#extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void);
+proc vulkanUnloadLibrary*() {.
+  importc: "SDL_Vulkan_UnloadLibrary".}
+
+#extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_GetInstanceExtensions(
+#                           SDL_Window *window,
+#                           unsigned int *pCount,
+#                           const char **pNames);
+proc vulkanGetInstanceExtensions*(window: WindowPtr, pCount: ptr cuint, pNames: cstringArray): Bool32 {.
+  importc: "SDL_Vulkan_GetInstanceExtensions".}
+
+#extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_CreateSurface(
+#                       SDL_Window *window,
+#                       VkInstance instance,
+#                       VkSurfaceKHR* surface);
+proc vulkanCreateSurface*(window: WindowPtr, instance: VulkanInstance, surface: ptr VulkanSurface): Bool32 {.
+  importc: "SDL_Vulkan_CreateSurface".}
+
+#extern DECLSPEC void SDLCALL SDL_Vulkan_GetDrawableSize(SDL_Window * window,
+#                                                       int *w, int *h);
+proc vulkanGetDrawableSize*(window: WindowPtr, w, h: ptr cint) {.
+  importc: "SDL_Vulkan_GetDrawableSize".}
+
+##SDL_keyboard.h:
+proc getKeyboardFocus*: WindowPtr {.importc: "SDL_GetKeyboardFocus".}
+  #Get the window which currently has keyboard focus.
+proc getKeyboardState*(numkeys: ptr int = nil): ptr array[0 .. SDL_NUM_SCANCODES.int, uint8] {.importc: "SDL_GetKeyboardState".}
+  #Get the snapshot of the current state of the keyboard
+proc getModState*: Keymod {.importc: "SDL_GetModState".}
+  #Get the current key modifier state for the keyboard
+proc setModState*(state: Keymod) {.importc: "SDL_SetModState".}
+  #Set the current key modifier state for the keyboard
+proc getKeyFromScancode*(scancode: ScanCode): cint {.importc: "SDL_GetKeyFromScancode".}
+  #Get the key code corresponding to the given scancode according to the current keyboard layout
+proc getScancodeFromKey*(key: cint): ScanCode {.importc: "SDL_GetScancodeFromKey".}
+  #Get the scancode corresponding to the given key code according to the current keyboard layout
+proc getScancodeName*(scancode: ScanCode): cstring {.importc: "SDL_GetScancodeName".}
+  #Get a human-readable name for a scancode
+proc getScancodeFromName*(name: cstring): ScanCode {.importc: "SDL_GetScancodeFromName".}
+  #Get a scancode from a human-readable name
+proc getKeyName*(key: cint): cstring {.
+  importc: "SDL_GetKeyName".}
+  #Get a human-readable name for a key
+proc getKeyFromName*(name: cstring): cint {.
+  importc: "SDL_GetKeyFromName".}
+  #Get a key code from a human-readable name
+proc startTextInput* {.
+  importc: "SDL_StartTextInput".}
+  #Start accepting Unicode text input events
+proc isTextInputActive*: bool {.
+  importc: "SDL_IsTextInputActive".}
+proc stopTextInput* {.
+  importc: "SDL_StopTextInput".}
+proc setTextInputRect*(rect: ptr Rect) {.
+  importc: "SDL_SetTextInputRect".}
+proc hasScreenKeyboardSupport*: bool {.importc: "SDL_HasScreenKeyboardSupport".}
+proc isScreenKeyboardShown*(window: WindowPtr): bool {.importc: "SDL_IsScreenKeyboardShown".}
+
+
+
+proc getMouseFocus*(): WindowPtr {.importc: "SDL_GetMouseFocus".}
+#*
+#   \brief Retrieve the current state of the mouse.
+#
+#   The current button state is returned as a button bitmask, which can
+#   be tested using the SDL_BUTTON(X) macros, and x and y are set to the
+#   mouse cursor position relative to the focus window for the currently
+#   selected mouse.  You can pass NULL for either x or y.
+#
+proc getMouseState*(x, y: var cint): uint8 {.importc: "SDL_GetMouseState", discardable.}
+proc getMouseState*(x, y: ptr cint): uint8 {.importc: "SDL_GetMouseState", discardable.}
+#*
+proc getRelativeMouseState*(x, y: var cint): uint8 {.
+  importc: "SDL_GetRelativeMouseState".}
+#*
+proc warpMouseInWindow*(window: WindowPtr; x, y: cint)  {.
+  importc: "SDL_WarpMouseInWindow".}
+#*
+proc setRelativeMouseMode*(enabled: Bool32): SDL_Return  {.
+  importc: "SDL_SetRelativeMouseMode".}
+#*
+proc captureMouse*(enabled: Bool32): SDL_Return {.
+  importc: "SDL_CaptureMouse" .}
+#*
+proc getRelativeMouseMode*(): Bool32 {.importc: "SDL_GetRelativeMouseMode".}
+#*
+proc createCursor*(data, mask: ptr uint8;
+  w, h, hot_x, hot_y: cint): CursorPtr {.importc: "SDL_CreateCursor".}
+#*
+proc createColorCursor*(surface: SurfacePtr; hot_x, hot_y: cint): CursorPtr {.
+  importc: "SDL_CreateColorCursor".}
+#*
+type
+  SystemCursor* = enum
+    SDL_SYSTEM_CURSOR_ARROW,     ## Arrow
+    SDL_SYSTEM_CURSOR_IBEAM,     ## I-beam
+    SDL_SYSTEM_CURSOR_WAIT,      ## Wait
+    SDL_SYSTEM_CURSOR_CROSSHAIR, ## Crosshair
+    SDL_SYSTEM_CURSOR_WAITARROW, ## Small wait cursor (or Wait if not available)
+    SDL_SYSTEM_CURSOR_SIZENWSE,  ## Double arrow pointing northwest and southeast
+    SDL_SYSTEM_CURSOR_SIZENESW,  ## Double arrow pointing northeast and southwest
+    SDL_SYSTEM_CURSOR_SIZEWE,    ## Double arrow pointing west and east
+    SDL_SYSTEM_CURSOR_SIZENS,    ## Double arrow pointing north and south
+    SDL_SYSTEM_CURSOR_SIZEALL,   ## Four pointed arrow pointing north, south, east, and west
+    SDL_SYSTEM_CURSOR_NO,        ## Slashed circle or crossbones
+    SDL_SYSTEM_CURSOR_HAND       ## Hand
+
+proc createSystemCursor*(c: SystemCursor): CursorPtr {.
+  importc: "SDL_CreateSystemCursor".}
+proc setCursor*(cursor: CursorPtr) {.importc: "SDL_SetCursor".}
+proc getCursor*(): CursorPtr {.importc: "SDL_GetCursor".}
+proc freeCursor* (cursor: CursorPtr) {.importc: "SDL_FreeCursor".}
+proc showCursor* (toggle: bool): Bool32 {.importc: "SDL_ShowCursor", discardable.}
+
+
+# Function prototypes
+#*
+#   Pumps the event loop, gathering events from the input devices.
+#
+#   This function updates the event queue and internal input device state.
+#
+#   This should only be run in the thread that sets the video mode.
+#
+proc pumpEvents*() {.importc: "SDL_PumpEvents".}
+
+#*
+#   Checks the event queue for messages and optionally returns them.
+#
+#   If \c action is ::SDL_ADDEVENT, up to \c numevents events will be added to
+#   the back of the event queue.
+#
+#   If \c action is ::SDL_PEEKEVENT, up to \c numevents events at the front
+#   of the event queue, within the specified minimum and maximum type,
+#   will be returned and will not be removed from the queue.
+#
+#   If \c action is ::SDL_GETEVENT, up to \c numevents events at the front
+#   of the event queue, within the specified minimum and maximum type,
+#   will be returned and will be removed from the queue.
+#
+#   \return The number of events actually stored, or -1 if there was an error.
+#
+#   This function is thread-safe.
+#
+proc peepEvents*(events: ptr Event; numevents: cint; action: Eventaction;
+  minType: uint32; maxType: uint32): cint {.importc: "SDL_PeepEvents".}
+#@}
+#*
+#   Checks to see if certain event types are in the event queue.
+#
+proc hasEvent*(kind: uint32): Bool32 {.importc: "SDL_HasEvent".}
+proc hasEvents*(minType: uint32; maxType: uint32): Bool32 {.importc: "SDL_HasEvents".}
+proc flushEvent*(kind: uint32) {.importc: "SDL_FlushEvent".}
+proc flushEvents*(minType: uint32; maxType: uint32) {.importc: "SDL_FlushEvents".}
+
+proc pollEvent*(event: var Event): Bool32 {.importc: "SDL_PollEvent".}
+proc waitEvent*(event: var Event): Bool32 {.importc: "SDL_WaitEvent".}
+proc waitEventTimeout*(event: var Event; timeout: cint): Bool32 {.importc: "SDL_WaitEventTimeout".}
+#*
+#   \brief Add an event to the event queue.
+#
+#   \return 1 on success, 0 if the event was filtered, or -1 if the event queue
+#           was full or there was some other error.
+#
+proc pushEvent*(event: ptr Event): cint {.importc: "SDL_PushEvent".}
+
+#*
+proc setEventFilter*(filter: EventFilter; userdata: pointer) {.importc: "SDL_SetEventFilter".}
+#*
+#   Return the current event filter - can be used to "chain" filters.
+#   If there is no event filter set, this function returns SDL_FALSE.
+#
+proc getEventFilter*(filter: var EventFilter; userdata: var pointer): Bool32 {.importc: "SDL_GetEventFilter".}
+#*
+#   Add a function which is called when an event is added to the queue.
+#
+proc addEventWatch*(filter: EventFilter; userdata: pointer) {.importc: "SDL_AddEventWatch".}
+#*
+#   Remove an event watch function added with SDL_AddEventWatch()
+#
+proc delEventWatch*(filter: EventFilter; userdata: pointer) {.importc: "SDL_DelEventWatch".}
+#*
+#   Run the filter function on the current event queue, removing any
+#   events for which the filter returns 0.
+#
+proc filterEvents*(filter: EventFilter; userdata: pointer) {.importc: "SDL_FilterEvents".}
+#@{
+#
+#/**
+#   This function allows you to set the state of processing certain events.
+#    - If \c state is set to ::SDL_IGNORE, that event will be automatically
+#      dropped from the event queue and will not event be filtered.
+#    - If \c state is set to ::SDL_ENABLE, that event will be processed
+#      normally.
+#    - If \c state is set to ::SDL_QUERY, SDL_EventState() will return the
+#      current processing state of the specified event.
+#
+proc eventState*(kind: EventType; state: cint): uint8 {.importc: "SDL_EventState".}
+#@}
+#
+#/**
+#   This function allocates a set of user-defined events, and returns
+#   the beginning event number for that set of events.
+#
+#   If there aren't enough user-defined events left, this function
+#   returns (uint32)-1
+#
+proc registerEvents*(numevents: cint): uint32 {.importc: "SDL_RegisterEvents".}
+
+
+proc setError*(fmt: cstring) {.varargs, importc: "SDL_SetError".}
+proc getError*(): cstring {.importc: "SDL_GetError".}
+proc clearError*() {.importc: "SDL_ClearError".}
+
+#extern DECLSPEC const char* SDLCALL SDL_GetPixelFormatName(uint32 format);
+proc getPixelFormatName* (format: uint32): cstring {.
+  importc: "SDL_GetPixelFormatName".}
+  ## Get the human readable name of a pixel format
+
+#extern DECLSPEC SDL_bool SDLCALL SDL_PixelFormatEnumToMasks(uint32 format,
+#                                                            int *bpp,
+#                                                            uint32 * Rmask,
+#                                                            uint32 * Gmask,
+#                                                            uint32 * Bmask,
+#                                                            uint32 * Amask);
+proc pixelFormatEnumToMasks* (format: uint32; bpp: var cint;
+  Rmask, Gmask, Bmask, Amask: var uint32): bool {.
+  importc: "SDL_PixelFormatEnumToMasks".}
+  ##Convert one of the enumerated pixel formats to a bpp and RGBA masks.
+  ##Returns TRUE or FALSE if the conversion wasn't possible.
+
+
+#extern DECLSPEC uint32 SDLCALL SDL_MasksToPixelFormatEnum(int bpp,
+#                                                          uint32 Rmask,
+#                                                          uint32 Gmask,
+#                                                          uint32 Bmask,
+#                                                          uint32 Amask);
+proc masksToPixelFormatEnum* (bpp: cint; Rmask, Gmask, Bmask, Amask: uint32): uint32 {.
+  importc: "SDL_MasksToPixelFormatEnum".}
+  ##Convert a bpp and RGBA masks to an enumerated pixel format.
+  ##The pixel format, or ::SDL_PIXELFORMAT_UNKNOWN if the conversion wasn't possible.
+
+#extern DECLSPEC SDL_PixelFormat * SDLCALL SDL_AllocFormat(uint32 pixel_format);
+proc allocFormat* (pixelFormat: uint32): ptr PixelFormat {.
+  importc: "SDL_AllocFormat".}
+##Create an SDL_PixelFormat structure from a pixel format enum.
+
+#extern DECLSPEC void SDLCALL SDL_FreeFormat(SDL_PixelFormat *format);
+proc freeFormat* (format: ptr PixelFormat) {.
+  importc: "SDL_FreeFormat".}
+  ##Free an SDL_PixelFormat structure.
+
+#extern DECLSPEC SDL_Palette *SDLCALL SDL_AllocPalette(int ncolors);
+proc allocPalette* (numColors: cint): ptr Palette {.
+  importc: "SDL_AllocPalette".}
+  ##Create a palette structure with the specified number of color entries.
+  ##Returns A new palette, or NULL if there wasn't enough memory.
+  ##Note: The palette entries are initialized to white.
+
+#extern DECLSPEC int SDLCALL SDL_SetPixelFormatPalette(SDL_PixelFormat * format,
+#                                                      SDL_Palette *palette);
+proc setPixelFormatPalette* (format: ptr PixelFormat; palette: ptr Palette): cint {.
+  importc: "SDL_SetPixelFormatPalette".}
+  ##Set the palette for a pixel format structure.
+
+#extern DECLSPEC int SDLCALL SDL_SetPaletteColors(SDL_Palette * palette,
+#                                                 const SDL_Color * colors,
+#                                                 int firstcolor, int ncolors);
+proc setPaletteColors* (palette: ptr Palette; colors: ptr Color; first, numColors: cint): SDL_Return {.discardable,
+  importc: "SDL_SetPaletteColors".}
+  ## Set a range of colors in a palette.
+#extern DECLSPEC void SDLCALL SDL_FreePalette(SDL_Palette * palette);
+proc freePalette* (palette: ptr Palette) {.
+  importc: "SDL_FreePalette".}
+  ##Free a palette created with SDL_AllocPalette().
+
+#extern DECLSPEC uint32 SDLCALL SDL_MapRGB(const SDL_PixelFormat * format,
+#                                          uint8 r, uint8 g, uint8 b);
+proc mapRGB* (format: ptr PixelFormat; r,g,b: uint8): uint32 {.
+  importc: "SDL_MapRGB".}
+  ##Maps an RGB triple to an opaque pixel value for a given pixel format.
+
+#extern DECLSPEC uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormat * format,
+#                                           uint8 r, uint8 g, uint8 b,
+#                                           uint8 a);
+proc mapRGBA* (format: ptr PixelFormat; r,g,b,a: uint8): uint32 {.
+  importc: "SDL_MapRGBA".}
+  ##Maps an RGBA quadruple to a pixel value for a given pixel format.
+
+#extern DECLSPEC void SDLCALL SDL_GetRGB(uint32 pixel,
+#                                        const SDL_PixelFormat * format,
+#                                        uint8 * r, uint8 * g, uint8 * b);
+proc getRGB* (pixel: uint32; format: ptr PixelFormat; r,g,b: var uint8) {.
+  importc: "SDL_GetRGB".}
+  ##Get the RGB components from a pixel of the specified format.
+
+#extern DECLSPEC void SDLCALL SDL_GetRGBA(uint32 pixel,
+#                                         const SDL_PixelFormat * format,
+#                                         uint8 * r, uint8 * g, uint8 * b,
+#                                         uint8 * a);
+proc getRGBA* (pixel: uint32; format: ptr PixelFormat; r,g,b,a: var uint8) {.
+  importc: "SDL_GetRGBA".}
+  ##Get the RGBA components from a pixel of the specified format.
+
+#extern DECLSPEC void SDLCALL SDL_CalculateGammaRamp(float gamma, uint16 * ramp);
+proc calculateGammaRamp* (gamma: cfloat; ramp: ptr uint16) {.
+  importc: "SDL_CalculateGammaRamp".}
+  ##Calculate a 256 entry gamma ramp for a gamma value.
+
+# SDL_clipboard.h
+proc setClipboardText*(text: cstring): cint {.importc: "SDL_SetClipboardText".}
+proc getClipboardText*(): cstring {.importc: "SDL_GetClipboardText".}
+proc hasClipboardText*(): Bool32 {.importc: "SDL_HasClipboardText".}
+proc freeClipboardText*(text: cstring) {.importc: "SDL_free".}
+
+
+proc getNumTouchFingers*(id: TouchID): cint {.importc: "SDL_GetNumTouchFingers".}
+proc getTouchFinger*(id: TouchID, index: cint): ptr Finger {.importc: "SDL_GetTouchFinger".}
+
+# SDL_system.h
+when defined(windows):
+
+  proc direct3D9GetAdapterIndex* (displayIndex: cint): cint {.
+    importc: "SDL_Direct3D9GetAdapterIndex".}
+    ## Returns the D3D9 adapter index that matches the specified display index.
+    ## This adapter index can be passed to IDirect3D9::CreateDevice and controls
+    ## on which monitor a full screen application will appear.
+
+  #extern DECLSPEC IDirect3DDevice9* SDLCALL SDL_RenderGetD3D9Device(SDL_Renderer * renderer);
+  proc getD3D9Device* (renderer: RendererPtr): pointer {.
+    importc:"SDL_RenderGetD3D9Device".}
+    ## Returns the D3D device associated with a renderer, or NULL if it's not a D3D renderer.
+    ## Once you are done using the device, you should release it to avoid a resource leak.
+
+  #extern DECLSPEC void SDLCALL SDL_DXGIGetOutputInfo( int displayIndex, int *adapterIndex, int *outputIndex );
+  proc dXGIGetOutputInfo* (displayIndex: cint, adapterIndex,outputIndex: ptr cint) {.importc: "SDL_DXGIGetOutputInfo".}
+    ## Returns the DXGI Adapter and Output indices for the specified display index.
+    ## These can be passed to EnumAdapters and EnumOutputs respectively to get the objects
+    ## required to create a DX10 or DX11 device and swap chain.
+
+elif defined(iPhone) or defined(ios):
+
+
+  #extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(
+  #    SDL_Window * window, int interval,
+  #    void (*callback)(void*), void *callbackParam);
+  proc iPhoneSetAnimationCallback*(window: WindowPtr, interval:cint, callback: VoidCallback, callbackParam: pointer): cint {.
+    importc: "SDL_iPhoneSetAnimationCallback".}
+
+  #extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled);
+  proc iPhoneSetEventPump*(enabled: bool) {.
+    importc: "SDL_iPhoneSetEventPump".}
+
+  #extern DECLSPEC int SDLCALL SDL_iPhoneKeyboardShow(SDL_Window * window);
+  proc iPhoneKeyboardShow*(window:WindowPtr): cint {.
+    importc: "SDL_iPhoneKeyboardShow".}
+  #extern DECLSPEC int SDLCALL SDL_iPhoneKeyboardHide(SDL_Window * window);
+  proc iPhoneKeyboardHide*(window:WindowPtr): cint {.
+    importc: "SDL_iPhoneKeyboardHide".}
+  #extern DECLSPEC SDL_bool SDLCALL SDL_iPhoneKeyboardIsShown(SDL_Window * window);
+  proc iPhoneKeyboardIsShown*(window:WindowPtr): bool {.
+    importc: "SDL_iPhoneKeyboardIsShown".}
+  #extern DECLSPEC int SDLCALL SDL_iPhoneKeyboardToggle(SDL_Window * window);
+  proc iPhoneKeyboardToggle*(window:WindowPtr): cint {.
+    importc: "SDL_iPhoneKeyboardToggle".}
+
+elif defined(android):
+
+  #extern DECLSPEC void * SDLCALL SDL_AndroidGetJNIEnv();
+  proc androidGetJNIEnv*(): pointer {.importc: "SDL_AndroidGetJNIEnv".}
+
+  #extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity();
+  proc androidGetActivity*(): pointer {.importc: "SDL_AndroidGetActivity".}
+
+  #extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState();
+  proc androidGetExternalStorageState*(): cint {.
+    importc: "SDL_AndroidGetExternalStorageState".}
+
+  #extern DECLSPEC const char * SDLCALL SDL_AndroidGetInternalStoragePath();
+  proc androidGetInternalStoragePath* (): cstring {.
+    importc: "SDL_AndroidGetInternalStoragePath".}
+
+  #extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath();
+  proc androidGetExternalStoragePath* (): cstring {.
+    importc: "SDL_AndroidGetExternalStoragePath".}
+
+const
+  SDL_QUERY* = -1
+  SDL_IGNORE* = 0
+  SDL_DISABLE* = 0
+  SDL_ENABLE* = 1
+
+##define SDL_GetEventState(type) SDL_EventState(type, SDL_QUERY)
+proc getEventState*(kind: EventType): uint8 {.inline.} = eventState(kind, SDL_QUERY)
+
+##define SDL_BUTTON(X)          (1 << ((X)-1))
+template SDL_BUTTON*(x: uint8): uint8 = (1'u8 shl (x - 1'u8))
+const
+  BUTTON_LEFT* = 1'u8
+  BUTTON_MIDDLE* = 2'u8
+  BUTTON_RIGHT* = 3'u8
+  BUTTON_X1* = 4'u8
+  BUTTON_X2* = 5'u8
+  BUTTON_LMASK* = SDL_BUTTON(BUTTON_LEFT)
+  BUTTON_MMASK* = SDL_BUTTON(BUTTON_MIDDLE)
+  BUTTON_RMASK* = SDL_BUTTON(BUTTON_RIGHT)
+  BUTTON_X1MASK* = SDL_BUTTON(BUTTON_X1)
+  BUTTON_X2MASK* = SDL_BUTTON(BUTTON_X2)
+
+const SDL_TOUCH_MOUSEID* = high(uint32)
+
+## compatibility functions
+
+proc createRGBSurface* (width, height, depth: int32): SurfacePtr {.inline.} = sdl2.createRGBSurface(
+  0, width, height, depth, 0,0,0,0)
+proc getSize*(window: WindowPtr): Point {.inline.} = getSize(window, result.x, result.y)
+
+proc destroyTexture*(texture: TexturePtr) {.inline.} = destroy(texture)
+#proc destroy* (texture: TexturePtr) {.inline.} = texture.destroyTexture
+proc destroyRenderer*(renderer: RendererPtr) {.inline.} = destroy(renderer)
+#proc destroy* (renderer: RendererPtr) {.inline.} = renderer.destroyRenderer
+
+proc destroy* (window: WindowPtr) {.inline.} = window.destroyWindow
+proc destroy* (cursor: CursorPtr) {.inline.} = cursor.freeCursor
+proc destroy* (surface: SurfacePtr) {.inline.} = surface.freeSurface
+proc destroy* (format: ptr PixelFormat) {.inline.} = format.freeFormat
+proc destroy* (palette: ptr Palette) {.inline.} = palette.freePalette
+
+proc blitSurface*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr;
+  dstrect: ptr Rect): SDL_Return {.inline, discardable.} = upperBlit(src, srcrect, dst, dstrect)
+proc blitScaled*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr;
+  dstrect: ptr Rect): SDL_Return {.inline, discardable.} = upperBlitScaled(src, srcrect, dst, dstrect)
+
+#proc init*(flags: cint): SDL_Return {.inline, deprecated.} = sdl2.init(flags)
+#proc quit*() {.inline,deprecated.} = sdl2.quit()
+
+#/#define SDL_LoadBMP(file)     SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)
+proc loadBMP*(file: string): SurfacePtr {.inline.} = loadBMP_RW(rwFromFile(cstring(file), "rb"), 1)
+##define SDL_SaveBMP(surface, file) \
+#  SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1)
+proc saveBMP*(surface: SurfacePtr; file: string): SDL_Return {.
+  inline, discardable.} = saveBMP_RW(surface, rwFromFile(file, "wb"), 1)
+
+proc color*(r, g, b, a: range[0..255]): Color = (r.uint8, g.uint8, b.uint8, a.uint8)
+
+proc rect*(x, y: cint; w = cint(0), h = cint(0)): Rect =
+  result.x = x
+  result.y = y
+  result.w = w
+  result.h = h
+
+proc point*[T: SomeNumber](x, y: T): Point = (x.cint, y.cint)
+
+proc contains*(some: Rect; point: Point): bool =
+  return point.x >= some.x and point.x <= (some.x + some.w) and
+          point.y >= some.y and point.y <= (some.y + some.h)
+
+const
+  HINT_RENDER_SCALE_QUALITY* = "SDL_RENDER_SCALE_QUALITY"
+
+proc setHint*(name: cstring, value: cstring): bool {.
+  importc: "SDL_SetHint".}
+
+proc setHintWithPriority*(name: cstring, value: cstring, priority: cint): bool {.
+  importc: "SDL_SetHintWithPriority".}
+
+proc getHint*(name: cstring): cstring {.
+  importc: "SDL_GetHint".}
+
+proc size* (ctx:RWopsPtr): int64 {.inline.} =
+  ctx.size(ctx)
+proc seek* (ctx:RWopsPtr; offset:int64; whence:cint): int64 {.inline.} =
+  ctx.seek(ctx,offset,whence)
+proc read* (ctx:RWopsPtr; `ptr`: pointer; size,maxnum:csize_t): csize_t{.inline.} =
+  ctx.read(ctx, `ptr`, size, maxnum)
+proc write* (ctx:RWopsPtr; `ptr`:pointer; size,num:csize_t): csize_t{.inline.} =
+  ctx.write(ctx, `ptr`, size, num)
+proc close* (ctx:RWopsPtr): cint {.inline.} =
+  ctx.close(ctx)
+
+when not defined(SDL_Static):
+  {.pop.}
+
+let defaultEvent* = Event(kind: QuitEvent)
+  ## a default "initialized" Event

+ 677 - 0
src/nodesnim/thirdparty/sdl2/audio.nim

@@ -0,0 +1,677 @@
+import sdl2
+#
+#  Simple DirectMedia Layer
+#  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+#
+#  This software is provided 'as-is', without any express or implied
+#  warranty.  In no event will the authors be held liable for any damages
+#  arising from the use of this software.
+#
+#  Permission is granted to anyone to use this software for any purpose,
+#  including commercial applications, and to alter it and redistribute it
+#  freely, subject to the following restrictions:
+#
+#  1. The origin of this software must not be misrepresented; you must not
+#     claim that you wrote the original software. If you use this software
+#     in a product, an acknowledgment in the product documentation would be
+#     appreciated but is not required.
+#  2. Altered source versions must be plainly marked as such, and must not be
+#     misrepresented as being the original software.
+#  3. This notice may not be removed or altered from any source distribution.
+#
+#*
+#   \file SDL_audio.h
+#
+#   Access to the raw audio mixing buffer for the SDL library.
+#
+
+# Set up for C function definitions, even when using C++
+#*
+#   \brief Audio format flags.
+#
+#   These are what the 16 bits in 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.
+#
+type
+  AudioFormat* = uint16
+#*
+#   \name Audio flags
+#
+# @{
+const
+  SDL_AUDIO_MASK_BITSIZE*  = uint32(0x000000FF)
+  SDL_AUDIO_MASK_DATATYPE* = uint32(1 shl 8)
+  SDL_AUDIO_MASK_ENDIAN*   = uint32(1 shl 12)
+  SDL_AUDIO_MASK_SIGNED*   = uint32(1 shl 15)
+
+template SDL_AUDIO_BITSIZE*(x: uint32): uint32 =
+  (x and SDL_AUDIO_MASK_BITSIZE)
+
+template SDL_AUDIO_ISFLOAT*(x: uint32): bool =
+  (x and SDL_AUDIO_MASK_DATATYPE) != 0
+
+template SDL_AUDIO_ISBIGENDIAN*(x: uint32): bool =
+  (x and SDL_AUDIO_MASK_ENDIAN) != 0
+
+template SDL_AUDIO_ISSIGNED*(x: uint32): bool =
+  (x and SDL_AUDIO_MASK_SIGNED) != 0
+
+template SDL_AUDIO_ISINT*(x: uint32): bool =
+  not SDL_AUDIO_ISFLOAT(x)
+
+template SDL_AUDIO_ISLITTLEENDIAN*(x: uint32): bool =
+  not SDL_AUDIO_ISBIGENDIAN(x)
+
+template SDL_AUDIO_ISUNSIGNED*(x: uint32): bool =
+  not SDL_AUDIO_ISSIGNED(x)
+
+#*
+#   \name Audio format flags
+#
+#   Defaults to LSB byte order.
+#
+# @{
+const
+  AUDIO_U8* = 0x00000008    #*< Unsigned 8-bit samples
+  AUDIO_S8* = 0x00008008    #*< Signed 8-bit samples
+  AUDIO_U16LSB* = 0x00000010 #*< Unsigned 16-bit samples
+  AUDIO_S16LSB* = 0x00008010 #*< Signed 16-bit samples
+  AUDIO_U16MSB* = 0x00001010 #*< As above, but big-endian byte order
+  AUDIO_S16MSB* = 0x00009010 #*< As above, but big-endian byte order
+  AUDIO_U16* = AUDIO_U16LSB
+  AUDIO_S16* = AUDIO_S16LSB
+
+# @}
+#*
+#   \name int32 support
+#
+# @{
+const
+  AUDIO_S32LSB* = 0x00008020 #*< 32-bit integer samples
+  AUDIO_S32MSB* = 0x00009020 #*< As above, but big-endian byte order
+  AUDIO_S32* = AUDIO_S32LSB
+# @}
+#*
+#   \name float32 support
+#
+# @{
+const
+  AUDIO_F32LSB* = 0x00008120 #*< 32-bit floating point samples
+  AUDIO_F32MSB* = 0x00009120 #*< As above, but big-endian byte order
+  AUDIO_F32* = AUDIO_F32LSB
+# @}
+#*
+#   \name Native audio byte ordering
+#
+# @{
+when false:
+  ## TODO system.cpuEndian
+  when SDL_BYTEORDER == SDL_LIL_ENDIAN:
+    const
+      AUDIO_U16SYS* = AUDIO_U16LSB
+      AUDIO_S16SYS* = AUDIO_S16LSB
+      AUDIO_S32SYS* = AUDIO_S32LSB
+      AUDIO_F32SYS* = AUDIO_F32LSB
+  else:
+    const
+      AUDIO_U16SYS* = AUDIO_U16MSB
+      AUDIO_S16SYS* = AUDIO_S16MSB
+      AUDIO_S32SYS* = AUDIO_S32MSB
+      AUDIO_F32SYS* = AUDIO_F32MSB
+# @}
+#*
+#   \name Allow change flags
+#
+#   Which audio format changes are allowed when opening a device.
+#
+# @{
+const
+  SDL_AUDIO_ALLOW_FREQUENCY_CHANGE* = 0x00000001
+  SDL_AUDIO_ALLOW_FORMAT_CHANGE* = 0x00000002
+  SDL_AUDIO_ALLOW_CHANNELS_CHANGE* = 0x00000004
+  SDL_AUDIO_ALLOW_ANY_CHANGE* = (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE or
+      SDL_AUDIO_ALLOW_FORMAT_CHANGE or SDL_AUDIO_ALLOW_CHANNELS_CHANGE)
+# @}
+# @}
+# Audio flags
+#*
+#   This function is called when the audio device needs more data.
+#
+#   \param userdata An application-specific parameter saved in
+#                   the AudioSpec structure
+#   \param stream A pointer to the audio data buffer.
+#   \param len    The length of that buffer in bytes.
+#
+#   Once the callback returns, the buffer will no longer be valid.
+#   Stereo samples are stored in a LRLRLR ordering.
+#
+type
+  AudioCallback* = proc (userdata: pointer; stream: ptr uint8; len: cint) {.cdecl.}
+#*
+#   The calculated values in this structure are calculated by SDL_OpenAudio().
+#
+type
+  AudioSpec* = object
+    freq*: cint             #*< DSP frequency -- samples per second
+    format*: AudioFormat #*< Audio data format
+    channels*: uint8        #*< Number of channels: 1 mono, 2 stereo
+    silence*: uint8         #*< Audio buffer silence value (calculated)
+    samples*: uint16        #*< Audio buffer size in samples (power of 2)
+    padding*: uint16        #*< Necessary for some compile environments
+    size*: uint32           #*< Audio buffer size in bytes (calculated)
+    callback*: AudioCallback
+    userdata*: pointer
+
+  AudioCVT* {.packed.} = object
+    needed*: cint           #*< Set to 1 if conversion possible
+    src_format*: AudioFormat #*< Source audio format
+    dst_format*: AudioFormat #*< Target audio format
+    rate_incr*: cdouble     #*< Rate conversion increment
+    buf*: ptr uint8         #*< Buffer to hold entire audio data
+    len*: cint              #*< Length of original audio buffer
+    len_cvt*: cint          #*< Length of converted audio buffer
+    len_mult*: cint         #*< buffer must be len*len_mult big
+    len_ratio*: cdouble     #*< Given len, final size is len*len_ratio
+    filters*: array[10, AudioFilter] #*< Filter list
+    filter_index*: cint     #*< Current audio conversion function
+
+  AudioFilter* = proc (cvt: ptr AudioCVT; format: AudioFormat){.cdecl.}
+
+type
+  AudioStream = object
+    # The AudioStream object. SDL2 doesn't make the contents of this object
+    # visible to users of the C API, so we don't make it visible either.
+    cvt_before_resampling*: AudioCVT
+    cvt_after_resampling*: AudioCVT
+    queue*: pointer
+    first_run*: Bool32
+    staging_buffer*: ptr uint8
+    staging_buffer_size*: cint
+    staging_buffer_filled*: cint
+    work_buffer_base*: ptr uint8  # maybe unaligned pointer from SDL_realloc().
+    work_buffer_len*: cint
+    src_sample_frame_size*: cint
+    src_format*: AudioFormat
+    src_channels*: uint8
+    src_rate*: cint
+    dst_sample_frame_size*: cint
+    dst_format*: AudioFormat
+    dst_channels*: uint8
+    dst_rate*: cint
+    rate_incr*: cdouble
+    pre_resample_channels*: uint8
+    packetlen*: cint
+    resampler_padding_samples*: cint
+    resampler_padding*: ptr cfloat
+    resampler_state*: pointer
+    resampler_func*: proc(stream: AudioStreamPtr, inbuf: pointer, inbuflen: cint, outbuf: pointer, outbuflen: cint): cint
+    reset_resampler_func*: proc(stream: AudioStreamPtr)
+    cleanup_resampler_func*: proc(stream: AudioStreamPtr)
+  
+  AudioStreamPtr* = ptr AudioStream
+    ## (Available since SDL 2.0.7)
+    ## A pointer to an `SDL_AudioStream`_. Audio streams were added to SDL2
+    ## in version 2.0.7, to provide an easier-to-use alternative to 
+    ## `SDL_AudioCVT`_.
+    ##
+    ## .. _SDL_AudioStream: https://wiki.libsdl.org/Tutorials/AudioStream
+    ## .. _SDL_AudioCVT: https://wiki.libsdl.org/SDL_AudioCVT
+    ##
+    ## See Also:
+    ## * `newAudioStream proc<#newAudioStream,AudioFormat,uint8,cint,AudioFormat,uint8,cint>`_
+    ## * `newAudioStream proc<#newAudioStream,AudioSpec,AudioSpec>`_
+    ## * `put proc<#put,AudioStreamPtr,pointer,cint>`_
+    ## * `get proc<#get,AudioStreamPtr,pointer,cint>`_
+    ## * `available proc<#available,AudioStreamPtr>`_
+    ## * `flush proc<#flush,AudioStreamPtr>`_
+    ## * `clear proc<#clear,AudioStreamPtr>`_
+    ## * `destroy proc<#destroy,AudioStreamPtr>`_
+
+when false:
+  #*
+  #   A structure to hold a set of audio conversion filters and buffers.
+  #
+  when defined(GNUC):#__GNUC__):
+    # This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't
+    #   pad it out to 88 bytes to guarantee ABI compatibility between compilers.
+    #   vvv
+    #   The next time we rev the ABI, make sure to size the ints and add padding.
+    #
+    const
+      AudioCVT_PACKED* = x#__attribute__((packed))
+  else:
+    const
+      AudioCVT_PACKED* = true
+
+#*
+#   SDL Audio Device IDs.
+#
+#   A successful call to SDL_OpenAudio() is always device id 1, and legacy
+#   SDL audio APIs assume you want this device ID. SDL_OpenAudioDevice() calls
+#   always returns devices >= 2 on success. The legacy calls are good both
+#   for backwards compatibility and when you don't care about multiple,
+#   specific, or capture devices.
+#
+type
+  AudioDeviceID* = uint32
+
+#*
+#   \name Audio state
+#
+#   Get the current audio state.
+#
+# @{
+type
+  AudioStatus* {.size: sizeof(cint).} = enum
+    SDL_AUDIO_STOPPED = 0, SDL_AUDIO_PLAYING, SDL_AUDIO_PAUSED
+const
+  SDL_MIX_MAXVOLUME* = 128
+
+when defined(SDL_Static):
+  static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2."
+else:
+  {.push callConv: cdecl, dynlib: LibName.}
+
+# Function prototypes
+#*
+#   \name Driver discovery functions
+#
+#   These functions return the list of built in audio drivers, in the
+#   order that they are normally initialized by default.
+#
+# @{
+proc getNumAudioDrivers*(): cint {.
+  importc: "SDL_GetNumAudioDrivers".}
+proc getAudioDriver*(index: cint): cstring {.
+  importc: "SDL_GetAudioDriver".}
+# @}
+#*
+#   \name Initialization and cleanup
+#
+#   \internal These functions are used internally, and should not be used unless
+#             you have a specific need to specify the audio driver you want to
+#             use.  You should normally use SDL_Init() or SDL_InitSubSystem().
+#
+# @{
+proc audioInit*(driver_name: cstring): cint {.
+  importc: "SDL_AudioInit".}
+proc audioQuit*() {.
+  importc: "SDL_AudioQuit".}
+# @}
+#*
+#   This function returns the name of the current audio driver, or NULL
+#   if no driver has been initialized.
+#
+proc getCurrentAudioDriver*(): cstring {.
+  importc: "SDL_GetCurrentAudioDriver".}
+#*
+#   This function opens the audio device with the desired parameters, and
+#   returns 0 if successful, placing the actual hardware parameters in the
+#   structure pointed to by \c obtained.  If \c obtained is NULL, the audio
+#   data passed to the callback function will be guaranteed to be in the
+#   requested format, and will be automatically converted to the hardware
+#   audio format if necessary.  This function returns -1 if it failed
+#   to open the audio device, or couldn't set up the audio thread.
+#
+#   When filling in the desired audio spec structure,
+#     - \c desired->freq should be the desired audio frequency in samples-per-
+#       second.
+#     - \c desired->format should be the desired audio format.
+#     - \c desired->samples is the desired size of the audio buffer, in
+#       samples.  This number should be a power of two, and may be adjusted by
+#       the audio driver to a value more suitable for the hardware.  Good values
+#       seem to range between 512 and 8096 inclusive, depending on the
+#       application and CPU speed.  Smaller values yield faster response time,
+#       but can lead to underflow if the application is doing heavy processing
+#       and cannot fill the audio buffer in time.  A stereo sample consists of
+#       both right and left channels in LR ordering.
+#       Note that the number of samples is directly related to time by the
+#       following formula:  \code ms = (samples*1000)/freq \endcode
+#     - \c desired->size is the size in bytes of the audio buffer, and is
+#       calculated by SDL_OpenAudio().
+#     - \c desired->silence is the value used to set the buffer to silence,
+#       and is calculated by SDL_OpenAudio().
+#     - \c desired->callback should be set to a function that will be called
+#       when the audio device is ready for more data.  It is passed a pointer
+#       to the audio buffer, and the length in bytes of the audio buffer.
+#       This function usually runs in a separate thread, and so you should
+#       protect data structures that it accesses by calling SDL_LockAudio()
+#       and SDL_UnlockAudio() in your code.
+#     - \c desired->userdata is passed as the first parameter to your callback
+#       function.
+#
+#   The audio device starts out playing silence when it's opened, and should
+#   be enabled for playing by calling \c SDL_PauseAudio(0) when you are ready
+#   for your audio callback function to be called.  Since the audio driver
+#   may modify the requested size of the audio buffer, you should allocate
+#   any local mixing buffers after you open the audio device.
+#
+proc openAudio*(desired: ptr AudioSpec; obtained: ptr AudioSpec): cint {.
+  importc: "SDL_OpenAudio".}
+
+#*
+#   Get the number of available devices exposed by the current driver.
+#   Only valid after a successfully initializing the audio subsystem.
+#   Returns -1 if an explicit list of devices can't be determined; this is
+#   not an error. For example, if SDL is set up to talk to a remote audio
+#   server, it can't list every one available on the Internet, but it will
+#   still allow a specific host to be specified to SDL_OpenAudioDevice().
+#
+#   In many common cases, when this function returns a value <= 0, it can still
+#   successfully open the default device (NULL for first argument of
+#   SDL_OpenAudioDevice()).
+#
+proc getNumAudioDevices*(iscapture: cint): cint {.
+  importc: "SDL_GetNumAudioDevices".}
+#*
+#   Get the human-readable name of a specific audio device.
+#   Must be a value between 0 and (number of audio devices-1).
+#   Only valid after a successfully initializing the audio subsystem.
+#   The values returned by this function reflect the latest call to
+#   SDL_GetNumAudioDevices(); recall that function to redetect available
+#   hardware.
+#
+#   The string returned by this function is UTF-8 encoded, read-only, and
+#   managed internally. You are not to free it. If you need to keep the
+#   string for any length of time, you should make your own copy of it, as it
+#   will be invalid next time any of several other SDL functions is called.
+#
+proc getAudioDeviceName*(index: cint; iscapture: cint): cstring {.
+  importc: "SDL_GetAudioDeviceName".}
+#*
+#   Open a specific audio device. Passing in a device name of NULL requests
+#   the most reasonable default (and is equivalent to calling SDL_OpenAudio()).
+#
+#   The device name is a UTF-8 string reported by SDL_GetAudioDeviceName(), but
+#   some drivers allow arbitrary and driver-specific strings, such as a
+#   hostname/IP address for a remote audio server, or a filename in the
+#   diskaudio driver.
+#
+#   \return 0 on error, a valid device ID that is >= 2 on success.
+#
+#   SDL_OpenAudio(), unlike this function, always acts on device ID 1.
+#
+proc openAudioDevice*(device: cstring; iscapture: cint;
+                      desired: ptr AudioSpec;
+                      obtained: ptr AudioSpec; allowed_changes: cint): AudioDeviceID {.
+  importc: "SDL_OpenAudioDevice".}
+
+proc getAudioStatus*(): AudioStatus {.
+  importc: "SDL_GetAudioStatus".}
+proc getAudioDeviceStatus*(dev: AudioDeviceID): AudioStatus {.
+  importc: "SDL_GetAudioDeviceStatus".}
+
+#*
+#   \brief Use this function to get the number of bytes of still-queued audio.
+#
+#   \param dev the device ID of which we will query queued audio size
+#
+#   \return the number of bytes (not samples!) of queued audio.
+#
+#   \sa SDL_GetQueuedAudioSize()
+#
+proc getQueuedAudioSize*(dev: AudioDeviceID): uint32 {.
+  importc: "SDL_GetQueuedAudioSize".}
+
+#*
+#   \brief Use this function to queue more audio on non-callback devices.
+#
+#   \param dev  the device ID to which we will queue audio
+#   \param data the data to queue to the device for later playback
+#   \param len  the number of bytes (not samples!) to which (data) points
+#
+#   \return 0 on success or a negative error code on failure; call SDL_GetError() for more information.
+#
+#   \sa SDL_QueueAudio()
+#
+proc queueAudio*(dev: AudioDeviceID, data: pointer, len: uint32): cint {.
+  importc: "SDL_QueueAudio".}
+
+# @}
+# Audio State
+#*
+#   \name Pause audio functions
+#
+#   These functions pause and unpause the audio callback processing.
+#   They should be called with a parameter of 0 after opening the audio
+#   device to start playing sound.  This is so you can safely initialize
+#   data for your callback function after opening the audio device.
+#   Silence will be written to the audio device during the pause.
+#
+# @{
+proc pauseAudio*(pause_on: cint) {.
+  importc: "SDL_PauseAudio".}
+proc pauseAudioDevice*(dev: AudioDeviceID; pause_on: cint) {.
+  importc: "SDL_PauseAudioDevice".}
+# @}
+# Pause audio functions
+#*
+#   This function loads a WAVE from the data source, automatically freeing
+#   that source if \c freesrc is non-zero.  For example, to load a WAVE file,
+#   you could do:
+#   \code
+#       SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...);
+#   \endcode
+#
+#   If this function succeeds, it returns the given AudioSpec,
+#   filled with the audio data format of the wave data, and sets
+#   \c *audio_buf to a malloc()'d buffer containing the audio data,
+#   and sets \c *audio_len to the length of that audio buffer, in bytes.
+#   You need to free the audio buffer with SDL_FreeWAV() when you are
+#   done with it.
+#
+#   This function returns NULL and sets the SDL error message if the
+#   wave file cannot be opened, uses an unknown data format, or is
+#   corrupt.  Currently raw and MS-ADPCM WAVE files are supported.
+#
+
+proc loadWAV_RW*(src: ptr RWops; freesrc: cint;
+                 spec: ptr AudioSpec; audio_buf: ptr ptr uint8;
+                 audio_len: ptr uint32): ptr AudioSpec {.
+  importc: "SDL_LoadWAV_RW".}
+
+#*
+#   Loads a WAV from a file.
+#   Compatibility convenience function.
+#
+template loadWAV*(file: string, spec: ptr AudioSpec, audio_buf: ptr ptr uint8, audio_len: ptr uint32): ptr AudioSpec =
+  loadWAV_RW(rwFromFile(file, "rb"), 1, spec, audio_buf, audio_len)
+
+#*
+#   This function frees data previously allocated with SDL_LoadWAV_RW()
+#
+proc freeWAV*(audio_buf: ptr uint8) {.
+  importc: "SDL_FreeWAV".}
+#*
+#   This function takes a source format and rate and a destination format
+#   and rate, and initializes the \c cvt structure with information needed
+#   by SDL_ConvertAudio() to convert a buffer of audio data from one format
+#   to the other.
+#
+#   \return -1 if the format conversion is not supported, 0 if there's
+#   no conversion needed, or 1 if the audio filter is set up.
+#
+proc buildAudioCVT*(cvt: ptr AudioCVT; src_format: AudioFormat;
+                        src_channels: uint8; src_rate: cint;
+                        dst_format: AudioFormat; dst_channels: uint8;
+                        dst_rate: cint): cint {.
+  importc: "SDL_BuildAudioCVT".}
+#*
+#   Once you have initialized the \c cvt structure using SDL_BuildAudioCVT(),
+#   created an audio buffer \c cvt->buf, and filled it with \c cvt->len bytes of
+#   audio data in the source format, this function will convert it in-place
+#   to the desired format.
+#
+#   The data conversion may expand the size of the audio data, so the buffer
+#   \c cvt->buf should be allocated after the \c cvt structure is initialized by
+#   SDL_BuildAudioCVT(), and should be \c cvt->len*cvt->len_mult bytes long.
+#
+proc convertAudio*(cvt: ptr AudioCVT): cint {.
+  importc: "SDL_ConvertAudio".}
+
+#*
+#   This takes two audio buffers of the playing audio format and mixes
+#   them, performing addition, volume adjustment, and overflow clipping.
+#   The volume ranges from 0 - 128, and should be set to ::SDL_MIX_MAXVOLUME
+#   for full audio volume.  Note this does not change hardware volume.
+#   This is provided for convenience -- you can mix your own audio data.
+#
+proc mixAudio*(dst: ptr uint8; src: ptr uint8; len: uint32; volume: cint) {.
+  importc: "SDL_MixAudio".}
+#*
+#   This works like SDL_MixAudio(), but you specify the audio format instead of
+#   using the format of audio device 1. Thus it can be used when no audio
+#   device is open at all.
+#
+proc mixAudioFormat*(dst: ptr uint8; src: ptr uint8;
+                         format: AudioFormat; len: uint32; volume: cint) {.
+  importc: "SDL_MixAudioFormat".}
+#*
+#   \name Audio lock functions
+#
+#   The lock manipulated by these functions protects the callback function.
+#   During a SDL_LockAudio()/SDL_UnlockAudio() pair, you can be guaranteed that
+#   the callback function is not running.  Do not call these from the callback
+#   function or you will cause deadlock.
+#
+# @{
+proc lockAudio*() {.
+  importc: "SDL_LockAudio".}
+proc lockAudioDevice*(dev: AudioDeviceID) {.
+  importc: "SDL_LockAudioDevice".}
+proc unlockAudio*() {.
+  importc: "SDL_UnlockAudio".}
+proc unlockAudioDevice*(dev: AudioDeviceID) {.
+  importc: "SDL_UnlockAudioDevice".}
+# @}
+# Audio lock functions
+#*
+#   This function shuts down audio processing and closes the audio device.
+#
+proc closeAudio*() {.
+  importc: "SDL_CloseAudio".}
+proc closeAudioDevice*(dev: AudioDeviceID) {.
+  importc: "SDL_CloseAudioDevice".}
+# Ends C function definitions when using C++
+
+
+proc newAudioStream*(
+  src_format: AudioFormat;
+  src_channels: uint8;
+  src_rate: cint;
+  dst_format: AudioFormat;
+  dst_channels: uint8;
+  dst_rate: cint): AudioStreamPtr {.importc: "SDL_NewAudioStream".}
+  ## (Available since SDL 2.0.7)
+  ## Create a new audio stream. return 0 on success, or -1
+  ## on error.
+  ## 
+  ## Parameters:
+  ## * `src_format` The format of the source audio
+  ## * `src_channels` The number of channels of the source audio
+  ## * `src_rate` The sampling rate of the source audio
+  ## * `dst_format` The format of the desired audio output
+  ## * `dst_channels` The number of channels of the desired audio output
+  ## * `dst_rate The` sampling rate of the desired audio output
+  ##
+  ## See also:
+  ## * `AudioStreamPtr type<#AudioStreamPtr>`_
+  ## * `newAudioStream proc<#newAudioStream,AudioSpec,AudioSpec>`_
+
+proc newAudioStream*(srcSpec, destSpec: AudioSpec): AudioStreamPtr =
+  ## (Available since SDL 2.0.7)
+  ## Create a new audio stream that converts from `srcSpec` to `destSpec`.
+  ##
+  ## See also:
+  ## * `AudioStreamPtr type<#AudioStreamPtr>`_
+  ## * `newAudioStream proc<#newAudioStream,AudioFormat,uint8,cint,AudioFormat,uint8,cint>`_
+  newAudioStream(
+    srcSpec.format, srcSpec.channels, srcSpec.freq,
+    destSpec.format, destSpec.channels, destSpec.freq)
+
+proc put*(
+  stream: AudioStreamPtr,
+  buf: pointer,
+  len: cint): cint {.importc: "SDL_AudioStreamPut".}
+  ## (Available since SDL 2.0.7)
+  ## Add data to be converted/resampled to the stream. Returns 0 on success, or -1 on error.
+  ## 
+  ## Parameters:
+  ## * `stream` The stream the audio data is being added to
+  ## * `buf` A pointer to the audio data to add
+  ## * `len` The number of bytes to write to the stream
+  ##
+  ## See also:
+  ## * `AudioStreamPtr type<#AudioStreamPtr>`_
+
+proc get*(
+  stream: AudioStreamPtr,
+  buf: pointer,
+  len: cint): cint {.importc: "SDL_AudioStreamGet".}
+  ## (Available since SDL 2.0.7)
+  ## Get converted/resampled data from the stream.
+  ## Returns the number of bytes read from the stream, or -1 on error.
+  ## 
+  ## Parameters:
+  ## * `stream` The stream the audio is being requested from
+  ## * `buf` A buffer to fill with audio data
+  ## * `len` The maximum number of bytes to fill
+  ##
+  ## See also:
+  ## * `AudioStreamPtr type<#AudioStreamPtr>`_
+
+proc available*(stream: AudioStreamPtr): cint {.importc: "SDL_AudioStreamAvailable".}
+  ## (Available since SDL 2.0.7)
+  ## Get the number of converted/resampled bytes available (BYTES, not samples!).
+  ## The stream may be buffering data behind the scenes until it has enough to
+  ## resample correctly, so this number might be lower than what you expect, or even
+  ## be zero. Add more data or flush the stream if you need the data now.
+  ##
+  ## See also:
+  ## * `AudioStreamPtr type<#AudioStreamPtr>`_
+
+proc flush*(stream: AudioStreamPtr): cint {.importc: "SDL_AudioStreamFlush".}
+  ## (Available since SDL 2.0.7)
+  ## Tell the stream that you're done sending data, and anything being buffered
+  ## should be converted/resampled and made available immediately. Returns 0
+  ## on success, -1 on error.
+  ##
+  ## It is legal to add more data to a stream after flushing, but there will
+  ## be audio gaps in the output. Generally this is intended to signal the
+  ## end of input, so the complete output becomes available.
+  ##
+  ## See also:
+  ## * `AudioStreamPtr type<#AudioStreamPtr>`_
+
+proc clear*(stream: AudioStreamPtr) {.importc: "SDL_AudioStreamClear".}
+  ## (Available since SDL 2.0.7)
+  ## Clear any pending data in the stream without converting it.
+  ##
+  ## See also:
+  ## * `AudioStreamPtr type<#AudioStreamPtr>`_
+
+proc destroy*(stream: AudioStreamPtr) {.importc: "SDL_FreeAudioStream".}
+  ## (Available since SDL 2.0.7)
+  ## Free an audio stream.
+  ##
+  ## See also:
+  ## * `AudioStreamPtr type<#AudioStreamPtr>`_
+
+
+# vi: set ts=4 sw=4 expandtab:
+when not defined(SDL_Static):
+  {.pop.}

+ 294 - 0
src/nodesnim/thirdparty/sdl2/gamecontroller.nim

@@ -0,0 +1,294 @@
+import "../sdl2"
+import "joystick"
+
+discard """
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+
+
+\file SDL_gamecontroller.h
+
+Include file for SDL game controller event handling
+
+"""
+
+##
+#   \file SDL_gamecontroller.h
+#
+#   In order to use these functions, SDL_Init() must have been called
+#   with the ::SDL_INIT_JOYSTICK flag.  This causes SDL to scan the system
+#   for game controllers, and load appropriate drivers.
+#
+#   If you would like to receive controller updates while the application
+#   is in the background, you should set the following hint before calling
+#   SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS
+#
+
+# The gamecontroller structure used to identify an SDL game controller# /
+type
+  GameController* = object
+  GameControllerPtr* = ptr GameController
+
+  GameControllerBindType* {.size: sizeof(cint).} = enum
+    SDL_CONTROLLER_BINDTYPE_NONE,
+    SDL_CONTROLLER_BINDTYPE_BUTTON,
+    SDL_CONTROLLER_BINDTYPE_AXIS,
+    SDL_CONTROLLER_BINDTYPE_HAT
+
+# Get the SDL joystick layer binding for this controller button/axis mapping
+
+type
+  GameControllerButtonBind* = object
+    case bindType*: GameControllerBindType
+      of SDL_CONTROLLER_BINDTYPE_NONE:
+        nil
+      of SDL_CONTROLLER_BINDTYPE_BUTTON:
+        button*: cint
+      of SDL_CONTROLLER_BINDTYPE_AXIS:
+        axis*: cint
+      of SDL_CONTROLLER_BINDTYPE_HAT:
+        hat*, hatMask*: cint
+
+when defined(SDL_Static):
+  static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2."
+else:
+  {.push callConv: cdecl, dynlib: LibName.}
+
+##
+#  To count the number of game controllers in the system for the following:
+#  int nJoysticks = SDL_NumJoysticks();
+#  int nGameControllers = 0;
+#  for ( int i = 0; i < nJoysticks; i++ ) {
+#      if ( SDL_IsGameController(i) ) {
+#          nGameControllers++;
+#      }
+#  }
+#
+#  Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is:
+#  guid,name,mappings
+#
+#  Where GUID is the string value from SDL_JoystickGetGUIDString(), name is the human readable string for the device and mappings are controller mappings to joystick ones.
+#  Under Windows there is a reserved GUID of "xinput" that covers any XInput devices.
+#  The mapping format for joystick is:
+#      bX - a joystick button, index X
+#      hX.Y - hat X with value Y
+#      aX - axis X of the joystick
+#  Buttons can be used as a controller axis and vice versa.
+#
+#  This string shows an example of a valid mapping for a controller
+#  "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7",
+#
+# /
+
+##
+#   Add or update an existing mapping configuration
+#
+#  \return 1 if mapping is added, 0 if updated, -1 on error
+# /
+proc gameControllerAddMapping* (mappingString: cstring): cint {.
+  importc: "SDL_GameControllerAddMapping".}
+
+##
+#   Get a mapping string for a GUID
+#
+#   \return the mapping string.  Must be freed with SDL_free.  Returns NULL if no mapping is available
+# /
+proc gameControllerMappingForGUID* (guid: JoystickGuid): cstring {.
+  importc: "SDL_GameControllerMappingForGUID".}
+
+##
+#   Get a mapping string for an open GameController
+#
+#   \return the mapping string.  Must be freed with SDL_free.  Returns NULL if no mapping is available
+# /
+proc mapping* (gameController: GameControllerPtr): cstring {.
+  importc: "SDL_GameControllerMapping".}
+
+##
+#   Is the joystick on this index supported by the game controller interface?
+# /
+proc isGameController* (joystickIndex: cint): Bool32 {.
+  importc: "SDL_IsGameController".}
+
+
+##
+#   Get the implementation dependent name of a game controller.
+#   This can be called before any controllers are opened.
+#   If no name can be found, this function returns NULL.
+# /
+proc gameControllerNameForIndex* (joystickIndex: cint): cstring {.
+  importc: "SDL_GameControllerNameForIndex".}
+
+##
+#   Open a game controller for use.
+#   The index passed as an argument refers to the N'th game controller on the system.
+#   This index is the value which will identify this controller in future controller
+#   events.
+#
+#   \return A controller identifier, or NULL if an error occurred.
+# /
+proc gameControllerOpen* (joystickIndex: cint): GameControllerPtr {.
+  importc: "SDL_GameControllerOpen".}
+
+##
+#   Return the name for this currently opened controller
+# /
+proc name* (gameController: GameControllerPtr): cstring {.
+  importc: "SDL_GameControllerName".}
+
+##
+#   Returns SDL_TRUE if the controller has been opened and currently connected,
+#   or SDL_FALSE if it has not.
+# /
+proc getAttached* (gameController: GameControllerPtr): Bool32 {.
+  importc: "SDL_GameControllerGetAttached".}
+
+##
+#   Get the underlying joystick object used by a controller
+# /
+proc getJoystick* (gameController: GameControllerPtr): JoystickPtr {.
+  importc: "SDL_GameControllerGetJoystick".}
+
+##
+#   Enable/disable controller event polling.
+#
+#   If controller events are disabled, you must call SDL_GameControllerUpdate()
+#   yourself and check the state of the controller when you want controller
+#   information.
+#
+#   The state can be one of ::SDL_QUERY, ::SDL_ENABLE or ::SDL_IGNORE.
+# /
+proc gameControllerEventState* (state: cint): cint {.
+  importc: "SDL_GameControllerEventState".}
+
+##
+#   Update the current state of the open game controllers.
+#
+#   This is called automatically by the event loop if any game controller
+#   events are enabled.
+# /
+proc gameControllerUpdate* () {.
+  importc: "SDL_GameControllerUpdate".}
+
+
+##
+#   The list of axes available from a controller
+# /
+type
+  GameControllerAxis* {.size: sizeof(cint).} = enum
+    SDL_CONTROLLER_AXIS_INVALID = -1,
+    SDL_CONTROLLER_AXIS_LEFTX,
+    SDL_CONTROLLER_AXIS_LEFTY,
+    SDL_CONTROLLER_AXIS_RIGHTX,
+    SDL_CONTROLLER_AXIS_RIGHTY,
+    SDL_CONTROLLER_AXIS_TRIGGERLEFT,
+    SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
+    SDL_CONTROLLER_AXIS_MAX
+
+converter toInt* (some: GameControllerAxis): uint8 = uint8(some)
+
+##
+#   turn this string into a axis mapping
+# /
+proc gameControllerGetAxisFromString* (pchString: cstring): GameControllerAxis {.
+  importc: "SDL_GameControllerGetAxisFromString".}
+
+##
+#   turn this axis enum into a string mapping
+# /
+proc gameControllerGetStringForAxis* (axis: GameControllerAxis): cstring {.
+  importc: "SDL_GameControllerGetStringForAxis".}
+
+##
+#   Get the SDL joystick layer binding for this controller button mapping
+# /
+proc getBindForAxis* (gameController: GameControllerPtr, axis: GameControllerAxis): GameControllerButtonBind {.
+  importc: "SDL_GameControllerGetBindForAxis".}
+
+##
+#   Get the current state of an axis control on a game controller.
+#
+#   The state is a value ranging from -32768 to 32767.
+#
+#   The axis indices start at index 0.
+# /
+proc getAxis* (gameController: GameControllerPtr, axis: GameControllerAxis): int16 {.
+  importc: "SDL_GameControllerGetAxis".}
+
+##
+#   The list of buttons available from a controller
+# /
+type
+  GameControllerButton* {.size: sizeof(cint).} = enum
+    SDL_CONTROLLER_BUTTON_INVALID = -1,
+    SDL_CONTROLLER_BUTTON_A,
+    SDL_CONTROLLER_BUTTON_B,
+    SDL_CONTROLLER_BUTTON_X,
+    SDL_CONTROLLER_BUTTON_Y,
+    SDL_CONTROLLER_BUTTON_BACK,
+    SDL_CONTROLLER_BUTTON_GUIDE,
+    SDL_CONTROLLER_BUTTON_START,
+    SDL_CONTROLLER_BUTTON_LEFTSTICK,
+    SDL_CONTROLLER_BUTTON_RIGHTSTICK,
+    SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
+    SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
+    SDL_CONTROLLER_BUTTON_DPAD_UP,
+    SDL_CONTROLLER_BUTTON_DPAD_DOWN,
+    SDL_CONTROLLER_BUTTON_DPAD_LEFT,
+    SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
+    SDL_CONTROLLER_BUTTON_MAX
+
+converter toInt* (some: GameControllerButton): uint8 = uint8(some)
+
+##
+#   turn this string into a button mapping
+# /
+proc gameControllerGetButtonFromString* (pchString: cstring): GameControllerButton {.
+  importc: "SDL_GameControllerGetButtonFromString".}
+
+##
+#   turn this button enum into a string mapping
+# /
+proc gameControllerGetStringForButton* (button: GameControllerButton): cstring {.
+  importc: "SDL_GameControllerGetStringForButton".}
+
+##
+#   Get the SDL joystick layer binding for this controller button mapping
+# /
+proc getBindForButton* (gameController: GameControllerPtr, button: GameControllerButton): GameControllerButtonBind {.
+  importc: "SDL_GameControllerGetBindForButton".}
+
+
+##
+#   Get the current state of a button on a game controller.
+#
+#   The button indices start at index 0.
+# /
+proc getButton* (gameController: GameControllerPtr, button: GameControllerButton): uint8 {.
+  importc: "SDL_GameControllerGetButton".}
+
+##
+#   Close a controller previously opened with SDL_GameControllerOpen().
+# /
+proc close* (gameController: GameControllerPtr) {.
+  importc: "SDL_GameControllerClose".}
+
+when not defined(SDL_Static):
+  {.pop.}

+ 259 - 0
src/nodesnim/thirdparty/sdl2/gfx.nim

@@ -0,0 +1,259 @@
+#
+#
+#SDL2_gfxPrimitives.h: graphics primitives for SDL
+#
+#Copyright (C) 2012  Andreas Schiffler
+#
+#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.
+#
+#Andreas Schiffler -- aschiffler at ferzkopp dot net
+#
+#
+
+# Docs: http://www.ferzkopp.net/Software/SDL_gfx-2.0/Docs/html/_s_d_l__gfx_primitives_8c.html
+
+import sdl2
+
+when not defined(SDL_Static):
+  when defined(windows):
+    const LibName = "SDL2_gfx.dll"
+  elif defined(macosx):
+    const LibName = "libSDL2_gfx.dylib"
+  else:
+    const LibName = "libSDL2_gfx(|-2.0).so(|.0)"
+else:
+  static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2_gfx."
+
+const
+  FPS_UPPER_LIMIT* = 200
+  FPS_LOWER_LIMIT* = 1
+  FPS_DEFAULT* = 30
+
+type
+  FpsManager* {.pure, final.} = object
+    framecount*: cint
+    rateticks*: cfloat
+    baseticks*: cint
+    lastticks*: cint
+    rate*: cint
+
+{.pragma: i, importc, discardable.}
+
+when not defined(SDL_Static):
+  {.push callConv:cdecl, dynlib: LibName.}
+
+# ---- Function Prototypes
+# Note: all ___Color routines expect the color to be in format 0xAABBGGRR
+# Pixel
+proc pixelColor*(renderer: RendererPtr; x, y: int16; color: uint32): SDL_Return {.importc, discardable.}
+proc pixelRGBA*(renderer: RendererPtr; x: int16; y: int16; r: uint8;
+                g: uint8; b: uint8; a: uint8): SDL_Return  {.importc, discardable.}
+# Horizontal line
+proc hlineColor*(renderer: RendererPtr; x1: int16; x2: int16;
+                 y: int16; color: uint32): SDL_Return {.importc, discardable.}
+proc hlineRGBA*(renderer: RendererPtr; x1: int16; x2: int16; y: int16;
+                r,g,b,a: uint8): SDL_Return {.importc, discardable.}
+# Vertical line
+proc vlineColor*(renderer: RendererPtr; x,y1,y2: int16;
+                  color: uint32): SDL_Return {.importc, discardable.}
+proc vlineRGBA*(renderer: RendererPtr; x,y1,y2: int16;
+                r,g,b,a: uint8): SDL_Return {.importc, discardable.}
+# Rectangle
+proc rectangleColor*(renderer: RendererPtr; x1,y1,x2,y2: int16;
+      color: uint32): SDL_Return {.importc, discardable.}
+proc rectangleRGBA*(renderer: RendererPtr; x1,y1,x2,y2: int16; r,g,b,a: uint8): SDL_Return {.
+      importc, discardable.}
+# Rounded-Corner Rectangle
+proc roundedRectangleColor*(renderer: RendererPtr; x1,y1,x2,y2,rad: int16;
+                            color: uint32): SDL_Return {.importc, discardable.}
+proc roundedRectangleRGBA*(renderer: RendererPtr; x1,y1,x2,y2,rad: int16;
+              r,g,b,a: uint8): SDL_Return {.importc, discardable.}
+# Filled rectangle (Box)
+proc boxColor*(renderer: RendererPtr; x1, y1, x2, y2: int16;
+  color: uint32): SDL_Return {.importc, discardable.}
+proc boxRGBA*(renderer: RendererPtr; x1, y1, x2, y2: int16;
+  r, g, b, a: uint8): SDL_Return {.importc, discardable.}
+# Rounded-Corner Filled rectangle (Box)
+proc roundedBoxColor*(renderer: RendererPtr; x1,y1,x2,y2,rad: int16;
+                       color: uint32): SDL_Return {.importc, discardable.}
+proc roundedBoxRGBA*(renderer: RendererPtr; x1,y1,x2,y2,rad: int16;
+                  r,g,b,a: uint8): SDL_Return {.importc, discardable.}
+# Line
+proc lineColor*(renderer: RendererPtr; x1,y1,x2,y2: int16;
+    color: uint32): SDL_Return {.importc, discardable.}
+proc lineRGBA*(renderer: RendererPtr; x1,y1,x2,y2: int16; r,g,b,a: uint8): SDL_Return {.
+  importc, discardable.}
+# AA Line
+proc aalineColor*(renderer: RendererPtr; x1: int16; y1: int16;
+                  x2: int16; y2: int16; color: uint32): SDL_Return {.importc, discardable.}
+proc aalineRGBA*(renderer: RendererPtr; x1: int16; y1: int16;
+                 x2: int16; y2: int16; r: uint8; g: uint8; b: uint8;
+                 a: uint8): SDL_Return {.importc, discardable.}
+# Thick Line
+proc thickLineColor*(renderer: RendererPtr; x1, y1, x2, y2: int16;
+  width: uint8; color: uint32): SDL_Return {.importc, discardable.}
+proc thickLineRGBA*(renderer: RendererPtr; x1, y1, x2, y2: int16;
+  width, r, g, b, a: uint8): SDL_Return {.importc, discardable.}
+# Circle
+proc circleColor*(renderer: RendererPtr; x, y, rad: int16;
+  color: uint32): SDL_Return {.importc, discardable.}
+proc circleRGBA*(renderer: RendererPtr; x, y, rad: int16;
+  r, g, b, a: uint8): SDL_Return {.importc, discardable.}
+# Arc
+proc arcColor*(renderer: RendererPtr; x, y, rad, start, finish: int16;
+  color: uint32): SDL_Return {.importc, discardable.}
+proc arcRGBA*(renderer: RendererPtr; x, y, rad, start, finish: int16;
+  r, g, b, a: uint8): SDL_Return {.importc, discardable.}
+# AA Circle
+proc aacircleColor*(renderer: RendererPtr; x, y, rad: int16;
+  color: uint32): SDL_Return {.importc, discardable.}
+proc aacircleRGBA*(renderer: RendererPtr; x, y, rad: int16;
+  r, g, b, a: uint8): SDL_Return {.importc, discardable.}
+# Filled Circle
+proc filledCircleColor*(renderer: RendererPtr; x, y, r: int16;
+  color: uint32): SDL_Return {.importc, discardable.}
+proc filledCircleRGBA*(renderer: RendererPtr; x, y, rad: int16;
+  r, g, b, a: uint8): SDL_Return {.importc, discardable.}
+# Ellipse
+proc ellipseColor*(renderer: RendererPtr; x: int16; y: int16;
+                   rx: int16; ry: int16; color: uint32): SDL_Return {.importc, discardable.}
+proc ellipseRGBA*(renderer: RendererPtr; x: int16; y: int16;
+                  rx: int16; ry: int16; r: uint8; g: uint8; b: uint8;
+                  a: uint8): SDL_Return {.importc, discardable.}
+# AA Ellipse
+proc aaellipseColor*(renderer: RendererPtr; x, y, rx, ry: int16;
+  color: uint32): SDL_Return {.importc, discardable.}
+proc aaellipseRGBA*(renderer: RendererPtr; x, y, rx, ry: int16;
+  r, g, b, a: uint8): SDL_Return {.importc, discardable.}
+# Filled Ellipse
+proc filledEllipseColor*(renderer: RendererPtr; x, y, rx, ry: int16;
+  color: uint32): SDL_Return {.importc, discardable.}
+proc filledEllipseRGBA*(renderer: RendererPtr; x, y, rx, ry: int16;
+  r, g, b, a: uint8): SDL_Return {.importc, discardable.}
+# Pie
+proc pieColor*(renderer: RendererPtr; x, y, rad, start, finish: int16;
+  color: uint32): SDL_Return {.importc, discardable.}
+proc pieRGBA*(renderer: RendererPtr; x, y, rad, start, finish: int16;
+  r, g, b, a: uint8): SDL_Return  {.importc, discardable.}
+# Filled Pie
+proc filledPieColor*(renderer: RendererPtr; x, y, rad, start, finish: int16;
+  color: uint32): SDL_Return {.importc, discardable.}
+proc filledPieRGBA*(renderer: RendererPtr; x, y, rad, start, finish: int16;
+  r, g, b, a: uint8): SDL_Return {.importc, discardable.}
+# Trigon
+proc trigonColor*(renderer: RendererPtr; x1,y1,x2,y2,x3,y3: int16,
+                   color: uint32): SDL_Return {.importc, discardable.}
+proc trigonRGBA*(renderer: RendererPtr; x1, y1, x2, y2, x3, y3: int16;
+                  r,g,b,a: uint8): SDL_Return {.importc, discardable.}
+# AA-Trigon
+proc aaTrigonColor*(renderer: RendererPtr; x1, y1, x2, y2, x3, y3: int16;
+                    color: uint32): SDL_Return {.importc: "aatrigonColor",
+                    discardable.}
+proc aaTrigonRGBA*(renderer: RendererPtr; x1, y1, x2, y2, x3, y3: int16;
+                    r,g,b,a: uint8): SDL_Return {.importc: "aatrigonRGBA",
+                    discardable.}
+# Filled Trigon
+proc filledTrigonColor*(renderer: RendererPtr; x1: int16; y1: int16;
+                        x2: int16; y2: int16; x3: int16; y3: int16;
+                        color: uint32): SDL_Return {.importc, discardable.}
+proc filledTrigonRGBA*(renderer: RendererPtr; x1: int16; y1: int16;
+                       x2: int16; y2: int16; x3: int16; y3: int16;
+                       r,g,b,a: uint8): SDL_Return {.importc, discardable.}
+# Polygon
+proc polygonColor*(renderer: RendererPtr; vx: ptr int16; vy: ptr int16;
+                   n: cint; color: uint32): SDL_Return {.importc, discardable.}
+proc polygonRGBA*(renderer: RendererPtr; vx: ptr int16; vy: ptr int16;
+                  n: cint; r,g,b,a: uint8): SDL_Return {.importc, discardable.}
+# AA-Polygon
+proc aaPolygonColor*(renderer: RendererPtr; vx: ptr int16; vy: ptr int16;
+                     n: cint; color: uint32): SDL_Return {.importc: "aapolygonColor",
+                     discardable.}
+proc aaPolygonRGBA*(renderer: RendererPtr; vx: ptr int16; vy: ptr int16;
+                    n: cint; r,g,b,a: uint8): SDL_Return {.importc: "aapolygonRGBA",
+                    discardable.}
+# Filled Polygon
+proc filledPolygonColor*(renderer: RendererPtr; vx: ptr int16;
+                         vy: ptr int16; n: cint; color: uint32): SDL_Return {.importc, discardable.}
+proc filledPolygonRGBA*(renderer: RendererPtr; vx: ptr int16;
+                        vy: ptr int16; n: cint; r: uint8; g: uint8; b: uint8;
+                        a: uint8): SDL_Return {.importc, discardable.}
+# Textured Polygon
+proc texturedPolygon*(renderer: RendererPtr; vx: ptr int16;
+                      vy: ptr int16; n: cint; texture: SurfacePtr;
+                      texture_dx: cint; texture_dy: cint): SDL_Return {.importc, discardable.}
+# Bezier
+proc bezierColor*(renderer: RendererPtr; vx,vy: ptr int16;
+                  n: cint; s: cint; color: uint32): SDL_Return {.importc, discardable.}
+proc bezierRGBA*(renderer: RendererPtr; vx, vy: ptr int16;
+                 n: cint; s: cint; r, g, b, a: uint8): SDL_Return {.importc, discardable.}
+# Characters/Strings
+proc gfxPrimitivesSetFont*(fontdata: pointer; cw: uint32; ch: uint32) {.importc.}
+proc gfxPrimitivesSetFontRotation*(rotation: uint32) {.importc.}
+proc characterColor*(renderer: RendererPtr; x: int16; y: int16;
+                     c: char; color: uint32): SDL_Return {.importc.}
+proc characterRGBA*(renderer: RendererPtr; x: int16; y: int16; c: char;
+                    r,g,b,a: uint8): SDL_Return {.importc.}
+proc stringColor*(renderer: RendererPtr; x: int16; y: int16;
+                  s: cstring; color: uint32): SDL_Return {.importc.}
+proc stringRGBA*(renderer: RendererPtr; x: int16; y: int16; s: cstring;
+                 r,g,b,a: uint8): SDL_Return {.importc, discardable.}
+# Ends C function definitions when using C++
+
+proc rotozoomSurface*(src: SurfacePtr; angle, zoom: cdouble;
+  smooth: cint): SurfacePtr {.importc.}
+proc rotozoomSurfaceXY*(src: SurfacePtr; angle, zoomX, zoomY: cdouble;
+  smooth: cint): SurfacePtr {.importc.}
+proc rotozoomSurfaceSize*(width, height: cint; angle, zoom: cdouble;
+  dstwidth, dstheight: var cint) {.importc.}
+proc rotozoomSurfaceSizeXY*(width, height: cint; angle, zoomX, zoomY: cdouble;
+                            dstwidth, dstheight: var cint) {.importc.}
+proc zoomSurface*(src: SurfacePtr; zoomX, zoomY: cdouble;
+  smooth: cint): SurfacePtr {.importc.}
+proc zoomSurfaceSize*(width, height: cint; zoomX, zoomY: cdouble;
+  dstWidth, dstHeight: var cint) {.importc.}
+
+proc shrinkSurface*(src: SurfacePtr; factorx, factorY: cint): SurfacePtr {.importc.}
+proc rotateSurface90Degrees*(src: SurfacePtr;
+  numClockwiseTurns: cint): SurfacePtr {.importc.}
+
+proc init*(manager: var FpsManager) {.importc: "SDL_initFramerate".}
+proc setFramerate*(manager: var FpsManager; rate: cint): SDL_Return {.
+  importc: "SDL_setFramerate", discardable.}
+proc getFramerate*(manager: var FpsManager): cint {.importc: "SDL_getFramerate".}
+proc getFramecount*(manager: var FpsManager): cint {.importc: "SDL_getFramecount".}
+proc delay*(manager: var FpsManager): cint {.importc: "SDL_framerateDelay", discardable.}
+
+when not defined(SDL_Static):
+  {.pop.}
+
+from strutils import splitLines
+proc mlStringRGBA*(renderer: RendererPtr; x,y: int16, S: string, R,G,B,A: uint8, lineSpacing = 2'i16) =
+  ## Draw a multi-line string
+  var ln = 0
+  for L in splitLines(S):
+    renderer.stringRGBA(x,(y + int16(ln * 8) + int16(ln * lineSpacing)),L, R,G,B,A)
+    inc ln
+proc mlStringRGBA*(renderer: RendererPtr; x,y: int16; S: seq[string]; R,G,B,A: uint8; lineSpacing = 2'i16) =
+  var ln = 0
+  while ln < S.len:
+    renderer.stringRGBA(x, y + int16(ln * 8 + ln * lineSpacing), S[ln], R,G,B,A)
+    inc ln
+
+{.deprecated: [TFPSmanager: FpsManager].}

+ 1193 - 0
src/nodesnim/thirdparty/sdl2/haptic.nim

@@ -0,0 +1,1193 @@
+import "../sdl2"
+import "joystick"
+
+#
+#  Simple DirectMedia Layer
+#  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+#
+#  This software is provided 'as-is', without any express or implied
+#  warranty.  In no event will the authors be held liable for any damages
+#  arising from the use of this software.
+#
+#  Permission is granted to anyone to use this software for any purpose,
+#  including commercial applications, and to alter it and redistribute it
+#  freely, subject to the following restrictions:
+#
+#  1. The origin of this software must not be misrepresented; you must not
+#     claim that you wrote the original software. If you use this software
+#     in a product, an acknowledgment in the product documentation would be
+#     appreciated but is not required.
+#  2. Altered source versions must be plainly marked as such, and must not be
+#     misrepresented as being the original software.
+#  3. This notice may not be removed or altered from any source distribution.
+#
+
+#
+#  \file SDL_haptic.h
+#
+#  \brief The SDL Haptic subsystem allows you to control haptic (force feedback)
+#         devices.
+#
+#  The basic usage is as follows:
+#   - Initialize the Subsystem (::SDL_INIT_HAPTIC).
+#   - Open a Haptic Device.
+#    - SDL_HapticOpen() to open from index.
+#    - SDL_HapticOpenFromJoystick() to open from an existing joystick.
+#   - Create an effect (::SDL_HapticEffect).
+#   - Upload the effect with SDL_HapticNewEffect().
+#   - Run the effect with SDL_HapticRunEffect().
+#   - (optional) Free the effect with SDL_HapticDestroyEffect().
+#   - Close the haptic device with SDL_HapticClose().
+#
+#   \par Simple rumble example:
+#   \code
+#    haptic: HapticPtr;
+#
+#    // Open the device
+#    haptic = SDL_HapticOpen( 0 );
+#    if (haptic == NULL)
+#       return -1;
+#
+#    // Initialize simple rumble
+#    if (SDL_HapticRumbleInit( haptic ) != 0)
+#       return -1;
+#
+#    // Play effect at 50% strength for 2 seconds
+#    if (SDL_HapticRumblePlay( haptic, 0.5, 2000 ) != 0)
+#       return -1;
+#    SDL_Delay( 2000 );
+#
+#    // Clean up
+#    SDL_HapticClose( haptic );
+#  \endcode
+#
+#  \par Complete example:
+#  \code
+#  int test_haptic( joystick: Joystick ) {
+#    haptic: HapticPtr;
+#    SDL_HapticEffect effect;
+#    effect: cint_id;
+#
+#    // Open the device
+#    haptic = SDL_HapticOpenFromJoystick( joystick );
+#    if (haptic == NULL) return -1; // Most likely joystick isn't haptic
+#
+#    // See if it can do sine waves
+#    if ((SDL_HapticQuery(haptic) & SDL_HAPTIC_SINE)==0) {
+#       SDL_HapticClose(haptic); // No sine effect
+#       return -1;
+#    }
+#
+#    // Create the effect
+#    memset( &effect, 0, sizeof(SDL_HapticEffect) ); // 0 is safe default
+#    effect.type = SDL_HAPTIC_SINE;
+#    effect.periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates
+#    effect.periodic.direction.dir[0] = 18000; // Force comes from south
+#    effect.periodic.period = 1000; // 1000 ms
+#    effect.periodic.magnitude = 20000; // 20000/32767 strength
+#    effect.periodic.length = 5000; // 5 seconds long
+#    effect.periodic.attack_length = 1000; // Takes 1 second to get max strength
+#    effect.periodic.fade_length = 1000; // Takes 1 second to fade away
+#
+#    // Upload the effect
+#    effect_id = SDL_HapticNewEffect( haptic, &effect );
+#
+#    // Test the effect
+#    SDL_HapticRunEffect( haptic, effect_id, 1 );
+#    SDL_Delay( 5000); // Wait for the effect to finish
+#
+#    // We destroy the effect, although closing the device also does this
+#    SDL_HapticDestroyEffect( haptic, effect_id );
+#
+#    // Close the device
+#    SDL_HapticClose(haptic);
+#
+#    return 0; // Success
+#  }
+#  \endcode
+#
+#  You can also find out more information on my blog:
+#  http://bobbens.dyndns.org/journal/2010/sdl_haptic/
+#
+#  \author Edgar Simo Serra
+# /
+
+#
+#  \typedef SDL_Haptic
+#
+#  \brief The haptic structure used to identify an SDL haptic.
+#
+#  \sa SDL_HapticOpen
+#  \sa SDL_HapticOpenFromJoystick
+#  \sa SDL_HapticClose
+
+type
+  Haptic* = object
+  HapticPtr* = ptr Haptic
+
+
+#
+#  \name Haptic features
+#
+#  Different haptic features a device can have.
+
+#  @{
+
+#
+#  \name Haptic effects
+
+#  @{
+
+#
+#  \brief Constant effect supported.
+#
+#  Constant haptic effect.
+#
+#  \sa SDL_HapticCondition
+
+const SDL_HAPTIC_CONSTANT* = (1 shl 0)
+
+#
+#  \brief Sine wave effect supported.
+#
+#  Periodic haptic effect that simulates sine waves.
+#
+#  \sa SDL_HapticPeriodic
+
+const SDL_HAPTIC_SINE* = (1 shl 1)
+
+#
+#  \brief Left/Right effect supported.
+#
+#  Haptic effect for direct control over high/low frequency motors.
+#
+#  \sa SDL_HapticLeftRight
+#  \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry,
+#          we ran out of bits, and this is important for XInput devices.
+
+const SDL_HAPTIC_LEFTRIGHT* = (1 shl 2)
+
+#  !!! FIXME: put this back when we have more bits in 2.1
+#  const SDL_HAPTIC_SQUARE* = (1 shl 2)
+
+#
+#  \brief Triangle wave effect supported.
+#
+#  Periodic haptic effect that simulates triangular waves.
+#
+#  \sa SDL_HapticPeriodic
+
+const SDL_HAPTIC_TRIANGLE* = (1 shl 3)
+
+#
+#  \brief Sawtoothup wave effect supported.
+#
+#  Periodic haptic effect that simulates saw tooth up waves.
+#
+#  \sa SDL_HapticPeriodic
+
+const SDL_HAPTIC_SAWTOOTHUP* = (1 shl 4)
+
+#
+#  \brief Sawtoothdown wave effect supported.
+#
+#  Periodic haptic effect that simulates saw tooth down waves.
+#
+#  \sa SDL_HapticPeriodic
+
+const SDL_HAPTIC_SAWTOOTHDOWN* = (1 shl 5)
+
+#
+#  \brief Ramp effect supported.
+#
+#  Ramp haptic effect.
+#
+#  \sa SDL_HapticRamp
+
+const SDL_HAPTIC_RAMP* = (1 shl 6)
+
+#
+#  \brief Spring effect supported - uses axes position.
+#
+#  Condition haptic effect that simulates a spring.  Effect is based on the
+#  axes position.
+#
+#  \sa SDL_HapticCondition
+
+const SDL_HAPTIC_SPRING* = (1 shl 7)
+
+#
+#  \brief Damper effect supported - uses axes velocity.
+#
+#  Condition haptic effect that simulates dampening.  Effect is based on the
+#  axes velocity.
+#
+#  \sa SDL_HapticCondition
+
+const SDL_HAPTIC_DAMPER* = (1 shl 8)
+
+#
+#  \brief Inertia effect supported - uses axes acceleration.
+#
+#  Condition haptic effect that simulates inertia.  Effect is based on the axes
+#  acceleration.
+#
+#  \sa SDL_HapticCondition
+
+const SDL_HAPTIC_INERTIA* = (1 shl 9)
+
+#
+#  \brief Friction effect supported - uses axes movement.
+#
+#  Condition haptic effect that simulates friction.  Effect is based on the
+#  axes movement.
+#
+#  \sa SDL_HapticCondition
+
+const SDL_HAPTIC_FRICTION* = (1 shl 10)
+
+#
+#  \brief Custom effect is supported.
+#
+#  User defined custom haptic effect.
+
+const SDL_HAPTIC_CUSTOM* = (1 shl 11)
+
+#  @} #  Haptic effects
+
+#  These last few are features the device has, not effects
+
+#
+#  \brief Device can set global gain.
+#
+#  Device supports setting the global gain.
+#
+#  \sa SDL_HapticSetGain
+
+const SDL_HAPTIC_GAIN* = (1 shl 12)
+
+#
+#  \brief Device can set autocenter.
+#
+#  Device supports setting autocenter.
+#
+#  \sa SDL_HapticSetAutocenter
+
+const SDL_HAPTIC_AUTOCENTER* = (1 shl 13)
+
+#
+#  \brief Device can be queried for effect status.
+#
+#  Device can be queried for effect status.
+#
+#  \sa SDL_HapticGetEffectStatus
+
+const SDL_HAPTIC_STATUS* = (1 shl 14)
+
+#
+#  \brief Device can be paused.
+#
+#  \sa SDL_HapticPause
+#  \sa SDL_HapticUnpause
+
+const SDL_HAPTIC_PAUSE* = (1 shl 15)
+
+
+#
+#  \name Direction encodings
+
+#  @{
+
+#
+#  \brief Uses polar coordinates for the direction.
+#
+#  \sa HapticDirection
+
+const SDL_HAPTIC_POLAR* = 0
+
+#
+#  \brief Uses cartesian coordinates for the direction.
+#
+#  \sa HapticDirection
+
+const SDL_HAPTIC_CARTESIAN* = 1
+
+#
+#  \brief Uses spherical coordinates for the direction.
+#
+#  \sa HapticDirection
+
+const SDL_HAPTIC_SPHERICAL* = 2
+
+#  @} #  Direction encodings
+
+#  @} #  Haptic features
+
+#
+#  Misc defines.
+
+
+#
+#  \brief Used to play a device an infinite number of times.
+#
+#  \sa SDL_HapticRunEffect
+
+const SDL_HAPTIC_INFINITY* = 4294967295'u
+
+
+#
+#  \brief Structure that represents a haptic direction.
+#
+#  Directions can be specified by:
+#   - ::SDL_HAPTIC_POLAR : Specified by polar coordinates.
+#   - ::SDL_HAPTIC_CARTESIAN : Specified by cartesian coordinates.
+#   - ::SDL_HAPTIC_SPHERICAL : Specified by spherical coordinates.
+#
+#  Cardinal directions of the haptic device are relative to the positioning
+#  of the device.  North is considered to be away from the user.
+#
+#  The following diagram represents the cardinal directions:
+#  \verbatim
+#                 .--.
+#                 |__| .-------.
+#                 |=.| |.-----.|
+#                 |--| ||     ||
+#                 |  | |'-----'|
+#                 |__|~')_____('
+#                   [ COMPUTER ]
+#
+#
+#                     North (0,-1)
+#                         ^
+#                         |
+#                         | = (1,0)  West <----[ HAPTIC ]----> East (-1,0)
+#                         |
+#                         |
+#                         v
+#                      South (0,1)
+#
+#
+#                      [ USER ]
+#                        \|||/ = (o o)
+#                  ---ooO-(_)-Ooo---
+#    \endverbatim
+#
+#  If type is ::SDL_HAPTIC_POLAR, direction is encoded by hundredths of a
+#  degree starting north and turning clockwise.  ::SDL_HAPTIC_POLAR only uses
+#  the first \c dir parameter.  The cardinal directions would be:
+#   - North: 0 (0 degrees)
+#   - East: 9000 (90 degrees)
+#   - South: 18000 (180 degrees)
+#   - West: 27000 (270 degrees)
+#
+#  If type is ::SDL_HAPTIC_CARTESIAN, direction is encoded by three positions
+# = (X axis, Y axis and Z axis (with 3 axes)).  ::SDL_HAPTIC_CARTESIAN uses
+#  the first three \c dir parameters.  The cardinal directions would be:
+#   - North:  0,-1, 0
+#   - East:  -1, 0, 0
+#   - South:  0, 1, 0
+#   - West:   1, 0, 0
+#
+#  The Z axis represents the height of the effect if supported, otherwise
+#  it's unused.  In cartesian encoding (1, 2) would be the same as (2, 4), you
+#  can use any multiple you want, only the direction matters.
+#
+#  If type is ::SDL_HAPTIC_SPHERICAL, direction is encoded by two rotations.
+#  The first two \c dir parameters are used.  The \c dir parameters are as
+#  follows (all values are in hundredths of degrees):
+#   - Degrees from (1, 0) rotated towards (0, 1).
+#   - Degrees towards (0, 0, 1) (device needs at least 3 axes).
+#
+#
+#  Example of force coming from the south with all encodings (force coming
+#  from the south means the user will have to pull the stick to counteract):
+#  \code
+#  HapticDirection direction;
+#
+#  // Cartesian directions
+#  direction.type = SDL_HAPTIC_CARTESIAN; // Using cartesian direction encoding.
+#  direction.dir[0] = 0; // X position
+#  direction.dir[1] = 1; // Y position
+#  // Assuming the device has 2 axes, we don't need to specify third parameter.
+#
+#  // Polar directions
+#  direction.type = SDL_HAPTIC_POLAR; // We'll be using polar direction encoding.
+#  direction.dir[0] = 18000; // Polar only uses first parameter
+#
+#  // Spherical coordinates
+#  direction.type = SDL_HAPTIC_SPHERICAL; // Spherical encoding
+#  direction.dir[0] = 9000; // Since we only have two axes we don't need more parameters.
+#  \endcode
+#
+#  \sa SDL_HAPTIC_POLAR
+#  \sa SDL_HAPTIC_CARTESIAN
+#  \sa SDL_HAPTIC_SPHERICAL
+#  \sa SDL_HapticEffect
+#  \sa SDL_HapticNumAxes
+
+type
+  HapticDirection* = object
+    kind: uint8         #  < The type of encoding.
+    dir: array[3, int32]      #  < The encoded direction.
+
+
+#
+#  \brief A structure containing a template for a Constant effect.
+#
+#  The struct is exclusive to the ::SDL_HAPTIC_CONSTANT effect.
+#
+#  A constant effect applies a constant force in the specified direction
+#  to the joystick.
+#
+#  \sa SDL_HAPTIC_CONSTANT
+#  \sa SDL_HapticEffect
+
+type
+  HapticConstant* = object
+    #  Header
+    kind: uint16            #  < ::SDL_HAPTIC_CONSTANT
+    direction: HapticDirection  #  < Direction of the effect.
+
+    #  Replay
+    length: uint32          #  < Duration of the effect.
+    delay: uint16           #  < Delay before starting the effect.
+
+    #  Trigger
+    button: uint16          #  < Button that triggers the effect.
+    interval: uint16        #  < How soon it can be triggered again after button.
+
+    #  Constant
+    level: int16           #  < Strength of the constant effect.
+
+    #  Envelope
+    attack_length: uint16   #  < Duration of the attack.
+    attack_level: uint16    #  < Level at the start of the attack.
+    fade_length: uint16     #  < Duration of the fade.
+    fade_level: uint16      #  < Level at the end of the fade.
+
+#
+#  \brief A structure containing a template for a Periodic effect.
+#
+#  The struct handles the following effects:
+#   - ::SDL_HAPTIC_SINE
+#   - ::SDL_HAPTIC_LEFTRIGHT
+#   - ::SDL_HAPTIC_TRIANGLE
+#   - ::SDL_HAPTIC_SAWTOOTHUP
+#   - ::SDL_HAPTIC_SAWTOOTHDOWN
+#
+#  A periodic effect consists in a wave-shaped effect that repeats itself
+#  over time.  The type determines the shape of the wave and the parameters
+#  determine the dimensions of the wave.
+#
+#  Phase is given by hundredth of a cycle meaning that giving the phase a value
+#  of 9000 will displace it 25% of its period.  Here are sample values:
+#   -     0: No phase displacement.
+#   -  9000: Displaced 25% of its period.
+#   - 18000: Displaced 50% of its period.
+#   - 27000: Displaced 75% of its period.
+#   - 36000: Displaced 100% of its period, same as 0, but 0 is preferred.
+#
+#  Examples:
+#  \verbatim
+#    SDL_HAPTIC_SINE
+#      __      __      __      __
+#     /  \    /  \    /  \    /
+#    /    \__/    \__/    \__/
+#
+#    SDL_HAPTIC_SQUARE
+#     __    __    __    __    __
+#    |  |  |  |  |  |  |  |  |  |
+#    |  |__|  |__|  |__|  |__|  |
+#
+#    SDL_HAPTIC_TRIANGLE
+#      /\    /\    /\    /\    /\
+#     /  \  /  \  /  \  /  \  /
+#    /    \/    \/    \/    \/
+#
+#    SDL_HAPTIC_SAWTOOTHUP
+#      /|  /|  /|  /|  /|  /|  /|
+#     / | / | / | / | / | / | / |
+#    /  |/  |/  |/  |/  |/  |/  |
+#
+#    SDL_HAPTIC_SAWTOOTHDOWN
+#    \  |\  |\  |\  |\  |\  |\  |
+#     \ | \ | \ | \ | \ | \ | \ |
+#      \|  \|  \|  \|  \|  \|  \|
+#    \endverbatim
+#
+#  \sa SDL_HAPTIC_SINE
+#  \sa SDL_HAPTIC_LEFTRIGHT
+#  \sa SDL_HAPTIC_TRIANGLE
+#  \sa SDL_HAPTIC_SAWTOOTHUP
+#  \sa SDL_HAPTIC_SAWTOOTHDOWN
+#  \sa SDL_HapticEffect
+
+type
+  HapticPeriodic* = object
+    #  Header
+    kind: uint16        #  < ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_LEFTRIGHT,
+                        #    ::SDL_HAPTIC_TRIANGLE, ::SDL_HAPTIC_SAWTOOTHUP or
+                        #    ::SDL_HAPTIC_SAWTOOTHDOWN
+    direction: HapticDirection  #  < Direction of the effect.
+
+    #  Replay
+    length: uint32      #  < Duration of the effect.
+    delay: uint16       #  < Delay before starting the effect.
+
+    #  Trigger
+    button: uint16      #  < Button that triggers the effect.
+    interval: uint16    #  < How soon it can be triggered again after button.
+
+    #  Periodic
+    period: uint16      #  < Period of the wave.
+    magnitude: int16   #  < Peak value.
+    offset: int16      #  < Mean value of the wave.
+    phase: uint16       #  < Horizontal shift given by hundredth of a cycle.
+
+    #  Envelope
+    attack_length: uint16   #  < Duration of the attack.
+    attack_level: uint16    #  < Level at the start of the attack.
+    fade_length: uint16 #  < Duration of the fade.
+    fade_level: uint16  #  < Level at the end of the fade.
+
+#
+#  \brief A structure containing a template for a Condition effect.
+#
+#  The struct handles the following effects:
+#   - ::SDL_HAPTIC_SPRING: Effect based on axes position.
+#   - ::SDL_HAPTIC_DAMPER: Effect based on axes velocity.
+#   - ::SDL_HAPTIC_INERTIA: Effect based on axes acceleration.
+#   - ::SDL_HAPTIC_FRICTION: Effect based on axes movement.
+#
+#  Direction is handled by condition internals instead of a direction member.
+#  The condition effect specific members have three parameters.  The first
+#  refers to the X axis, the second refers to the Y axis and the third
+#  refers to the Z axis.  The right terms refer to the positive side of the
+#  axis and the left terms refer to the negative side of the axis.  Please
+#  refer to the ::HapticDirection diagram for which side is positive and
+#  which is negative.
+#
+#  \sa HapticDirection
+#  \sa SDL_HAPTIC_SPRING
+#  \sa SDL_HAPTIC_DAMPER
+#  \sa SDL_HAPTIC_INERTIA
+#  \sa SDL_HAPTIC_FRICTION
+#  \sa SDL_HapticEffect
+
+type
+  HapticCondition* = object
+    #  Header
+    kind: uint16            #  < ::SDL_HAPTIC_SPRING, ::SDL_HAPTIC_DAMPER,
+                            #     ::SDL_HAPTIC_INERTIA or ::SDL_HAPTIC_FRICTION
+    direction: HapticDirection  #  < Direction of the effect - Not used ATM.
+
+    #  Replay
+    length: uint32          #  < Duration of the effect.
+    delay: uint16           #  < Delay before starting the effect.
+
+    #  Trigger
+    button: uint16          #  < Button that triggers the effect.
+    interval: uint16        #  < How soon it can be triggered again after button.
+
+    #  Condition
+    right_sat: array[3, uint16]    #  < Level when joystick is to the positive side.
+    left_sat: array[3, uint16]     #  < Level when joystick is to the negative side.
+    right_coeff: array[3, int16]  #  < How fast to increase the force towards the positive side.
+    left_coeff: array[3, int16]   #  < How fast to increase the force towards the negative side.
+    deadband: array[3, uint16]     #  < Size of the dead zone.
+    center: array[3, int16]       #  < Position of the dead zone.
+
+#
+#  \brief A structure containing a template for a Ramp effect.
+#
+#  This struct is exclusively for the ::SDL_HAPTIC_RAMP effect.
+#
+#  The ramp effect starts at start strength and ends at end strength.
+#  It augments in linear fashion.  If you use attack and fade with a ramp
+#  the effects get added to the ramp effect making the effect become
+#  quadratic instead of linear.
+#
+#  \sa SDL_HAPTIC_RAMP
+#  \sa SDL_HapticEffect
+
+type
+  HapticRamp* = object
+    #  Header
+    kind: uint16            #  < ::SDL_HAPTIC_RAMP
+    direction: HapticDirection  #  < Direction of the effect.
+
+    #  Replay
+    length: uint32          #  < Duration of the effect.
+    delay: uint16           #  < Delay before starting the effect.
+
+    #  Trigger
+    button: uint16          #  < Button that triggers the effect.
+    interval: uint16        #  < How soon it can be triggered again after button.
+
+    #  Ramp
+    start: int16           #  < Beginning strength level.
+    fin: int16             #  < Ending strength level.
+
+    #  Envelope
+    attack_length: uint16   #  < Duration of the attack.
+    attack_level: uint16    #  < Level at the start of the attack.
+    fade_length: uint16     #  < Duration of the fade.
+    fade_level: uint16      #  < Level at the end of the fade.
+
+#
+#  \brief A structure containing a template for a Left/Right effect.
+#
+#  This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect.
+#
+#  The Left/Right effect is used to explicitly control the large and small
+#  motors, commonly found in modern game controllers. One motor is high
+#  frequency, the other is low frequency.
+#
+#  \sa SDL_HAPTIC_LEFTRIGHT
+#  \sa SDL_HapticEffect
+
+type
+  HapticLeftRight* = object
+    #  Header
+    kind: uint16            #  < ::SDL_HAPTIC_LEFTRIGHT
+
+    #  Replay
+    length: uint32          #  < Duration of the effect.
+
+    #  Rumble
+    large_magnitude: uint16 #  < Control of the large controller motor.
+    small_magnitude: uint16 #  < Control of the small controller motor.
+
+#
+#  \brief A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect.
+#
+#  A custom force feedback effect is much like a periodic effect, where the
+#  application can define its exact shape.  You will have to allocate the
+#  data yourself.  Data should consist of channels#  samples uint16 samples.
+#
+#  If channels is one, the effect is rotated using the defined direction.
+#  Otherwise it uses the samples in data for the different axes.
+#
+#  \sa SDL_HAPTIC_CUSTOM
+#  \sa SDL_HapticEffect
+
+type
+  HapticCustom* = object
+    #  Header
+    kind: uint16            #  < ::SDL_HAPTIC_CUSTOM
+    direction: HapticDirection  #  < Direction of the effect.
+
+    #  Replay
+    length: uint32          #  < Duration of the effect.
+    delay: uint16           #  < Delay before starting the effect.
+
+    #  Trigger
+    button: uint16          #  < Button that triggers the effect.
+    interval: uint16        #  < How soon it can be triggered again after button.
+
+    #  Custom
+    channels: uint8         #  < Axes to use, minimum of one.
+    period: uint16          #  < Sample periods.
+    samples: uint16         #  < Amount of samples.
+    data: ptr uint16           #  < Should contain channels*samples items.
+
+    #  Envelope
+    attack_length: uint16   #  < Duration of the attack.
+    attack_level: uint16    #  < Level at the start of the attack.
+    fade_length: uint16     #  < Duration of the fade.
+    fade_level: uint16      #  < Level at the end of the fade.
+
+#
+#  \brief The generic template for any haptic effect.
+#
+#  All values max at 32767 (0x7FFF).  Signed values also can be negative.
+#  Time values unless specified otherwise are in milliseconds.
+#
+#  You can also pass ::SDL_HAPTIC_INFINITY to length instead of a 0-32767
+#  value.  Neither delay, interval, attack_length nor fade_length support
+#  ::SDL_HAPTIC_INFINITY.  Fade will also not be used since effect never ends.
+#
+#  Additionally, the ::SDL_HAPTIC_RAMP effect does not support a duration of
+#  ::SDL_HAPTIC_INFINITY.
+#
+#  Button triggers may not be supported on all devices, it is advised to not
+#  use them if possible.  Buttons start at index 1 instead of index 0 like
+#  the joystick.
+#
+#  If both attack_length and fade_level are 0, the envelope is not used,
+#  otherwise both values are used.
+#
+#  Common parts:
+#  \code
+#  // Replay - All effects have this
+#  uint32 length;        // Duration of effect (ms).
+#  uint16 delay;         // Delay before starting effect.
+#
+#  // Trigger - All effects have this
+#  uint16 button;        // Button that triggers effect.
+#  uint16 interval;      // How soon before effect can be triggered again.
+#
+#  // Envelope - All effects except condition effects have this
+#  uint16 attack_length; // Duration of the attack (ms).
+#  uint16 attack_level;  // Level at the start of the attack.
+#  uint16 fade_length;   // Duration of the fade out (ms).
+#  uint16 fade_level;    // Level at the end of the fade.
+#  \endcode
+#
+#
+#  Here we have an example of a constant effect evolution in time:
+#  \verbatim
+#    Strength
+#    ^
+#    |
+#    |    effect level -->  _________________
+#    |                     /                 \
+#    |                    /                   \
+#    |                   /                     \
+#    |                  /                       \
+#    | attack_level --> |                        \
+#    |                  |                        |  <---  fade_level
+#    |
+#    +--------------------------------------------------> Time
+#                       [--]                 [---]
+#                       attack_length        fade_length
+#
+#    [------------------][-----------------------]
+#    delay               length
+#    \endverbatim
+#
+#  Note either the attack_level or the fade_level may be above the actual
+#  effect level.
+#
+#  \sa SDL_HapticConstant
+#  \sa SDL_HapticPeriodic
+#  \sa SDL_HapticCondition
+#  \sa SDL_HapticRamp
+#  \sa SDL_HapticLeftRight
+#  \sa SDL_HapticCustom
+
+type
+  HapticEffect* = object {.union.}
+    #  Common for all force feedback effects
+    kind: uint16                    #  < 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.
+
+
+
+when defined(SDL_Static):
+  static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2."
+else:
+  {.push callConv: cdecl, dynlib: LibName.}
+
+#  Function prototypes
+#
+#  \brief Count the number of haptic devices attached to the system.
+#
+#  \return Number of haptic devices detected on the system.
+
+proc numHaptics*():cint {.importc: "SDL_NumHaptics".}
+
+#
+#  \brief Get the implementation dependent name of a Haptic device.
+#
+#  This can be called before any joysticks are opened.
+#  If no name can be found, this function returns NULL.
+#
+#  \param device_index Index of the device to get its name.
+#  \return Name of the device or NULL on error.
+#
+#  \sa SDL_NumHaptics
+
+proc hapticName*(device_index: cint):cstring {.importc: "SDL_HapticName".}
+
+#
+#  \brief Opens a Haptic device for usage.
+#
+#  The index passed as an argument refers to the N'th Haptic device on this
+#  system.
+#
+#  When opening a haptic device, its gain will be set to maximum and
+#  autocenter will be disabled.  To modify these values use
+#  SDL_HapticSetGain() and SDL_HapticSetAutocenter().
+#
+#  \param device_index Index of the device to open.
+#  \return Device identifier or NULL on error.
+#
+#  \sa SDL_HapticIndex
+#  \sa SDL_HapticOpenFromMouse
+#  \sa SDL_HapticOpenFromJoystick
+#  \sa SDL_HapticClose
+#  \sa SDL_HapticSetGain
+#  \sa SDL_HapticSetAutocenter
+#  \sa SDL_HapticPause
+#  \sa SDL_HapticStopAll
+
+proc hapticOpen*(device_index: cint):HapticPtr {.importc: "SDL_HapticOpen".}
+
+#
+#  \brief Checks if the haptic device at index has been opened.
+#
+#  \param device_index Index to check to see if it has been opened.
+#  \return 1 if it has been opened or 0 if it hasn't.
+#
+#  \sa SDL_HapticOpen
+#  \sa SDL_HapticIndex
+
+proc hapticOpened*(device_index: cint):cint {.importc: "SDL_HapticOpened".}
+
+#
+#  \brief Gets the index of a haptic device.
+#
+#  \param haptic Haptic device to get the index of.
+#  \return The index of the haptic device or -1 on error.
+#
+#  \sa SDL_HapticOpen
+#  \sa SDL_HapticOpened
+
+proc index*(haptic: HapticPtr):cint {.importc: "SDL_HapticIndex".}
+
+#
+#  \brief Gets whether or not the current mouse has haptic capabilities.
+#
+#  \return SDL_TRUE if the mouse is haptic, SDL_FALSE if it isn't.
+#
+#  \sa SDL_HapticOpenFromMouse
+
+proc mouseIsHaptic*():cint {.importc: "SDL_MouseIsHaptic".}
+
+#
+#  \brief Tries to open a haptic device from the current mouse.
+#
+#  \return The haptic device identifier or NULL on error.
+#
+#  \sa SDL_MouseIsHaptic
+#  \sa SDL_HapticOpen
+
+proc hapticOpenFromMouse*():HapticPtr {.importc: "SDL_HapticOpenFromMouse".}
+
+#
+#  \brief Checks to see if a joystick has haptic features.
+#
+#  \param joystick Joystick to test for haptic capabilities.
+#  \return 1 if the joystick is haptic, 0 if it isn't
+#          or -1 if an error ocurred.
+#
+#  \sa SDL_HapticOpenFromJoystick
+
+proc joystickIsHaptic*(joystick: Joystick):cint {.importc: "SDL_JoystickIsHaptic".}
+
+#
+#  \brief Opens a Haptic device for usage from a Joystick device.
+#
+#  You must still close the haptic device seperately.  It will not be closed
+#  with the joystick.
+#
+#  When opening from a joystick you should first close the haptic device before
+#  closing the joystick device.  If not, on some implementations the haptic
+#  device will also get unallocated and you'll be unable to use force feedback
+#  on that device.
+#
+#  \param joystick Joystick to create a haptic device from.
+#  \return A valid haptic device identifier on success or NULL on error.
+#
+#  \sa SDL_HapticOpen
+#  \sa SDL_HapticClose
+
+proc hapticOpenFromJoystick*(joystick: JoystickPtr):HapticPtr {.importc: "SDL_HapticOpenFromJoystick".}
+
+#
+#  \brief Closes a Haptic device previously opened with SDL_HapticOpen().
+#
+#  \param haptic Haptic device to close.
+
+proc close*(haptic: HapticPtr) {.importc: "SDL_HapticClose".}
+
+#
+#  \brief Returns the number of effects a haptic device can store.
+#
+#  On some platforms this isn't fully supported, and therefore is an
+#  approximation.  Always check to see if your created effect was actually
+#  created and do not rely solely on SDL_HapticNumEffects().
+#
+#  \param haptic The haptic device to query effect max.
+#  \return The number of effects the haptic device can store or
+#          -1 on error.
+#
+#  \sa SDL_HapticNumEffectsPlaying
+#  \sa SDL_HapticQuery
+
+proc numEffects*(haptic: HapticPtr):cint {.importc: "SDL_HapticNumEffects".}
+
+#
+#  \brief Returns the number of effects a haptic device can play at the same
+#         time.
+#
+#  This is not supported on all platforms, but will always return a value.
+#  Added here for the sake of completeness.
+#
+#  \param haptic The haptic device to query maximum playing effects.
+#  \return The number of effects the haptic device can play at the same time
+#          or -1 on error.
+#
+#  \sa SDL_HapticNumEffects
+#  \sa SDL_HapticQuery
+
+proc numEffectsPlaying*(haptic: HapticPtr):cint {.importc: "SDL_HapticNumEffectsPlaying".}
+
+#
+#  \brief Gets the haptic devices supported features in bitwise matter.
+#
+#  Example:
+#  \code
+#  if (SDL_HapticQuery(haptic) & SDL_HAPTIC_CONSTANT) {
+#      printf("We have constant haptic effect!");
+#  }
+#  \endcode
+#
+#  \param haptic The haptic device to query.
+#  \return Haptic features in bitwise manner (OR'd).
+#
+#  \sa SDL_HapticNumEffects
+#  \sa SDL_HapticEffectSupported
+
+proc query*(haptic: HapticPtr):uint {.importc: "SDL_HapticQuery".}
+
+
+#
+#  \brief Gets the number of haptic axes the device has.
+#
+#  \sa HapticDirection
+
+proc numAxes*(haptic: HapticPtr):cint {.importc: "SDL_HapticNumAxes".}
+
+#
+#  \brief Checks to see if effect is supported by haptic.
+#
+#  \param haptic Haptic device to check on.
+#  \param effect Effect to check to see if it is supported.
+#  \return SDL_TRUE if effect is supported, SDL_FALSE if it isn't or -1 on error.
+#
+#  \sa SDL_HapticQuery
+#  \sa SDL_HapticNewEffect
+
+proc effectSupported*(haptic: HapticPtr, effect: ptr HapticEffect):cint {.importc: "SDL_HapticEffectSupported".}
+
+#
+#  \brief Creates a new haptic effect on the device.
+#
+#  \param haptic Haptic device to create the effect on.
+#  \param effect Properties of the effect to create.
+#  \return The id of the effect on success or -1 on error.
+#
+#  \sa SDL_HapticUpdateEffect
+#  \sa SDL_HapticRunEffect
+#  \sa SDL_HapticDestroyEffect
+
+proc newEffect*(haptic: HapticPtr, effect: ptr HapticEffect):cint {.importc: "SDL_HapticNewEffect".}
+
+#
+#  \brief Updates the properties of an effect.
+#
+#  Can be used dynamically, although behaviour when dynamically changing
+#  direction may be strange.  Specifically the effect may reupload itself
+#  and start playing from the start.  You cannot change the type either when
+#  running SDL_HapticUpdateEffect().
+#
+#  \param haptic Haptic device that has the effect.
+#  \param effect Effect to update.
+#  \param data New effect properties to use.
+#  \return 0 on success or -1 on error.
+#
+#  \sa SDL_HapticNewEffect
+#  \sa SDL_HapticRunEffect
+#  \sa SDL_HapticDestroyEffect
+
+proc updateEffect*(haptic: HapticPtr, effect: cint, data: ptr HapticEffect):cint {.importc: "SDL_HapticUpdateEffect".}
+
+#
+#  \brief Runs the haptic effect on its associated haptic device.
+#
+#  If iterations are ::SDL_HAPTIC_INFINITY, it'll run the effect over and over
+#  repeating the envelope (attack and fade) every time.  If you only want the
+#  effect to last forever, set ::SDL_HAPTIC_INFINITY in the effect's length
+#  parameter.
+#
+#  \param haptic Haptic device to run the effect on.
+#  \param effect Identifier of the haptic effect to run.
+#  \param iterations Number of iterations to run the effect. Use
+#         ::SDL_HAPTIC_INFINITY for infinity.
+#  \return 0 on success or -1 on error.
+#
+#  \sa SDL_HapticStopEffect
+#  \sa SDL_HapticDestroyEffect
+#  \sa SDL_HapticGetEffectStatus
+
+proc runEffect*(haptic: HapticPtr, effect: cint, iterations: uint32):cint {.importc: "SDL_HapticRunEffect".}
+
+#
+#  \brief Stops the haptic effect on its associated haptic device.
+#
+#  \param haptic Haptic device to stop the effect on.
+#  \param effect Identifier of the effect to stop.
+#  \return 0 on success or -1 on error.
+#
+#  \sa SDL_HapticRunEffect
+#  \sa SDL_HapticDestroyEffect
+
+proc stopEffect*(haptic: HapticPtr, effect: cint):cint {.importc: "SDL_HapticStopEffect".}
+
+#
+#  \brief Destroys a haptic effect on the device.
+#
+#  This will stop the effect if it's running.  Effects are automatically
+#  destroyed when the device is closed.
+#
+#  \param haptic Device to destroy the effect on.
+#  \param effect Identifier of the effect to destroy.
+#
+#  \sa SDL_HapticNewEffect
+
+proc destroyEffect*(haptic: HapticPtr, effect: cint) {.importc: "SDL_HapticDestroyEffect".}
+
+#
+#  \brief Gets the status of the current effect on the haptic device.
+#
+#  Device must support the ::SDL_HAPTIC_STATUS feature.
+#
+#  \param haptic Haptic device to query the effect status on.
+#  \param effect Identifier of the effect to query its status.
+#  \return 0 if it isn't playing, 1 if it is playing or -1 on error.
+#
+#  \sa SDL_HapticRunEffect
+#  \sa SDL_HapticStopEffect
+
+proc getEffectStatus*(haptic: HapticPtr, effect: cint):cint {.importc: "SDL_HapticGetEffectStatus".}
+
+#
+#  \brief Sets the global gain of the device.
+#
+#  Device must support the ::SDL_HAPTIC_GAIN feature.
+#
+#  The user may specify the maximum gain by setting the environment variable
+#  SDL_HAPTIC_GAIN_MAX which should be between 0 and 100.  All calls to
+#  SDL_HapticSetGain() will scale linearly using SDL_HAPTIC_GAIN_MAX as the
+#  maximum.
+#
+#  \param haptic Haptic device to set the gain on.
+#  \param gain Value to set the gain to, should be between 0 and 100.
+#  \return 0 on success or -1 on error.
+#
+#  \sa SDL_HapticQuery
+
+proc setGain*(haptic: HapticPtr, gain: int ):cint {.importc: "SDL_HapticSetGain".}
+
+#
+#  \brief Sets the global autocenter of the device.
+#
+#  Autocenter should be between 0 and 100.  Setting it to 0 will disable
+#  autocentering.
+#
+#  Device must support the ::SDL_HAPTIC_AUTOCENTER feature.
+#
+#  \param haptic Haptic device to set autocentering on.
+#  \param autocenter Value to set autocenter to, 0 disables autocentering.
+#  \return 0 on success or -1 on error.
+#
+#  \sa SDL_HapticQuery
+
+proc setAutocenter*(haptic: HapticPtr, autocenter: int ):cint {.importc: "SDL_HapticSetAutocenter".}
+
+#
+#  \brief Pauses a haptic device.
+#
+#  Device must support the ::SDL_HAPTIC_PAUSE feature.  Call
+#  SDL_HapticUnpause() to resume playback.
+#
+#  Do not modify the effects nor add new ones while the device is paused.
+#  That can cause all sorts of weird errors.
+#
+#  \param haptic Haptic device to pause.
+#  \return 0 on success or -1 on error.
+#
+#  \sa SDL_HapticUnpause
+
+proc pause*(haptic: HapticPtr):cint {.importc: "SDL_HapticPause".}
+
+#
+#  \brief Unpauses a haptic device.
+#
+#  Call to unpause after SDL_HapticPause().
+#
+#  \param haptic Haptic device to pause.
+#  \return 0 on success or -1 on error.
+#
+#  \sa SDL_HapticPause
+
+proc unpause*(haptic: HapticPtr):cint {.importc: "SDL_HapticUnpause".}
+
+#
+#  \brief Stops all the currently playing effects on a haptic device.
+#
+#  \param haptic Haptic device to stop.
+#  \return 0 on success or -1 on error.
+
+proc stopAll*(haptic: HapticPtr):cint {.importc: "SDL_HapticStopAll".}
+
+#
+#  \brief Checks to see if rumble is supported on a haptic device.
+#
+#  \param haptic Haptic device to check to see if it supports rumble.
+#  \return SDL_TRUE if effect is supported, SDL_FALSE if it isn't or -1 on error.
+#
+#  \sa SDL_HapticRumbleInit
+#  \sa SDL_HapticRumblePlay
+#  \sa SDL_HapticRumbleStop
+
+proc rumbleSupported*(haptic: HapticPtr):cint {.importc: "SDL_HapticRumbleSupported".}
+
+#
+#  \brief Initializes the haptic device for simple rumble playback.
+#
+#  \param haptic Haptic device to initialize for simple rumble playback.
+#  \return 0 on success or -1 on error.
+#
+#  \sa SDL_HapticOpen
+#  \sa SDL_HapticRumbleSupported
+#  \sa SDL_HapticRumblePlay
+#  \sa SDL_HapticRumbleStop
+
+proc rumbleInit*(haptic: HapticPtr):cint {.importc: "SDL_HapticRumbleInit".}
+
+#
+#  \brief Runs simple rumble on a haptic device
+#
+#  \param haptic Haptic device to play rumble effect on.
+#  \param strength Strength of the rumble to play as a 0-1 float value.
+#  \param length Length of the rumble to play in milliseconds.
+#  \return 0 on success or -1 on error.
+#
+#  \sa SDL_HapticRumbleSupported
+#  \sa SDL_HapticRumbleInit
+#  \sa SDL_HapticRumbleStop
+
+proc rumblePlay*(haptic: HapticPtr, strength: float, length: uint32 ):cint {.importc: "SDL_HapticRumblePlay".}
+
+#
+#  \brief Stops the simple rumble on a haptic device.
+#
+#  \param haptic Haptic to stop the rumble on.
+#  \return 0 on success or -1 on error.
+#
+#  \sa SDL_HapticRumbleSupported
+#  \sa SDL_HapticRumbleInit
+#  \sa SDL_HapticRumblePlay
+
+proc rumbleStop*(haptic: HapticPtr):cint {.importc: "SDL_HapticRumbleStop".}
+
+when not defined(SDL_Static):
+  {.pop.}

+ 87 - 0
src/nodesnim/thirdparty/sdl2/image.nim

@@ -0,0 +1,87 @@
+import ../sdl2
+
+when not defined(SDL_Static):
+  when defined(windows):
+    const LibName = "SDL2_image.dll"
+  elif defined(macosx):
+    const LibName = "libSDL2_image.dylib"
+  else:
+    const LibName = "libSDL2_image(|-2.0).so(|.0)"
+else:
+  static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2."
+
+const
+  IMG_INIT_JPG* = 0x00000001
+  IMG_INIT_PNG* = 0x00000002
+  IMG_INIT_TIF* = 0x00000004
+  IMG_INIT_WEBP* = 0x00000008
+
+when not defined(SDL_Static):
+  {.push callConv:cdecl, dynlib: LibName.}
+
+proc linkedVersion*(): ptr SDL_version {.importc: "IMG_Linked_Version".}
+
+proc init*(flags: cint = IMG_INIT_JPG or IMG_INIT_PNG): cint {.importc: "IMG_Init".}
+  ## It returns the flags successfully initialized, or 0 on failure.
+  ## This is completely different than SDL_Init() -_-
+
+proc quit*() {.importc: "IMG_Quit".}
+# 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);
+#
+proc loadTyped_RW*(src: RWopsPtr; freesrc: cint; `type`: cstring): SurfacePtr {.importc: "IMG_LoadTyped_RW".}
+# Convenience functions
+proc load*(file: cstring): SurfacePtr {.importc: "IMG_Load".}
+proc load_RW*(src: RWopsPtr; freesrc: cint): SurfacePtr {.importc: "IMG_Load_RW".}
+  ##Load an image directly into a render texture.
+#
+proc loadTexture*(renderer: RendererPtr; file: cstring): TexturePtr {.importc: "IMG_LoadTexture".}
+proc loadTexture_RW*(renderer: RendererPtr; src: RWopsPtr;
+                     freesrc: cint): TexturePtr {.importc: "IMG_LoadTexture_RW".}
+proc loadTextureTyped_RW*(renderer: RendererPtr; src: RWopsPtr;
+                          freesrc: cint; `type`: cstring): TexturePtr {.importc: "IMG_LoadTextureTyped_RW".}
+
+#discard """
+# Functions to detect a file type, given a seekable source
+proc isICO*(src: RWopsPtr): cint {.importc: "IMG_isICO".}
+proc isCUR*(src: RWopsPtr): cint {.importc: "IMG_isCUR".}
+proc isBMP*(src: RWopsPtr): cint {.importc: "IMG_isBMP".}
+proc isGIF*(src: RWopsPtr): cint {.importc: "IMG_isGIF".}
+proc isJPG*(src: RWopsPtr): cint {.importc: "IMG_isJPG".}
+proc isLBM*(src: RWopsPtr): cint {.importc: "IMG_isLBM".}
+proc isPCX*(src: RWopsPtr): cint {.importc: "IMG_isPCX".}
+proc isPNG*(src: RWopsPtr): cint {.importc: "IMG_isPNG".}
+proc isPNM*(src: RWopsPtr): cint {.importc: "IMG_isPNM".}
+proc isTIF*(src: RWopsPtr): cint {.importc: "IMG_isTIF".}
+proc isXCF*(src: RWopsPtr): cint {.importc: "IMG_isXCF".}
+proc isXPM*(src: RWopsPtr): cint {.importc: "IMG_isXPM".}
+proc isXV*(src: RWopsPtr): cint {.importc: "IMG_isXV".}
+proc isWEBP*(src: RWopsPtr): cint {.importc: "IMG_isWEBP".}
+# Individual loading functions
+proc loadICO_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadICO_RW".}
+proc loadCUR_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadCUR_RW".}
+proc loadBMP_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadBMP_RW".}
+proc loadGIF_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadGIF_RW".}
+proc loadJPG_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadJPG_RW".}
+proc loadLBM_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadLBM_RW".}
+proc loadPCX_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadPCX_RW".}
+proc loadPNG_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadPNG_RW".}
+proc loadPNM_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadPNM_RW".}
+proc loadTGA_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadTGA_RW".}
+proc loadTIF_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadTIF_RW".}
+proc loadXCF_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadXCF_RW".}
+proc loadXPM_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadXPM_RW".}
+proc loadXV_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadXV_RW".}
+proc loadWEBP_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadWEBP_RW".}
+proc readXPMFromArray*(xpm: cstringArray): SurfacePtr {.importc: "IMG_ReadXPMFromArray".}
+# Saving functions
+proc savePNG*(surface: SurfacePtr, file: cstring): cint {.importc: "IMG_SavePNG".}
+#"""
+
+when not defined(SDL_Static):
+  {.pop.}

+ 271 - 0
src/nodesnim/thirdparty/sdl2/joystick.nim

@@ -0,0 +1,271 @@
+import "../sdl2"
+
+
+discard """ Simple DirectMedia Layer
+Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+
+
+\file SDL_joystick.h
+
+Include file for SDL joystick event handling
+
+The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks, with the exact joystick
+ behind a device_index changing as joysticks are plugged and unplugged.
+
+The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted
+ then it will get a new instance_id, instance_id's are monotonically increasing identifiers of a joystick plugged in.
+
+The term JoystickGUID is a stable 128-bit identifier for a joystick device that does not change over time, it identifies class of
+ the device (a X360 wired controller for example). This identifier is platform dependent.
+
+"""
+
+#*
+#   \file SDL_joystick.h
+#
+#   In order to use these functions, SDL_Init() must have been called
+#   with the ::SDL_INIT_JOYSTICK flag.  This causes SDL to scan the system
+#   for joysticks, and load appropriate drivers.
+#
+#   If you would like to receive joystick updates while the application
+#   is in the background, you should set the following hint before calling
+#   SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS
+#
+
+# The joystick structure used to identify an SDL joystick#
+type
+  Joystick* = object
+  JoystickPtr* = ptr Joystick
+
+# A structure that encodes the stable unique id for a joystick device#
+type
+  JoystickGuid* = object
+    data: array[16, uint8]
+  JoystickID* = int32
+
+when defined(SDL_Static):
+  static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2."
+else:
+  {.push callConv: cdecl, dynlib: LibName.}
+
+#  Function prototypes# /
+##
+#   Count the number of joysticks attached to the system right now
+# /
+proc numJoysticks*(): cint {.
+  importc: "SDL_NumJoysticks".}
+
+##
+#   Get the implementation dependent name of a joystick.
+#   This can be called before any joysticks are opened.
+#   If no name can be found, this function returns NULL.
+# /
+proc joystickNameForIndex*(device_index: cint): cstring {.
+  importc: "SDL_JoystickNameForIndex".}
+
+##
+#   Open a joystick for use.
+#   The index passed as an argument refers tothe N'th joystick on the system.
+#   This index is the value which will identify this joystick in future joystick
+#   events.
+#
+#   \return A joystick identifier, or NULL if an error occurred.
+# /
+proc joystickOpen*(device_index: cint): JoystickPtr {.
+  importc: "SDL_JoystickOpen".}
+
+##
+#   Return the name for this currently opened joystick.
+#   If no name can be found, this function returns NULL.
+# /
+proc joystickName*(joystick: ptr Joystick): cstring {.importc: "SDL_JoystickName".}
+proc name* (joystick: ptr Joystick): cstring {.inline.} = joystick.joystickName
+
+##
+#   Return the GUID for the joystick at this index
+# /
+proc joystickGetDeviceGUID*(device_index: cint): JoystickGUID {.
+  importc: "SDL_JoystickGetDeviceGUID".}
+
+# *
+#   Return the GUID for this opened joystick
+#
+proc joystickGetGUID*(joystick: JoystickPtr): JoystickGUID {.
+  importc: "SDL_JoystickGetGUID".}
+proc getGUID* (joystick: JoystickPtr): JoystickGUID {.inline.} = joystick.joystickGetGUID
+
+# *
+#   Return a string representation for this guid. pszGUID must point to at least 33 bytes
+#   (32 for the string plus a NULL terminator).
+#
+proc joystickGetGUIDString*(guid: JoystickGUID, pszGUID: cstring, cbGUID: cint) {.
+  importc: "SDL_JoystickGetGUIDString".}
+
+# *
+#   convert a string into a joystick formatted guid
+#
+proc joystickGetGUIDFromString*(pchGUID: cstring): JoystickGUID {.
+  importc: "SDL_JoystickGetGUIDFromString".}
+
+# *
+#   Returns SDL_TRUE if the joystick has been opened and currently connected, or SDL_FALSE if it has not.
+#
+proc joystickGetAttached*(joystick: JoystickPtr): Bool32 {.
+  importc: "SDL_JoystickGetAttached".}
+proc getAttached* (joystick: JoystickPtr): Bool32 {.inline.} = joystick.joystickGetAttached
+
+# *
+#   Get the instance ID of an opened joystick or -1 if the joystick is invalid.
+#
+proc joystickInstanceID*(joystick: JoystickPtr): JoystickID {.
+  importc: "SDL_JoystickInstanceID".}
+proc instanceID* (joystick: JoystickPtr): JoystickID {.inline.} = joystick.joystickInstanceID
+
+# *
+#   Get the number of general axis controls on a joystick.
+#
+proc joystickNumAxes*(joystick: JoystickPtr): cint {.
+  importc: "SDL_JoystickNumAxes".}
+proc numAxes* (joystick: JoystickPtr): cint {.inline.} = joystick.joystickNumAxes
+
+# *
+#   Get the number of trackballs on a joystick.
+#
+#   Joystick trackballs have only relative motion events associated
+#   with them and their state cannot be polled.
+#   events are enabled.
+#
+proc joystickNumBalls*(joystick: JoystickPtr): cint {.
+  importc: "SDL_JoystickNumBalls".}
+proc numBalls* (joystick: JoystickPtr): cint {.inline.} = joystick.joystickNumBalls
+
+#
+#   Get the number of POV hats on a joystick.
+#
+proc joystickNumHats*(joystick: JoystickPtr): cint {.
+  importc: "SDL_JoystickNumHats".}
+proc numHats* (joystick: JoystickPtr): cint {.inline.} = joystick.joystickNumHats
+
+#
+#   Get the number of buttons on a joystick.
+#
+proc joystickNumButtons*(joystick: JoystickPtr): cint {.
+  importc: "SDL_JoystickNumButtons".}
+proc numButtons* (joystick: JoystickPtr): cint {.inline.} = joystick.joystickNumButtons
+
+#
+#   Update the current state of the open joysticks.
+#
+#   This is called automatically by the event loop if any joystick
+#
+proc joystickUpdate*() {.
+  importc: "SDL_JoystickUpdate".}
+
+#
+#   Enable/disable joystick event polling.
+#
+#   If joystick events are disabled, you must call SDL_JoystickUpdate()
+#   yourself and check the state of the joystick when you want joystick
+#   information.
+#
+#   The state can be one of ::SDL_QUERY, ::SDL_ENABLE or ::SDL_IGNORE.
+#
+proc joystickEventState*(state: cint): cint {.
+  importc: "SDL_JoystickEventState".}
+
+#
+#   Get the current state of an axis control on a joystick.
+#
+#   The state is a value ranging from -32768 to 32767.
+#
+#   The axis indices start at index 0.
+#
+proc joystickGetAxis*(joystick: JoystickPtr, axis: cint): int16 {.
+  importc: "SDL_JoystickGetAxis".}
+proc getAxis* (joystick: JoystickPtr, axis: cint): int16 {.inline.} = joystick.joystickGetAxis(axis)
+
+#
+#   \name Hat positions
+#
+#  @{#
+const
+  SDL_HAT_CENTERED*:cint = (0x00000000)
+  SDL_HAT_UP*:cint = (0x00000001)
+  SDL_HAT_RIGHT*:cint = (0x00000002)
+  SDL_HAT_DOWN*:cint = (0x00000004)
+  SDL_HAT_LEFT*:cint = (0x00000008)
+  SDL_HAT_RIGHTUP*:cint = (SDL_HAT_RIGHT or SDL_HAT_UP)
+  SDL_HAT_RIGHTDOWN*:cint = (SDL_HAT_RIGHT or SDL_HAT_DOWN)
+  SDL_HAT_LEFTUP*:cint = (SDL_HAT_LEFT or SDL_HAT_UP)
+  SDL_HAT_LEFTDOWN*:cint = (SDL_HAT_LEFT or SDL_HAT_DOWN)
+#  @}#
+
+#
+#   Get the current state of a POV hat on a joystick.
+#
+#   The hat indices start at index 0.
+#
+#   \return The return value is one of the following positions:
+#            - ::SDL_HAT_CENTERED
+#            - ::SDL_HAT_UP
+#            - ::SDL_HAT_RIGHT
+#            - ::SDL_HAT_DOWN
+#            - ::SDL_HAT_LEFT
+#            - ::SDL_HAT_RIGHTUP
+#            - ::SDL_HAT_RIGHTDOWN
+#            - ::SDL_HAT_LEFTUP
+#            - ::SDL_HAT_LEFTDOWN
+#
+proc joystickGetHat*(joystick: JoystickPtr, hat: cint): uint8 {.
+  importc: "SDL_JoystickGetHat".}
+proc getHat* (joystick: JoystickPtr, hat: cint): uint8 {.inline.} = joystick.joystickGetHat(hat)
+
+#
+#   Get the ball axis change since the last poll.
+#
+#   \return 0, or -1 if you passed it invalid parameters.
+#
+#   The ball indices start at index 0.
+#
+proc joystickGetBall*(joystick: JoystickPtr, ball: cint, dx: ptr cint, dy: ptr cint): cint {.
+  importc: "SDL_JoystickGetBall".}
+proc getBall* (joystick: JoystickPtr, ball: cint, dx: ptr cint, dy: ptr cint): cint {.inline.} = joystick.joystickGetBall(ball, dx, dy)
+
+#
+#   Get the current state of a button on a joystick.
+#
+#   The button indices start at index 0.
+#
+proc joystickGetButton*(joystick: JoystickPtr, button: cint): uint8 {.
+  importc: "SDL_JoystickGetButton".}
+proc getButton* (joystick: JoystickPtr, button: cint): uint8 {.inline.} = joystick.joystickGetButton(button)
+
+#
+#   Close a joystick previously opened with SDL_JoystickOpen().
+#
+proc joystickClose*(joystick: JoystickPtr) {.
+  importc: "SDL_JoystickClose".}
+proc close* (joystick: JoystickPtr) {.inline.} = joystick.joystickClose()
+
+# Ends C function definitions when using C++
+
+# vi: set ts=4 sw=4 expandtab:
+when not defined(SDL_Static):
+  {.pop.}

+ 633 - 0
src/nodesnim/thirdparty/sdl2/mixer.nim

@@ -0,0 +1,633 @@
+#
+#  SDL_mixer:  An audio mixer library based on the SDL library
+#  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+#
+#  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.
+#
+
+{.deadCodeElim: on.}
+# Dynamically link to the correct library for our system:
+
+when not defined(SDL_Static):
+  when defined(windows):
+    const LibName* = "SDL2_mixer.dll"
+  elif defined(macosx):
+    const LibName* = "libSDL2_mixer.dylib"
+  else:
+    const LibName* = "libSDL2_mixer(|-2.0).so(|.0)"
+else:
+  static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2."
+
+when not defined(SDL_Static):
+  {.push callConv:cdecl, dynlib: LibName.}
+
+import sdl2, sdl2.audio
+
+when system.cpuEndian == littleEndian: # SDL_BYTEORDER == SDL_LIL_ENDIAN
+  const
+    MIX_DEFAULT_FORMAT* = AUDIO_S16LSB
+else:
+  const
+    MIX_DEFAULT_FORMAT* = AUDIO_S16MSB
+
+# Remove prefixes in our wrapper, we have modules in Nim:
+
+# These are not recognized by c2nim, but that's easy to fix:
+
+# This function gets the version of the dynamically linked SDL_mixer library.
+#   it should NOT be used to fill a version structure, instead you should
+#   use the SDL_MIXER_VERSION() macro.
+#
+
+proc linkedVersion*(): ptr SDL_version {.importc: "Mix_Linked_Version".}
+
+const
+    MIX_INIT_FLAC*       : cint = 0x00000001
+    MIX_INIT_MOD*        : cint = 0x00000002
+    MIX_INIT_MODPLUG*    : cint = 0x00000004
+    MIX_INIT_MP3*        : cint = 0x00000008
+    MIX_INIT_OGG*        : cint = 0x00000010
+    MIX_INIT_FLUIDSYNTH* : cint = 0x00000020
+
+
+# Loads dynamic libraries and prepares them for use.  Flags should be
+#   one or more flags from MIX_InitFlags OR'd together.
+#   It returns the flags successfully initialized, or 0 on failure.
+#
+
+proc init*(flags: cint): cint {.importc: "Mix_Init".}
+# Unloads libraries loaded with Mix_Init
+
+proc quit*() {.importc: "Mix_Quit".}
+# The default mixer has 8 simultaneous mixing channels
+
+const
+  MIX_CHANNELS* = 8
+
+# Good default values for a PC soundcard
+
+const
+  MIX_DEFAULT_FREQUENCY* = 22050
+  MIX_DEFAULT_CHANNELS* = 2
+
+# Volume of a chunk
+
+const
+  MIX_MAX_VOLUME* = 128
+
+# The internal format for an audio chunk
+
+type
+  ChunkPtr* = ptr Chunk
+  Chunk* = object
+    allocated*: cint
+    abuf*: ptr uint8
+    alen*: uint32
+    volume*: uint8            # Per-sample volume, 0-128
+
+
+# The different fading types supported
+
+type
+  Fading* {.size: sizeof(cint).} = enum
+    MIX_NO_FADING, MIX_FADING_OUT, MIX_FADING_IN
+  MusicType* {.size: sizeof(cint).} = enum
+    MUS_NONE, MUS_CMD, MUS_WAV, MUS_MOD, MUS_MID, MUS_OGG, MUS_MP3, MUS_MP3_MAD,
+    MUS_FLAC, MUS_MODPLUG
+
+
+
+# The internal format for a music chunk interpreted via mikmod
+
+type
+  MusicPtr* = ptr Music
+  Music* = object
+
+
+# Open the mixer with a certain audio format
+
+proc openAudio*(frequency: cint; format: uint16; channels: cint;
+                    chunksize: cint): cint {.importc: "Mix_OpenAudio".}
+# Dynamically change the number of channels managed by the mixer.
+#   If decreasing the number of channels, the upper channels are
+#   stopped.
+#   This function returns the new number of allocated channels.
+#
+
+proc allocateChannels*(numchans: cint): cint {.
+    importc: "Mix_AllocateChannels".}
+# Find out what the actual audio device parameters are.
+#   This function returns 1 if the audio has been opened, 0 otherwise.
+#
+
+proc querySpec*(frequency: ptr cint; format: ptr uint16; channels: ptr cint): cint {.
+    importc: "Mix_QuerySpec".}
+# Load a wave file or a music (.mod .s3m .it .xm) file
+
+proc loadWAV_RW*(src: RWopsPtr; freesrc: cint): ptr Chunk {.importc: "Mix_LoadWAV_RW".}
+
+template loadWAV*(file: untyped): untyped =
+  loadWAV_RW(rwFromFile(file, "rb"), 1)
+
+proc loadMUS*(file: cstring): ptr Music {.importc: "Mix_LoadMUS".}
+# Load a music file from an SDL_RWops object (Ogg and MikMod specific currently)
+#   Matt Campbell (matt@campbellhome.dhs.org) April 2000
+
+proc loadMUS_RW*(src: RWopsPtr; freesrc: cint): ptr Music {.
+    importc: "Mix_LoadMUS_RW".}
+# Load a music file from an SDL_RWops object assuming a specific format
+
+proc loadMUSType_RW*(src: RWopsPtr; `type`: MusicType; freesrc: cint): ptr Music {.
+    importc: "Mix_LoadMUSType_RW".}
+# Load a wave file of the mixer format from a memory buffer
+
+proc quickLoad_WAV*(mem: ptr uint8): ptr Chunk {.importc: "Mix_QuickLoad_WAV".}
+# Load raw audio data of the mixer format from a memory buffer
+
+proc quickLoad_RAW*(mem: ptr uint8; len: uint32): ptr Chunk {.importc: "Mix_QuickLoad_RAW".}
+# Free an audio chunk previously loaded
+
+proc freeChunk*(chunk: ptr Chunk) {.importc: "Mix_FreeChunk".}
+proc freeMusic*(music: ptr Music) {.importc: "Mix_FreeMusic".}
+# Get a list of chunk/music decoders that this build of SDL_mixer provides.
+#   This list can change between builds AND runs of the program, if external
+#   libraries that add functionality become available.
+#   You must successfully call Mix_OpenAudio() before calling these functions.
+#   This API is only available in SDL_mixer 1.2.9 and later.
+#
+#   // usage...
+#   int i;
+#   const int total = Mix_GetNumChunkDecoders();
+#   for (i = 0; i < total; i++)
+#       printf("Supported chunk decoder: [%s]\n", Mix_GetChunkDecoder(i));
+#
+#   Appearing in this list doesn't promise your specific audio file will
+#   decode...but it's handy to know if you have, say, a functioning Timidity
+#   install.
+#
+#   These return values are static, read-only data; do not modify or free it.
+#   The pointers remain valid until you call Mix_CloseAudio().
+#
+
+proc getNumChunkDecoders*(): cint {.importc: "Mix_GetNumChunkDecoders".}
+proc getChunkDecoder*(index: cint): cstring {.importc: "Mix_GetChunkDecoder".}
+proc getNumMusicDecoders*(): cint {.importc: "Mix_GetNumMusicDecoders".}
+proc getMusicDecoder*(index: cint): cstring {.importc: "Mix_GetMusicDecoder".}
+# Find out the music format of a mixer music, or the currently playing
+#   music, if 'music' is NULL.
+#
+
+proc getMusicType*(music: ptr Music): MusicType {.importc: "Mix_GetMusicType".}
+# Set a function that is called after all mixing is performed.
+#   This can be used to provide real-time visual display of the audio stream
+#   or add a custom mixer filter for the stream data.
+#
+
+proc setPostMix*(mix_func: proc (udata: pointer; stream: ptr uint8;
+                                     len: cint) {.cdecl.}; arg: pointer) {.importc: "Mix_SetPostMix".}
+# Add your own music player or additional mixer function.
+#   If 'mix_func' is NULL, the default music player is re-enabled.
+#
+
+proc hookMusic*(mix_func: proc (udata: pointer; stream: ptr uint8; len: cint) {.
+    cdecl.}; arg: pointer) {.importc: "Mix_HookMusic".}
+# Add your own callback when the music has finished playing.
+#   This callback is only called if the music finishes naturally.
+#
+
+proc hookMusicFinished*(music_finished: proc () {.cdecl.}) {.importc: "Mix_HookMusicFinished".}
+# Get a pointer to the user data for the current music hook
+
+proc getMusicHookData*(): pointer {.importc: "Mix_GetMusicHookData".}
+#
+#  Add your own callback when a channel has finished playing. NULL
+#   to disable callback. The callback may be called from the mixer's audio
+#   callback or it could be called as a result of Mix_HaltChannel(), etc.
+#   do not call SDL_LockAudio() from this callback; you will either be
+#   inside the audio callback, or SDL_mixer will explicitly lock the audio
+#   before calling your callback.
+#
+
+proc channelFinished*(channel_finished: proc (channel: cint) {.cdecl.}) {.importc: "Mix_ChannelFinished".}
+# Special Effects API by ryan c. gordon. (icculus@icculus.org)
+
+const
+  MIX_CHANNEL_POST* = - 2
+
+# This is the format of a special effect callback:
+#
+#    myeffect(int chan, void *stream, int len, void *udata);
+#
+#  (chan) is the channel number that your effect is affecting. (stream) is
+#   the buffer of data to work upon. (len) is the size of (stream), and
+#   (udata) is a user-defined bit of data, which you pass as the last arg of
+#   Mix_RegisterEffect(), and is passed back unmolested to your callback.
+#   Your effect changes the contents of (stream) based on whatever parameters
+#   are significant, or just leaves it be, if you prefer. You can do whatever
+#   you like to the buffer, though, and it will continue in its changed state
+#   down the mixing pipeline, through any other effect functions, then finally
+#   to be mixed with the rest of the channels and music for the final output
+#   stream.
+#
+#  DO NOT EVER call SDL_LockAudio() from your callback function!
+#
+
+type
+  Mix_EffectFunc_t* = proc (chan: cint; stream: pointer; len: cint;
+                            udata: pointer) {.cdecl.}
+
+#
+#  This is a callback that signifies that a channel has finished all its
+#   loops and has completed playback. This gets called if the buffer
+#   plays out normally, or if you call Mix_HaltChannel(), implicitly stop
+#   a channel via Mix_AllocateChannels(), or unregister a callback while
+#   it's still playing.
+#
+#  DO NOT EVER call SDL_LockAudio() from your callback function!
+#
+
+type
+  Mix_EffectDone_t* = proc (chan: cint; udata: pointer) {.cdecl.}
+
+# Register a special effect function. At mixing time, the channel data is
+#   copied into a buffer and passed through each registered effect function.
+#   After it passes through all the functions, it is mixed into the final
+#   output stream. The copy to buffer is performed once, then each effect
+#   function performs on the output of the previous effect. Understand that
+#   this extra copy to a buffer is not performed if there are no effects
+#   registered for a given chunk, which saves CPU cycles, and any given
+#   effect will be extra cycles, too, so it is crucial that your code run
+#   fast. Also note that the data that your function is given is in the
+#   format of the sound device, and not the format you gave to Mix_OpenAudio(),
+#   although they may in reality be the same. This is an unfortunate but
+#   necessary speed concern. Use Mix_QuerySpec() to determine if you can
+#   handle the data before you register your effect, and take appropriate
+#   actions.
+#  You may also specify a callback (Mix_EffectDone_t) that is called when
+#   the channel finishes playing. This gives you a more fine-grained control
+#   than Mix_ChannelFinished(), in case you need to free effect-specific
+#   resources, etc. If you don't need this, you can specify NULL.
+#  You may set the callbacks before or after calling Mix_PlayChannel().
+#  Things like Mix_SetPanning() are just internal special effect functions,
+#   so if you are using that, you've already incurred the overhead of a copy
+#   to a separate buffer, and that these effects will be in the queue with
+#   any functions you've registered. The list of registered effects for a
+#   channel is reset when a chunk finishes playing, so you need to explicitly
+#   set them with each call to Mix_PlayChannel*().
+#  You may also register a special effect function that is to be run after
+#   final mixing occurs. The rules for these callbacks are identical to those
+#   in Mix_RegisterEffect, but they are run after all the channels and the
+#   music have been mixed into a single stream, whereas channel-specific
+#   effects run on a given channel before any other mixing occurs. These
+#   global effect callbacks are call "posteffects". Posteffects only have
+#   their Mix_EffectDone_t function called when they are unregistered (since
+#   the main output stream is never "done" in the same sense as a channel).
+#   You must unregister them manually when you've had enough. Your callback
+#   will be told that the channel being mixed is (MIX_CHANNEL_POST) if the
+#   processing is considered a posteffect.
+#
+#  After all these effects have finished processing, the callback registered
+#   through Mix_SetPostMix() runs, and then the stream goes to the audio
+#   device.
+#
+#  DO NOT EVER call SDL_LockAudio() from your callback function!
+#
+#  returns zero if error (no such channel), nonzero if added.
+#   Error messages can be retrieved from Mix_GetError().
+#
+
+proc registerEffect*(chan: cint; f: Mix_EffectFunc_t; d: Mix_EffectDone_t;
+                         arg: pointer): cint {.importc: "Mix_RegisterEffect".}
+# You may not need to call this explicitly, unless you need to stop an
+#   effect from processing in the middle of a chunk's playback.
+#  Posteffects are never implicitly unregistered as they are for channels,
+#   but they may be explicitly unregistered through this function by
+#   specifying MIX_CHANNEL_POST for a channel.
+#  returns zero if error (no such channel or effect), nonzero if removed.
+#   Error messages can be retrieved from Mix_GetError().
+#
+
+proc unregisterEffect*(channel: cint; f: Mix_EffectFunc_t): cint {.importc: "Mix_UnregisterEffect".}
+# You may not need to call this explicitly, unless you need to stop all
+#   effects from processing in the middle of a chunk's playback. Note that
+#   this will also shut off some internal effect processing, since
+#   Mix_SetPanning() and others may use this API under the hood. This is
+#   called internally when a channel completes playback.
+#  Posteffects are never implicitly unregistered as they are for channels,
+#   but they may be explicitly unregistered through this function by
+#   specifying MIX_CHANNEL_POST for a channel.
+#  returns zero if error (no such channel), nonzero if all effects removed.
+#   Error messages can be retrieved from Mix_GetError().
+#
+
+proc unregisterAllEffects*(channel: cint): cint {.importc: "Mix_UnregisterAllEffects".}
+
+const
+  MIX_EFFECTSMAXSPEED* = "MIX_EFFECTSMAXSPEED"
+
+#
+#  These are the internally-defined mixing effects. They use the same API that
+#   effects defined in the application use, but are provided here as a
+#   convenience. Some effects can reduce their quality or use more memory in
+#   the name of speed; to enable this, make sure the environment variable
+#   MIX_EFFECTSMAXSPEED (see above) is defined before you call
+#   Mix_OpenAudio().
+#
+# Set the panning of a channel. The left and right channels are specified
+#   as integers between 0 and 255, quietest to loudest, respectively.
+#
+#  Technically, this is just individual volume control for a sample with
+#   two (stereo) channels, so it can be used for more than just panning.
+#   If you want real panning, call it like this:
+#
+#    Mix_SetPanning(channel, left, 255 - left);
+#
+#  ...which isn't so hard.
+#
+#  Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
+#   the panning will be done to the final mixed stream before passing it on
+#   to the audio device.
+#
+#  This uses the Mix_RegisterEffect() API internally, and returns without
+#   registering the effect function if the audio device is not configured
+#   for stereo output. Setting both (left) and (right) to 255 causes this
+#   effect to be unregistered, since that is the data's normal state.
+#
+#  returns zero if error (no such channel or Mix_RegisterEffect() fails),
+#   nonzero if panning effect enabled. Note that an audio device in mono
+#   mode is a no-op, but this call will return successful in that case.
+#   Error messages can be retrieved from Mix_GetError().
+#
+
+proc setPanning*(channel: cint; left: uint8; right: uint8): cint {.importc: "Mix_SetPanning".}
+# Set the position of a channel. (angle) is an integer from 0 to 360, that
+#   specifies the location of the sound in relation to the listener. (angle)
+#   will be reduced as neccesary (540 becomes 180 degrees, -100 becomes 260).
+#   Angle 0 is due north, and rotates clockwise as the value increases.
+#   For efficiency, the precision of this effect may be limited (angles 1
+#   through 7 might all produce the same effect, 8 through 15 are equal, etc).
+#   (distance) is an integer between 0 and 255 that specifies the space
+#   between the sound and the listener. The larger the number, the further
+#   away the sound is. Using 255 does not guarantee that the channel will be
+#   culled from the mixing process or be completely silent. For efficiency,
+#   the precision of this effect may be limited (distance 0 through 5 might
+#   all produce the same effect, 6 through 10 are equal, etc). Setting (angle)
+#   and (distance) to 0 unregisters this effect, since the data would be
+#   unchanged.
+#
+#  If you need more precise positional audio, consider using OpenAL for
+#   spatialized effects instead of SDL_mixer. This is only meant to be a
+#   basic effect for simple "3D" games.
+#
+#  If the audio device is configured for mono output, then you won't get
+#   any effectiveness from the angle; however, distance attenuation on the
+#   channel will still occur. While this effect will function with stereo
+#   voices, it makes more sense to use voices with only one channel of sound,
+#   so when they are mixed through this effect, the positioning will sound
+#   correct. You can convert them to mono through SDL before giving them to
+#   the mixer in the first place if you like.
+#
+#  Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
+#   the positioning will be done to the final mixed stream before passing it
+#   on to the audio device.
+#
+#  This is a convenience wrapper over Mix_SetDistance() and Mix_SetPanning().
+#
+#  returns zero if error (no such channel or Mix_RegisterEffect() fails),
+#   nonzero if position effect is enabled.
+#   Error messages can be retrieved from Mix_GetError().
+#
+
+proc setPosition*(channel: cint; angle: int16; distance: uint8): cint {.importc: "Mix_SetPosition".}
+# Set the "distance" of a channel. (distance) is an integer from 0 to 255
+#   that specifies the location of the sound in relation to the listener.
+#   Distance 0 is overlapping the listener, and 255 is as far away as possible
+#   A distance of 255 does not guarantee silence; in such a case, you might
+#   want to try changing the chunk's volume, or just cull the sample from the
+#   mixing process with Mix_HaltChannel().
+#  For efficiency, the precision of this effect may be limited (distances 1
+#   through 7 might all produce the same effect, 8 through 15 are equal, etc).
+#   (distance) is an integer between 0 and 255 that specifies the space
+#   between the sound and the listener. The larger the number, the further
+#   away the sound is.
+#  Setting (distance) to 0 unregisters this effect, since the data would be
+#   unchanged.
+#  If you need more precise positional audio, consider using OpenAL for
+#   spatialized effects instead of SDL_mixer. This is only meant to be a
+#   basic effect for simple "3D" games.
+#
+#  Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
+#   the distance attenuation will be done to the final mixed stream before
+#   passing it on to the audio device.
+#
+#  This uses the Mix_RegisterEffect() API internally.
+#
+#  returns zero if error (no such channel or Mix_RegisterEffect() fails),
+#   nonzero if position effect is enabled.
+#   Error messages can be retrieved from Mix_GetError().
+#
+
+proc setDistance*(channel: cint; distance: uint8): cint {.importc: "Mix_SetDistance".}
+#
+#  !!! FIXME : Haven't implemented, since the effect goes past the
+#               end of the sound buffer. Will have to think about this.
+#                --ryan.
+#
+
+when false:
+  # Causes an echo effect to be mixed into a sound. (echo) is the amount
+  #   of echo to mix. 0 is no echo, 255 is infinite (and probably not
+  #   what you want).
+  #
+  #  Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
+  #   the reverbing will be done to the final mixed stream before passing it on
+  #   to the audio device.
+  #
+  #  This uses the Mix_RegisterEffect() API internally. If you specify an echo
+  #   of zero, the effect is unregistered, as the data is already in that state.
+  #
+  #  returns zero if error (no such channel or Mix_RegisterEffect() fails),
+  #   nonzero if reversing effect is enabled.
+  #   Error messages can be retrieved from Mix_GetError().
+  #
+  proc setReverb*(channel: cint; echo: uint8): cint {.importc: "Mix_SetReverb".}
+# Causes a channel to reverse its stereo. This is handy if the user has his
+#   speakers hooked up backwards, or you would like to have a minor bit of
+#   psychedelia in your sound code.  :)  Calling this function with (flip)
+#   set to non-zero reverses the chunks's usual channels. If (flip) is zero,
+#   the effect is unregistered.
+#
+#  This uses the Mix_RegisterEffect() API internally, and thus is probably
+#   more CPU intensive than having the user just plug in his speakers
+#   correctly. Mix_SetReverseStereo() returns without registering the effect
+#   function if the audio device is not configured for stereo output.
+#
+#  If you specify MIX_CHANNEL_POST for (channel), then this the effect is used
+#   on the final mixed stream before sending it on to the audio device (a
+#   posteffect).
+#
+#  returns zero if error (no such channel or Mix_RegisterEffect() fails),
+#   nonzero if reversing effect is enabled. Note that an audio device in mono
+#   mode is a no-op, but this call will return successful in that case.
+#   Error messages can be retrieved from Mix_GetError().
+#
+
+proc setReverseStereo*(channel: cint; flip: cint): cint {.importc: "Mix_SetReverseStereo".}
+# end of effects API. --ryan.
+# Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate
+#   them dynamically to the next sample if requested with a -1 value below.
+#   Returns the number of reserved channels.
+#
+
+proc reserveChannels*(num: cint): cint {.importc: "Mix_ReserveChannels".}
+# Channel grouping functions
+# Attach a tag to a channel. A tag can be assigned to several mixer
+#   channels, to form groups of channels.
+#   If 'tag' is -1, the tag is removed (actually -1 is the tag used to
+#   represent the group of all the channels).
+#   Returns true if everything was OK.
+#
+
+proc groupChannel*(which: cint; tag: cint): cint {.importc: "Mix_GroupChannel".}
+# Assign several consecutive channels to a group
+
+proc groupChannels*(`from`: cint; to: cint; tag: cint): cint {.importc: "Mix_GroupChannels".}
+# Finds the first available channel in a group of channels,
+#   returning -1 if none are available.
+#
+
+proc groupAvailable*(tag: cint): cint {.importc: "Mix_GroupAvailable".}
+# Returns the number of channels in a group. This is also a subtle
+#   way to get the total number of channels when 'tag' is -1
+#
+
+proc groupCount*(tag: cint): cint {.importc: "Mix_GroupCount".}
+# Finds the "oldest" sample playing in a group of channels
+
+proc groupOldest*(tag: cint): cint {.importc: "Mix_GroupOldest".}
+# Finds the "most recent" (i.e. last) sample playing in a group of channels
+
+proc groupNewer*(tag: cint): cint {.importc: "Mix_GroupNewer".}
+# Play an audio chunk on a specific channel.
+#   If the specified channel is -1, play on the first free channel.
+#   If 'loops' is greater than zero, loop the sound that many times.
+#   If 'loops' is -1, loop inifinitely (~65000 times).
+#   The sound is played at most 'ticks' milliseconds. If -1, play forever.
+#   Returns which channel was used to play the sound.
+#
+
+proc playChannelTimed*(channel: cint; chunk: ptr Chunk; loops: cint;
+                           ticks: cint): cint {.importc: "Mix_PlayChannelTimed".}
+
+# The same as above, but the sound is played forever
+
+template playChannel*(channel, chunk, loops: untyped): untyped =
+  playChannelTimed(channel, chunk, loops, - 1)
+
+proc playMusic*(music: ptr Music; loops: cint): cint {.importc: "Mix_PlayMusic".}
+# Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions
+
+proc fadeInMusic*(music: ptr Music; loops: cint; ms: cint): cint {.importc: "Mix_FadeInMusic".}
+proc fadeInMusicPos*(music: ptr Music; loops: cint; ms: cint;
+                         position: cdouble): cint {.importc: "Mix_FadeInMusicPos".}
+template fadeInChannel*(channel, chunk, loops, ms: untyped): untyped =
+  fadeInChannelTimed(channel, chunk, loops, ms, - 1)
+
+proc fadeInChannelTimed*(channel: cint; chunk: ptr Chunk; loops: cint;
+                             ms: cint; ticks: cint): cint {.importc: "Mix_FadeInChannelTimed".}
+# Set the volume in the range of 0-128 of a specific channel or chunk.
+#   If the specified channel is -1, set volume for all channels.
+#   Returns the original volume.
+#   If the specified volume is -1, just return the current volume.
+#
+
+proc volume*(channel: cint; volume: cint): cint {.importc: "Mix_Volume".}
+proc volumeChunk*(chunk: ptr Chunk; volume: cint): cint {.importc: "Mix_VolumeChunk".}
+proc volumeMusic*(volume: cint): cint {.importc: "Mix_VolumeMusic".}
+# Halt playing of a particular channel
+
+proc haltChannel*(channel: cint): cint {.importc: "Mix_HaltChannel".}
+proc haltGroup*(tag: cint): cint {.importc: "Mix_HaltGroup".}
+proc haltMusic*(): cint {.importc: "Mix_HaltMusic".}
+# Change the expiration delay for a particular channel.
+#   The sample will stop playing after the 'ticks' milliseconds have elapsed,
+#   or remove the expiration if 'ticks' is -1
+#
+
+proc expireChannel*(channel: cint; ticks: cint): cint {.importc: "Mix_ExpireChannel".}
+# Halt a channel, fading it out progressively till it's silent
+#   The ms parameter indicates the number of milliseconds the fading
+#   will take.
+#
+
+proc fadeOutChannel*(which: cint; ms: cint): cint {.importc: "Mix_FadeOutChannel".}
+proc fadeOutGroup*(tag: cint; ms: cint): cint {.importc: "Mix_FadeOutGroup".}
+proc fadeOutMusic*(ms: cint): cint {.importc: "Mix_FadeOutMusic".}
+# Query the fading status of a channel
+
+proc fadingMusic*(): Fading {.importc: "Mix_FadingMusic".}
+proc fadingChannel*(which: cint): Fading {.importc: "Mix_FadingChannel".}
+# Pause/Resume a particular channel
+
+proc pause*(channel: cint) {.importc: "Mix_Pause".}
+proc resume*(channel: cint) {.importc: "Mix_Resume".}
+proc paused*(channel: cint): cint {.importc: "Mix_Paused".}
+# Pause/Resume the music stream
+
+proc pauseMusic*() {.importc: "Mix_PauseMusic".}
+proc resumeMusic*() {.importc: "Mix_ResumeMusic".}
+proc rewindMusic*() {.importc: "Mix_RewindMusic".}
+proc pausedMusic*(): cint {.importc: "Mix_PausedMusic".}
+# Set the current position in the music stream.
+#   This returns 0 if successful, or -1 if it failed or isn't implemented.
+#   This function is only implemented for MOD music formats (set pattern
+#   order number) and for OGG, FLAC, MP3_MAD, and MODPLUG music (set
+#   position in seconds), at the moment.
+#
+
+proc setMusicPosition*(position: cdouble): cint {.importc: "Mix_SetMusicPosition".}
+
+# Check the status of a specific channel.
+#   If the specified channel is -1, check all channels.
+#
+proc playing*(channel: cint): cint {.importc: "Mix_Playing".}
+proc playingMusic*(): cint {.importc: "Mix_PlayingMusic".}
+
+# Stop music and set external music playback command
+proc setMusicCMD*(command: cstring): cint {.importc: "Mix_SetMusicCMD".}
+# Synchro value is set by MikMod from modules while playing
+
+proc setSynchroValue*(value: cint): cint {.importc: "Mix_SetSynchroValue".}
+proc getSynchroValue*(): cint {.importc: "Mix_GetSynchroValue".}
+# Set/Get/Iterate SoundFonts paths to use by supported MIDI backends
+
+proc setSoundFonts*(paths: cstring): cint {.
+    importc: "Mix_SetSoundFonts".}
+proc getSoundFonts*(): cstring {.importc: "Mix_GetSoundFonts".}
+proc eachSoundFont*(function: proc (a2: cstring; a3: pointer): cint {.cdecl.};
+                        data: pointer): cint {.importc: "Mix_EachSoundFont".}
+# Get the Chunk currently associated with a mixer channel
+#    Returns NULL if it's an invalid channel, or there's no chunk associated.
+#
+
+proc getChunk*(channel: cint): ptr Chunk {.importc: "Mix_GetChunk".}
+# Close the mixer, halting all playing audio
+
+proc closeAudio*() {.importc: "Mix_CloseAudio".}
+
+when not defined(SDL_Static):
+  {.pop.}

+ 301 - 0
src/nodesnim/thirdparty/sdl2/net.nim

@@ -0,0 +1,301 @@
+#
+#  SDL_net:  An example cross-platform network library for use with SDL
+#  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+#  Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com>
+#
+#  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.
+#
+# $Id$
+import sdl2
+
+when not defined(SDL_Static):
+  when defined(windows):
+    const LibName* = "SDL2_net.dll"
+  elif defined(macosx):
+    const LibName* = "libSDL2_net.dylib"
+  else:
+    const LibName* = "libSDL2_net(|-2.0).so(|.0)"
+else:
+  static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2."
+
+type
+  IpAddress* = object
+    host*: uint32           # 32-bit IPv4 host address
+    port*: uint16           # 16-bit protocol port
+
+  TcpSocket* = pointer
+
+const
+  INADDR_ANY* = 0x00000000
+  INADDR_NONE* = 0xFFFFFFFF
+  INADDR_LOOPBACK* = 0x7F000001
+  INADDR_BROADCAST* = 0xFFFFFFFF
+# The maximum channels on a a UDP socket
+const
+  SDLNET_MAX_UDPCHANNELS* = 32
+# The maximum addresses bound to a single UDP socket channel
+const
+  SDLNET_MAX_UDPADDRESSES* = 4
+type
+  UDPsocket* = ptr object
+  UDPpacket* = object
+    channel*: cint          # The src/dst channel of the packet
+    data*: ptr uint8        # The packet data
+    len*: cint              # The length of the packet data
+    maxlen*: cint           # The size of the data buffer
+    status*: cint           # packet status after sending
+    address*: IpAddress     # The source/dest address of an incoming/outgoing packet
+
+#*********************************************************************
+# Hooks for checking sockets for available data
+#*********************************************************************
+type
+  SocketSet* = pointer
+# Any network socket can be safely cast to this socket type
+type
+  GenericSocketObj* = object
+    ready*: cint
+  GenericSocket* = ptr GenericSocketObj
+
+when not defined(SDL_Static):
+  {.push dynlib: LibName, callconv: cdecl.}
+# This function gets the version of the dynamically linked SDL_net library.
+#   it should NOT be used to fill a version structure, instead you should
+#   use the SDL_NET_VERSION() macro.
+#
+
+proc linkedVersion*(): ptr SDL_Version {.importc: "SDLNet_Linked_Version".}
+# Initialize/Cleanup the network API
+#   SDL must be initialized before calls to functions in this library,
+#   because this library uses utility functions from the SDL library.
+#
+proc init*(): cint {.importc: "SDLNet_Init".}
+proc quit*() {.importc: "SDLNet_Quit".}
+#*********************************************************************
+# IPv4 hostname resolution API
+#*********************************************************************
+
+# Resolve a host name and port to an IP address in network form.
+#   If the function succeeds, it will return 0.
+#   If the host couldn't be resolved, the host portion of the returned
+#   address will be INADDR_NONE, and the function will return -1.
+#   If 'host' is NULL, the resolved host will be set to INADDR_ANY.
+#
+proc resolveHost*(address: ptr IpAddress; host: cstring; port: uint16): cint {.importc: "SDLNet_ResolveHost".}
+# Resolve an ip address to a host name in canonical form.
+#   If the ip couldn't be resolved, this function returns NULL,
+#   otherwise a pointer to a static buffer containing the hostname
+#   is returned.  Note that this function is not thread-safe.
+#
+proc resolveIP*(ip: ptr IpAddress): cstring {.importc: "SDLNet_ResolveIP".}
+# Get the addresses of network interfaces on this system.
+#   This returns the number of addresses saved in 'addresses'
+#
+proc getLocalAddresses*(addresses: ptr IpAddress; maxcount: cint): cint {.importc: "SDLNet_GetLocalAddresses".}
+#*********************************************************************
+# TCP network API
+#*********************************************************************
+
+# Open a TCP network socket
+#   If ip.host is INADDR_NONE or INADDR_ANY, this creates a local server
+#   socket on the given port, otherwise a TCP connection to the remote
+#   host and port is attempted. The address passed in should already be
+#   swapped to network byte order (addresses returned from
+#   SDLNet_ResolveHost() are already in the correct form).
+#   The newly created socket is returned, or NULL if there was an error.
+#
+proc tcpOpen*(ip: ptr IpAddress): TcpSocket {.importc: "SDLNet_TCP_Open".}
+# Accept an incoming connection on the given server socket.
+#   The newly created socket is returned, or NULL if there was an error.
+#
+proc tcpAccept*(server: TcpSocket): TcpSocket {.importc: "SDLNet_TCP_Accept".}
+# Get the IP address of the remote system associated with the socket.
+#   If the socket is a server socket, this function returns NULL.
+#
+proc tcpGetPeerAddress*(sock: TcpSocket): ptr IpAddress {.importc: "SDLNet_TCP_GetPeerAddress".}
+# Send 'len' bytes of 'data' over the non-server socket 'sock'
+#   This function returns the actual amount of data sent.  If the return value
+#   is less than the amount of data sent, then either the remote connection was
+#   closed, or an unknown socket error occurred.
+#
+proc tcpSend*(sock: TcpSocket; data: pointer; len: cint): cint {.importc: "SDLNet_TCP_Send".}
+# Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
+#   and store them in the buffer pointed to by 'data'.
+#   This function returns the actual amount of data received.  If the return
+#   value is less than or equal to zero, then either the remote connection was
+#   closed, or an unknown socket error occurred.
+#
+proc tcpRecv*(sock: TcpSocket; data: pointer; maxlen: cint): cint {.importc: "SDLNet_TCP_Recv".}
+# Close a TCP network socket
+proc tcpClose*(sock: TcpSocket) {.importc: "SDLNet_TCP_Close".}
+#*********************************************************************
+# UDP network API
+#*********************************************************************
+
+# Allocate/resize/free a single UDP packet 'size' bytes long.
+#   The new packet is returned, or NULL if the function ran out of memory.
+#
+proc allocPacket*(size: cint): ptr UDPpacket {.importc: "SDLNet_AllocPacket".}
+proc resizePacket*(packet: ptr UDPpacket; newsize: cint): cint {.importc: "SDLNet_ResizePacket".}
+proc freePacket*(packet: ptr UDPpacket) {.importc: "SDLNet_FreePacket".}
+# Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets,
+#   each 'size' bytes long.
+#   A pointer to the first packet in the array is returned, or NULL if the
+#   function ran out of memory.
+#
+proc allocPacketV*(howmany: cint; size: cint): ptr ptr UDPpacket {.importc: "SDLNet_AllocPacketV".}
+proc freePacketV*(packetV: ptr ptr UDPpacket) {.importc: "SDLNet_FreePacketV".}
+# Open a UDP network socket
+#   If 'port' is non-zero, the UDP socket is bound to a local port.
+#   The 'port' should be given in native byte order, but is used
+#   internally in network (big endian) byte order, in addresses, etc.
+#   This allows other systems to send to this socket via a known port.
+#
+proc udpOpen*(port: uint16): UDPsocket {.importc: "SDLNet_UDP_Open".}
+# Set the percentage of simulated packet loss for packets sent on the socket.
+#
+proc udpSetPacketLoss*(sock: UDPsocket; percent: cint) {.importc: "SDLNet_UDP_SetPacketLoss".}
+# Bind the address 'address' to the requested channel on the UDP socket.
+#   If the channel is -1, then the first unbound channel that has not yet
+#   been bound to the maximum number of addresses will be bound with
+#   the given address as it's primary address.
+#   If the channel is already bound, this new address will be added to the
+#   list of valid source addresses for packets arriving on the channel.
+#   If the channel is not already bound, then the address becomes the primary
+#   address, to which all outbound packets on the channel are sent.
+#   This function returns the channel which was bound, or -1 on error.
+#
+proc udpBind*(sock: UDPsocket; channel: cint; address: ptr IpAddress): cint {.importc: "SDLNet_UDP_Bind".}
+# Unbind all addresses from the given channel
+proc udpUnbind*(sock: UDPsocket; channel: cint) {.importc: "SDLNet_UDP_Unbind".}
+# Get the primary IP address of the remote system associated with the
+#   socket and channel.  If the channel is -1, then the primary IP port
+#   of the UDP socket is returned -- this is only meaningful for sockets
+#   opened with a specific port.
+#   If the channel is not bound and not -1, this function returns NULL.
+#
+proc udpGetPeerAddress*(sock: UDPsocket; channel: cint): ptr IpAddress {.importc: "SDLNet_UDP_GetPeerAddress".}
+# Send a vector of packets to the the channels specified within the packet.
+#   If the channel specified in the packet is -1, the packet will be sent to
+#   the address in the 'src' member of the packet.
+#   Each packet will be updated with the status of the packet after it has
+#   been sent, -1 if the packet send failed.
+#   This function returns the number of packets sent.
+#
+proc udpSendV*(sock: UDPsocket; packets: ptr ptr UDPpacket;
+               npackets: cint): cint {.importc: "SDLNet_UDP_SendV".}
+# Send a single packet to the specified channel.
+#   If the channel specified in the packet is -1, the packet will be sent to
+#   the address in the 'src' member of the packet.
+#   The packet will be updated with the status of the packet after it has
+#   been sent.
+#   This function returns 1 if the packet was sent, or 0 on error.
+#
+#   NOTE:
+#   The maximum size of the packet is limited by the MTU (Maximum Transfer Unit)
+#   of the transport medium.  It can be as low as 250 bytes for some PPP links,
+#   and as high as 1500 bytes for ethernet.
+#
+proc udpSend*(sock: UDPsocket; channel: cint; packet: ptr UDPpacket): cint {.importc: "SDLNet_UDP_Send".}
+# Receive a vector of pending packets from the UDP socket.
+#   The returned packets contain the source address and the channel they arrived
+#   on.  If they did not arrive on a bound channel, the the channel will be set
+#   to -1.
+#   The channels are checked in highest to lowest order, so if an address is
+#   bound to multiple channels, the highest channel with the source address
+#   bound will be returned.
+#   This function returns the number of packets read from the network, or -1
+#   on error.  This function does not block, so can return 0 packets pending.
+#
+proc udpRecvV*(sock: UDPsocket; packets: ptr ptr UDPpacket): cint {.importc: "SDLNet_UDP_RecvV".}
+# Receive a single packet from the UDP socket.
+#   The returned packet contains the source address and the channel it arrived
+#   on.  If it did not arrive on a bound channel, the the channel will be set
+#   to -1.
+#   The channels are checked in highest to lowest order, so if an address is
+#   bound to multiple channels, the highest channel with the source address
+#   bound will be returned.
+#   This function returns the number of packets read from the network, or -1
+#   on error.  This function does not block, so can return 0 packets pending.
+#
+proc udpRecv*(sock: UDPsocket; packet: ptr UDPpacket): cint {.importc: "SDLNet_UDP_Recv".}
+# Close a UDP network socket
+proc udpClose*(sock: UDPsocket) {.importc: "SDLNet_UDP_Close".}
+
+# Allocate a socket set for use with SDLNet_CheckSockets()
+#   This returns a socket set for up to 'maxsockets' sockets, or NULL if
+#   the function ran out of memory.
+#
+proc allocSocketSet*(maxsockets: cint): SocketSet {.importc: "SDLNet_AllocSocketSet".}
+# Add a socket to a set of sockets to be checked for available data
+proc addSocket*(set: SocketSet; sock: GenericSocket): cint {.importc: "SDLNet_AddSocket".}
+
+# Remove a socket from a set of sockets to be checked for available data
+proc delSocket*(set: SocketSet; sock: GenericSocket): cint {.importc: "SDLNet_DelSocket".}
+
+# This function checks to see if data is available for reading on the
+#   given set of sockets.  If 'timeout' is 0, it performs a quick poll,
+#   otherwise the function returns when either data is available for
+#   reading, or the timeout in milliseconds has elapsed, which ever occurs
+#   first.  This function returns the number of sockets ready for reading,
+#   or -1 if there was an error with the select() system call.
+#
+proc checkSockets*(set: SocketSet; timeout: uint32): cint {.importc: "SDLNet_CheckSockets".}
+# After calling CheckSockets(), you can use this function on a
+#   socket that was in the socket set, to find out if data is available
+#   for reading.
+#
+
+# Free a set of sockets allocated by SDL_NetAllocSocketSet()
+proc freeSocketSet*(set: SocketSet) {.importc: "SDLNet_FreeSocketSet".}
+#*********************************************************************
+# Error reporting functions
+#*********************************************************************
+proc setError*(fmt: cstring) {.varargs, importc: "SDLNet_SetError".}
+proc getError*(): cstring {.importc: "SDLNet_GetError".}
+#*********************************************************************
+# Inline functions to read/write network data
+#*********************************************************************
+# Warning, some systems have data access alignment restrictions
+
+proc write16* (value: uint16, dest: pointer) {.importc: "SDLNet_Write16".}
+proc write32* (value: uint32, dest: pointer) {.importc: "SDLNet_Write32".}
+proc read16* (src: pointer): uint16 {.importc: "SDLNet_Read16".}
+proc read32* (src: pointer): uint32 {.importc: "SDLNet_Read32".}
+
+when not defined(SDL_Static):
+  {.pop.}
+
+proc tcpAddSocket*(set: SocketSet; sock: TcpSocket): cint =
+  addSocket(set, cast[GenericSocket](sock))
+
+proc udpAddSocket*(set: SocketSet; sock: UDPsocket): cint =
+  addSocket(set, cast[GenericSocket](sock))
+
+
+proc tcpDelSocket*(set: SocketSet; sock: TcpSocket): cint {.inline.} =
+  delSocket(set, cast[GenericSocket](sock))
+
+proc udpDelSocket*(set: SocketSet; sock: UDPsocket): cint {.inline.} =
+  delSocket(set, cast[GenericSocket](sock))
+
+
+##define SDLNet_SocketReady(sock) _SDLNet_SocketReady((SDLNet_GenericSocket)(sock))
+#proc _SDLNet_SocketReady*(sock: SDLNet_GenericSocket): cint =
+#  #return (sock != NULL) && (sock->ready);
+proc socketReady* (sock: GenericSocket): bool =
+  not(sock.isNil) and sock.ready > 0

+ 401 - 0
src/nodesnim/thirdparty/sdl2/private/keycodes.nim

@@ -0,0 +1,401 @@
+## do not import this, it is included in sdl2.nim
+
+type
+  Scancode* {.size: sizeof(cint).} = enum
+    SDL_SCANCODE_UNKNOWN = 0,
+    SDL_SCANCODE_A = 4, SDL_SCANCODE_B = 5, SDL_SCANCODE_C = 6,
+    SDL_SCANCODE_D = 7, SDL_SCANCODE_E = 8, SDL_SCANCODE_F = 9,
+    SDL_SCANCODE_G = 10, SDL_SCANCODE_H = 11, SDL_SCANCODE_I = 12,
+    SDL_SCANCODE_J = 13, SDL_SCANCODE_K = 14, SDL_SCANCODE_L = 15,
+    SDL_SCANCODE_M = 16, SDL_SCANCODE_N = 17, SDL_SCANCODE_O = 18,
+    SDL_SCANCODE_P = 19, SDL_SCANCODE_Q = 20, SDL_SCANCODE_R = 21,
+    SDL_SCANCODE_S = 22, SDL_SCANCODE_T = 23, SDL_SCANCODE_U = 24,
+    SDL_SCANCODE_V = 25, SDL_SCANCODE_W = 26, SDL_SCANCODE_X = 27,
+    SDL_SCANCODE_Y = 28, SDL_SCANCODE_Z = 29, SDL_SCANCODE_1 = 30,
+    SDL_SCANCODE_2 = 31, SDL_SCANCODE_3 = 32, SDL_SCANCODE_4 = 33,
+    SDL_SCANCODE_5 = 34, SDL_SCANCODE_6 = 35, SDL_SCANCODE_7 = 36,
+    SDL_SCANCODE_8 = 37, SDL_SCANCODE_9 = 38, SDL_SCANCODE_0 = 39,
+    SDL_SCANCODE_RETURN = 40, SDL_SCANCODE_ESCAPE = 41,
+    SDL_SCANCODE_BACKSPACE = 42, SDL_SCANCODE_TAB = 43,
+    SDL_SCANCODE_SPACE = 44, SDL_SCANCODE_MINUS = 45,
+    SDL_SCANCODE_EQUALS = 46, SDL_SCANCODE_LEFTBRACKET = 47,
+    SDL_SCANCODE_RIGHTBRACKET = 48, SDL_SCANCODE_BACKSLASH = 49,
+    SDL_SCANCODE_NONUSHASH = 50, #
+    SDL_SCANCODE_SEMICOLON = 51, SDL_SCANCODE_APOSTROPHE = 52, SDL_SCANCODE_GRAVE = 53,
+    SDL_SCANCODE_COMMA = 54, SDL_SCANCODE_PERIOD = 55,
+    SDL_SCANCODE_SLASH = 56, SDL_SCANCODE_CAPSLOCK = 57, SDL_SCANCODE_F1 = 58,
+    SDL_SCANCODE_F2 = 59, SDL_SCANCODE_F3 = 60, SDL_SCANCODE_F4 = 61,
+    SDL_SCANCODE_F5 = 62, SDL_SCANCODE_F6 = 63, SDL_SCANCODE_F7 = 64,
+    SDL_SCANCODE_F8 = 65, SDL_SCANCODE_F9 = 66, SDL_SCANCODE_F10 = 67,
+    SDL_SCANCODE_F11 = 68, SDL_SCANCODE_F12 = 69,
+    SDL_SCANCODE_PRINTSCREEN = 70, SDL_SCANCODE_SCROLLLOCK = 71,
+    SDL_SCANCODE_PAUSE = 72, SDL_SCANCODE_INSERT = 73,
+    SDL_SCANCODE_HOME = 74, SDL_SCANCODE_PAGEUP = 75,
+    SDL_SCANCODE_DELETE = 76, SDL_SCANCODE_END = 77,
+    SDL_SCANCODE_PAGEDOWN = 78, SDL_SCANCODE_RIGHT = 79,
+    SDL_SCANCODE_LEFT = 80, SDL_SCANCODE_DOWN = 81, SDL_SCANCODE_UP = 82, SDL_SCANCODE_NUMLOCKCLEAR = 83,
+    SDL_SCANCODE_KP_DIVIDE = 84, SDL_SCANCODE_KP_MULTIPLY = 85,
+    SDL_SCANCODE_KP_MINUS = 86, SDL_SCANCODE_KP_PLUS = 87,
+    SDL_SCANCODE_KP_ENTER = 88, SDL_SCANCODE_KP_1 = 89,
+    SDL_SCANCODE_KP_2 = 90, SDL_SCANCODE_KP_3 = 91, SDL_SCANCODE_KP_4 = 92,
+    SDL_SCANCODE_KP_5 = 93, SDL_SCANCODE_KP_6 = 94, SDL_SCANCODE_KP_7 = 95,
+    SDL_SCANCODE_KP_8 = 96, SDL_SCANCODE_KP_9 = 97, SDL_SCANCODE_KP_0 = 98,
+    SDL_SCANCODE_KP_PERIOD = 99, SDL_SCANCODE_NONUSBACKSLASH = 100,
+    SDL_SCANCODE_APPLICATION = 101, #*< windows contextual menu, compose
+    SDL_SCANCODE_POWER = 102,
+    SDL_SCANCODE_KP_EQUALS = 103, SDL_SCANCODE_F13 = 104,
+    SDL_SCANCODE_F14 = 105, SDL_SCANCODE_F15 = 106, SDL_SCANCODE_F16 = 107,
+    SDL_SCANCODE_F17 = 108, SDL_SCANCODE_F18 = 109, SDL_SCANCODE_F19 = 110,
+    SDL_SCANCODE_F20 = 111, SDL_SCANCODE_F21 = 112, SDL_SCANCODE_F22 = 113,
+    SDL_SCANCODE_F23 = 114, SDL_SCANCODE_F24 = 115,
+    SDL_SCANCODE_EXECUTE = 116, SDL_SCANCODE_HELP = 117,
+    SDL_SCANCODE_MENU = 118, SDL_SCANCODE_SELECT = 119,
+    SDL_SCANCODE_STOP = 120, SDL_SCANCODE_AGAIN = 121, #*< redo
+    SDL_SCANCODE_UNDO = 122, SDL_SCANCODE_CUT = 123, SDL_SCANCODE_COPY = 124,
+    SDL_SCANCODE_PASTE = 125, SDL_SCANCODE_FIND = 126,
+    SDL_SCANCODE_MUTE = 127, SDL_SCANCODE_VOLUMEUP = 128, SDL_SCANCODE_VOLUMEDOWN = 129,
+    SDL_SCANCODE_KP_COMMA = 133, SDL_SCANCODE_KP_EQUALSAS400 = 134, SDL_SCANCODE_INTERNATIONAL1 = 135,
+    SDL_SCANCODE_INTERNATIONAL2 = 136, SDL_SCANCODE_INTERNATIONAL3 = 137, #*< Yen
+    SDL_SCANCODE_INTERNATIONAL4 = 138, SDL_SCANCODE_INTERNATIONAL5 = 139,
+    SDL_SCANCODE_INTERNATIONAL6 = 140, SDL_SCANCODE_INTERNATIONAL7 = 141,
+    SDL_SCANCODE_INTERNATIONAL8 = 142, SDL_SCANCODE_INTERNATIONAL9 = 143, SDL_SCANCODE_LANG1 = 144, #*< Hangul/English toggle
+    SDL_SCANCODE_LANG2 = 145, #*< Hanja conversion
+    SDL_SCANCODE_LANG3 = 146, #*< Katakana
+    SDL_SCANCODE_LANG4 = 147, #*< Hiragana
+    SDL_SCANCODE_LANG5 = 148, #*< Zenkaku/Hankaku
+    SDL_SCANCODE_LANG6 = 149, #*< reserved
+    SDL_SCANCODE_LANG7 = 150, #*< reserved
+    SDL_SCANCODE_LANG8 = 151, #*< reserved
+    SDL_SCANCODE_LANG9 = 152, #*< reserved
+    SDL_SCANCODE_ALTERASE = 153, #*< Erase-Eaze
+    SDL_SCANCODE_SYSREQ = 154, SDL_SCANCODE_CANCEL = 155,
+    SDL_SCANCODE_CLEAR = 156, SDL_SCANCODE_PRIOR = 157,
+    SDL_SCANCODE_RETURN2 = 158, SDL_SCANCODE_SEPARATOR = 159,
+    SDL_SCANCODE_OUT = 160, SDL_SCANCODE_OPER = 161,
+    SDL_SCANCODE_CLEARAGAIN = 162, SDL_SCANCODE_CRSEL = 163,
+    SDL_SCANCODE_EXSEL = 164, SDL_SCANCODE_KP_00 = 176,
+    SDL_SCANCODE_KP_000 = 177, SDL_SCANCODE_THOUSANDSSEPARATOR = 178,
+    SDL_SCANCODE_DECIMALSEPARATOR = 179, SDL_SCANCODE_CURRENCYUNIT = 180,
+    SDL_SCANCODE_CURRENCYSUBUNIT = 181, SDL_SCANCODE_KP_LEFTPAREN = 182,
+    SDL_SCANCODE_KP_RIGHTPAREN = 183, SDL_SCANCODE_KP_LEFTBRACE = 184,
+    SDL_SCANCODE_KP_RIGHTBRACE = 185, SDL_SCANCODE_KP_TAB = 186,
+    SDL_SCANCODE_KP_BACKSPACE = 187, SDL_SCANCODE_KP_A = 188,
+    SDL_SCANCODE_KP_B = 189, SDL_SCANCODE_KP_C = 190, SDL_SCANCODE_KP_D = 191,
+    SDL_SCANCODE_KP_E = 192, SDL_SCANCODE_KP_F = 193,
+    SDL_SCANCODE_KP_XOR = 194, SDL_SCANCODE_KP_POWER = 195,
+    SDL_SCANCODE_KP_PERCENT = 196, SDL_SCANCODE_KP_LESS = 197,
+    SDL_SCANCODE_KP_GREATER = 198, SDL_SCANCODE_KP_AMPERSAND = 199,
+    SDL_SCANCODE_KP_DBLAMPERSAND = 200, SDL_SCANCODE_KP_VERTICALBAR = 201,
+    SDL_SCANCODE_KP_DBLVERTICALBAR = 202, SDL_SCANCODE_KP_COLON = 203,
+    SDL_SCANCODE_KP_HASH = 204, SDL_SCANCODE_KP_SPACE = 205,
+    SDL_SCANCODE_KP_AT = 206, SDL_SCANCODE_KP_EXCLAM = 207,
+    SDL_SCANCODE_KP_MEMSTORE = 208, SDL_SCANCODE_KP_MEMRECALL = 209,
+    SDL_SCANCODE_KP_MEMCLEAR = 210, SDL_SCANCODE_KP_MEMADD = 211,
+    SDL_SCANCODE_KP_MEMSUBTRACT = 212, SDL_SCANCODE_KP_MEMMULTIPLY = 213,
+    SDL_SCANCODE_KP_MEMDIVIDE = 214, SDL_SCANCODE_KP_PLUSMINUS = 215,
+    SDL_SCANCODE_KP_CLEAR = 216, SDL_SCANCODE_KP_CLEARENTRY = 217,
+    SDL_SCANCODE_KP_BINARY = 218, SDL_SCANCODE_KP_OCTAL = 219,
+    SDL_SCANCODE_KP_DECIMAL = 220, SDL_SCANCODE_KP_HEXADECIMAL = 221,
+    SDL_SCANCODE_LCTRL = 224, SDL_SCANCODE_LSHIFT = 225, SDL_SCANCODE_LALT = 226, #*< alt, option
+    SDL_SCANCODE_LGUI = 227, #*< windows, command (apple), meta
+    SDL_SCANCODE_RCTRL = 228, SDL_SCANCODE_RSHIFT = 229, SDL_SCANCODE_RALT = 230, #*< alt gr, option
+    SDL_SCANCODE_RGUI = 231, #*< windows, command (apple), meta
+    SDL_SCANCODE_MODE = 257,
+    SDL_SCANCODE_AUDIONEXT = 258, SDL_SCANCODE_AUDIOPREV = 259,
+    SDL_SCANCODE_AUDIOSTOP = 260, SDL_SCANCODE_AUDIOPLAY = 261,
+    SDL_SCANCODE_AUDIOMUTE = 262, SDL_SCANCODE_MEDIASELECT = 263,
+    SDL_SCANCODE_WWW = 264, SDL_SCANCODE_MAIL = 265,
+    SDL_SCANCODE_CALCULATOR = 266, SDL_SCANCODE_COMPUTER = 267,
+    SDL_SCANCODE_AC_SEARCH = 268, SDL_SCANCODE_AC_HOME = 269,
+    SDL_SCANCODE_AC_BACK = 270, SDL_SCANCODE_AC_FORWARD = 271,
+    SDL_SCANCODE_AC_STOP = 272, SDL_SCANCODE_AC_REFRESH = 273, SDL_SCANCODE_AC_BOOKMARKS = 274,
+    SDL_SCANCODE_BRIGHTNESSDOWN = 275, SDL_SCANCODE_BRIGHTNESSUP = 276, SDL_SCANCODE_DISPLAYSWITCH = 277,
+    SDL_SCANCODE_KBDILLUMTOGGLE = 278, SDL_SCANCODE_KBDILLUMDOWN = 279,
+    SDL_SCANCODE_KBDILLUMUP = 280, SDL_SCANCODE_EJECT = 281, SDL_SCANCODE_SLEEP = 282,
+    SDL_NUM_SCANCODES = 512 #*< not a key, just marks the number of scancodes
+                            #                                 for array bounds
+
+const SDLK_SCANCODE_MASK = 1 shl 30
+template SDL_SCANCODE_TO_KEYCODE(some: ScanCode): untyped = (some.cint or SDLK_SCANCODE_MASK)
+
+const
+  K_UNKNOWN*: cint = 0
+
+  K_BACKSPACE*: cint = '\b'.cint
+  K_TAB*: cint = '\t'.cint
+  K_RETURN*: cint = '\r'.cint
+  K_ESCAPE*: cint = '\27'.cint
+  K_SPACE*: cint = ' '.cint
+  K_EXCLAIM*: cint = '!'.cint
+  K_QUOTEDBL*: cint = '"'.cint
+  K_HASH*: cint = '#'.cint
+  K_DOLLAR*: cint = '$'.cint
+  K_PERCENT*: cint = '%'.cint
+  K_AMPERSAND*: cint = '&'.cint
+  K_QUOTE*: cint = '\''.cint
+  K_LEFTPAREN*: cint = '('.cint
+  K_RIGHTPAREN*: cint = ')'.cint
+  K_ASTERISK*: cint = '*'.cint
+  K_PLUS*: cint = '+'.cint
+  K_COMMA*: cint = ','.cint
+  K_MINUS*: cint = '-'.cint
+  K_PERIOD*: cint = '.'.cint
+  K_SLASH*: cint = '/'.cint
+  K_0*: cint = '0'.cint
+  K_1*: cint = '1'.cint
+  K_2*: cint = '2'.cint
+  K_3*: cint = '3'.cint
+  K_4*: cint = '4'.cint
+  K_5*: cint = '5'.cint
+  K_6*: cint = '6'.cint
+  K_7*: cint = '7'.cint
+  K_8*: cint = '8'.cint
+  K_9*: cint = '9'.cint
+  K_COLON*: cint = ':'.cint
+  K_SEMICOLON*: cint = ';'.cint
+  K_LESS*: cint = '<'.cint
+  K_EQUALS*: cint = '='.cint
+  K_GREATER*: cint = '>'.cint
+  K_QUESTION*: cint = '?'.cint
+  K_AT*: cint = '@'.cint # Skip uppercase letters
+  K_LEFTBRACKET*: cint = '['.cint
+  K_BACKSLASH*: cint = '\\'.cint
+  K_RIGHTBRACKET*: cint = ']'.cint
+  K_CARET*: cint = '^'.cint
+  K_UNDERSCORE*: cint = '_'.cint
+  K_BACKQUOTE*: cint = '`'.cint
+  K_a*: cint = 'a'.cint
+  K_b*: cint = 'b'.cint
+  K_c*: cint = 'c'.cint
+  K_d*: cint = 'd'.cint
+  K_e*: cint = 'e'.cint
+  K_f*: cint = 'f'.cint
+  K_g*: cint = 'g'.cint
+  K_h*: cint = 'h'.cint
+  K_i*: cint = 'i'.cint
+  K_j*: cint = 'j'.cint
+  K_k*: cint = 'k'.cint
+  K_l*: cint = 'l'.cint
+  K_m*: cint = 'm'.cint
+  K_n*: cint = 'n'.cint
+  K_o*: cint = 'o'.cint
+  K_p*: cint = 'p'.cint
+  K_q*: cint = 'q'.cint
+  K_r*: cint =  'r'.cint
+  K_s*: cint =  's'.cint
+  K_t*: cint =  't'.cint
+  K_u*: cint =  'u'.cint
+  K_v*: cint =  'v'.cint
+  K_w*: cint =  'w'.cint
+  K_x*: cint =  'x'.cint
+  K_y*: cint =  'y'.cint
+  K_z*: cint =  'z'.cint
+
+  K_DELETE*: cint =  '\127'.cint
+  K_CAPSLOCK*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK)
+
+  K_F1*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F1)
+  K_F2*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F2)
+  K_F3*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F3)
+  K_F4*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F4)
+  K_F5*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F5)
+  K_F6*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F6)
+  K_F7*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F7)
+  K_F8*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F8)
+  K_F9*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F9)
+  K_F10*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F10)
+  K_F11*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F11)
+  K_F12*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F12)
+
+  K_PRINTSCREEN*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRINTSCREEN)
+  K_SCROLLLOCK*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SCROLLLOCK)
+  K_PAUSE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAUSE)
+  K_INSERT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_INSERT)
+  K_HOME*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HOME)
+  K_PAGEUP*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEUP)
+  K_END*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_END)
+  K_PAGEDOWN*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEDOWN)
+  K_RIGHT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RIGHT)
+  K_LEFT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LEFT)
+  K_DOWN*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DOWN)
+  K_UP*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UP)
+
+  K_NUMLOCKCLEAR*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_NUMLOCKCLEAR)
+  K_KP_DIVIDE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DIVIDE)
+  K_KP_MULTIPLY*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MULTIPLY)
+  K_KP_MINUS*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MINUS)
+  K_KP_PLUS*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUS)
+  K_KP_ENTER*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_ENTER)
+  K_KP_1*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_1)
+  K_KP_2*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_2)
+  K_KP_3*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_3)
+  K_KP_4*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_4)
+  K_KP_5*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_5)
+  K_KP_6*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_6)
+  K_KP_7*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_7)
+  K_KP_8*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_8)
+  K_KP_9*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_9)
+  K_KP_0*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_0)
+  K_KP_PERIOD*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERIOD)
+
+  K_APPLICATION*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APPLICATION)
+  K_POWER*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_POWER)
+  K_KP_EQUALS*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALS)
+  K_F13*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F13)
+  K_F14*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F14)
+  K_F15*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F15)
+  K_F16*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F16)
+  K_F17*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F17)
+  K_F18*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F18)
+  K_F19*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F19)
+  K_F20*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F20)
+  K_F21*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F21)
+  K_F22*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F22)
+  K_F23*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F23)
+  K_F24*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F24)
+  K_EXECUTE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXECUTE)
+  K_HELP*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HELP)
+  K_MENU*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MENU)
+  K_SELECT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SELECT)
+  K_STOP*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_STOP)
+  K_AGAIN*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AGAIN)
+  K_UNDO*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UNDO)
+  K_CUT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CUT)
+  K_COPY*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COPY)
+  K_PASTE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PASTE)
+  K_FIND*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_FIND)
+  K_MUTE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MUTE)
+  K_VOLUMEUP*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEUP)
+  K_VOLUMEDOWN*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEDOWN)
+  K_KP_COMMA*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COMMA)
+  K_KP_EQUALSAS400*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALSAS400)
+
+  K_ALTERASE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ALTERASE)
+  K_SYSREQ*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SYSREQ)
+  K_CANCEL*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CANCEL)
+  K_CLEAR*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEAR)
+  K_PRIOR*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRIOR)
+  K_RETURN2*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RETURN2)
+  K_SEPARATOR*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SEPARATOR)
+  K_OUT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OUT)
+  K_OPER*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OPER)
+  K_CLEARAGAIN*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEARAGAIN)
+  K_CRSEL*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CRSEL)
+  K_EXSEL*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXSEL)
+
+  K_KP_00*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_00)
+  K_KP_000*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_000)
+  K_THOUSANDSSEPARATOR*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_THOUSANDSSEPARATOR)
+  K_DECIMALSEPARATOR*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DECIMALSEPARATOR)
+  K_CURRENCYUNIT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYUNIT)
+  K_CURRENCYSUBUNIT*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYSUBUNIT)
+  K_KP_LEFTPAREN*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTPAREN)
+  K_KP_RIGHTPAREN*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTPAREN)
+  K_KP_LEFTBRACE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTBRACE)
+  K_KP_RIGHTBRACE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTBRACE)
+  K_KP_TAB*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_TAB)
+  K_KP_BACKSPACE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BACKSPACE)
+  K_KP_A*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_A)
+  K_KP_B*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_B)
+  K_KP_C*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_C)
+  K_KP_D*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_D)
+  K_KP_E*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_E)
+  K_KP_F*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_F)
+  K_KP_XOR*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_XOR)
+  K_KP_POWER*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_POWER)
+  K_KP_PERCENT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERCENT)
+  K_KP_LESS*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LESS)
+  K_KP_GREATER*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_GREATER)
+  K_KP_AMPERSAND*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AMPERSAND)
+  K_KP_DBLAMPERSAND*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLAMPERSAND)
+  K_KP_VERTICALBAR*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_VERTICALBAR)
+  K_KP_DBLVERTICALBAR*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLVERTICALBAR)
+  K_KP_COLON*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COLON)
+  K_KP_HASH*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HASH)
+  K_KP_SPACE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_SPACE)
+  K_KP_AT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AT)
+  K_KP_EXCLAM*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EXCLAM)
+  K_KP_MEMSTORE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSTORE)
+  K_KP_MEMRECALL*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMRECALL)
+  K_KP_MEMCLEAR*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMCLEAR)
+  K_KP_MEMADD*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMADD)
+  K_KP_MEMSUBTRACT*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSUBTRACT)
+  K_KP_MEMMULTIPLY*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMMULTIPLY)
+  K_KP_MEMDIVIDE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMDIVIDE)
+  K_KP_PLUSMINUS*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUSMINUS)
+  K_KP_CLEAR*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEAR)
+  K_KP_CLEARENTRY*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEARENTRY)
+  K_KP_BINARY*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BINARY)
+  K_KP_OCTAL*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_OCTAL)
+  K_KP_DECIMAL*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DECIMAL)
+  K_KP_HEXADECIMAL*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HEXADECIMAL)
+
+  K_LCTRL*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LCTRL)
+  K_LSHIFT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LSHIFT)
+  K_LALT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LALT)
+  K_LGUI*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LGUI)
+  K_RCTRL*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RCTRL)
+  K_RSHIFT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RSHIFT)
+  K_RALT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RALT)
+  K_RGUI*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RGUI)
+
+  K_MODE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MODE)
+
+  K_AUDIONEXT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIONEXT)
+  K_AUDIOPREV*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPREV)
+  K_AUDIOSTOP*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOSTOP)
+  K_AUDIOPLAY*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPLAY)
+  K_AUDIOMUTE*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOMUTE)
+  K_MEDIASELECT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIASELECT)
+  K_WWW*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_WWW)
+  K_MAIL*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MAIL)
+  K_CALCULATOR*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALCULATOR)
+  K_COMPUTER*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COMPUTER)
+  K_AC_SEARCH*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_SEARCH)
+  K_AC_HOME*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_HOME)
+  K_AC_BACK*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BACK)
+  K_AC_FORWARD*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_FORWARD)
+  K_AC_STOP*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_STOP)
+  K_AC_REFRESH*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_REFRESH)
+  K_AC_BOOKMARKS*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BOOKMARKS)
+
+  K_BRIGHTNESSDOWN*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSDOWN)
+  K_BRIGHTNESSUP*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSUP)
+  K_DISPLAYSWITCH*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DISPLAYSWITCH)
+  K_KBDILLUMTOGGLE*: cint =
+    SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMTOGGLE)
+  K_KBDILLUMDOWN*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN)
+  K_KBDILLUMUP*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP)
+  K_EJECT*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT)
+  K_SLEEP*: cint =  SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP)
+
+type
+  Keymod* {.size: sizeof(cint).} = enum
+    KMOD_NONE = 0x0000, KMOD_LSHIFT = 0x0001, KMOD_RSHIFT = 0x0002,
+    KMOD_LCTRL= 0x0040, KMOD_RCTRL  = 0x0080, KMOD_LALT   = 0x0100,
+    KMOD_RALT = 0x0200, KMOD_LGUI   = 0x0400, KMOD_RGUI   = 0x0800,
+    KMOD_NUM  = 0x1000, KMOD_CAPS   = 0x2000, KMOD_MODE   = 0x4000,
+    KMOD_RESERVED=0x8000
+
+converter toInt*(some: Keymod): cint = cint(some)
+
+template KMOD_CTRL*: untyped = (KMOD_LCTRL or KMOD_RCTRL)
+template KMOD_SHIFT*:untyped = (KMOD_LSHIFT or KMOD_RSHIFT)
+template KMOD_ALT*: untyped = (KMOD_LALT or KMOD_RALT)
+template KMOD_GUI*: untyped = (KMOD_LGUI or KMOD_RGUI)
+
+{.deprecated: [TScancode: Scancode].}
+{.deprecated: [TKeymod: Keymod].}
+
+

+ 215 - 0
src/nodesnim/thirdparty/sdl2/ttf.nim

@@ -0,0 +1,215 @@
+{.deadCodeElim: on.}
+
+when not defined(SDL_Static):
+  when defined(windows):
+    const LibName* = "SDL2_ttf.dll"
+  elif defined(macosx):
+    const LibName = "libSDL2_ttf.dylib"
+  else:
+    const LibName = "libSDL2_ttf(|-2.0).so(|.0)"
+else:
+  static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2."
+
+import sdl2
+
+type
+  FontPtr* = ptr object{.pure.}
+
+# Set up for C function definitions, even when using C++
+# Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
+#/*
+##define SDL_TTF_MAJOR_VERSION  2
+##define SDL_TTF_MINOR_VERSION  0
+##define SDL_TTF_PATCHLEVEL     12
+#
+# This macro can be used to fill a version structure with the compile-time
+#  version of the SDL_ttf library.
+#
+##define SDL_TTF_VERSION(X)                                             \
+#{                                                                      \
+# (X)->major = SDL_TTF_MAJOR_VERSION;                           \
+# (X)->minor = SDL_TTF_MINOR_VERSION;                           \
+# (X)->patch = SDL_TTF_PATCHLEVEL;                              \
+#}
+# Backwards compatibility
+##define TTF_MAJOR_VERSION      SDL_TTF_MAJOR_VERSION
+##define TTF_MINOR_VERSION      SDL_TTF_MINOR_VERSION
+#//#define TTF_PATCHLEVEL               SDL_TTF_PATCHLEVEL
+##define TTF_VERSION(X)         SDL_TTF_VERSION(X)
+
+when not defined(SDL_Static):
+  {.push callConv:cdecl, dynlib:LibName.}
+
+proc ttfLinkedVersion*(): ptr SDL_version {.importc: "TTF_Linked_Version".}
+# ZERO WIDTH NO-BREAKSPACE (Unicode byte order mark)
+const
+  UNICODE_BOM_NATIVE* = 0x0000FEFF
+  UNICODE_BOM_SWAPPED* = 0x0000FFFE
+# This function tells the library whether UNICODE text is generally
+#   byteswapped.  A UNICODE BOM character in a string will override
+#   this setting for the remainder of that string.
+#
+proc ttfByteSwappedUnicode*(swapped: cint) {.importc: "TTF_ByteSwappedUNICODE".}
+
+# Initialize the TTF engine - returns 0 if successful, -1 on error
+proc ttfInit*(): SDL_Return  {.importc: "TTF_Init", discardable.}
+# Open a font file and create a font of the specified point size.
+#  Some .fon fonts will have several sizes embedded in the file, so the
+#  point size becomes the index of choosing which size.  If the value
+#  is too high, the last indexed size will be the default.
+proc openFont*(file: cstring; ptsize: cint): FontPtr {.importc: "TTF_OpenFont".}
+proc openFontIndex*(file: cstring; ptsize: cint; index: clong): FontPtr {.importc: "TTF_OpenFontIndex".}
+proc openFontRW*(src: ptr RWops; freesrc: cint; ptsize: cint): FontPtr {.importc: "TTF_OpenFontRW".}
+proc openFontIndexRW*(src: ptr RWops; freesrc: cint; ptsize: cint;
+                          index: clong): FontPtr {.importc: "TTF_OpenFontIndexRW".}
+# Set and retrieve the font style
+const
+  TTF_STYLE_NORMAL* = 0x00000000
+  TTF_STYLE_BOLD* = 0x00000001
+  TTF_STYLE_ITALIC* = 0x00000002
+  TTF_STYLE_UNDERLINE* = 0x00000004
+  TTF_STYLE_STRIKETHROUGH* = 0x00000008
+proc getFontStyle*(font: FontPtr): cint  {.importc: "TTF_GetFontStyle".}
+proc setFontStyle*(font: FontPtr; style: cint) {.importc: "TTF_SetFontStyle".}
+proc getFontOutline*(font: FontPtr): cint {.importc: "TTF_GetFontOutline".}
+proc setFontOutline*(font: FontPtr; outline: cint) {.importc: "TTF_SetFontOutline".}
+
+# Set and retrieve FreeType hinter settings
+const
+  TTF_HINTING_NORMAL* = 0
+  TTF_HINTING_LIGHT* = 1
+  TTF_HINTING_MONO* = 2
+  TTF_HINTING_NONE* = 3
+proc getFontHinting*(font: FontPtr): cint {.importc: "TTF_GetFontHinting".}
+proc setFontHinting*(font: FontPtr; hinting: cint) {.importc: "TTF_SetFontHinting".}
+# Get the total height of the font - usually equal to point size
+proc fontHeight*(font: FontPtr): cint {.importc: "TTF_FontHeight".}
+# Get the offset from the baseline to the top of the font
+#   This is a positive value, relative to the baseline.
+#
+proc fontAscent*(font: FontPtr): cint {.importc: "TTF_FontAscent".}
+# Get the offset from the baseline to the bottom of the font
+#   This is a negative value, relative to the baseline.
+#
+proc fontDescent*(font: FontPtr): cint {.importc: "TTF_FontDescent".}
+# Get the recommended spacing between lines of text for this font
+proc fontLineSkip*(font: FontPtr): cint {.importc: "TTF_FontLineSkip".}
+# Get/Set whether or not kerning is allowed for this font
+proc getFontKerning*(font: FontPtr): cint {.importc: "TTF_GetFontKerning".}
+proc setFontKerning*(font: FontPtr; allowed: cint) {.importc: "TTF_SetFontKerning".}
+# Get the number of faces of the font
+proc fontFaces*(font: FontPtr): clong {.importc: "TTF_FontFaces".}
+# Get the font face attributes, if any
+proc fontFaceIsFixedWidth*(font: FontPtr): cint {.importc: "TTF_FontFaceIsFixedWidth".}
+proc fontFaceFamilyName*(font: FontPtr): cstring {.importc: "TTF_FontFaceFamilyName".}
+proc fontFaceStyleName*(font: FontPtr): cstring {.importc: "TTF_FontFaceStyleName".}
+# Check wether a glyph is provided by the font or not
+proc glyphIsProvided*(font: FontPtr; ch: uint16): cint {.importc: "TTF_GlyphIsProvided".}
+# Get the metrics (dimensions) of a glyph
+#   To understand what these metrics mean, here is a useful link:
+#    http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html
+#
+proc glyphMetrics*(font: FontPtr; ch: uint16; minx: ptr cint;
+                       maxx: ptr cint; miny: ptr cint; maxy: ptr cint;
+                       advance: ptr cint): cint {.importc: "TTF_GlyphMetrics".}
+# Get the dimensions of a rendered string of text
+proc sizeText*(font: FontPtr; text: cstring; w: ptr cint; h: ptr cint): cint{.
+  importc: "TTF_SizeText".}
+proc sizeUtf8*(font: FontPtr; text: cstring; w: ptr cint; h: ptr cint): cint{.
+  importc: "TTF_SizeUTF8".}
+proc sizeUnicode*(font: FontPtr; text: ptr uint16; w, h: ptr cint): cint{.
+  importc: "TTF_SizeUNICODE".}
+# Create an 8-bit palettized surface and render the given text at
+#   fast quality with the given font and color.  The 0 pixel is the
+#   colorkey, giving a transparent background, and the 1 pixel is set
+#   to the text color.
+#   This function returns the new surface, or NULL if there was an error.
+#
+proc renderTextSolid*(font: FontPtr; text: cstring; fg: Color): SurfacePtr{.
+  importc: "TTF_RenderText_Solid".}
+proc renderUtf8Solid*(font: FontPtr; text: cstring; fg: Color): SurfacePtr{.
+  importc: "TTF_RenderUTF8_Solid".}
+proc renderUnicodeSolid*(font: FontPtr; text: ptr uint16;
+  fg: Color): SurfacePtr {.importc: "TTF_RenderUNICODE_Solid".}
+# Create an 8-bit palettized surface and render the given glyph at
+#   fast quality with the given font and color.  The 0 pixel is the
+#   colorkey, giving a transparent background, and the 1 pixel is set
+#   to the text color.  The glyph is rendered without any padding or
+#   centering in the X direction, and aligned normally in the Y direction.
+#   This function returns the new surface, or NULL if there was an error.
+#
+proc renderGlyphSolid*(font: FontPtr; ch: uint16; fg: Color): SurfacePtr {.
+  importc: "TTF_RenderGlyph_Solid".}
+
+proc renderTextShaded*(font: FontPtr; text: cstring; fg, bg: Color): SurfacePtr {.
+  importc: "TTF_RenderText_Shaded".}
+proc renderUtf8Shaded*(font: FontPtr; text: cstring; fg, bg: Color): SurfacePtr {.
+  importc: "TTF_RenderUTF8_Shaded".}
+proc renderUnicodeShaded*(font: FontPtr; text: ptr uint16;
+  fg, bg: Color): SurfacePtr {.importc: "TTF_RenderUNICODE_Shaded".}
+# Create an 8-bit palettized surface and render the given glyph at
+#   high quality with the given font and colors.  The 0 pixel is background,
+#   while other pixels have varying degrees of the foreground color.
+#   The glyph is rendered without any padding or centering in the X
+#   direction, and aligned normally in the Y direction.
+#   This function returns the new surface, or NULL if there was an error.
+#
+proc renderGlyphShaded*(font: FontPtr; ch: uint16; fg, bg: Color): SurfacePtr {.
+  importc: "TTF_RenderGlyph_Shaded".}
+# Create a 32-bit ARGB surface and render the given text at high quality,
+#   using alpha blending to dither the font with the given color.
+#   This function returns the new surface, or NULL if there was an error.
+#
+proc renderTextBlended*(font: FontPtr; text: cstring; fg: Color): SurfacePtr {.
+  importc: "TTF_RenderText_Blended".}
+proc renderUtf8Blended*(font: FontPtr; text: cstring; fg: Color): SurfacePtr {.
+  importc: "TTF_RenderUTF8_Blended".}
+proc renderUnicodeBlended*(font: FontPtr; text: ptr uint16;
+  fg: Color): SurfacePtr {.importc: "TTF_RenderUNICODE_Blended".}
+# Create a 32-bit ARGB surface and render the given text at high quality,
+#   using alpha blending to dither the font with the given color.
+#   Text is wrapped to multiple lines on line endings and on word boundaries
+#   if it extends beyond wrapLength in pixels.
+#   This function returns the new surface, or NULL if there was an error.
+#
+proc renderTextBlendedWrapped*(font: FontPtr; text: cstring; fg: Color; wrapLength: uint32):
+  SurfacePtr {.importc: "TTF_RenderText_Blended_Wrapped".}
+proc renderUtf8BlendedWrapped*(font: FontPtr; text: cstring; fg: Color;
+  wrapLength: uint32): SurfacePtr {.importc: "TTF_RenderUTF8_Blended_Wrapped".}
+proc renderUnicodeBlendedWrapped*(font: FontPtr; text: ptr uint16; fg: Color;
+  wrapLength: uint32): SurfacePtr  {.importc: "TTF_RenderUNICODE_Blended_Wrapped".}
+# Create a 32-bit ARGB surface and render the given glyph at high quality,
+#   using alpha blending to dither the font with the given color.
+#   The glyph is rendered without any padding or centering in the X
+#   direction, and aligned normally in the Y direction.
+#   This function returns the new surface, or NULL if there was an error.
+#
+proc renderGlyphBlended*(font: FontPtr; ch: uint16; fg: Color): SurfacePtr {.
+  importc: "TTF_RenderGlyph_Blended".}
+
+
+#
+#/* Close an opened font file
+proc close*(font: FontPtr) {.importc: "TTF_CloseFont".}
+# De-initialize the TTF engine
+proc ttfQuit*() {.importc: "TTF_Quit".}
+# Check if the TTF engine is initialized
+proc ttfWasInit*(): bool {.importc: "TTF_WasInit".}
+# Get the kerning size of two glyphs
+proc getFontKerningSize*(font: FontPtr; prev_index, indx: cint): cint {.
+  importc: "TTF_GetFontKerningSize".}
+
+when not defined(SDL_Static):
+  {.pop.}
+
+
+# For compatibility with previous versions, here are the old functions
+##define TTF_RenderText(font, text, fg, bg)     \
+# TTF_RenderText_Shaded(font, text, fg, bg)
+##define TTF_RenderUTF8(font, text, fg, bg)     \
+# TTF_RenderUTF8_Shaded(font, text, fg, bg)
+##define TTF_RenderUNICODE(font, text, fg, bg)  \
+# TTF_RenderUNICODE_Shaded(font, text, fg, bg)
+
+proc renderText*(font: FontPtr; text: cstring;
+  fg, bg: Color): SurfacePtr = renderTextShaded(font, text, fg, bg)

+ 1 - 0
src/nodesnim/window.nim

@@ -195,3 +195,4 @@ proc windowLaunch* =
     raise newException(MainSceneNotLoadedError, "Main scene is not indicated!")
   changeScene(main_scene.name)
   glutMainLoop()
+  current_scene.exit()

+ 1 - 1
tests/test7.nim

@@ -31,7 +31,7 @@ violet.process =
   proc() =
     if Input.isActionJustPressed("change_scene"):
       echo "bye from main scene :("
-      changeScene("Second scene")
+      changeScene("Second scene")  # This function changes current scene.
 
 lightblue.process =
   proc() =

+ 22 - 0
tests/test8.nim

@@ -0,0 +1,22 @@
+# --- Test 8. Use TextureRect node. --- #
+import nodesnim
+
+
+Window("hello world")
+
+var
+  mainobj: SceneObj
+  main = Scene("Main", mainobj)
+
+  texturerectobj: TextureRectObj
+  texturerect = TextureRect(texturerectobj)
+
+main.addChild(texturerect)
+
+texturerect.loadTexture("assets/sharp.jpg")
+texturerect.resize(640, 360)
+
+
+addScene(main)
+setMainScene("Main")
+windowLaunch()