/*

Boost Software License - Version 1.0 - August 17th, 2003

Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:

The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

*/
module derelict.sdl2.internal.sdl_dynload;

public {
      import derelict.sdl2.internal.sdl_dynamic,
             derelict.sdl2.internal.sdl_types;
      import derelict.util.loader;
}

import derelict.util.exception,
       derelict.util.system;

/*
This function is not part of the public interface,  but SDL expects it to be called before any subsystems have been intiailized.
Normally, this happens via linking with libSDLmain, but since that doesn't happen when using Derelict, then the loader must
load this function and call it before the load method returns. Otherwise, bad things can happen.
*/
private extern(C) nothrow alias da_SDL_SetMainReady = void function();

class DerelictSDL2Loader : SharedLibLoader {
      this() {
            super(libNames);
      }

protected:
      override void configureMinimumVersion(SharedLibVersion minVersion)
      {
            if(minVersion.major == 2 && minVersion.minor == 0) {
                  if(minVersion.patch == 4) {
                        missingSymbolCallback = &allowSDL_2_0_4;
                  }
                  else if(minVersion.patch == 3) {
                        missingSymbolCallback = &allowSDL_2_0_3;
                  }
                  else if(minVersion.patch == 2) {
                        missingSymbolCallback = &allowSDL_2_0_2;
                  }
                  else if(minVersion.patch == 1) {
                        missingSymbolCallback = &allowSDL_2_0_1;
                  }
                  else if(minVersion.patch == 0) {
                        missingSymbolCallback = &allowSDL_2_0_0;
                  }
            }
      }

      override void loadSymbols()
      {
            bindFunc(cast(void**)&SDL_Init, "SDL_Init");
            bindFunc(cast(void**)&SDL_InitSubSystem, "SDL_InitSubSystem");
            bindFunc(cast(void**)&SDL_QuitSubSystem, "SDL_QuitSubSystem");
            bindFunc(cast(void**)&SDL_WasInit, "SDL_WasInit");
            bindFunc(cast(void**)&SDL_Quit, "SDL_Quit");
            bindFunc(cast(void**)&SDL_free, "SDL_free");
            bindFunc(cast(void**)&SDL_SetAssertionHandler, "SDL_SetAssertionHandler");
            bindFunc(cast(void**)&SDL_GetDefaultAssertionHandler, "SDL_GetDefaultAssertionHandler");
            bindFunc(cast(void**)&SDL_GetAssertionHandler, "SDL_GetAssertionHandler");
            bindFunc(cast(void**)&SDL_GetAssertionReport, "SDL_GetAssertionReport");
            bindFunc(cast(void**)&SDL_ResetAssertionReport, "SDL_ResetAssertionReport");
            bindFunc(cast(void**)&SDL_GetNumAudioDrivers, "SDL_GetNumAudioDrivers");
            bindFunc(cast(void**)&SDL_GetAudioDriver, "SDL_GetAudioDriver");
            bindFunc(cast(void**)&SDL_AudioInit, "SDL_AudioInit");
            bindFunc(cast(void**)&SDL_AudioQuit, "SDL_AudioQuit");
            bindFunc(cast(void**)&SDL_GetCurrentAudioDriver, "SDL_GetCurrentAudioDriver");
            bindFunc(cast(void**)&SDL_OpenAudio, "SDL_OpenAudio");
            bindFunc(cast(void**)&SDL_GetNumAudioDevices, "SDL_GetNumAudioDevices");
            bindFunc(cast(void**)&SDL_GetAudioDeviceName, "SDL_GetAudioDeviceName");
            bindFunc(cast(void**)&SDL_OpenAudioDevice, "SDL_OpenAudioDevice");
            bindFunc(cast(void**)&SDL_GetAudioStatus, "SDL_GetAudioStatus");
            bindFunc(cast(void**)&SDL_GetAudioDeviceStatus, "SDL_GetAudioDeviceStatus");
            bindFunc(cast(void**)&SDL_PauseAudio, "SDL_PauseAudio");
            bindFunc(cast(void**)&SDL_PauseAudioDevice, "SDL_PauseAudioDevice");
            bindFunc(cast(void**)&SDL_LoadWAV_RW, "SDL_LoadWAV_RW");
            bindFunc(cast(void**)&SDL_FreeWAV, "SDL_FreeWAV");
            bindFunc(cast(void**)&SDL_BuildAudioCVT, "SDL_BuildAudioCVT");
            bindFunc(cast(void**)&SDL_ConvertAudio, "SDL_ConvertAudio");
            bindFunc(cast(void**)&SDL_MixAudio, "SDL_MixAudio");
            bindFunc(cast(void**)&SDL_MixAudioFormat, "SDL_MixAudioFormat");
            bindFunc(cast(void**)&SDL_QueueAudio, "SDL_QueueAudio");
            bindFunc(cast(void**)&SDL_DequeueAudio, "SDL_DequeueAudio");
            bindFunc(cast(void**)&SDL_GetQueuedAudioSize, "SDL_GetQueuedAudioSize");
            bindFunc(cast(void**)&SDL_ClearQueuedAudio, "SDL_ClearQueuedAudio");
            bindFunc(cast(void**)&SDL_LockAudio, "SDL_LockAudio");
            bindFunc(cast(void**)&SDL_LockAudioDevice, "SDL_LockAudioDevice");
            bindFunc(cast(void**)&SDL_UnlockAudio, "SDL_UnlockAudio");
            bindFunc(cast(void**)&SDL_UnlockAudioDevice, "SDL_UnlockAudioDevice");
            bindFunc(cast(void**)&SDL_CloseAudio, "SDL_CloseAudio");
            bindFunc(cast(void**)&SDL_CloseAudioDevice, "SDL_CloseAudioDevice");
            //bindFunc(cast(void**)&SDL_AudioDeviceConnected, "SDL_AudioDeviceConnected");
            bindFunc(cast(void**)&SDL_SetClipboardText, "SDL_SetClipboardText");
            bindFunc(cast(void**)&SDL_GetClipboardText, "SDL_GetClipboardText");
            bindFunc(cast(void**)&SDL_HasClipboardText, "SDL_HasClipboardText");
            bindFunc(cast(void**)&SDL_GetCPUCount, "SDL_GetCPUCount");
            bindFunc(cast(void**)&SDL_GetCPUCacheLineSize, "SDL_GetCPUCacheLineSize");
            bindFunc(cast(void**)&SDL_HasRDTSC, "SDL_HasRDTSC");
            bindFunc(cast(void**)&SDL_HasAltiVec, "SDL_HasAltiVec");
            bindFunc(cast(void**)&SDL_HasMMX, "SDL_HasMMX");
            bindFunc(cast(void**)&SDL_Has3DNow, "SDL_Has3DNow");
            bindFunc(cast(void**)&SDL_HasSSE, "SDL_HasSSE");
            bindFunc(cast(void**)&SDL_HasSSE2, "SDL_HasSSE2");
            bindFunc(cast(void**)&SDL_HasSSE3, "SDL_HasSSE3");
            bindFunc(cast(void**)&SDL_HasSSE41, "SDL_HasSSE41");
            bindFunc(cast(void**)&SDL_HasSSE42, "SDL_HasSSE42");
            bindFunc(cast(void**)&SDL_HasAVX, "SDL_HasAVX");
            bindFunc(cast(void**)&SDL_HasAVX2, "SDL_HasAVX2");
            bindFunc(cast(void**)&SDL_GetSystemRAM, "SDL_GetSystemRAM");
            bindFunc(cast(void**)&SDL_SetError, "SDL_SetError");
            bindFunc(cast(void**)&SDL_GetError, "SDL_GetError");
            bindFunc(cast(void**)&SDL_ClearError, "SDL_ClearError");
            bindFunc(cast(void**)&SDL_PumpEvents, "SDL_PumpEvents");
            bindFunc(cast(void**)&SDL_PeepEvents, "SDL_PeepEvents");
            bindFunc(cast(void**)&SDL_HasEvent, "SDL_HasEvent");
            bindFunc(cast(void**)&SDL_HasEvents, "SDL_HasEvents");
            bindFunc(cast(void**)&SDL_FlushEvent, "SDL_FlushEvent");
            bindFunc(cast(void**)&SDL_FlushEvents, "SDL_FlushEvents");
            bindFunc(cast(void**)&SDL_PollEvent, "SDL_PollEvent");
            bindFunc(cast(void**)&SDL_WaitEvent, "SDL_WaitEvent");
            bindFunc(cast(void**)&SDL_WaitEventTimeout, "SDL_WaitEventTimeout");
            bindFunc(cast(void**)&SDL_PushEvent, "SDL_PushEvent");
            bindFunc(cast(void**)&SDL_SetEventFilter, "SDL_SetEventFilter");
            bindFunc(cast(void**)&SDL_GetEventFilter, "SDL_GetEventFilter");
            bindFunc(cast(void**)&SDL_AddEventWatch, "SDL_AddEventWatch");
            bindFunc(cast(void**)&SDL_DelEventWatch, "SDL_DelEventWatch");
            bindFunc(cast(void**)&SDL_FilterEvents, "SDL_FilterEvents");
            bindFunc(cast(void**)&SDL_EventState, "SDL_EventState");
            bindFunc(cast(void**)&SDL_RegisterEvents, "SDL_RegisterEvents");
            bindFunc(cast(void**)&SDL_GetBasePath, "SDL_GetBasePath");
            bindFunc(cast(void**)&SDL_GetPrefPath, "SDL_GetPrefPath");
            bindFunc(cast(void**)&SDL_GameControllerAddMappingsFromRW, "SDL_GameControllerAddMappingsFromRW");
            bindFunc(cast(void**)&SDL_GameControllerAddMapping, "SDL_GameControllerAddMapping");
            bindFunc(cast(void**)&SDL_GameControllerMappingForGUID, "SDL_GameControllerMappingForGUID");
            bindFunc(cast(void**)&SDL_GameControllerMapping, "SDL_GameControllerMapping");
            bindFunc(cast(void**)&SDL_IsGameController, "SDL_IsGameController");
            bindFunc(cast(void**)&SDL_GameControllerNameForIndex, "SDL_GameControllerNameForIndex");
            bindFunc(cast(void**)&SDL_GameControllerOpen, "SDL_GameControllerOpen");
            bindFunc(cast(void**)&SDL_GameControllerFromInstanceID, "SDL_GameControllerFromInstanceID");
            bindFunc(cast(void**)&SDL_GameControllerName, "SDL_GameControllerName");
            bindFunc(cast(void**)&SDL_GameControllerGetAttached, "SDL_GameControllerGetAttached");
            bindFunc(cast(void**)&SDL_GameControllerGetJoystick, "SDL_GameControllerGetJoystick");
            bindFunc(cast(void**)&SDL_GameControllerEventState, "SDL_GameControllerEventState");
            bindFunc(cast(void**)&SDL_GameControllerUpdate, "SDL_GameControllerUpdate");
            bindFunc(cast(void**)&SDL_GameControllerGetAxisFromString, "SDL_GameControllerGetAxisFromString");
            bindFunc(cast(void**)&SDL_GameControllerGetStringForAxis, "SDL_GameControllerGetStringForAxis");
            bindFunc(cast(void**)&SDL_GameControllerGetBindForAxis, "SDL_GameControllerGetBindForAxis");
            bindFunc(cast(void**)&SDL_GameControllerGetAxis, "SDL_GameControllerGetAxis");
            bindFunc(cast(void**)&SDL_GameControllerGetButtonFromString, "SDL_GameControllerGetButtonFromString");
            bindFunc(cast(void**)&SDL_GameControllerGetStringForButton, "SDL_GameControllerGetStringForButton");
            bindFunc(cast(void**)&SDL_GameControllerGetBindForButton, "SDL_GameControllerGetBindForButton");
            bindFunc(cast(void**)&SDL_GameControllerGetButton, "SDL_GameControllerGetButton");
            bindFunc(cast(void**)&SDL_GameControllerClose, "SDL_GameControllerClose");
            bindFunc(cast(void**)&SDL_RecordGesture, "SDL_RecordGesture");
            bindFunc(cast(void**)&SDL_SaveAllDollarTemplates, "SDL_SaveAllDollarTemplates");
            bindFunc(cast(void**)&SDL_SaveDollarTemplate, "SDL_SaveDollarTemplate");
            bindFunc(cast(void**)&SDL_LoadDollarTemplates, "SDL_LoadDollarTemplates");
            bindFunc(cast(void**)&SDL_NumHaptics, "SDL_NumHaptics");
            bindFunc(cast(void**)&SDL_HapticName, "SDL_HapticName");
            bindFunc(cast(void**)&SDL_HapticOpen, "SDL_HapticOpen");
            bindFunc(cast(void**)&SDL_HapticOpened, "SDL_HapticOpened");
            bindFunc(cast(void**)&SDL_HapticIndex, "SDL_HapticIndex");
            bindFunc(cast(void**)&SDL_MouseIsHaptic, "SDL_MouseIsHaptic");
            bindFunc(cast(void**)&SDL_HapticOpenFromMouse, "SDL_HapticOpenFromMouse");
            bindFunc(cast(void**)&SDL_JoystickIsHaptic, "SDL_JoystickIsHaptic");
            bindFunc(cast(void**)&SDL_HapticOpenFromJoystick, "SDL_HapticOpenFromJoystick");
            bindFunc(cast(void**)&SDL_HapticClose, "SDL_HapticClose");
            bindFunc(cast(void**)&SDL_HapticNumEffects, "SDL_HapticNumEffects");
            bindFunc(cast(void**)&SDL_HapticNumEffectsPlaying, "SDL_HapticNumEffectsPlaying");
            bindFunc(cast(void**)&SDL_HapticQuery, "SDL_HapticQuery");
            bindFunc(cast(void**)&SDL_HapticNumAxes, "SDL_HapticNumAxes");
            bindFunc(cast(void**)&SDL_HapticEffectSupported, "SDL_HapticEffectSupported");
            bindFunc(cast(void**)&SDL_HapticNewEffect, "SDL_HapticNewEffect");
            bindFunc(cast(void**)&SDL_HapticUpdateEffect, "SDL_HapticUpdateEffect");
            bindFunc(cast(void**)&SDL_HapticRunEffect, "SDL_HapticRunEffect");
            bindFunc(cast(void**)&SDL_HapticStopEffect, "SDL_HapticStopEffect");
            bindFunc(cast(void**)&SDL_HapticDestroyEffect, "SDL_HapticDestroyEffect");
            bindFunc(cast(void**)&SDL_HapticGetEffectStatus, "SDL_HapticGetEffectStatus");
            bindFunc(cast(void**)&SDL_HapticSetGain, "SDL_HapticSetGain");
            bindFunc(cast(void**)&SDL_HapticSetAutocenter, "SDL_HapticSetAutocenter");
            bindFunc(cast(void**)&SDL_HapticPause, "SDL_HapticPause");
            bindFunc(cast(void**)&SDL_HapticUnpause, "SDL_HapticUnpause");
            bindFunc(cast(void**)&SDL_HapticStopAll, "SDL_HapticStopAll");
            bindFunc(cast(void**)&SDL_HapticRumbleSupported, "SDL_HapticRumbleSupported");
            bindFunc(cast(void**)&SDL_HapticRumbleInit, "SDL_HapticRumbleInit");
            bindFunc(cast(void**)&SDL_HapticRumblePlay, "SDL_HapticRumblePlay");
            bindFunc(cast(void**)&SDL_HapticRumbleStop, "SDL_HapticRumbleStop");
            bindFunc(cast(void**)&SDL_SetHintWithPriority, "SDL_SetHintWithPriority");
            bindFunc(cast(void**)&SDL_SetHint, "SDL_SetHint");
            bindFunc(cast(void**)&SDL_GetHint, "SDL_GetHint");
            bindFunc(cast(void**)&SDL_GetHintBoolean, "SDL_GetHintBoolean");
            bindFunc(cast(void**)&SDL_AddHintCallback, "SDL_AddHintCallback");
            bindFunc(cast(void**)&SDL_DelHintCallback, "SDL_DelHintCallback");
            bindFunc(cast(void**)&SDL_ClearHints, "SDL_ClearHints");
            bindFunc(cast(void**)&SDL_NumJoysticks, "SDL_NumJoysticks");
            bindFunc(cast(void**)&SDL_JoystickNameForIndex, "SDL_JoystickNameForIndex");
            bindFunc(cast(void**)&SDL_JoystickOpen, "SDL_JoystickOpen");
            bindFunc(cast(void**)&SDL_JoystickName, "SDL_JoystickName");
            bindFunc(cast(void**)&SDL_JoystickFromInstanceID, "SDL_JoystickFromInstanceID");
            bindFunc(cast(void**)&SDL_JoystickGetDeviceGUID, "SDL_JoystickGetDeviceGUID");
            bindFunc(cast(void**)&SDL_JoystickGetGUID, "SDL_JoystickGetGUID");
            bindFunc(cast(void**)&SDL_JoystickGetGUIDString, "SDL_JoystickGetGUIDString");
            bindFunc(cast(void**)&SDL_JoystickGetGUIDFromString, "SDL_JoystickGetGUIDFromString");
            bindFunc(cast(void**)&SDL_JoystickGetAttached, "SDL_JoystickGetAttached");
            bindFunc(cast(void**)&SDL_JoystickInstanceID, "SDL_JoystickInstanceID");
            bindFunc(cast(void**)&SDL_JoystickNumAxes, "SDL_JoystickNumAxes");
            bindFunc(cast(void**)&SDL_JoystickNumBalls, "SDL_JoystickNumBalls");
            bindFunc(cast(void**)&SDL_JoystickNumHats, "SDL_JoystickNumHats");
            bindFunc(cast(void**)&SDL_JoystickNumButtons, "SDL_JoystickNumButtons");
            bindFunc(cast(void**)&SDL_JoystickUpdate, "SDL_JoystickUpdate");
            bindFunc(cast(void**)&SDL_JoystickEventState, "SDL_JoystickEventState");
            bindFunc(cast(void**)&SDL_JoystickGetAxis, "SDL_JoystickGetAxis");
            bindFunc(cast(void**)&SDL_JoystickGetHat, "SDL_JoystickGetHat");
            bindFunc(cast(void**)&SDL_JoystickGetBall, "SDL_JoystickGetBall");
            bindFunc(cast(void**)&SDL_JoystickGetButton, "SDL_JoystickGetButton");
            bindFunc(cast(void**)&SDL_JoystickClose, "SDL_JoystickClose");
            bindFunc(cast(void**)&SDL_JoystickCurrentPowerLevel, "SDL_JoystickCurrentPowerLevel");
            bindFunc(cast(void**)&SDL_GetKeyboardFocus, "SDL_GetKeyboardFocus");
            bindFunc(cast(void**)&SDL_GetKeyboardState, "SDL_GetKeyboardState");
            bindFunc(cast(void**)&SDL_GetModState, "SDL_GetModState");
            bindFunc(cast(void**)&SDL_SetModState, "SDL_SetModState");
            bindFunc(cast(void**)&SDL_GetKeyFromScancode, "SDL_GetKeyFromScancode");
            bindFunc(cast(void**)&SDL_GetScancodeFromKey, "SDL_GetScancodeFromKey");
            bindFunc(cast(void**)&SDL_GetScancodeName, "SDL_GetScancodeName");
            bindFunc(cast(void**)&SDL_GetScancodeFromName, "SDL_GetScancodeFromName");
            bindFunc(cast(void**)&SDL_GetKeyName, "SDL_GetKeyName");
            bindFunc(cast(void**)&SDL_GetKeyFromName, "SDL_GetKeyFromName");
            bindFunc(cast(void**)&SDL_StartTextInput, "SDL_StartTextInput");
            bindFunc(cast(void**)&SDL_IsTextInputActive, "SDL_IsTextInputActive");
            bindFunc(cast(void**)&SDL_StopTextInput, "SDL_StopTextInput");
            bindFunc(cast(void**)&SDL_SetTextInputRect, "SDL_SetTextInputRect");
            bindFunc(cast(void**)&SDL_HasScreenKeyboardSupport, "SDL_HasScreenKeyboardSupport");
            bindFunc(cast(void**)&SDL_IsScreenKeyboardShown, "SDL_IsScreenKeyboardShown");
            bindFunc(cast(void**)&SDL_LoadObject, "SDL_LoadObject");
            bindFunc(cast(void**)&SDL_LoadFunction, "SDL_LoadFunction");
            bindFunc(cast(void**)&SDL_UnloadObject, "SDL_UnloadObject");
            bindFunc(cast(void**)&SDL_LogSetAllPriority, "SDL_LogSetAllPriority");
            bindFunc(cast(void**)&SDL_LogSetPriority, "SDL_LogSetPriority");
            bindFunc(cast(void**)&SDL_LogGetPriority, "SDL_LogGetPriority");
            bindFunc(cast(void**)&SDL_LogResetPriorities, "SDL_LogResetPriorities");
            bindFunc(cast(void**)&SDL_Log, "SDL_Log");
            bindFunc(cast(void**)&SDL_LogVerbose, "SDL_LogVerbose");
            bindFunc(cast(void**)&SDL_LogDebug, "SDL_LogDebug");
            bindFunc(cast(void**)&SDL_LogInfo, "SDL_LogInfo");
            bindFunc(cast(void**)&SDL_LogWarn, "SDL_LogWarn");
            bindFunc(cast(void**)&SDL_LogError, "SDL_LogError");
            bindFunc(cast(void**)&SDL_LogCritical, "SDL_LogCritical");
            bindFunc(cast(void**)&SDL_LogMessage, "SDL_LogMessage");
            bindFunc(cast(void**)&SDL_LogMessageV, "SDL_LogMessageV");
            bindFunc(cast(void**)&SDL_LogGetOutputFunction, "SDL_LogGetOutputFunction");
            bindFunc(cast(void**)&SDL_LogSetOutputFunction, "SDL_LogSetOutputFunction");
            bindFunc(cast(void**)&SDL_ShowMessageBox, "SDL_ShowMessageBox");
            bindFunc(cast(void**)&SDL_ShowSimpleMessageBox, "SDL_ShowSimpleMessageBox");
            bindFunc(cast(void**)&SDL_GetMouseFocus, "SDL_GetMouseFocus");
            bindFunc(cast(void**)&SDL_GetMouseState, "SDL_GetMouseState");
            bindFunc(cast(void**)&SDL_GetGlobalMouseState, "SDL_GetGlobalMouseState");
            bindFunc(cast(void**)&SDL_GetRelativeMouseState, "SDL_GetRelativeMouseState");
            bindFunc(cast(void**)&SDL_WarpMouseInWindow, "SDL_WarpMouseInWindow");
            bindFunc(cast(void**)&SDL_WarpMouseGlobal, "SDL_WarpMouseGlobal");
            bindFunc(cast(void**)&SDL_SetRelativeMouseMode, "SDL_SetRelativeMouseMode");
            bindFunc(cast(void**)&SDL_CaptureMouse, "SDL_CaptureMouse");
            bindFunc(cast(void**)&SDL_GetRelativeMouseMode, "SDL_GetRelativeMouseMode");
            bindFunc(cast(void**)&SDL_CreateCursor, "SDL_CreateCursor");
            bindFunc(cast(void**)&SDL_CreateColorCursor, "SDL_CreateColorCursor");
            bindFunc(cast(void**)&SDL_CreateSystemCursor, "SDL_CreateSystemCursor");
            bindFunc(cast(void**)&SDL_SetCursor, "SDL_SetCursor");
            bindFunc(cast(void**)&SDL_GetCursor, "SDL_GetCursor");
            bindFunc(cast(void**)&SDL_GetDefaultCursor, "SDL_GetDefaultCursor");
            bindFunc(cast(void**)&SDL_FreeCursor, "SDL_FreeCursor");
            bindFunc(cast(void**)&SDL_ShowCursor, "SDL_ShowCursor");
            bindFunc(cast(void**)&SDL_GetPixelFormatName, "SDL_GetPixelFormatName");
            bindFunc(cast(void**)&SDL_PixelFormatEnumToMasks, "SDL_PixelFormatEnumToMasks");
            bindFunc(cast(void**)&SDL_MasksToPixelFormatEnum, "SDL_MasksToPixelFormatEnum");
            bindFunc(cast(void**)&SDL_AllocFormat, "SDL_AllocFormat");
            bindFunc(cast(void**)&SDL_FreeFormat, "SDL_FreeFormat");
            bindFunc(cast(void**)&SDL_AllocPalette, "SDL_AllocPalette");
            bindFunc(cast(void**)&SDL_SetPixelFormatPalette, "SDL_SetPixelFormatPalette");
            bindFunc(cast(void**)&SDL_SetPaletteColors, "SDL_SetPaletteColors");
            bindFunc(cast(void**)&SDL_FreePalette, "SDL_FreePalette");
            bindFunc(cast(void**)&SDL_MapRGB, "SDL_MapRGB");
            bindFunc(cast(void**)&SDL_MapRGBA, "SDL_MapRGBA");
            bindFunc(cast(void**)&SDL_GetRGB, "SDL_GetRGB");
            bindFunc(cast(void**)&SDL_GetRGBA, "SDL_GetRGBA");
            bindFunc(cast(void**)&SDL_CalculateGammaRamp, "SDL_CalculateGammaRamp");
            bindFunc(cast(void**)&SDL_GetPlatform, "SDL_GetPlatform");
            bindFunc(cast(void**)&SDL_GetPowerInfo, "SDL_GetPowerInfo");
            bindFunc(cast(void**)&SDL_HasIntersection, "SDL_HasIntersection");
            bindFunc(cast(void**)&SDL_IntersectRect, "SDL_IntersectRect");
            bindFunc(cast(void**)&SDL_UnionRect, "SDL_UnionRect");
            bindFunc(cast(void**)&SDL_EnclosePoints, "SDL_EnclosePoints");
            bindFunc(cast(void**)&SDL_IntersectRectAndLine, "SDL_IntersectRectAndLine");
            bindFunc(cast(void**)&SDL_GetNumRenderDrivers, "SDL_GetNumRenderDrivers");
            bindFunc(cast(void**)&SDL_GetRenderDriverInfo, "SDL_GetRenderDriverInfo");
            bindFunc(cast(void**)&SDL_CreateWindowAndRenderer, "SDL_CreateWindowAndRenderer");
            bindFunc(cast(void**)&SDL_CreateRenderer, "SDL_CreateRenderer");
            bindFunc(cast(void**)&SDL_CreateSoftwareRenderer, "SDL_CreateSoftwareRenderer");
            bindFunc(cast(void**)&SDL_GetRenderer, "SDL_GetRenderer");
            bindFunc(cast(void**)&SDL_GetRendererInfo, "SDL_GetRendererInfo");
            bindFunc(cast(void**)&SDL_GetRendererOutputSize, "SDL_GetRendererOutputSize");
            bindFunc(cast(void**)&SDL_CreateTexture, "SDL_CreateTexture");
            bindFunc(cast(void**)&SDL_CreateTextureFromSurface, "SDL_CreateTextureFromSurface");
            bindFunc(cast(void**)&SDL_QueryTexture, "SDL_QueryTexture");
            bindFunc(cast(void**)&SDL_SetTextureColorMod, "SDL_SetTextureColorMod");
            bindFunc(cast(void**)&SDL_GetTextureColorMod, "SDL_GetTextureColorMod");
            bindFunc(cast(void**)&SDL_SetTextureAlphaMod, "SDL_SetTextureAlphaMod");
            bindFunc(cast(void**)&SDL_GetTextureAlphaMod, "SDL_GetTextureAlphaMod");
            bindFunc(cast(void**)&SDL_SetTextureBlendMode, "SDL_SetTextureBlendMode");
            bindFunc(cast(void**)&SDL_GetTextureBlendMode, "SDL_GetTextureBlendMode");
            bindFunc(cast(void**)&SDL_UpdateTexture, "SDL_UpdateTexture");
            bindFunc(cast(void**)&SDL_UpdateYUVTexture, "SDL_UpdateYUVTexture");
            bindFunc(cast(void**)&SDL_LockTexture, "SDL_LockTexture");
            bindFunc(cast(void**)&SDL_UnlockTexture, "SDL_UnlockTexture");
            bindFunc(cast(void**)&SDL_RenderTargetSupported, "SDL_RenderTargetSupported");
            bindFunc(cast(void**)&SDL_SetRenderTarget, "SDL_SetRenderTarget");
            bindFunc(cast(void**)&SDL_GetRenderTarget, "SDL_GetRenderTarget");
            bindFunc(cast(void**)&SDL_RenderSetClipRect, "SDL_RenderSetClipRect");
            bindFunc(cast(void**)&SDL_RenderGetClipRect, "SDL_RenderGetClipRect");
            bindFunc(cast(void**)&SDL_RenderSetLogicalSize, "SDL_RenderSetLogicalSize");
            bindFunc(cast(void**)&SDL_RenderGetLogicalSize, "SDL_RenderGetLogicalSize");
            bindFunc(cast(void**)&SDL_RenderSetIntegerScale, "SDL_RenderSetIntegerScale");
            bindFunc(cast(void**)&SDL_RenderGetIntegerScale, "SDL_RenderGetIntegerScale");
            bindFunc(cast(void**)&SDL_RenderSetViewport, "SDL_RenderSetViewport");
            bindFunc(cast(void**)&SDL_RenderGetViewport, "SDL_RenderGetViewport");
            bindFunc(cast(void**)&SDL_RenderIsClipEnabled, "SDL_RenderIsClipEnabled");
            bindFunc(cast(void**)&SDL_RenderSetScale, "SDL_RenderSetScale");
            bindFunc(cast(void**)&SDL_RenderGetScale, "SDL_RenderGetScale");
            bindFunc(cast(void**)&SDL_SetRenderDrawColor, "SDL_SetRenderDrawColor");
            bindFunc(cast(void**)&SDL_GetRenderDrawColor, "SDL_GetRenderDrawColor");
            bindFunc(cast(void**)&SDL_SetRenderDrawBlendMode, "SDL_SetRenderDrawBlendMode");
            bindFunc(cast(void**)&SDL_GetRenderDrawBlendMode, "SDL_GetRenderDrawBlendMode");
            bindFunc(cast(void**)&SDL_RenderClear, "SDL_RenderClear");
            bindFunc(cast(void**)&SDL_RenderDrawPoint, "SDL_RenderDrawPoint");
            bindFunc(cast(void**)&SDL_RenderDrawPoints, "SDL_RenderDrawPoints");
            bindFunc(cast(void**)&SDL_RenderDrawLine, "SDL_RenderDrawLine");
            bindFunc(cast(void**)&SDL_RenderDrawLines, "SDL_RenderDrawLines");
            bindFunc(cast(void**)&SDL_RenderDrawRect, "SDL_RenderDrawRect");
            bindFunc(cast(void**)&SDL_RenderDrawRects, "SDL_RenderDrawRects");
            bindFunc(cast(void**)&SDL_RenderFillRect, "SDL_RenderFillRect");
            bindFunc(cast(void**)&SDL_RenderFillRects, "SDL_RenderFillRects");
            bindFunc(cast(void**)&SDL_RenderCopy, "SDL_RenderCopy");
            bindFunc(cast(void**)&SDL_RenderCopyEx, "SDL_RenderCopyEx");
            bindFunc(cast(void**)&SDL_RenderReadPixels, "SDL_RenderReadPixels");
            bindFunc(cast(void**)&SDL_RenderPresent, "SDL_RenderPresent");
            bindFunc(cast(void**)&SDL_DestroyTexture, "SDL_DestroyTexture");
            bindFunc(cast(void**)&SDL_DestroyRenderer, "SDL_DestroyRenderer");
            bindFunc(cast(void**)&SDL_GL_BindTexture, "SDL_GL_BindTexture");
            bindFunc(cast(void**)&SDL_GL_UnbindTexture, "SDL_GL_UnbindTexture");
            bindFunc(cast(void**)&SDL_RWFromFile, "SDL_RWFromFile");
            bindFunc(cast(void**)&SDL_RWFromFP, "SDL_RWFromFP");
            bindFunc(cast(void**)&SDL_RWFromMem, "SDL_RWFromMem");
            bindFunc(cast(void**)&SDL_RWFromConstMem, "SDL_RWFromConstMem");
            bindFunc(cast(void**)&SDL_AllocRW, "SDL_AllocRW");
            bindFunc(cast(void**)&SDL_FreeRW, "SDL_FreeRW");
            bindFunc(cast(void**)&SDL_ReadU8, "SDL_ReadU8");
            bindFunc(cast(void**)&SDL_ReadLE16, "SDL_ReadLE16");
            bindFunc(cast(void**)&SDL_ReadBE16, "SDL_ReadBE16");
            bindFunc(cast(void**)&SDL_ReadLE32, "SDL_ReadLE32");
            bindFunc(cast(void**)&SDL_ReadBE32, "SDL_ReadBE32");
            bindFunc(cast(void**)&SDL_ReadLE64, "SDL_ReadLE64");
            bindFunc(cast(void**)&SDL_ReadBE64, "SDL_ReadBE64");
            bindFunc(cast(void**)&SDL_WriteU8, "SDL_WriteU8");
            bindFunc(cast(void**)&SDL_WriteLE16, "SDL_WriteLE16");
            bindFunc(cast(void**)&SDL_WriteBE16, "SDL_WriteBE16");
            bindFunc(cast(void**)&SDL_WriteLE32, "SDL_WriteLE32");
            bindFunc(cast(void**)&SDL_WriteBE32, "SDL_WriteBE32");
            bindFunc(cast(void**)&SDL_WriteLE64, "SDL_WriteLE64");
            bindFunc(cast(void**)&SDL_WriteBE64, "SDL_WriteBE64");
            bindFunc(cast(void**)&SDL_CreateShapedWindow, "SDL_CreateShapedWindow");
            bindFunc(cast(void**)&SDL_IsShapedWindow, "SDL_IsShapedWindow");
            bindFunc(cast(void**)&SDL_SetWindowShape, "SDL_SetWindowShape");
            bindFunc(cast(void**)&SDL_GetShapedWindowMode, "SDL_GetShapedWindowMode");
            bindFunc(cast(void**)&SDL_CreateRGBSurface, "SDL_CreateRGBSurface");
            bindFunc(cast(void**)&SDL_CreateRGBSurfaceWithFormat, "SDL_CreateRGBSurfaceWithFormat");
            bindFunc(cast(void**)&SDL_CreateRGBSurfaceFrom, "SDL_CreateRGBSurfaceFrom");
            bindFunc(cast(void**)&SDL_CreateRGBSurfaceWithFormatFrom, "SDL_CreateRGBSurfaceWithFormatFrom");
            bindFunc(cast(void**)&SDL_FreeSurface, "SDL_FreeSurface");
            bindFunc(cast(void**)&SDL_SetSurfacePalette, "SDL_SetSurfacePalette");
            bindFunc(cast(void**)&SDL_LockSurface, "SDL_LockSurface");
            bindFunc(cast(void**)&SDL_UnlockSurface, "SDL_UnlockSurface");
            bindFunc(cast(void**)&SDL_LoadBMP_RW, "SDL_LoadBMP_RW");
            bindFunc(cast(void**)&SDL_SaveBMP_RW, "SDL_SaveBMP_RW");
            bindFunc(cast(void**)&SDL_SetSurfaceRLE, "SDL_SetSurfaceRLE");
            bindFunc(cast(void**)&SDL_SetColorKey, "SDL_SetColorKey");
            bindFunc(cast(void**)&SDL_GetColorKey, "SDL_GetColorKey");
            bindFunc(cast(void**)&SDL_SetSurfaceColorMod, "SDL_SetSurfaceColorMod");
            bindFunc(cast(void**)&SDL_GetSurfaceColorMod, "SDL_GetSurfaceColorMod");
            bindFunc(cast(void**)&SDL_SetSurfaceAlphaMod, "SDL_SetSurfaceAlphaMod");
            bindFunc(cast(void**)&SDL_GetSurfaceAlphaMod, "SDL_GetSurfaceAlphaMod");
            bindFunc(cast(void**)&SDL_SetSurfaceBlendMode, "SDL_SetSurfaceBlendMode");
            bindFunc(cast(void**)&SDL_GetSurfaceBlendMode, "SDL_GetSurfaceBlendMode");
            bindFunc(cast(void**)&SDL_SetClipRect, "SDL_SetClipRect");
            bindFunc(cast(void**)&SDL_GetClipRect, "SDL_GetClipRect");
            bindFunc(cast(void**)&SDL_ConvertSurface, "SDL_ConvertSurface");
            bindFunc(cast(void**)&SDL_ConvertSurfaceFormat, "SDL_ConvertSurfaceFormat");
            bindFunc(cast(void**)&SDL_ConvertPixels, "SDL_ConvertPixels");
            bindFunc(cast(void**)&SDL_FillRect, "SDL_FillRect");
            bindFunc(cast(void**)&SDL_FillRects, "SDL_FillRects");
            bindFunc(cast(void**)&SDL_UpperBlit, "SDL_UpperBlit");
            bindFunc(cast(void**)&SDL_LowerBlit, "SDL_LowerBlit");
            bindFunc(cast(void**)&SDL_SoftStretch, "SDL_SoftStretch");
            bindFunc(cast(void**)&SDL_UpperBlitScaled, "SDL_UpperBlitScaled");
            bindFunc(cast(void**)&SDL_LowerBlitScaled, "SDL_LowerBlitScaled");
            static if(Derelict_OS_Windows) {
                bindFunc(cast(void**)&SDL_Direct3D9GetAdapterIndex, "SDL_Direct3D9GetAdapterIndex") ;
                bindFunc(cast(void**)&SDL_RenderGetD3D9Device, "SDL_RenderGetD3D9Device");
                bindFunc(cast(void**)&SDL_DXGIGetOutputInfo, "SDL_DXGIGetOutputInfo");
            }
            static if(Derelict_OS_iOS) {
                bindFunc(cast(void**)&SDL_iPhoneSetAnimationCallback, "SDL_iPhoneSetAnimationCallback");
                bindFunc(cast(void**)&SDL_iPhoneSetEventPump, "SDL_iPhoneSetEventPump");
            }
            static if(Derelict_OS_Android) {
                bindFunc(cast(void**)&SDL_AndroidGetJNIEnv, "SDL_AndroidGetJNIEnv");
                bindFunc(cast(void**)&SDL_AndroidGetActivity, "SDL_AndroidGetActivity");

                bindFunc(cast(void**)&SDL_AndroidGetInternalStoragePath, "SDL_AndroidGetInternalStoragePath");
                bindFunc(cast(void**)&SDL_AndroidGetInternalStorageState, "SDL_AndroidGetInternalStorageState");
                bindFunc(cast(void**)&SDL_AndroidGetExternalStoragePath, "SDL_AndroidGetExternalStoragePath");
            }
            static if(Derelict_OS_WinRT) {
                bindFunc(cast(void**)&SDL_WinRTGetFSPathUNICODE, "SDL_WinRTGetFSPathUNICODE");
                bindFunc(cast(void**)&SDL_WinRTGetFSPathUTF8, "SDL_WinRTGetFSPathUTF8");
                bindFunc(cast(void**)&SDL_WinRTRunApp, "SDL_WinRTRunApp");
            }

            bindFunc(cast(void**)&SDL_GetWindowWMInfo, "SDL_GetWindowWMInfo");
            bindFunc(cast(void**)&SDL_GetTicks, "SDL_GetTicks");
            bindFunc(cast(void**)&SDL_GetPerformanceCounter, "SDL_GetPerformanceCounter");
            bindFunc(cast(void**)&SDL_GetPerformanceFrequency, "SDL_GetPerformanceFrequency");
            bindFunc(cast(void**)&SDL_Delay, "SDL_Delay");
            bindFunc(cast(void**)&SDL_AddTimer, "SDL_AddTimer");
            bindFunc(cast(void**)&SDL_RemoveTimer, "SDL_RemoveTimer");
            bindFunc(cast(void**)&SDL_GetNumTouchDevices, "SDL_GetNumTouchDevices");
            bindFunc(cast(void**)&SDL_GetTouchDevice, "SDL_GetTouchDevice");
            bindFunc(cast(void**)&SDL_GetNumTouchFingers, "SDL_GetNumTouchFingers");
            bindFunc(cast(void**)&SDL_GetTouchFinger, "SDL_GetTouchFinger");
            bindFunc(cast(void**)&SDL_GetVersion, "SDL_GetVersion");
            bindFunc(cast(void**)&SDL_GetRevision, "SDL_GetRevision");
            bindFunc(cast(void**)&SDL_GetRevisionNumber, "SDL_GetRevisionNumber");
            bindFunc(cast(void**)&SDL_GetNumVideoDrivers, "SDL_GetNumVideoDrivers");
            bindFunc(cast(void**)&SDL_GetVideoDriver, "SDL_GetVideoDriver");
            bindFunc(cast(void**)&SDL_VideoInit, "SDL_VideoInit");
            bindFunc(cast(void**)&SDL_VideoQuit, "SDL_VideoQuit");
            bindFunc(cast(void**)&SDL_GetCurrentVideoDriver, "SDL_GetCurrentVideoDriver");
            bindFunc(cast(void**)&SDL_GetNumVideoDisplays, "SDL_GetNumVideoDisplays");
            bindFunc(cast(void**)&SDL_GetDisplayName, "SDL_GetDisplayName");
            bindFunc(cast(void**)&SDL_GetDisplayBounds, "SDL_GetDisplayBounds");
            bindFunc(cast(void**)&SDL_GetDisplayDPI, "SDL_GetDisplayDPI");
            bindFunc(cast(void**)&SDL_GetDisplayUsableBounds, "SDL_GetDisplayUsableBounds");
            bindFunc(cast(void**)&SDL_GetNumDisplayModes, "SDL_GetNumDisplayModes");
            bindFunc(cast(void**)&SDL_GetDisplayMode, "SDL_GetDisplayMode");
            bindFunc(cast(void**)&SDL_GetDesktopDisplayMode, "SDL_GetDesktopDisplayMode");
            bindFunc(cast(void**)&SDL_GetCurrentDisplayMode, "SDL_GetCurrentDisplayMode");
            bindFunc(cast(void**)&SDL_GetClosestDisplayMode, "SDL_GetClosestDisplayMode");
            bindFunc(cast(void**)&SDL_GetWindowDisplayIndex, "SDL_GetWindowDisplayIndex");
            bindFunc(cast(void**)&SDL_SetWindowDisplayMode, "SDL_SetWindowDisplayMode");
            bindFunc(cast(void**)&SDL_GetWindowDisplayMode, "SDL_GetWindowDisplayMode");
            bindFunc(cast(void**)&SDL_GetWindowPixelFormat, "SDL_GetWindowPixelFormat");
            bindFunc(cast(void**)&SDL_CreateWindow, "SDL_CreateWindow");
            bindFunc(cast(void**)&SDL_CreateWindowFrom, "SDL_CreateWindowFrom");
            bindFunc(cast(void**)&SDL_GetWindowID, "SDL_GetWindowID");
            bindFunc(cast(void**)&SDL_GetWindowFromID, "SDL_GetWindowFromID");
            bindFunc(cast(void**)&SDL_GetWindowFlags, "SDL_GetWindowFlags");
            bindFunc(cast(void**)&SDL_SetWindowTitle, "SDL_SetWindowTitle");
            bindFunc(cast(void**)&SDL_GetWindowTitle, "SDL_GetWindowTitle");
            bindFunc(cast(void**)&SDL_SetWindowIcon, "SDL_SetWindowIcon");
            bindFunc(cast(void**)&SDL_SetWindowData, "SDL_SetWindowData");
            bindFunc(cast(void**)&SDL_GetWindowData, "SDL_GetWindowData");
            bindFunc(cast(void**)&SDL_SetWindowPosition, "SDL_SetWindowPosition");
            bindFunc(cast(void**)&SDL_GetWindowPosition, "SDL_GetWindowPosition");
            bindFunc(cast(void**)&SDL_SetWindowSize, "SDL_SetWindowSize");
            bindFunc(cast(void**)&SDL_GetWindowSize, "SDL_GetWindowSize");
            bindFunc(cast(void**)&SDL_GetWindowBordersSize, "SDL_GetWindowBordersSize");
            bindFunc(cast(void**)&SDL_SetWindowMinimumSize, "SDL_SetWindowMinimumSize");
            bindFunc(cast(void**)&SDL_GetWindowMinimumSize, "SDL_GetWindowMinimumSize");
            bindFunc(cast(void**)&SDL_SetWindowMaximumSize, "SDL_SetWindowMaximumSize");
            bindFunc(cast(void**)&SDL_GetWindowMaximumSize, "SDL_GetWindowMaximumSize");
            bindFunc(cast(void**)&SDL_SetWindowBordered, "SDL_SetWindowBordered");
            bindFunc(cast(void**)&SDL_SetWindowResizable, "SDL_SetWindowResizable");
            bindFunc(cast(void**)&SDL_ShowWindow, "SDL_ShowWindow");
            bindFunc(cast(void**)&SDL_HideWindow, "SDL_HideWindow");
            bindFunc(cast(void**)&SDL_RaiseWindow, "SDL_RaiseWindow");
            bindFunc(cast(void**)&SDL_MaximizeWindow, "SDL_MaximizeWindow");
            bindFunc(cast(void**)&SDL_MinimizeWindow, "SDL_MinimizeWindow");
            bindFunc(cast(void**)&SDL_RestoreWindow, "SDL_RestoreWindow");
            bindFunc(cast(void**)&SDL_SetWindowFullscreen, "SDL_SetWindowFullscreen");
            bindFunc(cast(void**)&SDL_GetWindowSurface, "SDL_GetWindowSurface");
            bindFunc(cast(void**)&SDL_UpdateWindowSurface, "SDL_UpdateWindowSurface");
            bindFunc(cast(void**)&SDL_UpdateWindowSurfaceRects, "SDL_UpdateWindowSurfaceRects");
            bindFunc(cast(void**)&SDL_SetWindowGrab, "SDL_SetWindowGrab");
            bindFunc(cast(void**)&SDL_GetWindowGrab, "SDL_GetWindowGrab");
            bindFunc(cast(void**)&SDL_GetGrabbedWindow, "SDL_GetGrabbedWindow");
            bindFunc(cast(void**)&SDL_SetWindowBrightness, "SDL_SetWindowBrightness");
            bindFunc(cast(void**)&SDL_GetWindowBrightness, "SDL_GetWindowBrightness");
            bindFunc(cast(void**)&SDL_SetWindowOpacity, "SDL_SetWindowOpacity");
            bindFunc(cast(void**)&SDL_GetWindowOpacity, "SDL_GetWindowOpacity");
            bindFunc(cast(void**)&SDL_SetWindowModalFor, "SDL_SetWindowModalFor");
            bindFunc(cast(void**)&SDL_SetWindowInputFocus, "SDL_SetWindowInputFocus");
            bindFunc(cast(void**)&SDL_SetWindowGammaRamp, "SDL_SetWindowGammaRamp");
            bindFunc(cast(void**)&SDL_GetWindowGammaRamp, "SDL_GetWindowGammaRamp");
            bindFunc(cast(void**)&SDL_SetWindowHitTest, "SDL_SetWindowHitTest");
            bindFunc(cast(void**)&SDL_DestroyWindow, "SDL_DestroyWindow");
            bindFunc(cast(void**)&SDL_IsScreenSaverEnabled, "SDL_IsScreenSaverEnabled");
            bindFunc(cast(void**)&SDL_EnableScreenSaver, "SDL_EnableScreenSaver");
            bindFunc(cast(void**)&SDL_DisableScreenSaver, "SDL_DisableScreenSaver");
            bindFunc(cast(void**)&SDL_GL_LoadLibrary, "SDL_GL_LoadLibrary");
            bindFunc(cast(void**)&SDL_GL_GetProcAddress, "SDL_GL_GetProcAddress");
            bindFunc(cast(void**)&SDL_GL_UnloadLibrary, "SDL_GL_UnloadLibrary");
            bindFunc(cast(void**)&SDL_GL_ExtensionSupported, "SDL_GL_ExtensionSupported");
            bindFunc(cast(void**)&SDL_GL_ResetAttributes, "SDL_GL_ResetAttributes");
            bindFunc(cast(void**)&SDL_GL_SetAttribute, "SDL_GL_SetAttribute");
            bindFunc(cast(void**)&SDL_GL_GetAttribute, "SDL_GL_GetAttribute");
            bindFunc(cast(void**)&SDL_GL_CreateContext, "SDL_GL_CreateContext");
            bindFunc(cast(void**)&SDL_GL_MakeCurrent, "SDL_GL_MakeCurrent");
            bindFunc(cast(void**)&SDL_GL_GetCurrentWindow, "SDL_GL_GetCurrentWindow");
            bindFunc(cast(void**)&SDL_GL_GetCurrentContext, "SDL_GL_GetCurrentContext");
            bindFunc(cast(void**)&SDL_GL_SetSwapInterval, "SDL_GL_SetSwapInterval");
            bindFunc(cast(void**)&SDL_GL_GetSwapInterval, "SDL_GL_GetSwapInterval");
            bindFunc(cast(void**)&SDL_GL_SwapWindow, "SDL_GL_SwapWindow");
            bindFunc(cast(void**)&SDL_GL_DeleteContext, "SDL_GL_DeleteContext");
            bindFunc(cast(void**)&SDL_GL_GetDrawableSize, "SDL_GL_GetDrawableSize");

            // SDL_init will fail if SDL_SetMainReady has not been called.
            // Since there's no SDL_main on the D side, it needs to be handled
            // manually. My understanding that this is fine on the platforms
            // that D is currently available on. If we ever get on to Android
            // or iPhone, though, this will need to be versioned.
            // I've wrapped it in a try/catch because it seem the function is
            // not always exported on Linux. See issue #153
            // https://github.com/aldacron/Derelict3/issues/153
            try {
                  da_SDL_SetMainReady setReady;
                  bindFunc(cast(void**)&setReady, "SDL_SetMainReady");
                  setReady();
            } catch( DerelictException de ) {}
      }

private:
      ShouldThrow allowSDL_2_0_0(string symbolName) {
            switch(symbolName) {
                  // Functions added in 2.0.1
                  case "SDL_free": break;
                  case "SDL_SetAssertionHandler": break;
                  case "SDL_GetAssertionReport": break;
                  case "SDL_ResetAssertionReport": break;
                  case "SDL_GetSystemRAM": break;
                  case "SDL_UpdateYUVTexture": break;
                  case "SDL_GL_GetDrawableSize": break;
                  case "SDL_GetBasePath": break;
                  case "SDL_GetPrefPath": break;
                  default: return allowSDL_2_0_1(symbolName);
            }
            return ShouldThrow.No;
      }

      ShouldThrow allowSDL_2_0_1(string symbolName)
      {
            switch(symbolName) {
                  // Functions added in 2.0.2
                  case "SDL_HasAVX": break;
                  case "SDL_GameControllerAddMappingsFromRW": break;
                  case "SDL_GetDefaultAssertionHandler": break;
                  case "SDL_GetAssertionHandler": break;
                  case "SDL_GL_ResetAttributes": break;

                  static if(Derelict_OS_Windows) {
                        case "SDL_Direct3D9GetAdapterIndex": break;
                        case "SDL_RenderGetD3D9Device": break;
                        case "SDL_DXGIGetOutputInfo": break;
                  } else static if(Derelict_OS_iOS) {
                        case "SDL_iPhoneSetAnimationCallback": break;
                        case "SDL_iPhoneSetEventPump": break;
                  } else static if(Derelict_OS_Android) {
                        case "SDL_AndroidGetJNIEnv": break;
                        case "SDL_AndroidGetActivity": break;
                        case "SDL_AndroidGetInternalStoragePath": break;
                        case "SDL_AndroidGetInternalStorageState": break;
                        case "SDL_AndroidGetExternalStoragePath": break;
                  }
                  default: return allowSDL_2_0_2(symbolName);
            }
            return ShouldThrow.No;
      }

      ShouldThrow allowSDL_2_0_2(string symbolName)
      {
            static if(Derelict_OS_WinRT) {
                  switch(symbolName) {
                        // Functions added in 2.0.3
                        static if(Derelict_OS_WinRT) {
                              case "SDL_WinRTGetFSPathUNICODE": break;
                              case "SDL_WinRTGetFSPathUTF8": break;
                              case "SDL_WinRTRunApp": break;
                        }
                        default: return allowSDL_2_0_3(symbolName);
                  }
            }
            return ShouldThrow.No;
      }

      ShouldThrow allowSDL_2_0_3(string symbolName)
      {
            switch(symbolName) {
                  // Functions added in 2.0.4
                  case "SDL_CaptureMouse": break;
                  case "SDL_ClearQueuedAudio": break;
                  case "SDL_GameControllerFromInstanceID": break;
                  case "SDL_GetDisplayDPI": break;
                  case "SDL_GetGlobalMouseState": break;
                  case "SDL_GetGrabbedWindow": break;
                  case "SDL_GetQueuedAudioSize": break;
                  case "SDL_HasAVX2": break;
                  case "SDL_JoystickCurrentPowerLevel": break;
                  case "SDL_JoystickFromInstanceID": break;
                  case "SDL_QueueAudio": break;
                  case "SDL_RenderIsClipEnabled": break;
                  case "SDL_SetWindowHitTest": break;
                  case "SDL_WarpMouseGlobal": break;
                  default: return allowSDL_2_0_4(symbolName);
            }
            return ShouldThrow.No;
      }

      ShouldThrow allowSDL_2_0_4(string symbolName)
      {
            switch(symbolName) {
                  // Functions added in 2.0.5
                  case "SDL_DequeueAudio": break;
                  case "SDL_GetHintBoolean": break;
                  case "SDL_RenderSetIntegerScale": break;
                  case "SDL_RenderGetIntegerScale": break;
                  case "SDL_CreateRGBSurfaceWithFormat": break;
                  case "SDL_CreateRGBSurfaceWithFormatFrom": break;
                  case "SDL_GetDisplayUsableBounds": break;
                  case "SDL_GetWindowBordersSize": break;
                  case "SDL_SetWindowResizable": break;
                  case "SDL_SetWindowOpacity": break;
                  case "SDL_GetWindowOpacity": break;
                  case "SDL_SetWindowModalFor": break;
                  case "SDL_SetWindowInputFocus": break;
                  default: return ShouldThrow.Yes;
            }
            return ShouldThrow.No;
      }
}

__gshared DerelictSDL2Loader DerelictSDL2;

shared static this()
{
    DerelictSDL2 = new DerelictSDL2Loader();
}

private:
      static if(Derelict_OS_Windows)
        enum libNames = "SDL2.dll";
      else static if(Derelict_OS_Mac)
        enum libNames = "libSDL2.dylib, /usr/local/lib/libSDL2.dylib, /usr/local/lib/libSDL2/libSDL2.dylib, ../Frameworks/SDL2.framework/SDL2, /Library/Frameworks/SDL2.framework/SDL2, /System/Library/Frameworks/SDL2.framework/SDL2, /opt/local/lib/libSDL2.dylib";
      else static if(Derelict_OS_Posix)
        enum libNames = "libSDL2.so, libSDL2-2.0.so, libSDL2-2.0.so.0, /usr/local/lib/libSDL2.so, /usr/local/lib/libSDL2-2.0.so, /usr/local/lib/libSDL2-2.0.so.0";
      else
        static assert(0, "Need to implement SDL2 libNames for this operating system.");
