Browse Source

Updated to stable SDL 2.0.

Lasse Öörni 12 years ago
parent
commit
5bfde24e0b
100 changed files with 10922 additions and 5909 deletions
  1. 920 810
      Source/Android/src/org/libsdl/app/SDLActivity.java
  2. 1 1
      Source/ThirdParty/SDL/CMakeLists.txt
  3. 23 42
      Source/ThirdParty/SDL/CREDITS.txt
  4. 11 12
      Source/ThirdParty/SDL/README.txt
  5. 6 5
      Source/ThirdParty/SDL/include/SDL.h
  6. 47 0
      Source/ThirdParty/SDL/include/SDL_atomic.h
  7. 12 7
      Source/ThirdParty/SDL/include/SDL_audio.h
  8. 11 4
      Source/ThirdParty/SDL/include/SDL_bits.h
  9. 11 4
      Source/ThirdParty/SDL/include/SDL_blendmode.h
  10. 5 5
      Source/ThirdParty/SDL/include/SDL_config.h
  11. 2 4
      Source/ThirdParty/SDL/include/SDL_config_android.h
  12. 0 3
      Source/ThirdParty/SDL/include/SDL_config_macosx.h
  13. 2 3
      Source/ThirdParty/SDL/include/SDL_config_windows.h
  14. 4 0
      Source/ThirdParty/SDL/include/SDL_gamecontroller.h
  15. 42 12
      Source/ThirdParty/SDL/include/SDL_haptic.h
  16. 43 4
      Source/ThirdParty/SDL/include/SDL_hints.h
  17. 4 0
      Source/ThirdParty/SDL/include/SDL_joystick.h
  18. 7 1
      Source/ThirdParty/SDL/include/SDL_platform.h
  19. 4 1
      Source/ThirdParty/SDL/include/SDL_render.h
  20. 2 2
      Source/ThirdParty/SDL/include/SDL_revision.h
  21. 1 1
      Source/ThirdParty/SDL/include/SDL_shape.h
  22. 13 456
      Source/ThirdParty/SDL/include/SDL_stdinc.h
  23. 14 16
      Source/ThirdParty/SDL/include/SDL_surface.h
  24. 1 1
      Source/ThirdParty/SDL/include/SDL_syswm.h
  25. 63 1
      Source/ThirdParty/SDL/include/SDL_thread.h
  26. 11 1
      Source/ThirdParty/SDL/include/SDL_video.h
  27. 63 45
      Source/ThirdParty/SDL/src/SDL.c
  28. 0 6
      Source/ThirdParty/SDL/src/SDL_assert.c
  29. 0 1
      Source/ThirdParty/SDL/src/SDL_assert_c.h
  30. 111 26
      Source/ThirdParty/SDL/src/SDL_hints.c
  31. 19 12
      Source/ThirdParty/SDL/src/SDL_log.c
  32. 14 0
      Source/ThirdParty/SDL/src/atomic/SDL_atomic.c
  33. 32 17
      Source/ThirdParty/SDL/src/audio/SDL_audio.c
  34. 1 2
      Source/ThirdParty/SDL/src/audio/SDL_audiocvt.c
  35. 1 1
      Source/ThirdParty/SDL/src/audio/alsa/SDL_alsa_audio.c
  36. 3 3
      Source/ThirdParty/SDL/src/audio/alsa/SDL_alsa_audio.h
  37. 4 18
      Source/ThirdParty/SDL/src/audio/android/SDL_androidaudio.c
  38. 2 0
      Source/ThirdParty/SDL/src/audio/android/SDL_androidaudio.h
  39. 0 3
      Source/ThirdParty/SDL/src/audio/coreaudio/SDL_coreaudio.h
  40. 44 34
      Source/ThirdParty/SDL/src/audio/directsound/SDL_directsound.c
  41. 4 4
      Source/ThirdParty/SDL/src/audio/disk/SDL_diskaudio.c
  42. 0 129
      Source/ThirdParty/SDL/src/audio/nds/SDL_ndsaudio.c
  43. 39 3
      Source/ThirdParty/SDL/src/audio/pulseaudio/SDL_pulseaudio.c
  44. 329 0
      Source/ThirdParty/SDL/src/audio/sndio/SDL_sndioaudio.c
  45. 13 10
      Source/ThirdParty/SDL/src/audio/sndio/SDL_sndioaudio.h
  46. 43 23
      Source/ThirdParty/SDL/src/audio/winmm/SDL_winmm.c
  47. 1426 1357
      Source/ThirdParty/SDL/src/core/android/SDL_android.c
  48. 1 0
      Source/ThirdParty/SDL/src/core/android/SDL_android.h
  49. 1 1
      Source/ThirdParty/SDL/src/events/SDL_events.c
  50. 2 1
      Source/ThirdParty/SDL/src/events/SDL_gesture.c
  51. 17 0
      Source/ThirdParty/SDL/src/events/SDL_mouse.c
  52. 2 1
      Source/ThirdParty/SDL/src/events/SDL_sysevents.h
  53. 0 41
      Source/ThirdParty/SDL/src/events/nds/SDL_ndsgesture.c
  54. 3 3
      Source/ThirdParty/SDL/src/events/scancodes_darwin.h
  55. 6 6
      Source/ThirdParty/SDL/src/events/scancodes_windows.h
  56. 14 14
      Source/ThirdParty/SDL/src/events/scancodes_xfree86.h
  57. 71 35
      Source/ThirdParty/SDL/src/haptic/SDL_haptic.c
  58. 7 4
      Source/ThirdParty/SDL/src/haptic/darwin/SDL_syshaptic.c
  59. 13 28
      Source/ThirdParty/SDL/src/haptic/dummy/SDL_syshaptic.c
  60. 30 4
      Source/ThirdParty/SDL/src/haptic/linux/SDL_syshaptic.c
  61. 0 330
      Source/ThirdParty/SDL/src/haptic/nds/SDL_syshaptic.c
  62. 105 25
      Source/ThirdParty/SDL/src/haptic/windows/SDL_syshaptic.c
  63. 1 37
      Source/ThirdParty/SDL/src/joystick/SDL_gamecontroller.c
  64. 65 0
      Source/ThirdParty/SDL/src/joystick/SDL_gamecontrollerdb.h
  65. 24 7
      Source/ThirdParty/SDL/src/joystick/SDL_joystick.c
  66. 16 0
      Source/ThirdParty/SDL/src/joystick/darwin/SDL_sysjoystick.c
  67. 0 209
      Source/ThirdParty/SDL/src/joystick/nds/SDL_sysjoystick.c
  68. 11 65
      Source/ThirdParty/SDL/src/libm/math_libm.h
  69. 14 0
      Source/ThirdParty/SDL/src/libm/math_private.h
  70. 1 1
      Source/ThirdParty/SDL/src/loadso/dlopen/SDL_sysloadso.c
  71. 5 0
      Source/ThirdParty/SDL/src/main/android/SDL_android_main.c
  72. 0 19
      Source/ThirdParty/SDL/src/main/android/SDL_android_main.cpp
  73. 4 2
      Source/ThirdParty/SDL/src/main/windows/SDL_windows_main.c
  74. 0 44
      Source/ThirdParty/SDL/src/power/nds/SDL_syspower.c
  75. 26 16
      Source/ThirdParty/SDL/src/render/SDL_render.c
  76. 8 8
      Source/ThirdParty/SDL/src/render/SDL_yuv_sw.c
  77. 376 54
      Source/ThirdParty/SDL/src/render/direct3d/SDL_render_d3d.c
  78. 0 315
      Source/ThirdParty/SDL/src/render/nds/SDL_libgl2D.c
  79. 0 154
      Source/ThirdParty/SDL/src/render/nds/SDL_libgl2D.h
  80. 0 418
      Source/ThirdParty/SDL/src/render/nds/SDL_ndsrender.c
  81. 1 0
      Source/ThirdParty/SDL/src/render/opengl/SDL_glfuncs.h
  82. 11 6
      Source/ThirdParty/SDL/src/render/opengl/SDL_render_gl.c
  83. 1 0
      Source/ThirdParty/SDL/src/render/opengles/SDL_glesfuncs.h
  84. 26 5
      Source/ThirdParty/SDL/src/render/opengles/SDL_render_gles.c
  85. 1 1
      Source/ThirdParty/SDL/src/render/opengles2/SDL_gles2funcs.h
  86. 11 9
      Source/ThirdParty/SDL/src/render/opengles2/SDL_render_gles2.c
  87. 0 2
      Source/ThirdParty/SDL/src/render/software/SDL_render_sw.c
  88. 12 6
      Source/ThirdParty/SDL/src/stdlib/SDL_getenv.c
  89. 4 4
      Source/ThirdParty/SDL/src/stdlib/SDL_iconv.c
  90. 21 10
      Source/ThirdParty/SDL/src/stdlib/SDL_malloc.c
  91. 2 3
      Source/ThirdParty/SDL/src/stdlib/SDL_qsort.c
  92. 123 686
      Source/ThirdParty/SDL/src/stdlib/SDL_stdlib.c
  93. 248 245
      Source/ThirdParty/SDL/src/stdlib/SDL_string.c
  94. 150 0
      Source/ThirdParty/SDL/src/test/SDL_test_assert.c
  95. 1411 0
      Source/ThirdParty/SDL/src/test/SDL_test_common.c
  96. 107 0
      Source/ThirdParty/SDL/src/test/SDL_test_compare.c
  97. 165 0
      Source/ThirdParty/SDL/src/test/SDL_test_crc32.c
  98. 3238 0
      Source/ThirdParty/SDL/src/test/SDL_test_font.c
  99. 524 0
      Source/ThirdParty/SDL/src/test/SDL_test_fuzzer.c
  100. 635 0
      Source/ThirdParty/SDL/src/test/SDL_test_harness.c

+ 920 - 810
Source/Android/src/org/libsdl/app/SDLActivity.java

@@ -1,810 +1,920 @@
-// Modified by Lasse Oorni for Urho3D
-
-package org.libsdl.app;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-
-import android.app.*;
-import android.content.*;
-import android.view.*;
-import android.view.inputmethod.BaseInputConnection;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.AbsoluteLayout;
-import android.os.*;
-import android.util.Log;
-import android.graphics.*;
-import android.media.*;
-import android.hardware.*;
-
-
-/**
-    SDL Activity
-*/
-public class SDLActivity extends Activity {
-    private static final String TAG = "SDL";
-
-    // Keep track of the paused state
-    public static boolean mIsPaused = false;
-
-    // Main components
-    protected static SDLActivity mSingleton;
-    protected static SDLSurface mSurface;
-    protected static View mTextEdit;
-    protected static ViewGroup mLayout;
-
-    // This is what SDL runs in. It invokes SDL_main(), eventually
-    protected static Thread mSDLThread;
-
-    // Audio
-    protected static Thread mAudioThread;
-    protected static AudioTrack mAudioTrack;
-
-    // EGL objects
-    protected static EGLContext  mEGLContext;
-    protected static EGLSurface  mEGLSurface;
-    protected static EGLDisplay  mEGLDisplay;
-    protected static EGLConfig   mEGLConfig;
-    protected static int mGLMajor, mGLMinor;
-
-    // Load the .so
-    static {
-		// Urho3D: everything resides in urho3d.so
-        System.loadLibrary("Urho3D");
-    }
-
-    // Setup
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        //Log.v("SDL", "onCreate()");
-        super.onCreate(savedInstanceState);
-        
-        // So we can call stuff from static callbacks
-        mSingleton = this;
-        
-        // Urho3D: reset paused status
-        mIsPaused = false;
-
-        // Set up the surface
-        mSurface = new SDLSurface(getApplication());
-
-        mLayout = new AbsoluteLayout(this);
-        mLayout.addView(mSurface);
-
-        setContentView(mLayout);
-    }
-
-    // Events
-    @Override
-    protected void onPause() {
-        Log.v("SDL", "onPause()");
-        super.onPause();
-        // Don't call SDLActivity.nativePause(); here, it will be called by SDLSurface::surfaceDestroyed
-    }
-
-    @Override
-    protected void onResume() {
-        Log.v("SDL", "onResume()");
-        super.onResume();
-        // Don't call SDLActivity.nativeResume(); here, it will be called via SDLSurface::surfaceChanged->SDLActivity::startApp
-    }
-
-    @Override
-    public void onLowMemory() {
-        Log.v("SDL", "onLowMemory()");
-        super.onLowMemory();
-        SDLActivity.nativeLowMemory();
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        Log.v("SDL", "onDestroy()");
-        // Send a quit message to the application
-        SDLActivity.nativeQuit();
-
-        // Now wait for the SDL thread to quit
-        if (mSDLThread != null) {
-            try {
-                mSDLThread.join();
-            } catch(Exception e) {
-                Log.v("SDL", "Problem stopping thread: " + e);
-            }
-            mSDLThread = null;
-
-            //Log.v("SDL", "Finished waiting for SDL thread");
-        }
-    }
-
-    // Messages from the SDLMain thread
-    static final int COMMAND_CHANGE_TITLE = 1;
-    static final int COMMAND_UNUSED = 2;
-    static final int COMMAND_TEXTEDIT_HIDE = 3;
-    // Urho3D: added
-    static final int COMMAND_FINISH = 4;
-
-    protected static final int COMMAND_USER = 0x8000;
-
-    /**
-     * This method is called by SDL if SDL did not handle a message itself.
-     * This happens if a received message contains an unsupported command.
-     * Method can be overwritten to handle Messages in a different class.
-     * @param command the command of the message.
-     * @param param the parameter of the message. May be null.
-     * @return if the message was handled in overridden method.
-     */
-    protected boolean onUnhandledMessage(int command, Object param) {
-        return false;
-    }
-
-    /**
-     * A Handler class for Messages from native SDL applications.
-     * It uses current Activities as target (e.g. for the title).
-     * static to prevent implicit references to enclosing object.
-     */
-    protected static class SDLCommandHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            Context context = getContext();
-            if (context == null) {
-                Log.e(TAG, "error handling message, getContext() returned null");
-                return;
-            }
-            switch (msg.arg1) {
-            case COMMAND_CHANGE_TITLE:
-                if (context instanceof Activity) {
-                    ((Activity) context).setTitle((String)msg.obj);
-                } else {
-                    Log.e(TAG, "error handling message, getContext() returned no Activity");
-                }
-                break;
-            case COMMAND_TEXTEDIT_HIDE:
-                if (mTextEdit != null) {
-                    mTextEdit.setVisibility(View.GONE);
-
-                    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
-                    imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0);
-                }
-                break;
-            // Urho3D: added
-            case COMMAND_FINISH:
-                if (context instanceof Activity)
-                    ((Activity) context).finish();
-                break;
-
-            default:
-                if ((context instanceof SDLActivity) && !((SDLActivity) context).onUnhandledMessage(msg.arg1, msg.obj)) {
-                    Log.e(TAG, "error handling message, command is " + msg.arg1);
-                }
-            }
-        }
-    }
-
-    // Handler for the messages
-    Handler commandHandler = new SDLCommandHandler();
-
-    // Send a message from the SDLMain thread
-    boolean sendCommand(int command, Object data) {
-        Message msg = commandHandler.obtainMessage();
-        msg.arg1 = command;
-        msg.obj = data;
-        return commandHandler.sendMessage(msg);
-    }
-
-    // C functions we call
-    public static native void nativeInit(String filesDir);
-    public static native void nativeLowMemory();
-    public static native void nativeQuit();
-    public static native void nativePause();
-    public static native void nativeResume();
-    public static native void onNativeResize(int x, int y, int format);
-    public static native void onNativeKeyDown(int keycode);
-    public static native void onNativeKeyUp(int keycode);
-    public static native void onNativeTouch(int touchDevId, int pointerFingerId,
-                                            int action, float x, 
-                                            float y, float p);
-    public static native void onNativeAccel(float x, float y, float z);
-    public static native void nativeRunAudioThread();
-
-
-    // Java functions called from C
-
-    public static boolean createGLContext(int majorVersion, int minorVersion, int[] attribs) {
-        return initEGL(majorVersion, minorVersion, attribs);
-    }
-
-    public static void flipBuffers() {
-        flipEGL();
-    }
-
-    public static boolean setActivityTitle(String title) {
-        // Called from SDLMain() thread and can't directly affect the view
-        return mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title);
-    }
-
-    public static void finishActivity()
-    {
-        mSingleton.sendCommand(COMMAND_FINISH, null);
-    }
-
-    public static boolean sendMessage(int command, int param) {
-        return mSingleton.sendCommand(command, Integer.valueOf(param));
-    }
-
-    public static Context getContext() {
-        return mSingleton;
-    }
-
-    public static void startApp() {
-        // Start up the C app thread
-        if (mSDLThread == null) {
-            mSDLThread = new Thread(new SDLMain(), "SDLThread");
-            mSDLThread.start();
-        }
-        else {
-            /*
-             * Some Android variants may send multiple surfaceChanged events, so we don't need to resume every time
-             * every time we get one of those events, only if it comes after surfaceDestroyed
-             */
-            if (mIsPaused) {
-                SDLActivity.nativeResume();
-                SDLActivity.mIsPaused = false;
-            }
-        }
-    }
-    
-    static class ShowTextInputTask implements Runnable {
-        /*
-         * This is used to regulate the pan&scan method to have some offset from
-         * the bottom edge of the input region and the top edge of an input
-         * method (soft keyboard)
-         */
-        static final int HEIGHT_PADDING = 15;
-
-        public int x, y, w, h;
-
-        public ShowTextInputTask(int x, int y, int w, int h) {
-            this.x = x;
-            this.y = y;
-            this.w = w;
-            this.h = h;
-        }
-
-        @Override
-        public void run() {
-            AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(
-                    w, h + HEIGHT_PADDING, x, y);
-
-            if (mTextEdit == null) {
-                mTextEdit = new DummyEdit(getContext());
-
-                mLayout.addView(mTextEdit, params);
-            } else {
-                mTextEdit.setLayoutParams(params);
-            }
-
-            mTextEdit.setVisibility(View.VISIBLE);
-            mTextEdit.requestFocus();
-
-            InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-            imm.showSoftInput(mTextEdit, 0);
-        }
-    }
-
-    public static boolean showTextInput(int x, int y, int w, int h) {
-        // Transfer the task to the main thread as a Runnable
-        return mSingleton.commandHandler.post(new ShowTextInputTask(x, y, w, h));
-    }
-
-
-    // EGL functions
-    public static boolean initEGL(int majorVersion, int minorVersion, int[] attribs) {
-        try {
-            if (SDLActivity.mEGLDisplay == null) {
-                Log.v("SDL", "Starting up OpenGL ES " + majorVersion + "." + minorVersion);
-
-                EGL10 egl = (EGL10)EGLContext.getEGL();
-
-                EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-
-                int[] version = new int[2];
-                egl.eglInitialize(dpy, version);
-
-                EGLConfig[] configs = new EGLConfig[1];
-                int[] num_config = new int[1];
-                if (!egl.eglChooseConfig(dpy, attribs, configs, 1, num_config) || num_config[0] == 0) {
-                    Log.e("SDL", "No EGL config available");
-                    return false;
-                }
-                EGLConfig config = configs[0];
-
-                SDLActivity.mEGLDisplay = dpy;
-                SDLActivity.mEGLConfig = config;
-                SDLActivity.mGLMajor = majorVersion;
-                SDLActivity.mGLMinor = minorVersion;
-            }
-            return SDLActivity.createEGLSurface();
-
-        } catch(Exception e) {
-            Log.v("SDL", e + "");
-            for (StackTraceElement s : e.getStackTrace()) {
-                Log.v("SDL", s.toString());
-            }
-            return false;
-        }
-    }
-
-    public static boolean createEGLContext() {
-        EGL10 egl = (EGL10)EGLContext.getEGL();
-        int EGL_CONTEXT_CLIENT_VERSION=0x3098;
-        int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, SDLActivity.mGLMajor, EGL10.EGL_NONE };
-        SDLActivity.mEGLContext = egl.eglCreateContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, EGL10.EGL_NO_CONTEXT, contextAttrs);
-        if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) {
-            Log.e("SDL", "Couldn't create context");
-            return false;
-        }
-        return true;
-    }
-
-    public static boolean createEGLSurface() {
-        if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLConfig != null) {
-            EGL10 egl = (EGL10)EGLContext.getEGL();
-            if (SDLActivity.mEGLContext == null) createEGLContext();
-
-            Log.v("SDL", "Creating new EGL Surface");
-            EGLSurface surface = egl.eglCreateWindowSurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, SDLActivity.mSurface, null);
-            if (surface == EGL10.EGL_NO_SURFACE) {
-                Log.e("SDL", "Couldn't create surface");
-                return false;
-            }
-
-            if (egl.eglGetCurrentContext() != SDLActivity.mEGLContext) {
-                if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) {
-                    Log.e("SDL", "Old EGL Context doesnt work, trying with a new one");
-                    // TODO: Notify the user via a message that the old context could not be restored, and that textures need to be manually restored.
-                    createEGLContext();
-                    if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) {
-                        Log.e("SDL", "Failed making EGL Context current");
-                        return false;
-                    }
-                }
-            }
-            SDLActivity.mEGLSurface = surface;
-            return true;
-        } else {
-            Log.e("SDL", "Surface creation failed, display = " + SDLActivity.mEGLDisplay + ", config = " + SDLActivity.mEGLConfig);
-            return false;
-        }
-    }
-
-    // EGL buffer flip
-    public static void flipEGL() {
-        try {
-            EGL10 egl = (EGL10)EGLContext.getEGL();
-
-            egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, null);
-
-            // drawing here
-
-            egl.eglWaitGL();
-
-            egl.eglSwapBuffers(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
-
-
-        } catch(Exception e) {
-            Log.v("SDL", "flipEGL(): " + e);
-            for (StackTraceElement s : e.getStackTrace()) {
-                Log.v("SDL", s.toString());
-            }
-        }
-    }
-
-    // Audio
-    public static void audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
-        int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
-        int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
-        int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
-        
-        Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + (sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
-        
-        // Let the user pick a larger buffer if they really want -- but ye
-        // gods they probably shouldn't, the minimums are horrifyingly high
-        // latency already
-        desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
-        
-        mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
-                channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
-        
-        audioStartThread();
-        
-        Log.v("SDL", "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + (mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
-    }
-    
-    public static void audioStartThread() {
-        mAudioThread = new Thread(new Runnable() {
-            @Override
-            public void run() {
-                mAudioTrack.play();
-                nativeRunAudioThread();
-            }
-        });
-        
-        // I'd take REALTIME if I could get it!
-        mAudioThread.setPriority(Thread.MAX_PRIORITY);
-        mAudioThread.start();
-    }
-    
-    public static void audioWriteShortBuffer(short[] buffer) {
-        for (int i = 0; i < buffer.length; ) {
-            int result = mAudioTrack.write(buffer, i, buffer.length - i);
-            if (result > 0) {
-                i += result;
-            } else if (result == 0) {
-                try {
-                    Thread.sleep(1);
-                } catch(InterruptedException e) {
-                    // Nom nom
-                }
-            } else {
-                Log.w("SDL", "SDL audio: error return from write(short)");
-                return;
-            }
-        }
-    }
-    
-    public static void audioWriteByteBuffer(byte[] buffer) {
-        for (int i = 0; i < buffer.length; ) {
-            int result = mAudioTrack.write(buffer, i, buffer.length - i);
-            if (result > 0) {
-                i += result;
-            } else if (result == 0) {
-                try {
-                    Thread.sleep(1);
-                } catch(InterruptedException e) {
-                    // Nom nom
-                }
-            } else {
-                Log.w("SDL", "SDL audio: error return from write(byte)");
-                return;
-            }
-        }
-    }
-
-    public static void audioQuit() {
-        if (mAudioThread != null) {
-            try {
-                mAudioThread.join();
-            } catch(Exception e) {
-                Log.v("SDL", "Problem stopping audio thread: " + e);
-            }
-            mAudioThread = null;
-
-            //Log.v("SDL", "Finished waiting for audio thread");
-        }
-
-        if (mAudioTrack != null) {
-            mAudioTrack.stop();
-            mAudioTrack = null;
-        }
-    }
-}
-
-/**
-    Simple nativeInit() runnable
-*/
-class SDLMain implements Runnable {
-    @Override
-    public void run() {
-        // Runs SDL_main()
-        SDLActivity.nativeInit(((Activity)SDLActivity.getContext()).getFilesDir().getAbsolutePath());
-
-        //Log.v("SDL", "SDL thread terminated");
-        // Urho3D: finish activity when SDL_main returns
-        SDLActivity.finishActivity();
-    }
-}
-
-
-/**
-    SDLSurface. This is what we draw on, so we need to know when it's created
-    in order to do anything useful. 
-
-    Because of this, that's where we set up the SDL thread
-*/
-class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, 
-    View.OnKeyListener, View.OnTouchListener, SensorEventListener  {
-
-    // Sensors
-    protected static SensorManager mSensorManager;
-
-    // Keep track of the surface size to normalize touch events
-    protected static float mWidth, mHeight;
-
-    // Startup    
-    public SDLSurface(Context context) {
-        super(context);
-        getHolder().addCallback(this); 
-    
-        setFocusable(true);
-        setFocusableInTouchMode(true);
-        requestFocus();
-        setOnKeyListener(this); 
-        setOnTouchListener(this);   
-
-        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
-
-        // Some arbitrary defaults to avoid a potential division by zero
-        mWidth = 1.0f;
-        mHeight = 1.0f;
-    }
-
-    // Called when we have a valid drawing surface
-    @Override
-    public void surfaceCreated(SurfaceHolder holder) {
-        Log.v("SDL", "surfaceCreated()");
-        holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
-        enableSensor(Sensor.TYPE_ACCELEROMETER, true);
-    }
-
-    // Called when we lose the surface
-    @Override
-    public void surfaceDestroyed(SurfaceHolder holder) {
-        Log.v("SDL", "surfaceDestroyed()");
-        if (!SDLActivity.mIsPaused) {
-            SDLActivity.mIsPaused = true;
-            SDLActivity.nativePause();
-        }
-        enableSensor(Sensor.TYPE_ACCELEROMETER, false);
-    }
-
-    // Called when the surface is resized
-    @Override
-    public void surfaceChanged(SurfaceHolder holder,
-                               int format, int width, int height) {
-        Log.v("SDL", "surfaceChanged()");
-
-        int sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565 by default
-        switch (format) {
-        case PixelFormat.A_8:
-            Log.v("SDL", "pixel format A_8");
-            break;
-        case PixelFormat.LA_88:
-            Log.v("SDL", "pixel format LA_88");
-            break;
-        case PixelFormat.L_8:
-            Log.v("SDL", "pixel format L_8");
-            break;
-        case PixelFormat.RGBA_4444:
-            Log.v("SDL", "pixel format RGBA_4444");
-            sdlFormat = 0x15421002; // SDL_PIXELFORMAT_RGBA4444
-            break;
-        case PixelFormat.RGBA_5551:
-            Log.v("SDL", "pixel format RGBA_5551");
-            sdlFormat = 0x15441002; // SDL_PIXELFORMAT_RGBA5551
-            break;
-        case PixelFormat.RGBA_8888:
-            Log.v("SDL", "pixel format RGBA_8888");
-            sdlFormat = 0x16462004; // SDL_PIXELFORMAT_RGBA8888
-            break;
-        case PixelFormat.RGBX_8888:
-            Log.v("SDL", "pixel format RGBX_8888");
-            sdlFormat = 0x16261804; // SDL_PIXELFORMAT_RGBX8888
-            break;
-        case PixelFormat.RGB_332:
-            Log.v("SDL", "pixel format RGB_332");
-            sdlFormat = 0x14110801; // SDL_PIXELFORMAT_RGB332
-            break;
-        case PixelFormat.RGB_565:
-            Log.v("SDL", "pixel format RGB_565");
-            sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565
-            break;
-        case PixelFormat.RGB_888:
-            Log.v("SDL", "pixel format RGB_888");
-            // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead?
-            sdlFormat = 0x16161804; // SDL_PIXELFORMAT_RGB888
-            break;
-        default:
-            Log.v("SDL", "pixel format unknown " + format);
-            break;
-        }
-
-        mWidth = width;
-        mHeight = height;
-        SDLActivity.onNativeResize(width, height, sdlFormat);
-        Log.v("SDL", "Window size:" + width + "x"+height);
-
-        SDLActivity.startApp();
-    }
-
-    // unused
-    @Override
-    public void onDraw(Canvas canvas) {}
-
-
-    // Key events
-    @Override
-    public boolean onKey(View  v, int keyCode, KeyEvent event) {
-
-        // Urho3D: let the home & volume keys be handled by the system
-        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_HOME)
-            return false;
-
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            //Log.v("SDL", "key down: " + keyCode);
-            SDLActivity.onNativeKeyDown(keyCode);
-            return true;
-        }
-        else if (event.getAction() == KeyEvent.ACTION_UP) {
-            //Log.v("SDL", "key up: " + keyCode);
-            SDLActivity.onNativeKeyUp(keyCode);
-            return true;
-        }
-        
-        return false;
-    }
-
-    // Touch events
-    @Override
-    public boolean onTouch(View v, MotionEvent event) {
-             final int touchDevId = event.getDeviceId();
-             final int pointerCount = event.getPointerCount();
-             // touchId, pointerId, action, x, y, pressure
-             int actionPointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; /* API 8: event.getActionIndex(); */
-             int pointerFingerId = event.getPointerId(actionPointerIndex);
-             int action = (event.getAction() & MotionEvent.ACTION_MASK); /* API 8: event.getActionMasked(); */
-
-             float x = event.getX(actionPointerIndex) / mWidth;
-             float y = event.getY(actionPointerIndex) / mHeight;
-             float p = event.getPressure(actionPointerIndex);
-
-             if (action == MotionEvent.ACTION_MOVE && pointerCount > 1) {
-                // TODO send motion to every pointer if its position has
-                // changed since prev event.
-                for (int i = 0; i < pointerCount; i++) {
-                    pointerFingerId = event.getPointerId(i);
-                    x = event.getX(i) / mWidth;
-                    y = event.getY(i) / mHeight;
-                    p = event.getPressure(i);
-                    SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
-                }
-             } else {
-                SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
-             }
-      return true;
-   } 
-
-    // Sensor events
-    public void enableSensor(int sensortype, boolean enabled) {
-        // TODO: This uses getDefaultSensor - what if we have >1 accels?
-        if (enabled) {
-            mSensorManager.registerListener(this, 
-                            mSensorManager.getDefaultSensor(sensortype), 
-                            SensorManager.SENSOR_DELAY_GAME, null);
-        } else {
-            mSensorManager.unregisterListener(this, 
-                            mSensorManager.getDefaultSensor(sensortype));
-        }
-    }
-    
-    @Override
-    public void onAccuracyChanged(Sensor sensor, int accuracy) {
-        // TODO
-    }
-
-    @Override
-    public void onSensorChanged(SensorEvent event) {
-        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
-            SDLActivity.onNativeAccel(event.values[0] / SensorManager.GRAVITY_EARTH,
-                                      event.values[1] / SensorManager.GRAVITY_EARTH,
-                                      event.values[2] / SensorManager.GRAVITY_EARTH);
-        }
-    }
-    
-}
-
-/* This is a fake invisible editor view that receives the input and defines the
- * pan&scan region
- */
-class DummyEdit extends View implements View.OnKeyListener {
-    InputConnection ic;
-
-    public DummyEdit(Context context) {
-        super(context);
-        setFocusableInTouchMode(true);
-        setFocusable(true);
-        setOnKeyListener(this);
-    }
-
-    @Override
-    public boolean onCheckIsTextEditor() {
-        return true;
-    }
-
-    @Override
-    public boolean onKey(View v, int keyCode, KeyEvent event) {
-
-        // This handles the hardware keyboard input
-        if (event.isPrintingKey()) {
-            if (event.getAction() == KeyEvent.ACTION_DOWN) {
-                ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
-            }
-            return true;
-        }
-
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            SDLActivity.onNativeKeyDown(keyCode);
-            return true;
-        } else if (event.getAction() == KeyEvent.ACTION_UP) {
-            SDLActivity.onNativeKeyUp(keyCode);
-            return true;
-        }
-
-        return false;
-    }
-
-    @Override
-    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
-        ic = new SDLInputConnection(this, true);
-
-        outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
-                | 33554432 /* API 11: EditorInfo.IME_FLAG_NO_FULLSCREEN */;
-
-        return ic;
-    }
-}
-
-class SDLInputConnection extends BaseInputConnection {
-
-    public SDLInputConnection(View targetView, boolean fullEditor) {
-        super(targetView, fullEditor);
-
-    }
-
-    @Override
-    public boolean sendKeyEvent(KeyEvent event) {
-
-        /*
-         * This handles the keycodes from soft keyboard (and IME-translated
-         * input from hardkeyboard)
-         */
-        int keyCode = event.getKeyCode();
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            if (event.isPrintingKey()) {
-                commitText(String.valueOf((char) event.getUnicodeChar()), 1);
-            }
-            SDLActivity.onNativeKeyDown(keyCode);
-            return true;
-        } else if (event.getAction() == KeyEvent.ACTION_UP) {
-
-            SDLActivity.onNativeKeyUp(keyCode);
-            return true;
-        }
-        return super.sendKeyEvent(event);
-    }
-
-    @Override
-    public boolean commitText(CharSequence text, int newCursorPosition) {
-
-        nativeCommitText(text.toString(), newCursorPosition);
-
-        return super.commitText(text, newCursorPosition);
-    }
-
-    @Override
-    public boolean setComposingText(CharSequence text, int newCursorPosition) {
-
-        nativeSetComposingText(text.toString(), newCursorPosition);
-
-        return super.setComposingText(text, newCursorPosition);
-    }
-
-    public native void nativeCommitText(String text, int newCursorPosition);
-
-    public native void nativeSetComposingText(String text, int newCursorPosition);
-
-}
+// Modified by Lasse Oorni for Urho3D
+
+package org.libsdl.app;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+
+import android.app.*;
+import android.content.*;
+import android.view.*;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AbsoluteLayout;
+import android.os.*;
+import android.util.Log;
+import android.graphics.*;
+import android.media.*;
+import android.hardware.*;
+
+
+/**
+    SDL Activity
+*/
+public class SDLActivity extends Activity {
+    private static final String TAG = "SDL";
+
+    // Keep track of the paused state
+    public static boolean mIsPaused = false, mIsSurfaceReady = false, mHasFocus = true;
+
+    // Main components
+    protected static SDLActivity mSingleton;
+    protected static SDLSurface mSurface;
+    protected static View mTextEdit;
+    protected static ViewGroup mLayout;
+
+    // This is what SDL runs in. It invokes SDL_main(), eventually
+    protected static Thread mSDLThread;
+
+    // Audio
+    protected static Thread mAudioThread;
+    protected static AudioTrack mAudioTrack;
+
+    // EGL objects
+    protected static EGLContext  mEGLContext;
+    protected static EGLSurface  mEGLSurface;
+    protected static EGLDisplay  mEGLDisplay;
+    protected static EGLConfig   mEGLConfig;
+    protected static int mGLMajor, mGLMinor;
+
+    // Load the .so
+    static {
+		// Urho3D: everything resides in urho3d.so
+        System.loadLibrary("Urho3D");
+    }
+
+    // Setup
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        //Log.v("SDL", "onCreate()");
+        super.onCreate(savedInstanceState);
+        
+        // So we can call stuff from static callbacks
+        mSingleton = this;
+
+        // Set up the surface
+        mEGLSurface = EGL10.EGL_NO_SURFACE;
+        mSurface = new SDLSurface(getApplication());
+        mEGLContext = EGL10.EGL_NO_CONTEXT;
+
+        mLayout = new AbsoluteLayout(this);
+        mLayout.addView(mSurface);
+
+        setContentView(mLayout);
+    }
+
+    // Events
+    @Override
+    protected void onPause() {
+        Log.v("SDL", "onPause()");
+        super.onPause();
+        SDLActivity.handlePause();
+    }
+
+    @Override
+    protected void onResume() {
+        Log.v("SDL", "onResume()");
+        super.onResume();
+        SDLActivity.handleResume();
+    }
+
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        Log.v("SDL", "onWindowFocusChanged(): " + hasFocus);
+
+        SDLActivity.mHasFocus = hasFocus;
+        if (hasFocus) {
+            SDLActivity.handleResume();
+        }
+    }
+
+    @Override
+    public void onLowMemory() {
+        Log.v("SDL", "onLowMemory()");
+        super.onLowMemory();
+        SDLActivity.nativeLowMemory();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        Log.v("SDL", "onDestroy()");
+        // Send a quit message to the application
+        SDLActivity.nativeQuit();
+
+        // Now wait for the SDL thread to quit
+        if (mSDLThread != null) {
+            try {
+                mSDLThread.join();
+            } catch(Exception e) {
+                Log.v("SDL", "Problem stopping thread: " + e);
+            }
+            mSDLThread = null;
+
+            //Log.v("SDL", "Finished waiting for SDL thread");
+        }
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        int keyCode = event.getKeyCode();
+        // Ignore volume keys so they're handled by Android
+        // Urho3D: also ignore the Home key
+        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
+            keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
+			keyCode == KeyEvent.KEYCODE_HOME) {
+            return false;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    /** Called by onPause or surfaceDestroyed. Even if surfaceDestroyed
+     *  is the first to be called, mIsSurfaceReady should still be set
+     *  to 'true' during the call to onPause (in a usual scenario).
+     */
+    public static void handlePause() {
+        if (!SDLActivity.mIsPaused && SDLActivity.mIsSurfaceReady) {
+            SDLActivity.mIsPaused = true;
+            SDLActivity.nativePause();
+            mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, false);
+        }
+    }
+
+    /** Called by onResume or surfaceCreated. An actual resume should be done only when the surface is ready.
+     * Note: Some Android variants may send multiple surfaceChanged events, so we don't need to resume
+     * every time we get one of those events, only if it comes after surfaceDestroyed
+     */
+    public static void handleResume() {
+        if (SDLActivity.mIsPaused && SDLActivity.mIsSurfaceReady && SDLActivity.mHasFocus) {
+            SDLActivity.mIsPaused = false;
+            SDLActivity.nativeResume();
+            mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true);
+        }
+    }
+
+
+    // Messages from the SDLMain thread
+    static final int COMMAND_CHANGE_TITLE = 1;
+    static final int COMMAND_UNUSED = 2;
+    static final int COMMAND_TEXTEDIT_HIDE = 3;
+    // Urho3D: added
+    static final int COMMAND_FINISH = 4;
+
+    protected static final int COMMAND_USER = 0x8000;
+
+    /**
+     * This method is called by SDL if SDL did not handle a message itself.
+     * This happens if a received message contains an unsupported command.
+     * Method can be overwritten to handle Messages in a different class.
+     * @param command the command of the message.
+     * @param param the parameter of the message. May be null.
+     * @return if the message was handled in overridden method.
+     */
+    protected boolean onUnhandledMessage(int command, Object param) {
+        return false;
+    }
+
+    /**
+     * A Handler class for Messages from native SDL applications.
+     * It uses current Activities as target (e.g. for the title).
+     * static to prevent implicit references to enclosing object.
+     */
+    protected static class SDLCommandHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            Context context = getContext();
+            if (context == null) {
+                Log.e(TAG, "error handling message, getContext() returned null");
+                return;
+            }
+            switch (msg.arg1) {
+            case COMMAND_CHANGE_TITLE:
+                if (context instanceof Activity) {
+                    ((Activity) context).setTitle((String)msg.obj);
+                } else {
+                    Log.e(TAG, "error handling message, getContext() returned no Activity");
+                }
+                break;
+            case COMMAND_TEXTEDIT_HIDE:
+                if (mTextEdit != null) {
+                    mTextEdit.setVisibility(View.GONE);
+
+                    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+                    imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0);
+                }
+                break;
+            // Urho3D: added
+            case COMMAND_FINISH:
+                if (context instanceof Activity)
+                    ((Activity) context).finish();
+                break;
+
+            default:
+                if ((context instanceof SDLActivity) && !((SDLActivity) context).onUnhandledMessage(msg.arg1, msg.obj)) {
+                    Log.e(TAG, "error handling message, command is " + msg.arg1);
+                }
+            }
+        }
+    }
+
+    // Handler for the messages
+    Handler commandHandler = new SDLCommandHandler();
+
+    // Send a message from the SDLMain thread
+    boolean sendCommand(int command, Object data) {
+        Message msg = commandHandler.obtainMessage();
+        msg.arg1 = command;
+        msg.obj = data;
+        return commandHandler.sendMessage(msg);
+    }
+
+    // C functions we call
+    public static native void nativeInit(String filesDir);
+    public static native void nativeLowMemory();
+    public static native void nativeQuit();
+    public static native void nativePause();
+    public static native void nativeResume();
+    public static native void onNativeResize(int x, int y, int format);
+    public static native void onNativeKeyDown(int keycode);
+    public static native void onNativeKeyUp(int keycode);
+    public static native void onNativeKeyboardFocusLost();
+    public static native void onNativeTouch(int touchDevId, int pointerFingerId,
+                                            int action, float x, 
+                                            float y, float p);
+    public static native void onNativeAccel(float x, float y, float z);
+
+    // Java functions called from C
+
+    public static boolean createGLContext(int majorVersion, int minorVersion, int[] attribs) {
+        return initEGL(majorVersion, minorVersion, attribs);
+    }
+    
+    public static void deleteGLContext() {
+        if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLContext != EGL10.EGL_NO_CONTEXT) {
+            EGL10 egl = (EGL10)EGLContext.getEGL();
+            egl.eglMakeCurrent(SDLActivity.mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+            egl.eglDestroyContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLContext);
+            SDLActivity.mEGLContext = EGL10.EGL_NO_CONTEXT;
+
+            if (SDLActivity.mEGLSurface != EGL10.EGL_NO_SURFACE) {
+                egl.eglDestroySurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
+                SDLActivity.mEGLSurface = EGL10.EGL_NO_SURFACE;
+            }
+        }
+    }
+
+    public static void flipBuffers() {
+        flipEGL();
+    }
+
+    public static boolean setActivityTitle(String title) {
+        // Called from SDLMain() thread and can't directly affect the view
+        return mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title);
+    }
+
+    public static void finishActivity()
+    {
+        mSingleton.sendCommand(COMMAND_FINISH, null);
+    }
+
+    public static boolean sendMessage(int command, int param) {
+        return mSingleton.sendCommand(command, Integer.valueOf(param));
+    }
+
+    public static Context getContext() {
+        return mSingleton;
+    }
+
+    static class ShowTextInputTask implements Runnable {
+        /*
+         * This is used to regulate the pan&scan method to have some offset from
+         * the bottom edge of the input region and the top edge of an input
+         * method (soft keyboard)
+         */
+        static final int HEIGHT_PADDING = 15;
+
+        public int x, y, w, h;
+
+        public ShowTextInputTask(int x, int y, int w, int h) {
+            this.x = x;
+            this.y = y;
+            this.w = w;
+            this.h = h;
+        }
+
+        @Override
+        public void run() {
+            AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(
+                    w, h + HEIGHT_PADDING, x, y);
+
+            if (mTextEdit == null) {
+                mTextEdit = new DummyEdit(getContext());
+
+                mLayout.addView(mTextEdit, params);
+            } else {
+                mTextEdit.setLayoutParams(params);
+            }
+
+            mTextEdit.setVisibility(View.VISIBLE);
+            mTextEdit.requestFocus();
+
+            InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+            imm.showSoftInput(mTextEdit, 0);
+        }
+    }
+
+    public static boolean showTextInput(int x, int y, int w, int h) {
+        // Transfer the task to the main thread as a Runnable
+        return mSingleton.commandHandler.post(new ShowTextInputTask(x, y, w, h));
+    }
+
+
+    // EGL functions
+    public static boolean initEGL(int majorVersion, int minorVersion, int[] attribs) {
+        try {
+            EGL10 egl = (EGL10)EGLContext.getEGL();
+            
+            if (SDLActivity.mEGLDisplay == null) {
+                SDLActivity.mEGLDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+                int[] version = new int[2];
+                egl.eglInitialize(SDLActivity.mEGLDisplay, version);
+            }
+            
+            if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) {
+                // No current GL context exists, we will create a new one.
+                Log.v("SDL", "Starting up OpenGL ES " + majorVersion + "." + minorVersion);
+                EGLConfig[] configs = new EGLConfig[128];
+                int[] num_config = new int[1];
+                if (!egl.eglChooseConfig(SDLActivity.mEGLDisplay, attribs, configs, 1, num_config) || num_config[0] == 0) {
+                    Log.e("SDL", "No EGL config available");
+                    return false;
+                }
+                EGLConfig config = null;
+                int bestdiff = -1, bitdiff;
+                int[] value = new int[1];
+                
+                // eglChooseConfig returns a number of configurations that match or exceed the requested attribs.
+                // From those, we select the one that matches our requirements more closely
+                Log.v("SDL", "Got " + num_config[0] + " valid modes from egl");
+                for(int i = 0; i < num_config[0]; i++) {
+                    bitdiff = 0;
+                    // Go through some of the attributes and compute the bit difference between what we want and what we get.
+                    for (int j = 0; ; j += 2) {
+                        if (attribs[j] == EGL10.EGL_NONE)
+                            break;
+
+                        if (attribs[j+1] != EGL10.EGL_DONT_CARE && (attribs[j] == EGL10.EGL_RED_SIZE ||
+                            attribs[j] == EGL10.EGL_GREEN_SIZE ||
+                            attribs[j] == EGL10.EGL_BLUE_SIZE ||
+                            attribs[j] == EGL10.EGL_ALPHA_SIZE ||
+                            attribs[j] == EGL10.EGL_DEPTH_SIZE ||
+                            attribs[j] == EGL10.EGL_STENCIL_SIZE)) {
+                            egl.eglGetConfigAttrib(SDLActivity.mEGLDisplay, configs[i], attribs[j], value);
+                            bitdiff += value[0] - attribs[j + 1]; // value is always >= attrib
+                        }
+                    }
+                    
+                    if (bitdiff < bestdiff || bestdiff == -1) {
+                        config = configs[i];
+                        bestdiff = bitdiff;
+                    }
+                    
+                    if (bitdiff == 0) break; // we found an exact match!
+                }
+                
+                Log.d("SDL", "Selected mode with a total bit difference of " + bestdiff);
+
+                SDLActivity.mEGLConfig = config;
+                SDLActivity.mGLMajor = majorVersion;
+                SDLActivity.mGLMinor = minorVersion;
+            }
+            
+            return SDLActivity.createEGLSurface();
+
+        } catch(Exception e) {
+            Log.v("SDL", e + "");
+            for (StackTraceElement s : e.getStackTrace()) {
+                Log.v("SDL", s.toString());
+            }
+            return false;
+        }
+    }
+
+    public static boolean createEGLContext() {
+        EGL10 egl = (EGL10)EGLContext.getEGL();
+        int EGL_CONTEXT_CLIENT_VERSION=0x3098;
+        int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, SDLActivity.mGLMajor, EGL10.EGL_NONE };
+        SDLActivity.mEGLContext = egl.eglCreateContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, EGL10.EGL_NO_CONTEXT, contextAttrs);
+        if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) {
+            Log.e("SDL", "Couldn't create context");
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean createEGLSurface() {
+        if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLConfig != null) {
+            EGL10 egl = (EGL10)EGLContext.getEGL();
+            if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) createEGLContext();
+
+            if (SDLActivity.mEGLSurface == EGL10.EGL_NO_SURFACE) {
+                Log.v("SDL", "Creating new EGL Surface");
+                SDLActivity.mEGLSurface = egl.eglCreateWindowSurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, SDLActivity.mSurface, null);
+                if (SDLActivity.mEGLSurface == EGL10.EGL_NO_SURFACE) {
+                    Log.e("SDL", "Couldn't create surface");
+                    return false;
+                }
+            }
+            else Log.v("SDL", "EGL Surface remains valid");
+
+            if (egl.eglGetCurrentContext() != SDLActivity.mEGLContext) {
+                if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface, SDLActivity.mEGLSurface, SDLActivity.mEGLContext)) {
+                    Log.e("SDL", "Old EGL Context doesnt work, trying with a new one");
+                    // TODO: Notify the user via a message that the old context could not be restored, and that textures need to be manually restored.
+                    createEGLContext();
+                    if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface, SDLActivity.mEGLSurface, SDLActivity.mEGLContext)) {
+                        Log.e("SDL", "Failed making EGL Context current");
+                        return false;
+                    }
+                }
+                else Log.v("SDL", "EGL Context made current");
+            }
+            else Log.v("SDL", "EGL Context remains current");
+
+            return true;
+        } else {
+            Log.e("SDL", "Surface creation failed, display = " + SDLActivity.mEGLDisplay + ", config = " + SDLActivity.mEGLConfig);
+            return false;
+        }
+    }
+
+    // EGL buffer flip
+    public static void flipEGL() {
+        try {
+            EGL10 egl = (EGL10)EGLContext.getEGL();
+
+            egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, null);
+
+            // drawing here
+
+            egl.eglWaitGL();
+
+            egl.eglSwapBuffers(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
+
+
+        } catch(Exception e) {
+            Log.v("SDL", "flipEGL(): " + e);
+            for (StackTraceElement s : e.getStackTrace()) {
+                Log.v("SDL", s.toString());
+            }
+        }
+    }
+
+    // Audio
+    public static int audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
+        int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
+        int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
+        
+        Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + (sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
+        
+        // Let the user pick a larger buffer if they really want -- but ye
+        // gods they probably shouldn't, the minimums are horrifyingly high
+        // latency already
+        desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
+        
+        if (mAudioTrack == null) {
+            mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
+                    channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
+            
+            // Instantiating AudioTrack can "succeed" without an exception and the track may still be invalid
+            // Ref: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/AudioTrack.java
+            // Ref: http://developer.android.com/reference/android/media/AudioTrack.html#getState()
+            
+            if (mAudioTrack.getState() != AudioTrack.STATE_INITIALIZED) {
+                Log.e("SDL", "Failed during initialization of Audio Track");
+                mAudioTrack = null;
+                return -1;
+            }
+            
+            mAudioTrack.play();
+        }
+       
+        Log.v("SDL", "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + (mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
+        
+        return 0;
+    }
+    
+    public static void audioWriteShortBuffer(short[] buffer) {
+        for (int i = 0; i < buffer.length; ) {
+            int result = mAudioTrack.write(buffer, i, buffer.length - i);
+            if (result > 0) {
+                i += result;
+            } else if (result == 0) {
+                try {
+                    Thread.sleep(1);
+                } catch(InterruptedException e) {
+                    // Nom nom
+                }
+            } else {
+                Log.w("SDL", "SDL audio: error return from write(short)");
+                return;
+            }
+        }
+    }
+    
+    public static void audioWriteByteBuffer(byte[] buffer) {
+        for (int i = 0; i < buffer.length; ) {
+            int result = mAudioTrack.write(buffer, i, buffer.length - i);
+            if (result > 0) {
+                i += result;
+            } else if (result == 0) {
+                try {
+                    Thread.sleep(1);
+                } catch(InterruptedException e) {
+                    // Nom nom
+                }
+            } else {
+                Log.w("SDL", "SDL audio: error return from write(byte)");
+                return;
+            }
+        }
+    }
+
+    public static void audioQuit() {
+        if (mAudioTrack != null) {
+            mAudioTrack.stop();
+            mAudioTrack = null;
+        }
+    }
+}
+
+/**
+    Simple nativeInit() runnable
+*/
+class SDLMain implements Runnable {
+    @Override
+    public void run() {
+        // Runs SDL_main()
+        // Urho3D: pass filesDir
+        SDLActivity.nativeInit(((Activity)SDLActivity.getContext()).getFilesDir().getAbsolutePath());
+        //Log.v("SDL", "SDL thread terminated");
+        // Urho3D: finish activity when SDL_main returns
+        SDLActivity.finishActivity();
+    }
+}
+
+
+/**
+    SDLSurface. This is what we draw on, so we need to know when it's created
+    in order to do anything useful. 
+
+    Because of this, that's where we set up the SDL thread
+*/
+class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, 
+    View.OnKeyListener, View.OnTouchListener, SensorEventListener  {
+
+    // Sensors
+    protected static SensorManager mSensorManager;
+
+    // Keep track of the surface size to normalize touch events
+    protected static float mWidth, mHeight;
+
+    // Startup    
+    public SDLSurface(Context context) {
+        super(context);
+        getHolder().addCallback(this); 
+    
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+        requestFocus();
+        setOnKeyListener(this); 
+        setOnTouchListener(this);   
+
+        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
+
+        // Some arbitrary defaults to avoid a potential division by zero
+        mWidth = 1.0f;
+        mHeight = 1.0f;
+    }
+
+    // Called when we have a valid drawing surface
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+        Log.v("SDL", "surfaceCreated()");
+        holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
+        // Set mIsSurfaceReady to 'true' *before* any call to handleResume
+        SDLActivity.mIsSurfaceReady = true;
+    }
+
+    // Called when we lose the surface
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        Log.v("SDL", "surfaceDestroyed()");
+        // Call this *before* setting mIsSurfaceReady to 'false'
+        SDLActivity.handlePause();
+        SDLActivity.mIsSurfaceReady = false;
+
+        /* We have to clear the current context and destroy the egl surface here
+         * Otherwise there's BAD_NATIVE_WINDOW errors coming from eglCreateWindowSurface on resume
+         * Ref: http://stackoverflow.com/questions/8762589/eglcreatewindowsurface-on-ics-and-switching-from-2d-to-3d
+         */
+        
+        EGL10 egl = (EGL10)EGLContext.getEGL();
+        egl.eglMakeCurrent(SDLActivity.mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+        egl.eglDestroySurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
+        SDLActivity.mEGLSurface = EGL10.EGL_NO_SURFACE;
+    }
+
+    // Called when the surface is resized
+    @Override
+    public void surfaceChanged(SurfaceHolder holder,
+                               int format, int width, int height) {
+        Log.v("SDL", "surfaceChanged()");
+
+        int sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565 by default
+        switch (format) {
+        case PixelFormat.A_8:
+            Log.v("SDL", "pixel format A_8");
+            break;
+        case PixelFormat.LA_88:
+            Log.v("SDL", "pixel format LA_88");
+            break;
+        case PixelFormat.L_8:
+            Log.v("SDL", "pixel format L_8");
+            break;
+        case PixelFormat.RGBA_4444:
+            Log.v("SDL", "pixel format RGBA_4444");
+            sdlFormat = 0x15421002; // SDL_PIXELFORMAT_RGBA4444
+            break;
+        case PixelFormat.RGBA_5551:
+            Log.v("SDL", "pixel format RGBA_5551");
+            sdlFormat = 0x15441002; // SDL_PIXELFORMAT_RGBA5551
+            break;
+        case PixelFormat.RGBA_8888:
+            Log.v("SDL", "pixel format RGBA_8888");
+            sdlFormat = 0x16462004; // SDL_PIXELFORMAT_RGBA8888
+            break;
+        case PixelFormat.RGBX_8888:
+            Log.v("SDL", "pixel format RGBX_8888");
+            sdlFormat = 0x16261804; // SDL_PIXELFORMAT_RGBX8888
+            break;
+        case PixelFormat.RGB_332:
+            Log.v("SDL", "pixel format RGB_332");
+            sdlFormat = 0x14110801; // SDL_PIXELFORMAT_RGB332
+            break;
+        case PixelFormat.RGB_565:
+            Log.v("SDL", "pixel format RGB_565");
+            sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565
+            break;
+        case PixelFormat.RGB_888:
+            Log.v("SDL", "pixel format RGB_888");
+            // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead?
+            sdlFormat = 0x16161804; // SDL_PIXELFORMAT_RGB888
+            break;
+        default:
+            Log.v("SDL", "pixel format unknown " + format);
+            break;
+        }
+
+        mWidth = width;
+        mHeight = height;
+        SDLActivity.onNativeResize(width, height, sdlFormat);
+        Log.v("SDL", "Window size:" + width + "x"+height);
+
+        // Set mIsSurfaceReady to 'true' *before* making a call to handleResume
+        SDLActivity.mIsSurfaceReady = true;
+
+        if (SDLActivity.mSDLThread == null) {
+            // This is the entry point to the C app.
+            // Start up the C app thread and enable sensor input for the first time
+
+            SDLActivity.mSDLThread = new Thread(new SDLMain(), "SDLThread");
+            enableSensor(Sensor.TYPE_ACCELEROMETER, true);
+            SDLActivity.mSDLThread.start();
+        } else {
+            // The app already exists, we resume via handleResume
+            // Multiple sequential calls to surfaceChanged are handled internally by handleResume
+
+            SDLActivity.handleResume();
+        }
+    }
+
+    // unused
+    @Override
+    public void onDraw(Canvas canvas) {}
+
+
+    // Key events
+    @Override
+    public boolean onKey(View  v, int keyCode, KeyEvent event) {
+        
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            //Log.v("SDL", "key down: " + keyCode);
+            SDLActivity.onNativeKeyDown(keyCode);
+            return true;
+        }
+        else if (event.getAction() == KeyEvent.ACTION_UP) {
+            //Log.v("SDL", "key up: " + keyCode);
+            SDLActivity.onNativeKeyUp(keyCode);
+            return true;
+        }
+        
+        return false;
+    }
+
+    // Touch events
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+             final int touchDevId = event.getDeviceId();
+             final int pointerCount = event.getPointerCount();
+             // touchId, pointerId, action, x, y, pressure
+             int actionPointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; /* API 8: event.getActionIndex(); */
+             int pointerFingerId = event.getPointerId(actionPointerIndex);
+             int action = (event.getAction() & MotionEvent.ACTION_MASK); /* API 8: event.getActionMasked(); */
+
+             float x = event.getX(actionPointerIndex) / mWidth;
+             float y = event.getY(actionPointerIndex) / mHeight;
+             float p = event.getPressure(actionPointerIndex);
+
+             if (action == MotionEvent.ACTION_MOVE && pointerCount > 1) {
+                // TODO send motion to every pointer if its position has
+                // changed since prev event.
+                for (int i = 0; i < pointerCount; i++) {
+                    pointerFingerId = event.getPointerId(i);
+                    x = event.getX(i) / mWidth;
+                    y = event.getY(i) / mHeight;
+                    p = event.getPressure(i);
+                    SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
+                }
+             } else {
+                SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
+             }
+      return true;
+   } 
+
+    // Sensor events
+    public void enableSensor(int sensortype, boolean enabled) {
+        // TODO: This uses getDefaultSensor - what if we have >1 accels?
+        if (enabled) {
+            mSensorManager.registerListener(this, 
+                            mSensorManager.getDefaultSensor(sensortype), 
+                            SensorManager.SENSOR_DELAY_GAME, null);
+        } else {
+            mSensorManager.unregisterListener(this, 
+                            mSensorManager.getDefaultSensor(sensortype));
+        }
+    }
+    
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        // TODO
+    }
+
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+            SDLActivity.onNativeAccel(event.values[0] / SensorManager.GRAVITY_EARTH,
+                                      event.values[1] / SensorManager.GRAVITY_EARTH,
+                                      event.values[2] / SensorManager.GRAVITY_EARTH);
+        }
+    }
+    
+}
+
+/* This is a fake invisible editor view that receives the input and defines the
+ * pan&scan region
+ */
+class DummyEdit extends View implements View.OnKeyListener {
+    InputConnection ic;
+
+    public DummyEdit(Context context) {
+        super(context);
+        setFocusableInTouchMode(true);
+        setFocusable(true);
+        setOnKeyListener(this);
+    }
+
+    @Override
+    public boolean onCheckIsTextEditor() {
+        return true;
+    }
+
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+
+        // This handles the hardware keyboard input
+        if (event.isPrintingKey()) {
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
+            }
+            return true;
+        }
+
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            SDLActivity.onNativeKeyDown(keyCode);
+            return true;
+        } else if (event.getAction() == KeyEvent.ACTION_UP) {
+            SDLActivity.onNativeKeyUp(keyCode);
+            return true;
+        }
+
+        return false;
+    }
+        
+    //
+    @Override
+    public boolean onKeyPreIme (int keyCode, KeyEvent event) {
+        // As seen on StackOverflow: http://stackoverflow.com/questions/7634346/keyboard-hide-event
+        // FIXME: Discussion at http://bugzilla.libsdl.org/show_bug.cgi?id=1639
+        // FIXME: This is not a 100% effective solution to the problem of detecting if the keyboard is showing or not
+        // FIXME: A more effective solution would be to change our Layout from AbsoluteLayout to Relative or Linear
+        // FIXME: And determine the keyboard presence doing this: http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android
+        // FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :)
+        if (event.getAction()==KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
+            if (SDLActivity.mTextEdit != null && SDLActivity.mTextEdit.getVisibility() == View.VISIBLE) {
+                SDLActivity.onNativeKeyboardFocusLost();
+            }
+        }
+        return super.onKeyPreIme(keyCode, event);
+    }
+
+    @Override
+    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+        ic = new SDLInputConnection(this, true);
+
+        outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
+                | 33554432 /* API 11: EditorInfo.IME_FLAG_NO_FULLSCREEN */;
+
+        return ic;
+    }
+}
+
+class SDLInputConnection extends BaseInputConnection {
+
+    public SDLInputConnection(View targetView, boolean fullEditor) {
+        super(targetView, fullEditor);
+
+    }
+
+    @Override
+    public boolean sendKeyEvent(KeyEvent event) {
+
+        /*
+         * This handles the keycodes from soft keyboard (and IME-translated
+         * input from hardkeyboard)
+         */
+        int keyCode = event.getKeyCode();
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            if (event.isPrintingKey()) {
+                commitText(String.valueOf((char) event.getUnicodeChar()), 1);
+            }
+            SDLActivity.onNativeKeyDown(keyCode);
+            return true;
+        } else if (event.getAction() == KeyEvent.ACTION_UP) {
+
+            SDLActivity.onNativeKeyUp(keyCode);
+            return true;
+        }
+        return super.sendKeyEvent(event);
+    }
+
+    @Override
+    public boolean commitText(CharSequence text, int newCursorPosition) {
+
+        nativeCommitText(text.toString(), newCursorPosition);
+
+        return super.commitText(text, newCursorPosition);
+    }
+
+    @Override
+    public boolean setComposingText(CharSequence text, int newCursorPosition) {
+
+        nativeSetComposingText(text.toString(), newCursorPosition);
+
+        return super.setComposingText(text, newCursorPosition);
+    }
+
+    public native void nativeCommitText(String text, int newCursorPosition);
+
+    public native void nativeSetComposingText(String text, int newCursorPosition);
+
+}
+

+ 1 - 1
Source/ThirdParty/SDL/CMakeLists.txt

@@ -37,7 +37,7 @@ elseif (APPLE)
     )
 elseif (ANDROID)
     file (GLOB SYS_C_FILES
-        src/audio/android/*.c src/core/android/*.cpp src/joystick/android/*.c src/loadso/dlopen/*.c
+        src/audio/android/*.c src/core/android/*.c src/joystick/android/*.c src/loadso/dlopen/*.c src/main/android/*.c
         src/thread/pthread/*.c src/timer/unix/*.c src/video/android/*.c src/haptic/dummy/*.c
     )
 else ()

+ 23 - 42
Source/ThirdParty/SDL/CREDITS.txt

@@ -5,64 +5,45 @@ Thanks to everyone who made this possible, including:
 * Cliff Matthews, for giving me a reason to start this project. :)
  -- Executor rocks!  *grin*
 
-* The Linux Fund, C Magazine, Educational Technology Resources Inc.,
-  Gareth Noyce, Jesse Pavel, Keith Kitchin, Jeremy Horvath, Thomas Nicholson,
-  Hans-Peter Gygax, the Eternal Lands Development Team, Lars Brubaker,
-  and Phoenix Kokido for financial contributions
-
-* Edgar "bobbens" Simo for his force feedback API development during the
-  Google Summer of Code 2008
-
-* Aaron Wishnick for his work on audio resampling and pitch shifting during
-  the Google Summer of Code 2008
-
-* Holmes Futrell for port of SDL to the iPhone and iPod Touch during the
-  Google Summer of Code 2008
-
-* Szymon "Wilku" Wilczek for adding support for multiple mice and tablets
-  during the Google Summer of Code 2008
+* Ryan Gordon for helping everybody out and keeping the dream alive. :)
 
-* Marty Leisner, Andrew, Will, Edgar Simo, Donny Viszneki, Andrea Mazzoleni,
-  Dmytro Bogovych, and Couriersud for helping find SDL 1.3 bugs in the great
-  SDL Bug Hunt of January 2009!
+* Gabriel Jacobo for his work on the Android port and generally helping out all around.
+ 
+* Philipp Wiesemann for his attention to detail reviewing the entire SDL code base and proposes patches.
 
-* Donny Viszneki for helping fix SDL 1.3 bugs in the great SDL Bug Hunt of
-  January 2009!
+* Andreas Schiffler for his dedication to unit tests, Visual Studio projects, and managing the Google Summer of Code.
 
-* Luke Benstead for OpenGL 3.0 support
+* Mike Sartain for incorporating SDL into Team Fortress 2 and cheering me on at Valve.
 
-* Gaëtan de Menten for writing the PHP and SQL behind the SDL website
+* Alfred Reynolds for the game controller API and general (in)sanity
 
-* Tim Jones for the new look of the SDL website
+* Jørgen Tjernø for numerous magical Mac OS X fixes.
 
-* Ryan Gordon for helping everybody out and keeping the dream alive. :)
+* Pierre-Loup Griffais for his deep knowledge of OpenGL drivers.
+ 
+* Sheena Smith for many months of great work on the SDL wiki creating the API documentation and style guides.
 
-* Mattias Engdegård, for help with the Solaris port and lots of other help
+* Paul Hunkin for his port of SDL to Android during the Google Summer of Code 2010.
 
-* Eric Wing, Max Horn, and Darrell Walisser for unflagging work on the Mac OS X port
+* Eli Gottlieb for his work on shaped windows during the Google Summer of Code 2010.
 
-* David Carré, for the Pandora port
+* Jim Grandpre for his work on multi-touch and gesture recognition during
+  the Google Summer of Code 2010.
 
-* Couriersud for the DirectFB driver
+* Edgar "bobbens" Simo for his force feedback API development during the
+  Google Summer of Code 2008.
 
-* Jon Atkins for SDL_image, SDL_mixer and SDL_net documentation
+* Aaron Wishnick for his work on audio resampling and pitch shifting during
+  the Google Summer of Code 2008.
 
-* Arne Claus, for the 2004 winning SDL logo,
-  and Shandy Brown, Jac, Alex Lyman, Mikkel Gjoel, #Guy, Jonas Hartmann,
-  Daniel Liljeberg,  Ronald Sowa, DocD, Pekka Jaervinen, Patrick Avella,
-  Erkki Kontilla, Levon Gavalian, Hal Emerich, David Wiktorsson,
-  S. Schury and F. Hufsky, Ciska de Ruyver, Shredweat, Tyler Montbriand,
-  Martin Andersson, Merlyn Wysard, Fernando Ibanez, David Miller,
-  Andre Bommele, lovesby.com, Francisco Camenforte Torres, and David Igreja
-  for other logo entries.
+* Holmes Futrell for his port of SDL to the iPhone and iPod Touch during the
+  Google Summer of Code 2008.
 
-* Bob Pendleton and David Olofson for being long time contributors to
-  the SDL mailing list.
+* Jon Atkins for SDL_image, SDL_mixer and SDL_net documentation.
 
 * Everybody at Loki Software, Inc. for their great contributions!
 
- And a big hand to everyone else who gave me appreciation, advice,
- and suggestions, especially the good folks on the SDL mailing list.
+ And a big hand to everyone else who has contributed over the years.
 
 THANKS! :)
 

+ 11 - 12
Source/ThirdParty/SDL/README.txt

@@ -8,18 +8,17 @@
 ---
 http://www.libsdl.org/
 
-This is the Simple DirectMedia Layer, a general API that provides low
-level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL,
-and 2D framebuffer across multiple platforms.
-
-The current version supports Windows, Mac OS X, Linux, FreeBSD,
-NetBSD, OpenBSD, BSD/OS, Solaris, iOS, and Android. The code contains
-support for other operating systems but those are not officially supported.
-
-SDL is written in C, but works with C++ natively, and has bindings to
-several other languages, including Ada, C#, Eiffel, Erlang, Euphoria,
-Go, Guile, Haskell, Java, Lisp, Lua, ML, Objective C, Pascal, Perl, PHP,
-Pike, Pliant, Python, Ruby, and Smalltalk.
+Simple DirectMedia Layer is a cross-platform development library designed
+to provide low level access to audio, keyboard, mouse, joystick, and graphics
+hardware via OpenGL and Direct3D. It is used by video playback software,
+emulators, and popular games including Valve's award winning catalog
+and many Humble Bundle games.
+
+SDL officially supports Windows, Mac OS X, Linux, iOS, and Android.
+Support for other platforms may be found in the source code.
+
+SDL is written in C, works natively with C++, and there are bindings 
+available for several other languages, including C# and Python.
 
 This library is distributed under the zlib license, which can be found
 in the file "COPYING.txt".

+ 6 - 5
Source/ThirdParty/SDL/include/SDL.h

@@ -106,13 +106,14 @@ extern "C" {
 /*@{*/
 #define SDL_INIT_TIMER          0x00000001
 #define SDL_INIT_AUDIO          0x00000010
-#define SDL_INIT_VIDEO          0x00000020
-#define SDL_INIT_JOYSTICK       0x00000200
+#define SDL_INIT_VIDEO          0x00000020  /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
+#define SDL_INIT_JOYSTICK       0x00000200  /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
 #define SDL_INIT_HAPTIC         0x00001000
-#define SDL_INIT_GAMECONTROLLER 0x00002000      /**< turn on game controller also implicitly does JOYSTICK */
-#define SDL_INIT_NOPARACHUTE    0x00100000      /**< Don't catch fatal signals */
+#define SDL_INIT_GAMECONTROLLER 0x00002000  /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
+#define SDL_INIT_EVENTS         0x00004000
+#define SDL_INIT_NOPARACHUTE    0x00100000  /**< Don't catch fatal signals */
 #define SDL_INIT_EVERYTHING ( \
-                SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | \
+                SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
                 SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \
             )
 /*@}*/

+ 47 - 0
Source/ThirdParty/SDL/include/SDL_atomic.h

@@ -45,6 +45,7 @@
  *
  * There's also lots of good information here:
  * http://www.1024cores.net/home/lock-free-algorithms
+ * http://preshing.com/
  *
  * These operations may or may not actually be implemented using
  * processor specific atomic operations. When possible they are
@@ -135,6 +136,52 @@ void _ReadWriteBarrier(void);
 { SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); }
 #endif
 
+/**
+ * Memory barriers are designed to prevent reads and writes from being
+ * reordered by the compiler and being seen out of order on multi-core CPUs.
+ *
+ * A typical pattern would be for thread A to write some data and a flag,
+ * and for thread B to read the flag and get the data. In this case you
+ * would insert a release barrier between writing the data and the flag,
+ * guaranteeing that the data write completes no later than the flag is
+ * written, and you would insert an acquire barrier between reading the
+ * flag and reading the data, to ensure that all the reads associated
+ * with the flag have completed.
+ *
+ * In this pattern you should always see a release barrier paired with
+ * an acquire barrier and you should gate the data reads/writes with a
+ * single flag variable.
+ *
+ * For more information on these semantics, take a look at the blog post:
+ * http://preshing.com/20120913/acquire-and-release-semantics
+ */
+#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+#define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("lwsync" : : : "memory")
+#define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("lwsync" : : : "memory")
+#elif defined(__GNUC__) && defined(__arm__)
+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
+#define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("dmb ish" : : : "memory")
+#define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("dmb ish" : : : "memory")
+#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
+#ifdef __thumb__
+/* The mcr instruction isn't available in thumb mode, use real functions */
+extern DECLSPEC void SDLCALL SDL_MemoryBarrierRelease();
+extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquire();
+#else
+#define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#endif /* __thumb__ */
+#else
+#define SDL_MemoryBarrierRelease()   __asm__ __volatile__ ("" : : : "memory")
+#define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("" : : : "memory")
+#endif /* __GNUC__ && __arm__ */
+#else
+/* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */
+#define SDL_MemoryBarrierRelease()  SDL_CompilerBarrier()
+#define SDL_MemoryBarrierAcquire()  SDL_CompilerBarrier()
+#endif
+
+
 /* Platform specific optimized versions of the atomic functions,
  * you can disable these by defining SDL_DISABLE_ATOMIC_INLINE
  */

+ 12 - 7
Source/ThirdParty/SDL/include/SDL_audio.h

@@ -183,6 +183,17 @@ typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt,
 /**
  *  A structure to hold a set of audio conversion filters and buffers.
  */
+#ifdef __GNUC__
+/* This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't
+   pad it out to 88 bytes to guarantee ABI compatibility between compilers.
+   vvv
+   The next time we rev the ABI, make sure to size the ints and add padding.
+*/
+#define SDL_AUDIOCVT_PACKED __attribute__((packed))
+#else
+#define SDL_AUDIOCVT_PACKED
+#endif
+/* */
 typedef struct SDL_AudioCVT
 {
     int needed;                 /**< Set to 1 if conversion possible */
@@ -196,7 +207,7 @@ typedef struct SDL_AudioCVT
     double len_ratio;           /**< Given len, final size is len*len_ratio */
     SDL_AudioFilter filters[10];        /**< Filter list */
     int filter_index;           /**< Current audio conversion function */
-} SDL_AudioCVT;
+} SDL_AUDIOCVT_PACKED SDL_AudioCVT;
 
 
 /* Function prototypes */
@@ -484,12 +495,6 @@ extern DECLSPEC void SDLCALL SDL_UnlockAudioDevice(SDL_AudioDeviceID dev);
 extern DECLSPEC void SDLCALL SDL_CloseAudio(void);
 extern DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID dev);
 
-/**
- * \return 1 if audio device is still functioning, zero if not, -1 on error.
- */
-extern DECLSPEC int SDLCALL SDL_AudioDeviceConnected(SDL_AudioDeviceID dev);
-
-
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
 }

+ 11 - 4
Source/ThirdParty/SDL/include/SDL_bits.h

@@ -45,15 +45,18 @@ extern "C" {
  *  with 0. This operation can also be stated as "count leading zeroes" and
  *  "log base 2".
  *
- *  \return Index of the most significant bit.
+ *  \return Index of the most significant bit, or -1 if the value is 0.
  */
-SDL_FORCE_INLINE Sint8
+SDL_FORCE_INLINE int
 SDL_MostSignificantBitIndex32(Uint32 x)
 {
 #if defined(__GNUC__) && __GNUC__ >= 4
     /* Count Leading Zeroes builtin in GCC.
      * http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Other-Builtins.html
      */
+    if (x == 0) {
+        return -1;
+    }
     return 31 - __builtin_clz(x);
 #else
     /* Based off of Bit Twiddling Hacks by Sean Eron Anderson
@@ -61,11 +64,15 @@ SDL_MostSignificantBitIndex32(Uint32 x)
      * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
      */
     const Uint32 b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
-    const Uint8  S[] = {1, 2, 4, 8, 16};
+    const int    S[] = {1, 2, 4, 8, 16};
 
-    Uint8 msbIndex = 0;
+    int msbIndex = 0;
     int i;
 
+    if (x == 0) {
+        return -1;
+    }
+
     for (i = 4; i >= 0; i--)
     {
         if (x & b[i])

+ 11 - 4
Source/ThirdParty/SDL/include/SDL_blendmode.h

@@ -39,10 +39,17 @@ extern "C" {
  */
 typedef enum
 {
-    SDL_BLENDMODE_NONE = 0x00000000,     /**< No blending */
-    SDL_BLENDMODE_BLEND = 0x00000001,    /**< dst = (src * A) + (dst * (1-A)) */
-    SDL_BLENDMODE_ADD = 0x00000002,      /**< dst = (src * A) + dst */
-    SDL_BLENDMODE_MOD = 0x00000004       /**< dst = src * dst */
+    SDL_BLENDMODE_NONE = 0x00000000,     /**< no blending
+                                              dstRGBA = srcRGBA */
+    SDL_BLENDMODE_BLEND = 0x00000001,    /**< alpha blending
+                                              dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
+                                              dstA = srcA + (dstA * (1-srcA)) */
+    SDL_BLENDMODE_ADD = 0x00000002,      /**< additive blending
+                                              dstRGB = (srcRGB * srcA) + dstRGB
+                                              dstA = dstA */
+    SDL_BLENDMODE_MOD = 0x00000004       /**< color modulate
+                                              dstRGB = srcRGB * dstRGB
+                                              dstA = dstA */
 } SDL_BlendMode;
 
 /* Ends C function definitions when using C++ */

+ 5 - 5
Source/ThirdParty/SDL/include/SDL_config.h

@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2011 Sam Lantinga <[email protected]>
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -30,17 +30,17 @@
  *  \file SDL_config.h
  */
 
-// Urho3D: choose from prebuilt config files on all OSes
+// Urho3D: choose from prebuilt config files on all platforms
 #if defined(__WIN32__)
 #include "SDL_config_windows.h"
 #elif defined(__MACOSX__)
 #include "SDL_config_macosx.h"
-#elif defined(__IPHONEOS__) 
+#elif defined(__IPHONEOS__)
 #include "SDL_config_iphoneos.h"
 #elif defined(__ANDROID__)
 #include "SDL_config_android.h"
-#elif defined(__NINTENDODS__)
-#include "SDL_config_nintendods.h"
+#elif defined(__PSP__)
+#include "SDL_config_psp.h"
 #else
 #include "SDL_config_linux.h"
 #endif /* platform config */

+ 2 - 4
Source/ThirdParty/SDL/include/SDL_config_android.h

@@ -19,8 +19,6 @@
   3. This notice may not be removed or altered from any source distribution.
 */
 
-// Modified by Lasse Oorni for Urho3D
-
 #ifndef _SDL_config_android_h
 #define _SDL_config_android_h
 
@@ -34,6 +32,8 @@
 
 #include <stdarg.h>
 
+#define HAVE_GCC_ATOMICS    1
+
 #define HAVE_ALLOCA_H       1
 #define HAVE_SYS_TYPES_H    1
 #define HAVE_STDIO_H    1
@@ -103,8 +103,6 @@
 #define HAVE_SETJMP 1
 #define HAVE_NANOSLEEP  1
 #define HAVE_SYSCONF    1
-// Urho3D: enable use of GCC atomics
-#define HAVE_GCC_ATOMICS 1
 
 #define SIZEOF_VOIDP 4
 

+ 0 - 3
Source/ThirdParty/SDL/include/SDL_config_macosx.h

@@ -36,10 +36,7 @@
 #endif
 
 /* Useful headers */
-/* If we specified an SDK or have a post-PowerPC chip, then alloca.h exists. */
-#if ( (MAC_OS_X_VERSION_MIN_REQUIRED >= 1030) || (!defined(__POWERPC__)) )
 #define HAVE_ALLOCA_H       1
-#endif
 #define HAVE_SYS_TYPES_H    1
 #define HAVE_STDIO_H    1
 #define STDC_HEADERS    1

+ 2 - 3
Source/ThirdParty/SDL/include/SDL_config_windows.h

@@ -78,9 +78,8 @@ typedef unsigned int uintptr_t;
 # define SIZEOF_VOIDP 4
 #endif
 
-/* Enabled for SDL 1.2 (binary compatibility) */
-// Urho3D: enable libc
-#define HAVE_LIBC     1
+/* This is disabled by default to avoid C runtime dependencies and manifest requirements */
+//#define HAVE_LIBC     1
 #ifdef HAVE_LIBC
 /* Useful headers */
 #define HAVE_STDIO_H 1

+ 4 - 0
Source/ThirdParty/SDL/include/SDL_gamecontroller.h

@@ -44,6 +44,10 @@ extern "C" {
  *  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 */

+ 42 - 12
Source/ThirdParty/SDL/include/SDL_haptic.h

@@ -166,13 +166,18 @@ typedef struct _SDL_Haptic SDL_Haptic;
 #define SDL_HAPTIC_SINE       (1<<1)
 
 /**
- *  \brief Square wave effect supported.
+ *  \brief Left/Right effect supported.
  *
- *  Periodic haptic effect that simulates square waves.
+ *  Haptic effect for direct control over high/low frequency motors.
  *
- *  \sa SDL_HapticPeriodic
+ *  \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.
  */
-#define SDL_HAPTIC_SQUARE     (1<<2)
+#define SDL_HAPTIC_LEFTRIGHT     (1<<2)
+
+/* !!! FIXME: put this back when we have more bits in 2.1 */
+/*#define SDL_HAPTIC_SQUARE     (1<<2)*/
 
 /**
  *  \brief Triangle wave effect supported.
@@ -478,7 +483,7 @@ typedef struct SDL_HapticConstant
  *
  *  The struct handles the following effects:
  *   - ::SDL_HAPTIC_SINE
- *   - ::SDL_HAPTIC_SQUARE
+ *   - ::SDL_HAPTIC_LEFTRIGHT
  *   - ::SDL_HAPTIC_TRIANGLE
  *   - ::SDL_HAPTIC_SAWTOOTHUP
  *   - ::SDL_HAPTIC_SAWTOOTHDOWN
@@ -524,7 +529,7 @@ typedef struct SDL_HapticConstant
     \endverbatim
  *
  *  \sa SDL_HAPTIC_SINE
- *  \sa SDL_HAPTIC_SQUARE
+ *  \sa SDL_HAPTIC_LEFTRIGHT
  *  \sa SDL_HAPTIC_TRIANGLE
  *  \sa SDL_HAPTIC_SAWTOOTHUP
  *  \sa SDL_HAPTIC_SAWTOOTHDOWN
@@ -533,7 +538,7 @@ typedef struct SDL_HapticConstant
 typedef struct SDL_HapticPeriodic
 {
     /* Header */
-    Uint16 type;        /**< ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_SQUARE,
+    Uint16 type;        /**< ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_LEFTRIGHT,
                              ::SDL_HAPTIC_TRIANGLE, ::SDL_HAPTIC_SAWTOOTHUP or
                              ::SDL_HAPTIC_SAWTOOTHDOWN */
     SDL_HapticDirection direction;  /**< Direction of the effect. */
@@ -645,6 +650,31 @@ typedef struct SDL_HapticRamp
     Uint16 fade_level;      /**< Level at the end of the fade. */
 } SDL_HapticRamp;
 
+/**
+ * \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
+ */
+typedef struct SDL_HapticLeftRight
+{
+    /* Header */
+    Uint16 type;            /**< ::SDL_HAPTIC_LEFTRIGHT */
+
+    /* Replay */
+    Uint32 length;          /**< Duration of the effect. */
+
+    /* Rumble */
+    Uint16 large_magnitude; /**< Control of the large controller motor. */
+    Uint16 small_magnitude; /**< Control of the small controller motor. */
+} SDL_HapticLeftRight;
+
 /**
  *  \brief A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect.
  *
@@ -751,6 +781,7 @@ typedef struct SDL_HapticCustom
  *  \sa SDL_HapticPeriodic
  *  \sa SDL_HapticCondition
  *  \sa SDL_HapticRamp
+ *  \sa SDL_HapticLeftRight
  *  \sa SDL_HapticCustom
  */
 typedef union SDL_HapticEffect
@@ -761,6 +792,7 @@ typedef union SDL_HapticEffect
     SDL_HapticPeriodic periodic;    /**< Periodic effect. */
     SDL_HapticCondition condition;  /**< Condition effect. */
     SDL_HapticRamp ramp;            /**< Ramp effect. */
+    SDL_HapticLeftRight leftright;  /**< Left/Right effect. */
     SDL_HapticCustom custom;        /**< Custom effect. */
 } SDL_HapticEffect;
 
@@ -926,7 +958,7 @@ extern DECLSPEC int SDLCALL SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic);
  *
  *  Example:
  *  \code
- *  if (SDL_HapticQueryEffects(haptic) & SDL_HAPTIC_CONSTANT) {
+ *  if (SDL_HapticQuery(haptic) & SDL_HAPTIC_CONSTANT) {
  *      printf("We have constant haptic effect!");
  *  }
  *  \endcode
@@ -986,7 +1018,7 @@ extern DECLSPEC int SDLCALL SDL_HapticNewEffect(SDL_Haptic * haptic,
  *  \param haptic Haptic device that has the effect.
  *  \param effect Effect to update.
  *  \param data New effect properties to use.
- *  \return The id of the effect on success or -1 on error.
+ *  \return 0 on success or -1 on error.
  *
  *  \sa SDL_HapticNewEffect
  *  \sa SDL_HapticRunEffect
@@ -1132,7 +1164,7 @@ extern DECLSPEC int SDLCALL SDL_HapticUnpause(SDL_Haptic * haptic);
 extern DECLSPEC int SDLCALL SDL_HapticStopAll(SDL_Haptic * haptic);
 
 /**
- *  \brief Checks to see if rumble is supported on a haptic device..
+ *  \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.
@@ -1182,8 +1214,6 @@ extern DECLSPEC int SDLCALL SDL_HapticRumblePlay(SDL_Haptic * haptic, float stre
  */
 extern DECLSPEC int SDLCALL SDL_HapticRumbleStop(SDL_Haptic * haptic);
 
-
-
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
 }

+ 43 - 4
Source/ThirdParty/SDL/include/SDL_hints.h

@@ -100,7 +100,7 @@ extern "C" {
  *  This variable can be set to the following values:
  *    "0" or "nearest" - Nearest pixel sampling
  *    "1" or "linear"  - Linear filtering (supported by OpenGL and Direct3D)
- *    "2" or "best"    - Anisotropic filtering (supported by Direct3D)
+ *    "2" or "best"    - Currently this is the same as "linear"
  *
  *  By default nearest pixel sampling is used
  */
@@ -218,13 +218,13 @@ extern "C" {
 /**
  *  \brief  A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background.
  *
- * The default value is "0".
- *
  *  The variable can be set to the following values:
  *    "0"       - Disable joystick & gamecontroller input events when the
  *                application is in the background.
  *    "1"       - Enable joystick & gamecontroller input events when the
  *                application is in the backgroumd.
+ *
+ *  The default value is "0".  This hint may be set at any time.
  */
 #define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"
 
@@ -240,6 +240,23 @@ extern "C" {
 #define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST"
 
 
+/**
+ *  \brief A variable that controls the timer resolution, in milliseconds.
+ *
+ *  The higher resolution the timer, the more frequently the CPU services
+ *  timer interrupts, and the more precise delays are, but this takes up
+ *  power and CPU time.  This hint is only used on Windows 7 and earlier.
+ *
+ *  See this blog post for more information:
+ *  http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/
+ *
+ *  If this variable is set to "0", the system timer resolution is not set.
+ *
+ *  The default value is "1". This hint may be set at any time.
+ */
+#define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION"
+
+
 
 /**
  *  \brief  An enumeration of hint priorities
@@ -273,7 +290,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name,
 extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name,
                                              const char *value);
 
-
 /**
  *  \brief Get a hint
  *
@@ -281,6 +297,29 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name,
  */
 extern DECLSPEC const char * SDLCALL SDL_GetHint(const char *name);
 
+/**
+ *  \brief Add a function to watch a particular hint
+ *
+ *  \param name The hint to watch
+ *  \param callback The function to call when the hint value changes
+ *  \param userdata A pointer to pass to the callback function
+ */
+typedef void (*SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue);
+extern DECLSPEC void SDLCALL SDL_AddHintCallback(const char *name,
+                                                 SDL_HintCallback callback,
+                                                 void *userdata);
+
+/**
+ *  \brief Remove a function watching a particular hint
+ *
+ *  \param name The hint being watched
+ *  \param callback The function being called when the hint value changes
+ *  \param userdata A pointer being passed to the callback function
+ */
+extern DECLSPEC void SDLCALL SDL_DelHintCallback(const char *name,
+                                                 SDL_HintCallback callback,
+                                                 void *userdata);
+
 /**
  *  \brief  Clear all hints
  *

+ 4 - 0
Source/ThirdParty/SDL/include/SDL_joystick.h

@@ -54,6 +54,10 @@ extern "C" {
  *  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 */

+ 7 - 1
Source/ThirdParty/SDL/include/SDL_platform.h

@@ -83,6 +83,12 @@
 /* if not compiling for iPhone */
 #undef __MACOSX__
 #define __MACOSX__  1
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+# error SDL for Mac OS X only supports deploying on 10.5 and above.
+#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1050 */
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
+# error SDL for Mac OS X must be built with a 10.6 SDK or above.
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1060 */
 #endif /* TARGET_OS_IPHONE */
 #endif /* defined(__APPLE__) */
 
@@ -114,7 +120,7 @@
 #undef __SOLARIS__
 #define __SOLARIS__ 1
 #endif
-#if defined(WIN32) || defined(_WIN32)
+#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
 #undef __WIN32__
 #define __WIN32__   1
 #endif

+ 4 - 1
Source/ThirdParty/SDL/include/SDL_render.h

@@ -37,9 +37,12 @@
  *  them, and may also be stretched with linear interpolation.
  *
  *  This API is designed to accelerate simple 2D operations. You may
- *  want more functionality such as rotation and particle effects and
+ *  want more functionality such as polygons and particle effects and
  *  in that case you should use SDL's OpenGL/Direct3D support or one
  *  of the many good 3D engines.
+ *
+ *  These functions must be called from the main thread.
+ *  See this bug for details: http://bugzilla.libsdl.org/show_bug.cgi?id=1995
  */
 
 #ifndef _SDL_render_h

+ 2 - 2
Source/ThirdParty/SDL/include/SDL_revision.h

@@ -1,2 +1,2 @@
-#define SDL_REVISION "hg-0:aaaaaaaaaaah"
-#define SDL_REVISION_NUMBER 0
+#define SDL_REVISION "hg-7633:d6a8fa507a45"
+#define SDL_REVISION_NUMBER 7633

+ 1 - 1
Source/ThirdParty/SDL/include/SDL_shape.h

@@ -55,7 +55,7 @@ extern "C" {
  *  \param h     The height of the window.
  *  \param flags The flags for the window, a mask of SDL_WINDOW_BORDERLESS with any of the following:
  *               ::SDL_WINDOW_OPENGL,     ::SDL_WINDOW_INPUT_GRABBED,
- *               ::SDL_WINDOW_SHOWN,      ::SDL_WINDOW_RESIZABLE,
+ *               ::SDL_WINDOW_HIDDEN,     ::SDL_WINDOW_RESIZABLE,
  *               ::SDL_WINDOW_MAXIMIZED,  ::SDL_WINDOW_MINIMIZED,
  *       ::SDL_WINDOW_BORDERLESS is always set, and ::SDL_WINDOW_FULLSCREEN is always unset.
  *

+ 13 - 456
Source/ThirdParty/SDL/include/SDL_stdinc.h

@@ -19,8 +19,6 @@
   3. This notice may not be removed or altered from any source distribution.
 */
 
-// Modified by Lasse Oorni for Urho3D
-
 /**
  *  \file SDL_stdinc.h
  *
@@ -229,76 +227,17 @@ char *alloca();
 #define SDL_stack_free(data)            SDL_free(data)
 #endif
 
-
-/* SDL stdinc inline functions:
-
-   The theory here is that by default we forcibly inline what we can, and your
-   app will use the inline version by default. However we expose a non-inline
-   version too, so the symbol is always available in the library even if your app
-   bypassed the inline version. The SDL_*_inline versions aren't guaranteed to
-   exist, so never call them directly; use SDL_* instead, and trust the system
-   to give you the right thing.
-
-   The benefit here is that you can dlsym() these functions, which you
-   couldn't if you had macros, you can link against a foreign build of SDL
-   even if you configured differently, and you can drop the unconfigured SDL
-   headers into a project without #defining HAVE_MALLOC (etc) and still link.
-
-   If you want to disable the inline functions and just use SDL's functions,
-   you can define SDL_STDINC_NO_INLINES before including this file.
-*/
-
 extern DECLSPEC void *SDLCALL SDL_malloc(size_t size);
-#if defined(HAVE_MALLOC) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE void *SDL_malloc_inline(size_t size) { return malloc(size); }
-#define SDL_malloc SDL_malloc_inline
-#endif
-
 extern DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size);
-#if defined(HAVE_CALLOC) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE void *SDL_calloc_inline(size_t nmemb, size_t size) { return calloc(nmemb, size); }
-#define SDL_calloc SDL_calloc_inline
-#endif
-
 extern DECLSPEC void *SDLCALL SDL_realloc(void *mem, size_t size);
-#if defined(HAVE_REALLOC) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE void *SDL_realloc_inline(void *mem, size_t size) { return realloc(mem, size); }
-#define SDL_realloc SDL_realloc_inline
-#endif
-
 extern DECLSPEC void SDLCALL SDL_free(void *mem);
-#if defined(HAVE_FREE) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE void SDL_free_inline(void *mem) { free(mem); }
-#define SDL_free SDL_free_inline
-#endif
 
 extern DECLSPEC char *SDLCALL SDL_getenv(const char *name);
-#if defined(HAVE_GETENV) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE char *SDL_getenv_inline(const char *name) { return getenv(name); }
-#define SDL_getenv SDL_getenv_inline
-#endif
-
 extern DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value, int overwrite);
-#if defined(HAVE_SETENV) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE int SDL_setenv_inline(const char *name, const char *value, int overwrite) { return setenv(name, value, overwrite); }
-#define SDL_setenv SDL_setenv_inline
-#endif
 
 extern DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, int (*compare) (const void *, const void *));
-#if defined(HAVE_QSORT) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE void SDL_qsort_inline(void *base, size_t nmemb, size_t size, int (*compare) (const void *, const void *)) { qsort(base, nmemb, size, compare); }
-#define SDL_qsort SDL_qsort_inline
-#endif
 
 extern DECLSPEC int SDLCALL SDL_abs(int x);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_ABS
-SDL_FORCE_INLINE int SDL_abs_inline(int x) { return abs(x); }
-#else
-SDL_FORCE_INLINE int SDL_abs_inline(int x) { return ((x) < 0 ? -(x) : (x)); }
-#endif
-#define SDL_abs SDL_abs_inline
-#endif /* !SDL_STDINC_NO_INLINES */
 
 /* !!! FIXME: these have side effects. You probably shouldn't use them. */
 /* !!! FIXME: Maybe we do forceinline functions of SDL_mini, SDL_minf, etc? */
@@ -309,35 +248,14 @@ extern DECLSPEC int SDLCALL SDL_isdigit(int x);
 extern DECLSPEC int SDLCALL SDL_isspace(int x);
 extern DECLSPEC int SDLCALL SDL_toupper(int x);
 extern DECLSPEC int SDLCALL SDL_tolower(int x);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_CTYPE_H
-SDL_FORCE_INLINE int SDL_isdigit_inline(int x) { return isdigit(x); }
-SDL_FORCE_INLINE int SDL_isspace_inline(int x) { return isspace(x); }
-SDL_FORCE_INLINE int SDL_toupper_inline(int x) { return toupper(x); }
-SDL_FORCE_INLINE int SDL_tolower_inline(int x) { return tolower(x); }
-#else
-SDL_FORCE_INLINE int SDL_isdigit_inline(int x) { return ((x) >= '0') && ((x) <= '9'); }
-SDL_FORCE_INLINE int SDL_isspace_inline(int x) { return ((x) == ' ') || ((x) == '\t') || ((x) == '\r') || ((x) == '\n'); }
-SDL_FORCE_INLINE int SDL_toupper_inline(int x) { return ((x) >= 'a') && ((x) <= 'z') ? ('A'+((x)-'a')) : (x); }
-SDL_FORCE_INLINE int SDL_tolower_inline(int x) { return ((x) >= 'A') && ((x) <= 'Z') ? ('a'+((x)-'A')) : (x); }
-#endif
-#define SDL_isdigit SDL_isdigit_inline
-#define SDL_isspace SDL_isspace_inline
-#define SDL_toupper SDL_toupper_inline
-#define SDL_tolower SDL_tolower_inline
-#endif /* !SDL_STDINC_NO_INLINES */
 
 extern DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len);
-#if defined(HAVE_MEMSET) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE void *SDL_memset_inline(void *dst, int c, size_t len) { return memset(dst, c, len); }
-#define SDL_memset SDL_memset_inline
-#endif
 
 #define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x)))
 #define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x)))
 
-/* !!! FIXME: does this _really_ beat memset() on any modern platform? */
-SDL_FORCE_INLINE void SDL_memset4(void *dst, int val, size_t len)
+/* Note that memset() is a byte assignment and this is a 32-bit assignment, so they're not directly equivalent. */
+SDL_FORCE_INLINE void SDL_memset4(void *dst, int val, size_t dwords)
 {
 #if defined(__GNUC__) && defined(i386)
     int u0, u1, u2;
@@ -345,17 +263,16 @@ SDL_FORCE_INLINE void SDL_memset4(void *dst, int val, size_t len)
         "cld \n\t"
         "rep ; stosl \n\t"
         : "=&D" (u0), "=&a" (u1), "=&c" (u2)
-        : "0" (dst), "1" (val), "2" (SDL_static_cast(Uint32, len))
+        : "0" (dst), "1" (val), "2" (SDL_static_cast(Uint32, dwords))
         : "memory"
     );
-/* !!! FIXME: amd64? */
 #else
-    size_t _n = (len + 3) / 4;
+    size_t _n = (dwords + 3) / 4;
     Uint32 *_p = SDL_static_cast(Uint32 *, dst);
     Uint32 _val = (val);
-    if (len == 0)
+    if (dwords == 0)
         return;
-    switch (len % 4)
+    switch (dwords % 4)
     {
         case 0: do {    *_p++ = _val;
         case 3:         *_p++ = _val;
@@ -368,327 +285,54 @@ SDL_FORCE_INLINE void SDL_memset4(void *dst, int val, size_t len)
 
 
 extern DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len);
-#if !defined(SDL_STDINC_NO_INLINES)
-#if defined(__MACOSX__) && defined(HAVE_MEMCPY)
-SDL_FORCE_INLINE void *SDL_memcpy_inline(void *dst, const void *src, size_t len)
-{
-    /* We can count on memcpy existing on Mac OS X and being well-tuned. */
-    return memcpy(dst, src, len);
-}
-#define SDL_memcpy SDL_memcpy_inline
-#elif defined(__GNUC__) && defined(i386) && !defined(__WIN32__)
-SDL_FORCE_INLINE void *SDL_memcpy_inline(void *dst, const void *src, size_t len)
-{
-    /* !!! FIXME: does this _really_ beat memcpy() on any modern platform? */
-    /* !!! FIXME: shouldn't we just force the inputs to ecx/edi/esi instead of this tapdance with outputs? */
-    /* !!! FIXME: amd64? */
-    int u0, u1, u2;
-    __asm__ __volatile__ (
-        "cld \n\t"
-        "rep ; movsl \n\t"
-        "testb $2,%b4 \n\t"
-        "je 1f \n\t"
-        "movsw \n"
-        "1:\ttestb $1,%b4 \n\t"
-        "je 2f \n\t"
-        "movsb \n"
-        "2:"
-        : "=&c" (u0), "=&D" (u1), "=&S" (u2)
-        : "0" (SDL_static_cast(unsigned, len)/4), "q" (len), "1" (dst), "2" (src)
-        : "memory"
-    );
-    return dst;
-}
-#define SDL_memcpy SDL_memcpy_inline
-#elif defined(HAVE_MEMCPY)
-SDL_FORCE_INLINE void *SDL_memcpy_inline(void *dst, const void *src, size_t len)
-{
-    return memcpy(dst, src, len);
-}
-#define SDL_memcpy SDL_memcpy_inline
-#elif defined(HAVE_BCOPY)  /* !!! FIXME: is there _really_ ever a time where you have bcopy and not memcpy? */
-SDL_FORCE_INLINE void *SDL_memcpy_inline(void *dst, const void *src, size_t len)
-{
-    bcopy(src, dst, len);
-    return dst;
-}
-#define SDL_memcpy SDL_memcpy_inline
-#endif
-#endif /* !SDL_STDINC_NO_INLINES */
-
 
 SDL_FORCE_INLINE void *SDL_memcpy4(void *dst, const void *src, size_t dwords)
 {
-#if defined(__GNUC__) && defined(i386)
-    /* !!! FIXME: does this _really_ beat memcpy() on any modern platform? */
-    /* !!! FIXME: shouldn't we just force the inputs to ecx/edi/esi instead of this tapdance with outputs? */
-    int ecx, edi, esi;
-    __asm__ __volatile__ (
-        "cld \n\t"
-        "rep ; movsl \n\t"
-        : "=&c" (ecx), "=&D" (edi), "=&S" (esi)
-        : "0" (SDL_static_cast(unsigned, dwords)), "1" (dst), "2" (src)
-        : "memory"
-    );
-    return dst;
-#else
     return SDL_memcpy(dst, src, dwords * 4);
-#endif
 }
 
 extern DECLSPEC void *SDLCALL SDL_memmove(void *dst, const void *src, size_t len);
-#if defined(HAVE_MEMMOVE) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE void *SDL_memmove_inline(void *dst, const void *src, size_t len) { return memmove(dst, src, len); }
-#define SDL_memmove SDL_memmove_inline
-#endif
-
 extern DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len);
-#if defined(HAVE_MEMCMP) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE int SDL_memcmp_inline(const void *s1, const void *s2, size_t len) { return memcmp(s1, s2, len); }
-#define SDL_memcmp SDL_memcmp_inline
-#endif
-
-extern DECLSPEC size_t SDLCALL SDL_strlen(const char *str);
-#if defined(HAVE_STRLEN) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE size_t SDL_strlen_inline(const char *str) { return strlen(str); }
-#define SDL_strlen SDL_strlen_inline
-#endif
 
 extern DECLSPEC size_t SDLCALL SDL_wcslen(const wchar_t *wstr);
-#if defined(HAVE_WCSLEN) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE size_t SDL_wcslen_inline(const wchar_t *wstr) { return wcslen(wstr); }
-#define SDL_wcslen SDL_wcslen_inline
-#endif
-
 extern DECLSPEC size_t SDLCALL SDL_wcslcpy(wchar_t *dst, const wchar_t *src, size_t maxlen);
-#if defined(HAVE_WCSLCPY) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE size_t SDL_wcslcpy_inline(wchar_t *dst, const wchar_t *src, size_t maxlen) { return wcslcpy(dst, src, maxlen); }
-#define SDL_wcslcpy SDL_wcslcpy_inline
-#endif
-
 extern DECLSPEC size_t SDLCALL SDL_wcslcat(wchar_t *dst, const wchar_t *src, size_t maxlen);
-#if defined(HAVE_WCSLCAT) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE size_t SDL_wcslcat_inline(wchar_t *dst, const wchar_t *src, size_t maxlen) { return wcslcat(dst, src, maxlen); }
-#define SDL_wcslcat SDL_wcslcat_inline
-#endif
 
+extern DECLSPEC size_t SDLCALL SDL_strlen(const char *str);
 extern DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen);
-#if defined(HAVE_STRLCPY) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE size_t SDL_strlcpy_inline(char *dst, const char *src, size_t maxlen) { return strlcpy(dst, src, maxlen); }
-#define SDL_strlcpy SDL_strlcpy_inline
-#else
-#endif
-
 extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(char *dst, const char *src, size_t dst_bytes);
-
 extern DECLSPEC size_t SDLCALL SDL_strlcat(char *dst, const char *src, size_t maxlen);
-#if defined(HAVE_STRLCAT) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE size_t SDL_strlcat_inline(char *dst, const char *src, size_t maxlen) { return strlcat(dst, src, maxlen); }
-#define SDL_strlcat SDL_strlcat_inline
-#endif
-
 extern DECLSPEC char *SDLCALL SDL_strdup(const char *str);
-#if defined(HAVE_STRDUP) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE char *SDL_strdup_inline(const char *str) { return strdup(str); }
-#define SDL_strdup SDL_strdup_inline
-#endif
-
 extern DECLSPEC char *SDLCALL SDL_strrev(char *str);
-#if defined(HAVE__STRREV) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE char *SDL_strrev_inline(char *str) { return _strrev(str); }
-#define SDL_strrev SDL_strrev_inline
-#endif
-
 extern DECLSPEC char *SDLCALL SDL_strupr(char *str);
-#if defined(HAVE__STRUPR) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE char *SDL_strupr_inline(char *str) { return _strupr(str); }
-#define SDL_strupr SDL_strupr_inline
-#endif
-
 extern DECLSPEC char *SDLCALL SDL_strlwr(char *str);
-#if defined(HAVE__STRLWR) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE char *SDL_strlwr_inline(char *str) { return _strlwr(str); }
-#define SDL_strlwr SDL_strlwr_inline
-#endif
-
 extern DECLSPEC char *SDLCALL SDL_strchr(const char *str, int c);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_STRCHR
-SDL_FORCE_INLINE char *SDL_strchr_inline(const char *str, int c) { return SDL_const_cast(char*,strchr(str, c)); }
-#define SDL_strchr SDL_strchr_inline
-#elif defined(HAVE_INDEX)  /* !!! FIXME: is there anywhere that has this but not strchr? */
-SDL_FORCE_INLINE char *SDL_strchr_inline(const char *str, int c) { return SDL_const_cast(char*,index(str, c)); }
-#define SDL_strchr SDL_strchr_inline
-#endif
-#endif /* !SDL_STDINC_NO_INLINES */
-
 extern DECLSPEC char *SDLCALL SDL_strrchr(const char *str, int c);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_STRRCHR
-SDL_FORCE_INLINE char *SDL_strrchr_inline(const char *str, int c) { return SDL_const_cast(char*,strrchr(str, c)); }
-#define SDL_strrchr SDL_strrchr_inline
-#elif defined(HAVE_RINDEX)  /* !!! FIXME: is there anywhere that has this but not strrchr? */
-SDL_FORCE_INLINE char *SDL_strrchr_inline(const char *str, int c) { return SDL_const_cast(char*,rindex(str, c)); }
-#define SDL_strrchr SDL_strrchr_inline
-#endif
-#endif /* !SDL_STDINC_NO_INLINES */
-
 extern DECLSPEC char *SDLCALL SDL_strstr(const char *haystack, const char *needle);
-#if defined(HAVE_STRSTR) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE char *SDL_strstr_inline(const char *haystack, const char *needle) { return SDL_const_cast(char*,strstr(haystack, needle)); }
-#define SDL_strstr SDL_strstr_inline
-#endif
-
-extern DECLSPEC char *SDLCALL SDL_ltoa(long value, char *str, int radix);
-#if defined(HAVE__LTOA) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE char *SDL_ltoa_inline(long value, char *str, int radix) { return _ltoa(value, str, radix); }
-#define SDL_ltoa SDL_ltoa_inline
-#endif
 
 extern DECLSPEC char *SDLCALL SDL_itoa(int value, char *str, int radix);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_ITOA
-// Urho3D: fix deprecation warning
-SDL_FORCE_INLINE char *SDL_itoa_inline(int value, char *str, int radix) { return _itoa(value, str, radix); }
-#else
-SDL_FORCE_INLINE char *SDL_itoa_inline(int value, char *str, int radix) { return SDL_ltoa((long)value, str, radix); }
-#endif
-#define SDL_itoa SDL_itoa_inline
-#endif /* !SDL_STDINC_NO_INLINES */
-
-extern DECLSPEC char *SDLCALL SDL_ultoa(unsigned long value, char *str, int radix);
-#if defined(HAVE__ULTOA) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE char *SDL_ultoa_inline(unsigned long value, char *str, int radix) { return _ultoa(value, str, radix); }
-#define SDL_ultoa SDL_ultoa_inline
-#endif
-
 extern DECLSPEC char *SDLCALL SDL_uitoa(unsigned int value, char *str, int radix);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE__UITOA
-SDL_FORCE_INLINE char *SDL_uitoa_inline(unsigned int value, char *str, int radix) { return _uitoa(value, str, radix); }
-#else
-SDL_FORCE_INLINE char *SDL_uitoa_inline(unsigned int value, char *str, int radix) { return SDL_ultoa((unsigned long)value, str, radix); }
-#endif
-#define SDL_uitoa SDL_uitoa_inline
-#endif /* !SDL_STDINC_NO_INLINES */
-
-
-extern DECLSPEC long SDLCALL SDL_strtol(const char *str, char **endp, int base);
-#if defined(HAVE_STRTOL) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE long SDL_strtol_inline(const char *str, char **endp, int base) { return strtol(str, endp, base); }
-#define SDL_strtol SDL_strtol_inline
-#endif
-
-extern DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *str, char **endp, int base);
-#if defined(HAVE_STRTOUL) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE unsigned long SDLCALL SDL_strtoul_inline(const char *str, char **endp, int base) { return strtoul(str, endp, base); }
-#define SDL_strtoul SDL_strtoul_inline
-#endif
-
+extern DECLSPEC char *SDLCALL SDL_ltoa(long value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_ultoa(unsigned long value, char *str, int radix);
 extern DECLSPEC char *SDLCALL SDL_lltoa(Sint64 value, char *str, int radix);
-#if defined(HAVE__I64TOA) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE char *SDL_lltoa_inline(Sint64 value, char *str, int radix) { return _i64toa(value, str, radix); }
-#define SDL_lltoa SDL_lltoa_inline
-#endif
-
 extern DECLSPEC char *SDLCALL SDL_ulltoa(Uint64 value, char *str, int radix);
-#if defined(HAVE__UI64TOA) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE char *SDL_ulltoa_inline(Uint64 value, char *str, int radix) { return _ui64toa(value, str, radix); }
-#define SDL_ulltoa SDL_ulltoa_inline
-#endif
 
-// Urho3D: disabled
-/*
+extern DECLSPEC int SDLCALL SDL_atoi(const char *str);
+extern DECLSPEC double SDLCALL SDL_atof(const char *str);
+extern DECLSPEC long SDLCALL SDL_strtol(const char *str, char **endp, int base);
+extern DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *str, char **endp, int base);
 extern DECLSPEC Sint64 SDLCALL SDL_strtoll(const char *str, char **endp, int base);
-#if defined(HAVE_STRTOLL) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE Sint64 SDL_strtoll_inline(const char *str, char **endp, int base) { return strtoll(str, endp, base); }
-#define SDL_strtoll SDL_strtoll_inline
-#endif
-*/
-
 extern DECLSPEC Uint64 SDLCALL SDL_strtoull(const char *str, char **endp, int base);
-#if defined(HAVE_STRTOULL) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE Uint64 SDL_strtoull_inline(const char *str, char **endp, int base) { return strtoull(str, endp, base); }
-#define SDL_strtoull SDL_strtoull_inline
-#endif
-
 extern DECLSPEC double SDLCALL SDL_strtod(const char *str, char **endp);
-#if defined(HAVE_STRTOD) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_strtod_inline(const char *str, char **endp) { return strtod(str, endp); }
-#define SDL_strtod SDL_strtod_inline
-#endif
-
-extern DECLSPEC int SDLCALL SDL_atoi(const char *str);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_ATOI
-SDL_FORCE_INLINE int SDL_atoi_inline(const char *str) { return atoi(str); }
-#else
-SDL_FORCE_INLINE int SDL_atoi_inline(const char *str) { return SDL_strtol(str, NULL, 0); }
-#endif
-#define SDL_atoi SDL_atoi_inline
-#endif /* !SDL_STDINC_NO_INLINES */
-
-extern DECLSPEC double SDLCALL SDL_atof(const char *str);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_ATOF
-SDL_FORCE_INLINE double SDL_atof_inline(const char *str) { return (double) atof(str); }
-#else
-SDL_FORCE_INLINE double SDL_atof_inline(const char *str) { return SDL_strtod(str, NULL); }
-#endif
-#define SDL_atof SDL_atof_inline
-#endif /* !SDL_STDINC_NO_INLINES */
-
 
 extern DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2);
-#if defined(HAVE_STRCMP) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE int SDL_strcmp_inline(const char *str1, const char *str2) { return strcmp(str1, str2); }
-#define SDL_strcmp SDL_strcmp_inline
-#endif
-
 extern DECLSPEC int SDLCALL SDL_strncmp(const char *str1, const char *str2, size_t maxlen);
-#if defined(HAVE_STRNCMP) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE int SDL_strncmp_inline(const char *str1, const char *str2, size_t maxlen) { return strncmp(str1, str2, maxlen); }
-#define SDL_strncmp SDL_strncmp_inline
-#endif
-
 extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_STRCASECMP
-SDL_FORCE_INLINE int SDL_strcasecmp_inline(const char *str1, const char *str2) { return strcasecmp(str1, str2); }
-#define SDL_strcasecmp SDL_strcasecmp_inline
-#elif defined(HAVE__STRICMP)
-SDL_FORCE_INLINE int SDL_strcasecmp_inline(const char *str1, const char *str2) { return _stricmp(str1, str2); }
-#define SDL_strcasecmp SDL_strcasecmp_inline
-#endif
-#endif /* !SDL_STDINC_NO_INLINES */
-
 extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t len);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_STRNCASECMP
-SDL_FORCE_INLINE int SDL_strncasecmp_inline(const char *str1, const char *str2, size_t len) { return strncasecmp(str1, str2, len); }
-#define SDL_strncasecmp SDL_strncasecmp_inline
-#elif defined(HAVE__STRNICMP)
-SDL_FORCE_INLINE int SDL_strncasecmp_inline(const char *str1, const char *str2, size_t len) { return _strnicmp(str1, str2, len); }
-#define SDL_strncasecmp SDL_strncasecmp_inline
-#endif
-#endif /* !SDL_STDINC_NO_INLINES */
 
-/* Not doing SDL_*_inline functions for these, because of the varargs. */
 extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, const char *fmt, ...);
-#ifdef HAVE_SSCANF
-#define SDL_sscanf sscanf
-#endif
-
 extern DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...);
-#ifdef HAVE_SNPRINTF
-#define SDL_snprintf snprintf
-#endif
-
 extern DECLSPEC int SDLCALL SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap);
-#if defined(HAVE_VSNPRINTF) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE int SDL_vsnprintf_inline(char *text, size_t maxlen, const char *fmt, va_list ap) { return vsnprintf(text, maxlen, fmt, ap); }
-#define SDL_vsnprintf SDL_vsnprintf_inline
-#endif
 
 #ifndef HAVE_M_PI
 #ifndef M_PI
@@ -697,106 +341,19 @@ SDL_FORCE_INLINE int SDL_vsnprintf_inline(char *text, size_t maxlen, const char
 #endif
 
 extern DECLSPEC double SDLCALL SDL_atan(double x);
-#if defined(HAVE_ATAN) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_atan_inline(double x) { return atan(x); }
-#define SDL_atan SDL_atan_inline
-#endif
-
 extern DECLSPEC double SDLCALL SDL_atan2(double x, double y);
-#if defined(HAVE_ATAN2) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_atan2_inline(double x, double y) { return atan2(x, y); }
-#define SDL_atan2 SDL_atan2_inline
-#endif
-
 extern DECLSPEC double SDLCALL SDL_ceil(double x);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_CEIL
-SDL_FORCE_INLINE double SDL_ceil_inline(double x) { return ceil(x); }
-#else
-SDL_FORCE_INLINE double SDL_ceil_inline(double x) { return (double)(int)((x)+0.5); }
-#endif
-#define SDL_ceil SDL_ceil_inline
-#endif /* !SDL_STDINC_NO_INLINES */
-
-// Urho3D: disabled
-/*
 extern DECLSPEC double SDLCALL SDL_copysign(double x, double y);
-#if defined(HAVE_COPYSIGN) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_copysign_inline(double x, double y) { return copysign(x, y); }
-#define SDL_copysign SDL_copysign_inline
-#endif
-*/
-
 extern DECLSPEC double SDLCALL SDL_cos(double x);
-#if defined(HAVE_COS) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_cos_inline(double x) { return cos(x); }
-#define SDL_cos SDL_cos_inline
-#endif
-
 extern DECLSPEC float SDLCALL SDL_cosf(float x);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_COSF
-SDL_FORCE_INLINE float SDL_cosf_inline(float x) { return cosf(x); }
-#else
-SDL_FORCE_INLINE float SDL_cosf_inline(float x) { return (float)SDL_cos((double)x); }
-#endif
-#define SDL_cosf SDL_cosf_inline
-#endif /* !SDL_STDINC_NO_INLINES */
-
 extern DECLSPEC double SDLCALL SDL_fabs(double x);
-#if defined(HAVE_FABS) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_fabs_inline(double x) { return fabs(x); }
-#define SDL_fabs SDL_fabs_inline
-#endif
-
 extern DECLSPEC double SDLCALL SDL_floor(double x);
-#if defined(HAVE_FLOOR) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_floor_inline(double x) { return floor(x); }
-#define SDL_floor SDL_floor_inline
-#endif
-
 extern DECLSPEC double SDLCALL SDL_log(double x);
-#if defined(HAVE_LOG) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_log_inline(double x) { return log(x); }
-#define SDL_log SDL_log_inline
-#endif
-
 extern DECLSPEC double SDLCALL SDL_pow(double x, double y);
-#if defined(HAVE_POW) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_pow_inline(double x, double y) { return pow(x, y); }
-#define SDL_pow SDL_pow_inline
-#endif
-
-// Urho3D: disabled
-/*
 extern DECLSPEC double SDLCALL SDL_scalbn(double x, int n);
-#if defined(HAVE_SCALBN) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_scalbn_inline(double x, int n) { return scalbn(x, n); }
-#define SDL_scalbn SDL_scalbn_inline
-#endif
-*/
-
 extern DECLSPEC double SDLCALL SDL_sin(double x);
-#if defined(HAVE_SIN) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_sin_inline(double x) { return sin(x); }
-#define SDL_sin SDL_sin_inline
-#endif
-
 extern DECLSPEC float SDLCALL SDL_sinf(float x);
-#ifndef SDL_STDINC_NO_INLINES
-#ifdef HAVE_SINF
-SDL_FORCE_INLINE float SDL_sinf_inline(float x) { return sinf(x); }
-#else
-SDL_FORCE_INLINE float SDL_sinf_inline(float x) { return (float)SDL_sin((double)x); }
-#endif
-#define SDL_sinf SDL_sinf_inline
-#endif /* !SDL_STDINC_NO_INLINES */
-
 extern DECLSPEC double SDLCALL SDL_sqrt(double x);
-#if defined(HAVE_SQRT) && !defined(SDL_STDINC_NO_INLINES)
-SDL_FORCE_INLINE double SDL_sqrt_inline(double x) { return sqrt(x); }
-#define SDL_sqrt SDL_sqrt_inline
-#endif
 
 /* The SDL implementation of iconv() returns these error codes */
 #define SDL_ICONV_ERROR     (size_t)-1

+ 14 - 16
Source/ThirdParty/SDL/include/SDL_surface.h

@@ -399,44 +399,42 @@ extern DECLSPEC int SDLCALL SDL_FillRects
  *
  *  The blit function should not be called on a locked surface.
  *
- *  The blit semantics for surfaces with and without alpha and colorkey
+ *  The blit semantics for surfaces with and without blending and colorkey
  *  are defined as follows:
  *  \verbatim
     RGBA->RGB:
-      SDL_SRCALPHA set:
-        alpha-blend (using alpha-channel).
+      Source surface blend mode set to SDL_BLENDMODE_BLEND:
+        alpha-blend (using the source alpha-channel and per-surface alpha)
         SDL_SRCCOLORKEY ignored.
-      SDL_SRCALPHA not set:
+      Source surface blend mode set to SDL_BLENDMODE_NONE:
         copy RGB.
         if SDL_SRCCOLORKEY set, only copy the pixels matching the
         RGB values of the source color key, ignoring alpha in the
         comparison.
 
     RGB->RGBA:
-      SDL_SRCALPHA set:
-        alpha-blend (using the source per-surface alpha value);
-        set destination alpha to opaque.
-      SDL_SRCALPHA not set:
+      Source surface blend mode set to SDL_BLENDMODE_BLEND:
+        alpha-blend (using the source per-surface alpha)
+      Source surface blend mode set to SDL_BLENDMODE_NONE:
         copy RGB, set destination alpha to source per-surface alpha value.
       both:
         if SDL_SRCCOLORKEY set, only copy the pixels matching the
         source color key.
 
     RGBA->RGBA:
-      SDL_SRCALPHA set:
-        alpha-blend (using the source alpha channel) the RGB values;
-        leave destination alpha untouched. [Note: is this correct?]
+      Source surface blend mode set to SDL_BLENDMODE_BLEND:
+        alpha-blend (using the source alpha-channel and per-surface alpha)
         SDL_SRCCOLORKEY ignored.
-      SDL_SRCALPHA not set:
+      Source surface blend mode set to SDL_BLENDMODE_NONE:
         copy all of RGBA to the destination.
         if SDL_SRCCOLORKEY set, only copy the pixels matching the
         RGB values of the source color key, ignoring alpha in the
-       comparison.
+        comparison.
 
     RGB->RGB:
-      SDL_SRCALPHA set:
-        alpha-blend (using the source per-surface alpha value).
-      SDL_SRCALPHA not set:
+      Source surface blend mode set to SDL_BLENDMODE_BLEND:
+        alpha-blend (using the source per-surface alpha)
+      Source surface blend mode set to SDL_BLENDMODE_NONE:
         copy RGB.
       both:
         if SDL_SRCCOLORKEY set, only copy the pixels matching the

+ 1 - 1
Source/ThirdParty/SDL/include/SDL_syswm.h

@@ -219,7 +219,7 @@ typedef struct SDL_SysWMinfo SDL_SysWMinfo;
  *  \code
  *  SDL_SysWMinfo info;
  *  SDL_VERSION(&info.version);
- *  if ( SDL_GetWindowWMInfo(&info) ) { ... }
+ *  if ( SDL_GetWindowWMInfo(window, &info) ) { ... }
  *  \endcode
  */
 extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowWMInfo(SDL_Window * window,

+ 63 - 1
Source/ThirdParty/SDL/include/SDL_thread.h

@@ -32,6 +32,7 @@
 #include "SDL_error.h"
 
 /* Thread synchronization primitives */
+#include "SDL_atomic.h"
 #include "SDL_mutex.h"
 
 #include "begin_code.h"
@@ -47,6 +48,9 @@ typedef struct SDL_Thread SDL_Thread;
 /* The SDL thread ID */
 typedef unsigned long SDL_threadID;
 
+/* Thread local storage ID, 0 is the invalid ID */
+typedef unsigned int SDL_TLSID;
+
 /* The SDL thread priority
  *
  * Note: On many systems you require special privileges to set high priority.
@@ -105,7 +109,7 @@ SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
 /**
  *  Create a thread.
  */
-#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, _beginthreadex, _endthreadex)
+#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)_endthreadex)
 
 #else
 
@@ -166,6 +170,64 @@ extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority);
  */
 extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status);
 
+/**
+ *  \brief Create an identifier that is globally visible to all threads but refers to data that is thread-specific.
+ *
+ *  \return The newly created thread local storage identifier, or 0 on error
+ *
+ *  \code
+ *  static SDL_SpinLock tls_lock;
+ *  static SDL_TLSID thread_local_storage;
+ * 
+ *  void SetMyThreadData(void *value)
+ *  {
+ *      if (!thread_local_storage) {
+ *          SDL_AtomicLock(&tls_lock);
+ *          if (!thread_local_storage) {
+ *              thread_local_storage = SDL_TLSCreate();
+ *          }
+ *          SDL_AtomicUnLock(&tls_lock);
+ *      }
+ *      SDL_TLSSet(thread_local_storage, value);
+ *  }
+ *  
+ *  void *GetMyThreadData(void)
+ *  {
+ *      return SDL_TLSGet(thread_local_storage);
+ *  }
+ *  \endcode
+ *
+ *  \sa SDL_TLSGet()
+ *  \sa SDL_TLSSet()
+ */
+extern DECLSPEC SDL_TLSID SDLCALL SDL_TLSCreate(void);
+
+/**
+ *  \brief Get the value associated with a thread local storage ID for the current thread.
+ *
+ *  \param id The thread local storage ID
+ *
+ *  \return The value associated with the ID for the current thread, or NULL if no value has been set.
+ *
+ *  \sa SDL_TLSCreate()
+ *  \sa SDL_TLSSet()
+ */
+extern DECLSPEC void * SDLCALL SDL_TLSGet(SDL_TLSID id);
+
+/**
+ *  \brief Set the value associated with a thread local storage ID for the current thread.
+ *
+ *  \param id The thread local storage ID
+ *  \param value The value to associate with the ID for the current thread
+ *  \param destructor A function called when the thread exits, to free the value.
+ *
+ *  \return 0 on success, -1 on error
+ *
+ *  \sa SDL_TLSCreate()
+ *  \sa SDL_TLSGet()
+ */
+extern DECLSPEC int SDLCALL SDL_TLSSet(SDL_TLSID id, const void *value, void (*destructor)(void*));
+
 
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus

+ 11 - 1
Source/ThirdParty/SDL/include/SDL_video.h

@@ -396,7 +396,7 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window * window);
  *  \param h     The height of the window.
  *  \param flags The flags for the window, a mask of any of the following:
  *               ::SDL_WINDOW_FULLSCREEN, ::SDL_WINDOW_OPENGL,
- *               ::SDL_WINDOW_SHOWN,      ::SDL_WINDOW_BORDERLESS,
+ *               ::SDL_WINDOW_HIDDEN,     ::SDL_WINDOW_BORDERLESS,
  *               ::SDL_WINDOW_RESIZABLE,  ::SDL_WINDOW_MAXIMIZED,
  *               ::SDL_WINDOW_MINIMIZED,  ::SDL_WINDOW_INPUT_GRABBED.
  *
@@ -892,6 +892,16 @@ extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_CreateContext(SDL_Window *
 extern DECLSPEC int SDLCALL SDL_GL_MakeCurrent(SDL_Window * window,
                                                SDL_GLContext context);
 
+/**
+ *  \brief Get the currently active OpenGL window.
+ */
+extern DECLSPEC SDL_Window* SDLCALL SDL_GL_GetCurrentWindow(void);
+
+/**
+ *  \brief Get the currently active OpenGL context.
+ */
+extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void);
+
 /**
  *  \brief Set the swap interval for the current OpenGL context.
  *

+ 63 - 45
Source/ThirdParty/SDL/src/SDL.c

@@ -25,8 +25,8 @@
 #include "SDL.h"
 #include "SDL_bits.h"
 #include "SDL_revision.h"
-#include "SDL_fatal.h"
 #include "SDL_assert_c.h"
+#include "events/SDL_events_c.h"
 #include "haptic/SDL_haptic_c.h"
 #include "joystick/SDL_joystick_c.h"
 
@@ -107,12 +107,46 @@ SDL_InitSubSystem(Uint32 flags)
         return -1;
     }
 
+    /* Clear the error message */
+    SDL_ClearError();
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+    if (SDL_HelperWindowCreate() < 0) {
+        return -1;
+    }
+#endif
+
 #if !SDL_TIMERS_DISABLED
     SDL_InitTicks();
 #endif
 
+    if ((flags & SDL_INIT_GAMECONTROLLER)) {
+        /* game controller implies joystick */
+        flags |= SDL_INIT_JOYSTICK;
+    }
+
+    if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) {
+        /* video or joystick implies events */
+        flags |= SDL_INIT_EVENTS;
+    }
+
+    /* Initialize the event subsystem */
+    if ((flags & SDL_INIT_EVENTS)) {
+#if !SDL_EVENTS_DISABLED
+        if (SDL_PrivateShouldInitSubsystem(SDL_INIT_EVENTS)) {
+            if (SDL_StartEventLoop() < 0) {
+                return (-1);
+            }
+            SDL_QuitInit();
+        }
+        SDL_PrivateSubsystemRefCountIncr(SDL_INIT_EVENTS);
+#else
+        return SDL_SetError("SDL not built with events support");
+#endif
+    }
+
     /* Initialize the timer subsystem */
-    if ((flags & SDL_INIT_TIMER) ){
+    if ((flags & SDL_INIT_TIMER)){
 #if !SDL_TIMERS_DISABLED
         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_TIMER)) {
             if (SDL_TimerInit() < 0) {
@@ -125,8 +159,8 @@ SDL_InitSubSystem(Uint32 flags)
 #endif
     }
 
-    /* Initialize the video/event subsystem */
-    if ((flags & SDL_INIT_VIDEO) ){
+    /* Initialize the video subsystem */
+    if ((flags & SDL_INIT_VIDEO)){
 #if !SDL_VIDEO_DISABLED
         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_VIDEO)) {
             if (SDL_VideoInit(NULL) < 0) {
@@ -140,7 +174,7 @@ SDL_InitSubSystem(Uint32 flags)
     }
 
     /* Initialize the audio subsystem */
-    if ((flags & SDL_INIT_AUDIO) ){
+    if ((flags & SDL_INIT_AUDIO)){
 #if !SDL_AUDIO_DISABLED
         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_AUDIO)) {
             if (SDL_AudioInit(NULL) < 0) {
@@ -153,13 +187,8 @@ SDL_InitSubSystem(Uint32 flags)
 #endif
     }
 
-    if ((flags & SDL_INIT_GAMECONTROLLER)) {
-        /* Game controller implies Joystick. */
-        flags |= SDL_INIT_JOYSTICK;
-    }
-
     /* Initialize the joystick subsystem */
-    if ((flags & SDL_INIT_JOYSTICK) ){
+    if ((flags & SDL_INIT_JOYSTICK)){
 #if !SDL_JOYSTICK_DISABLED
         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_JOYSTICK)) {
            if (SDL_JoystickInit() < 0) {
@@ -172,7 +201,7 @@ SDL_InitSubSystem(Uint32 flags)
 #endif
     }
 
-    if ((flags & SDL_INIT_GAMECONTROLLER) ){
+    if ((flags & SDL_INIT_GAMECONTROLLER)){
 #if !SDL_JOYSTICK_DISABLED
         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_GAMECONTROLLER)) {
             if (SDL_GameControllerInit() < 0) {
@@ -186,7 +215,7 @@ SDL_InitSubSystem(Uint32 flags)
     }
 
     /* Initialize the haptic subsystem */
-    if ((flags & SDL_INIT_HAPTIC) ){
+    if ((flags & SDL_INIT_HAPTIC)){
 #if !SDL_HAPTIC_DISABLED
         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_HAPTIC)) {
             if (SDL_HapticInit() < 0) {
@@ -205,30 +234,7 @@ SDL_InitSubSystem(Uint32 flags)
 int
 SDL_Init(Uint32 flags)
 {
-    if (SDL_AssertionsInit() < 0) {
-        return -1;
-    }
-
-    /* Clear the error message */
-    SDL_ClearError();
-
-#if SDL_VIDEO_DRIVER_WINDOWS
-    if (SDL_HelperWindowCreate() < 0) {
-        return -1;
-    }
-#endif
-
-    /* Initialize the desired subsystems */
-    if (SDL_InitSubSystem(flags) < 0) {
-        return (-1);
-    }
-
-    /* Everything is initialized */
-    if (!(flags & SDL_INIT_NOPARACHUTE)) {
-        SDL_InstallParachute();
-    }
-
-    return (0);
+    return SDL_InitSubSystem(flags);
 }
 
 void
@@ -237,7 +243,7 @@ SDL_QuitSubSystem(Uint32 flags)
     /* Shut down requested initialized subsystems */
 #if !SDL_JOYSTICK_DISABLED
     if ((flags & SDL_INIT_GAMECONTROLLER)) {
-        /* Game controller implies Joystick. */
+        /* game controller implies joystick */
         flags |= SDL_INIT_JOYSTICK;
 
         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_GAMECONTROLLER)) {
@@ -247,6 +253,9 @@ SDL_QuitSubSystem(Uint32 flags)
     }
 
     if ((flags & SDL_INIT_JOYSTICK)) {
+        /* joystick implies events */
+        flags |= SDL_INIT_EVENTS;
+
         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_JOYSTICK)) {
             SDL_JoystickQuit();
         }
@@ -274,6 +283,9 @@ SDL_QuitSubSystem(Uint32 flags)
 
 #if !SDL_VIDEO_DISABLED
     if ((flags & SDL_INIT_VIDEO)) {
+        /* video implies events */
+        flags |= SDL_INIT_EVENTS;
+
         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_VIDEO)) {
             SDL_VideoQuit();
         }
@@ -289,6 +301,16 @@ SDL_QuitSubSystem(Uint32 flags)
         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_TIMER);
     }
 #endif
+
+#if !SDL_EVENTS_DISABLED
+    if ((flags & SDL_INIT_EVENTS)) {
+        if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_EVENTS)) {
+            SDL_QuitQuit();
+            SDL_StopEventLoop();
+        }
+        SDL_PrivateSubsystemRefCountDecr(SDL_INIT_EVENTS);
+    }
+#endif
 }
 
 Uint32
@@ -327,9 +349,6 @@ SDL_Quit(void)
 #endif
     SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
 
-    /* Uninstall any parachute signal handlers */
-    SDL_UninstallParachute();
-
     SDL_ClearHints();
     SDL_AssertionsQuit();
     SDL_LogResetPriorities();
@@ -371,9 +390,6 @@ SDL_GetPlatform()
     return "AIX";
 #elif __ANDROID__
     return "Android";
-#elif __HAIKU__
-/* Haiku must appear here before BeOS, since it also defines __BEOS__ */
-    return "Haiku";
 #elif __BEOS__
     return "BeOS";
 #elif __BSDI__
@@ -382,6 +398,8 @@ SDL_GetPlatform()
     return "Dreamcast";
 #elif __FREEBSD__
     return "FreeBSD";
+#elif __HAIKU__
+    return "Haiku";
 #elif __HPUX__
     return "HP-UX";
 #elif __IRIX__
@@ -411,7 +429,7 @@ SDL_GetPlatform()
 #elif __WIN32__
     return "Windows";
 #elif __IPHONEOS__
-    return "iPhone OS";
+    return "iOS";
 #elif __PSP__
     return "PlayStation Portable";
 #else

+ 0 - 6
Source/ThirdParty/SDL/src/SDL_assert.c

@@ -325,12 +325,6 @@ SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
 }
 
 
-int SDL_AssertionsInit(void)
-{
-    /* this is a no-op at the moment. */
-    return 0;
-}
-
 void SDL_AssertionsQuit(void)
 {
     SDL_GenerateAssertionReport();

+ 0 - 1
Source/ThirdParty/SDL/src/SDL_assert_c.h

@@ -19,7 +19,6 @@
   3. This notice may not be removed or altered from any source distribution.
 */
 
-extern int SDL_AssertionsInit(void);
 extern void SDL_AssertionsQuit(void);
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 111 - 26
Source/ThirdParty/SDL/src/SDL_hints.c

@@ -21,43 +21,35 @@
 #include "SDL_config.h"
 
 #include "SDL_hints.h"
-#include "SDL_hints_c.h"
+#include "SDL_error.h"
 
 
 /* Assuming there aren't many hints set and they aren't being queried in
-   critical performance paths, we'll just use a linked list here.
+   critical performance paths, we'll just use linked lists here.
  */
+typedef struct SDL_HintWatch {
+    SDL_HintCallback callback;
+    void *userdata;
+    struct SDL_HintWatch *next;
+} SDL_HintWatch;
+
 typedef struct SDL_Hint {
     char *name;
     char *value;
     SDL_HintPriority priority;
-    SDL_HintChangedCb callback;
+    SDL_HintWatch *callbacks;
     struct SDL_Hint *next;
 } SDL_Hint;
 
 static SDL_Hint *SDL_hints;
 
-SDL_bool
-SDL_RegisterHintChangedCb(const char *name, SDL_HintChangedCb hintCb)
-{
-    SDL_Hint *hint;
-
-    for (hint = SDL_hints; hint; hint = hint->next) {
-        if (SDL_strcmp(name, hint->name) == 0) {
-            hint->callback = hintCb;
-            return SDL_TRUE;
-        }
-    }
-
-    return SDL_FALSE;
-}
-
 SDL_bool
 SDL_SetHintWithPriority(const char *name, const char *value,
                         SDL_HintPriority priority)
 {
     const char *env;
     SDL_Hint *hint;
+    SDL_HintWatch *entry;
 
     if (!name || !value) {
         return SDL_FALSE;
@@ -73,12 +65,21 @@ SDL_SetHintWithPriority(const char *name, const char *value,
             if (priority < hint->priority) {
                 return SDL_FALSE;
             }
-            if (SDL_strcmp(hint->value, value) != 0) {
-                if (hint->callback != NULL) {
-                    (*hint->callback)(name, hint->value, value);
+            if (!hint->value || !value || SDL_strcmp(hint->value, value) != 0) {
+                for (entry = hint->callbacks; entry; ) {
+                    /* Save the next entry in case this one is deleted */
+                    SDL_HintWatch *next = entry->next;
+                    entry->callback(entry->userdata, name, hint->value, value);
+                    entry = next;
+                }
+                if (hint->value) {
+                    SDL_free(hint->value);
+                }
+                if (value) {
+                    hint->value = SDL_strdup(value);
+                } else {
+                    hint->value = NULL;
                 }
-                SDL_free(hint->value);
-                hint->value = SDL_strdup(value);
             }
             hint->priority = priority;
             return SDL_TRUE;
@@ -91,9 +92,9 @@ SDL_SetHintWithPriority(const char *name, const char *value,
         return SDL_FALSE;
     }
     hint->name = SDL_strdup(name);
-    hint->value = SDL_strdup(value);
+    hint->value = value ? SDL_strdup(value) : NULL;
     hint->priority = priority;
-    hint->callback = NULL;
+    hint->callbacks = NULL;
     hint->next = SDL_hints;
     SDL_hints = hint;
     return SDL_TRUE;
@@ -123,16 +124,100 @@ SDL_GetHint(const char *name)
     return env;
 }
 
+void
+SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
+{
+    SDL_Hint *hint;
+    SDL_HintWatch *entry;
+    const char *value;
+
+    if (!name || !*name) {
+        SDL_InvalidParamError("name");
+        return;
+    }
+    if (!callback) {
+        SDL_InvalidParamError("callback");
+        return;
+    }
+
+    SDL_DelHintCallback(name, callback, userdata);
+
+    entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
+    entry->callback = callback;
+    entry->userdata = userdata;
+
+    for (hint = SDL_hints; hint; hint = hint->next) {
+        if (SDL_strcmp(name, hint->name) == 0) {
+            break;
+        }
+    }
+    if (!hint) {
+        /* Need to add a hint entry for this watcher */
+        hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
+        if (!hint) {
+            return;
+        }
+        hint->name = SDL_strdup(name);
+        hint->value = NULL;
+        hint->priority = SDL_HINT_DEFAULT;
+        hint->callbacks = NULL;
+        hint->next = SDL_hints;
+        SDL_hints = hint;
+    }
+
+    /* Add it to the callbacks for this hint */
+    entry->next = hint->callbacks;
+    hint->callbacks = entry;
+
+    /* Now call it with the current value */
+    value = SDL_GetHint(name);
+    callback(userdata, name, value, value);
+}
+
+void
+SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
+{
+    SDL_Hint *hint;
+    SDL_HintWatch *entry, *prev;
+
+    for (hint = SDL_hints; hint; hint = hint->next) {
+        if (SDL_strcmp(name, hint->name) == 0) {
+            prev = NULL;
+            for (entry = hint->callbacks; entry; entry = entry->next) {
+                if (callback == entry->callback && userdata == entry->userdata) {
+                    if (prev) {
+                        prev->next = entry->next;
+                    } else {
+                        hint->callbacks = entry->next;
+                    }
+                    SDL_free(entry);
+                    break;
+                }
+                prev = entry;
+            }
+            return;
+        }
+    }
+}
+
 void SDL_ClearHints(void)
 {
     SDL_Hint *hint;
+    SDL_HintWatch *entry;
 
     while (SDL_hints) {
         hint = SDL_hints;
         SDL_hints = hint->next;
 
         SDL_free(hint->name);
-        SDL_free(hint->value);
+        if (hint->value) {
+            SDL_free(hint->value);
+        }
+        for (entry = hint->callbacks; entry; ) {
+            SDL_HintWatch *freeable = entry;
+            entry = entry->next;
+            SDL_free(freeable);
+        }
         SDL_free(hint);
     }
 }

+ 19 - 12
Source/ThirdParty/SDL/src/SDL_log.c

@@ -266,6 +266,7 @@ void
 SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
 {
     char *message;
+    size_t len;
 
     /* Nothing to do if we don't have an output function */
     if (!SDL_log_function) {
@@ -286,7 +287,18 @@ SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list
     if (!message) {
         return;
     }
+
     SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap);
+
+    /* Chop off final endline. */
+    len = SDL_strlen(message);
+    if ((len > 0) && (message[len-1] == '\n')) {
+        message[--len] = '\0';
+        if ((len > 0) && (message[len-1] == '\r')) {  /* catch "\r\n", too. */
+            message[--len] = '\0';
+        }
+    }
+
     SDL_log_function(SDL_log_userdata, category, priority, message);
     SDL_stack_free(message);
 }
@@ -305,6 +317,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
 {
 #if defined(__WIN32__)
     /* Way too many allocations here, urgh */
+    /* Note: One can't call SDL_SetError here, since that function itself logs. */
     {
         char *output;
         size_t length;
@@ -319,16 +332,16 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
             if (!attachResult) {
                     attachError = GetLastError();
                     if (attachError == ERROR_INVALID_HANDLE) {
-                        SDL_SetError("Parent process has no console");
+                        OutputDebugString(TEXT("Parent process has no console"));
                         consoleAttached = -1;
                     } else if (attachError == ERROR_GEN_FAILURE) {
-                         SDL_SetError("Could not attach to console of parent process");
+                         OutputDebugString(TEXT("Could not attach to console of parent process"));
                          consoleAttached = -1;
                     } else if (attachError == ERROR_ACCESS_DENIED) {  
                          /* Already attached */
                         consoleAttached = 1;
                     } else {
-                        SDL_SetError("Error %d attaching console", attachError);
+                        OutputDebugString(TEXT("Error attaching console"));
                         consoleAttached = -1;
                     }
                 } else {
@@ -352,10 +365,10 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
         /* Screen output to stderr, if console was attached. */
         if (consoleAttached == 1) {
                 if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
-                    SDL_SetError("Error %d calling WriteConsole", GetLastError());
+                    OutputDebugString(TEXT("Error calling WriteConsole"));
                 }
                 if (charsWritten == ERROR_NOT_ENOUGH_MEMORY) {
-                    SDL_SetError("Insufficient heap memory to write message of size %d", length);
+                    OutputDebugString(TEXT("Insufficient heap memory to write message"));
                 }
         }
 
@@ -386,15 +399,9 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
     }
 #elif defined(__PSP__)
     {
-        unsigned int length;
-        char*        output;
         FILE*        pFile;
-        length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
-        output = SDL_stack_alloc(char, length);
-        SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
         pFile = fopen ("SDL_Log.txt", "a");
-        fwrite (output, strlen (output), 1, pFile);
-        SDL_stack_free(output);
+        fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
         fclose (pFile);
     }
 #endif

+ 14 - 0
Source/ThirdParty/SDL/src/atomic/SDL_atomic.c

@@ -101,4 +101,18 @@ SDL_AtomicCASPtr(void **a, void *oldval, void *newval)
     return retval;
 }
 
+#if defined(__GNUC__) && defined(__arm__) && \
+   (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__))
+__asm__(
+"   .align 2\n"
+"   .globl _SDL_MemoryBarrierRelease\n"
+"   .globl _SDL_MemoryBarrierAcquire\n"
+"_SDL_MemoryBarrierRelease:\n"
+"_SDL_MemoryBarrierAcquire:\n"
+"   mov r0, #0\n"
+"   mcr p15, 0, r0, c7, c10, 5\n"
+"   bx lr\n"
+);
+#endif /* __GNUC__ && __arm__ && ARMV6 */
+
 /* vi: set ts=4 sw=4 expandtab: */

+ 32 - 17
Source/ThirdParty/SDL/src/audio/SDL_audio.c

@@ -67,6 +67,7 @@ extern AudioBootStrap NDSAUD_bootstrap;
 extern AudioBootStrap FUSIONSOUND_bootstrap;
 extern AudioBootStrap ANDROIDAUD_bootstrap;
 extern AudioBootStrap PSPAUD_bootstrap;
+extern AudioBootStrap SNDIO_bootstrap;
 
 /* Available audio drivers */
 static const AudioBootStrap *const bootstrap[] = {
@@ -76,6 +77,9 @@ static const AudioBootStrap *const bootstrap[] = {
 #if SDL_AUDIO_DRIVER_ALSA
     &ALSA_bootstrap,
 #endif
+#if SDL_AUDIO_DRIVER_SNDIO
+    &SNDIO_bootstrap,
+#endif
 #if SDL_AUDIO_DRIVER_BSD
     &BSD_AUDIO_bootstrap,
 #endif
@@ -356,9 +360,7 @@ SDL_RunAudio(void *devicep)
                 device->convert.len_mult;
         }
 #endif
-
-        /* stream_len = device->convert.len; */
-        stream_len = device->spec.size;
+        stream_len = device->convert.len;
     } else {
         stream_len = device->spec.size;
     }
@@ -457,15 +459,11 @@ SDL_RunAudio(void *devicep)
         }
     } else {
         /* Otherwise, do not use the streamer. This is the old code. */
+        const int silence = (int) device->spec.silence;
 
         /* Loop, filling the audio buffers */
         while (device->enabled) {
 
-            if (device->paused) {
-                SDL_Delay(delay);
-                continue;
-            }
-
             /* Fill the current buffer with sound */
             if (device->convert.needed) {
                 if (device->convert.buf) {
@@ -481,7 +479,11 @@ SDL_RunAudio(void *devicep)
             }
 
             SDL_LockMutex(device->mixer_lock);
-            (*fill) (udata, stream, stream_len);
+            if (device->paused) {
+                SDL_memset(stream, silence, stream_len);
+            } else {
+                (*fill) (udata, stream, stream_len);
+            }
             SDL_UnlockMutex(device->mixer_lock);
 
             /* Convert the audio if necessary */
@@ -954,12 +956,6 @@ open_audio_device(const char *devname, int iscapture,
         return 0;
     }
 
-    /* If the audio driver changes the buffer size, accept it */
-    if (device->spec.samples != obtained->samples) {
-        obtained->samples = device->spec.samples;
-        SDL_CalculateAudioSpec(obtained);
-    }
-
     /* See if we need to do any conversion */
     build_cvt = SDL_FALSE;
     if (obtained->freq != device->spec.freq) {
@@ -983,6 +979,16 @@ open_audio_device(const char *devname, int iscapture,
             build_cvt = SDL_TRUE;
         }
     }
+
+    /* If the audio driver changes the buffer size, accept it.
+       This needs to be done after the format is modified above,
+       otherwise it might not have the correct buffer size.
+     */
+    if (device->spec.samples != obtained->samples) {
+        obtained->samples = device->spec.samples;
+        SDL_CalculateAudioSpec(obtained);
+    }
+
     if (build_cvt) {
         /* Build an audio conversion block */
         if (SDL_BuildAudioCVT(&device->convert,
@@ -994,7 +1000,7 @@ open_audio_device(const char *devname, int iscapture,
             return 0;
         }
         if (device->convert.needed) {
-            device->convert.len = (int) (((double) obtained->size) /
+            device->convert.len = (int) (((double) device->spec.size) /
                                          device->convert.len_ratio);
 
             device->convert.buf =
@@ -1110,7 +1116,9 @@ SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
 {
     SDL_AudioDevice *device = get_audio_device(devid);
     if (device) {
+        current_audio.impl.LockDevice(device);
         device->paused = pause_on;
+        current_audio.impl.UnlockDevice(device);
     }
 }
 
@@ -1173,8 +1181,15 @@ void
 SDL_AudioQuit(void)
 {
     SDL_AudioDeviceID i;
+
+    if (!current_audio.name) {  /* not initialized?! */
+        return;
+    }
+
     for (i = 0; i < SDL_arraysize(open_devices); i++) {
-        SDL_CloseAudioDevice(i);
+        if (open_devices[i] != NULL) {
+            SDL_CloseAudioDevice(i+1);
+        }
     }
 
     /* Free the driver data */

+ 1 - 2
Source/ThirdParty/SDL/src/audio/SDL_audiocvt.c

@@ -293,10 +293,9 @@ SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
         const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
         type *dst = (type *) (cvt->buf + cvt->len_cvt * 2); \
         for (i = cvt->len_cvt / sizeof(type); i; --i) { \
-            const type val = *src; \
             src -= 1; \
             dst -= 2; \
-            dst[0] = dst[1] = val; \
+            dst[0] = dst[1] = *src; \
         } \
     }
 

+ 1 - 1
Source/ThirdParty/SDL/src/audio/alsa/SDL_alsa_audio.c

@@ -643,7 +643,7 @@ ALSA_OpenDevice(_THIS, const char *devname, int iscapture)
         ALSA_CloseDevice(this);
         return SDL_OutOfMemory();
     }
-    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
 
     /* Switch to blocking mode for playback */
     ALSA_snd_pcm_nonblock(pcm_handle, 0);

+ 3 - 3
Source/ThirdParty/SDL/src/audio/alsa/SDL_alsa_audio.h

@@ -20,8 +20,8 @@
 */
 #include "SDL_config.h"
 
-#ifndef _ALSA_PCM_audio_h
-#define _ALSA_PCM_audio_h
+#ifndef _SDL_ALSA_audio_h
+#define _SDL_ALSA_audio_h
 
 #include <alsa/asoundlib.h>
 
@@ -40,6 +40,6 @@ struct SDL_PrivateAudioData
     int mixlen;
 };
 
-#endif /* _ALSA_PCM_audio_h */
+#endif /* _SDL_ALSA_audio_h */
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 4 - 18
Source/ThirdParty/SDL/src/audio/android/SDL_androidaudio.c

@@ -50,12 +50,6 @@ AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
 
     audioDevice = this;
 
-    this->hidden = SDL_malloc(sizeof(*(this->hidden)));
-    if (!this->hidden) {
-        return SDL_OutOfMemory();
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
     test_format = SDL_FirstAudioFormat(this->spec.format);
     while (test_format != 0) { /* no "UNKNOWN" constant */
         if ((test_format == AUDIO_U8) || (test_format == AUDIO_S16LSB)) {
@@ -110,10 +104,9 @@ AndroidAUD_GetDeviceBuf(_THIS)
 static void
 AndroidAUD_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_free(this->hidden);
-        this->hidden = NULL;
-    }
+    /* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread
+       so it's safe to terminate the Java side buffer and AudioTrack
+     */
     Android_JNI_CloseAudioDevice();
 
     if (audioDevice == this) {
@@ -131,7 +124,6 @@ AndroidAUD_Init(SDL_AudioDriverImpl * impl)
     impl->CloseDevice = AndroidAUD_CloseDevice;
 
     /* and the capabilities */
-    impl->ProvidesOwnCallbackThread = 1;
     impl->HasCaptureSupport = 0; /* TODO */
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->OnlyHasDefaultInputDevice = 1;
@@ -143,13 +135,7 @@ AudioBootStrap ANDROIDAUD_bootstrap = {
     "android", "SDL Android audio driver", AndroidAUD_Init, 0
 };
 
-/* Called by the Java code to start the audio processing on a thread */
-void
-Android_RunAudioThread()
-{
-    SDL_RunAudio(audioDevice);
-}
-
 #endif /* SDL_AUDIO_DRIVER_ANDROID */
 
 /* vi: set ts=4 sw=4 expandtab: */
+

+ 2 - 0
Source/ThirdParty/SDL/src/audio/android/SDL_androidaudio.h

@@ -32,6 +32,8 @@ struct SDL_PrivateAudioData
 {
 };
 
+static void AndroidAUD_CloseDevice(_THIS);
+
 #endif /* _SDL_androidaudio_h */
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 0 - 3
Source/ThirdParty/SDL/src/audio/coreaudio/SDL_coreaudio.h

@@ -32,9 +32,6 @@
 #if MACOSX_COREAUDIO
 #include <CoreAudio/CoreAudio.h>
 #include <CoreServices/CoreServices.h>
-#if MAC_OS_X_VERSION_MAX_ALLOWED <= 1050
-#include <AudioUnit/AUNTComponent.h>
-#endif
 #else
 #include <AudioToolbox/AudioToolbox.h>
 #endif

+ 44 - 34
Source/ThirdParty/SDL/src/audio/directsound/SDL_directsound.c

@@ -30,6 +30,10 @@
 #include "../SDL_audio_c.h"
 #include "SDL_directsound.h"
 
+#ifndef WAVE_FORMAT_IEEE_FLOAT
+#define WAVE_FORMAT_IEEE_FLOAT 0x0003
+#endif
+
 /* DirectX function pointers for audio */
 static void* DSoundDLL = NULL;
 typedef HRESULT(WINAPI*fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
@@ -342,7 +346,7 @@ DSOUND_CloseDevice(_THIS)
    number of audio chunks available in the created buffer.
 */
 static int
-CreateSecondary(_THIS, HWND focus, WAVEFORMATEX * wavefmt)
+CreateSecondary(_THIS, HWND focus)
 {
     LPDIRECTSOUND sndObj = this->hidden->sound;
     LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
@@ -352,6 +356,24 @@ CreateSecondary(_THIS, HWND focus, WAVEFORMATEX * wavefmt)
     DSBUFFERDESC format;
     LPVOID pvAudioPtr1, pvAudioPtr2;
     DWORD dwAudioBytes1, dwAudioBytes2;
+    WAVEFORMATEX wfmt;
+
+    SDL_zero(wfmt);
+
+    if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
+        wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+    } else {
+        wfmt.wFormatTag = WAVE_FORMAT_PCM;
+    }
+
+    wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
+    wfmt.nChannels = this->spec.channels;
+    wfmt.nSamplesPerSec = this->spec.freq;
+    wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
+    wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
+
+    /* Update the fragment size as size in bytes */
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Try to set primary mixing privileges */
     if (focus) {
@@ -367,7 +389,7 @@ CreateSecondary(_THIS, HWND focus, WAVEFORMATEX * wavefmt)
     }
 
     /* Try to create the secondary buffer */
-    SDL_memset(&format, 0, sizeof(format));
+    SDL_zero(format);
     format.dwSize = sizeof(format);
     format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
     if (!focus) {
@@ -382,12 +404,12 @@ CreateSecondary(_THIS, HWND focus, WAVEFORMATEX * wavefmt)
                             DSBSIZE_MIN / numchunks, DSBSIZE_MAX / numchunks);
     }
     format.dwReserved = 0;
-    format.lpwfxFormat = wavefmt;
+    format.lpwfxFormat = &wfmt;
     result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
     if (result != DS_OK) {
         return SetDSerror("DirectSound CreateSoundBuffer", result);
     }
-    IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt);
+    IDirectSoundBuffer_SetFormat(*sndbuf, &wfmt);
 
     /* Silence the initial audio buffer */
     result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
@@ -433,8 +455,8 @@ static int
 DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
 {
     HRESULT result;
-    WAVEFORMATEX waveformat;
-    int valid_format = 0;
+    SDL_bool valid_format = SDL_FALSE;
+    SDL_bool tried_format = SDL_FALSE;
     SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
     FindDevGUIDData devguid;
     LPGUID guid = NULL;
@@ -461,13 +483,25 @@ DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
     }
     SDL_memset(this->hidden, 0, (sizeof *this->hidden));
 
+    /* Open the audio device */
+    result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
+    if (result != DS_OK) {
+        DSOUND_CloseDevice(this);
+        return SetDSerror("DirectSoundCreate", result);
+    }
+
     while ((!valid_format) && (test_format)) {
         switch (test_format) {
         case AUDIO_U8:
         case AUDIO_S16:
         case AUDIO_S32:
+        case AUDIO_F32:
+            tried_format = SDL_TRUE;
             this->spec.format = test_format;
-            valid_format = 1;
+            this->hidden->num_buffers = CreateSecondary(this, NULL);
+            if (this->hidden->num_buffers > 0) {
+                valid_format = SDL_TRUE;
+            }
             break;
         }
         test_format = SDL_NextAudioFormat();
@@ -475,36 +509,12 @@ DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
 
     if (!valid_format) {
         DSOUND_CloseDevice(this);
+        if (tried_format) {
+            return -1;  // CreateSecondary() should have called SDL_SetError().
+        }
         return SDL_SetError("DirectSound: Unsupported audio format");
     }
 
-    SDL_memset(&waveformat, 0, sizeof(waveformat));
-    waveformat.wFormatTag = WAVE_FORMAT_PCM;
-    waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
-    waveformat.nChannels = this->spec.channels;
-    waveformat.nSamplesPerSec = this->spec.freq;
-    waveformat.nBlockAlign =
-        waveformat.nChannels * (waveformat.wBitsPerSample / 8);
-    waveformat.nAvgBytesPerSec =
-        waveformat.nSamplesPerSec * waveformat.nBlockAlign;
-
-    /* Update the fragment size as size in bytes */
-    SDL_CalculateAudioSpec(&this->spec);
-
-    /* Open the audio device */
-    result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
-    if (result != DS_OK) {
-        DSOUND_CloseDevice(this);
-        return SetDSerror("DirectSoundCreate", result);
-    }
-
-    /* Create the audio buffer to which we write */
-    this->hidden->num_buffers = CreateSecondary(this, NULL, &waveformat);
-    if (this->hidden->num_buffers < 0) {
-        DSOUND_CloseDevice(this);
-        return -1;
-    }
-
     /* The buffer will auto-start playing in DSOUND_WaitDevice() */
     this->hidden->mixlen = this->spec.size;
 

+ 4 - 4
Source/ThirdParty/SDL/src/audio/disk/SDL_diskaudio.c

@@ -114,6 +114,10 @@ DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
     }
     SDL_memset(this->hidden, 0, sizeof(*this->hidden));
 
+    this->hidden->mixlen = this->spec.size;
+    this->hidden->write_delay =
+        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
+
     /* Open the audio device */
     this->hidden->output = SDL_RWFromFile(fname, "wb");
     if (this->hidden->output == NULL) {
@@ -129,10 +133,6 @@ DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
-    this->hidden->mixlen = this->spec.size;
-    this->hidden->write_delay =
-        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
-
 #if HAVE_STDIO_H
     fprintf(stderr,
             "WARNING: You are using the SDL disk writer audio driver!\n"

+ 0 - 129
Source/ThirdParty/SDL/src/audio/nds/SDL_ndsaudio.c

@@ -1,129 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2012 Sam Lantinga <[email protected]>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-#include "SDL_config.h"
-
-#if SDL_AUDIO_DRIVER_NDS
-
-/* Output audio to NDS */
-
-#include <nds.h>
-
-#include "SDL_audio.h"
-#include "../SDL_audio_c.h"
-#include "SDL_ndsaudio.h"
-
-static int
-NDSAUD_OpenDevice(_THIS, const char *devname, int iscapture)
-{
-    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
-    int valid_datatype = 0;
-
-    this->hidden = SDL_malloc(sizeof(*(this->hidden)));
-    if (!this->hidden) {
-        SDL_OutOfMemory();
-        return 0;
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    while ((!valid_datatype) && (test_format)) {
-        this->spec.format = test_format;
-        switch (test_format) {
-        case AUDIO_S8:
-            /*case AUDIO_S16LSB: */
-            valid_datatype = 1;
-            break;
-        default:
-            test_format = SDL_NextAudioFormat();
-            break;
-        }
-    }
-
-#if 0
-    /* set the generic sound parameters */
-    setGenericSound(22050,      /* sample rate */
-                    127,        /* volume */
-                    64,         /* panning/balance */
-                    0);         /* sound format */
-#endif
-
-    return 1;
-}
-
-static void
-NDSAUD_PlayDevice(_THIS)
-{
-#if 0
-    playGenericSound(this->hidden->mixbuf, this->hidden->mixlen);
-
-//    sound->data = this->hidden->mixbuf;/* pointer to raw audio data */
-//    sound->len = this->hidden->mixlen; /* size of raw data pointed to above */
-//    sound->rate = 22050; /* sample rate = 22050Hz */
-//    sound->vol = 127;    /* volume [0..127] for [min..max] */
-//    sound->pan = 64;     /* balance [0..127] for [left..right] */
-//    sound->format = 0;   /* 0 for 16-bit, 1 for 8-bit */
-//    playSound(sound);
-#endif
-}
-
-
-static Uint8 *
-NDSAUD_GetDeviceBuf(_THIS)
-{
-    return this->hidden->mixbuf;        /* is this right? */
-}
-
-static void
-NDSAUD_WaitDevice(_THIS)
-{
-    /* stub */
-}
-
-static void
-NDSAUD_CloseDevice(_THIS)
-{
-    /* stub */
-}
-
-static int
-NDSAUD_Init(SDL_AudioDriverImpl * impl)
-{
-    /* Set the function pointers */
-    impl->OpenDevice = NDSAUD_OpenDevice;
-    impl->PlayDevice = NDSAUD_PlayDevice;
-    impl->WaitDevice = NDSAUD_WaitDevice;
-    impl->GetDeviceBuf = NDSAUD_GetDeviceBuf;
-    impl->CloseDevice = NDSAUD_CloseDevice;
-
-    /* and the capabilities */
-    impl->HasCaptureSupport = 1;
-    impl->OnlyHasDefaultOutputDevice = 1;
-    impl->OnlyHasDefaultInputDevice = 1;
-
-    return 1;   /* this audio target is available. */
-}
-
-AudioBootStrap NDSAUD_bootstrap = {
-    "nds", "SDL NDS audio driver", NDSAUD_Init, 0       /*1? */
-};
-
-#endif /* SDL_AUDIO_DRIVER_NDS */
-
-/* vi: set ts=4 sw=4 expandtab: */

+ 39 - 3
Source/ThirdParty/SDL/src/audio/pulseaudio/SDL_pulseaudio.c

@@ -49,7 +49,7 @@
 
 #if (PA_API_VERSION < 12)
 /** Return non-zero if the passed state is one of the connected states */
-static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) {
+static __inline__ int PA_CONTEXT_IS_GOOD(pa_context_state_t x) {
     return
         x == PA_CONTEXT_CONNECTING ||
         x == PA_CONTEXT_AUTHORIZING ||
@@ -57,7 +57,7 @@ static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) {
         x == PA_CONTEXT_READY;
 }
 /** Return non-zero if the passed state is one of the connected states */
-static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
+static __inline__ int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
     return
         x == PA_STREAM_CREATING ||
         x == PA_STREAM_READY;
@@ -65,6 +65,7 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
 #endif /* pulseaudio <= 0.9.10 */
 
 
+static const char *(*PULSEAUDIO_pa_get_library_version) (void);
 static pa_simple *(*PULSEAUDIO_pa_simple_new) (const char *, const char *,
     pa_stream_direction_t, const char *, const char *, const pa_sample_spec *,
     const pa_channel_map *, const pa_buffer_attr *, int *);
@@ -177,6 +178,7 @@ LoadPulseAudioLibrary(void)
 static int
 load_pulseaudio_syms(void)
 {
+    SDL_PULSEAUDIO_SYM(pa_get_library_version);
     SDL_PULSEAUDIO_SYM(pa_simple_new);
     SDL_PULSEAUDIO_SYM(pa_simple_free);
     SDL_PULSEAUDIO_SYM(pa_mainloop_new);
@@ -322,6 +324,28 @@ PULSEAUDIO_CloseDevice(_THIS)
 }
 
 
+static __inline__ int
+squashVersion(const int major, const int minor, const int patch)
+{
+    return ((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF);
+}
+
+/* Workaround for older pulse: pa_context_new() must have non-NULL appname */
+static const char *
+getAppName(void)
+{
+    const char *verstr = PULSEAUDIO_pa_get_library_version();
+    if (verstr != NULL) {
+        int maj, min, patch;
+        if (SDL_sscanf(verstr, "%d.%d.%d", &maj, &min, &patch) == 3) {
+            if (squashVersion(maj, min, patch) >= squashVersion(0, 9, 15)) {
+                return NULL;  /* 0.9.15+ handles NULL correctly. */
+            }
+        }
+    }
+    return "SDL Application";  /* oh well. */
+}
+
 static int
 PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
 {
@@ -360,6 +384,18 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
         case AUDIO_S16MSB:
             paspec.format = PA_SAMPLE_S16BE;
             break;
+        case AUDIO_S32LSB:
+            paspec.format = PA_SAMPLE_S32LE;
+            break;
+        case AUDIO_S32MSB:
+            paspec.format = PA_SAMPLE_S32BE;
+            break;
+        case AUDIO_F32LSB:
+            paspec.format = PA_SAMPLE_FLOAT32LE;
+            break;
+        case AUDIO_F32MSB:
+            paspec.format = PA_SAMPLE_FLOAT32BE;
+            break;
         default:
             paspec.format = PA_SAMPLE_INVALID;
             break;
@@ -420,7 +456,7 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
     }
 
     h->mainloop_api = PULSEAUDIO_pa_mainloop_get_api(h->mainloop);
-    h->context = PULSEAUDIO_pa_context_new(h->mainloop_api, NULL);
+    h->context = PULSEAUDIO_pa_context_new(h->mainloop_api, getAppName());
     if (!h->context) {
         PULSEAUDIO_CloseDevice(this);
         return SDL_SetError("pa_context_new() failed");

+ 329 - 0
Source/ThirdParty/SDL/src/audio/sndio/SDL_sndioaudio.c

@@ -0,0 +1,329 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_config.h"
+
+#if SDL_AUDIO_DRIVER_SNDIO
+
+/* OpenBSD sndio target */
+
+#if HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#include <unistd.h>
+
+#include "SDL_audio.h"
+#include "../SDL_audiomem.h"
+#include "../SDL_audio_c.h"
+#include "SDL_sndioaudio.h"
+
+#ifdef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
+#include "SDL_loadso.h"
+#endif
+
+static struct sio_hdl * (*SNDIO_sio_open)(const char *, unsigned int, int);
+static void (*SNDIO_sio_close)(struct sio_hdl *);
+static int (*SNDIO_sio_setpar)(struct sio_hdl *, struct sio_par *);
+static int (*SNDIO_sio_getpar)(struct sio_hdl *, struct sio_par *);
+static int (*SNDIO_sio_start)(struct sio_hdl *);
+static int (*SNDIO_sio_stop)(struct sio_hdl *);
+static size_t (*SNDIO_sio_read)(struct sio_hdl *, void *, size_t);
+static size_t (*SNDIO_sio_write)(struct sio_hdl *, const void *, size_t);
+static void (*SNDIO_sio_initpar)(struct sio_par *);
+
+#ifdef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
+static const char *sndio_library = SDL_AUDIO_DRIVER_SNDIO_DYNAMIC;
+static void *sndio_handle = NULL;
+
+static int
+load_sndio_sym(const char *fn, void **addr)
+{
+    *addr = SDL_LoadFunction(sndio_handle, fn);
+    if (*addr == NULL) {
+        /* Don't call SDL_SetError(): SDL_LoadFunction already did. */
+        return 0;
+    }
+
+    return 1;
+}
+
+/* cast funcs to char* first, to please GCC's strict aliasing rules. */
+#define SDL_SNDIO_SYM(x) \
+    if (!load_sndio_sym(#x, (void **) (char *) &SNDIO_##x)) return -1
+#else
+#define SDL_SNDIO_SYM(x) SNDIO_##x = x
+#endif
+
+static int
+load_sndio_syms(void)
+{
+    SDL_SNDIO_SYM(sio_open);
+    SDL_SNDIO_SYM(sio_close);
+    SDL_SNDIO_SYM(sio_setpar);
+    SDL_SNDIO_SYM(sio_getpar);
+    SDL_SNDIO_SYM(sio_start);
+    SDL_SNDIO_SYM(sio_stop);
+    SDL_SNDIO_SYM(sio_read);
+    SDL_SNDIO_SYM(sio_write);
+    SDL_SNDIO_SYM(sio_initpar);
+    return 0;
+}
+
+#undef SDL_SNDIO_SYM
+
+#ifdef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
+
+static void
+UnloadSNDIOLibrary(void)
+{
+    if (sndio_handle != NULL) {
+        SDL_UnloadObject(sndio_handle);
+        sndio_handle = NULL;
+    }
+}
+
+static int
+LoadSNDIOLibrary(void)
+{
+    int retval = 0;
+    if (sndio_handle == NULL) {
+        sndio_handle = SDL_LoadObject(sndio_library);
+        if (sndio_handle == NULL) {
+            retval = -1;
+            /* Don't call SDL_SetError(): SDL_LoadObject already did. */
+        } else {
+            retval = load_sndio_syms();
+            if (retval < 0) {
+                UnloadSNDIOLibrary();
+            }
+        }
+    }
+    return retval;
+}
+
+#else
+
+static void
+UnloadSNDIOLibrary(void)
+{
+}
+
+static int
+LoadSNDIOLibrary(void)
+{
+    load_sndio_syms();
+    return 0;
+}
+
+#endif /* SDL_AUDIO_DRIVER_SNDIO_DYNAMIC */
+
+
+
+
+static void
+SNDIO_WaitDevice(_THIS)
+{
+    /* no-op; SNDIO_sio_write() blocks if necessary. */
+}
+
+static void
+SNDIO_PlayDevice(_THIS)
+{
+    const int written = SNDIO_sio_write(this->hidden->dev,
+                                        this->hidden->mixbuf,
+                                        this->hidden->mixlen);
+
+    /* If we couldn't write, assume fatal error for now */
+    if ( written == 0 ) {
+        this->enabled = 0;
+    }
+#ifdef DEBUG_AUDIO
+    fprintf(stderr, "Wrote %d bytes of audio data\n", written);
+#endif
+}
+
+static Uint8 *
+SNDIO_GetDeviceBuf(_THIS)
+{
+    return this->hidden->mixbuf;
+}
+
+static void
+SNDIO_WaitDone(_THIS)
+{
+    SNDIO_sio_stop(this->hidden->dev);
+}
+
+static void
+SNDIO_CloseDevice(_THIS)
+{
+    if (this->hidden != NULL) {
+        if (this->hidden->mixbuf != NULL) {
+            SDL_FreeAudioMem(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+        if ( this->hidden->dev != NULL ) {
+            SNDIO_sio_close(this->hidden->dev);
+            this->hidden->dev = NULL;
+        }
+        SDL_free(this->hidden);
+        this->hidden = NULL;
+    }
+}
+
+static int
+SNDIO_OpenDevice(_THIS, const char *devname, int iscapture)
+{
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
+    struct sio_par par;
+    int status;
+
+    this->hidden = (struct SDL_PrivateAudioData *)
+        SDL_malloc(sizeof(*this->hidden));
+    if (this->hidden == NULL) {
+        return SDL_OutOfMemory();
+    }
+    SDL_memset(this->hidden, 0, sizeof(*this->hidden));
+
+    this->hidden->mixlen = this->spec.size;
+
+    /* !!! FIXME: SIO_DEVANY can be a specific device... */
+    if ((this->hidden->dev = SNDIO_sio_open(NULL, SIO_PLAY, 0)) == NULL) {
+        SNDIO_CloseDevice(this);
+        return SDL_SetError("sio_open() failed");
+    }
+
+    SNDIO_sio_initpar(&par);
+
+    par.rate = this->spec.freq;
+    par.pchan = this->spec.channels;
+    par.round = this->spec.samples;
+    par.appbufsz = par.round * 2;
+
+    /* Try for a closest match on audio format */
+    status = -1;
+    while (test_format && (status < 0)) {
+        if (!SDL_AUDIO_ISFLOAT(test_format)) {
+            par.le = SDL_AUDIO_ISLITTLEENDIAN(test_format) ? 1 : 0;
+            par.sig = SDL_AUDIO_ISSIGNED(test_format) ? 1 : 0;
+            par.bits = SDL_AUDIO_BITSIZE(test_format);
+
+            if (SNDIO_sio_setpar(this->hidden->dev, &par) == 1) {
+                status = 0;
+                break;
+            }
+        }
+        test_format = SDL_NextAudioFormat();
+    }
+
+    if (status < 0) {
+        SNDIO_CloseDevice(this);
+        return SDL_SetError("sndio: Couldn't find any hardware audio formats");
+    }
+
+    if (SNDIO_sio_getpar(this->hidden->dev, &par) == 0) {
+        SNDIO_CloseDevice(this);
+        return SDL_SetError("sio_getpar() failed");
+    }
+
+    if ((par.bits == 32) && (par.sig) && (par.le))
+        this->spec.format = AUDIO_S32LSB;
+    else if ((par.bits == 32) && (par.sig) && (!par.le))
+        this->spec.format = AUDIO_S32MSB;
+    else if ((par.bits == 16) && (par.sig) && (par.le))
+        this->spec.format = AUDIO_S16LSB;
+    else if ((par.bits == 16) && (par.sig) && (!par.le))
+        this->spec.format = AUDIO_S16MSB;
+    else if ((par.bits == 16) && (!par.sig) && (par.le))
+        this->spec.format = AUDIO_U16LSB;
+    else if ((par.bits == 16) && (!par.sig) && (!par.le))
+        this->spec.format = AUDIO_U16MSB;
+    else if ((par.bits == 8) && (par.sig))
+        this->spec.format = AUDIO_S8;
+    else if ((par.bits == 8) && (!par.sig))
+        this->spec.format = AUDIO_U8;
+    else {
+        SNDIO_CloseDevice(this);
+        return SDL_SetError("sndio: Got unsupported hardware audio format.");
+    }
+
+    this->spec.freq = par.rate;
+    this->spec.channels = par.pchan;
+    this->spec.samples = par.round;
+
+    /* Calculate the final parameters for this audio specification */
+    SDL_CalculateAudioSpec(&this->spec);
+
+    /* Allocate mixing buffer */
+    this->hidden->mixlen = this->spec.size;
+    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    if (this->hidden->mixbuf == NULL) {
+        SNDIO_CloseDevice(this);
+        return SDL_OutOfMemory();
+    }
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
+
+    if (!SNDIO_sio_start(this->hidden->dev)) {
+        return SDL_SetError("sio_start() failed");
+    }
+
+    /* We're ready to rock and roll. :-) */
+    return 0;
+}
+
+static void
+SNDIO_Deinitialize(void)
+{
+    UnloadSNDIOLibrary();
+}
+
+static int
+SNDIO_Init(SDL_AudioDriverImpl * impl)
+{
+    if (LoadSNDIOLibrary() < 0) {
+        return 0;
+    }
+
+    /* Set the function pointers */
+    impl->OpenDevice = SNDIO_OpenDevice;
+    impl->WaitDevice = SNDIO_WaitDevice;
+    impl->PlayDevice = SNDIO_PlayDevice;
+    impl->GetDeviceBuf = SNDIO_GetDeviceBuf;
+    impl->WaitDone = SNDIO_WaitDone;
+    impl->CloseDevice = SNDIO_CloseDevice;
+    impl->Deinitialize = SNDIO_Deinitialize;
+    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: sndio can handle multiple devices. */
+
+    return 1;   /* this audio target is available. */
+}
+
+AudioBootStrap SNDIO_bootstrap = {
+    "sndio", "OpenBSD sndio", SNDIO_Init, 0
+};
+
+#endif /* SDL_AUDIO_DRIVER_SNDIO */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 13 - 10
Source/ThirdParty/SDL/src/audio/nds/SDL_ndsaudio.h → Source/ThirdParty/SDL/src/audio/sndio/SDL_sndioaudio.h

@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2012 Sam Lantinga <[email protected]>
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -20,23 +20,26 @@
 */
 #include "SDL_config.h"
 
-#ifndef _SDL_ndsaudio_h
-#define _SDL_ndsaudio_h
+#ifndef _SDL_sndioaudio_h
+#define _SDL_sndioaudio_h
+
+#include <sndio.h>
 
 #include "../SDL_sysaudio.h"
-#include <nds/arm9/sound.h>
 
 /* Hidden "this" pointer for the audio functions */
-#define _THIS	SDL_AudioDevice *this
+#define _THIS   SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
 {
-    /* The file descriptor for the audio device */
+    /* The audio device handle */
+    struct sio_hdl *dev;
+
+    /* Raw mixing buffer */
     Uint8 *mixbuf;
-    Uint32 mixlen;
-    Uint32 write_delay;
-    Uint32 initial_calls;
+    int mixlen;
 };
 
-#endif /* _SDL_ndsaudio_h */
+#endif /* _SDL_sndioaudio_h */
+
 /* vi: set ts=4 sw=4 expandtab: */

+ 43 - 23
Source/ThirdParty/SDL/src/audio/winmm/SDL_winmm.c

@@ -32,6 +32,10 @@
 #include "../SDL_audio_c.h"
 #include "SDL_winmm.h"
 
+#ifndef WAVE_FORMAT_IEEE_FLOAT
+#define WAVE_FORMAT_IEEE_FLOAT 0x0003
+#endif
+
 #define DETECT_DEV_IMPL(typ, capstyp) \
 static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \
     const UINT devcount = wave##typ##GetNumDevs(); \
@@ -193,6 +197,30 @@ WINMM_CloseDevice(_THIS)
     }
 }
 
+static SDL_bool
+PrepWaveFormat(_THIS, UINT_PTR devId, WAVEFORMATEX *pfmt, const int iscapture)
+{
+    SDL_zerop(pfmt);
+
+    if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
+        pfmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+    } else {
+        pfmt->wFormatTag = WAVE_FORMAT_PCM;
+    }
+    pfmt->wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
+
+    pfmt->nChannels = this->spec.channels;
+    pfmt->nSamplesPerSec = this->spec.freq;
+    pfmt->nBlockAlign = pfmt->nChannels * (pfmt->wBitsPerSample / 8);
+    pfmt->nAvgBytesPerSec = pfmt->nSamplesPerSec * pfmt->nBlockAlign;
+
+    if (iscapture) {
+        return (waveInOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
+    } else {
+        return (waveOutOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
+    }
+}
+
 static int
 WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
 {
@@ -250,17 +278,28 @@ WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
     for (i = 0; i < NUM_BUFFERS; ++i)
         this->hidden->wavebuf[i].dwUser = 0xFFFF;
 
+    if (this->spec.channels > 2)
+        this->spec.channels = 2;        /* !!! FIXME: is this right? */
+
+    /* Check the buffer size -- minimum of 1/4 second (word aligned) */
+    if (this->spec.samples < (this->spec.freq / 4))
+        this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
+
     while ((!valid_datatype) && (test_format)) {
-        valid_datatype = 1;
-        this->spec.format = test_format;
         switch (test_format) {
         case AUDIO_U8:
         case AUDIO_S16:
         case AUDIO_S32:
-            break;              /* valid. */
+        case AUDIO_F32:
+            this->spec.format = test_format;
+            if (PrepWaveFormat(this, devId, &waveformat, iscapture)) {
+                valid_datatype = 1;
+            } else {
+                test_format = SDL_NextAudioFormat();
+            }
+            break;
 
         default:
-            valid_datatype = 0;
             test_format = SDL_NextAudioFormat();
             break;
         }
@@ -271,25 +310,6 @@ WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
         return SDL_SetError("Unsupported audio format");
     }
 
-    /* Set basic WAVE format parameters */
-    SDL_memset(&waveformat, '\0', sizeof(waveformat));
-    waveformat.wFormatTag = WAVE_FORMAT_PCM;
-    waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
-
-    if (this->spec.channels > 2)
-        this->spec.channels = 2;        /* !!! FIXME: is this right? */
-
-    waveformat.nChannels = this->spec.channels;
-    waveformat.nSamplesPerSec = this->spec.freq;
-    waveformat.nBlockAlign =
-        waveformat.nChannels * (waveformat.wBitsPerSample / 8);
-    waveformat.nAvgBytesPerSec =
-        waveformat.nSamplesPerSec * waveformat.nBlockAlign;
-
-    /* Check the buffer size -- minimum of 1/4 second (word aligned) */
-    if (this->spec.samples < (this->spec.freq / 4))
-        this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
-
     /* Update the fragment size as size in bytes */
     SDL_CalculateAudioSpec(&this->spec);
 

+ 1426 - 1357
Source/ThirdParty/SDL/src/core/android/SDL_android.cpp → Source/ThirdParty/SDL/src/core/android/SDL_android.c

@@ -1,1357 +1,1426 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-// Modified by Lasse Oorni for Urho3D
-
-#include "SDL_config.h"
-#include "SDL_stdinc.h"
-#include "SDL_assert.h"
-#include "SDL_log.h"
-#include "SDL_main.h"
-
-#ifdef __ANDROID__
-
-#include "SDL_system.h"
-#include "SDL_android.h"
-// Urho3D: do not require EGL to allow compiling on API level 8
-// #include <EGL/egl.h>
-#define EGL_BUFFER_SIZE			0x3020
-#define EGL_ALPHA_SIZE			0x3021
-#define EGL_BLUE_SIZE			0x3022
-#define EGL_GREEN_SIZE			0x3023
-#define EGL_RED_SIZE			0x3024
-#define EGL_DEPTH_SIZE			0x3025
-#define EGL_STENCIL_SIZE		0x3026
-#define EGL_SAMPLES			0x3031
-#define EGL_SAMPLE_BUFFERS		0x3032
-#define EGL_RENDERABLE_TYPE		0x3040
-#define EGL_OPENGL_ES_BIT		0x0001	/* EGL_RENDERABLE_TYPE mask bits */
-#define EGL_OPENGL_ES2_BIT		0x0004	/* EGL_RENDERABLE_TYPE mask bits */
-#define EGL_NONE			0x3038	/* Attrib list terminator */
-
-extern "C" {
-#include "../../events/SDL_events_c.h"
-#include "../../video/android/SDL_androidkeyboard.h"
-#include "../../video/android/SDL_androidtouch.h"
-#include "../../video/android/SDL_androidvideo.h"
-
-#include <android/log.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <unistd.h>
-#define LOG_TAG "SDL_android"
-//#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
-//#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
-#define LOGI(...) do {} while (false)
-#define LOGE(...) do {} while (false)
-
-/* Uncomment this to log messages entering and exiting methods in this file */
-//#define DEBUG_JNI
-
-/* Implemented in audio/android/SDL_androidaudio.c */
-extern void Android_RunAudioThread();
-
-static void Android_JNI_ThreadDestroyed(void*);
-} // C
-
-/*******************************************************************************
- This file links the Java side of Android with libsdl
-*******************************************************************************/
-#include <jni.h>
-#include <android/log.h>
-
-
-/*******************************************************************************
-                               Globals
-*******************************************************************************/
-static pthread_key_t mThreadKey;
-static JavaVM* mJavaVM;
-
-// Main activity
-static jclass mActivityClass;
-
-// method signatures
-static jmethodID midCreateGLContext;
-static jmethodID midFlipBuffers;
-static jmethodID midAudioInit;
-static jmethodID midAudioWriteShortBuffer;
-static jmethodID midAudioWriteByteBuffer;
-static jmethodID midAudioQuit;
-
-// Accelerometer data storage
-static float fLastAccelerometer[3];
-static bool bHasNewData;
-
-// Urho3D: application files dir
-static char* mFilesDir = 0;
-
-/*******************************************************************************
-                 Functions called by JNI
-*******************************************************************************/
-
-// Library init
-extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
-{
-    JNIEnv *env;
-    mJavaVM = vm;
-    LOGI("JNI_OnLoad called");
-    if (mJavaVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
-        LOGE("Failed to get the environment using GetEnv()");
-        return -1;
-    }
-    /*
-     * Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
-     * Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
-     */
-    if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed)) {
-        __android_log_print(ANDROID_LOG_ERROR, "SDL", "Error initializing pthread key");
-    }
-    else {
-        Android_JNI_SetupThread();
-    }
-
-    return JNI_VERSION_1_4;
-}
-
-// Urho3D: added function
-extern "C" const char* SDL_Android_GetFilesDir()
-{
-    return mFilesDir;
-}
-
-// Called before SDL_main() to initialize JNI bindings
-// Urho3D: added passing user files directory from SDLActivity on startup
-extern "C" void SDL_Android_Init(JNIEnv* mEnv, jclass cls, jstring filesDir)
-{
-    __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init()");
-
-    Android_JNI_SetupThread();
-
-    // Copy the files dir
-    const char *str;
-    str = mEnv->GetStringUTFChars(filesDir, 0);
-    if (str)
-    {
-        if (mFilesDir)
-            free(mFilesDir);
-
-        size_t length = strlen(str) + 1;
-        mFilesDir = (char*)malloc(length);
-        memcpy(mFilesDir, str, length);
-        mEnv->ReleaseStringUTFChars(filesDir, str);
-    }
-
-    mActivityClass = (jclass)mEnv->NewGlobalRef(cls);
-
-    midCreateGLContext = mEnv->GetStaticMethodID(mActivityClass,
-                                "createGLContext","(II[I)Z");
-    midFlipBuffers = mEnv->GetStaticMethodID(mActivityClass,
-                                "flipBuffers","()V");
-    midAudioInit = mEnv->GetStaticMethodID(mActivityClass,
-                                "audioInit", "(IZZI)V");
-    midAudioWriteShortBuffer = mEnv->GetStaticMethodID(mActivityClass,
-                                "audioWriteShortBuffer", "([S)V");
-    midAudioWriteByteBuffer = mEnv->GetStaticMethodID(mActivityClass,
-                                "audioWriteByteBuffer", "([B)V");
-    midAudioQuit = mEnv->GetStaticMethodID(mActivityClass,
-                                "audioQuit", "()V");
-
-    bHasNewData = false;
-
-    if(!midCreateGLContext || !midFlipBuffers || !midAudioInit ||
-       !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) {
-        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
-    }
-    __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init() finished!");
-}
-
-// Resize
-extern "C" void Java_org_libsdl_app_SDLActivity_onNativeResize(
-                                    JNIEnv* env, jclass jcls,
-                                    jint width, jint height, jint format)
-{
-    Android_SetScreenResolution(width, height, format);
-}
-
-// Keydown
-extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
-                                    JNIEnv* env, jclass jcls, jint keycode)
-{
-    Android_OnKeyDown(keycode);
-}
-
-// Keyup
-extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
-                                    JNIEnv* env, jclass jcls, jint keycode)
-{
-    Android_OnKeyUp(keycode);
-}
-
-// Touch
-extern "C" void Java_org_libsdl_app_SDLActivity_onNativeTouch(
-                                    JNIEnv* env, jclass jcls,
-                                    jint touch_device_id_in, jint pointer_finger_id_in,
-                                    jint action, jfloat x, jfloat y, jfloat p)
-{
-    Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
-}
-
-// Accelerometer
-extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel(
-                                    JNIEnv* env, jclass jcls,
-                                    jfloat x, jfloat y, jfloat z)
-{
-    fLastAccelerometer[0] = x;
-    fLastAccelerometer[1] = y;
-    fLastAccelerometer[2] = z;
-    bHasNewData = true;
-}
-
-// Start up the SDL app
-// Urho3D: added passing user files directory from SDLActivity on startup
-extern "C" void Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jstring filesDir)
-{
-    /* This interface could expand with ABI negotiation, calbacks, etc. */
-    SDL_Android_Init(env, cls, filesDir);
-
-    SDL_SetMainReady();
-
-    /* Run the application code! */
-    int status;
-    char *argv[2];
-    argv[0] = strdup("SDL_app");
-    argv[1] = NULL;
-    status = SDL_main(1, argv);
-
-    /* Do not issue an exit or the whole application will terminate instead of just the SDL thread */
-    //exit(status);
-}
-
-// Low memory
-extern "C" void Java_org_libsdl_app_SDLActivity_nativeLowMemory(
-                                    JNIEnv* env, jclass cls)
-{
-    SDL_SendAppEvent(SDL_APP_LOWMEMORY);
-}
-
-// Quit
-extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit(
-                                    JNIEnv* env, jclass cls)
-{
-    // Inject a SDL_QUIT event
-    SDL_SendQuit();
-    SDL_SendAppEvent(SDL_APP_TERMINATING);
-}
-
-// Pause
-extern "C" void Java_org_libsdl_app_SDLActivity_nativePause(
-                                    JNIEnv* env, jclass cls)
-{
-    if (Android_Window) {
-        /* Signal the pause semaphore so the event loop knows to pause and (optionally) block itself */
-        if (!SDL_SemValue(Android_PauseSem)) SDL_SemPost(Android_PauseSem);
-        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
-        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
-    }
-
-    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativePause()");
-    SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
-    SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
-}
-
-// Resume
-extern "C" void Java_org_libsdl_app_SDLActivity_nativeResume(
-                                    JNIEnv* env, jclass cls)
-{
-    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeResume()");
-    SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
-    SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
-
-    if (Android_Window) {
-        /* Signal the resume semaphore so the event loop knows to resume and restore the GL Context
-         * We can't restore the GL Context here because it needs to be done on the SDL main thread
-         * and this function will be called from the Java thread instead.
-         */
-        if (!SDL_SemValue(Android_ResumeSem)) SDL_SemPost(Android_ResumeSem);
-        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
-        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
-    }
-}
-
-extern "C" void Java_org_libsdl_app_SDLActivity_nativeRunAudioThread(
-                                    JNIEnv* env, jclass cls)
-{
-    /* This is the audio thread, with a different environment */
-    Android_JNI_SetupThread();
-
-    Android_RunAudioThread();
-}
-
-extern "C" void Java_org_libsdl_app_SDLInputConnection_nativeCommitText(
-                                    JNIEnv* env, jclass cls,
-                                    jstring text, jint newCursorPosition)
-{
-    const char *utftext = env->GetStringUTFChars(text, NULL);
-
-    SDL_SendKeyboardText(utftext);
-
-    env->ReleaseStringUTFChars(text, utftext);
-}
-
-extern "C" void Java_org_libsdl_app_SDLInputConnection_nativeSetComposingText(
-                                    JNIEnv* env, jclass cls,
-                                    jstring text, jint newCursorPosition)
-{
-    const char *utftext = env->GetStringUTFChars(text, NULL);
-
-    SDL_SendEditingText(utftext, 0, 0);
-
-    env->ReleaseStringUTFChars(text, utftext);
-}
-
-
-
-/*******************************************************************************
-             Functions called by SDL into Java
-*******************************************************************************/
-
-class LocalReferenceHolder
-{
-private:
-    static int s_active;
-
-public:
-    static bool IsActive() {
-        return s_active > 0;
-    }
-
-public:
-    LocalReferenceHolder(const char *func) : m_env(NULL), m_func(func) {
-#ifdef DEBUG_JNI
-        SDL_Log("Entering function %s", m_func);
-#endif
-    }
-    ~LocalReferenceHolder() {
-#ifdef DEBUG_JNI
-        SDL_Log("Leaving function %s", m_func);
-#endif
-        if (m_env) {
-            m_env->PopLocalFrame(NULL);
-            --s_active;
-        }
-    }
-
-    bool init(JNIEnv *env, jint capacity = 16) {
-        if (env->PushLocalFrame(capacity) < 0) {
-            SDL_SetError("Failed to allocate enough JVM local references");
-            return false;
-        }
-        ++s_active;
-        m_env = env;
-        return true;
-    }
-
-protected:
-    JNIEnv *m_env;
-    const char *m_func;
-};
-int LocalReferenceHolder::s_active;
-
-extern "C" SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion,
-                                int red, int green, int blue, int alpha,
-                                int buffer, int depth, int stencil,
-                                int buffers, int samples)
-{
-    JNIEnv *env = Android_JNI_GetEnv();
-
-    jint attribs[] = {
-        EGL_RED_SIZE, red,
-        EGL_GREEN_SIZE, green,
-        EGL_BLUE_SIZE, blue,
-        EGL_ALPHA_SIZE, alpha,
-        EGL_BUFFER_SIZE, buffer,
-        EGL_DEPTH_SIZE, depth,
-        EGL_STENCIL_SIZE, stencil,
-        EGL_SAMPLE_BUFFERS, buffers,
-        EGL_SAMPLES, samples,
-        EGL_RENDERABLE_TYPE, (majorVersion == 1 ? EGL_OPENGL_ES_BIT : EGL_OPENGL_ES2_BIT),
-        EGL_NONE
-    };
-    int len = SDL_arraysize(attribs);
-
-    jintArray array;
-
-    array = env->NewIntArray(len);
-    env->SetIntArrayRegion(array, 0, len, attribs);
-
-    jboolean success = env->CallStaticBooleanMethod(mActivityClass, midCreateGLContext, majorVersion, minorVersion, array);
-
-    env->DeleteLocalRef(array);
-
-    return success ? SDL_TRUE : SDL_FALSE;
-}
-
-extern "C" void Android_JNI_SwapWindow()
-{
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-    mEnv->CallStaticVoidMethod(mActivityClass, midFlipBuffers);
-}
-
-extern "C" void Android_JNI_SetActivityTitle(const char *title)
-{
-    jmethodID mid;
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-    mid = mEnv->GetStaticMethodID(mActivityClass,"setActivityTitle","(Ljava/lang/String;)Z");
-    if (mid) {
-        jstring jtitle = reinterpret_cast<jstring>(mEnv->NewStringUTF(title));
-        mEnv->CallStaticBooleanMethod(mActivityClass, mid, jtitle);
-        mEnv->DeleteLocalRef(jtitle);
-    }
-}
-
-extern "C" SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
-{
-    int i;
-    SDL_bool retval = SDL_FALSE;
-
-    if (bHasNewData) {
-        for (i = 0; i < 3; ++i) {
-            values[i] = fLastAccelerometer[i];
-        }
-        bHasNewData = false;
-        retval = SDL_TRUE;
-    }
-
-    return retval;
-}
-
-static void Android_JNI_ThreadDestroyed(void* value) {
-    /* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
-    JNIEnv *env = (JNIEnv*) value;
-    if (env != NULL) {
-        mJavaVM->DetachCurrentThread();
-        pthread_setspecific(mThreadKey, NULL);
-    }
-}
-
-JNIEnv* Android_JNI_GetEnv(void) {
-    /* From http://developer.android.com/guide/practices/jni.html
-     * All threads are Linux threads, scheduled by the kernel.
-     * They're usually started from managed code (using Thread.start), but they can also be created elsewhere and then
-     * attached to the JavaVM. For example, a thread started with pthread_create can be attached with the
-     * JNI AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a thread is attached, it has no JNIEnv,
-     * and cannot make JNI calls.
-     * Attaching a natively-created thread causes a java.lang.Thread object to be constructed and added to the "main"
-     * ThreadGroup, making it visible to the debugger. Calling AttachCurrentThread on an already-attached thread
-     * is a no-op.
-     * Note: You can call this function any number of times for the same thread, there's no harm in it
-     */
-
-    JNIEnv *env;
-    int status = mJavaVM->AttachCurrentThread(&env, NULL);
-    if(status < 0) {
-        LOGE("failed to attach current thread");
-        return 0;
-    }
-
-    return env;
-}
-
-int Android_JNI_SetupThread(void) {
-    /* From http://developer.android.com/guide/practices/jni.html
-     * Threads attached through JNI must call DetachCurrentThread before they exit. If coding this directly is awkward,
-     * in Android 2.0 (Eclair) and higher you can use pthread_key_create to define a destructor function that will be
-     * called before the thread exits, and call DetachCurrentThread from there. (Use that key with pthread_setspecific
-     * to store the JNIEnv in thread-local-storage; that way it'll be passed into your destructor as the argument.)
-     * Note: The destructor is not called unless the stored value is != NULL
-     * Note: You can call this function any number of times for the same thread, there's no harm in it
-     *       (except for some lost CPU cycles)
-     */
-    JNIEnv *env = Android_JNI_GetEnv();
-    pthread_setspecific(mThreadKey, (void*) env);
-    return 1;
-}
-
-//
-// Audio support
-//
-static jboolean audioBuffer16Bit = JNI_FALSE;
-static jboolean audioBufferStereo = JNI_FALSE;
-static jobject audioBuffer = NULL;
-static void* audioBufferPinned = NULL;
-
-extern "C" int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
-{
-    int audioBufferFrames;
-
-    JNIEnv *env = Android_JNI_GetEnv();
-
-    if (!env) {
-        LOGE("callback_handler: failed to attach current thread");
-    }
-    Android_JNI_SetupThread();
-
-    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
-    audioBuffer16Bit = is16Bit;
-    audioBufferStereo = channelCount > 1;
-
-    env->CallStaticVoidMethod(mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames);
-
-    /* Allocating the audio buffer from the Java side and passing it as the return value for audioInit no longer works on
-     * Android >= 4.2 due to a "stale global reference" error. So now we allocate this buffer directly from this side. */
-
-    if (is16Bit) {
-        jshortArray audioBufferLocal = env->NewShortArray(desiredBufferFrames * (audioBufferStereo ? 2 : 1));
-        if (audioBufferLocal) {
-            audioBuffer = env->NewGlobalRef(audioBufferLocal);
-            env->DeleteLocalRef(audioBufferLocal);
-        }
-    }
-    else {
-        jbyteArray audioBufferLocal = env->NewByteArray(desiredBufferFrames * (audioBufferStereo ? 2 : 1));
-        if (audioBufferLocal) {
-            audioBuffer = env->NewGlobalRef(audioBufferLocal);
-            env->DeleteLocalRef(audioBufferLocal);
-        }
-    }
-
-    if (audioBuffer == NULL) {
-        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer!");
-        return 0;
-    }
-
-    jboolean isCopy = JNI_FALSE;
-    if (audioBuffer16Bit) {
-        audioBufferPinned = env->GetShortArrayElements((jshortArray)audioBuffer, &isCopy);
-        audioBufferFrames = env->GetArrayLength((jshortArray)audioBuffer);
-    } else {
-        audioBufferPinned = env->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy);
-        audioBufferFrames = env->GetArrayLength((jbyteArray)audioBuffer);
-    }
-    if (audioBufferStereo) {
-        audioBufferFrames /= 2;
-    }
-
-    return audioBufferFrames;
-}
-
-extern "C" void * Android_JNI_GetAudioBuffer()
-{
-    return audioBufferPinned;
-}
-
-extern "C" void Android_JNI_WriteAudioBuffer()
-{
-    JNIEnv *mAudioEnv = Android_JNI_GetEnv();
-
-    if (audioBuffer16Bit) {
-        mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
-        mAudioEnv->CallStaticVoidMethod(mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
-    } else {
-        mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
-        mAudioEnv->CallStaticVoidMethod(mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
-    }
-
-    /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
-}
-
-extern "C" void Android_JNI_CloseAudioDevice()
-{
-    JNIEnv *env = Android_JNI_GetEnv();
-
-    env->CallStaticVoidMethod(mActivityClass, midAudioQuit);
-
-    if (audioBuffer) {
-        env->DeleteGlobalRef(audioBuffer);
-        audioBuffer = NULL;
-        audioBufferPinned = NULL;
-    }
-}
-
-// Test for an exception and call SDL_SetError with its detail if one occurs
-// If optional parameter silent is truthy then SDL_SetError() is not called.
-static bool Android_JNI_ExceptionOccurred(bool silent = false)
-{
-    SDL_assert(LocalReferenceHolder::IsActive());
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-
-    jthrowable exception = mEnv->ExceptionOccurred();
-    if (exception != NULL) {
-        jmethodID mid;
-
-        // Until this happens most JNI operations have undefined behaviour
-        mEnv->ExceptionClear();
-
-        if (!silent) {
-            jclass exceptionClass = mEnv->GetObjectClass(exception);
-            jclass classClass = mEnv->FindClass("java/lang/Class");
-
-            mid = mEnv->GetMethodID(classClass, "getName", "()Ljava/lang/String;");
-            jstring exceptionName = (jstring)mEnv->CallObjectMethod(exceptionClass, mid);
-            const char* exceptionNameUTF8 = mEnv->GetStringUTFChars(exceptionName, 0);
-
-            mid = mEnv->GetMethodID(exceptionClass, "getMessage", "()Ljava/lang/String;");
-            jstring exceptionMessage = (jstring)mEnv->CallObjectMethod(exception, mid);
-
-            if (exceptionMessage != NULL) {
-                const char* exceptionMessageUTF8 = mEnv->GetStringUTFChars(exceptionMessage, 0);
-                SDL_SetError("%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
-                mEnv->ReleaseStringUTFChars(exceptionMessage, exceptionMessageUTF8);
-            } else {
-                SDL_SetError("%s", exceptionNameUTF8);
-            }
-
-            mEnv->ReleaseStringUTFChars(exceptionName, exceptionNameUTF8);
-        }
-
-        return true;
-    }
-
-    return false;
-}
-
-static int Android_JNI_FileOpen(SDL_RWops* ctx)
-{
-    LocalReferenceHolder refs(__FUNCTION__);
-    int result = 0;
-
-    jmethodID mid;
-    jobject context;
-    jobject assetManager;
-    jobject inputStream;
-    jclass channels;
-    jobject readableByteChannel;
-    jstring fileNameJString;
-    jobject fd;
-    jclass fdCls;
-    jfieldID descriptor;
-
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-    if (!refs.init(mEnv)) {
-        goto failure;
-    }
-
-    fileNameJString = (jstring)ctx->hidden.androidio.fileNameRef;
-    ctx->hidden.androidio.position = 0;
-
-    // context = SDLActivity.getContext();
-    mid = mEnv->GetStaticMethodID(mActivityClass,
-            "getContext","()Landroid/content/Context;");
-    context = mEnv->CallStaticObjectMethod(mActivityClass, mid);
-
-
-    // assetManager = context.getAssets();
-    mid = mEnv->GetMethodID(mEnv->GetObjectClass(context),
-            "getAssets", "()Landroid/content/res/AssetManager;");
-    assetManager = mEnv->CallObjectMethod(context, mid);
-
-    /* First let's try opening the file to obtain an AssetFileDescriptor.
-    * This method reads the files directly from the APKs using standard *nix calls
-    */
-    mid = mEnv->GetMethodID(mEnv->GetObjectClass(assetManager), "openFd", "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
-    inputStream = mEnv->CallObjectMethod(assetManager, mid, fileNameJString);
-    if (Android_JNI_ExceptionOccurred(true)) {
-        goto fallback;
-    }
-
-    mid = mEnv->GetMethodID(mEnv->GetObjectClass(inputStream), "getStartOffset", "()J");
-    ctx->hidden.androidio.offset = mEnv->CallLongMethod(inputStream, mid);
-    if (Android_JNI_ExceptionOccurred(true)) {
-        goto fallback;
-    }
-
-    mid = mEnv->GetMethodID(mEnv->GetObjectClass(inputStream), "getDeclaredLength", "()J");
-    ctx->hidden.androidio.size = mEnv->CallLongMethod(inputStream, mid);
-    if (Android_JNI_ExceptionOccurred(true)) {
-        goto fallback;
-    }
-
-    mid = mEnv->GetMethodID(mEnv->GetObjectClass(inputStream), "getFileDescriptor", "()Ljava/io/FileDescriptor;");
-    fd = mEnv->CallObjectMethod(inputStream, mid);
-    fdCls = mEnv->GetObjectClass(fd);
-    descriptor = mEnv->GetFieldID(fdCls, "descriptor", "I");
-    ctx->hidden.androidio.fd = mEnv->GetIntField(fd, descriptor);
-    ctx->hidden.androidio.assetFileDescriptorRef = mEnv->NewGlobalRef(inputStream);
-
-    // Seek to the correct offset in the file.
-    lseek(ctx->hidden.androidio.fd, (off_t)ctx->hidden.androidio.offset, SEEK_SET);
-
-    if (false) {
-fallback:
-        // Disabled log message because of spam on the Nexus 7
-        //__android_log_print(ANDROID_LOG_DEBUG, "SDL", "Falling back to legacy InputStream method for opening file");
-
-        /* Try the old method using InputStream */
-        ctx->hidden.androidio.assetFileDescriptorRef = NULL;
-
-        // inputStream = assetManager.open(<filename>);
-        mid = mEnv->GetMethodID(mEnv->GetObjectClass(assetManager),
-                "open", "(Ljava/lang/String;I)Ljava/io/InputStream;");
-        inputStream = mEnv->CallObjectMethod(assetManager, mid, fileNameJString, 1 /*ACCESS_RANDOM*/);
-        if (Android_JNI_ExceptionOccurred()) {
-            goto failure;
-        }
-
-        ctx->hidden.androidio.inputStreamRef = mEnv->NewGlobalRef(inputStream);
-
-        // Despite all the visible documentation on [Asset]InputStream claiming
-        // that the .available() method is not guaranteed to return the entire file
-        // size, comments in <sdk>/samples/<ver>/ApiDemos/src/com/example/ ...
-        // android/apis/content/ReadAsset.java imply that Android's
-        // AssetInputStream.available() /will/ always return the total file size
-
-        // size = inputStream.available();
-        mid = mEnv->GetMethodID(mEnv->GetObjectClass(inputStream),
-                "available", "()I");
-        ctx->hidden.androidio.size = (long)mEnv->CallIntMethod(inputStream, mid);
-        if (Android_JNI_ExceptionOccurred()) {
-            goto failure;
-        }
-
-        // readableByteChannel = Channels.newChannel(inputStream);
-        channels = mEnv->FindClass("java/nio/channels/Channels");
-        mid = mEnv->GetStaticMethodID(channels,
-                "newChannel",
-                "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
-        readableByteChannel = mEnv->CallStaticObjectMethod(
-                channels, mid, inputStream);
-        if (Android_JNI_ExceptionOccurred()) {
-            goto failure;
-        }
-
-        ctx->hidden.androidio.readableByteChannelRef =
-            mEnv->NewGlobalRef(readableByteChannel);
-
-        // Store .read id for reading purposes
-        mid = mEnv->GetMethodID(mEnv->GetObjectClass(readableByteChannel),
-                "read", "(Ljava/nio/ByteBuffer;)I");
-        ctx->hidden.androidio.readMethod = mid;
-    }
-
-    if (false) {
-failure:
-        result = -1;
-
-        mEnv->DeleteGlobalRef((jobject)ctx->hidden.androidio.fileNameRef);
-
-        if(ctx->hidden.androidio.inputStreamRef != NULL) {
-            mEnv->DeleteGlobalRef((jobject)ctx->hidden.androidio.inputStreamRef);
-        }
-
-        if(ctx->hidden.androidio.readableByteChannelRef != NULL) {
-            mEnv->DeleteGlobalRef((jobject)ctx->hidden.androidio.readableByteChannelRef);
-        }
-
-        if(ctx->hidden.androidio.assetFileDescriptorRef != NULL) {
-            mEnv->DeleteGlobalRef((jobject)ctx->hidden.androidio.assetFileDescriptorRef);
-        }
-
-    }
-
-    return result;
-}
-
-extern "C" int Android_JNI_FileOpen(SDL_RWops* ctx,
-        const char* fileName, const char*)
-{
-    LocalReferenceHolder refs(__FUNCTION__);
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-
-    if (!refs.init(mEnv)) {
-        return -1;
-    }
-
-    if (!ctx) {
-        return -1;
-    }
-
-    jstring fileNameJString = mEnv->NewStringUTF(fileName);
-    ctx->hidden.androidio.fileNameRef = mEnv->NewGlobalRef(fileNameJString);
-    ctx->hidden.androidio.inputStreamRef = NULL;
-    ctx->hidden.androidio.readableByteChannelRef = NULL;
-    ctx->hidden.androidio.readMethod = NULL;
-    ctx->hidden.androidio.assetFileDescriptorRef = NULL;
-
-    return Android_JNI_FileOpen(ctx);
-}
-
-extern "C" size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
-        size_t size, size_t maxnum)
-{
-    LocalReferenceHolder refs(__FUNCTION__);
-
-    if (ctx->hidden.androidio.assetFileDescriptorRef) {
-        size_t bytesMax = size * maxnum;
-        if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && ctx->hidden.androidio.position + bytesMax > ctx->hidden.androidio.size) {
-            bytesMax = ctx->hidden.androidio.size - ctx->hidden.androidio.position;
-        }
-        size_t result = read(ctx->hidden.androidio.fd, buffer, bytesMax );
-        if (result > 0) {
-            ctx->hidden.androidio.position += result;
-            return result / size;
-        }
-        return 0;
-    } else {
-        jlong bytesRemaining = (jlong) (size * maxnum);
-        jlong bytesMax = (jlong) (ctx->hidden.androidio.size -  ctx->hidden.androidio.position);
-        int bytesRead = 0;
-
-        /* Don't read more bytes than those that remain in the file, otherwise we get an exception */
-        if (bytesRemaining >  bytesMax) bytesRemaining = bytesMax;
-
-        JNIEnv *mEnv = Android_JNI_GetEnv();
-        if (!refs.init(mEnv)) {
-            return -1;
-        }
-
-        jobject readableByteChannel = (jobject)ctx->hidden.androidio.readableByteChannelRef;
-        jmethodID readMethod = (jmethodID)ctx->hidden.androidio.readMethod;
-        jobject byteBuffer = mEnv->NewDirectByteBuffer(buffer, bytesRemaining);
-
-        while (bytesRemaining > 0) {
-            // result = readableByteChannel.read(...);
-            int result = mEnv->CallIntMethod(readableByteChannel, readMethod, byteBuffer);
-
-            if (Android_JNI_ExceptionOccurred()) {
-                return 0;
-            }
-
-            if (result < 0) {
-                break;
-            }
-
-            bytesRemaining -= result;
-            bytesRead += result;
-            ctx->hidden.androidio.position += result;
-        }
-        return bytesRead / size;
-    }
-}
-
-extern "C" size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer,
-        size_t size, size_t num)
-{
-    SDL_SetError("Cannot write to Android package filesystem");
-    return 0;
-}
-
-static int Android_JNI_FileClose(SDL_RWops* ctx, bool release)
-{
-    LocalReferenceHolder refs(__FUNCTION__);
-    int result = 0;
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-
-    if (!refs.init(mEnv)) {
-        return SDL_SetError("Failed to allocate enough JVM local references");
-    }
-
-    if (ctx) {
-        if (release) {
-            mEnv->DeleteGlobalRef((jobject)ctx->hidden.androidio.fileNameRef);
-        }
-
-        if (ctx->hidden.androidio.assetFileDescriptorRef) {
-            jobject inputStream = (jobject)ctx->hidden.androidio.assetFileDescriptorRef;
-            jmethodID mid = mEnv->GetMethodID(mEnv->GetObjectClass(inputStream),
-                    "close", "()V");
-            mEnv->CallVoidMethod(inputStream, mid);
-            mEnv->DeleteGlobalRef((jobject)ctx->hidden.androidio.assetFileDescriptorRef);
-            if (Android_JNI_ExceptionOccurred()) {
-                result = -1;
-            }
-        }
-        else {
-            jobject inputStream = (jobject)ctx->hidden.androidio.inputStreamRef;
-
-            // inputStream.close();
-            jmethodID mid = mEnv->GetMethodID(mEnv->GetObjectClass(inputStream),
-                    "close", "()V");
-            mEnv->CallVoidMethod(inputStream, mid);
-            mEnv->DeleteGlobalRef((jobject)ctx->hidden.androidio.inputStreamRef);
-            mEnv->DeleteGlobalRef((jobject)ctx->hidden.androidio.readableByteChannelRef);
-            if (Android_JNI_ExceptionOccurred()) {
-                result = -1;
-            }
-        }
-
-        if (release) {
-            SDL_FreeRW(ctx);
-        }
-    }
-
-    return result;
-}
-
-
-extern "C" Sint64 Android_JNI_FileSize(SDL_RWops* ctx)
-{
-    return ctx->hidden.androidio.size;
-}
-
-extern "C" Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
-{
-    if (ctx->hidden.androidio.assetFileDescriptorRef) {
-        switch (whence) {
-            case RW_SEEK_SET:
-                if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
-                offset += ctx->hidden.androidio.offset;
-                break;
-            case RW_SEEK_CUR:
-                offset += ctx->hidden.androidio.position;
-                if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
-                offset += ctx->hidden.androidio.offset;
-                break;
-            case RW_SEEK_END:
-                offset = ctx->hidden.androidio.offset + ctx->hidden.androidio.size + offset;
-                break;
-            default:
-                return SDL_SetError("Unknown value for 'whence'");
-        }
-        whence = SEEK_SET;
-
-        off_t ret = lseek(ctx->hidden.androidio.fd, (off_t)offset, SEEK_SET);
-        if (ret == -1) return -1;
-        ctx->hidden.androidio.position = ret - ctx->hidden.androidio.offset;
-    } else {
-        Sint64 newPosition;
-
-        switch (whence) {
-            case RW_SEEK_SET:
-                newPosition = offset;
-                break;
-            case RW_SEEK_CUR:
-                newPosition = ctx->hidden.androidio.position + offset;
-                break;
-            case RW_SEEK_END:
-                newPosition = ctx->hidden.androidio.size + offset;
-                break;
-            default:
-                return SDL_SetError("Unknown value for 'whence'");
-        }
-
-        /* Validate the new position */
-        if (newPosition < 0) {
-            return SDL_Error(SDL_EFSEEK);
-        }
-        if (newPosition > ctx->hidden.androidio.size) {
-            newPosition = ctx->hidden.androidio.size;
-        }
-
-        Sint64 movement = newPosition - ctx->hidden.androidio.position;
-        if (movement > 0) {
-            unsigned char buffer[4096];
-
-            // The easy case where we're seeking forwards
-            while (movement > 0) {
-                Sint64 amount = sizeof (buffer);
-                if (amount > movement) {
-                    amount = movement;
-                }
-                size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount);
-                if (result <= 0) {
-                    // Failed to read/skip the required amount, so fail
-                    return -1;
-                }
-
-                movement -= result;
-            }
-
-        } else if (movement < 0) {
-            // We can't seek backwards so we have to reopen the file and seek
-            // forwards which obviously isn't very efficient
-            Android_JNI_FileClose(ctx, false);
-            Android_JNI_FileOpen(ctx);
-            Android_JNI_FileSeek(ctx, newPosition, RW_SEEK_SET);
-        }
-    }
-
-    return ctx->hidden.androidio.position;
-
-}
-
-extern "C" int Android_JNI_FileClose(SDL_RWops* ctx)
-{
-    return Android_JNI_FileClose(ctx, true);
-}
-
-// returns a new global reference which needs to be released later
-static jobject Android_JNI_GetSystemServiceObject(const char* name)
-{
-    LocalReferenceHolder refs(__FUNCTION__);
-    JNIEnv* env = Android_JNI_GetEnv();
-    if (!refs.init(env)) {
-        return NULL;
-    }
-
-    jstring service = env->NewStringUTF(name);
-
-    jmethodID mid;
-
-    mid = env->GetStaticMethodID(mActivityClass, "getContext", "()Landroid/content/Context;");
-    jobject context = env->CallStaticObjectMethod(mActivityClass, mid);
-
-    mid = env->GetMethodID(mActivityClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
-    jobject manager = env->CallObjectMethod(context, mid, service);
-
-    env->DeleteLocalRef(service);
-
-    return manager ? env->NewGlobalRef(manager) : NULL;
-}
-
-#define SETUP_CLIPBOARD(error) \
-    LocalReferenceHolder refs(__FUNCTION__); \
-    JNIEnv* env = Android_JNI_GetEnv(); \
-    if (!refs.init(env)) { \
-        return error; \
-    } \
-    jobject clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \
-    if (!clipboard) { \
-        return error; \
-    }
-
-extern "C" int Android_JNI_SetClipboardText(const char* text)
-{
-    SETUP_CLIPBOARD(-1)
-
-    jmethodID mid = env->GetMethodID(env->GetObjectClass(clipboard), "setText", "(Ljava/lang/CharSequence;)V");
-    jstring string = env->NewStringUTF(text);
-    env->CallVoidMethod(clipboard, mid, string);
-    env->DeleteGlobalRef(clipboard);
-    env->DeleteLocalRef(string);
-    return 0;
-}
-
-extern "C" char* Android_JNI_GetClipboardText()
-{
-    SETUP_CLIPBOARD(SDL_strdup(""))
-
-    jmethodID mid = env->GetMethodID(env->GetObjectClass(clipboard), "getText", "()Ljava/lang/CharSequence;");
-    jobject sequence = env->CallObjectMethod(clipboard, mid);
-    env->DeleteGlobalRef(clipboard);
-    if (sequence) {
-        mid = env->GetMethodID(env->GetObjectClass(sequence), "toString", "()Ljava/lang/String;");
-        jstring string = reinterpret_cast<jstring>(env->CallObjectMethod(sequence, mid));
-        const char* utf = env->GetStringUTFChars(string, 0);
-        if (utf) {
-            char* text = SDL_strdup(utf);
-            env->ReleaseStringUTFChars(string, utf);
-            return text;
-        }
-    }
-    return SDL_strdup("");
-}
-
-extern "C" SDL_bool Android_JNI_HasClipboardText()
-{
-    SETUP_CLIPBOARD(SDL_FALSE)
-
-    jmethodID mid = env->GetMethodID(env->GetObjectClass(clipboard), "hasText", "()Z");
-    jboolean has = env->CallBooleanMethod(clipboard, mid);
-    env->DeleteGlobalRef(clipboard);
-    return has ? SDL_TRUE : SDL_FALSE;
-}
-
-
-// returns 0 on success or -1 on error (others undefined then)
-// returns truthy or falsy value in plugged, charged and battery
-// returns the value in seconds and percent or -1 if not available
-extern "C" int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent)
-{
-    LocalReferenceHolder refs(__FUNCTION__);
-    JNIEnv* env = Android_JNI_GetEnv();
-    if (!refs.init(env)) {
-        return -1;
-    }
-
-    jmethodID mid;
-
-    mid = env->GetStaticMethodID(mActivityClass, "getContext", "()Landroid/content/Context;");
-    jobject context = env->CallStaticObjectMethod(mActivityClass, mid);
-
-    jstring action = env->NewStringUTF("android.intent.action.BATTERY_CHANGED");
-
-    jclass cls = env->FindClass("android/content/IntentFilter");
-
-    mid = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;)V");
-    jobject filter = env->NewObject(cls, mid, action);
-
-    env->DeleteLocalRef(action);
-
-    mid = env->GetMethodID(mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
-    jobject intent = env->CallObjectMethod(context, mid, NULL, filter);
-
-    env->DeleteLocalRef(filter);
-
-    cls = env->GetObjectClass(intent);
-
-    jstring iname;
-    jmethodID imid = env->GetMethodID(cls, "getIntExtra", "(Ljava/lang/String;I)I");
-
-#define GET_INT_EXTRA(var, key) \
-    iname = env->NewStringUTF(key); \
-    int var = env->CallIntMethod(intent, imid, iname, -1); \
-    env->DeleteLocalRef(iname);
-
-    jstring bname;
-    jmethodID bmid = env->GetMethodID(cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z");
-
-#define GET_BOOL_EXTRA(var, key) \
-    bname = env->NewStringUTF(key); \
-    int var = env->CallBooleanMethod(intent, bmid, bname, JNI_FALSE); \
-    env->DeleteLocalRef(bname);
-
-    if (plugged) {
-        GET_INT_EXTRA(plug, "plugged") // == BatteryManager.EXTRA_PLUGGED (API 5)
-        if (plug == -1) {
-            return -1;
-        }
-        // 1 == BatteryManager.BATTERY_PLUGGED_AC
-        // 2 == BatteryManager.BATTERY_PLUGGED_USB
-        *plugged = (0 < plug) ? 1 : 0;
-    }
-
-    if (charged) {
-        GET_INT_EXTRA(status, "status") // == BatteryManager.EXTRA_STATUS (API 5)
-        if (status == -1) {
-            return -1;
-        }
-        // 5 == BatteryManager.BATTERY_STATUS_FULL
-        *charged = (status == 5) ? 1 : 0;
-    }
-
-    if (battery) {
-        GET_BOOL_EXTRA(present, "present") // == BatteryManager.EXTRA_PRESENT (API 5)
-        *battery = present ? 1 : 0;
-    }
-
-    if (seconds) {
-        *seconds = -1; // not possible
-    }
-
-    if (percent) {
-        GET_INT_EXTRA(level, "level") // == BatteryManager.EXTRA_LEVEL (API 5)
-        GET_INT_EXTRA(scale, "scale") // == BatteryManager.EXTRA_SCALE (API 5)
-        if ((level == -1) || (scale == -1)) {
-            return -1;
-        }
-        *percent = level * 100 / scale;
-    }
-
-    env->DeleteLocalRef(intent);
-
-    return 0;
-}
-
-// sends message to be handled on the UI event dispatch thread
-extern "C" int Android_JNI_SendMessage(int command, int param)
-{
-    JNIEnv *env = Android_JNI_GetEnv();
-    if (!env) {
-        return -1;
-    }
-    jmethodID mid = env->GetStaticMethodID(mActivityClass, "sendMessage", "(II)Z");
-    if (!mid) {
-        return -1;
-    }
-    jboolean success = env->CallStaticBooleanMethod(mActivityClass, mid, command, param);
-    return success ? 0 : -1;
-}
-
-extern "C" void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
-{
-    JNIEnv *env = Android_JNI_GetEnv();
-    if (!env) {
-        return;
-    }
-
-    jmethodID mid = env->GetStaticMethodID(mActivityClass, "showTextInput", "(IIII)Z");
-    if (!mid) {
-        return;
-    }
-    env->CallStaticBooleanMethod( mActivityClass, mid,
-                               inputRect->x,
-                               inputRect->y,
-                               inputRect->w,
-                               inputRect->h );
-}
-
-extern "C" void Android_JNI_HideTextInput()
-{
-    // has to match Activity constant
-    const int COMMAND_TEXTEDIT_HIDE = 3;
-    Android_JNI_SendMessage(COMMAND_TEXTEDIT_HIDE, 0);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Functions exposed to SDL applications in SDL_system.h
-//
-
-extern "C" void *SDL_AndroidGetJNIEnv()
-{
-    return Android_JNI_GetEnv();
-}
-
-
-
-extern "C" void *SDL_AndroidGetActivity()
-{
-    /* See SDL_system.h for caveats on using this function. */
-
-    jmethodID mid;
-
-    JNIEnv *env = Android_JNI_GetEnv();
-    if (!env) {
-        return NULL;
-    }
-
-    // return SDLActivity.getContext();
-    mid = env->GetStaticMethodID(mActivityClass,
-            "getContext","()Landroid/content/Context;");
-    return env->CallStaticObjectMethod(mActivityClass, mid);
-}
-
-extern "C" const char * SDL_AndroidGetInternalStoragePath()
-{
-    static char *s_AndroidInternalFilesPath = NULL;
-
-    if (!s_AndroidInternalFilesPath) {
-        LocalReferenceHolder refs(__FUNCTION__);
-        jmethodID mid;
-        jobject context;
-        jobject fileObject;
-        jstring pathString;
-        const char *path;
-
-        JNIEnv *env = Android_JNI_GetEnv();
-        if (!refs.init(env)) {
-            return NULL;
-        }
-
-        // context = SDLActivity.getContext();
-        mid = env->GetStaticMethodID(mActivityClass,
-                "getContext","()Landroid/content/Context;");
-        context = env->CallStaticObjectMethod(mActivityClass, mid);
-
-        // fileObj = context.getFilesDir();
-        mid = env->GetMethodID(env->GetObjectClass(context),
-                "getFilesDir", "()Ljava/io/File;");
-        fileObject = env->CallObjectMethod(context, mid);
-        if (!fileObject) {
-            SDL_SetError("Couldn't get internal directory");
-            return NULL;
-        }
-
-        // path = fileObject.getAbsolutePath();
-        mid = env->GetMethodID(env->GetObjectClass(fileObject),
-                "getAbsolutePath", "()Ljava/lang/String;");
-        pathString = (jstring)env->CallObjectMethod(fileObject, mid);
-
-        path = env->GetStringUTFChars(pathString, NULL);
-        s_AndroidInternalFilesPath = SDL_strdup(path);
-        env->ReleaseStringUTFChars(pathString, path);
-    }
-    return s_AndroidInternalFilesPath;
-}
-
-extern "C" int SDL_AndroidGetExternalStorageState()
-{
-    LocalReferenceHolder refs(__FUNCTION__);
-    jmethodID mid;
-    jclass cls;
-    jstring stateString;
-    const char *state;
-    int stateFlags;
-
-    JNIEnv *env = Android_JNI_GetEnv();
-    if (!refs.init(env)) {
-        return 0;
-    }
-
-    cls = env->FindClass("android/os/Environment");
-    mid = env->GetStaticMethodID(cls,
-            "getExternalStorageState", "()Ljava/lang/String;");
-    stateString = (jstring)env->CallStaticObjectMethod(cls, mid);
-
-    state = env->GetStringUTFChars(stateString, NULL);
-
-    // Print an info message so people debugging know the storage state
-    __android_log_print(ANDROID_LOG_INFO, "SDL", "external storage state: %s", state);
-
-    if (SDL_strcmp(state, "mounted") == 0) {
-        stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ |
-                     SDL_ANDROID_EXTERNAL_STORAGE_WRITE;
-    } else if (SDL_strcmp(state, "mounted_ro") == 0) {
-        stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ;
-    } else {
-        stateFlags = 0;
-    }
-    env->ReleaseStringUTFChars(stateString, state);
-
-    return stateFlags;
-}
-
-extern "C" const char * SDL_AndroidGetExternalStoragePath()
-{
-    static char *s_AndroidExternalFilesPath = NULL;
-
-    if (!s_AndroidExternalFilesPath) {
-        LocalReferenceHolder refs(__FUNCTION__);
-        jmethodID mid;
-        jobject context;
-        jobject fileObject;
-        jstring pathString;
-        const char *path;
-
-        JNIEnv *env = Android_JNI_GetEnv();
-        if (!refs.init(env)) {
-            return NULL;
-        }
-
-        // context = SDLActivity.getContext();
-        mid = env->GetStaticMethodID(mActivityClass,
-                "getContext","()Landroid/content/Context;");
-        context = env->CallStaticObjectMethod(mActivityClass, mid);
-
-        // fileObj = context.getExternalFilesDir();
-        mid = env->GetMethodID(env->GetObjectClass(context),
-                "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
-        fileObject = env->CallObjectMethod(context, mid, NULL);
-        if (!fileObject) {
-            SDL_SetError("Couldn't get external directory");
-            return NULL;
-        }
-
-        // path = fileObject.getAbsolutePath();
-        mid = env->GetMethodID(env->GetObjectClass(fileObject),
-                "getAbsolutePath", "()Ljava/lang/String;");
-        pathString = (jstring)env->CallObjectMethod(fileObject, mid);
-
-        path = env->GetStringUTFChars(pathString, NULL);
-        s_AndroidExternalFilesPath = SDL_strdup(path);
-        env->ReleaseStringUTFChars(pathString, path);
-    }
-    return s_AndroidExternalFilesPath;
-}
-
-#endif /* __ANDROID__ */
-
-/* vi: set ts=4 sw=4 expandtab: */
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+// Modified by Lasse Oorni for Urho3D
+
+#include "SDL_config.h"
+#include "SDL_stdinc.h"
+#include "SDL_assert.h"
+#include "SDL_log.h"
+
+#ifdef __ANDROID__
+
+#include "SDL_system.h"
+#include "SDL_android.h"
+// Urho3D: do not require EGL to allow compiling on API level 8
+// #include <EGL/egl.h>
+#define EGL_BUFFER_SIZE			0x3020
+#define EGL_ALPHA_SIZE			0x3021
+#define EGL_BLUE_SIZE			0x3022
+#define EGL_GREEN_SIZE			0x3023
+#define EGL_RED_SIZE			0x3024
+#define EGL_DEPTH_SIZE			0x3025
+#define EGL_STENCIL_SIZE		0x3026
+#define EGL_SAMPLES			0x3031
+#define EGL_SAMPLE_BUFFERS		0x3032
+#define EGL_RENDERABLE_TYPE		0x3040
+#define EGL_OPENGL_ES_BIT		0x0001	/* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_OPENGL_ES2_BIT		0x0004	/* EGL_RENDERABLE_TYPE mask bits */
+#define EGL_NONE			0x3038	/* Attrib list terminator */
+
+#include "../../events/SDL_events_c.h"
+#include "../../video/android/SDL_androidkeyboard.h"
+#include "../../video/android/SDL_androidtouch.h"
+#include "../../video/android/SDL_androidvideo.h"
+
+#include <android/log.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <unistd.h>
+#define LOG_TAG "SDL_android"
+//#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+//#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+#define LOGI(...) do {} while (false)
+#define LOGE(...) do {} while (false)
+
+/* Uncomment this to log messages entering and exiting methods in this file */
+//#define DEBUG_JNI
+
+static void Android_JNI_ThreadDestroyed(void*);
+
+/*******************************************************************************
+ This file links the Java side of Android with libsdl
+*******************************************************************************/
+#include <jni.h>
+#include <android/log.h>
+#include <stdbool.h>
+
+
+/*******************************************************************************
+                               Globals
+*******************************************************************************/
+static pthread_key_t mThreadKey;
+static JavaVM* mJavaVM;
+
+// Main activity
+static jclass mActivityClass;
+
+// method signatures
+static jmethodID midCreateGLContext;
+static jmethodID midDeleteGLContext;
+static jmethodID midFlipBuffers;
+static jmethodID midAudioInit;
+static jmethodID midAudioWriteShortBuffer;
+static jmethodID midAudioWriteByteBuffer;
+static jmethodID midAudioQuit;
+
+// Accelerometer data storage
+static float fLastAccelerometer[3];
+static bool bHasNewData;
+
+// Urho3D: application files dir
+static char* mFilesDir = 0;
+
+/*******************************************************************************
+                 Functions called by JNI
+*******************************************************************************/
+
+// Library init
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    JNIEnv *env;
+    mJavaVM = vm;
+    LOGI("JNI_OnLoad called");
+    if ((*mJavaVM)->GetEnv(mJavaVM, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        LOGE("Failed to get the environment using GetEnv()");
+        return -1;
+    }
+    /*
+     * Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
+     * Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
+     */
+    if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed)) {
+        __android_log_print(ANDROID_LOG_ERROR, "SDL", "Error initializing pthread key");
+    }
+    else {
+        Android_JNI_SetupThread();
+    }
+
+    return JNI_VERSION_1_4;
+}
+
+// Urho3D: added function
+const char* SDL_Android_GetFilesDir()
+{
+    return mFilesDir;
+}
+
+// Called before SDL_main() to initialize JNI bindings
+// Urho3D: added passing user files directory from SDLActivity on startup
+void SDL_Android_Init(JNIEnv* mEnv, jclass cls, jstring filesDir)
+{
+    __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init()");
+
+    Android_JNI_SetupThread();
+
+    // Copy the files dir
+    const char *str;
+    str = (*mEnv)->GetStringUTFChars(mEnv, filesDir, 0);
+    if (str)
+    {
+        if (mFilesDir)
+            free(mFilesDir);
+
+        size_t length = strlen(str) + 1;
+        mFilesDir = (char*)malloc(length);
+        memcpy(mFilesDir, str, length);
+        (*mEnv)->ReleaseStringUTFChars(mEnv, filesDir, str);
+    }
+
+    mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
+
+    midCreateGLContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "createGLContext","(II[I)Z");
+    midDeleteGLContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "deleteGLContext","()V");
+    midFlipBuffers = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "flipBuffers","()V");
+    midAudioInit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "audioInit", "(IZZI)I");
+    midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "audioWriteShortBuffer", "([S)V");
+    midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "audioWriteByteBuffer", "([B)V");
+    midAudioQuit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "audioQuit", "()V");
+
+    bHasNewData = false;
+
+    if(!midCreateGLContext || !midFlipBuffers || !midAudioInit ||
+       !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) {
+        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
+    }
+    __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init() finished!");
+}
+
+// Urho3D: moved function here due to link error
+// Start up the SDL app
+void Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jstring filesDir)
+{
+    /* This interface could expand with ABI negotiation, callbacks, etc. */
+    SDL_Android_Init(env, cls, filesDir);
+
+    SDL_SetMainReady();
+
+    /* Run the application code! */
+    int status;
+    char *argv[2];
+    argv[0] = SDL_strdup("SDL_app");
+    argv[1] = NULL;
+    status = SDL_main(1, argv);
+
+    /* Do not issue an exit or the whole application will terminate instead of just the SDL thread */
+    //exit(status);
+}
+
+// Resize
+void Java_org_libsdl_app_SDLActivity_onNativeResize(
+                                    JNIEnv* env, jclass jcls,
+                                    jint width, jint height, jint format)
+{
+    Android_SetScreenResolution(width, height, format);
+}
+
+// Keydown
+void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
+                                    JNIEnv* env, jclass jcls, jint keycode)
+{
+    Android_OnKeyDown(keycode);
+}
+
+// Keyup
+void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
+                                    JNIEnv* env, jclass jcls, jint keycode)
+{
+    Android_OnKeyUp(keycode);
+}
+
+// Keyboard Focus Lost
+void Java_org_libsdl_app_SDLActivity_onNativeKeyboardFocusLost(
+                                    JNIEnv* env, jclass jcls)
+{
+    /* Calling SDL_StopTextInput will take care of hiding the keyboard and cleaning up the DummyText widget */
+    SDL_StopTextInput();
+}
+
+
+// Touch
+void Java_org_libsdl_app_SDLActivity_onNativeTouch(
+                                    JNIEnv* env, jclass jcls,
+                                    jint touch_device_id_in, jint pointer_finger_id_in,
+                                    jint action, jfloat x, jfloat y, jfloat p)
+{
+    Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
+}
+
+// Accelerometer
+void Java_org_libsdl_app_SDLActivity_onNativeAccel(
+                                    JNIEnv* env, jclass jcls,
+                                    jfloat x, jfloat y, jfloat z)
+{
+    fLastAccelerometer[0] = x;
+    fLastAccelerometer[1] = y;
+    fLastAccelerometer[2] = z;
+    bHasNewData = true;
+}
+
+// Low memory
+void Java_org_libsdl_app_SDLActivity_nativeLowMemory(
+                                    JNIEnv* env, jclass cls)
+{
+    SDL_SendAppEvent(SDL_APP_LOWMEMORY);
+}
+
+// Quit
+void Java_org_libsdl_app_SDLActivity_nativeQuit(
+                                    JNIEnv* env, jclass cls)
+{
+    // Inject a SDL_QUIT event
+    SDL_SendQuit();
+    SDL_SendAppEvent(SDL_APP_TERMINATING);
+}
+
+// Pause
+void Java_org_libsdl_app_SDLActivity_nativePause(
+                                    JNIEnv* env, jclass cls)
+{
+    if (Android_Window) {
+        /* Signal the pause semaphore so the event loop knows to pause and (optionally) block itself */
+        if (!SDL_SemValue(Android_PauseSem)) SDL_SemPost(Android_PauseSem);
+        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
+        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
+    }
+
+    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativePause()");
+    SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
+    SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
+}
+
+// Resume
+void Java_org_libsdl_app_SDLActivity_nativeResume(
+                                    JNIEnv* env, jclass cls)
+{
+    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeResume()");
+    SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
+    SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
+
+    if (Android_Window) {
+        /* Signal the resume semaphore so the event loop knows to resume and restore the GL Context
+         * We can't restore the GL Context here because it needs to be done on the SDL main thread
+         * and this function will be called from the Java thread instead.
+         */
+        if (!SDL_SemValue(Android_ResumeSem)) SDL_SemPost(Android_ResumeSem);
+        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
+        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
+    }
+}
+
+void Java_org_libsdl_app_SDLInputConnection_nativeCommitText(
+                                    JNIEnv* env, jclass cls,
+                                    jstring text, jint newCursorPosition)
+{
+    const char *utftext = (*env)->GetStringUTFChars(env, text, NULL);
+
+    SDL_SendKeyboardText(utftext);
+
+    (*env)->ReleaseStringUTFChars(env, text, utftext);
+}
+
+void Java_org_libsdl_app_SDLInputConnection_nativeSetComposingText(
+                                    JNIEnv* env, jclass cls,
+                                    jstring text, jint newCursorPosition)
+{
+    const char *utftext = (*env)->GetStringUTFChars(env, text, NULL);
+
+    SDL_SendEditingText(utftext, 0, 0);
+
+    (*env)->ReleaseStringUTFChars(env, text, utftext);
+}
+
+
+
+/*******************************************************************************
+             Functions called by SDL into Java
+*******************************************************************************/
+
+static int s_active = 0;
+struct LocalReferenceHolder
+{
+    JNIEnv *m_env;
+    const char *m_func;
+};
+
+static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *func)
+{
+    struct LocalReferenceHolder refholder;
+    refholder.m_env = NULL;
+    refholder.m_func = func;
+#ifdef DEBUG_JNI
+    SDL_Log("Entering function %s", func);
+#endif
+    return refholder;
+}
+
+static SDL_bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env)
+{
+    const int capacity = 16;
+    if ((*env)->PushLocalFrame(env, capacity) < 0) {
+        SDL_SetError("Failed to allocate enough JVM local references");
+        return SDL_FALSE;
+    }
+    ++s_active;
+    refholder->m_env = env;
+    return SDL_TRUE;
+}
+
+static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder)
+{
+#ifdef DEBUG_JNI
+    SDL_Log("Leaving function %s", refholder->m_func);
+#endif
+    if (refholder->m_env) {
+        JNIEnv* env = refholder->m_env;
+        (*env)->PopLocalFrame(env, NULL);
+        --s_active;
+    }
+}
+
+static SDL_bool LocalReferenceHolder_IsActive()
+{
+    return s_active > 0;    
+}
+
+
+SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion,
+                                int red, int green, int blue, int alpha,
+                                int buffer, int depth, int stencil,
+                                int buffers, int samples)
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+
+    jint attribs[] = {
+        EGL_RED_SIZE, red,
+        EGL_GREEN_SIZE, green,
+        EGL_BLUE_SIZE, blue,
+        EGL_ALPHA_SIZE, alpha,
+        EGL_BUFFER_SIZE, buffer,
+        EGL_DEPTH_SIZE, depth,
+        EGL_STENCIL_SIZE, stencil,
+        EGL_SAMPLE_BUFFERS, buffers,
+        EGL_SAMPLES, samples,
+        EGL_RENDERABLE_TYPE, (majorVersion == 1 ? EGL_OPENGL_ES_BIT : EGL_OPENGL_ES2_BIT),
+        EGL_NONE
+    };
+    int len = SDL_arraysize(attribs);
+
+    jintArray array;
+
+    array = (*env)->NewIntArray(env, len);
+    (*env)->SetIntArrayRegion(env, array, 0, len, attribs);
+
+    jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass, midCreateGLContext, majorVersion, minorVersion, array);
+
+    (*env)->DeleteLocalRef(env, array);
+
+    return success ? SDL_TRUE : SDL_FALSE;
+}
+
+SDL_bool Android_JNI_DeleteContext(void)
+{
+    /* There's only one context, so no parameter for now */
+    JNIEnv *env = Android_JNI_GetEnv();
+    (*env)->CallStaticVoidMethod(env, mActivityClass, midDeleteGLContext);
+    return SDL_TRUE;
+}
+
+void Android_JNI_SwapWindow()
+{
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, midFlipBuffers);
+}
+
+void Android_JNI_SetActivityTitle(const char *title)
+{
+    jmethodID mid;
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,"setActivityTitle","(Ljava/lang/String;)Z");
+    if (mid) {
+        jstring jtitle = (jstring)((*mEnv)->NewStringUTF(mEnv, title));
+        (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, mid, jtitle);
+        (*mEnv)->DeleteLocalRef(mEnv, jtitle);
+    }
+}
+
+SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
+{
+    int i;
+    SDL_bool retval = SDL_FALSE;
+
+    if (bHasNewData) {
+        for (i = 0; i < 3; ++i) {
+            values[i] = fLastAccelerometer[i];
+        }
+        bHasNewData = false;
+        retval = SDL_TRUE;
+    }
+
+    return retval;
+}
+
+static void Android_JNI_ThreadDestroyed(void* value) {
+    /* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
+    JNIEnv *env = (JNIEnv*) value;
+    if (env != NULL) {
+        (*mJavaVM)->DetachCurrentThread(mJavaVM);
+        pthread_setspecific(mThreadKey, NULL);
+    }
+}
+
+JNIEnv* Android_JNI_GetEnv(void) {
+    /* From http://developer.android.com/guide/practices/jni.html
+     * All threads are Linux threads, scheduled by the kernel.
+     * They're usually started from managed code (using Thread.start), but they can also be created elsewhere and then
+     * attached to the JavaVM. For example, a thread started with pthread_create can be attached with the
+     * JNI AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a thread is attached, it has no JNIEnv,
+     * and cannot make JNI calls.
+     * Attaching a natively-created thread causes a java.lang.Thread object to be constructed and added to the "main"
+     * ThreadGroup, making it visible to the debugger. Calling AttachCurrentThread on an already-attached thread
+     * is a no-op.
+     * Note: You can call this function any number of times for the same thread, there's no harm in it
+     */
+
+    JNIEnv *env;
+    int status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env, NULL);
+    if(status < 0) {
+        LOGE("failed to attach current thread");
+        return 0;
+    }
+
+    return env;
+}
+
+int Android_JNI_SetupThread(void) {
+    /* From http://developer.android.com/guide/practices/jni.html
+     * Threads attached through JNI must call DetachCurrentThread before they exit. If coding this directly is awkward,
+     * in Android 2.0 (Eclair) and higher you can use pthread_key_create to define a destructor function that will be
+     * called before the thread exits, and call DetachCurrentThread from there. (Use that key with pthread_setspecific
+     * to store the JNIEnv in thread-local-storage; that way it'll be passed into your destructor as the argument.)
+     * Note: The destructor is not called unless the stored value is != NULL
+     * Note: You can call this function any number of times for the same thread, there's no harm in it
+     *       (except for some lost CPU cycles)
+     */
+    JNIEnv *env = Android_JNI_GetEnv();
+    pthread_setspecific(mThreadKey, (void*) env);
+    return 1;
+}
+
+//
+// Audio support
+//
+static jboolean audioBuffer16Bit = JNI_FALSE;
+static jboolean audioBufferStereo = JNI_FALSE;
+static jobject audioBuffer = NULL;
+static void* audioBufferPinned = NULL;
+
+int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
+{
+    int audioBufferFrames;
+
+    JNIEnv *env = Android_JNI_GetEnv();
+
+    if (!env) {
+        LOGE("callback_handler: failed to attach current thread");
+    }
+    Android_JNI_SetupThread();
+
+    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
+    audioBuffer16Bit = is16Bit;
+    audioBufferStereo = channelCount > 1;
+
+    if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
+        /* Error during audio initialization */
+        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioTrack initialization!");
+        return 0;
+    }
+
+    /* Allocating the audio buffer from the Java side and passing it as the return value for audioInit no longer works on
+     * Android >= 4.2 due to a "stale global reference" error. So now we allocate this buffer directly from this side. */
+
+    if (is16Bit) {
+        jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
+        if (audioBufferLocal) {
+            audioBuffer = (*env)->NewGlobalRef(env, audioBufferLocal);
+            (*env)->DeleteLocalRef(env, audioBufferLocal);
+        }
+    }
+    else {
+        jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
+        if (audioBufferLocal) {
+            audioBuffer = (*env)->NewGlobalRef(env, audioBufferLocal);
+            (*env)->DeleteLocalRef(env, audioBufferLocal);
+        }
+    }
+
+    if (audioBuffer == NULL) {
+        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer!");
+        return 0;
+    }
+
+    jboolean isCopy = JNI_FALSE;
+    if (audioBuffer16Bit) {
+        audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
+        audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
+    } else {
+        audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
+        audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
+    }
+    if (audioBufferStereo) {
+        audioBufferFrames /= 2;
+    }
+
+    return audioBufferFrames;
+}
+
+void * Android_JNI_GetAudioBuffer()
+{
+    return audioBufferPinned;
+}
+
+void Android_JNI_WriteAudioBuffer()
+{
+    JNIEnv *mAudioEnv = Android_JNI_GetEnv();
+
+    if (audioBuffer16Bit) {
+        (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
+        (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
+    } else {
+        (*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
+        (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
+    }
+
+    /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
+}
+
+void Android_JNI_CloseAudioDevice()
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+
+    (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioQuit);
+
+    if (audioBuffer) {
+        (*env)->DeleteGlobalRef(env, audioBuffer);
+        audioBuffer = NULL;
+        audioBufferPinned = NULL;
+    }
+}
+
+// Test for an exception and call SDL_SetError with its detail if one occurs
+// If the parameter silent is truthy then SDL_SetError() will not be called.
+static bool Android_JNI_ExceptionOccurred(bool silent)
+{
+    SDL_assert(LocalReferenceHolder_IsActive());
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+
+    jthrowable exception = (*mEnv)->ExceptionOccurred(mEnv);
+    if (exception != NULL) {
+        jmethodID mid;
+
+        // Until this happens most JNI operations have undefined behaviour
+        (*mEnv)->ExceptionClear(mEnv);
+
+        if (!silent) {
+            jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
+            jclass classClass = (*mEnv)->FindClass(mEnv, "java/lang/Class");
+
+            mid = (*mEnv)->GetMethodID(mEnv, classClass, "getName", "()Ljava/lang/String;");
+            jstring exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
+            const char* exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
+
+            mid = (*mEnv)->GetMethodID(mEnv, exceptionClass, "getMessage", "()Ljava/lang/String;");
+            jstring exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
+
+            if (exceptionMessage != NULL) {
+                const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
+                SDL_SetError("%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
+                (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionMessage, exceptionMessageUTF8);
+            } else {
+                SDL_SetError("%s", exceptionNameUTF8);
+            }
+
+            (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionName, exceptionNameUTF8);
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+static int Internal_Android_JNI_FileOpen(SDL_RWops* ctx)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+
+    int result = 0;
+
+    jmethodID mid;
+    jobject context;
+    jobject assetManager;
+    jobject inputStream;
+    jclass channels;
+    jobject readableByteChannel;
+    jstring fileNameJString;
+    jobject fd;
+    jclass fdCls;
+    jfieldID descriptor;
+
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    if (!LocalReferenceHolder_Init(&refs, mEnv)) {
+        goto failure;
+    }
+
+    fileNameJString = (jstring)ctx->hidden.androidio.fileNameRef;
+    ctx->hidden.androidio.position = 0;
+
+    // context = SDLActivity.getContext();
+    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+            "getContext","()Landroid/content/Context;");
+    context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, mid);
+
+
+    // assetManager = context.getAssets();
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
+            "getAssets", "()Landroid/content/res/AssetManager;");
+    assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
+
+    /* First let's try opening the file to obtain an AssetFileDescriptor.
+    * This method reads the files directly from the APKs using standard *nix calls
+    */
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager), "openFd", "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
+    inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString);
+    if (Android_JNI_ExceptionOccurred(true)) {
+        goto fallback;
+    }
+
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getStartOffset", "()J");
+    ctx->hidden.androidio.offset = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
+    if (Android_JNI_ExceptionOccurred(true)) {
+        goto fallback;
+    }
+
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getDeclaredLength", "()J");
+    ctx->hidden.androidio.size = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
+    if (Android_JNI_ExceptionOccurred(true)) {
+        goto fallback;
+    }
+
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getFileDescriptor", "()Ljava/io/FileDescriptor;");
+    fd = (*mEnv)->CallObjectMethod(mEnv, inputStream, mid);
+    fdCls = (*mEnv)->GetObjectClass(mEnv, fd);
+    descriptor = (*mEnv)->GetFieldID(mEnv, fdCls, "descriptor", "I");
+    ctx->hidden.androidio.fd = (*mEnv)->GetIntField(mEnv, fd, descriptor);
+    ctx->hidden.androidio.assetFileDescriptorRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
+
+    // Seek to the correct offset in the file.
+    lseek(ctx->hidden.androidio.fd, (off_t)ctx->hidden.androidio.offset, SEEK_SET);
+
+    if (false) {
+fallback:
+        // Disabled log message because of spam on the Nexus 7
+        //__android_log_print(ANDROID_LOG_DEBUG, "SDL", "Falling back to legacy InputStream method for opening file");
+
+        /* Try the old method using InputStream */
+        ctx->hidden.androidio.assetFileDescriptorRef = NULL;
+
+        // inputStream = assetManager.open(<filename>);
+        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
+                "open", "(Ljava/lang/String;I)Ljava/io/InputStream;");
+        inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 /*ACCESS_RANDOM*/);
+        if (Android_JNI_ExceptionOccurred(false)) {
+            goto failure;
+        }
+
+        ctx->hidden.androidio.inputStreamRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
+
+        // Despite all the visible documentation on [Asset]InputStream claiming
+        // that the .available() method is not guaranteed to return the entire file
+        // size, comments in <sdk>/samples/<ver>/ApiDemos/src/com/example/ ...
+        // android/apis/content/ReadAsset.java imply that Android's
+        // AssetInputStream.available() /will/ always return the total file size
+
+        // size = inputStream.available();
+        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
+                "available", "()I");
+        ctx->hidden.androidio.size = (long)(*mEnv)->CallIntMethod(mEnv, inputStream, mid);
+        if (Android_JNI_ExceptionOccurred(false)) {
+            goto failure;
+        }
+
+        // readableByteChannel = Channels.newChannel(inputStream);
+        channels = (*mEnv)->FindClass(mEnv, "java/nio/channels/Channels");
+        mid = (*mEnv)->GetStaticMethodID(mEnv, channels,
+                "newChannel",
+                "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
+        readableByteChannel = (*mEnv)->CallStaticObjectMethod(
+                mEnv, channels, mid, inputStream);
+        if (Android_JNI_ExceptionOccurred(false)) {
+            goto failure;
+        }
+
+        ctx->hidden.androidio.readableByteChannelRef =
+            (*mEnv)->NewGlobalRef(mEnv, readableByteChannel);
+
+        // Store .read id for reading purposes
+        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, readableByteChannel),
+                "read", "(Ljava/nio/ByteBuffer;)I");
+        ctx->hidden.androidio.readMethod = mid;
+    }
+
+    if (false) {
+failure:
+        result = -1;
+
+        (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.fileNameRef);
+
+        if(ctx->hidden.androidio.inputStreamRef != NULL) {
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.inputStreamRef);
+        }
+
+        if(ctx->hidden.androidio.readableByteChannelRef != NULL) {
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.readableByteChannelRef);
+        }
+
+        if(ctx->hidden.androidio.assetFileDescriptorRef != NULL) {
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.assetFileDescriptorRef);
+        }
+
+    }
+    
+    LocalReferenceHolder_Cleanup(&refs);
+    return result;
+}
+
+int Android_JNI_FileOpen(SDL_RWops* ctx,
+        const char* fileName, const char* mode)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    int retval;
+
+    if (!LocalReferenceHolder_Init(&refs, mEnv)) {
+        LocalReferenceHolder_Cleanup(&refs);        
+        return -1;
+    }
+
+    if (!ctx) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return -1;
+    }
+
+    jstring fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
+    ctx->hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
+    ctx->hidden.androidio.inputStreamRef = NULL;
+    ctx->hidden.androidio.readableByteChannelRef = NULL;
+    ctx->hidden.androidio.readMethod = NULL;
+    ctx->hidden.androidio.assetFileDescriptorRef = NULL;
+
+    retval = Internal_Android_JNI_FileOpen(ctx);
+    LocalReferenceHolder_Cleanup(&refs);
+    return retval;
+}
+
+size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
+        size_t size, size_t maxnum)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+
+    if (ctx->hidden.androidio.assetFileDescriptorRef) {
+        size_t bytesMax = size * maxnum;
+        if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && ctx->hidden.androidio.position + bytesMax > ctx->hidden.androidio.size) {
+            bytesMax = ctx->hidden.androidio.size - ctx->hidden.androidio.position;
+        }
+        size_t result = read(ctx->hidden.androidio.fd, buffer, bytesMax );
+        if (result > 0) {
+            ctx->hidden.androidio.position += result;
+            LocalReferenceHolder_Cleanup(&refs);
+            return result / size;
+        }
+        LocalReferenceHolder_Cleanup(&refs);
+        return 0;
+    } else {
+        jlong bytesRemaining = (jlong) (size * maxnum);
+        jlong bytesMax = (jlong) (ctx->hidden.androidio.size -  ctx->hidden.androidio.position);
+        int bytesRead = 0;
+
+        /* Don't read more bytes than those that remain in the file, otherwise we get an exception */
+        if (bytesRemaining >  bytesMax) bytesRemaining = bytesMax;
+
+        JNIEnv *mEnv = Android_JNI_GetEnv();
+        if (!LocalReferenceHolder_Init(&refs, mEnv)) {
+            LocalReferenceHolder_Cleanup(&refs);            
+            return 0;
+        }
+
+        jobject readableByteChannel = (jobject)ctx->hidden.androidio.readableByteChannelRef;
+        jmethodID readMethod = (jmethodID)ctx->hidden.androidio.readMethod;
+        jobject byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
+
+        while (bytesRemaining > 0) {
+            // result = readableByteChannel.read(...);
+            int result = (*mEnv)->CallIntMethod(mEnv, readableByteChannel, readMethod, byteBuffer);
+
+            if (Android_JNI_ExceptionOccurred(false)) {
+                LocalReferenceHolder_Cleanup(&refs);            
+                return 0;
+            }
+
+            if (result < 0) {
+                break;
+            }
+
+            bytesRemaining -= result;
+            bytesRead += result;
+            ctx->hidden.androidio.position += result;
+        }
+        LocalReferenceHolder_Cleanup(&refs);                    
+        return bytesRead / size;
+    }
+}
+
+size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer,
+        size_t size, size_t num)
+{
+    SDL_SetError("Cannot write to Android package filesystem");
+    return 0;
+}
+
+static int Internal_Android_JNI_FileClose(SDL_RWops* ctx, bool release)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+
+    int result = 0;
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+
+    if (!LocalReferenceHolder_Init(&refs, mEnv)) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return SDL_SetError("Failed to allocate enough JVM local references");
+    }
+
+    if (ctx) {
+        if (release) {
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.fileNameRef);
+        }
+
+        if (ctx->hidden.androidio.assetFileDescriptorRef) {
+            jobject inputStream = (jobject)ctx->hidden.androidio.assetFileDescriptorRef;
+            jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
+                    "close", "()V");
+            (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.assetFileDescriptorRef);
+            if (Android_JNI_ExceptionOccurred(false)) {
+                result = -1;
+            }
+        }
+        else {
+            jobject inputStream = (jobject)ctx->hidden.androidio.inputStreamRef;
+
+            // inputStream.close();
+            jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
+                    "close", "()V");
+            (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.inputStreamRef);
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.readableByteChannelRef);
+            if (Android_JNI_ExceptionOccurred(false)) {
+                result = -1;
+            }
+        }
+
+        if (release) {
+            SDL_FreeRW(ctx);
+        }
+    }
+
+    LocalReferenceHolder_Cleanup(&refs);
+    return result;
+}
+
+
+Sint64 Android_JNI_FileSize(SDL_RWops* ctx)
+{
+    return ctx->hidden.androidio.size;
+}
+
+Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
+{
+    if (ctx->hidden.androidio.assetFileDescriptorRef) {
+        switch (whence) {
+            case RW_SEEK_SET:
+                if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
+                offset += ctx->hidden.androidio.offset;
+                break;
+            case RW_SEEK_CUR:
+                offset += ctx->hidden.androidio.position;
+                if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
+                offset += ctx->hidden.androidio.offset;
+                break;
+            case RW_SEEK_END:
+                offset = ctx->hidden.androidio.offset + ctx->hidden.androidio.size + offset;
+                break;
+            default:
+                return SDL_SetError("Unknown value for 'whence'");
+        }
+        whence = SEEK_SET;
+
+        off_t ret = lseek(ctx->hidden.androidio.fd, (off_t)offset, SEEK_SET);
+        if (ret == -1) return -1;
+        ctx->hidden.androidio.position = ret - ctx->hidden.androidio.offset;
+    } else {
+        Sint64 newPosition;
+
+        switch (whence) {
+            case RW_SEEK_SET:
+                newPosition = offset;
+                break;
+            case RW_SEEK_CUR:
+                newPosition = ctx->hidden.androidio.position + offset;
+                break;
+            case RW_SEEK_END:
+                newPosition = ctx->hidden.androidio.size + offset;
+                break;
+            default:
+                return SDL_SetError("Unknown value for 'whence'");
+        }
+
+        /* Validate the new position */
+        if (newPosition < 0) {
+            return SDL_Error(SDL_EFSEEK);
+        }
+        if (newPosition > ctx->hidden.androidio.size) {
+            newPosition = ctx->hidden.androidio.size;
+        }
+
+        Sint64 movement = newPosition - ctx->hidden.androidio.position;
+        if (movement > 0) {
+            unsigned char buffer[4096];
+
+            // The easy case where we're seeking forwards
+            while (movement > 0) {
+                Sint64 amount = sizeof (buffer);
+                if (amount > movement) {
+                    amount = movement;
+                }
+                size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount);
+                if (result <= 0) {
+                    // Failed to read/skip the required amount, so fail
+                    return -1;
+                }
+
+                movement -= result;
+            }
+
+        } else if (movement < 0) {
+            // We can't seek backwards so we have to reopen the file and seek
+            // forwards which obviously isn't very efficient
+            Internal_Android_JNI_FileClose(ctx, false);
+            Internal_Android_JNI_FileOpen(ctx);
+            Android_JNI_FileSeek(ctx, newPosition, RW_SEEK_SET);
+        }
+    }
+
+    return ctx->hidden.androidio.position;
+
+}
+
+int Android_JNI_FileClose(SDL_RWops* ctx)
+{
+    return Internal_Android_JNI_FileClose(ctx, true);
+}
+
+// returns a new global reference which needs to be released later
+static jobject Android_JNI_GetSystemServiceObject(const char* name)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+    JNIEnv* env = Android_JNI_GetEnv();
+    jobject retval = NULL;
+
+    if (!LocalReferenceHolder_Init(&refs, env)) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return NULL;
+    }
+
+    jstring service = (*env)->NewStringUTF(env, name);
+
+    jmethodID mid;
+
+    mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
+    jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+
+    mid = (*env)->GetMethodID(env, mActivityClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
+    jobject manager = (*env)->CallObjectMethod(env, context, mid, service);
+
+    (*env)->DeleteLocalRef(env, service);
+
+    retval = manager ? (*env)->NewGlobalRef(env, manager) : NULL;
+    LocalReferenceHolder_Cleanup(&refs);
+    return retval;
+}
+
+#define SETUP_CLIPBOARD(error) \
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); \
+    JNIEnv* env = Android_JNI_GetEnv(); \
+    if (!LocalReferenceHolder_Init(&refs, env)) { \
+        LocalReferenceHolder_Cleanup(&refs); \
+        return error; \
+    } \
+    jobject clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \
+    if (!clipboard) { \
+        LocalReferenceHolder_Cleanup(&refs); \
+        return error; \
+    }
+
+#define CLEANUP_CLIPBOARD() \
+    LocalReferenceHolder_Cleanup(&refs);
+
+int Android_JNI_SetClipboardText(const char* text)
+{
+    SETUP_CLIPBOARD(-1)
+
+    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "setText", "(Ljava/lang/CharSequence;)V");
+    jstring string = (*env)->NewStringUTF(env, text);
+    (*env)->CallVoidMethod(env, clipboard, mid, string);
+    (*env)->DeleteGlobalRef(env, clipboard);
+    (*env)->DeleteLocalRef(env, string);
+
+    CLEANUP_CLIPBOARD();
+
+    return 0;
+}
+
+char* Android_JNI_GetClipboardText()
+{
+    SETUP_CLIPBOARD(SDL_strdup(""))
+
+    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "getText", "()Ljava/lang/CharSequence;");
+    jobject sequence = (*env)->CallObjectMethod(env, clipboard, mid);
+    (*env)->DeleteGlobalRef(env, clipboard);
+    if (sequence) {
+        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, sequence), "toString", "()Ljava/lang/String;");
+        jstring string = (jstring)((*env)->CallObjectMethod(env, sequence, mid));
+        const char* utf = (*env)->GetStringUTFChars(env, string, 0);
+        if (utf) {
+            char* text = SDL_strdup(utf);
+            (*env)->ReleaseStringUTFChars(env, string, utf);
+
+            CLEANUP_CLIPBOARD();
+
+            return text;
+        }
+    }
+
+    CLEANUP_CLIPBOARD();    
+
+    return SDL_strdup("");
+}
+
+SDL_bool Android_JNI_HasClipboardText()
+{
+    SETUP_CLIPBOARD(SDL_FALSE)
+
+    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "hasText", "()Z");
+    jboolean has = (*env)->CallBooleanMethod(env, clipboard, mid);
+    (*env)->DeleteGlobalRef(env, clipboard);
+
+    CLEANUP_CLIPBOARD();
+    
+    return has ? SDL_TRUE : SDL_FALSE;
+}
+
+
+// returns 0 on success or -1 on error (others undefined then)
+// returns truthy or falsy value in plugged, charged and battery
+// returns the value in seconds and percent or -1 if not available
+int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+    JNIEnv* env = Android_JNI_GetEnv();
+    if (!LocalReferenceHolder_Init(&refs, env)) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return -1;
+    }
+
+    jmethodID mid;
+
+    mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
+    jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+
+    jstring action = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED");
+
+    jclass cls = (*env)->FindClass(env, "android/content/IntentFilter");
+
+    mid = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
+    jobject filter = (*env)->NewObject(env, cls, mid, action);
+
+    (*env)->DeleteLocalRef(env, action);
+
+    mid = (*env)->GetMethodID(env, mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
+    jobject intent = (*env)->CallObjectMethod(env, context, mid, NULL, filter);
+
+    (*env)->DeleteLocalRef(env, filter);
+
+    cls = (*env)->GetObjectClass(env, intent);
+
+    jstring iname;
+    jmethodID imid = (*env)->GetMethodID(env, cls, "getIntExtra", "(Ljava/lang/String;I)I");
+
+#define GET_INT_EXTRA(var, key) \
+    iname = (*env)->NewStringUTF(env, key); \
+    int var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \
+    (*env)->DeleteLocalRef(env, iname);
+
+    jstring bname;
+    jmethodID bmid = (*env)->GetMethodID(env, cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z");
+
+#define GET_BOOL_EXTRA(var, key) \
+    bname = (*env)->NewStringUTF(env, key); \
+    int var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \
+    (*env)->DeleteLocalRef(env, bname);
+
+    if (plugged) {
+        GET_INT_EXTRA(plug, "plugged") // == BatteryManager.EXTRA_PLUGGED (API 5)
+        if (plug == -1) {
+            LocalReferenceHolder_Cleanup(&refs);
+            return -1;
+        }
+        // 1 == BatteryManager.BATTERY_PLUGGED_AC
+        // 2 == BatteryManager.BATTERY_PLUGGED_USB
+        *plugged = (0 < plug) ? 1 : 0;
+    }
+
+    if (charged) {
+        GET_INT_EXTRA(status, "status") // == BatteryManager.EXTRA_STATUS (API 5)
+        if (status == -1) {
+            LocalReferenceHolder_Cleanup(&refs);
+            return -1;
+        }
+        // 5 == BatteryManager.BATTERY_STATUS_FULL
+        *charged = (status == 5) ? 1 : 0;
+    }
+
+    if (battery) {
+        GET_BOOL_EXTRA(present, "present") // == BatteryManager.EXTRA_PRESENT (API 5)
+        *battery = present ? 1 : 0;
+    }
+
+    if (seconds) {
+        *seconds = -1; // not possible
+    }
+
+    if (percent) {
+        GET_INT_EXTRA(level, "level") // == BatteryManager.EXTRA_LEVEL (API 5)
+        GET_INT_EXTRA(scale, "scale") // == BatteryManager.EXTRA_SCALE (API 5)
+        if ((level == -1) || (scale == -1)) {
+            LocalReferenceHolder_Cleanup(&refs);
+            return -1;
+        }
+        *percent = level * 100 / scale;
+    }
+
+    (*env)->DeleteLocalRef(env, intent);
+
+    LocalReferenceHolder_Cleanup(&refs);
+    return 0;
+}
+
+// sends message to be handled on the UI event dispatch thread
+int Android_JNI_SendMessage(int command, int param)
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+    if (!env) {
+        return -1;
+    }
+    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "sendMessage", "(II)Z");
+    if (!mid) {
+        return -1;
+    }
+    jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass, mid, command, param);
+    return success ? 0 : -1;
+}
+
+void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+    if (!env) {
+        return;
+    }
+
+    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIII)Z");
+    if (!mid) {
+        return;
+    }
+    (*env)->CallStaticBooleanMethod(env, mActivityClass, mid,
+                               inputRect->x,
+                               inputRect->y,
+                               inputRect->w,
+                               inputRect->h );
+}
+
+void Android_JNI_HideTextInput()
+{
+    // has to match Activity constant
+    const int COMMAND_TEXTEDIT_HIDE = 3;
+    Android_JNI_SendMessage(COMMAND_TEXTEDIT_HIDE, 0);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Functions exposed to SDL applications in SDL_system.h
+//
+
+void *SDL_AndroidGetJNIEnv()
+{
+    return Android_JNI_GetEnv();
+}
+
+
+
+void *SDL_AndroidGetActivity()
+{
+    /* See SDL_system.h for caveats on using this function. */
+
+    jmethodID mid;
+
+    JNIEnv *env = Android_JNI_GetEnv();
+    if (!env) {
+        return NULL;
+    }
+
+    // return SDLActivity.getContext();
+    mid = (*env)->GetStaticMethodID(env, mActivityClass,
+            "getContext","()Landroid/content/Context;");
+    return (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+}
+
+const char * SDL_AndroidGetInternalStoragePath()
+{
+    static char *s_AndroidInternalFilesPath = NULL;
+
+    if (!s_AndroidInternalFilesPath) {
+        struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+        jmethodID mid;
+        jobject context;
+        jobject fileObject;
+        jstring pathString;
+        const char *path;
+
+        JNIEnv *env = Android_JNI_GetEnv();
+        if (!LocalReferenceHolder_Init(&refs, env)) {
+            LocalReferenceHolder_Cleanup(&refs);
+            return NULL;
+        }
+
+        // context = SDLActivity.getContext();
+        mid = (*env)->GetStaticMethodID(env, mActivityClass,
+                "getContext","()Landroid/content/Context;");
+        context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+
+        // fileObj = context.getFilesDir();
+        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
+                "getFilesDir", "()Ljava/io/File;");
+        fileObject = (*env)->CallObjectMethod(env, context, mid);
+        if (!fileObject) {
+            SDL_SetError("Couldn't get internal directory");
+            LocalReferenceHolder_Cleanup(&refs);
+            return NULL;
+        }
+
+        // path = fileObject.getAbsolutePath();
+        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
+                "getAbsolutePath", "()Ljava/lang/String;");
+        pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
+
+        path = (*env)->GetStringUTFChars(env, pathString, NULL);
+        s_AndroidInternalFilesPath = SDL_strdup(path);
+        (*env)->ReleaseStringUTFChars(env, pathString, path);
+
+        LocalReferenceHolder_Cleanup(&refs);
+    }
+    return s_AndroidInternalFilesPath;
+}
+
+int SDL_AndroidGetExternalStorageState()
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+    jmethodID mid;
+    jclass cls;
+    jstring stateString;
+    const char *state;
+    int stateFlags;
+
+    JNIEnv *env = Android_JNI_GetEnv();
+    if (!LocalReferenceHolder_Init(&refs, env)) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return 0;
+    }
+
+    cls = (*env)->FindClass(env, "android/os/Environment");
+    mid = (*env)->GetStaticMethodID(env, cls,
+            "getExternalStorageState", "()Ljava/lang/String;");
+    stateString = (jstring)(*env)->CallStaticObjectMethod(env, cls, mid);
+
+    state = (*env)->GetStringUTFChars(env, stateString, NULL);
+
+    // Print an info message so people debugging know the storage state
+    __android_log_print(ANDROID_LOG_INFO, "SDL", "external storage state: %s", state);
+
+    if (SDL_strcmp(state, "mounted") == 0) {
+        stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ |
+                     SDL_ANDROID_EXTERNAL_STORAGE_WRITE;
+    } else if (SDL_strcmp(state, "mounted_ro") == 0) {
+        stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ;
+    } else {
+        stateFlags = 0;
+    }
+    (*env)->ReleaseStringUTFChars(env, stateString, state);
+
+    LocalReferenceHolder_Cleanup(&refs);
+    return stateFlags;
+}
+
+const char * SDL_AndroidGetExternalStoragePath()
+{
+    static char *s_AndroidExternalFilesPath = NULL;
+
+    if (!s_AndroidExternalFilesPath) {
+        struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+        jmethodID mid;
+        jobject context;
+        jobject fileObject;
+        jstring pathString;
+        const char *path;
+
+        JNIEnv *env = Android_JNI_GetEnv();
+        if (!LocalReferenceHolder_Init(&refs, env)) {
+            LocalReferenceHolder_Cleanup(&refs);
+            return NULL;
+        }
+
+        // context = SDLActivity.getContext();
+        mid = (*env)->GetStaticMethodID(env, mActivityClass,
+                "getContext","()Landroid/content/Context;");
+        context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+
+        // fileObj = context.getExternalFilesDir();
+        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
+                "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
+        fileObject = (*env)->CallObjectMethod(env, context, mid, NULL);
+        if (!fileObject) {
+            SDL_SetError("Couldn't get external directory");
+            LocalReferenceHolder_Cleanup(&refs);
+            return NULL;
+        }
+
+        // path = fileObject.getAbsolutePath();
+        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
+                "getAbsolutePath", "()Ljava/lang/String;");
+        pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
+
+        path = (*env)->GetStringUTFChars(env, pathString, NULL);
+        s_AndroidExternalFilesPath = SDL_strdup(path);
+        (*env)->ReleaseStringUTFChars(env, pathString, path);
+
+        LocalReferenceHolder_Cleanup(&refs);
+    }
+    return s_AndroidExternalFilesPath;
+}
+
+#endif /* __ANDROID__ */
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 1 - 0
Source/ThirdParty/SDL/src/core/android/SDL_android.h

@@ -31,6 +31,7 @@ extern "C" {
 
 /* Interface from the SDL library into the Android Java activity */
 extern SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion, int red, int green, int blue, int alpha, int buffer, int depth, int stencil, int buffers, int samples);
+extern SDL_bool Android_JNI_DeleteContext(void);
 extern void Android_JNI_SwapWindow();
 extern void Android_JNI_SetActivityTitle(const char *title);
 extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]);

+ 1 - 1
Source/ThirdParty/SDL/src/events/SDL_events.c

@@ -599,7 +599,7 @@ SDL_RegisterEvents(int numevents)
 {
     Uint32 event_base;
 
-    if (SDL_userevents+numevents <= SDL_LASTEVENT) {
+    if ((numevents > 0) && (SDL_userevents+numevents <= SDL_LASTEVENT)) {
         event_base = SDL_userevents;
         SDL_userevents += numevents;
     } else {

+ 2 - 1
Source/ThirdParty/SDL/src/events/SDL_gesture.c

@@ -398,11 +398,12 @@ static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
 
 static float dollarRecognize(const SDL_DollarPath *path,int *bestTempl,SDL_GestureTouch* touch)
 {
-
     SDL_FloatPoint points[DOLLARNPOINTS];
     int i;
     float bestDiff = 10000;
 
+    SDL_memset(points, 0, sizeof(points));
+
     dollarNormalize(path,points);
 
     //PrintPath(points);

+ 17 - 0
Source/ThirdParty/SDL/src/events/SDL_mouse.c

@@ -364,6 +364,23 @@ SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y)
 void
 SDL_MouseQuit(void)
 {
+    SDL_Cursor *cursor, *next;
+    SDL_Mouse *mouse = SDL_GetMouse();
+
+    SDL_ShowCursor(1);
+
+    cursor = mouse->cursors;
+    while (cursor) {
+        next = cursor->next;
+        SDL_FreeCursor(cursor);
+        cursor = next;
+    }
+
+    if (mouse->def_cursor && mouse->FreeCursor) {
+        mouse->FreeCursor(mouse->def_cursor);
+    }
+
+    SDL_zerop(mouse);
 }
 
 Uint32

+ 2 - 1
Source/ThirdParty/SDL/src/events/SDL_sysevents.h

@@ -24,7 +24,8 @@
 
 /* Useful functions and variables from SDL_sysevents.c */
 
-#ifdef __BEOS__                 /* The Be event loop runs in a separate thread */
+#if defined(__BEOS__) || defined(__HAIKU__) 
+/* The Be and Haiku event loops run in a separate thread */
 #define MUST_THREAD_EVENTS
 #endif
 

+ 0 - 41
Source/ThirdParty/SDL/src/events/nds/SDL_ndsgesture.c

@@ -1,41 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2012 Sam Lantinga <[email protected]>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "SDL_config.h"
-
-/* No supported under the NDS because of math operations. */
-
-#include "SDL_events.h"
-#include "../SDL_events_c.h"
-#include "../SDL_gesture_c.h"
-
-int SDL_GestureAddTouch(SDL_Touch* touch)
-{  
-	return 0;
-}
-
-void SDL_GestureProcessEvent(SDL_Event* event)
-{
-	return;
-}
-
-/* vi: set ts=4 sw=4 expandtab: */
-  

+ 3 - 3
Source/ThirdParty/SDL/src/events/scancodes_darwin.h

@@ -91,7 +91,7 @@ static const SDL_Scancode darwin_scancode_table[] = {
     /*  61 */   SDL_SCANCODE_RALT,
     /*  62 */   SDL_SCANCODE_RCTRL,
     /*  63 */   SDL_SCANCODE_RGUI, /* fn on portables, acts as a hardware-level modifier already, so we don't generate events for it, also XK_Meta_R */
-    /*  64 */   SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
+    /*  64 */   SDL_SCANCODE_F17,
     /*  65 */   SDL_SCANCODE_KP_PERIOD,
     /*  66 */   SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
     /*  67 */   SDL_SCANCODE_KP_MULTIPLY,
@@ -106,8 +106,8 @@ static const SDL_Scancode darwin_scancode_table[] = {
     /*  76 */   SDL_SCANCODE_KP_ENTER, /* keypad enter on external keyboards, fn-return on portables */
     /*  77 */   SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
     /*  78 */   SDL_SCANCODE_KP_MINUS,
-    /*  79 */   SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
-    /*  80 */   SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
+    /*  79 */   SDL_SCANCODE_F18,
+    /*  80 */   SDL_SCANCODE_F19,
     /*  81 */   SDL_SCANCODE_KP_EQUALS,
     /*  82 */   SDL_SCANCODE_KP_0,
     /*  83 */   SDL_SCANCODE_KP_1,

+ 6 - 6
Source/ThirdParty/SDL/src/events/scancodes_windows.h

@@ -38,18 +38,18 @@ static const SDL_Scancode windows_scancode_table[] =
 	SDL_SCANCODE_APOSTROPHE,	SDL_SCANCODE_GRAVE,			SDL_SCANCODE_LSHIFT,		SDL_SCANCODE_BACKSLASH,		SDL_SCANCODE_Z,			SDL_SCANCODE_X,				SDL_SCANCODE_C,				SDL_SCANCODE_V,			// 2 
 
 	SDL_SCANCODE_B,				SDL_SCANCODE_N,				SDL_SCANCODE_M,				SDL_SCANCODE_COMMA,			SDL_SCANCODE_PERIOD,	SDL_SCANCODE_SLASH,			SDL_SCANCODE_RSHIFT,		SDL_SCANCODE_PRINTSCREEN,// 3
-	SDL_SCANCODE_LALT,			SDL_SCANCODE_SPACE,			SDL_SCANCODE_CAPSLOCK,		SDL_SCANCODE_F1,			SDL_SCANCODE_F2,		SDL_SCANCODE_F3,			SDL_SCANCODE_F4,			SDL_SCANCODE_F5,			// 3 
+	SDL_SCANCODE_LALT,			SDL_SCANCODE_SPACE,			SDL_SCANCODE_CAPSLOCK,		SDL_SCANCODE_F1,			SDL_SCANCODE_F2,		SDL_SCANCODE_F3,			SDL_SCANCODE_F4,			SDL_SCANCODE_F5,		// 3 
 
 	SDL_SCANCODE_F6,			SDL_SCANCODE_F7,			SDL_SCANCODE_F8,			SDL_SCANCODE_F9,			SDL_SCANCODE_F10,		SDL_SCANCODE_NUMLOCKCLEAR,	SDL_SCANCODE_SCROLLLOCK,	SDL_SCANCODE_HOME,		// 4
 	SDL_SCANCODE_UP,			SDL_SCANCODE_PAGEUP,		SDL_SCANCODE_KP_MINUS,		SDL_SCANCODE_LEFT,			SDL_SCANCODE_KP_5,		SDL_SCANCODE_RIGHT,			SDL_SCANCODE_KP_PLUS,		SDL_SCANCODE_END,		// 4 
 
 	SDL_SCANCODE_DOWN,			SDL_SCANCODE_PAGEDOWN,		SDL_SCANCODE_INSERT,		SDL_SCANCODE_DELETE,		SDL_SCANCODE_UNKNOWN,	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_NONUSBACKSLASH,SDL_SCANCODE_F11,		// 5
-	SDL_SCANCODE_F12,			SDL_SCANCODE_PAUSE,			SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_LGUI,			SDL_SCANCODE_RGUI,		SDL_SCANCODE_APPLICATION,	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		// 5
+	SDL_SCANCODE_F12,			SDL_SCANCODE_PAUSE,			SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_LGUI,			SDL_SCANCODE_RGUI,		SDL_SCANCODE_APPLICATION,	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,	// 5
 
-	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		// 6
-	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		// 6 
+	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_F13,		SDL_SCANCODE_F14,			SDL_SCANCODE_F15,			SDL_SCANCODE_F16,		// 6
+	SDL_SCANCODE_F17,			SDL_SCANCODE_F18,			SDL_SCANCODE_F19,			SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,	// 6 
 	
-	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		// 7
-	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN		// 7 
+	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,	// 7
+	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,	SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN,		SDL_SCANCODE_UNKNOWN	// 7 
 };
 /* *INDENT-ON* */

+ 14 - 14
Source/ThirdParty/SDL/src/events/scancodes_xfree86.h

@@ -141,8 +141,8 @@ static const SDL_Scancode xfree86_scancode_table[] = {
     /*  112 */  SDL_SCANCODE_F15,
     /*  113 */  SDL_SCANCODE_F16,
     /*  114 */  SDL_SCANCODE_F17,
-    /*  115 */	SDL_SCANCODE_UNKNOWN,
-    /*	116 */  SDL_SCANCODE_UNKNOWN, /* is translated to XK_ISO_Level3_Shift by my X server, but I have no keyboard that generates this code, so I don't know what the correct SDL_SCANCODE_* for it is */
+    /*  115 */  SDL_SCANCODE_UNKNOWN,
+    /*  116 */  SDL_SCANCODE_UNKNOWN, /* is translated to XK_ISO_Level3_Shift by my X server, but I have no keyboard that generates this code, so I don't know what the correct SDL_SCANCODE_* for it is */
     /*  117 */  SDL_SCANCODE_UNKNOWN,
     /*  118 */  SDL_SCANCODE_KP_EQUALS,
     /*  119 */  SDL_SCANCODE_UNKNOWN,
@@ -298,7 +298,7 @@ static const SDL_Scancode xfree86_scancode_table2[] = {
     /* 118 */   SDL_SCANCODE_UNKNOWN,   /* plusminus */
     /* 119 */   SDL_SCANCODE_PAUSE,
     /* 120 */   SDL_SCANCODE_UNKNOWN,   /* XF86LaunchA */
-    /* 121 */   SDL_SCANCODE_UNKNOWN,	/* KP_Decimal */
+    /* 121 */   SDL_SCANCODE_UNKNOWN,   /* KP_Decimal */
     /* 122 */   SDL_SCANCODE_UNKNOWN,   /* Hangul */
     /* 123 */   SDL_SCANCODE_UNKNOWN,   /* Hangul_Hanja */
     /* 124 */   SDL_SCANCODE_UNKNOWN,
@@ -325,15 +325,15 @@ static const SDL_Scancode xfree86_scancode_table2[] = {
     /* 145 */   SDL_SCANCODE_UNKNOWN,   /* XF86Send */
     /* 146 */   SDL_SCANCODE_UNKNOWN,
     /* 147 */   SDL_SCANCODE_UNKNOWN,   /* XF86Xfer */
-    /* 148 */   SDL_SCANCODE_UNKNOWN,   /* XF86Launch1 */
-    /* 149 */   SDL_SCANCODE_UNKNOWN,   /* XF86Launch2 */
+    /* 148 */   SDL_SCANCODE_APP1,      /* XF86Launch1 */
+    /* 149 */   SDL_SCANCODE_APP2,      /* XF86Launch2 */
     /* 150 */   SDL_SCANCODE_WWW,
     /* 151 */   SDL_SCANCODE_UNKNOWN,   /* XF86DOS */
     /* 152 */   SDL_SCANCODE_UNKNOWN,   /* XF86ScreenSaver */
     /* 153 */   SDL_SCANCODE_UNKNOWN,
     /* 154 */   SDL_SCANCODE_UNKNOWN,   /* XF86RotateWindows */
     /* 155 */   SDL_SCANCODE_MAIL,
-    /* 156 */   SDL_SCANCODE_UNKNOWN,   /* XF86Favorites */
+    /* 156 */   SDL_SCANCODE_AC_BOOKMARKS,   /* XF86Favorites */
     /* 157 */   SDL_SCANCODE_COMPUTER,
     /* 158 */   SDL_SCANCODE_AC_BACK,
     /* 159 */   SDL_SCANCODE_AC_FORWARD,
@@ -348,7 +348,7 @@ static const SDL_Scancode xfree86_scancode_table2[] = {
     /* 168 */   SDL_SCANCODE_UNKNOWN,   /* XF86AudioRewind */
     /* 169 */   SDL_SCANCODE_UNKNOWN,   /* XF86Phone */
     /* 170 */   SDL_SCANCODE_UNKNOWN,
-    /* 171 */   SDL_SCANCODE_UNKNOWN,   /* XF86Tools */
+    /* 171 */   SDL_SCANCODE_F13,       /* XF86Tools */
     /* 172 */   SDL_SCANCODE_AC_HOME,
     /* 173 */   SDL_SCANCODE_AC_REFRESH,
     /* 174 */   SDL_SCANCODE_UNKNOWN,   /* XF86Close */
@@ -360,13 +360,13 @@ static const SDL_Scancode xfree86_scancode_table2[] = {
     /* 180 */   SDL_SCANCODE_UNKNOWN,   /* parenright */
     /* 181 */   SDL_SCANCODE_UNKNOWN,   /* XF86New */
     /* 182 */   SDL_SCANCODE_AGAIN,
-    /* 183 */   SDL_SCANCODE_UNKNOWN,   /* XF86Tools */
-    /* 184 */   SDL_SCANCODE_UNKNOWN,   /* XF86Launch5 */
-    /* 185 */   SDL_SCANCODE_UNKNOWN,   /* XF86MenuKB */
-    /* 186 */   SDL_SCANCODE_UNKNOWN,
-    /* 187 */   SDL_SCANCODE_UNKNOWN,
-    /* 188 */   SDL_SCANCODE_UNKNOWN,
-    /* 189 */   SDL_SCANCODE_UNKNOWN,
+    /* 183 */   SDL_SCANCODE_F13,       /* XF86Tools */
+    /* 184 */   SDL_SCANCODE_F14,       /* XF86Launch5 */
+    /* 185 */   SDL_SCANCODE_F15,       /* XF86Launch6 */
+    /* 186 */   SDL_SCANCODE_F16,       /* XF86Launch7 */
+    /* 187 */   SDL_SCANCODE_F17,       /* XF86Launch8 */
+    /* 188 */   SDL_SCANCODE_F18,       /* XF86Launch9 */
+    /* 189 */   SDL_SCANCODE_F19,       /* null keysym */
     /* 190 */   SDL_SCANCODE_UNKNOWN,
     /* 191 */   SDL_SCANCODE_UNKNOWN,
     /* 192 */   SDL_SCANCODE_UNKNOWN,   /* XF86TouchpadToggle */

+ 71 - 35
Source/ThirdParty/SDL/src/haptic/SDL_haptic.c

@@ -23,7 +23,7 @@
 #include "SDL_syshaptic.h"
 #include "SDL_haptic_c.h"
 #include "../joystick/SDL_joystick_c.h" /* For SDL_PrivateJoystickValid */
-
+#include "SDL_assert.h"
 
 Uint8 SDL_numhaptics = 0;
 SDL_Haptic **SDL_haptics = NULL;
@@ -149,18 +149,23 @@ SDL_HapticOpen(int device_index)
         return NULL;
     }
 
+    /* Add haptic to list */
+    for (i = 0; SDL_haptics[i]; i++)
+        /* Skip to next haptic */ ;
+    if (i >= SDL_numhaptics) {
+        SDL_free(haptic);
+        SDL_SetError("Haptic: Trying to add device past the number originally detected");
+        return NULL;
+    }
+    SDL_haptics[i] = haptic;
+    ++haptic->ref_count;
+
     /* Disable autocenter and set gain to max. */
     if (haptic->supported & SDL_HAPTIC_GAIN)
         SDL_HapticSetGain(haptic, 100);
     if (haptic->supported & SDL_HAPTIC_AUTOCENTER)
         SDL_HapticSetAutocenter(haptic, 0);
 
-    /* Add haptic to list */
-    ++haptic->ref_count;
-    for (i = 0; SDL_haptics[i]; i++)
-        /* Skip to next haptic */ ;
-    SDL_haptics[i] = haptic;
-
     return haptic;
 }
 
@@ -173,6 +178,13 @@ SDL_HapticOpened(int device_index)
 {
     int i, opened;
 
+    /* Make sure it's valid. */
+    if ((device_index < 0) || (device_index >= SDL_numhaptics)) {
+        SDL_SetError("Haptic: There are %d haptic devices available",
+                     SDL_numhaptics);
+        return 0;
+    }
+
     opened = 0;
     for (i = 0; SDL_haptics[i]; i++) {
         if (SDL_haptics[i]->index == (Uint8) device_index) {
@@ -262,6 +274,13 @@ SDL_HapticOpenFromJoystick(SDL_Joystick * joystick)
     int i;
     SDL_Haptic *haptic;
 
+    /* Make sure there is room. */
+    if (SDL_numhaptics <= 0) {
+        SDL_SetError("Haptic: There are %d haptic devices available",
+                     SDL_numhaptics);
+        return NULL;
+    }
+
     /* Must be a valid joystick */
     if (!SDL_PrivateJoystickValid(joystick)) {
         SDL_SetError("Haptic: Joystick isn't valid.");
@@ -299,10 +318,15 @@ SDL_HapticOpenFromJoystick(SDL_Joystick * joystick)
     }
 
     /* Add haptic to list */
-    ++haptic->ref_count;
     for (i = 0; SDL_haptics[i]; i++)
         /* Skip to next haptic */ ;
+    if (i >= SDL_numhaptics) {
+        SDL_free(haptic);
+        SDL_SetError("Haptic: Trying to add device past the number originally detected");
+        return NULL;
+    }
     SDL_haptics[i] = haptic;
+    ++haptic->ref_count;
 
     return haptic;
 }
@@ -699,32 +723,18 @@ SDL_HapticStopAll(SDL_Haptic * haptic)
     return SDL_SYS_HapticStopAll(haptic);
 }
 
-static void
-SDL_HapticRumbleCreate(SDL_HapticEffect * efx)
-{
-   SDL_memset(efx, 0, sizeof(SDL_HapticEffect));
-   efx->type = SDL_HAPTIC_SINE;
-   efx->periodic.period = 1000;
-   efx->periodic.magnitude = 0x4000;
-   efx->periodic.length = 5000;
-   efx->periodic.attack_length = 0;
-   efx->periodic.fade_length = 0;
-}
-
 /*
  * Checks to see if rumble is supported.
  */
 int
 SDL_HapticRumbleSupported(SDL_Haptic * haptic)
 {
-    SDL_HapticEffect efx;
-
     if (!ValidHaptic(haptic)) {
         return -1;
     }
 
-    SDL_HapticRumbleCreate(&efx);
-    return SDL_HapticEffectSupported(haptic, &efx);
+    /* Most things can use SINE, but XInput only has LEFTRIGHT. */
+    return ((haptic->supported & (SDL_HAPTIC_SINE|SDL_HAPTIC_LEFTRIGHT)) != 0);
 }
 
 /*
@@ -733,6 +743,8 @@ SDL_HapticRumbleSupported(SDL_Haptic * haptic)
 int
 SDL_HapticRumbleInit(SDL_Haptic * haptic)
 {
+    SDL_HapticEffect *efx = &haptic->rumble_effect;
+
     if (!ValidHaptic(haptic)) {
         return -1;
     }
@@ -742,8 +754,23 @@ SDL_HapticRumbleInit(SDL_Haptic * haptic)
         return 0;
     }
 
-    /* Copy over. */
-    SDL_HapticRumbleCreate(&haptic->rumble_effect);
+    SDL_zerop(efx);
+    if (haptic->supported & SDL_HAPTIC_SINE) {
+        efx->type = SDL_HAPTIC_SINE;
+        efx->periodic.period = 1000;
+        efx->periodic.magnitude = 0x4000;
+        efx->periodic.length = 5000;
+        efx->periodic.attack_length = 0;
+        efx->periodic.fade_length = 0;
+    } else if (haptic->supported & SDL_HAPTIC_LEFTRIGHT) {  /* XInput? */
+        efx->type = SDL_HAPTIC_LEFTRIGHT;
+        efx->leftright.length = 5000;
+        efx->leftright.large_magnitude = 0x4000;
+        efx->leftright.small_magnitude = 0x4000;
+    } else {
+        return SDL_SetError("Device doesn't support rumble");
+    }
+
     haptic->rumble_id = SDL_HapticNewEffect(haptic, &haptic->rumble_effect);
     if (haptic->rumble_id >= 0) {
         return 0;
@@ -757,7 +784,8 @@ SDL_HapticRumbleInit(SDL_Haptic * haptic)
 int
 SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length)
 {
-    SDL_HapticPeriodic *efx;
+    SDL_HapticEffect *efx;
+    Sint16 magnitude;
 
     if (!ValidHaptic(haptic)) {
         return -1;
@@ -770,16 +798,25 @@ SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length)
     /* Clamp strength. */
     if (strength > 1.0f) {
         strength = 1.0f;
-    }
-    else if (strength < 0.0f) {
+    } else if (strength < 0.0f) {
         strength = 0.0f;
     }
+    magnitude = (Sint16)(32767.0f*strength);
 
-    /* New effect. */
-    efx = &haptic->rumble_effect.periodic;
-    efx->magnitude = (Sint16)(32767.0f*strength);
-    efx->length = length;
-    SDL_HapticUpdateEffect(haptic, haptic->rumble_id, &haptic->rumble_effect);
+    efx = &haptic->rumble_effect;
+    if (efx->type == SDL_HAPTIC_SINE) {
+        efx->periodic.magnitude = magnitude;
+        efx->periodic.length = length;
+    } else if (efx->type == SDL_HAPTIC_LEFTRIGHT) {
+        efx->leftright.small_magnitude = efx->leftright.large_magnitude = magnitude;
+        efx->leftright.length = length;
+    } else {
+        SDL_assert(0 && "This should have been caught elsewhere");
+    }
+
+    if (SDL_HapticUpdateEffect(haptic, haptic->rumble_id, &haptic->rumble_effect) < 0) {
+        return -1;
+    }
 
     return SDL_HapticRunEffect(haptic, haptic->rumble_id, 1);
 }
@@ -801,4 +838,3 @@ SDL_HapticRumbleStop(SDL_Haptic * haptic)
     return SDL_HapticStopEffect(haptic, haptic->rumble_id);
 }
 
-

+ 7 - 4
Source/ThirdParty/SDL/src/haptic/darwin/SDL_syshaptic.c

@@ -342,7 +342,8 @@ GetSupportedFeatures(SDL_Haptic * haptic)
     /* Test for effects. */
     FF_TEST(FFCAP_ET_CONSTANTFORCE, SDL_HAPTIC_CONSTANT);
     FF_TEST(FFCAP_ET_RAMPFORCE, SDL_HAPTIC_RAMP);
-    FF_TEST(FFCAP_ET_SQUARE, SDL_HAPTIC_SQUARE);
+    /* !!! FIXME: put this back when we have more bits in 2.1 */
+    /*FF_TEST(FFCAP_ET_SQUARE, SDL_HAPTIC_SQUARE);*/
     FF_TEST(FFCAP_ET_SINE, SDL_HAPTIC_SINE);
     FF_TEST(FFCAP_ET_TRIANGLE, SDL_HAPTIC_TRIANGLE);
     FF_TEST(FFCAP_ET_SAWTOOTHUP, SDL_HAPTIC_SAWTOOTHUP);
@@ -750,7 +751,8 @@ SDL_SYS_ToFFEFFECT(SDL_Haptic * haptic, FFEFFECT * dest,
         break;
 
     case SDL_HAPTIC_SINE:
-    case SDL_HAPTIC_SQUARE:
+    /* !!! FIXME: put this back when we have more bits in 2.1 */
+    /*case SDL_HAPTIC_SQUARE:*/
     case SDL_HAPTIC_TRIANGLE:
     case SDL_HAPTIC_SAWTOOTHUP:
     case SDL_HAPTIC_SAWTOOTHDOWN:
@@ -978,8 +980,9 @@ SDL_SYS_HapticEffectType(Uint16 type)
     case SDL_HAPTIC_RAMP:
         return kFFEffectType_RampForce_ID;
 
-    case SDL_HAPTIC_SQUARE:
-        return kFFEffectType_Square_ID;
+    /* !!! FIXME: put this back when we have more bits in 2.1 */
+    /*case SDL_HAPTIC_SQUARE:
+        return kFFEffectType_Square_ID;*/
 
     case SDL_HAPTIC_SINE:
         return kFFEffectType_Sine_ID;

+ 13 - 28
Source/ThirdParty/SDL/src/haptic/dummy/SDL_syshaptic.c

@@ -29,8 +29,7 @@
 static int
 SDL_SYS_LogicError(void)
 {
-    SDL_SetError("Logic error: No haptic devices available.");
-    return 0;
+    return SDL_SetError("Logic error: No haptic devices available.");
 }
 
 
@@ -52,8 +51,7 @@ SDL_SYS_HapticName(int index)
 int
 SDL_SYS_HapticOpen(SDL_Haptic * haptic)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 
@@ -74,8 +72,7 @@ SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
 int
 SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 
@@ -104,8 +101,7 @@ int
 SDL_SYS_HapticNewEffect(SDL_Haptic * haptic,
                         struct haptic_effect *effect, SDL_HapticEffect * base)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 
@@ -114,8 +110,7 @@ SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
                            struct haptic_effect *effect,
                            SDL_HapticEffect * data)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 
@@ -123,16 +118,14 @@ int
 SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
                         Uint32 iterations)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 
 int
 SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 
@@ -148,47 +141,39 @@ int
 SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
                               struct haptic_effect *effect)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 
 int
 SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 
 int
 SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 int
 SDL_SYS_HapticPause(SDL_Haptic * haptic)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 int
 SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
 int
 SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
 {
-    SDL_SYS_LogicError();
-    return -1;
+    return SDL_SYS_LogicError();
 }
 
-
-
 #endif /* SDL_HAPTIC_DUMMY || SDL_HAPTIC_DISABLED */

+ 30 - 4
Source/ThirdParty/SDL/src/haptic/linux/SDL_syshaptic.c

@@ -99,7 +99,8 @@ EV_IsHaptic(int fd)
     /* Convert supported features to SDL_HAPTIC platform-neutral features. */
     EV_TEST(FF_CONSTANT, SDL_HAPTIC_CONSTANT);
     EV_TEST(FF_SINE, SDL_HAPTIC_SINE);
-    EV_TEST(FF_SQUARE, SDL_HAPTIC_SQUARE);
+    /* !!! FIXME: put this back when we have more bits in 2.1 */
+    /*EV_TEST(FF_SQUARE, SDL_HAPTIC_SQUARE);*/
     EV_TEST(FF_TRIANGLE, SDL_HAPTIC_TRIANGLE);
     EV_TEST(FF_SAW_UP, SDL_HAPTIC_SAWTOOTHUP);
     EV_TEST(FF_SAW_DOWN, SDL_HAPTIC_SAWTOOTHDOWN);
@@ -111,6 +112,7 @@ EV_IsHaptic(int fd)
     EV_TEST(FF_CUSTOM, SDL_HAPTIC_CUSTOM);
     EV_TEST(FF_GAIN, SDL_HAPTIC_GAIN);
     EV_TEST(FF_AUTOCENTER, SDL_HAPTIC_AUTOCENTER);
+    EV_TEST(FF_RUMBLE, SDL_HAPTIC_LEFTRIGHT);
 
     /* Return what it supports. */
     return ret;
@@ -559,6 +561,7 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
     SDL_HapticPeriodic *periodic;
     SDL_HapticCondition *condition;
     SDL_HapticRamp *ramp;
+    SDL_HapticLeftRight *leftright;
 
     /* Clear up */
     SDL_memset(dest, 0, sizeof(struct ff_effect));
@@ -596,7 +599,8 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
         break;
 
     case SDL_HAPTIC_SINE:
-    case SDL_HAPTIC_SQUARE:
+    /* !!! FIXME: put this back when we have more bits in 2.1 */
+    /*case SDL_HAPTIC_SQUARE:*/
     case SDL_HAPTIC_TRIANGLE:
     case SDL_HAPTIC_SAWTOOTHUP:
     case SDL_HAPTIC_SAWTOOTHDOWN:
@@ -620,8 +624,9 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
         /* Periodic */
         if (periodic->type == SDL_HAPTIC_SINE)
             dest->u.periodic.waveform = FF_SINE;
-        else if (periodic->type == SDL_HAPTIC_SQUARE)
-            dest->u.periodic.waveform = FF_SQUARE;
+        /* !!! FIXME: put this back when we have more bits in 2.1 */
+        /*else if (periodic->type == SDL_HAPTIC_SQUARE)
+            dest->u.periodic.waveform = FF_SQUARE;*/
         else if (periodic->type == SDL_HAPTIC_TRIANGLE)
             dest->u.periodic.waveform = FF_TRIANGLE;
         else if (periodic->type == SDL_HAPTIC_SAWTOOTHUP)
@@ -725,6 +730,27 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
 
         break;
 
+    case SDL_HAPTIC_LEFTRIGHT:
+        leftright = &src->leftright;
+
+        /* Header */
+        dest->type = FF_RUMBLE;
+        dest->direction = 0;
+
+        /* Replay */
+        dest->replay.length = (leftright->length == SDL_HAPTIC_INFINITY) ?
+            0 : CLAMP(leftright->length);
+
+        /* Trigger */
+        dest->trigger.button = 0;
+        dest->trigger.interval = 0;
+
+        /* Rumble */
+        dest->u.rumble.strong_magnitude = leftright->large_magnitude;
+        dest->u.rumble.weak_magnitude = leftright->small_magnitude;
+
+	break;
+
 
     default:
         return SDL_SetError("Haptic: Unknown effect type.");

+ 0 - 330
Source/ThirdParty/SDL/src/haptic/nds/SDL_syshaptic.c

@@ -1,330 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2012 Sam Lantinga <[email protected]>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-#include "SDL_config.h"
-
-#ifdef SDL_HAPTIC_NDS
-
-#include "SDL_haptic.h"
-#include "../SDL_syshaptic.h"
-#include "SDL_joystick.h"
-#include <nds/memory.h>
-#include <nds/arm9/rumble.h>
-
-#define MAX_HAPTICS  1
-/* right now only the ezf3in1 (and maybe official rumble pak) are supported
-   and there can only be one of those in at a time (in GBA slot.) */
-
-static SDL_Haptic *nds_haptic = NULL;
-
-struct haptic_hwdata
-{
-    enum
-    { NONE, OFFICIAL, EZF3IN1 } type;
-    int pos;
-};
-
-
-void
-NDS_EZF_OpenNorWrite() 
-{
-    GBA_BUS[0x0FF0000] = 0xD200;
-    GBA_BUS[0x0000000] = 0x1500;
-    GBA_BUS[0x0010000] = 0xD200;
-    GBA_BUS[0x0020000] = 0x1500;
-    GBA_BUS[0x0E20000] = 0x1500;
-    GBA_BUS[0x0FE0000] = 0x1500;
-}
-
-void
-NDS_EZF_CloseNorWrite() 
-{
-    GBA_BUS[0x0FF0000] = 0xD200;
-    GBA_BUS[0x0000000] = 0x1500;
-    GBA_BUS[0x0010000] = 0xD200;
-    GBA_BUS[0x0020000] = 0x1500;
-    GBA_BUS[0x0E20000] = 0xD200;
-    GBA_BUS[0x0FE0000] = 0x1500;
-}
-
-void
-NDS_EZF_ChipReset()
-{
-    GBA_BUS[0x0000] = 0x00F0;
-    GBA_BUS[0x1000] = 0x00F0;
-} uint32 NDS_EZF_IsPresent() 
-{
-    vuint16 id1, id2;
-
-    NDS_EZF_OpenNorWrite();
-
-    GBA_BUS[0x0555] = 0x00AA;
-    GBA_BUS[0x02AA] = 0x0055;
-    GBA_BUS[0x0555] = 0x0090;
-    GBA_BUS[0x1555] = 0x00AA;
-    GBA_BUS[0x12AA] = 0x0055;
-    GBA_BUS[0x1555] = 0x0090;
-    id1 = GBA_BUS[0x0001];
-    id2 = GBA_BUS[0x1001];
-    if ((id1 != 0x227E) || (id2 != 0x227E)) {
-        NDS_EZF_CloseNorWrite();
-        return 0;
-    }
-    id1 = GBA_BUS[0x000E];
-    id2 = GBA_BUS[0x100E];
-
-    NDS_EZF_CloseNorWrite();
-    if (id1 == 0x2218 && id2 == 0x2218) {
-        return 1;
-    }
-    return 0;
-}
-void
-NDS_EZF_SetShake(u8 pos) 
-{
-    u16 data = ((pos % 3) | 0x00F0);
-    GBA_BUS[0x0FF0000] = 0xD200;
-    GBA_BUS[0x0000000] = 0x1500;
-    GBA_BUS[0x0010000] = 0xD200;
-    GBA_BUS[0x0020000] = 0x1500;
-    GBA_BUS[0x0F10000] = data;
-    GBA_BUS[0x0FE0000] = 0x1500;
-
-    GBA_BUS[0] = 0x0000;        /* write any value for vibration. */
-    GBA_BUS[0] = 0x0002;
-}
-
-static int
-SDL_SYS_LogicError(void)
-{
-    SDL_SetError("Logic error: No haptic devices available.");
-    return 0;
-}
-
-
-int
-SDL_SYS_HapticInit(void)
-{
-    int ret = 0;
-    if (isRumbleInserted()) {
-        /* official rumble pak is present. */
-        ret = 1;
-        printf("debug: haptic present: nintendo\n");
-    } else if (NDS_EZF_IsPresent()) {
-        /* ezflash 3-in-1 pak is present. */
-        ret = 1;
-        printf("debug: haptic present: ezf3in1\n");
-        NDS_EZF_ChipReset();
-    } else {
-        printf("debug: no haptic found\n");
-    }
-
-    return ret;
-}
-
-
-const char *
-SDL_SYS_HapticName(int index)
-{
-    if (nds_haptic) {
-        switch (nds_haptic->hwdata->type) {
-        case OFFICIAL:
-            return "Nintendo DS Rumble Pak";
-        case EZF3IN1:
-            return "EZFlash 3-in-1 Rumble";
-        default:
-            return NULL;
-        }
-    }
-    return NULL;
-}
-
-
-int
-SDL_SYS_HapticOpen(SDL_Haptic * haptic)
-{
-    if (!haptic) {
-        return -1;
-    }
-
-    haptic->hwdata = SDL_malloc(sizeof(struct haptic_hwdata));
-    if (!haptic->hwdata) {
-        SDL_OutOfMemory();
-        return -1;
-    }
-    nds_haptic = haptic;
-
-    haptic->supported = SDL_HAPTIC_CONSTANT;
-
-    /* determine what is here, if anything */
-    haptic->hwdata->type = NONE;
-    if (isRumbleInserted()) {
-        /* official rumble pak is present. */
-        haptic->hwdata->type = OFFICIAL;
-    } else if (NDS_EZF_IsPresent()) {
-        /* ezflash 3-in-1 pak is present. */
-        haptic->hwdata->type = EZF3IN1;
-        NDS_EZF_ChipReset();
-    } else {
-        /* no haptic present */
-        SDL_SYS_LogicError();
-        return -1;
-    }
-
-    return 0;
-}
-
-
-int
-SDL_SYS_HapticMouse(void)
-{
-    return -1;
-}
-
-
-int
-SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
-{
-    return 0;
-}
-
-
-int
-SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
-{
-    /*SDL_SYS_LogicError(); */
-    return -1;
-}
-
-
-int
-SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
-{
-    return 0;
-}
-
-
-void
-SDL_SYS_HapticClose(SDL_Haptic * haptic)
-{
-    return;
-}
-
-
-void
-SDL_SYS_HapticQuit(void)
-{
-    return;
-}
-
-
-int
-SDL_SYS_HapticNewEffect(SDL_Haptic * haptic,
-                        struct haptic_effect *effect, SDL_HapticEffect * base)
-{
-    SDL_SYS_LogicError();
-    return -1;
-}
-
-
-int
-SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
-                           struct haptic_effect *effect,
-                           SDL_HapticEffect * data)
-{
-    SDL_SYS_LogicError();
-    return -1;
-}
-
-
-int
-SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
-                        Uint32 iterations)
-{
-    SDL_SYS_LogicError();
-    return -1;
-}
-
-
-int
-SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
-{
-    SDL_SYS_LogicError();
-    return -1;
-}
-
-
-void
-SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
-{
-    SDL_SYS_LogicError();
-    return;
-}
-
-
-int
-SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
-                              struct haptic_effect *effect)
-{
-    SDL_SYS_LogicError();
-    return -1;
-}
-
-
-int
-SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
-{
-    SDL_SYS_LogicError();
-    return -1;
-}
-
-
-int
-SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
-{
-    SDL_SYS_LogicError();
-    return -1;
-}
-
-int
-SDL_SYS_HapticPause(SDL_Haptic * haptic)
-{
-    SDL_SYS_LogicError();
-    return -1;
-}
-
-int
-SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
-{
-    SDL_SYS_LogicError();
-    return -1;
-}
-
-int
-SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
-{
-    SDL_SYS_LogicError();
-    return -1;
-}
-
-
-
-#endif /* SDL_HAPTIC_NDS */
-/* vi: set ts=4 sw=4 expandtab: */

+ 105 - 25
Source/ThirdParty/SDL/src/haptic/windows/SDL_syshaptic.c

@@ -23,6 +23,9 @@
 #ifdef SDL_HAPTIC_DINPUT
 
 #include "SDL_assert.h"
+#include "SDL_thread.h"
+#include "SDL_mutex.h"
+#include "SDL_timer.h"
 #include "SDL_hints.h"
 #include "SDL_haptic.h"
 #include "../SDL_syshaptic.h"
@@ -56,6 +59,10 @@ struct haptic_hwdata
     SDL_bool is_joystick;       /* Device is loaded as joystick. */
     Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
     Uint8 userid; /* XInput userid index for this joystick */
+    SDL_Thread *thread;
+    SDL_mutex *mutex;
+    volatile Uint32 stopTicks;
+    volatile int stopThread;
 };
 
 
@@ -102,6 +109,8 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
                               SDL_HapticEffect * src);
 static void SDL_SYS_HapticFreeDIEFFECT(DIEFFECT * effect, int type);
 static REFGUID SDL_SYS_HapticEffectType(SDL_HapticEffect * effect);
+static int SDLCALL SDL_RunXInputHaptic(void *arg);
+
 /* Callbacks. */
 static BOOL CALLBACK EnumHapticsCallback(const DIDEVICEINSTANCE *
                                          pdidInstance, VOID * pContext);
@@ -294,7 +303,8 @@ DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv)
     EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT);
     EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM);
     EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE);
-    EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE);
+    /* !!! FIXME: put this back when we have more bits in 2.1 */
+    /*EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE);*/
     EFFECT_TEST(GUID_Triangle, SDL_HAPTIC_TRIANGLE);
     EFFECT_TEST(GUID_SawtoothUp, SDL_HAPTIC_SAWTOOTHUP);
     EFFECT_TEST(GUID_SawtoothDown, SDL_HAPTIC_SAWTOOTHDOWN);
@@ -376,11 +386,11 @@ SDL_SYS_HapticOpenFromInstance(SDL_Haptic * haptic, DIDEVICEINSTANCE instance)
 static int
 SDL_SYS_HapticOpenFromXInput(SDL_Haptic * haptic, Uint8 userid)
 {
+    char threadName[32];
     XINPUT_VIBRATION vibration = { 0, 0 };  /* stop any current vibration */
     XINPUTSETSTATE(userid, &vibration);
 
-    /* !!! FIXME: we can probably do more than SINE if we figure out how to set up the left and right motors properly. */
-    haptic->supported = SDL_HAPTIC_SINE;
+    haptic->supported = SDL_HAPTIC_LEFTRIGHT;
 
     haptic->neffects = 1;
     haptic->nplaying = 1;
@@ -406,6 +416,30 @@ SDL_SYS_HapticOpenFromXInput(SDL_Haptic * haptic, Uint8 userid)
     haptic->hwdata->bXInputHaptic = 1;
     haptic->hwdata->userid = userid;
 
+    haptic->hwdata->mutex = SDL_CreateMutex();
+    if (haptic->hwdata->mutex == NULL) {
+        SDL_free(haptic->effects);
+        SDL_free(haptic->hwdata);
+        haptic->effects = NULL;
+        return SDL_SetError("Couldn't create XInput haptic mutex");
+    }
+
+    SDL_snprintf(threadName, sizeof (threadName), "SDLXInputDev%d", (int) userid);
+
+#if defined(__WIN32__) && !defined(HAVE_LIBC)  /* !!! FIXME: this is nasty. */
+    #undef SDL_CreateThread
+    haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
+#else
+    haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata);
+#endif
+    if (haptic->hwdata->thread == NULL) {
+        SDL_DestroyMutex(haptic->hwdata->mutex);
+        SDL_free(haptic->effects);
+        SDL_free(haptic->hwdata);
+        haptic->effects = NULL;
+        return SDL_SetError("Couldn't create XInput haptic thread");
+    }
+
     return 0;
  }
 
@@ -684,7 +718,11 @@ SDL_SYS_HapticClose(SDL_Haptic * haptic)
         haptic->neffects = 0;
 
         /* Clean up */
-        if (!haptic->hwdata->bXInputHaptic) {
+        if (haptic->hwdata->bXInputHaptic) {
+            haptic->hwdata->stopThread = 1;
+            SDL_WaitThread(haptic->hwdata->thread, NULL);
+            SDL_DestroyMutex(haptic->hwdata->mutex);
+        } else {
             IDirectInputDevice8_Unacquire(haptic->hwdata->device);
             /* Only release if isn't grabbed by a joystick. */
             if (haptic->hwdata->is_joystick == 0) {
@@ -897,7 +935,8 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
         break;
 
     case SDL_HAPTIC_SINE:
-    case SDL_HAPTIC_SQUARE:
+    /* !!! FIXME: put this back when we have more bits in 2.1 */
+    /*case SDL_HAPTIC_SQUARE:*/
     case SDL_HAPTIC_TRIANGLE:
     case SDL_HAPTIC_SAWTOOTHUP:
     case SDL_HAPTIC_SAWTOOTHDOWN:
@@ -1125,8 +1164,9 @@ SDL_SYS_HapticEffectType(SDL_HapticEffect * effect)
     case SDL_HAPTIC_RAMP:
         return &GUID_RampForce;
 
-    case SDL_HAPTIC_SQUARE:
-        return &GUID_Square;
+    /* !!! FIXME: put this back when we have more bits in 2.1 */
+    /*case SDL_HAPTIC_SQUARE:
+        return &GUID_Square;*/
 
     case SDL_HAPTIC_SINE:
         return &GUID_Sine;
@@ -1172,7 +1212,7 @@ SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
     HRESULT ret;
     REFGUID type = SDL_SYS_HapticEffectType(base);
 
-    if (type == NULL) {
+    if ((type == NULL) && (!haptic->hwdata->bXInputHaptic)) {
         goto err_hweffect;
     }
 
@@ -1187,7 +1227,7 @@ SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
     SDL_zerop(effect->hweffect);
 
     if (haptic->hwdata->bXInputHaptic) {
-        SDL_assert(base->type == SDL_HAPTIC_SINE);  /* should catch this at higher level */
+        SDL_assert(base->type == SDL_HAPTIC_LEFTRIGHT);  /* should catch this at higher level */
         return SDL_SYS_HapticUpdateEffect(haptic, effect, base);
     }
 
@@ -1231,20 +1271,15 @@ SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
     DIEFFECT temp;
 
     if (haptic->hwdata->bXInputHaptic) {
-        /* !!! FIXME: this isn't close to right. We only support "sine" effects,
-         * !!! FIXME:  we ignore most of the parameters, and we probably get
-         * !!! FIXME:  the ones we don't ignore wrong, too.
-         * !!! FIXME: if I had a better understanding of how the two motors
-         * !!! FIXME:  could be used in unison, perhaps I could implement other
-         * !!! FIXME:  effect types?
-         */
-        /* From MSDN:
-            "Note that the right motor is the high-frequency motor, the left
-             motor is the low-frequency motor. They do not always need to be
-             set to the same amount, as they provide different effects." */
         XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
-        SDL_assert(data->type == SDL_HAPTIC_SINE);
-        vib->wLeftMotorSpeed = vib->wRightMotorSpeed = data->periodic.magnitude * 2;
+        SDL_assert(data->type == SDL_HAPTIC_LEFTRIGHT);
+        vib->wLeftMotorSpeed = data->leftright.large_magnitude;
+        vib->wRightMotorSpeed = data->leftright.small_magnitude;
+        SDL_LockMutex(haptic->hwdata->mutex);
+        if (haptic->hwdata->stopTicks) {  /* running right now? Update it. */
+            XINPUTSETSTATE(haptic->hwdata->userid, vib);
+        }
+        SDL_UnlockMutex(haptic->hwdata->mutex);
         return 0;
     }
 
@@ -1295,7 +1330,11 @@ SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
 
     if (haptic->hwdata->bXInputHaptic) {
         XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
-        return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS);
+        SDL_assert(effect->effect.type == SDL_HAPTIC_LEFTRIGHT);  /* should catch this at higher level */
+        SDL_LockMutex(haptic->hwdata->mutex);
+        haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations);
+        SDL_UnlockMutex(haptic->hwdata->mutex);
+        return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1;
     }
 
     /* Check if it's infinite. */
@@ -1324,7 +1363,10 @@ SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
 
     if (haptic->hwdata->bXInputHaptic) {
         XINPUT_VIBRATION vibration = { 0, 0 };
-        return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS);
+        SDL_LockMutex(haptic->hwdata->mutex);
+        haptic->hwdata->stopTicks = 0;
+        SDL_UnlockMutex(haptic->hwdata->mutex);
+        return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
     }
 
     ret = IDirectInputEffect_Stop(effect->hweffect->ref);
@@ -1483,7 +1525,10 @@ SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
 
     if (haptic->hwdata->bXInputHaptic) {
         XINPUT_VIBRATION vibration = { 0, 0 };
-        return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS);
+        SDL_LockMutex(haptic->hwdata->mutex);
+        haptic->hwdata->stopTicks = 0;
+        SDL_UnlockMutex(haptic->hwdata->mutex);
+        return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
     }
 
     /* Try to stop the effects. */
@@ -1496,6 +1541,41 @@ SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
     return 0;
 }
 
+
+/* !!! FIXME: this is a hack, remove this later. */
+/* Since XInput doesn't offer a way to vibrate for X time, we hook into
+ *  SDL_PumpEvents() to check if it's time to stop vibrating with some
+ *  frequency.
+ * In practice, this works for 99% of use cases. But in an ideal world,
+ *  we do this in a separate thread so that:
+ *    - we aren't bound to when the app chooses to pump the event queue.
+ *    - we aren't adding more polling to the event queue
+ *    - we can emulate all the haptic effects correctly (start on a delay,
+ *      mix multiple effects, etc).
+ *
+ * Mostly, this is here to get rumbling to work, and all the other features
+ *  are absent in the XInput path for now.  :(
+ */
+static int SDLCALL
+SDL_RunXInputHaptic(void *arg)
+{
+    struct haptic_hwdata *hwdata = (struct haptic_hwdata *) arg;
+
+    while (!hwdata->stopThread) {
+        SDL_Delay(50);
+        SDL_LockMutex(hwdata->mutex);
+        /* If we're currently running and need to stop... */
+        if ((hwdata->stopTicks) && (hwdata->stopTicks < SDL_GetTicks())) {
+            XINPUT_VIBRATION vibration = { 0, 0 };
+            hwdata->stopTicks = 0;
+            XINPUTSETSTATE(hwdata->userid, &vibration);
+        }
+        SDL_UnlockMutex(hwdata->mutex);
+    }
+
+    return 0;
+}
+
 #endif /* SDL_HAPTIC_DINPUT */
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 1 - 37
Source/ThirdParty/SDL/src/joystick/SDL_gamecontroller.c

@@ -26,6 +26,7 @@
 #include "SDL_assert.h"
 #include "SDL_sysjoystick.h"
 #include "SDL_hints.h"
+#include "SDL_gamecontrollerdb.h"
 
 #if !SDL_EVENTS_DISABLED
 #include "../events/SDL_events_c.h"
@@ -85,43 +86,6 @@ typedef struct _ControllerMapping_t
     struct _ControllerMapping_t *next;
 } ControllerMapping_t;
 
-
-/* default mappings we support */
-const char *s_ControllerMappings [] =
-{
-#ifdef SDL_JOYSTICK_DINPUT
-    "xinput,X360 Controller,a:b10,b:b11,y:b13,x:b12,start:b4,guide:b14,back:b5,dpup:b0,dpleft:b2,dpdown:b1,dpright:b3,leftshoulder:b8,rightshoulder:b9,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5",
-    "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",
-    "88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,x:b0,y:b3,start:b11,back:b8,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.4,dpdown:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,guide:b12",
-    "4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,",
-    "25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,x:b0,y:b3,start:b8,guide:,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.4,dpdown:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5",
-    "ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,y:b3,x:b2,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
-	"6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", /* Guide button doesn't seem to be sent in DInput mode. */
-    "6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
-#elif defined(__MACOSX__)
-    "5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftshoulder:b4,rightshoulder:b5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5",
-    "4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,x:b15,y:b12,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9",
-    "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,y:b3,x:b2,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
-    "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
-    "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", /* Guide button doesn't seem to be sent in DInput mode. */
-    "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */
-    "6d0400000000000018c2000000000000,Logitech Rumble Gamepad F510(DInput),a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,rightx:a2,lefty:a1,righty:a3,lefttrigger:b6,righttrigger:b7,",
-#elif defined(__LINUX__)
-    "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5",
-    "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
-    "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
-    "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,x:b15,y:b12,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9",
-    "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
-    "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", /* Guide button doesn't seem to be sent in DInput mode. */
-    "030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
-    "030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
-    "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,y:b3,x:b2,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
-    "03000000ba2200002010000001010000,Jess Technology USB Game Controller,start:b9,a:b2,b:b1,x:b3,y:b0,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,leftshoulder:b4,rightshoulder:b5,guide:,back:b8",
-    "030000006d0400001ec2000020200000,Logitech Rumble Gamepad F510 (XInput),a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
-#endif
-    NULL
-};
-
 static ControllerMapping_t *s_pSupportedControllers = NULL;
 #ifdef SDL_JOYSTICK_DINPUT
 static ControllerMapping_t *s_pXInputMapping = NULL;

+ 65 - 0
Source/ThirdParty/SDL/src/joystick/SDL_gamecontrollerdb.h

@@ -0,0 +1,65 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+
+/* Default mappings we support
+
+   The easiest way to generate a new mapping is to start Steam in Big Picture
+   mode, configure your joystick and then look in config/config.vdf in your
+   Steam installation directory for the "SDL_GamepadBind" entry.
+ */
+static const char *s_ControllerMappings [] =
+{
+#ifdef SDL_JOYSTICK_DINPUT
+    "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+    "ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
+    "6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+	"6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
+    "88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,",
+    "4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
+    "25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,",
+    "xinput,X360 Controller,a:b10,b:b11,back:b5,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,guide:b14,leftshoulder:b8,leftstick:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b4,x:b12,y:b13,",
+#elif defined(__MACOSX__)
+    "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
+    "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
+    "6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+    "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
+    "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */
+    "4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
+    "5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
+#elif defined(__LINUX__)
+    "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
+    "03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
+    "030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+    "030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+    "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+    "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
+    "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+    "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
+    "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+    "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+    "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+#endif
+    NULL
+};
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 24 - 7
Source/ThirdParty/SDL/src/joystick/SDL_joystick.c

@@ -36,17 +36,30 @@ static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
 static SDL_Joystick *SDL_joysticks = NULL;
 static SDL_Joystick *SDL_updating_joystick = NULL;
 
+static void
+SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+    if (hint && *hint == '1') {
+        SDL_joystick_allows_background_events = SDL_TRUE;
+    } else {
+        SDL_joystick_allows_background_events = SDL_FALSE;
+    }
+}
+
 int
 SDL_JoystickInit(void)
 {
-    const char *hint;
     int status;
-	
-    /* Check to see if we should allow joystick events while in the background */
-    hint = SDL_GetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS);
-    if (hint && *hint == '1') {
-        SDL_joystick_allows_background_events = SDL_TRUE;
+
+    /* See if we should allow joystick events while in the background */
+    SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
+                        SDL_JoystickAllowBackgroundEventsChanged, NULL);
+
+#if !SDL_EVENTS_DISABLED
+    if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {
+        return -1;
     }
+#endif /* !SDL_EVENTS_DISABLED */
 
     status = SDL_SYS_JoystickInit();
     if (status >= 0) {
@@ -340,7 +353,7 @@ SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
 
 /*
  * Return if the joystick in question is currently attached to the system,
- *  \return 0 if not plugged in, 1 if still present.
+ *  \return SDL_FALSE if not plugged in, SDL_TRUE if still present.
  */
 SDL_bool
 SDL_JoystickGetAttached(SDL_Joystick * joystick)
@@ -458,6 +471,10 @@ SDL_JoystickQuit(void)
 
     /* Quit the joystick setup */
     SDL_SYS_JoystickQuit();
+
+#if !SDL_EVENTS_DISABLED
+    SDL_QuitSubSystem(SDL_INIT_EVENTS);
+#endif
 }
 
 

+ 16 - 0
Source/ThirdParty/SDL/src/joystick/darwin/SDL_sysjoystick.c

@@ -362,6 +362,22 @@ HIDAddElement(CFTypeRef refElement, recDevice * pDevice)
                         }
                     }
                     break;
+                case kHIDPage_Simulation:
+                    switch (usage) {
+                        case kHIDUsage_Sim_Rudder:
+                        case kHIDUsage_Sim_Throttle:
+                            element = (recElement *)
+                                NewPtrClear(sizeof(recElement));
+                            if (element) {
+                                pDevice->axes++;
+                                headElement = &(pDevice->firstAxis);
+                            }
+                            break;
+
+                        default:
+                            break;
+                    }
+                    break;
                 case kHIDPage_Button:
                     element = (recElement *)
                         NewPtrClear(sizeof(recElement));

+ 0 - 209
Source/ThirdParty/SDL/src/joystick/nds/SDL_sysjoystick.c

@@ -1,209 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2012 Sam Lantinga <[email protected]>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "SDL_config.h"
-
-#ifdef SDL_JOYSTICK_NDS
-
-/* This is the system specific header for the SDL joystick API */
-#include <nds.h>
-#include <stdio.h>              /* For the definition of NULL */
-
-#include "SDL_error.h"
-#include "SDL_events.h"
-#include "SDL_joystick.h"
-#include "../SDL_sysjoystick.h"
-#include "../SDL_joystick_c.h"
-
-#include "../../video/nds/SDL_ndsevents_c.h"
-
-/* Function to scan the system for joysticks.
- */
-int
-SDL_SYS_JoystickInit(void)
-{
-    return (1);
-}
-
-int SDL_SYS_NumJoysticks()
-{
-    return 1;
-}
-
-void SDL_SYS_JoystickDetect()
-{
-}
-
-SDL_bool SDL_SYS_JoystickNeedsPolling()
-{
-    return SDL_FALSE;
-}
-
-/* Function to get the device-dependent name of a joystick */
-const char *
-SDL_SYS_JoystickNameForDeviceIndex(int device_index)
-{
-    return "NDS builtin joypad";
-}
-
-/* Function to perform the mapping from device index to the instance id for this index */
-SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
-{
-    return device_index;
-}
-
-/* Function to open a joystick for use.
-   The joystick to open is specified by the index field of the joystick.
-   This should fill the nbuttons and naxes fields of the joystick structure.
-   It returns 0, or -1 if there is an error.
- */
-int
-SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
-{
-    joystick->nbuttons = 8;
-    joystick->nhats = 0;
-    joystick->nballs = 0;
-    joystick->naxes = 2;
-    return 0;
-}
-
-/* Function to determine is this joystick is attached to the system right now */
-SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
-{
-    return SDL_TRUE;
-}
-
-/* Function to update the state of a joystick - called as a device poll.
- * This function shouldn't update the joystick structure directly,
- * but instead should call SDL_PrivateJoystick*() to deliver events
- * and update joystick device state.
- */
-    void
-SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
-{
-    u32 keysd, keysu;
-    int magnitude = 16384;
-    
-        /*scanKeys(); - this is done in PumpEvents, because touch uses it too */ 
-        keysd = keysDown();
-    keysu = keysUp();
-
-    if ((keysd & KEY_UP)) {
-        SDL_PrivateJoystickAxis(joystick, 1, -magnitude);
-    }
-    if ((keysd & KEY_DOWN)) {
-        SDL_PrivateJoystickAxis(joystick, 1, magnitude);
-    }
-    if ((keysd & KEY_LEFT)) {
-        SDL_PrivateJoystickAxis(joystick, 0, -magnitude);
-    }
-    if ((keysd & KEY_RIGHT)) {
-        SDL_PrivateJoystickAxis(joystick, 0, magnitude);
-    }
-    if ((keysu & (KEY_UP | KEY_DOWN))) {
-        SDL_PrivateJoystickAxis(joystick, 1, 0);
-    }
-    if ((keysu & (KEY_LEFT | KEY_RIGHT))) {
-        SDL_PrivateJoystickAxis(joystick, 0, 0);
-    }
-    if ((keysd & KEY_A)) {
-        SDL_PrivateJoystickButton(joystick, 0, SDL_PRESSED);
-    }
-    if ((keysd & KEY_B)) {
-        SDL_PrivateJoystickButton(joystick, 1, SDL_PRESSED);
-    }
-    if ((keysd & KEY_X)) {
-        SDL_PrivateJoystickButton(joystick, 2, SDL_PRESSED);
-    }
-    if ((keysd & KEY_Y)) {
-        SDL_PrivateJoystickButton(joystick, 3, SDL_PRESSED);
-    }
-    if ((keysd & KEY_L)) {
-        SDL_PrivateJoystickButton(joystick, 4, SDL_PRESSED);
-    }
-    if ((keysd & KEY_R)) {
-        SDL_PrivateJoystickButton(joystick, 5, SDL_PRESSED);
-    }
-    if ((keysd & KEY_SELECT)) {
-        SDL_PrivateJoystickButton(joystick, 6, SDL_PRESSED);
-    }
-    if ((keysd & KEY_START)) {
-        SDL_PrivateJoystickButton(joystick, 7, SDL_PRESSED);
-    }
-    if ((keysu & KEY_A)) {
-        SDL_PrivateJoystickButton(joystick, 0, SDL_RELEASED);
-    }
-    if ((keysu & KEY_B)) {
-        SDL_PrivateJoystickButton(joystick, 1, SDL_RELEASED);
-    }
-    if ((keysu & KEY_X)) {
-        SDL_PrivateJoystickButton(joystick, 2, SDL_RELEASED);
-    }
-    if ((keysu & KEY_Y)) {
-        SDL_PrivateJoystickButton(joystick, 3, SDL_RELEASED);
-    }
-    if ((keysu & KEY_L)) {
-        SDL_PrivateJoystickButton(joystick, 4, SDL_RELEASED);
-    }
-    if ((keysu & KEY_R)) {
-        SDL_PrivateJoystickButton(joystick, 5, SDL_RELEASED);
-    }
-    if ((keysu & KEY_SELECT)) {
-        SDL_PrivateJoystickButton(joystick, 6, SDL_RELEASED);
-    }
-    if ((keysu & KEY_START)) {
-        SDL_PrivateJoystickButton(joystick, 7, SDL_RELEASED);
-    }
-}
-
-/* Function to close a joystick after use */
-void
-SDL_SYS_JoystickClose(SDL_Joystick * joystick)
-{
-}
-
-/* Function to perform any system-specific joystick related cleanup */
-void
-SDL_SYS_JoystickQuit(void)
-{
-}
-
-SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
-{
-    SDL_JoystickGUID guid;
-    // the GUID is just the first 16 chars of the name for now
-    const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
-    SDL_zero( guid );
-    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
-    return guid;
-}
-
-SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
-{
-    SDL_JoystickGUID guid;
-    // the GUID is just the first 16 chars of the name for now
-    const char *name = joystick->name;
-    SDL_zero( guid );
-    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
-    return guid;
-}
-
-#endif /* SDL_JOYSTICK_NDS */

+ 11 - 65
Source/ThirdParty/SDL/src/libm/math_libm.h

@@ -19,73 +19,19 @@
   3. This notice may not be removed or altered from any source distribution.
 */
 #include "SDL_config.h"
-#include "SDL_stdinc.h"
 
 /* Math routines from uClibc: http://www.uclibc.org */
 
-#ifdef HAVE_ATAN
-#define atan            SDL_uclibc_atan
-#else
-#define atan            SDL_atan
-#endif
-double atan(double x);
-
-#ifndef HAVE_ATAN2
-#define __ieee754_atan2 SDL_atan2
-#endif
-
-#ifdef HAVE_COPYSIGN
-#define copysign        SDL_uclibc_copysign
-#else
-#define copysign        SDL_copysign
-#endif
-double copysign(double x, double y);
-
-#ifdef HAVE_COS
-#define cos             SDL_uclibc_cos
-#else
-#define cos             SDL_cos
-#endif
-double cos(double x);
-
-#ifdef HAVE_FABS
-#define fabs            SDL_uclibc_fabs
-#else
-#define fabs            SDL_fabs
-#endif
-double fabs(double x);
-
-#ifdef HAVE_FLOOR
-#define floor           SDL_uclibc_floor
-#else
-#define floor           SDL_floor
-#endif
-double floor(double x);
-
-#ifndef HAVE_LOG
-#define __ieee754_log   SDL_log
-#endif
-
-#ifndef HAVE_POW
-#define __ieee754_pow   SDL_pow
-#endif
-
-#ifdef HAVE_SCALBN
-#define scalbn          SDL_uclibc_scalbn
-#else
-#define scalbn          SDL_scalbn
-#endif
-double scalbn(double x, int n);
-
-#ifdef HAVE_SIN
-#define sin             SDL_uclibc_sin
-#else
-#define sin             SDL_sin
-#endif
-double sin(double x);
-
-#ifndef HAVE_SQRT
-#define __ieee754_sqrt  SDL_sqrt
-#endif
+double SDL_uclibc_atan(double x);
+double SDL_uclibc_atan2(double y, double x);    
+double SDL_uclibc_copysign(double x, double y);       
+double SDL_uclibc_cos(double x);         
+double SDL_uclibc_fabs(double x);        
+double SDL_uclibc_floor(double x);
+double SDL_uclibc_log(double x);
+double SDL_uclibc_pow(double x, double y);    
+double SDL_uclibc_scalbn(double x, int n);
+double SDL_uclibc_sin(double x);
+double SDL_uclibc_sqrt(double x);
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 14 - 0
Source/ThirdParty/SDL/src/libm/math_private.h

@@ -25,7 +25,21 @@
 #define libm_hidden_proto(x)
 #define libm_hidden_def(x)
 
+#ifndef __HAIKU__ /* already defined in a system header. */
 typedef unsigned int u_int32_t;
+#endif
+
+#define atan            SDL_uclibc_atan
+#define __ieee754_atan2 SDL_uclibc_atan2
+#define copysign        SDL_uclibc_copysign
+#define cos             SDL_uclibc_cos
+#define fabs            SDL_uclibc_fabs
+#define floor           SDL_uclibc_floor
+#define __ieee754_log   SDL_uclibc_log
+#define __ieee754_pow   SDL_uclibc_pow
+#define scalbn          SDL_uclibc_scalbn
+#define sin             SDL_uclibc_sin
+#define __ieee754_sqrt  SDL_uclibc_sqrt
 
 /* The original fdlibm code used statements like:
 	n0 = ((*(int*)&one)>>29)^1;		* index of high word *

+ 1 - 1
Source/ThirdParty/SDL/src/loadso/dlopen/SDL_sysloadso.c

@@ -33,7 +33,7 @@
 void *
 SDL_LoadObject(const char *sofile)
 {
-    void *handle = dlopen(sofile, RTLD_NOW);
+    void *handle = dlopen(sofile, RTLD_NOW|RTLD_LOCAL);
     const char *loaderror = (char *) dlerror();
     if (handle == NULL) {
         SDL_SetError("Failed loading %s: %s", sofile, loaderror);

+ 5 - 0
Source/ThirdParty/SDL/src/main/android/SDL_android_main.c

@@ -0,0 +1,5 @@
+// Modified by Lasse Oorni for Urho3D
+
+// Urho3D: function moved to SDL_android.c due to link error
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 0 - 19
Source/ThirdParty/SDL/src/main/android/SDL_android_main.cpp

@@ -1,19 +0,0 @@
-// Modified by Lasse Oorni for Urho3D
-
-#include "SDL_config.h"
-
-#ifdef __ANDROID__
-
-/* Include the SDL main definition header */
-#include "SDL_main.h"
-
-/*******************************************************************************
-                 Functions called by JNI
-*******************************************************************************/
-#include <jni.h>
-
-// Urho3D: function moved to SDL_android.cpp
-
-#endif /* __ANDROID__ */
-
-/* vi: set ts=4 sw=4 expandtab: */

+ 4 - 2
Source/ThirdParty/SDL/src/main/windows/SDL_windows_main.c

@@ -54,7 +54,7 @@ ParseCommandLine(char *cmdline, char **argv)
     argc = last_argc = 0;
     for (bufp = cmdline; *bufp;) {
         /* Skip leading whitespace */
-        while (isspace(*bufp)) {
+        while (SDL_isspace(*bufp)) {
             ++bufp;
         }
         /* Skip over argument */
@@ -80,7 +80,7 @@ ParseCommandLine(char *cmdline, char **argv)
                 ++argc;
             }
             /* Skip over word */
-            while (*bufp && !isspace(*bufp)) {
+            while (*bufp && !SDL_isspace(*bufp)) {
                 ++bufp;
             }
         }
@@ -176,6 +176,8 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
     /* Run the main program */
     console_main(argc, argv);
 
+    SDL_stack_free(argv);
+
     SDL_free(cmdline);
 
     /* Hush little compiler, don't you cry... */

+ 0 - 44
Source/ThirdParty/SDL/src/power/nds/SDL_syspower.c

@@ -1,44 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2012 Sam Lantinga <[email protected]>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-#include "SDL_config.h"
-
-#ifndef SDL_POWER_DISABLED
-#if SDL_POWER_NINTENDODS
-
-#include "SDL_power.h"
-
-SDL_bool
-SDL_GetPowerInfo_NintendoDS(SDL_PowerState * state, int *seconds,
-                            int *percent)
-{
-    /* !!! FIXME: write me. */
-
-    *state = SDL_POWERSTATE_UNKNOWN;
-    *percent = -1;
-    *seconds = -1;
-
-    return SDL_TRUE;            /* always the definitive answer on Nintendo DS. */
-}
-
-#endif /* SDL_POWER_NINTENDODS */
-#endif /* SDL_POWER_DISABLED */
-
-/* vi: set ts=4 sw=4 expandtab: */

+ 26 - 16
Source/ThirdParty/SDL/src/render/SDL_render.c

@@ -151,6 +151,16 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
             event->motion.y -= renderer->viewport.y;
             event->motion.x = (int)(event->motion.x / renderer->scale.x);
             event->motion.y = (int)(event->motion.y / renderer->scale.y);
+            if (event->motion.xrel > 0) {
+                event->motion.xrel = SDL_max(1, (int)(event->motion.xrel / renderer->scale.x));
+            } else if (event->motion.xrel < 0) {
+                event->motion.xrel = SDL_min(-1, (int)(event->motion.xrel / renderer->scale.x));
+            }
+            if (event->motion.yrel > 0) {
+                event->motion.yrel = SDL_max(1, (int)(event->motion.yrel / renderer->scale.y));
+            } else if (event->motion.yrel < 0) {
+                event->motion.yrel = SDL_min(-1, (int)(event->motion.yrel / renderer->scale.y));
+            }
         }
     } else if (event->type == SDL_MOUSEBUTTONDOWN ||
                event->type == SDL_MOUSEBUTTONUP) {
@@ -764,6 +774,13 @@ SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
 
     CHECK_TEXTURE_MAGIC(texture, -1);
 
+    if (!pixels) {
+        return SDL_InvalidParamError("pixels");
+    }
+    if (!pitch) {
+        return SDL_InvalidParamError("pitch");
+    }
+
     if (!rect) {
         full_rect.x = 0;
         full_rect.y = 0;
@@ -1450,7 +1467,7 @@ SDL_RenderDrawRects(SDL_Renderer * renderer,
 int
 SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
 {
-    SDL_Rect full_rect;
+    SDL_Rect full_rect = { 0, 0, 0, 0 };
 
     CHECK_RENDERER_MAGIC(renderer, -1);
 
@@ -1532,22 +1549,10 @@ SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
     real_dstrect.x = 0;
     real_dstrect.y = 0;
     if (dstrect) {
-        if (!SDL_IntersectRect(dstrect, &real_dstrect, &real_dstrect)) {
+        if (!SDL_HasIntersection(dstrect, &real_dstrect)) {
             return 0;
         }
-        /* Clip srcrect by the same amount as dstrect was clipped */
-        if (dstrect->w != real_dstrect.w) {
-            int deltax = (real_dstrect.x - dstrect->x);
-            int deltaw = (real_dstrect.w - dstrect->w);
-            real_srcrect.x += (deltax * real_srcrect.w) / dstrect->w;
-            real_srcrect.w += (deltaw * real_srcrect.w) / dstrect->w;
-        }
-        if (dstrect->h != real_dstrect.h) {
-            int deltay = (real_dstrect.y - dstrect->y);
-            int deltah = (real_dstrect.h - dstrect->h);
-            real_srcrect.y += (deltay * real_srcrect.h) / dstrect->h;
-            real_srcrect.h += (deltah * real_srcrect.h) / dstrect->h;
-        }
+        real_dstrect = *dstrect;
     }
 
     if (texture->native) {
@@ -1684,9 +1689,14 @@ SDL_DestroyTexture(SDL_Texture * texture)
     SDL_Renderer *renderer;
 
     CHECK_TEXTURE_MAGIC(texture, );
-    texture->magic = NULL;
 
     renderer = texture->renderer;
+    if (texture == renderer->target) {
+        SDL_SetRenderTarget(renderer, NULL);
+    }
+
+    texture->magic = NULL;
+
     if (texture->next) {
         texture->next->prev = texture->prev;
     }

+ 8 - 8
Source/ThirdParty/SDL/src/render/SDL_yuv_sw.c

@@ -82,6 +82,7 @@
  * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  */
 
+#include "SDL_assert.h"
 #include "SDL_video.h"
 #include "SDL_cpuinfo.h"
 #include "SDL_yuv_sw_c.h"
@@ -1029,12 +1030,6 @@ SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
     int i;
     int CR, CB;
 
-    swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata));
-    if (!swdata) {
-        SDL_OutOfMemory();
-        return NULL;
-    }
-
     switch (format) {
     case SDL_PIXELFORMAT_YV12:
     case SDL_PIXELFORMAT_IYUV:
@@ -1043,11 +1038,16 @@ SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
     case SDL_PIXELFORMAT_YVYU:
         break;
     default:
-        SDL_SW_DestroyYUVTexture(swdata);
         SDL_SetError("Unsupported YUV format");
         return NULL;
     }
 
+    swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata));
+    if (!swdata) {
+        SDL_OutOfMemory();
+        return NULL;
+    }
+
     swdata->format = format;
     swdata->target_format = SDL_PIXELFORMAT_UNKNOWN;
     swdata->w = w;
@@ -1095,7 +1095,7 @@ SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
         swdata->planes[0] = swdata->pixels;
         break;
     default:
-        /* We should never get here (caught above) */
+        SDL_assert(0 && "We should never get here (caught above)");
         break;
     }
 

+ 376 - 54
Source/ThirdParty/SDL/src/render/direct3d/SDL_render_d3d.c

@@ -29,7 +29,7 @@
 #include "SDL_loadso.h"
 #include "SDL_syswm.h"
 #include "../SDL_sysrender.h"
-#include "stdio.h"
+#include <stdio.h>
 
 #if SDL_VIDEO_RENDER_D3D
 #define D3D_DEBUG_INFO
@@ -169,6 +169,32 @@ HRESULT WINAPI
         LPD3DXBUFFER*                   ppShader,
         LPD3DXBUFFER*                   ppErrorMsgs);
 
+static void PrintShaderData(LPDWORD shader_data, DWORD shader_size)
+{
+    OutputDebugStringA("const DWORD shader_data[] = {\n\t");
+    {
+        SDL_bool newline = SDL_FALSE;
+        unsigned i;
+        for (i = 0; i < shader_size / sizeof(DWORD); ++i) {
+            char dword[11];
+            if (i > 0) {
+                if ((i%6) == 0) {
+                    newline = SDL_TRUE;
+                }
+                if (newline) {
+                    OutputDebugStringA(",\n    ");
+                    newline = SDL_FALSE;
+                } else {
+                    OutputDebugStringA(", ");
+                }
+            }
+            SDL_snprintf(dword, sizeof(dword), "0x%8.8x", shader_data[i]);
+            OutputDebugStringA(dword);
+        }
+        OutputDebugStringA("\n};\n");
+    }
+}
+
 #endif /* ASSEMBLE_SHADER */
 
 
@@ -227,17 +253,27 @@ typedef struct
     D3DPRESENT_PARAMETERS pparams;
     SDL_bool updateSize;
     SDL_bool beginScene;
-    D3DTEXTUREFILTERTYPE scaleMode;
+    SDL_bool enableSeparateAlphaBlend;
+    D3DTEXTUREFILTERTYPE scaleMode[8];
     IDirect3DSurface9 *defaultRenderTarget;
     IDirect3DSurface9 *currentRenderTarget;
     void* d3dxDLL;
     ID3DXMatrixStack *matrixStack;
+    LPDIRECT3DPIXELSHADER9 ps_yuv;
 } D3D_RenderData;
 
 typedef struct
 {
     IDirect3DTexture9 *texture;
     D3DTEXTUREFILTERTYPE scaleMode;
+
+    /* YV12 texture support */
+    SDL_bool yuv;
+    IDirect3DTexture9 *utexture;
+    IDirect3DTexture9 *vtexture;
+    Uint8 *pixels;
+    int pitch;
+    SDL_Rect locked_rect;
 } D3D_TextureData;
 
 typedef struct
@@ -336,6 +372,9 @@ PixelFormatToD3DFMT(Uint32 format)
         return D3DFMT_X8R8G8B8;
     case SDL_PIXELFORMAT_ARGB8888:
         return D3DFMT_A8R8G8B8;
+    case SDL_PIXELFORMAT_YV12:
+    case SDL_PIXELFORMAT_IYUV:
+        return D3DFMT_L8;
     default:
         return D3DFMT_UNKNOWN;
     }
@@ -384,7 +423,8 @@ D3D_Reset(SDL_Renderer * renderer)
                                     D3DCULL_NONE);
     IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE);
     IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
-    data->scaleMode = D3DTEXF_FORCE_DWORD;
+    SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode));
+    D3D_UpdateViewport(renderer);
     return 0;
 }
 
@@ -410,7 +450,6 @@ D3D_ActivateRenderer(SDL_Renderer * renderer)
         if (D3D_Reset(renderer) < 0) {
             return -1;
         }
-        D3D_UpdateViewport(renderer);
 
         data->updateSize = SDL_FALSE;
     }
@@ -586,7 +625,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
         return NULL;
     }
     data->beginScene = SDL_TRUE;
-    data->scaleMode = D3DTEXF_FORCE_DWORD;
+    SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode));
 
     /* Get presentation parameters to fill info */
     result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain);
@@ -615,6 +654,10 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
         renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
     }
 
+    if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) {
+        data->enableSeparateAlphaBlend = SDL_TRUE;
+    }
+
     /* Set up parameters for rendering */
     IDirect3DDevice9_SetVertexShader(data->device, NULL);
     IDirect3DDevice9_SetFVF(data->device,
@@ -637,6 +680,10 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
                                           D3DTA_TEXTURE);
     IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2,
                                           D3DTA_DIFFUSE);
+    /* Enable separate alpha blend function, if possible */
+    if (data->enableSeparateAlphaBlend) {
+        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+    }
     /* Disable second texture stage, since we're done */
     IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP,
                                           D3DTOP_DISABLE);
@@ -667,6 +714,136 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
     IDirect3DDevice9_SetTransform(data->device, D3DTS_WORLD, &matrix);
     IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, &matrix);
 
+    if (caps.MaxSimultaneousTextures >= 3)
+    {
+#ifdef ASSEMBLE_SHADER
+        /* This shader was created by running the following HLSL through the fxc compiler
+           and then tuning the generated assembly.
+
+           fxc /T fx_4_0 /O3 /Gfa /Fc yuv.fxc yuv.fx
+
+           --- yuv.fx ---
+           Texture2D g_txY;
+           Texture2D g_txU;
+           Texture2D g_txV;
+
+           SamplerState samLinear
+           {
+               Filter = ANISOTROPIC;
+               AddressU = Clamp;
+               AddressV = Clamp;
+               MaxAnisotropy = 1;
+           };
+
+           struct VS_OUTPUT
+           {
+                float2 TextureUV  : TEXCOORD0;
+           };
+
+           struct PS_OUTPUT
+           {
+                float4 RGBAColor : SV_Target;
+           };
+
+           PS_OUTPUT YUV420( VS_OUTPUT In ) 
+           {
+               const float3 offset = {-0.0625, -0.5, -0.5};
+               const float3 Rcoeff = {1.164,  0.000,  1.596};
+               const float3 Gcoeff = {1.164, -0.391, -0.813};
+               const float3 Bcoeff = {1.164,  2.018,  0.000};
+
+               PS_OUTPUT Output;
+               float2 TextureUV = In.TextureUV;
+
+               float3 yuv;
+               yuv.x = g_txY.Sample( samLinear, TextureUV ).r;
+               yuv.y = g_txU.Sample( samLinear, TextureUV ).r;
+               yuv.z = g_txV.Sample( samLinear, TextureUV ).r;
+
+               yuv += offset;
+               Output.RGBAColor.r = dot(yuv, Rcoeff);
+               Output.RGBAColor.g = dot(yuv, Gcoeff);
+               Output.RGBAColor.b = dot(yuv, Bcoeff);
+               Output.RGBAColor.a = 1.0f;
+
+               return Output;
+           }
+
+           technique10 RenderYUV420
+           {
+               pass P0
+               {
+                    SetPixelShader( CompileShader( ps_4_0_level_9_0, YUV420() ) );
+               }
+           }
+        */
+        const char *shader_text =
+            "ps_2_0\n"
+            "def c0, -0.0625, -0.5, -0.5, 1\n"
+            "def c1, 1.16400003, 0, 1.59599996, 0\n"
+            "def c2, 1.16400003, -0.391000003, -0.813000023, 0\n"
+            "def c3, 1.16400003, 2.01799989, 0, 0\n"
+            "dcl t0.xy\n"
+            "dcl v0.xyzw\n"
+            "dcl_2d s0\n"
+            "dcl_2d s1\n"
+            "dcl_2d s2\n"
+            "texld r0, t0, s0\n"
+            "texld r1, t0, s1\n"
+            "texld r2, t0, s2\n"
+            "mov r0.y, r1.x\n"
+            "mov r0.z, r2.x\n"
+            "add r0.xyz, r0, c0\n"
+            "dp3 r1.x, r0, c1\n"
+            "dp3 r1.y, r0, c2\n"
+            "dp2add r1.z, r0, c3, c3.z\n"   /* Logically this is "dp3 r1.z, r0, c3" but the optimizer did its magic */
+            "mov r1.w, c0.w\n"
+            "mul r0, r1, v0\n"              /* Not in the HLSL, multiply by vertex color */
+            "mov oC0, r0\n"
+        ;
+        LPD3DXBUFFER pCode;
+        LPD3DXBUFFER pErrorMsgs;
+        LPDWORD shader_data = NULL;
+        DWORD   shader_size = 0;
+        result = D3DXAssembleShader(shader_text, SDL_strlen(shader_text), NULL, NULL, 0, &pCode, &pErrorMsgs);
+        if (!FAILED(result)) {
+            shader_data = (DWORD*)pCode->lpVtbl->GetBufferPointer(pCode);
+            shader_size = pCode->lpVtbl->GetBufferSize(pCode);
+            PrintShaderData(shader_data, shader_size);
+        } else {
+            const char *error = (const char *)pErrorMsgs->lpVtbl->GetBufferPointer(pErrorMsgs);
+            SDL_SetError("Couldn't assemble shader: %s", error);
+        }
+#else
+        const DWORD shader_data[] = {
+            0xffff0200, 0x05000051, 0xa00f0000, 0xbd800000, 0xbf000000, 0xbf000000,
+            0x3f800000, 0x05000051, 0xa00f0001, 0x3f94fdf4, 0x00000000, 0x3fcc49ba,
+            0x00000000, 0x05000051, 0xa00f0002, 0x3f94fdf4, 0xbec83127, 0xbf5020c5,
+            0x00000000, 0x05000051, 0xa00f0003, 0x3f94fdf4, 0x400126e9, 0x00000000,
+            0x00000000, 0x0200001f, 0x80000000, 0xb0030000, 0x0200001f, 0x80000000,
+            0x900f0000, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000,
+            0xa00f0801, 0x0200001f, 0x90000000, 0xa00f0802, 0x03000042, 0x800f0000,
+            0xb0e40000, 0xa0e40800, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801,
+            0x03000042, 0x800f0002, 0xb0e40000, 0xa0e40802, 0x02000001, 0x80020000,
+            0x80000001, 0x02000001, 0x80040000, 0x80000002, 0x03000002, 0x80070000,
+            0x80e40000, 0xa0e40000, 0x03000008, 0x80010001, 0x80e40000, 0xa0e40001,
+            0x03000008, 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001,
+            0x80e40000, 0xa0e40003, 0xa0aa0003, 0x02000001, 0x80080001, 0xa0ff0000,
+            0x03000005, 0x800f0000, 0x80e40001, 0x90e40000, 0x02000001, 0x800f0800,
+            0x80e40000, 0x0000ffff
+        };
+#endif
+        if (shader_data != NULL) {
+            result = IDirect3DDevice9_CreatePixelShader(data->device, shader_data, &data->ps_yuv);
+            if (!FAILED(result)) {
+                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
+                renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
+            } else {
+                D3D_SetError("CreatePixelShader()", result);
+            }
+        }
+    }
+
     return renderer;
 }
 
@@ -687,10 +864,8 @@ GetScaleQuality(void)
 
     if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
         return D3DTEXF_POINT;
-    } else if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) {
+    } else /*if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0)*/ {
         return D3DTEXF_LINEAR;
-    } else {
-        return D3DTEXF_ANISOTROPIC;
     }
 }
 
@@ -735,14 +910,35 @@ D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
         return D3D_SetError("CreateTexture()", result);
     }
 
+    if (texture->format == SDL_PIXELFORMAT_YV12 ||
+        texture->format == SDL_PIXELFORMAT_IYUV) {
+        data->yuv = SDL_TRUE;
+
+        result =
+            IDirect3DDevice9_CreateTexture(renderdata->device, texture->w / 2,
+                                           texture->h / 2, 1, usage,
+                                           PixelFormatToD3DFMT(texture->format),
+                                           pool, &data->utexture, NULL);
+        if (FAILED(result)) {
+            return D3D_SetError("CreateTexture()", result);
+        }
+
+        result =
+            IDirect3DDevice9_CreateTexture(renderdata->device, texture->w / 2,
+                                           texture->h / 2, 1, usage,
+                                           PixelFormatToD3DFMT(texture->format),
+                                           pool, &data->vtexture, NULL);
+        if (FAILED(result)) {
+            return D3D_SetError("CreateTexture()", result);
+        }
+    }
+
     return 0;
 }
 
 static int
-D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
-                  const SDL_Rect * rect, const void *pixels, int pitch)
+D3D_UpdateTextureInternal(IDirect3DTexture9 *texture, Uint32 format, SDL_bool full_texture, int x, int y, int w, int h, const void *pixels, int pitch)
 {
-    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
     RECT d3drect;
     D3DLOCKED_RECT locked;
     const Uint8 *src;
@@ -750,39 +946,70 @@ D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
     int row, length;
     HRESULT result;
 
-#ifdef USE_DYNAMIC_TEXTURE
-    if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
-        rect->x == 0 && rect->y == 0 &&
-        rect->w == texture->w && rect->h == texture->h) {
-        result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, NULL, D3DLOCK_DISCARD);
-    } else
-#endif
-    {
-        d3drect.left = rect->x;
-        d3drect.right = rect->x + rect->w;
-        d3drect.top = rect->y;
-        d3drect.bottom = rect->y + rect->h;
-        result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
+    if (full_texture) {
+        result = IDirect3DTexture9_LockRect(texture, 0, &locked, NULL, D3DLOCK_DISCARD);
+    } else {
+        d3drect.left = x;
+        d3drect.right = x + w;
+        d3drect.top = y;
+        d3drect.bottom = y + h;
+        result = IDirect3DTexture9_LockRect(texture, 0, &locked, &d3drect, 0);
     }
 
     if (FAILED(result)) {
         return D3D_SetError("LockRect()", result);
     }
 
-    src = pixels;
+    src = (const Uint8 *)pixels;
     dst = locked.pBits;
-    length = rect->w * SDL_BYTESPERPIXEL(texture->format);
+    length = w * SDL_BYTESPERPIXEL(format);
     if (length == pitch && length == locked.Pitch) {
-        SDL_memcpy(dst, src, length*rect->h);
+        SDL_memcpy(dst, src, length*h);
     } else {
-        for (row = 0; row < rect->h; ++row) {
+        for (row = 0; row < h; ++row) {
             SDL_memcpy(dst, src, length);
             src += pitch;
             dst += locked.Pitch;
         }
     }
-    IDirect3DTexture9_UnlockRect(data->texture, 0);
+    IDirect3DTexture9_UnlockRect(texture, 0);
+
+    return 0;
+}
+
+static int
+D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+                  const SDL_Rect * rect, const void *pixels, int pitch)
+{
+    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
+    SDL_bool full_texture = SDL_FALSE;
+
+#ifdef USE_DYNAMIC_TEXTURE
+    if (texture->access == SDL_TEXTUREACCESS_STREAMING &&
+        rect->x == 0 && rect->y == 0 &&
+        rect->w == texture->w && rect->h == texture->h) {
+        full_texture = SDL_TRUE;
+    }
+#endif
+
+    if (D3D_UpdateTextureInternal(data->texture, texture->format, full_texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
+        return -1;
+    }
+
+    if (data->yuv) {
+        /* Skip to the correct offset into the next texture */
+        pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
+
+        if (D3D_UpdateTextureInternal(texture->format == SDL_PIXELFORMAT_YV12 ? data->vtexture : data->utexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
+            return -1;
+        }
 
+        /* Skip to the correct offset into the next texture */
+        pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4);
+        if (D3D_UpdateTextureInternal(texture->format == SDL_PIXELFORMAT_YV12 ? data->utexture : data->vtexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {
+            return -1;
+        }
+    }
     return 0;
 }
 
@@ -795,17 +1022,33 @@ D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
     D3DLOCKED_RECT locked;
     HRESULT result;
 
-    d3drect.left = rect->x;
-    d3drect.right = rect->x + rect->w;
-    d3drect.top = rect->y;
-    d3drect.bottom = rect->y + rect->h;
+    if (data->yuv) {
+        // It's more efficient to upload directly...
+        if (!data->pixels) {
+            data->pitch = texture->w;
+            data->pixels = (Uint8 *)SDL_malloc((texture->h * data->pitch * 3) / 2);
+            if (!data->pixels) {
+                return SDL_OutOfMemory();
+            }
+        }
+        data->locked_rect = *rect;
+        *pixels =
+            (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
+                      rect->x * SDL_BYTESPERPIXEL(texture->format));
+        *pitch = data->pitch;
+    } else {
+        d3drect.left = rect->x;
+        d3drect.right = rect->x + rect->w;
+        d3drect.top = rect->y;
+        d3drect.bottom = rect->y + rect->h;
 
-    result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
-    if (FAILED(result)) {
-        return D3D_SetError("LockRect()", result);
+        result = IDirect3DTexture9_LockRect(data->texture, 0, &locked, &d3drect, 0);
+        if (FAILED(result)) {
+            return D3D_SetError("LockRect()", result);
+        }
+        *pixels = locked.pBits;
+        *pitch = locked.Pitch;
     }
-    *pixels = locked.pBits;
-    *pitch = locked.Pitch;
     return 0;
 }
 
@@ -814,7 +1057,15 @@ D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
     D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;
 
-    IDirect3DTexture9_UnlockRect(data->texture, 0);
+    if (data->yuv) {
+        const SDL_Rect *rect = &data->locked_rect;
+        void *pixels =
+            (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
+                      rect->x * SDL_BYTESPERPIXEL(texture->format));
+        D3D_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
+    } else {
+        IDirect3DTexture9_UnlockRect(data->texture, 0);
+    }
 }
 
 static int
@@ -902,7 +1153,7 @@ D3D_UpdateClipRect(SDL_Renderer * renderer)
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
         r.left = rect->x;
         r.top = rect->y;
-        r.right = rect->w + rect->w;
+        r.right = rect->x + rect->w;
         r.bottom = rect->y + rect->h;
 
         result = IDirect3DDevice9_SetScissorRect(data->device, &r);
@@ -979,6 +1230,12 @@ D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
                                         D3DBLEND_SRCALPHA);
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
                                         D3DBLEND_INVSRCALPHA);
+        if (data->enableSeparateAlphaBlend) {
+            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
+                                            D3DBLEND_ONE);
+            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
+                                            D3DBLEND_INVSRCALPHA);
+        }
         break;
     case SDL_BLENDMODE_ADD:
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
@@ -987,6 +1244,12 @@ D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
                                         D3DBLEND_SRCALPHA);
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
                                         D3DBLEND_ONE);
+        if (data->enableSeparateAlphaBlend) {
+            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
+                                            D3DBLEND_ZERO);
+            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
+                                            D3DBLEND_ONE);
+        }
         break;
     case SDL_BLENDMODE_MOD:
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
@@ -995,6 +1258,12 @@ D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
                                         D3DBLEND_ZERO);
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
                                         D3DBLEND_SRCCOLOR);
+        if (data->enableSeparateAlphaBlend) {
+            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
+                                            D3DBLEND_ZERO);
+            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
+                                            D3DBLEND_ONE);
+        }
         break;
     }
 }
@@ -1169,6 +1438,18 @@ D3D_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
     return 0;
 }
 
+static void
+D3D_UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
+{
+    if (texturedata->scaleMode != data->scaleMode[index]) {
+        IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER,
+                                         texturedata->scaleMode);
+        IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER,
+                                         texturedata->scaleMode);
+        data->scaleMode[index] = texturedata->scaleMode;
+    }
+}
+
 static int
 D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
                const SDL_Rect * srcrect, const SDL_FRect * dstrect)
@@ -1228,13 +1509,7 @@ D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
 
     D3D_SetBlendMode(data, texture->blendMode);
 
-    if (texturedata->scaleMode != data->scaleMode) {
-        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
-                                         texturedata->scaleMode);
-        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
-                                         texturedata->scaleMode);
-        data->scaleMode = texturedata->scaleMode;
-    }
+    D3D_UpdateTextureScaleMode(data, texturedata, 0);
 
     result =
         IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
@@ -1242,6 +1517,28 @@ D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
     if (FAILED(result)) {
         return D3D_SetError("SetTexture()", result);
     }
+
+    if (texturedata->yuv) {
+        shader = data->ps_yuv;
+
+        D3D_UpdateTextureScaleMode(data, texturedata, 1);
+        D3D_UpdateTextureScaleMode(data, texturedata, 2);
+
+        result =
+            IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *)
+                                        texturedata->utexture);
+        if (FAILED(result)) {
+            return D3D_SetError("SetTexture()", result);
+        }
+
+        result =
+            IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)
+                                        texturedata->vtexture);
+        if (FAILED(result)) {
+            return D3D_SetError("SetTexture()", result);
+        }
+    }
+
     if (shader) {
         result = IDirect3DDevice9_SetPixelShader(data->device, shader);
         if (FAILED(result)) {
@@ -1348,13 +1645,7 @@ D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
     ID3DXMatrixStack_Translate(data->matrixStack, (float)dstrect->x + centerx, (float)dstrect->y + centery, (float)0.0);
     IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)ID3DXMatrixStack_GetTop(data->matrixStack));
 
-    if (texturedata->scaleMode != data->scaleMode) {
-        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER,
-                                         texturedata->scaleMode);
-        IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER,
-                                         texturedata->scaleMode);
-        data->scaleMode = texturedata->scaleMode;
-    }
+    D3D_UpdateTextureScaleMode(data, texturedata, 0);
 
     result =
         IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)
@@ -1362,6 +1653,28 @@ D3D_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
     if (FAILED(result)) {
         return D3D_SetError("SetTexture()", result);
     }
+
+    if (texturedata->yuv) {
+        shader = data->ps_yuv;
+
+        D3D_UpdateTextureScaleMode(data, texturedata, 1);
+        D3D_UpdateTextureScaleMode(data, texturedata, 2);
+
+        result =
+            IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *)
+                                        texturedata->utexture);
+        if (FAILED(result)) {
+            return D3D_SetError("SetTexture()", result);
+        }
+
+        result =
+            IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)
+                                        texturedata->vtexture);
+        if (FAILED(result)) {
+            return D3D_SetError("SetTexture()", result);
+        }
+    }
+
     if (shader) {
         result = IDirect3DDevice9_SetPixelShader(data->device, shader);
         if (FAILED(result)) {
@@ -1484,6 +1797,15 @@ D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
     if (data->texture) {
         IDirect3DTexture9_Release(data->texture);
     }
+    if (data->utexture) {
+        IDirect3DTexture9_Release(data->utexture);
+    }
+    if (data->vtexture) {
+        IDirect3DTexture9_Release(data->vtexture);
+    }
+    if (data->pixels) {
+        SDL_free(data->pixels);
+    }
     SDL_free(data);
     texture->driverdata = NULL;
 }

+ 0 - 315
Source/ThirdParty/SDL/src/render/nds/SDL_libgl2D.c

@@ -1,315 +0,0 @@
-/*
- * Note: The Nintendo DS port to SDL uses excerpts from the libGL2D,
- * with permission of the original author. The following is mostly his
- * code/comments.
- *
- *
- *	Easy GL2D
- *
- *	Relminator 2010 
- *	Richard Eric M. Lope BSN RN
- *
- *	http://rel.betterwebber.com
- *
- *	A very small and simple DS rendering lib using the 3d core to render 2D stuff
- */
-#include "SDL_config.h"
-
-#if SDL_VIDEO_RENDER_NDS
-
-#include "SDL_libgl2D.h"
-
-/*
- * Our static global variable used for Depth values since we cannot
- * disable depth testing in the DS hardware This value is incremented
- * for every draw call. */
-v16 g_depth;
-int gCurrentTexture;
-
-/*
- * !!! PRIVATE !!!  Set orthographic projection at 1:1 correspondence
- * to screen coords glOrtho expects f32 values but if we use the
- * standard f32 values, we need to rescale either every vert or the
- * modelview matrix by the same amount to make it work.  That's gonna
- * give us lots of overflows and headaches.  So we "scale down" and
- * use an all integer value.
- */
-void SetOrtho(void)		
-{
-	glMatrixMode(GL_PROJECTION); // set matrixmode to projection
-	glLoadIdentity();			   // reset
-	glOrthof32(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1 << 12, 1 << 12);  // downscale projection matrix
-}
-
-/*
- * Initializes GL in 2D mode Also initializes GL in 3d mode so that we
- * could combine 2D and 3D later Almost a direct copy from the DS
- * example files
- */
-void glScreen2D(void)
-{
-	// initialize gl
-	glInit();
-	
-	// enable textures
-	glEnable(GL_TEXTURE_2D);
-	
-	// enable antialiasing
-	glEnable(GL_ANTIALIAS);
-		
-	// setup the rear plane
-	glClearColor(0, 0, 0, 31); // BG must be opaque for AA to work
-	glClearPolyID(63); // BG must have a unique polygon ID for AA to work
-	
-	glClearDepth(GL_MAX_DEPTH);
-
-	// this should work the same as the normal gl call
-	glViewport(0,0,255,191);
-
-	// any floating point gl call is being converted to fixed prior to being implemented
-	glMatrixMode(GL_PROJECTION);
-	glLoadIdentity();
-	gluPerspective(70, 256.0 / 192.0, 1, 200);
-
-	gluLookAt(	0.0, 0.0, 1.0,		//camera possition 
-				0.0, 0.0, 0.0,		//look at
-				0.0, 1.0, 0.0);		//up
-
-	glMaterialf(GL_AMBIENT, RGB15(31,31,31));
-	glMaterialf(GL_DIFFUSE, RGB15(31,31,31));
-	glMaterialf(GL_SPECULAR, BIT(15) | RGB15(31,31,31));
-	glMaterialf(GL_EMISSION, RGB15(31,31,31));
-
-	// ds uses a table for shinyness..this generates a half-ass one
-	glMaterialShinyness();
-
-	// not a real gl function and will likely change
-	glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK);
-}
-
-/*
- * Sets up OpenGL for 2d rendering Call this before drawing any of
- * GL2D's drawing or sprite functions.
- */
-void glBegin2D(void)
-{
-	// save 3d perpective projection matrix
-	glMatrixMode(GL_PROJECTION);   
-    glPushMatrix();
-	
-	// save 3d modelview matrix for safety
-	glMatrixMode(GL_MODELVIEW);
-    glPushMatrix();
-	
-	
-	// what?!! No glDisable(GL_DEPTH_TEST)?!!!!!!
-	glEnable(GL_BLEND);
-	glEnable(GL_TEXTURE_2D);
-	glDisable(GL_ANTIALIAS);	// disable AA
-	glDisable(GL_OUTLINE);	// disable edge-marking
-
-	glColor(0x7FFF);			// max color
-	
-	glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE);  // no culling
-
-	SetOrtho();
-	
-	glMatrixMode(GL_TEXTURE);	// reset texture matrix just in case we did some funky stuff with it
-	glLoadIdentity();
-	
-	glMatrixMode(GL_MODELVIEW); // reset modelview matrix. No need to scale up by << 12
-	glLoadIdentity();
-
-	gCurrentTexture = 0;		// set current texture to 0 
-	g_depth = 0; // set depth to 0. We need this var since we cannot disable depth testing
-}
-
-/*
- * Issue this after drawing 2d so that we don't mess the matrix stack.
- * The complement of glBegin2D.
- */
-void glEnd2D(void)
-{
-	// restore 3d matrices and set current matrix to modelview
-	glMatrixMode(GL_PROJECTION);    
-    glPopMatrix(1);
-	glMatrixMode(GL_MODELVIEW);
-    glPopMatrix(1);
-}
-
-/*
- * Draws a pixel
- * Parameters:
- *   x,y 	-> First coordinate of the line 
- *   color 	-> RGB15/ARGB16 color 
- */
-void glPutPixel(int x, int y, int color)
-{
-	glBindTexture(0, 0);
-	glColor(color);
-	glBegin(GL_TRIANGLES);
-		gxVertex3i(x, y, g_depth);
-		gxVertex2i(x, y);
-		gxVertex2i(x, y);
-	glEnd();
-	glColor(0x7FFF);
-	g_depth++;
-	gCurrentTexture = 0;
-}
-
-/*
- * Draws a line
- * Parameters:
- *   x1,y1 	-> First coordinate of the line 
- *   x2,y2 	-> Second coordinate of the line 
- *   color 	-> RGB15/ARGB16 color
- */
-void glLine(int x1, int y1, int x2, int y2, int color)
-{
-	x2++;
-	y2++;
-	
-	glBindTexture(0, 0);
-	glColor(color);
-	glBegin(GL_TRIANGLES);
-		gxVertex3i(x1, y1, g_depth);
-		gxVertex2i(x2, y2);
-		gxVertex2i(x2, y2);
-	glEnd();
-	glColor(0x7FFF);
-	g_depth++;
-	gCurrentTexture = 0;
-}
-
-/*
- * Draws a Filled Box
- * Parameters:
- *   x1,y1 	-> Top-left corner of the box 
- *   x2,y2 	-> Bottom-Right corner of the box 
- *   color 	-> RGB15/ARGB16 color 
-*/
-void glBoxFilled(int x1, int y1, int x2, int y2, int color)
-{
-	x2++;
-	y2++;
-	
-	glBindTexture(0, 0);
-	glColor(color);
-	glBegin(GL_QUADS);
-		gxVertex3i(x1, y1, g_depth); // use 3i for first vertex so that we increment HW depth
-		gxVertex2i(x1, y2); // no need for 3 vertices as 2i would share last depth call
-		gxVertex2i(x2, y2);
-		gxVertex2i(x2, y1);
-	glEnd();
-	glColor(0x7FFF);
-	g_depth++;
-	gCurrentTexture = 0;
-}
-
-/*
- *
- * Create a tile.
- * Very rigid and prone to human error.
- *
- * Parameters:
- *   *sprite 		 -> pointer to a glImage
- *   texture_width   -> width/height of the texture;
- *   texture_height  ->  valid sizes are enumerated in GL_TEXTURE_TYPE_ENUM (see glTexImage2d)
- *   sprite_width
- *   sprite_height   -> width/height of the picture in the texture.
- *   type 		     -> The format of the texture (see glTexImage2d)
- *   param 		     -> parameters for the texture (see glTexImage2d)
- */
-int glLoadTile(glImage              *sprite,
-			   int                  texture_width,
-			   int                  texture_height,
-			   int                  sprite_width,
-			   int                  sprite_height,
-			   GL_TEXTURE_TYPE_ENUM type,
-			   int 	                param,
-			   int					pallette_width,
-			   const u16			*palette,
-			   const uint8          *texture)
-{
-	int textureID;
-
-	glGenTextures(1, &textureID);
-	glBindTexture(0, textureID);
-	glTexImage2D(0, 0, type, texture_width, texture_height, 0, param, texture);
-	glColorTableEXT(0, 0, pallette_width, 0, 0, palette);
-
-	sprite->width 			= sprite_width;
-	sprite->height 			= sprite_height;
-	sprite->textureID 		= textureID;
-	
-	return textureID;
-}
-
-/*
- * I made this since the scale wrappers are either the vectorized mode
- * or does not permit you to scale only the axis you want to
- * scale. Needed for sprite scaling.
- */
-static inline void gxScalef32(s32 x, s32 y, s32 z)
-{
-	MATRIX_SCALE = x;
-	MATRIX_SCALE = y;
-	MATRIX_SCALE = z;
-}
-
-/*
- * I this made for future naming conflicts.
- */
-static inline void gxTranslate3f32(int32 x, int32 y, int32 z) 
-{
-	MATRIX_TRANSLATE = x;
-	MATRIX_TRANSLATE = y;
-	MATRIX_TRANSLATE = z;
-}
-
-/*
- * Draws an axis exclusive scaled sprite
- * Parameters:
- *   x 			-> x position of the sprite
- *   y 			-> y position of the sprite
- *   scaleX   	-> 20.12 FP X axis scale value (1 << 12 is normal)
- *   scaleY   	-> 20.12 FP Y axis scale value (1 << 12 is normal)
- *   flipmode 	-> mode for flipping (see GL_FLIP_MODE enum)
- *   *spr 		-> pointer to a glImage
- */
-void glSpriteScaleXY(int x, int y, s32 scaleX, s32 scaleY, int flipmode, const glImage *spr)
-{
-	const int x1 = 0;
-	const int y1 = 0;
-	const int x2 = spr->width;
-	const int y2 = spr->height;
-	const int u1 = ((flipmode & GL_FLIP_H) ? spr->width-1  : 0);
- 	const int u2 = ((flipmode & GL_FLIP_H) ? 0 : spr->width-1);
-	const int v1 = ((flipmode & GL_FLIP_V) ? spr->height-1 : 0);
-	const int v2 = ((flipmode & GL_FLIP_V) ? 0 : spr->height-1);
- 
-    if (spr->textureID != gCurrentTexture)
-    {
-        glBindTexture(GL_TEXTURE_2D, spr->textureID);
-        gCurrentTexture = spr->textureID;
-    }
-
-	glPushMatrix();
-
-		gxTranslate3f32(x, y, 0);
-		gxScalef32(scaleX, scaleY, 1 << 12);
-
-		glBegin(GL_QUADS);
-			
-			gxTexcoord2i(u1, v1); gxVertex3i(x1, y1, g_depth);	
-			gxTexcoord2i(u1, v2); gxVertex2i(x1, y2);
-			gxTexcoord2i(u2, v2); gxVertex2i(x2, y2);
-			gxTexcoord2i(u2, v1); gxVertex2i(x2, y1);
-			
-		glEnd();
-	
-	glPopMatrix(1);
-	g_depth++;
-}
-
-#endif /* SDL_VIDEO_RENDER_NDS */

+ 0 - 154
Source/ThirdParty/SDL/src/render/nds/SDL_libgl2D.h

@@ -1,154 +0,0 @@
-/*
- * Note: The Nintendo DS port to SDL uses excerpts from the libGL2D,
- * with permission of the original author. The following is mostly his
- * code/comments.
- *
- *
- *	Easy GL2D
- *
- *	Relminator 2010 
- *	Richard Eric M. Lope BSN RN
- *
- *	http://rel.betterwebber.com
- *
- *	A very small and simple DS rendering lib using the 3d core to render 2D stuff
- */
-#include "SDL_config.h"
-
-#if SDL_VIDEO_RENDER_NDS
-
-#include <nds/arm9/videoGL.h>
-
-/* LibGL extension(s) */
-static inline void gxTexcoord2i(t16 u, t16 v)
-{
-	GFX_TEX_COORD = (v << 20) | ((u << 4) & 0xFFFF);
-}
-
-static inline void gxVertex3i(v16 x, v16 y, v16 z)
-{
-	GFX_VERTEX16 = (y << 16) | (x & 0xFFFF);
-	GFX_VERTEX16 = ((uint32)(uint16)z);
-}
-
-static inline void gxVertex2i(v16 x, v16 y)
-{
-	GFX_VERTEX_XY = (y << 16) | (x & 0xFFFF);	
-}
-
-/*
- * Enums selecting flipping mode.
- *
- *	These enums are bits for flipping the sprites.
- *	You can "|" (or) GL_FLIP_V and GL_FLIP_H to flip 
- *	both ways.
- */
-typedef enum
-{
-	GL_FLIP_NONE 	= (1 << 0), /* No flipping */
-	GL_FLIP_V 		= (1 << 1), /* Sprite is rendered vertically flipped */
-	GL_FLIP_H 		= (1 << 2), /* Sprite is rendered horizontally flipped */
-} GL_FLIP_MODE;
-
-/* Struct for out GL-Based Images. */
-typedef struct 
-{
-	int		width;		/* Width of the Sprite */      			
-	int 	height;		/* Height of the Sprite */	
-	int		textureID;  /* Texture handle (used in glDeleteTextures())
-						   The texture handle in VRAM (returned by glGenTextures())
-						   ie. This references the actual texture stored in VRAM. */
-} glImage;
-
-extern v16 g_depth;
-extern int gCurrentTexture;
-
-/*
- * Draws an Axis Exclusive Scaled Sprite
- * Parameters:
- *   x X position of the sprite.
- *   y Y position of the sprite.
- *   scaleX 20.12 fixed-point X-Axis scale value (1 << 12 is normal).
- *   scaleY 20.12 fixed-point Y-Axis scale value (1 << 12 is normal).
- *   flipmode mode for flipping (see GL_FLIP_MODE enum).
- *   *spr pointer to a glImage. 
-*/
-void glSpriteScaleXY(int x, int y, s32 scaleX, s32 scaleY, int flipmode, const glImage *spr);
-
-/* Initializes our Tileset (like glInitSpriteset()) but without the use of Texture Packer auto-generated files.
- * Can only be used when tiles in a tilset are of the same dimensions.
- * Parameters:
- *   *sprite Pointer to an array of glImage.
- *   tile_wid Width of each tile in the texture.
- *   tile_hei Height of each tile in the texture.
- *   bmp_wid Width of of the texture or tileset.
- *   bmp_hei height of of the texture or tileset.
- *   type The format of the texture (see glTexImage2d()).
- *   sizeX The horizontal size of the texture; valid sizes are enumerated in GL_TEXTURE_TYPE_ENUM (see glTexImage2d()).
- *   sizeY The vertical size of the texture; valid sizes are enumerated in GL_TEXTURE_TYPE_ENUM (see glTexImage2d()).
- *   param parameters for the texture (see glTexImage2d()). 
- *   pallette_width Length of the palette. Valid values are <b>4, 16, 32, 256</b> (if <b>0</b>, then palette is removed from currently bound texture). 
- *   *palette Pointer to the palette data to load (if NULL, then palette is removed from currently bound texture).
- *   *texture Pointer to the texture data to load.
-*/
-int glLoadTile(glImage              *sprite,
-			   int                  texture_width,
-			   int                  texture_height,
-			   int                  sprite_width,
-			   int                  sprite_height,
-			   GL_TEXTURE_TYPE_ENUM type,
-			   int 	                param,
-			   int					pallette_width,
-			   const u16			*palette,
-			   const uint8          *texture);
-
-/* Initializes GL in 2D mode */
-void glScreen2D(void);
-
-/* 
- * Sets up OpenGL for 2d rendering. 
- *
- * Call this before drawing any of GL2D's drawing or sprite functions.
- */
-void glBegin2D(void);
-
-/*
- * Issue this after drawing 2d so that we don't mess the matrix stack.
- *
- * The complement of glBegin2D().
- */
-void glEnd2D(void);
-
-/*
- * Draws a Pixel
- *   x X position of the pixel.
- *   y Y position of the pixel.
- *   color RGB15/ARGB16 color.
- */
-void glPutPixel(int x, int y, int color);
-
-/*
- * Draws a Line
- *   x1,y1 Top-Left coordinate of the line.
- *   x2,y2 Bottom-Right coordinate of the line.
- *   color RGB15/ARGB16 color.
- */
-void glLine(int x1, int y1, int x2, int y2, int color);
-
-/* 
- * Draws a Box
- *   x1,y1 Top-Left coordinate of the box.
- *   x2,y2 Bottom-Right coordinate of the box.
- *   color RGB15/ARGB16 color.
-*/
-void glBox(int x1, int y1, int x2, int y2, int color);
-
-/*
- * Draws a Filled Box
- *   x1,y1 Top-Left coordinate of the box.
- *   x2,y2 Bottom-Right coordinate of the box.
- *   color RGB15/ARGB16 color.
- */
-void glBoxFilled(int x1, int y1, int x2, int y2, int color);
-
-#endif /* SDL_VIDEO_RENDER_NDS */

+ 0 - 418
Source/ThirdParty/SDL/src/render/nds/SDL_ndsrender.c

@@ -1,418 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2012 Sam Lantinga <[email protected]>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-#include "SDL_config.h"
-
-#if SDL_VIDEO_RENDER_NDS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <nds.h>
-
-#include "SDL_libgl2D.h"
-
-#include "SDL_video.h"
-#include "../../video/SDL_sysvideo.h"
-#include "SDL_render.h"
-#include "../SDL_sysrender.h"
-#include "SDL_log.h"
-
-/* Draws a partial sprite. Based on glSprite. */
-static void glSpritePartial(const SDL_Rect * srcrect, int x, int y, int flipmode, const glImage *spr)
-{
-	int x1 = x;
-	int y1 = y;
-	int x2 = x + srcrect->w;
-	int y2 = y + srcrect->h;
-
-	int	u1 = srcrect->x + ((flipmode & GL_FLIP_H) ? spr->width-1  : 0);
- 	int	u2 = srcrect->x + ((flipmode & GL_FLIP_H) ? 0 : srcrect->h);
-	int v1 = srcrect->y + ((flipmode & GL_FLIP_V) ? spr->height-1 : 0);
- 	int v2 = srcrect->y + ((flipmode & GL_FLIP_V) ? 0 : srcrect->h);
-
-    if (spr->textureID != gCurrentTexture) {
-        glBindTexture(GL_TEXTURE_2D, spr->textureID);
-        gCurrentTexture = spr->textureID;
-    }
-
-	glBegin(GL_QUADS);
-		
-		gxTexcoord2i(u1, v1); gxVertex3i(x1, y1, g_depth);	
-		gxTexcoord2i(u1, v2); gxVertex2i(x1, y2);
-		gxTexcoord2i(u2, v2); gxVertex2i(x2, y2);
-		gxTexcoord2i(u2, v1); gxVertex2i(x2, y1);
-		
-	glEnd();
-	
-	g_depth++;
-}
-
-/* SDL NDS renderer implementation */
-
-extern SDL_RenderDriver NDS_RenderDriver;
-
-typedef struct
-{
-	/* Whether current 3D engine is on the main or sub screen. */
-	int is_sub;
-} NDS_RenderData;
-
-typedef struct
-{
-	glImage image[1];
-} NDS_TextureData;
-
-static int NDS_UpdateViewport(SDL_Renderer *renderer)
-{
-	/* Nothing to do. */
-	return 0;
-}
-
-static int
-NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
-               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
-{
-    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
-    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
-	int dest_y;
-
-	if (data->is_sub) {
-		dest_y = dstrect->y;
-	} else {
-		dest_y = dstrect->y-SCREEN_HEIGHT;
-	}
-
-	if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
-		/* No scaling */
-		glSpritePartial(srcrect, dstrect->x, dest_y, GL_FLIP_NONE, txdat->image);
-	} else {
-		/* Convert the scaling proportion into a 20.12 value. */
-		s32 scale_w = divf32(dstrect->w << 12, texture->w << 12);
-		s32 scale_h = divf32(dstrect->h << 12, texture->h << 12);
-
-		glSpriteScaleXY(dstrect->x, dest_y, scale_w, scale_h, GL_FLIP_NONE, txdat->image);
-	}
-
-    return 0;
-}
-
-static int NDS_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
-{
-    NDS_TextureData *txdat = NULL;
-    int i;
-
-	SDL_Log("NDS_CreateTexture: NDS_CreateTexture.\n");
-
-	/* Sanity checks. */
-	for (i=0; i<NDS_RenderDriver.info.num_texture_formats; i++) {
-		if (texture->format == NDS_RenderDriver.info.texture_formats[i])
-			break;
-	}
-	if (i == NDS_RenderDriver.info.num_texture_formats) {
-		SDL_SetError("Unsupported texture format (%x)", texture->format);
-		return -1;
-	}
-
-	if (texture->w > NDS_RenderDriver.info.max_texture_width) {
-		SDL_SetError("Texture too large (%d)", texture->w);
-		return -1;
-	}
-
-	if (texture->h > NDS_RenderDriver.info.max_texture_height) {
-		SDL_SetError("Texture too tall (%d)", texture->h);
-		return -1;
-	}
-
-	texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
-	txdat = (NDS_TextureData *) texture->driverdata;
-	if (!txdat) {
-		SDL_OutOfMemory();
-		return -1;
-	}
-
-    return 0;
-}
-
-static void
-NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
-{
-    NDS_TextureData *txdat = texture->driverdata;
-
-    /* free anything else allocated for texture */
-    SDL_free(txdat);
-}
-
-/* size is no more than 512. */
-static int get_gltexture_size(unsigned int size)
-{
-	if (size > 256)
-		return TEXTURE_SIZE_512;
-	else if (size > 128)
-		return TEXTURE_SIZE_256;
-	else if (size > 64)
-		return TEXTURE_SIZE_128;
-	else if (size > 32)
-		return TEXTURE_SIZE_64;
-	else if (size > 16)
-		return TEXTURE_SIZE_32;
-	else if (size > 8)
-		return TEXTURE_SIZE_16;
-	else
-		return TEXTURE_SIZE_8;
-}
-
-static int NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
-							 const SDL_Rect * rect, const void *pixels, int pitch)
-{
-    NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
-	char *new_pixels = NULL;
-	const int gl_w = get_gltexture_size(rect->w);
-	const int gl_h = get_gltexture_size(rect->h);
-	const int w = 1 << (3+gl_w);	/* Texture sizes must be a power of 2. */
-	const int h = 1 << (3+gl_h);	/* Texture sizes must be a power of 2. */
-
-	if (w != rect->w || h != rect->h) {
-		/* Allocate a temporary surface and copy pixels into it while
-		 * enlarging the pitch. */
-		const char *src;
-		char *dst;
-		int new_pitch = 2 * w;
-		int i;
-
-		new_pixels = malloc(2 * w * h);
-		if (!new_pixels)
-			return SDL_ENOMEM;
-
-		src = pixels;
-		dst = new_pixels;
-		for (i=0; i<rect->h; i++) {
-			memcpy(dst, src, pitch);
-			src += pitch;
-			dst += new_pitch;
-		}
-	}
-
-	glLoadTile(txdat->image,
-				  gl_w, gl_h,
-				  rect->w, rect->h,
-				  texture->format == SDL_PIXELFORMAT_ABGR1555 ? GL_RGBA : GL_RGB,
-				  TEXGEN_OFF, 0, NULL,
-				  new_pixels? new_pixels : pixels);
-
-	if (new_pixels)
-		free(new_pixels);
-
-    return 0;
-}
-
-static int NDS_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
-						   const SDL_Rect *rect, void **pixels, int *pitch)
-{
-	SDL_Log("enter %s (todo)\n", __func__);
-
-    return 0;
-}
-
-static void NDS_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
-{
-	SDL_Log("enter %s\n", __func__);
-    /* stub! */
-}
-
-static int NDS_RenderClear(SDL_Renderer *renderer)
-{
-    glClearColor(renderer->r >> 3,
-                 renderer->g >> 3,
-                 renderer->b >> 3,
-                 renderer->a >> 3);
-
-	return 0;
-}
-
-static void NDS_RenderPresent(SDL_Renderer * renderer)
-{
-    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
-
-	glEnd2D();
-		
-	glFlush(0);
-
-	swiWaitForVBlank();
-
-	/* wait for capture unit to be ready */
-	while(REG_DISPCAPCNT & DCAP_ENABLE);
-
-	/* 3D engine can only work on one screen at a time. */
-	data->is_sub = !data->is_sub;
-	if (data->is_sub) {
-		lcdMainOnBottom();
-		vramSetBankC(VRAM_C_LCD);
-		vramSetBankD(VRAM_D_SUB_SPRITE);
-		REG_DISPCAPCNT = DCAP_BANK(2) | DCAP_ENABLE | DCAP_SIZE(3);
-	} else {
-		lcdMainOnTop();
-		vramSetBankD(VRAM_D_LCD);
-		vramSetBankC(VRAM_C_SUB_BG);
-		REG_DISPCAPCNT = DCAP_BANK(3) | DCAP_ENABLE | DCAP_SIZE(3);
-	}
-
-	glBegin2D();
-}
-
-static int NDS_RenderDrawPoints(SDL_Renderer *renderer, const SDL_Point *points,
-								int count)
-{
-    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
-	int i;
-	int color = RGB15(renderer->r >> 3,
-					  renderer->g >> 3,
-					  renderer->b >> 3);
-
-	for (i=0; i < count; i++) {
-		if (data->is_sub) {
-			glPutPixel(points[i].x, points[i].y, color);
-		} else {
-			glPutPixel(points[i].x, points[i].y - SCREEN_HEIGHT, color);
-		}
-	}
-
-	return 0;
-}
-
-static int NDS_RenderDrawLines(SDL_Renderer *renderer, const SDL_Point *points,
-							   int count)
-{
-    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
-	int i;
-	int color = RGB15(renderer->r >> 3,
-					  renderer->g >> 3,
-					  renderer->b >> 3);
-
-	for (i=0; i < count-1; i++) {
-		if (data->is_sub) {
-			glLine(points[i].x, points[i].y, points[i+1].x, points[i+1].y, color);
-		} else {
-			glLine(points[i].x, points[i].y - SCREEN_HEIGHT, 
-				   points[i+1].x, points[i+1].y - SCREEN_HEIGHT, color);
-		}
-	}
-
-	return 0;
-}
-
-static int NDS_RenderFillRects(SDL_Renderer *renderer, const SDL_Rect *rects,
-							   int count)
-{
-    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
-	int i;
-	int color = RGB15(renderer->r >> 3,
-					  renderer->g >> 3,
-					  renderer->b >> 3);
-
-	for (i=0; i<count; i++) {
-		if (data->is_sub) {
-			glBoxFilled(rects[i].x, rects[i].y, 
-						rects[i].x + rects[i].w,
-						rects[i].y + rects[i].h, color);
-	} else {
-			glBoxFilled(rects[i].x, rects[i].y - SCREEN_HEIGHT,
-						rects[i].x + rects[i].w,
-						rects[i].y + rects[i].h - SCREEN_HEIGHT,
-						color);
-		}
-	}
-
-	return 0;
-}
-
-static SDL_Renderer *
-NDS_CreateRenderer(SDL_Window * window, Uint32 flags)
-{
-    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
-    SDL_DisplayMode *displayMode = &display->current_mode;
-    SDL_Renderer *renderer;
-    NDS_RenderData *data;
-    int bpp;
-    Uint32 Rmask, Gmask, Bmask, Amask;
-
-	if (displayMode->format != SDL_PIXELFORMAT_ABGR1555) {
-		SDL_SetError("Unsupported pixel format (%x)", displayMode->format);
-		return NULL;
-	}
-
-    if (!SDL_PixelFormatEnumToMasks(displayMode->format, &bpp,
-                                    &Rmask, &Gmask, &Bmask, &Amask)) {
-        SDL_SetError("Unknown display format");
-        return NULL;
-    }
-
-    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
-    if (!renderer) {
-        SDL_OutOfMemory();
-        return NULL;
-    }
-
-    data = (NDS_RenderData *) SDL_calloc(1, sizeof(*data));
-    if (!data) {
-        SDL_free(renderer);
-        SDL_OutOfMemory();
-        return NULL;
-    }
-
-    renderer->info = NDS_RenderDriver.info;
-    renderer->info.flags = SDL_RENDERER_ACCELERATED;
-
-	renderer->CreateTexture = NDS_CreateTexture;
-	renderer->UpdateTexture = NDS_UpdateTexture;
-	renderer->LockTexture = NDS_LockTexture;
-	renderer->UnlockTexture = NDS_UnlockTexture;
-	renderer->UpdateViewport = NDS_UpdateViewport;
-	renderer->RenderClear = NDS_RenderClear;
-	renderer->RenderDrawPoints = NDS_RenderDrawPoints;
-	renderer->RenderDrawLines = NDS_RenderDrawLines;
-	renderer->RenderFillRects = NDS_RenderFillRects;
-	renderer->RenderCopy = NDS_RenderCopy;
-	/* renderer->RenderReadPixels = NDS_RenderReadPixels; - todo ? */
-	renderer->RenderPresent = NDS_RenderPresent;
-	renderer->DestroyTexture = NDS_DestroyTexture;
-	/* renderer->DestroyRenderer = NDS_DestroyRenderer; - todo ? */
-
-	renderer->driverdata = data;
-
-    return renderer;
-}
-
-SDL_RenderDriver NDS_RenderDriver = {
-	.CreateRenderer = NDS_CreateRenderer,
-    .info = {
-		.name = "nds",
-		.flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC,
-		.num_texture_formats = 2,
-		.texture_formats = { [0] = SDL_PIXELFORMAT_ABGR1555,
-							 [1] = SDL_PIXELFORMAT_BGR555,
-		},
-		.max_texture_width = 512,
-		.max_texture_height = 512,
-     }
-};
-
-#endif /* SDL_VIDEO_RENDER_NDS */
-
-/* vi: set ts=4 sw=4 expandtab: */

+ 1 - 0
Source/ThirdParty/SDL/src/render/opengl/SDL_glfuncs.h

@@ -15,6 +15,7 @@ SDL_PROC_UNUSED(void, glBitmap,
                 (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat,
                  const GLubyte *))
 SDL_PROC(void, glBlendFunc, (GLenum, GLenum))
+SDL_PROC(void, glBlendFuncSeparate, (GLenum, GLenum, GLenum, GLenum))
 SDL_PROC_UNUSED(void, glCallList, (GLuint))
 SDL_PROC_UNUSED(void, glCallLists, (GLsizei, GLenum, const GLvoid *))
 SDL_PROC(void, glClear, (GLbitfield))

+ 11 - 6
Source/ThirdParty/SDL/src/render/opengl/SDL_render_gl.c

@@ -277,7 +277,6 @@ GL_ActivateRenderer(SDL_Renderer * renderer)
 {
     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
 
-    GL_ClearErrors(renderer);
     if (SDL_CurrentContext != data->context) {
         if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
             return -1;
@@ -286,6 +285,9 @@ GL_ActivateRenderer(SDL_Renderer * renderer)
 
         GL_UpdateViewport(renderer);
     }
+
+    GL_ClearErrors(renderer);
+
     return 0;
 }
 
@@ -631,6 +633,10 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 
     GL_CheckError("", renderer);
     renderdata->glGenTextures(1, &data->texture);
+    if (GL_CheckError("glGenTexures()", renderer) < 0) {
+        SDL_free(data);
+        return -1;
+    }
     if ((renderdata->GL_ARB_texture_rectangle_supported)
         /*&& texture->access != SDL_TEXTUREACCESS_TARGET*/){
         data->type = GL_TEXTURE_RECTANGLE_ARB;
@@ -922,17 +928,17 @@ GL_SetBlendMode(GL_RenderData * data, int blendMode)
         case SDL_BLENDMODE_BLEND:
             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
             data->glEnable(GL_BLEND);
-            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+            data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
             break;
         case SDL_BLENDMODE_ADD:
             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
             data->glEnable(GL_BLEND);
-            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+            data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
             break;
         case SDL_BLENDMODE_MOD:
             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
             data->glEnable(GL_BLEND);
-            data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
+            data->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
             break;
         }
         data->current.blendMode = blendMode;
@@ -1233,7 +1239,6 @@ GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
                     Uint32 pixel_format, void * pixels, int pitch)
 {
     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
-    SDL_Window *window = renderer->window;
     Uint32 temp_format = SDL_PIXELFORMAT_ARGB8888;
     void *temp_pixels;
     int temp_pitch;
@@ -1253,7 +1258,7 @@ GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
 
     convert_format(data, temp_format, &internalFormat, &format, &type);
 
-    SDL_GetWindowSize(window, &w, &h);
+    SDL_GetRendererOutputSize(renderer, &w, &h);
 
     data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
     data->glPixelStorei(GL_PACK_ROW_LENGTH,

+ 1 - 0
Source/ThirdParty/SDL/src/render/opengles/SDL_glesfuncs.h

@@ -1,5 +1,6 @@
 SDL_PROC(void, glBindTexture, (GLenum, GLuint))
 SDL_PROC(void, glBlendFunc, (GLenum, GLenum))
+SDL_PROC(void, glBlendFuncSeparateOES, (GLenum, GLenum, GLenum, GLenum))
 SDL_PROC(void, glClear, (GLbitfield))
 SDL_PROC(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))
 SDL_PROC(void, glColor4f, (GLfloat, GLfloat, GLfloat, GLfloat))

+ 26 - 5
Source/ThirdParty/SDL/src/render/opengles/SDL_render_gles.c

@@ -121,6 +121,7 @@ typedef struct
 
     SDL_bool useDrawTexture;
     SDL_bool GL_OES_draw_texture_supported;
+    SDL_bool GL_OES_blend_func_separate_supported;
 } GLES_RenderData;
 
 typedef struct
@@ -376,6 +377,10 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
     }
     data->framebuffers = NULL;
 
+    if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) {
+        data->GL_OES_blend_func_separate_supported = SDL_TRUE;
+    }
+
     /* Set up parameters for rendering */
     GLES_ResetState(renderer);
 
@@ -470,6 +475,11 @@ GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
     renderdata->glGetError();
     renderdata->glEnable(GL_TEXTURE_2D);
     renderdata->glGenTextures(1, &data->texture);
+    result = renderdata->glGetError();
+    if (result != GL_NO_ERROR) {
+        SDL_free(data);
+        return GLES_SetError("glGenTextures()", result);
+    }
 
     data->type = GL_TEXTURE_2D;
     /* no NPOV textures allowed in OpenGL ES (yet) */
@@ -680,17 +690,29 @@ GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
         case SDL_BLENDMODE_BLEND:
             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
             data->glEnable(GL_BLEND);
-            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+            if (data->GL_OES_blend_func_separate_supported) {
+                data->glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+            } else {
+                data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+            }
             break;
         case SDL_BLENDMODE_ADD:
             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
             data->glEnable(GL_BLEND);
-            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+            if (data->GL_OES_blend_func_separate_supported) {
+                data->glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
+            } else {
+                data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+            }
             break;
         case SDL_BLENDMODE_MOD:
             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
             data->glEnable(GL_BLEND);
-            data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
+            if (data->GL_OES_blend_func_separate_supported) {
+                data->glBlendFuncSeparateOES(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
+            } else {
+                data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
+            }
             break;
         }
         data->current.blendMode = blendMode;
@@ -1006,7 +1028,6 @@ GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
                     Uint32 pixel_format, void * pixels, int pitch)
 {
     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-    SDL_Window *window = renderer->window;
     Uint32 temp_format = SDL_PIXELFORMAT_ABGR8888;
     void *temp_pixels;
     int temp_pitch;
@@ -1022,7 +1043,7 @@ GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
         return SDL_OutOfMemory();
     }
 
-    SDL_GetWindowSize(window, &w, &h);
+    SDL_GetRendererOutputSize(renderer, &w, &h);
 
     data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
 

+ 1 - 1
Source/ThirdParty/SDL/src/render/opengles2/SDL_gles2funcs.h

@@ -2,7 +2,7 @@ SDL_PROC(void, glActiveTexture, (GLenum))
 SDL_PROC(void, glAttachShader, (GLuint, GLuint))
 SDL_PROC(void, glBindAttribLocation, (GLuint, GLuint, const char *))
 SDL_PROC(void, glBindTexture, (GLenum, GLuint))
-SDL_PROC(void, glBlendFunc, (GLenum, GLenum))
+SDL_PROC(void, glBlendFuncSeparate, (GLenum, GLenum, GLenum, GLenum))
 SDL_PROC(void, glClear, (GLbitfield))
 SDL_PROC(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))
 SDL_PROC(void, glCompileShader, (GLuint))

+ 11 - 9
Source/ThirdParty/SDL/src/render/opengles2/SDL_render_gles2.c

@@ -418,6 +418,10 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
     /* Allocate the texture */
     rdata->glGetError();
     rdata->glGenTextures(1, &tdata->texture);
+    if (rdata->glGetError() != GL_NO_ERROR) {
+        SDL_free(tdata);
+        return SDL_SetError("Texture creation failed in glGenTextures()");
+    }
     rdata->glActiveTexture(GL_TEXTURE0);
     rdata->glBindTexture(tdata->texture_type, tdata->texture);
     rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
@@ -425,8 +429,7 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
     rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     rdata->glTexImage2D(tdata->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
-    if (rdata->glGetError() != GL_NO_ERROR)
-    {
+    if (rdata->glGetError() != GL_NO_ERROR) {
         rdata->glDeleteTextures(1, &tdata->texture);
         SDL_free(tdata);
         return SDL_SetError("Texture creation failed");
@@ -994,15 +997,15 @@ GLES2_SetBlendMode(GLES2_DriverContext *rdata, int blendMode)
             break;
         case SDL_BLENDMODE_BLEND:
             rdata->glEnable(GL_BLEND);
-            rdata->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+            rdata->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
             break;
         case SDL_BLENDMODE_ADD:
             rdata->glEnable(GL_BLEND);
-            rdata->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+            rdata->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
             break;
         case SDL_BLENDMODE_MOD:
             rdata->glEnable(GL_BLEND);
-            rdata->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
+            rdata->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
             break;
         }
         rdata->current.blendMode = blendMode;
@@ -1086,7 +1089,7 @@ GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int cou
     rdata->glDrawArrays(GL_POINTS, 0, count);
     SDL_stack_free(vertices);
     if (rdata->glGetError() != GL_NO_ERROR) {
-        return SDL_SetError("Failed to render lines");
+        return SDL_SetError("Failed to render points");
     }
     return 0;
 }
@@ -1160,7 +1163,7 @@ GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
         rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
     }
     if (rdata->glGetError() != GL_NO_ERROR) {
-        return SDL_SetError("Failed to render lines");
+        return SDL_SetError("Failed to render filled rects");
     }
     return 0;
 }
@@ -1508,7 +1511,6 @@ GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
                     Uint32 pixel_format, void * pixels, int pitch)
 {
     GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
-    SDL_Window *window = renderer->window;
     Uint32 temp_format = SDL_PIXELFORMAT_ABGR8888;
     void *temp_pixels;
     int temp_pitch;
@@ -1524,7 +1526,7 @@ GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
         return SDL_OutOfMemory();
     }
 
-    SDL_GetWindowSize(window, &w, &h);
+    SDL_GetRendererOutputSize(renderer, &w, &h);
 
     rdata->glPixelStorei(GL_PACK_ALIGNMENT, 1);
 

+ 0 - 2
Source/ThirdParty/SDL/src/render/software/SDL_render_sw.c

@@ -114,8 +114,6 @@ SW_ActivateRenderer(SDL_Renderer * renderer)
         SDL_Surface *surface = SDL_GetWindowSurface(renderer->window);
         if (surface) {
             data->surface = data->window = surface;
-            renderer->viewport.w = surface->w;
-            renderer->viewport.h = surface->h;
 
             SW_UpdateViewport(renderer);
             SW_UpdateClipRect(renderer);

+ 12 - 6
Source/ThirdParty/SDL/src/stdlib/SDL_getenv.c

@@ -31,9 +31,12 @@ static size_t SDL_envmemlen = 0;
 
 
 /* Put a variable into the environment */
-#ifdef SDL_setenv
-#undef SDL_setenv
-int SDL_setenv(const char *name, const char *value, int overwrite) { return SDL_setenv_inline(name, value, overwrite); }
+#if defined(HAVE_SETENV)
+int
+SDL_setenv(const char *name, const char *value, int overwrite)
+{
+    return setenv(name, value, overwrite);
+}
 #elif defined(__WIN32__)
 int
 SDL_setenv(const char *name, const char *value, int overwrite)
@@ -143,9 +146,12 @@ SDL_setenv(const char *name, const char *value, int overwrite)
 #endif
 
 /* Retrieve a variable named "name" from the environment */
-#ifdef SDL_getenv
-#undef SDL_getenv
-char *SDL_getenv(const char *name) { return SDL_getenv_inline(name); }
+#if defined(HAVE_GETENV)
+char *
+SDL_getenv(const char *name)
+{
+    return getenv(name);
+}
 #elif defined(__WIN32__)
 char *
 SDL_getenv(const char *name)

+ 4 - 4
Source/ThirdParty/SDL/src/stdlib/SDL_iconv.c

@@ -364,7 +364,7 @@ SDL_iconv(SDL_iconv_t cd,
                          */
                         ch = UNKNOWN_UNICODE;
                     } else {
-                        if (p[0] == 0xFC) {
+                        if (p[0] == 0xFC && srclen > 1 && (p[1] & 0xFC) == 0x80) {
                             overlong = SDL_TRUE;
                         }
                         ch = (Uint32) (p[0] & 0x01);
@@ -377,7 +377,7 @@ SDL_iconv(SDL_iconv_t cd,
                          */
                         ch = UNKNOWN_UNICODE;
                     } else {
-                        if (p[0] == 0xF8) {
+                        if (p[0] == 0xF8 && srclen > 1 && (p[1] & 0xF8) == 0x80) {
                             overlong = SDL_TRUE;
                         }
                         ch = (Uint32) (p[0] & 0x03);
@@ -390,7 +390,7 @@ SDL_iconv(SDL_iconv_t cd,
                          */
                         ch = UNKNOWN_UNICODE;
                     } else {
-                        if (p[0] == 0xF0) {
+                        if (p[0] == 0xF0 && srclen > 1 && (p[1] & 0xF0) == 0x80) {
                             overlong = SDL_TRUE;
                         }
                         ch = (Uint32) (p[0] & 0x07);
@@ -403,7 +403,7 @@ SDL_iconv(SDL_iconv_t cd,
                          */
                         ch = UNKNOWN_UNICODE;
                     } else {
-                        if (p[0] == 0xE0) {
+                        if (p[0] == 0xE0 && srclen > 1 && (p[1] & 0xE0) == 0x80) {
                             overlong = SDL_TRUE;
                         }
                         ch = (Uint32) (p[0] & 0x0F);

+ 21 - 10
Source/ThirdParty/SDL/src/stdlib/SDL_malloc.c

@@ -24,16 +24,27 @@
 
 #include "SDL_stdinc.h"
 
-#ifdef SDL_malloc
-/* expose the symbol, but use what we figured out elsewhere. */
-#undef SDL_malloc
-#undef SDL_calloc
-#undef SDL_realloc
-#undef SDL_free
-void *SDL_malloc(size_t size) { return SDL_malloc_inline(size); }
-void *SDL_calloc(size_t nmemb, size_t size) { return SDL_calloc_inline(nmemb, size); }
-void *SDL_realloc(void *ptr, size_t size) { return SDL_realloc_inline(ptr, size); }
-void SDL_free(void *ptr) { SDL_free_inline(ptr); }
+#if defined(HAVE_MALLOC)
+
+void *SDL_malloc(size_t size)
+{
+    return malloc(size);
+}
+
+void *SDL_calloc(size_t nmemb, size_t size)
+{
+    return calloc(nmemb, size);
+}
+
+void *SDL_realloc(void *ptr, size_t size)
+{
+    return realloc(ptr, size);
+}
+
+void SDL_free(void *ptr)
+{
+    free(ptr);
+}
 
 #else  /* the rest of this is a LOT of tapdancing to implement malloc. :) */
 

+ 2 - 3
Source/ThirdParty/SDL/src/stdlib/SDL_qsort.c

@@ -51,12 +51,11 @@
 #include "SDL_stdinc.h"
 #include "SDL_assert.h"
 
-#ifdef SDL_qsort
-#undef SDL_qsort
+#if defined(HAVE_QSORT)
 void
 SDL_qsort(void *base, size_t nmemb, size_t size, int (*compare) (const void *, const void *))
 {
-    SDL_qsort_inline(base, nmemb, size, compare);
+    qsort(base, nmemb, size, compare);
 }
 #else
 

+ 123 - 686
Source/ThirdParty/SDL/src/stdlib/SDL_stdlib.c

@@ -18,744 +18,181 @@
      misrepresented as being the original software.
   3. This notice may not be removed or altered from any source distribution.
 */
+
+// Modified by Lasse Oorni for Urho3D
+
 #include "SDL_config.h"
 
 /* This file contains portable stdlib functions for SDL */
 
 #include "SDL_stdinc.h"
+#include "../libm/math_libm.h"
 
-/* these are always #defined, make them real symbol in the library, too... */
-#undef SDL_ceil
-#undef SDL_abs
-#undef SDL_sinf
-#undef SDL_cosf
-#undef SDL_isdigit
-#undef SDL_isspace
-#undef SDL_toupper
-#undef SDL_tolower
-double SDL_ceil(double x) { return SDL_ceil_inline(x); }
-float SDL_cosf(float x) { return SDL_cosf_inline(x); }
-float SDL_sinf(float x) { return SDL_sinf_inline(x); }
-int SDL_abs(int x) { return SDL_abs_inline(x); }
-int SDL_isdigit(int x) { return SDL_isdigit_inline(x); }
-int SDL_isspace(int x) { return SDL_isspace_inline(x); }
-int SDL_toupper(int x) { return SDL_toupper_inline(x); }
-int SDL_tolower(int x) { return SDL_tolower_inline(x); }
-
-
-#ifndef HAVE_LIBC
-/* These are some C runtime intrinsics that need to be defined */
-
-#if defined(_MSC_VER)
-
-#ifndef __FLTUSED__
-#define __FLTUSED__
-__declspec(selectany) int _fltused = 1;
-#endif
-
-/* The optimizer on Visual Studio 2010/2012 generates memcpy() calls */
-#if _MSC_VER >= 1600 && defined(_WIN64) && !defined(_DEBUG)
-#include <intrin.h>
 
-#pragma function(memcpy)
-void * memcpy ( void * destination, const void * source, size_t num )
+double
+SDL_atan(double x)
 {
-    const Uint8 *src = (const Uint8 *)source;
-    Uint8 *dst = (Uint8 *)destination;
-    size_t i;
-    
-    /* All WIN64 architectures have SSE, right? */
-    if (!((uintptr_t) src & 15) && !((uintptr_t) dst & 15)) {
-        __m128 values[4];
-        for (i = num / 64; i--;) {
-            _mm_prefetch(src, _MM_HINT_NTA);
-            values[0] = *(__m128 *) (src + 0);
-            values[1] = *(__m128 *) (src + 16);
-            values[2] = *(__m128 *) (src + 32);
-            values[3] = *(__m128 *) (src + 48);
-            _mm_stream_ps((float *) (dst + 0), values[0]);
-            _mm_stream_ps((float *) (dst + 16), values[1]);
-            _mm_stream_ps((float *) (dst + 32), values[2]);
-            _mm_stream_ps((float *) (dst + 48), values[3]);
-            src += 64;
-            dst += 64;
-        }
-        num &= 63;
-    }
-
-    while (num--) {
-        *dst++ = *src++;
-    }
-    return destination;
+#ifdef HAVE_ATAN
+    return atan(x);
+#else
+    return SDL_uclibc_atan(x);
+#endif /* HAVE_ATAN */
 }
-#endif /* _MSC_VER == 1600 && defined(_WIN64) && !defined(_DEBUG) */
 
-#ifdef _M_IX86
+double
+SDL_atan2(double x, double y)
+{
+#if defined(HAVE_ATAN2)
+    return atan2(x, y);
+#else
+    return SDL_uclibc_atan2(x, y);
+#endif /* HAVE_ATAN2 */
+}
 
-void
-__declspec(naked)
-_chkstk()
+double
+SDL_ceil(double x)
 {
+#ifdef HAVE_CEIL
+    return ceil(x);
+#else
+    return (double)(int)((x)+0.5);
+#endif /* HAVE_CEIL */
 }
 
-/* Float to long */
-void
-__declspec(naked)
-_ftol()
+double
+SDL_copysign(double x, double y)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        push        ebp
-        mov         ebp,esp
-        sub         esp,20h
-        and         esp,0FFFFFFF0h
-        fld         st(0)
-        fst         dword ptr [esp+18h]
-        fistp       qword ptr [esp+10h]
-        fild        qword ptr [esp+10h]
-        mov         edx,dword ptr [esp+18h]
-        mov         eax,dword ptr [esp+10h]
-        test        eax,eax
-        je          integer_QnaN_or_zero
-arg_is_not_integer_QnaN:
-        fsubp       st(1),st
-        test        edx,edx
-        jns         positive
-        fstp        dword ptr [esp]
-        mov         ecx,dword ptr [esp]
-        xor         ecx,80000000h
-        add         ecx,7FFFFFFFh
-        adc         eax,0
-        mov         edx,dword ptr [esp+14h]
-        adc         edx,0
-        jmp         localexit
-positive:
-        fstp        dword ptr [esp]
-        mov         ecx,dword ptr [esp]
-        add         ecx,7FFFFFFFh
-        sbb         eax,0
-        mov         edx,dword ptr [esp+14h]
-        sbb         edx,0
-        jmp         localexit
-integer_QnaN_or_zero:
-        mov         edx,dword ptr [esp+14h]
-        test        edx,7FFFFFFFh
-        jne         arg_is_not_integer_QnaN
-        fstp        dword ptr [esp+18h]
-        fstp        dword ptr [esp+18h]
-localexit:
-        leave
-        ret
-    }
-    /* *INDENT-ON* */
+#if defined(HAVE_COPYSIGN)
+    return copysign(x, y);
+#else
+    return SDL_uclibc_copysign(x, y);
+#endif /* HAVE_COPYSIGN */
 }
 
-void
-_ftol2_sse()
+double
+SDL_cos(double x)
 {
-    _ftol();
+#if defined(HAVE_COS)
+    return cos(x);
+#else
+    return SDL_uclibc_cos(x);
+#endif /* HAVE_COS */
 }
 
-/* 64-bit math operators for 32-bit systems */
-void
-__declspec(naked)
-_allmul()
+float
+SDL_cosf(float x)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        push        ebp
-        mov         ebp,esp
-        push        edi
-        push        esi
-        push        ebx
-        sub         esp,0Ch
-        mov         eax,dword ptr [ebp+10h]
-        mov         edi,dword ptr [ebp+8]
-        mov         ebx,eax
-        mov         esi,eax
-        sar         esi,1Fh
-        mov         eax,dword ptr [ebp+8]
-        mul         ebx
-        imul        edi,esi
-        mov         ecx,edx
-        mov         dword ptr [ebp-18h],eax
-        mov         edx,dword ptr [ebp+0Ch]
-        add         ecx,edi
-        imul        ebx,edx
-        mov         eax,dword ptr [ebp-18h]
-        lea         ebx,[ebx+ecx]
-        mov         dword ptr [ebp-14h],ebx
-        mov         edx,dword ptr [ebp-14h]
-        add         esp,0Ch
-        pop         ebx
-        pop         esi
-        pop         edi
-        pop         ebp
-        ret         10h
-    }
-    /* *INDENT-ON* */
+#ifdef HAVE_COSF
+    return cosf(x);
+#else
+    return (float)SDL_cos((double)x);
+#endif
 }
 
-void
-__declspec(naked)
-_alldiv()
+double
+SDL_fabs(double x)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        push        edi
-        push        esi
-        push        ebx
-        xor         edi,edi
-        mov         eax,dword ptr [esp+14h]
-        or          eax,eax
-        jge         L1
-        inc         edi
-        mov         edx,dword ptr [esp+10h]
-        neg         eax
-        neg         edx
-        sbb         eax,0
-        mov         dword ptr [esp+14h],eax
-        mov         dword ptr [esp+10h],edx
-L1:
-        mov         eax,dword ptr [esp+1Ch]
-        or          eax,eax
-        jge         L2
-        inc         edi
-        mov         edx,dword ptr [esp+18h]
-        neg         eax
-        neg         edx
-        sbb         eax,0
-        mov         dword ptr [esp+1Ch],eax
-        mov         dword ptr [esp+18h],edx
-L2:
-        or          eax,eax
-        jne         L3
-        mov         ecx,dword ptr [esp+18h]
-        mov         eax,dword ptr [esp+14h]
-        xor         edx,edx
-        div         ecx
-        mov         ebx,eax
-        mov         eax,dword ptr [esp+10h]
-        div         ecx
-        mov         edx,ebx
-        jmp         L4
-L3:
-        mov         ebx,eax
-        mov         ecx,dword ptr [esp+18h]
-        mov         edx,dword ptr [esp+14h]
-        mov         eax,dword ptr [esp+10h]
-L5:
-        shr         ebx,1
-        rcr         ecx,1
-        shr         edx,1
-        rcr         eax,1
-        or          ebx,ebx
-        jne         L5
-        div         ecx
-        mov         esi,eax
-        mul         dword ptr [esp+1Ch]
-        mov         ecx,eax
-        mov         eax,dword ptr [esp+18h]
-        mul         esi
-        add         edx,ecx
-        jb          L6
-        cmp         edx,dword ptr [esp+14h]
-        ja          L6
-        jb          L7
-        cmp         eax,dword ptr [esp+10h]
-        jbe         L7
-L6:
-        dec         esi
-L7:
-        xor         edx,edx
-        mov         eax,esi
-L4:
-        dec         edi
-        jne         L8
-        neg         edx
-        neg         eax
-        sbb         edx,0
-L8:
-        pop         ebx
-        pop         esi
-        pop         edi
-        ret         10h
-    }
-    /* *INDENT-ON* */
+#if defined(HAVE_FABS)
+    return fabs(x); 
+#else
+    return SDL_uclibc_fabs(x);
+#endif /* HAVE_FABS */
 }
 
-void
-__declspec(naked)
-_aulldiv()
+double
+SDL_floor(double x)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        push        ebx
-        push        esi
-        mov         eax,dword ptr [esp+18h]
-        or          eax,eax
-        jne         L1
-        mov         ecx,dword ptr [esp+14h]
-        mov         eax,dword ptr [esp+10h]
-        xor         edx,edx
-        div         ecx
-        mov         ebx,eax
-        mov         eax,dword ptr [esp+0Ch]
-        div         ecx
-        mov         edx,ebx
-        jmp         L2
-L1:
-        mov         ecx,eax
-        mov         ebx,dword ptr [esp+14h]
-        mov         edx,dword ptr [esp+10h]
-        mov         eax,dword ptr [esp+0Ch]
-L3:
-        shr         ecx,1
-        rcr         ebx,1
-        shr         edx,1
-        rcr         eax,1
-        or          ecx,ecx
-        jne         L3
-        div         ebx
-        mov         esi,eax
-        mul         dword ptr [esp+18h]
-        mov         ecx,eax
-        mov         eax,dword ptr [esp+14h]
-        mul         esi
-        add         edx,ecx
-        jb          L4
-        cmp         edx,dword ptr [esp+10h]
-        ja          L4
-        jb          L5
-        cmp         eax,dword ptr [esp+0Ch]
-        jbe         L5
-L4:
-        dec         esi
-L5:
-        xor         edx,edx
-        mov         eax,esi
-L2:
-        pop         esi
-        pop         ebx
-        ret         10h
-    }
-    /* *INDENT-ON* */
+#if defined(HAVE_FLOOR)
+    return floor(x);
+#else
+    return SDL_uclibc_floor(x);
+#endif /* HAVE_FLOOR */
 }
 
-void
-__declspec(naked)
-_allrem()
+double
+SDL_log(double x)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        push        ebx
-        push        edi
-        xor         edi,edi
-        mov         eax,dword ptr [esp+10h]
-        or          eax,eax
-        jge         L1
-        inc         edi
-        mov         edx,dword ptr [esp+0Ch]
-        neg         eax
-        neg         edx
-        sbb         eax,0
-        mov         dword ptr [esp+10h],eax
-        mov         dword ptr [esp+0Ch],edx
-L1:
-        mov         eax,dword ptr [esp+18h]
-        or          eax,eax
-        jge         L2
-        mov         edx,dword ptr [esp+14h]
-        neg         eax
-        neg         edx
-        sbb         eax,0
-        mov         dword ptr [esp+18h],eax
-        mov         dword ptr [esp+14h],edx
-L2:
-        or          eax,eax
-        jne         L3
-        mov         ecx,dword ptr [esp+14h]
-        mov         eax,dword ptr [esp+10h]
-        xor         edx,edx
-        div         ecx
-        mov         eax,dword ptr [esp+0Ch]
-        div         ecx
-        mov         eax,edx
-        xor         edx,edx
-        dec         edi
-        jns         L4
-        jmp         L8
-L3:
-        mov         ebx,eax
-        mov         ecx,dword ptr [esp+14h]
-        mov         edx,dword ptr [esp+10h]
-        mov         eax,dword ptr [esp+0Ch]
-L5:
-        shr         ebx,1
-        rcr         ecx,1
-        shr         edx,1
-        rcr         eax,1
-        or          ebx,ebx
-        jne         L5
-        div         ecx
-        mov         ecx,eax
-        mul         dword ptr [esp+18h]
-        xchg        eax,ecx
-        mul         dword ptr [esp+14h]
-        add         edx,ecx
-        jb          L6
-        cmp         edx,dword ptr [esp+10h]
-        ja          L6
-        jb          L7
-        cmp         eax,dword ptr [esp+0Ch]
-        jbe         L7
-L6:
-        sub         eax,dword ptr [esp+14h]
-        sbb         edx,dword ptr [esp+18h]
-L7:
-        sub         eax,dword ptr [esp+0Ch]
-        sbb         edx,dword ptr [esp+10h]
-        dec         edi
-        jns         L8
-L4:
-        neg         edx
-        neg         eax
-        sbb         edx,0
-L8:
-        pop         edi
-        pop         ebx
-        ret         10h
-    }
-    /* *INDENT-ON* */
+#if defined(HAVE_LOG)
+    return log(x);
+#else
+    return SDL_uclibc_log(x);
+#endif /* HAVE_LOG */
 }
 
-void
-__declspec(naked)
-_aullrem()
+double
+SDL_pow(double x, double y)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        push        ebx
-        mov         eax,dword ptr [esp+14h]
-        or          eax,eax
-        jne         L1
-        mov         ecx,dword ptr [esp+10h]
-        mov         eax,dword ptr [esp+0Ch]
-        xor         edx,edx
-        div         ecx
-        mov         eax,dword ptr [esp+8]
-        div         ecx
-        mov         eax,edx
-        xor         edx,edx
-        jmp         L2
-L1:
-        mov         ecx,eax
-        mov         ebx,dword ptr [esp+10h]
-        mov         edx,dword ptr [esp+0Ch]
-        mov         eax,dword ptr [esp+8]
-L3:
-        shr         ecx,1
-        rcr         ebx,1
-        shr         edx,1
-        rcr         eax,1
-        or          ecx,ecx
-        jne         L3
-        div         ebx
-        mov         ecx,eax
-        mul         dword ptr [esp+14h]
-        xchg        eax,ecx
-        mul         dword ptr [esp+10h]
-        add         edx,ecx
-        jb          L4
-        cmp         edx,dword ptr [esp+0Ch]
-        ja          L4
-        jb          L5
-        cmp         eax,dword ptr [esp+8]
-        jbe         L5
-L4:
-        sub         eax,dword ptr [esp+10h]
-        sbb         edx,dword ptr [esp+14h]
-L5:
-        sub         eax,dword ptr [esp+8]
-        sbb         edx,dword ptr [esp+0Ch]
-        neg         edx
-        neg         eax
-        sbb         edx,0
-L2:
-        pop         ebx
-        ret         10h
-    }
-    /* *INDENT-ON* */
+#if defined(HAVE_POW)
+    return pow(x, y);
+#else
+    return SDL_uclibc_pow(x, y);
+#endif /* HAVE_POW */
 }
 
-void
-__declspec(naked)
-_alldvrm()
+double
+SDL_scalbn(double x, int n)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        push        edi
-        push        esi
-        push        ebp
-        xor         edi,edi
-        xor         ebp,ebp
-        mov         eax,dword ptr [esp+14h]
-        or          eax,eax
-        jge         L1
-        inc         edi
-        inc         ebp
-        mov         edx,dword ptr [esp+10h]
-        neg         eax
-        neg         edx
-        sbb         eax,0
-        mov         dword ptr [esp+14h],eax
-        mov         dword ptr [esp+10h],edx
-L1:
-        mov         eax,dword ptr [esp+1Ch]
-        or          eax,eax
-        jge         L2
-        inc         edi
-        mov         edx,dword ptr [esp+18h]
-        neg         eax
-        neg         edx
-        sbb         eax,0
-        mov         dword ptr [esp+1Ch],eax
-        mov         dword ptr [esp+18h],edx
-L2:
-        or          eax,eax
-        jne         L3
-        mov         ecx,dword ptr [esp+18h]
-        mov         eax,dword ptr [esp+14h]
-        xor         edx,edx
-        div         ecx
-        mov         ebx,eax
-        mov         eax,dword ptr [esp+10h]
-        div         ecx
-        mov         esi,eax
-        mov         eax,ebx
-        mul         dword ptr [esp+18h]
-        mov         ecx,eax
-        mov         eax,esi
-        mul         dword ptr [esp+18h]
-        add         edx,ecx
-        jmp         L4
-L3:
-        mov         ebx,eax
-        mov         ecx,dword ptr [esp+18h]
-        mov         edx,dword ptr [esp+14h]
-        mov         eax,dword ptr [esp+10h]
-L5:
-        shr         ebx,1
-        rcr         ecx,1
-        shr         edx,1
-        rcr         eax,1
-        or          ebx,ebx
-        jne         L5
-        div         ecx
-        mov         esi,eax
-        mul         dword ptr [esp+1Ch]
-        mov         ecx,eax
-        mov         eax,dword ptr [esp+18h]
-        mul         esi
-        add         edx,ecx
-        jb          L6
-        cmp         edx,dword ptr [esp+14h]
-        ja          L6
-        jb          L7
-        cmp         eax,dword ptr [esp+10h]
-        jbe         L7
-L6:
-        dec         esi
-        sub         eax,dword ptr [esp+18h]
-        sbb         edx,dword ptr [esp+1Ch]
-L7:
-        xor         ebx,ebx
-L4:
-        sub         eax,dword ptr [esp+10h]
-        sbb         edx,dword ptr [esp+14h]
-        dec         ebp
-        jns         L9
-        neg         edx
-        neg         eax
-        sbb         edx,0
-L9:
-        mov         ecx,edx
-        mov         edx,ebx
-        mov         ebx,ecx
-        mov         ecx,eax
-        mov         eax,esi
-        dec         edi
-        jne         L8
-        neg         edx
-        neg         eax
-        sbb         edx,0
-L8:
-        pop         ebp
-        pop         esi
-        pop         edi
-        ret         10h
-    }
-    /* *INDENT-ON* */
+#if defined(HAVE_SCALBN)
+    return scalbn(x, n);
+#else
+    return SDL_uclibc_scalbn(x, n);
+#endif /* HAVE_SCALBN */
 }
 
-void
-__declspec(naked)
-_aulldvrm()
+double
+SDL_sin(double x)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        push        esi
-        mov         eax,dword ptr [esp+14h]
-        or          eax,eax
-        jne         L1
-        mov         ecx,dword ptr [esp+10h]
-        mov         eax,dword ptr [esp+0Ch]
-        xor         edx,edx
-        div         ecx
-        mov         ebx,eax
-        mov         eax,dword ptr [esp+8]
-        div         ecx
-        mov         esi,eax
-        mov         eax,ebx
-        mul         dword ptr [esp+10h]
-        mov         ecx,eax
-        mov         eax,esi
-        mul         dword ptr [esp+10h]
-        add         edx,ecx
-        jmp         L2
-L1:
-        mov         ecx,eax
-        mov         ebx,dword ptr [esp+10h]
-        mov         edx,dword ptr [esp+0Ch]
-        mov         eax,dword ptr [esp+8]
-L3:
-        shr         ecx,1
-        rcr         ebx,1
-        shr         edx,1
-        rcr         eax,1
-        or          ecx,ecx
-        jne         L3
-        div         ebx
-        mov         esi,eax
-        mul         dword ptr [esp+14h]
-        mov         ecx,eax
-        mov         eax,dword ptr [esp+10h]
-        mul         esi
-        add         edx,ecx
-        jb          L4
-        cmp         edx,dword ptr [esp+0Ch]
-        ja          L4
-        jb          L5
-        cmp         eax,dword ptr [esp+8]
-        jbe         L5
-L4:
-        dec         esi
-        sub         eax,dword ptr [esp+10h]
-        sbb         edx,dword ptr [esp+14h]
-L5:
-        xor         ebx,ebx
-L2:
-        sub         eax,dword ptr [esp+8]
-        sbb         edx,dword ptr [esp+0Ch]
-        neg         edx
-        neg         eax
-        sbb         edx,0
-        mov         ecx,edx
-        mov         edx,ebx
-        mov         ebx,ecx
-        mov         ecx,eax
-        mov         eax,esi
-        pop         esi
-        ret         10h
-    }
-    /* *INDENT-ON* */
+#if defined(HAVE_SIN)
+    return sin(x);
+#else
+    return SDL_uclibc_sin(x);
+#endif /* HAVE_SIN */
 }
 
-void
-__declspec(naked)
-_allshl()
+float 
+SDL_sinf(float x)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        cmp         cl,40h
-        jae         RETZERO
-        cmp         cl,20h
-        jae         MORE32
-        shld        edx,eax,cl
-        shl         eax,cl
-        ret
-MORE32:
-        mov         edx,eax
-        xor         eax,eax
-        and         cl,1Fh
-        shl         edx,cl
-        ret
-RETZERO:
-        xor         eax,eax
-        xor         edx,edx
-        ret
-    }
-    /* *INDENT-ON* */
+#ifdef HAVE_SINF
+    return sinf(x);
+#else
+    return (float)SDL_sin((double)x);
+#endif /* HAVE_SINF */
 }
 
-void
-__declspec(naked)
-_allshr()
+double
+SDL_sqrt(double x)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        cmp         cl,40h
-        jae         RETZERO
-        cmp         cl,20h
-        jae         MORE32
-        shrd        eax,edx,cl
-        sar         edx,cl
-        ret
-MORE32:
-        mov         eax,edx
-        xor         edx,edx
-        and         cl,1Fh
-        sar         eax,cl
-        ret
-RETZERO:
-        xor         eax,eax
-        xor         edx,edx
-        ret
-    }
-    /* *INDENT-ON* */
+#if defined(HAVE_SQRT)
+    return sqrt(x);
+#else
+    return SDL_uclibc_sqrt(x);
+#endif
 }
 
-void
-__declspec(naked)
-_aullshr()
+int SDL_abs(int x)
 {
-    /* *INDENT-OFF* */
-    __asm {
-        cmp         cl,40h
-        jae         RETZERO
-        cmp         cl,20h
-        jae         MORE32
-        shrd        eax,edx,cl
-        shr         edx,cl
-        ret
-MORE32:
-        mov         eax,edx
-        xor         edx,edx
-        and         cl,1Fh
-        shr         eax,cl
-        ret
-RETZERO:
-        xor         eax,eax
-        xor         edx,edx
-        ret
-    }
-    /* *INDENT-ON* */
+#ifdef HAVE_ABS
+    return abs(x);
+#else
+    return ((x) < 0 ? -(x) : (x));
+#endif
 }
 
-#endif /* _M_IX86 */
+#ifdef HAVE_CTYPE_H
+int SDL_isdigit(int x) { return isdigit(x); }
+int SDL_isspace(int x) { return isspace(x); }
+int SDL_toupper(int x) { return toupper(x); }
+int SDL_tolower(int x) { return tolower(x); }
+#else
+int SDL_isdigit(int x) { return ((x) >= '0') && ((x) <= '9'); }
+int SDL_isspace(int x) { return ((x) == ' ') || ((x) == '\t') || ((x) == '\r') || ((x) == '\n') || ((x) == '\f') || ((x) == '\v'); }
+int SDL_toupper(int x) { return ((x) >= 'a') && ((x) <= 'z') ? ('A'+((x)-'a')) : (x); }
+int SDL_tolower(int x) { return ((x) >= 'A') && ((x) <= 'Z') ? ('a'+((x)-'A')) : (x); }
+#endif
 
-#endif /* MSC_VER */
 
+#ifndef HAVE_LIBC
+// Urho3D: disable MSVC runtime intrinsic replacements
 #endif /* !HAVE_LIBC */
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 248 - 245
Source/ThirdParty/SDL/src/stdlib/SDL_string.c

@@ -18,26 +18,12 @@
      misrepresented as being the original software.
   3. This notice may not be removed or altered from any source distribution.
 */
-
-// Modified by Lasse Oorni for Urho3D
-
 #include "SDL_config.h"
 
 /* This file contains portable string manipulation functions for SDL */
 
 #include "SDL_stdinc.h"
 
-/* these are always #defined, make them real symbol in the library, too... */
-#undef SDL_itoa
-#undef SDL_uitoa
-#undef SDL_atoi
-#undef SDL_atof
-char *SDL_itoa(int value, char *str, int radix) { return SDL_itoa_inline(value, str, radix); }
-char *SDL_uitoa(unsigned int value, char *str, int radix) { return SDL_uitoa_inline(value, str, radix); }
-int SDL_atoi(const char *str) { return SDL_atoi_inline(str); }
-double SDL_atof(const char *str) { return SDL_atof_inline(str); }
-
-
 
 #define SDL_isupperhex(X)   (((X) >= 'A') && ((X) <= 'F'))
 #define SDL_islowerhex(X)   (((X) >= 'a') && ((X) <= 'f'))
@@ -57,7 +43,7 @@ static int UTF8_TrailingBytes(unsigned char c)
         return 0;
 }
 
-#if !defined(SDL_sscanf) || !defined(SDL_strtol)
+#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOL)
 static size_t
 SDL_ScanLong(const char *text, int radix, long *valuep)
 {
@@ -98,7 +84,7 @@ SDL_ScanLong(const char *text, int radix, long *valuep)
 }
 #endif
 
-#if !defined(SDL_sscanf) || !defined(SDL_strtoul) || !defined(SDL_strtod)
+#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOUL) || !defined(HAVE_STRTOD)
 static size_t
 SDL_ScanUnsignedLong(const char *text, int radix, unsigned long *valuep)
 {
@@ -130,7 +116,7 @@ SDL_ScanUnsignedLong(const char *text, int radix, unsigned long *valuep)
 }
 #endif
 
-#ifndef SDL_sscanf
+#ifndef HAVE_SSCANF
 static size_t
 SDL_ScanUintPtrT(const char *text, int radix, uintptr_t * valuep)
 {
@@ -162,7 +148,7 @@ SDL_ScanUintPtrT(const char *text, int radix, uintptr_t * valuep)
 }
 #endif
 
-#if !defined(SDL_sscanf) || !defined(SDL_strtoll)
+#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOLL)
 static size_t
 SDL_ScanLongLong(const char *text, int radix, Sint64 * valuep)
 {
@@ -203,7 +189,7 @@ SDL_ScanLongLong(const char *text, int radix, Sint64 * valuep)
 }
 #endif
 
-#if !defined(SDL_sscanf) || !defined(SDL_strtoull)
+#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOULL)
 static size_t
 SDL_ScanUnsignedLongLong(const char *text, int radix, Uint64 * valuep)
 {
@@ -235,7 +221,7 @@ SDL_ScanUnsignedLongLong(const char *text, int radix, Uint64 * valuep)
 }
 #endif
 
-#if !defined(SDL_sscanf) || !defined(SDL_strtod)
+#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOD)
 static size_t
 SDL_ScanFloat(const char *text, double *valuep)
 {
@@ -271,14 +257,12 @@ SDL_ScanFloat(const char *text, double *valuep)
 }
 #endif
 
-
-#ifdef SDL_memset
-#undef SDL_memset
-void *SDL_memset(void *dst, int c, size_t len) { return SDL_memset_inline(dst, c, len); }
-#else
 void *
 SDL_memset(void *dst, int c, size_t len)
 {
+#if defined(HAVE_MEMSET)
+    return memset(dst, c, len);
+#else
     size_t left = (len % 4);
     Uint32 *dstp4;
     Uint8 *dstp1;
@@ -302,14 +286,9 @@ SDL_memset(void *dst, int c, size_t len)
     }
 
     return dst;
+#endif /* HAVE_MEMSET */
 }
-#endif
-
 
-#ifdef SDL_memcpy
-#undef SDL_memcpy
-void *SDL_memcpy(void *dst, const void *src, size_t len) { return SDL_memcpy_inline(dst, src, len); }
-#else
 void *
 SDL_memcpy(void *dst, const void *src, size_t len)
 {
@@ -318,6 +297,11 @@ SDL_memcpy(void *dst, const void *src, size_t len)
        On my machine this is twice as fast as the C code below.
      */
     return __builtin_memcpy(dst, src, len);
+#elif defined(HAVE_MEMCPY)
+    return memcpy(dst, src, len);
+#elif defined(HAVE_BCOPY)
+    bcopy(src, dst, len);
+    return dst;
 #else
     /* GCC 4.9.0 with -O3 will generate movaps instructions with the loop
        using Uint32* pointers, so we need to make sure the pointers are
@@ -357,16 +341,13 @@ SDL_memcpy(void *dst, const void *src, size_t len)
     return dst;
 #endif /* __GNUC__ */
 }
-#endif
-
 
-#ifdef SDL_memmove
-#undef SDL_memmove
-void *SDL_memmove(void *dst, const void *src, size_t len) { return SDL_memmove_inline(dst, src, len); }
-#else
 void *
 SDL_memmove(void *dst, const void *src, size_t len)
 {
+#if defined(HAVE_MEMMOVE)
+    return memmove(dst, src, len);
+#else
     char *srcp = (char *) src;
     char *dstp = (char *) dst;
 
@@ -382,16 +363,15 @@ SDL_memmove(void *dst, const void *src, size_t len)
         }
     }
     return dst;
+#endif /* HAVE_MEMMOVE */
 }
-#endif
 
-#ifdef SDL_memcmp
-#undef SDL_memcmp
-int SDL_memcmp(const void *s1, const void *s2, size_t len) { return SDL_memcmp_inline(s1, s2, len); }
-#else
 int
 SDL_memcmp(const void *s1, const void *s2, size_t len)
 {
+#if defined(HAVE_MEMCMP)
+    return memcmp(s1, s2, len);
+#else
     char *s1p = (char *) s1;
     char *s2p = (char *) s2;
     while (len--) {
@@ -402,46 +382,43 @@ SDL_memcmp(const void *s1, const void *s2, size_t len)
         ++s2p;
     }
     return 0;
+#endif /* HAVE_MEMCMP */
 }
-#endif
 
-#ifdef SDL_strlen
-#undef SDL_strlen
-size_t SDL_strlen(const char *string) { return SDL_strlen_inline(string); }
-#else
 size_t
 SDL_strlen(const char *string)
 {
+#if defined(HAVE_STRLEN)
+    return strlen(string);
+#else
     size_t len = 0;
     while (*string++) {
         ++len;
     }
     return len;
+#endif /* HAVE_STRLEN */
 }
-#endif
 
-#ifdef SDL_wcslen
-#undef SDL_wcslen
-size_t SDL_wcslen(const wchar_t * string) { return SDL_wcslen_inline(string); }
-#else
 size_t
 SDL_wcslen(const wchar_t * string)
 {
+#if defined(HAVE_WCSLEN)
+    return wcslen(string);
+#else
     size_t len = 0;
     while (*string++) {
         ++len;
     }
     return len;
+#endif /* HAVE_WCSLEN */
 }
-#endif
 
-#ifdef SDL_wcslcpy
-#undef SDL_wcslcpy
-size_t SDL_wcslcpy(wchar_t *dst, const wchar_t *src, size_t maxlen) { return SDL_wcslcpy_inline(dst, src, maxlen); }
-#else
 size_t
 SDL_wcslcpy(wchar_t *dst, const wchar_t *src, size_t maxlen)
 {
+#if defined(HAVE_WCSLCPY)
+    return wcslcpy(dst, src, maxlen);
+#else
     size_t srclen = SDL_wcslen(src);
     if (maxlen > 0) {
         size_t len = SDL_min(srclen, maxlen - 1);
@@ -449,32 +426,30 @@ SDL_wcslcpy(wchar_t *dst, const wchar_t *src, size_t maxlen)
         dst[len] = '\0';
     }
     return srclen;
+#endif /* HAVE_WCSLCPY */
 }
-#endif
 
-#ifdef SDL_wcslcat
-#undef SDL_wcslcat
-size_t SDL_wcslcat(wchar_t *dst, const wchar_t *src, size_t maxlen) { return SDL_wcslcat_inline(dst, src, maxlen); }
-#else
 size_t
 SDL_wcslcat(wchar_t *dst, const wchar_t *src, size_t maxlen)
 {
+#if defined(HAVE_WCSLCAT)
+    return wcslcat(dst, src, maxlen);
+#else
     size_t dstlen = SDL_wcslen(dst);
     size_t srclen = SDL_wcslen(src);
     if (dstlen < maxlen) {
         SDL_wcslcpy(dst + dstlen, src, maxlen - dstlen);
     }
     return dstlen + srclen;
+#endif /* HAVE_WCSLCAT */
 }
-#endif
 
-#ifdef SDL_strlcpy
-#undef SDL_strlcpy
-size_t SDL_strlcpy(char *dst, const char *src, size_t maxlen) { return SDL_strlcpy_inline(dst, src, maxlen); }
-#else
 size_t
 SDL_strlcpy(char *dst, const char *src, size_t maxlen)
 {
+#if defined(HAVE_STRLCPY)
+    return strlcpy(dst, src, maxlen);
+#else
     size_t srclen = SDL_strlen(src);
     if (maxlen > 0) {
         size_t len = SDL_min(srclen, maxlen - 1);
@@ -482,8 +457,8 @@ SDL_strlcpy(char *dst, const char *src, size_t maxlen)
         dst[len] = '\0';
     }
     return srclen;
+#endif /* HAVE_STRLCPY */
 }
-#endif
 
 size_t SDL_utf8strlcpy(char *dst, const char *src, size_t dst_bytes)
 {
@@ -517,45 +492,42 @@ size_t SDL_utf8strlcpy(char *dst, const char *src, size_t dst_bytes)
     return bytes;
 }
 
-#ifdef SDL_strlcat
-#undef SDL_strlcat
-size_t SDL_strlcat(char *dst, const char *src, size_t maxlen) { return SDL_strlcat_inline(dst, src, maxlen); }
-#else
 size_t
 SDL_strlcat(char *dst, const char *src, size_t maxlen)
 {
+#if defined(HAVE_STRLCAT)
+    return strlcat(dst, src, maxlen);
+#else
     size_t dstlen = SDL_strlen(dst);
     size_t srclen = SDL_strlen(src);
     if (dstlen < maxlen) {
         SDL_strlcpy(dst + dstlen, src, maxlen - dstlen);
     }
     return dstlen + srclen;
+#endif /* HAVE_STRLCAT */
 }
-#endif
 
-#ifdef SDL_strdup
-#undef SDL_strdup
-char *SDL_strdup(const char *string) { return SDL_strdup_inline(string); }
-#else
 char *
 SDL_strdup(const char *string)
 {
+#if defined(HAVE_STRDUP)
+    return strdup(string);
+#else
     size_t len = SDL_strlen(string) + 1;
     char *newstr = SDL_malloc(len);
     if (newstr) {
         SDL_strlcpy(newstr, string, len);
     }
     return newstr;
+#endif /* HAVE_STRDUP */
 }
-#endif
 
-#ifdef SDL_strrev
-#undef SDL_strrev
-char *SDL_strrev(char *string) { return SDL_strrev_inline(string); }
-#else
 char *
 SDL_strrev(char *string)
 {
+#if defined(HAVE__STRREV)
+    return _strrev(string);
+#else
     size_t len = SDL_strlen(string);
     char *a = &string[0];
     char *b = &string[len - 1];
@@ -566,48 +538,47 @@ SDL_strrev(char *string)
         *b-- = c;
     }
     return string;
+#endif /* HAVE__STRREV */
 }
-#endif
 
-#ifdef SDL_strupr
-#undef SDL_strupr
-char *SDL_strupr(char *string) { return SDL_strupr_inline(string); }
-#else
 char *
 SDL_strupr(char *string)
 {
+#if defined(HAVE__STRUPR)
+    return _strupr(string);
+#else
     char *bufp = string;
     while (*bufp) {
         *bufp = SDL_toupper((unsigned char) *bufp);
         ++bufp;
     }
     return string;
+#endif /* HAVE__STRUPR */
 }
-#endif
 
-#ifdef SDL_strlwr
-#undef SDL_strlwr
-char *SDL_strlwr(char *string) { return SDL_strlwr_inline(string); }
-#else
 char *
 SDL_strlwr(char *string)
 {
+#if defined(HAVE__STRLWR)
+    return _strlwr(string);
+#else
     char *bufp = string;
     while (*bufp) {
         *bufp = SDL_tolower((unsigned char) *bufp);
         ++bufp;
     }
     return string;
+#endif /* HAVE__STRLWR */
 }
-#endif
 
-#ifdef SDL_strchr
-#undef SDL_strchr
-char *SDL_strchr(const char *string, int c) { return SDL_strchr_inline(string, c); }
-#else
 char *
 SDL_strchr(const char *string, int c)
 {
+#ifdef HAVE_STRCHR
+    return SDL_const_cast(char*,strchr(string, c));
+#elif defined(HAVE_INDEX)
+    return SDL_const_cast(char*,index(string, c));
+#else
     while (*string) {
         if (*string == c) {
             return (char *) string;
@@ -615,16 +586,17 @@ SDL_strchr(const char *string, int c)
         ++string;
     }
     return NULL;
+#endif /* HAVE_STRCHR */
 }
-#endif
 
-#ifdef SDL_strrchr
-#undef SDL_strrchr
-char *SDL_strrchr(const char *string, int c) { return SDL_strrchr_inline(string, c); }
-#else
 char *
 SDL_strrchr(const char *string, int c)
 {
+#ifdef HAVE_STRRCHR
+    return SDL_const_cast(char*,strrchr(string, c));
+#elif defined(HAVE_RINDEX)
+    return SDL_const_cast(char*,rindex(string, c));
+#else
     const char *bufp = string + SDL_strlen(string) - 1;
     while (bufp >= string) {
         if (*bufp == c) {
@@ -633,16 +605,15 @@ SDL_strrchr(const char *string, int c)
         --bufp;
     }
     return NULL;
+#endif /* HAVE_STRRCHR */
 }
-#endif
 
-#ifdef SDL_strstr
-#undef SDL_strstr
-char *SDL_strstr(const char *haystack, const char *needle) { return SDL_strstr_inline(haystack, needle); }
-#else
 char *
 SDL_strstr(const char *haystack, const char *needle)
 {
+#if defined(HAVE_STRSTR)
+    return SDL_const_cast(char*,strstr(haystack, needle));
+#else
     size_t length = SDL_strlen(needle);
     while (*haystack) {
         if (SDL_strncmp(haystack, needle, length) == 0) {
@@ -651,11 +622,11 @@ SDL_strstr(const char *haystack, const char *needle)
         ++haystack;
     }
     return NULL;
+#endif /* HAVE_STRSTR */
 }
-#endif
 
-#if !defined(SDL_ltoa) || !defined(SDL_lltoa) || \
-    !defined(SDL_ultoa) || !defined(SDL_ulltoa)
+#if !defined(HAVE__LTOA) || !defined(HAVE__I64TOA) || \
+    !defined(HAVE__ULTOA) || !defined(HAVE__UI64TOA)
 static const char ntoa_table[] = {
     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
@@ -664,13 +635,32 @@ static const char ntoa_table[] = {
 };
 #endif /* ntoa() conversion table */
 
-#ifdef SDL_ltoa
-#undef SDL_ltoa
-char *SDL_ltoa(long value, char *string, int radix) { return SDL_ltoa_inline(value, string, radix); }
+char *
+SDL_itoa(int value, char *string, int radix)
+{
+#ifdef HAVE_ITOA
+    return itoa(value, string, radix);
+#else
+    return SDL_ltoa((long)value, string, radix);
+#endif /* HAVE_ITOA */
+}
+
+char *
+SDL_uitoa(unsigned int value, char *string, int radix)
+{
+#ifdef HAVE__UITOA
+    return _uitoa(value, string, radix);
 #else
+    return SDL_ultoa((unsigned long)value, string, radix);
+#endif /* HAVE__UITOA */
+}
+
 char *
 SDL_ltoa(long value, char *string, int radix)
 {
+#if defined(HAVE__LTOA)
+    return _ltoa(value, string, radix);
+#else
     char *bufp = string;
 
     if (value < 0) {
@@ -695,16 +685,15 @@ SDL_ltoa(long value, char *string, int radix)
     }
 
     return string;
+#endif /* HAVE__LTOA */
 }
-#endif
 
-#ifdef SDL_ultoa
-#undef SDL_ultoa
-char *SDL_ultoa(unsigned long value, char *string, int radix) { return SDL_ultoa_inline(value, string, radix); }
-#else
 char *
 SDL_ultoa(unsigned long value, char *string, int radix)
 {
+#if defined(HAVE__ULTOA)
+    return _ultoa(value, string, radix);
+#else
     char *bufp = string;
 
     if (value) {
@@ -721,68 +710,15 @@ SDL_ultoa(unsigned long value, char *string, int radix)
     SDL_strrev(string);
 
     return string;
+#endif /* HAVE__ULTOA */
 }
-#endif
-
-#ifdef SDL_strtol
-#undef SDL_strtol
-long SDL_strtol(const char *string, char **endp, int base) { return SDL_strtol_inline(string, endp, base); }
-#else
-long
-SDL_strtol(const char *string, char **endp, int base)
-{
-    size_t len;
-    long value;
-
-    if (!base) {
-        if ((SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0)) {
-            base = 16;
-        } else {
-            base = 10;
-        }
-    }
-
-    len = SDL_ScanLong(string, base, &value);
-    if (endp) {
-        *endp = (char *) string + len;
-    }
-    return value;
-}
-#endif
 
-#ifdef SDL_strtoul
-#undef SDL_strtoul
-unsigned long SDL_strtoul(const char *string, char **endp, int base) { return SDL_strtoul_inline(string, endp, base); }
-#else
-unsigned long
-SDL_strtoul(const char *string, char **endp, int base)
-{
-    size_t len;
-    unsigned long value;
-
-    if (!base) {
-        if ((SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0)) {
-            base = 16;
-        } else {
-            base = 10;
-        }
-    }
-
-    len = SDL_ScanUnsignedLong(string, base, &value);
-    if (endp) {
-        *endp = (char *) string + len;
-    }
-    return value;
-}
-#endif
-
-#ifdef SDL_lltoa
-#undef SDL_lltoa
-char *SDL_lltoa(Sint64 value, char *string, int radix) { return SDL_lltoa_inline(value, string, radix); }
-#else
 char *
 SDL_lltoa(Sint64 value, char *string, int radix)
 {
+#if defined(HAVE__I64TOA)
+    return _i64toa(value, string, radix);
+#else
     char *bufp = string;
 
     if (value < 0) {
@@ -807,16 +743,15 @@ SDL_lltoa(Sint64 value, char *string, int radix)
     }
 
     return string;
+#endif /* HAVE__I64TOA */
 }
-#endif
 
-#ifdef SDL_ulltoa
-#undef SDL_ulltoa
-char *SDL_ulltoa(Uint64 value, char *string, int radix) { return SDL_ulltoa_inline(value, string, radix); }
-#else
 char *
 SDL_ulltoa(Uint64 value, char *string, int radix)
 {
+#if defined(HAVE__UI64TOA)
+    return _ui64toa(value, string, radix);
+#else
     char *bufp = string;
 
     if (value) {
@@ -833,16 +768,83 @@ SDL_ulltoa(Uint64 value, char *string, int radix)
     SDL_strrev(string);
 
     return string;
+#endif /* HAVE__UI64TOA */
 }
-#endif
 
-#ifdef SDL_strtoll
-#undef SDL_strtoll
-Sint64 SDL_strtoll(const char *string, char **endp, int base) { return SDL_strtoll_inline(string, endp, base); }
+int SDL_atoi(const char *string)
+{
+#ifdef HAVE_ATOI
+    return atoi(string);
+#else
+    return SDL_strtol(string, NULL, 0);
+#endif /* HAVE_ATOI */
+}
+
+double SDL_atof(const char *string)
+{
+#ifdef HAVE_ATOF
+    return (double) atof(string);
+#else
+    return SDL_strtod(string, NULL);
+#endif /* HAVE_ATOF */
+}
+
+long
+SDL_strtol(const char *string, char **endp, int base)
+{
+#if defined(HAVE_STRTOL)
+    return strtol(string, endp, base);
+#else
+    size_t len;
+    long value;
+
+    if (!base) {
+        if ((SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0)) {
+            base = 16;
+        } else {
+            base = 10;
+        }
+    }
+
+    len = SDL_ScanLong(string, base, &value);
+    if (endp) {
+        *endp = (char *) string + len;
+    }
+    return value;
+#endif /* HAVE_STRTOL */
+}
+
+unsigned long
+SDL_strtoul(const char *string, char **endp, int base)
+{
+#if defined(HAVE_STRTOUL)
+    return strtoul(string, endp, base);
 #else
+    size_t len;
+    unsigned long value;
+
+    if (!base) {
+        if ((SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0)) {
+            base = 16;
+        } else {
+            base = 10;
+        }
+    }
+
+    len = SDL_ScanUnsignedLong(string, base, &value);
+    if (endp) {
+        *endp = (char *) string + len;
+    }
+    return value;
+#endif /* HAVE_STRTOUL */
+}
+
 Sint64
 SDL_strtoll(const char *string, char **endp, int base)
 {
+#if defined(HAVE_STRTOLL)
+    return strtoll(string, endp, base);
+#else
     size_t len;
     Sint64 value;
 
@@ -859,16 +861,15 @@ SDL_strtoll(const char *string, char **endp, int base)
         *endp = (char *) string + len;
     }
     return value;
+#endif /* HAVE_STRTOLL */
 }
-#endif
 
-#ifdef SDL_strtoull
-#undef SDL_strtoull
-Uint64 SDL_strtoull(const char *string, char **endp, int base) { return SDL_strtoull_inline(string, endp, base); }
-#else
 Uint64
 SDL_strtoull(const char *string, char **endp, int base)
 {
+#if defined(HAVE_STRTOULL)
+    return strtoull(string, endp, base);
+#else
     size_t len;
     Uint64 value;
 
@@ -885,16 +886,15 @@ SDL_strtoull(const char *string, char **endp, int base)
         *endp = (char *) string + len;
     }
     return value;
+#endif /* HAVE_STRTOULL */
 }
-#endif
 
-#ifdef SDL_strtod
-#undef SDL_strtod
-double SDL_strtod(const char *string, char **endp) { return SDL_strtod_inline(string, endp); }
-#else
 double
 SDL_strtod(const char *string, char **endp)
 {
+#if defined(HAVE_STRTOD)
+    return strtod(string, endp);
+#else
     size_t len;
     double value;
 
@@ -903,16 +903,15 @@ SDL_strtod(const char *string, char **endp)
         *endp = (char *) string + len;
     }
     return value;
+#endif /* HAVE_STRTOD */
 }
-#endif
 
-#ifdef SDL_strcmp
-#undef SDL_strcmp
-int SDL_strcmp(const char *str1, const char *str2) { return SDL_strcmp_inline(str1, str2); }
-#else
 int
 SDL_strcmp(const char *str1, const char *str2)
 {
+#if defined(HAVE_STRCMP)
+    return strcmp(str1, str2);
+#else
     while (*str1 && *str2) {
         if (*str1 != *str2)
             break;
@@ -920,16 +919,15 @@ SDL_strcmp(const char *str1, const char *str2)
         ++str2;
     }
     return (int) ((unsigned char) *str1 - (unsigned char) *str2);
+#endif /* HAVE_STRCMP */
 }
-#endif
 
-#ifdef SDL_strncmp
-#undef SDL_strncmp
-int SDL_strncmp(const char *str1, const char *str2, size_t maxlen) { return SDL_strncmp_inline(str1, str2, maxlen); }
-#else
 int
 SDL_strncmp(const char *str1, const char *str2, size_t maxlen)
 {
+#if defined(HAVE_STRNCMP)
+    return strncmp(str1, str2, maxlen);
+#else
     while (*str1 && *str2 && maxlen) {
         if (*str1 != *str2)
             break;
@@ -941,39 +939,41 @@ SDL_strncmp(const char *str1, const char *str2, size_t maxlen)
         return 0;
     }
     return (int) ((unsigned char) *str1 - (unsigned char) *str2);
+#endif /* HAVE_STRNCMP */
 }
-#endif
 
-#ifdef SDL_strcasecmp
-#undef SDL_strcasecmp
-int SDL_strcasecmp(const char *str1, const char *str2) { return SDL_strcasecmp_inline(str1, str2); }
-#else
 int
 SDL_strcasecmp(const char *str1, const char *str2)
 {
+#ifdef HAVE_STRCASECMP
+    return strcasecmp(str1, str2);
+#elif defined(HAVE__STRICMP)
+    return _stricmp(str1, str2);
+#else
     char a = 0;
     char b = 0;
     while (*str1 && *str2) {
-        a = SDL_tolower((unsigned char) *str1);
-        b = SDL_tolower((unsigned char) *str2);
+        a = SDL_toupper((unsigned char) *str1);
+        b = SDL_toupper((unsigned char) *str2);
         if (a != b)
             break;
         ++str1;
         ++str2;
     }
-    a = SDL_tolower(*str1);
-    b = SDL_tolower(*str2);
+    a = SDL_toupper(*str1);
+    b = SDL_toupper(*str2);
     return (int) ((unsigned char) a - (unsigned char) b);
+#endif /* HAVE_STRCASECMP */
 }
-#endif
 
-#ifdef SDL_strncasecmp
-#undef SDL_strncasecmp
-int SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen) { return SDL_strncasecmp_inline(str1, str2, maxlen); }
-#else
 int
 SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen)
 {
+#ifdef HAVE_STRNCASECMP
+    return strncasecmp(str1, str2, maxlen);
+#elif defined(HAVE__STRNICMP)
+    return _strnicmp(str1, str2, maxlen);
+#else
     char a = 0;
     char b = 0;
     while (*str1 && *str2 && maxlen) {
@@ -992,13 +992,11 @@ SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen)
         b = SDL_tolower((unsigned char) *str2);
         return (int) ((unsigned char) a - (unsigned char) b);
     }
+#endif /* HAVE_STRNCASECMP */
 }
-#endif
 
-#ifdef SDL_sscanf
-#undef SDL_sscanf
-// Urho3D: removed function, as vsscanf is not available on Visual Studio
-/*
+#ifdef HAVE_SSCANF
+int
 SDL_sscanf(const char *text, const char *fmt, ...)
 {
     int rc;
@@ -1008,7 +1006,6 @@ SDL_sscanf(const char *text, const char *fmt, ...)
     va_end(ap);
     return rc;
 }
-*/
 #else
 int
 SDL_sscanf(const char *text, const char *fmt, ...)
@@ -1274,12 +1271,8 @@ SDL_sscanf(const char *text, const char *fmt, ...)
 
     return retval;
 }
-#endif
+#endif /* HAVE_SSCANF */
 
-/* just undef; the headers only define this to snprintf because of varargs. */
-#ifdef SDL_snprintf
-#undef SDL_snprintf
-#endif
 int
 SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...)
 {
@@ -1293,9 +1286,11 @@ SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...)
     return retval;
 }
 
-#ifdef SDL_vsnprintf
-#undef SDL_vsnprintf
-int SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap) { return SDL_vsnprintf_inline(text, maxlen, fmt, ap); }
+#ifdef HAVE_VSNPRINTF
+int SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap)
+{
+    return vsnprintf(text, maxlen, fmt, ap);
+}
 #else
  /* FIXME: implement more of the format specifiers */
 typedef struct
@@ -1313,7 +1308,24 @@ typedef struct
 static size_t
 SDL_PrintString(char *text, size_t maxlen, SDL_FormatInfo *info, const char *string)
 {
-    return SDL_strlcpy(text, string, maxlen);
+    size_t length = 0;
+
+    if (info && info->width && (size_t)info->width > SDL_strlen(string)) {
+        char fill = info->pad_zeroes ? '0' : ' ';
+        size_t width = info->width - SDL_strlen(string);
+        while (width-- > 0 && maxlen > 0) {
+            *text++ = fill;
+            ++length;
+            --maxlen;
+        }
+    }
+
+    length += SDL_strlcpy(text, string, maxlen);
+
+    if (info && info->do_lowercase) {
+        SDL_strlwr(text);
+    }
+    return length;
 }
 
 static size_t
@@ -1355,14 +1367,13 @@ SDL_PrintUnsignedLongLong(char *text, size_t maxlen, SDL_FormatInfo *info, Uint6
 static size_t
 SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, double arg)
 {
-    int i, width;
+    int width;
     size_t len;
     size_t left = maxlen;
     char *textstart = text;
 
     if (arg) {
         /* This isn't especially accurate, but hey, it's easy. :) */
-        double precision = 1.0;
         unsigned long value;
 
         if (arg < 0) {
@@ -1391,9 +1402,6 @@ SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, double arg)
         if (info->precision < 0) {
             info->precision = 6;
         }
-        for (i = 0; i < info->precision; ++i) {
-            precision *= 0.1;
-        }
         if (info->force_type || info->precision > 0) {
             int mult = 10;
             if (left > 1) {
@@ -1581,6 +1589,7 @@ SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap)
                     }
                     /* Fall through to unsigned handling */
                 case 'u':
+                    info.pad_zeroes = SDL_TRUE;
                     switch (inttype) {
                     case DO_INT:
                         len = SDL_PrintUnsignedLong(text, left, &info,
@@ -1596,12 +1605,6 @@ SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap)
                                                         va_arg(ap, Uint64));
                         break;
                     }
-                    if (info.do_lowercase) {
-                        size_t i;
-                        for (i = 0; i < len && i < left; ++i) {
-                            text[i] = SDL_tolower((unsigned char)text[i]);
-                        }
-                    }
                     done = SDL_TRUE;
                     break;
                 case 'f':
@@ -1638,6 +1641,6 @@ SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap)
     }
     return (int)(text - textstart);
 }
-#endif
+#endif /* HAVE_VSNPRINTF */
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 150 - 0
Source/ThirdParty/SDL/src/test/SDL_test_assert.c

@@ -0,0 +1,150 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+
+ Used by the test framework and test cases.
+
+*/
+
+#include "SDL_config.h"
+
+#include "SDL_test.h"
+
+/* Assert check message format */
+const char *SDLTest_AssertCheckFormat = "Assert '%s': %s";
+
+/* Assert summary message format */
+const char *SDLTest_AssertSummaryFormat = "Assert Summary: Total=%d Passed=%d Failed=%d";
+
+/*! \brief counts the failed asserts */
+static Uint32 SDLTest_AssertsFailed = 0;
+
+/*! \brief counts the passed asserts */
+static Uint32 SDLTest_AssertsPassed = 0;
+
+/*
+ *  Assert that logs and break execution flow on failures (i.e. for harness errors).
+ */
+void SDLTest_Assert(int assertCondition, const char *assertDescription, ...)
+{
+        va_list list;
+    char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
+
+    /* Print assert description into a buffer */
+    SDL_memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
+    va_start(list, assertDescription);
+    SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, assertDescription, list);
+    va_end(list);
+
+    /* Log, then assert and break on failure */
+    SDL_assert((SDLTest_AssertCheck(assertCondition, logMessage)));
+}
+
+/*
+ * Assert that logs but does not break execution flow on failures (i.e. for test cases).
+ */
+int SDLTest_AssertCheck(int assertCondition, const char *assertDescription, ...)
+{
+    va_list list;
+    char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
+
+    /* Print assert description into a buffer */
+    SDL_memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
+    va_start(list, assertDescription);
+    SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, assertDescription, list);
+    va_end(list);
+
+    /* Log pass or fail message */
+    if (assertCondition == ASSERT_FAIL)
+    {
+        SDLTest_AssertsFailed++;
+        SDLTest_LogError(SDLTest_AssertCheckFormat, logMessage, "Failed");
+    }
+    else
+    {
+        SDLTest_AssertsPassed++;
+        SDLTest_Log(SDLTest_AssertCheckFormat, logMessage, "Passed");
+    }
+
+    return assertCondition;
+}
+
+/*
+ * Explicitly passing Assert that logs (i.e. for test cases).
+ */
+void SDLTest_AssertPass(const char *assertDescription, ...)
+{
+    va_list list;
+    char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
+
+    /* Print assert description into a buffer */
+    SDL_memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
+    va_start(list, assertDescription);
+    SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, assertDescription, list);
+    va_end(list);
+
+        /* Log pass message */
+    SDLTest_AssertsPassed++;
+    SDLTest_Log(SDLTest_AssertCheckFormat, logMessage, "Pass");
+}
+
+/*
+ * Resets the assert summary counters to zero.
+ */
+void SDLTest_ResetAssertSummary()
+{
+    SDLTest_AssertsPassed = 0;
+    SDLTest_AssertsFailed = 0;
+}
+
+/*
+ * Logs summary of all assertions (total, pass, fail) since last reset
+ * as INFO (failed==0) or ERROR (failed > 0).
+ */
+void SDLTest_LogAssertSummary()
+{
+    Uint32 totalAsserts = SDLTest_AssertsPassed + SDLTest_AssertsFailed;
+    if (SDLTest_AssertsFailed == 0)
+    {
+        SDLTest_Log(SDLTest_AssertSummaryFormat, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed);
+    }
+    else
+    {
+        SDLTest_LogError(SDLTest_AssertSummaryFormat, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed);
+    }
+}
+
+/*
+ * Converts the current assert state into a test result
+ */
+int SDLTest_AssertSummaryToTestResult()
+{
+    if (SDLTest_AssertsFailed > 0) {
+        return TEST_RESULT_FAILED;
+    } else {
+        if (SDLTest_AssertsPassed > 0) {
+            return TEST_RESULT_PASSED;
+        } else {
+            return TEST_RESULT_NO_ASSERT;
+        }
+    }
+}

+ 1411 - 0
Source/ThirdParty/SDL/src/test/SDL_test_common.c

@@ -0,0 +1,1411 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* Ported from original test\common.c file. */
+
+#include "SDL_config.h"
+#include "SDL_test.h"
+
+#include <stdio.h>
+
+#define VIDEO_USAGE \
+"[--video driver] [--renderer driver] [--gldebug] [--info all|video|modes|render|event] [--log all|error|system|audio|video|render|input] [--display N] [--fullscreen | --fullscreen-desktop | --windows N] [--title title] [--icon icon.bmp] [--center | --position X,Y] [--geometry WxH] [--min-geometry WxH] [--max-geometry WxH] [--logical WxH] [--scale N] [--depth N] [--refresh R] [--vsync] [--noframe] [--resize] [--minimize] [--maximize] [--grab]"
+
+#define AUDIO_USAGE \
+"[--rate N] [--format U8|S8|U16|U16LE|U16BE|S16|S16LE|S16BE] [--channels N] [--samples N]"
+
+SDLTest_CommonState *
+SDLTest_CommonCreateState(char **argv, Uint32 flags)
+{
+    SDLTest_CommonState *state = (SDLTest_CommonState *)SDL_calloc(1, sizeof(*state));
+    if (!state) {
+        SDL_OutOfMemory();
+        return NULL;
+    }
+
+    /* Initialize some defaults */
+    state->argv = argv;
+    state->flags = flags;
+    state->window_title = argv[0];
+    state->window_flags = 0;
+    state->window_x = SDL_WINDOWPOS_UNDEFINED;
+    state->window_y = SDL_WINDOWPOS_UNDEFINED;
+    state->window_w = DEFAULT_WINDOW_WIDTH;
+    state->window_h = DEFAULT_WINDOW_HEIGHT;
+    state->num_windows = 1;
+    state->audiospec.freq = 22050;
+    state->audiospec.format = AUDIO_S16;
+    state->audiospec.channels = 2;
+    state->audiospec.samples = 2048;
+
+    /* Set some very sane GL defaults */
+    state->gl_red_size = 3;
+    state->gl_green_size = 3;
+    state->gl_blue_size = 2;
+    state->gl_alpha_size = 0;
+    state->gl_buffer_size = 0;
+    state->gl_depth_size = 16;
+    state->gl_stencil_size = 0;
+    state->gl_double_buffer = 1;
+    state->gl_accum_red_size = 0;
+    state->gl_accum_green_size = 0;
+    state->gl_accum_blue_size = 0;
+    state->gl_accum_alpha_size = 0;
+    state->gl_stereo = 0;
+    state->gl_multisamplebuffers = 0;
+    state->gl_multisamplesamples = 0;
+    state->gl_retained_backing = 1;
+    state->gl_accelerated = -1;
+    state->gl_debug = 0;
+
+    return state;
+}
+
+int
+SDLTest_CommonArg(SDLTest_CommonState * state, int index)
+{
+    char **argv = state->argv;
+
+    if (SDL_strcasecmp(argv[index], "--video") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->videodriver = argv[index];
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--renderer") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->renderdriver = argv[index];
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--gldebug") == 0) {
+        state->gl_debug = 1;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--info") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        if (SDL_strcasecmp(argv[index], "all") == 0) {
+            state->verbose |=
+                (VERBOSE_VIDEO | VERBOSE_MODES | VERBOSE_RENDER |
+                 VERBOSE_EVENT);
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "video") == 0) {
+            state->verbose |= VERBOSE_VIDEO;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "modes") == 0) {
+            state->verbose |= VERBOSE_MODES;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "render") == 0) {
+            state->verbose |= VERBOSE_RENDER;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "event") == 0) {
+            state->verbose |= VERBOSE_EVENT;
+            return 2;
+        }
+        return -1;
+    }
+    if (SDL_strcasecmp(argv[index], "--log") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        if (SDL_strcasecmp(argv[index], "all") == 0) {
+            SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "error") == 0) {
+            SDL_LogSetPriority(SDL_LOG_CATEGORY_ERROR, SDL_LOG_PRIORITY_VERBOSE);
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "system") == 0) {
+            SDL_LogSetPriority(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE);
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "audio") == 0) {
+            SDL_LogSetPriority(SDL_LOG_CATEGORY_AUDIO, SDL_LOG_PRIORITY_VERBOSE);
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "video") == 0) {
+            SDL_LogSetPriority(SDL_LOG_CATEGORY_VIDEO, SDL_LOG_PRIORITY_VERBOSE);
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "render") == 0) {
+            SDL_LogSetPriority(SDL_LOG_CATEGORY_RENDER, SDL_LOG_PRIORITY_VERBOSE);
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "input") == 0) {
+            SDL_LogSetPriority(SDL_LOG_CATEGORY_INPUT, SDL_LOG_PRIORITY_VERBOSE);
+            return 2;
+        }
+        return -1;
+    }
+    if (SDL_strcasecmp(argv[index], "--display") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->display = SDL_atoi(argv[index]);
+        if (SDL_WINDOWPOS_ISUNDEFINED(state->window_x)) {
+            state->window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->display);
+            state->window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->display);
+        }
+        if (SDL_WINDOWPOS_ISCENTERED(state->window_x)) {
+            state->window_x = SDL_WINDOWPOS_CENTERED_DISPLAY(state->display);
+            state->window_y = SDL_WINDOWPOS_CENTERED_DISPLAY(state->display);
+        }
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--fullscreen") == 0) {
+        state->window_flags |= SDL_WINDOW_FULLSCREEN;
+        state->num_windows = 1;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--fullscreen-desktop") == 0) {
+        state->window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+        state->num_windows = 1;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--windows") == 0) {
+        ++index;
+        if (!argv[index] || !SDL_isdigit(*argv[index])) {
+            return -1;
+        }
+        if (!(state->window_flags & SDL_WINDOW_FULLSCREEN)) {
+            state->num_windows = SDL_atoi(argv[index]);
+        }
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--title") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->window_title = argv[index];
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--icon") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->window_icon = argv[index];
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--center") == 0) {
+        state->window_x = SDL_WINDOWPOS_CENTERED;
+        state->window_y = SDL_WINDOWPOS_CENTERED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--position") == 0) {
+        char *x, *y;
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        x = argv[index];
+        y = argv[index];
+        while (*y && *y != ',') {
+            ++y;
+        }
+        if (!*y) {
+            return -1;
+        }
+        *y++ = '\0';
+        state->window_x = SDL_atoi(x);
+        state->window_y = SDL_atoi(y);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--geometry") == 0) {
+        char *w, *h;
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        w = argv[index];
+        h = argv[index];
+        while (*h && *h != 'x') {
+            ++h;
+        }
+        if (!*h) {
+            return -1;
+        }
+        *h++ = '\0';
+        state->window_w = SDL_atoi(w);
+        state->window_h = SDL_atoi(h);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--min-geometry") == 0) {
+        char *w, *h;
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        w = argv[index];
+        h = argv[index];
+        while (*h && *h != 'x') {
+            ++h;
+        }
+        if (!*h) {
+            return -1;
+        }
+        *h++ = '\0';
+        state->window_minW = SDL_atoi(w);
+        state->window_minH = SDL_atoi(h);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--max-geometry") == 0) {
+        char *w, *h;
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        w = argv[index];
+        h = argv[index];
+        while (*h && *h != 'x') {
+            ++h;
+        }
+        if (!*h) {
+            return -1;
+        }
+        *h++ = '\0';
+        state->window_maxW = SDL_atoi(w);
+        state->window_maxH = SDL_atoi(h);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--logical") == 0) {
+        char *w, *h;
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        w = argv[index];
+        h = argv[index];
+        while (*h && *h != 'x') {
+            ++h;
+        }
+        if (!*h) {
+            return -1;
+        }
+        *h++ = '\0';
+        state->logical_w = SDL_atoi(w);
+        state->logical_h = SDL_atoi(h);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--scale") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->scale = (float)SDL_atof(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--depth") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->depth = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--refresh") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->refresh_rate = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--vsync") == 0) {
+        state->render_flags |= SDL_RENDERER_PRESENTVSYNC;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--noframe") == 0) {
+        state->window_flags |= SDL_WINDOW_BORDERLESS;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--resize") == 0) {
+        state->window_flags |= SDL_WINDOW_RESIZABLE;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
+        state->window_flags |= SDL_WINDOW_MINIMIZED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--maximize") == 0) {
+        state->window_flags |= SDL_WINDOW_MAXIMIZED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--grab") == 0) {
+        state->window_flags |= SDL_WINDOW_INPUT_GRABBED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--rate") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->audiospec.freq = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--format") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        if (SDL_strcasecmp(argv[index], "U8") == 0) {
+            state->audiospec.format = AUDIO_U8;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S8") == 0) {
+            state->audiospec.format = AUDIO_S8;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "U16") == 0) {
+            state->audiospec.format = AUDIO_U16;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "U16LE") == 0) {
+            state->audiospec.format = AUDIO_U16LSB;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "U16BE") == 0) {
+            state->audiospec.format = AUDIO_U16MSB;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S16") == 0) {
+            state->audiospec.format = AUDIO_S16;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S16LE") == 0) {
+            state->audiospec.format = AUDIO_S16LSB;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S16BE") == 0) {
+            state->audiospec.format = AUDIO_S16MSB;
+            return 2;
+        }
+        return -1;
+    }
+    if (SDL_strcasecmp(argv[index], "--channels") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->audiospec.channels = (Uint8) SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--samples") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->audiospec.samples = (Uint16) SDL_atoi(argv[index]);
+        return 2;
+    }
+    if ((SDL_strcasecmp(argv[index], "-h") == 0)
+        || (SDL_strcasecmp(argv[index], "--help") == 0)) {
+        /* Print the usage message */
+        return -1;
+    }
+    if (SDL_strcmp(argv[index], "-NSDocumentRevisionsDebugMode") == 0) {
+    /* Debug flag sent by Xcode */
+        return 2;
+    }
+    return 0;
+}
+
+const char *
+SDLTest_CommonUsage(SDLTest_CommonState * state)
+{
+    switch (state->flags & (SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
+    case SDL_INIT_VIDEO:
+        return VIDEO_USAGE;
+    case SDL_INIT_AUDIO:
+        return AUDIO_USAGE;
+    case (SDL_INIT_VIDEO | SDL_INIT_AUDIO):
+        return VIDEO_USAGE " " AUDIO_USAGE;
+    default:
+        return "";
+    }
+}
+
+static void
+SDLTest_PrintRendererFlag(Uint32 flag)
+{
+    switch (flag) {
+    case SDL_RENDERER_PRESENTVSYNC:
+        fprintf(stderr, "PresentVSync");
+        break;
+    case SDL_RENDERER_ACCELERATED:
+        fprintf(stderr, "Accelerated");
+        break;
+    default:
+        fprintf(stderr, "0x%8.8x", flag);
+        break;
+    }
+}
+
+static void
+SDLTest_PrintPixelFormat(Uint32 format)
+{
+    switch (format) {
+    case SDL_PIXELFORMAT_UNKNOWN:
+        fprintf(stderr, "Unknwon");
+        break;
+    case SDL_PIXELFORMAT_INDEX1LSB:
+        fprintf(stderr, "Index1LSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX1MSB:
+        fprintf(stderr, "Index1MSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX4LSB:
+        fprintf(stderr, "Index4LSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX4MSB:
+        fprintf(stderr, "Index4MSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX8:
+        fprintf(stderr, "Index8");
+        break;
+    case SDL_PIXELFORMAT_RGB332:
+        fprintf(stderr, "RGB332");
+        break;
+    case SDL_PIXELFORMAT_RGB444:
+        fprintf(stderr, "RGB444");
+        break;
+    case SDL_PIXELFORMAT_RGB555:
+        fprintf(stderr, "RGB555");
+        break;
+    case SDL_PIXELFORMAT_BGR555:
+        fprintf(stderr, "BGR555");
+        break;
+    case SDL_PIXELFORMAT_ARGB4444:
+        fprintf(stderr, "ARGB4444");
+        break;
+    case SDL_PIXELFORMAT_ABGR4444:
+        fprintf(stderr, "ABGR4444");
+        break;
+    case SDL_PIXELFORMAT_ARGB1555:
+        fprintf(stderr, "ARGB1555");
+        break;
+    case SDL_PIXELFORMAT_ABGR1555:
+        fprintf(stderr, "ABGR1555");
+        break;
+    case SDL_PIXELFORMAT_RGB565:
+        fprintf(stderr, "RGB565");
+        break;
+    case SDL_PIXELFORMAT_BGR565:
+        fprintf(stderr, "BGR565");
+        break;
+    case SDL_PIXELFORMAT_RGB24:
+        fprintf(stderr, "RGB24");
+        break;
+    case SDL_PIXELFORMAT_BGR24:
+        fprintf(stderr, "BGR24");
+        break;
+    case SDL_PIXELFORMAT_RGB888:
+        fprintf(stderr, "RGB888");
+        break;
+    case SDL_PIXELFORMAT_BGR888:
+        fprintf(stderr, "BGR888");
+        break;
+    case SDL_PIXELFORMAT_ARGB8888:
+        fprintf(stderr, "ARGB8888");
+        break;
+    case SDL_PIXELFORMAT_RGBA8888:
+        fprintf(stderr, "RGBA8888");
+        break;
+    case SDL_PIXELFORMAT_ABGR8888:
+        fprintf(stderr, "ABGR8888");
+        break;
+    case SDL_PIXELFORMAT_BGRA8888:
+        fprintf(stderr, "BGRA8888");
+        break;
+    case SDL_PIXELFORMAT_ARGB2101010:
+        fprintf(stderr, "ARGB2101010");
+        break;
+    case SDL_PIXELFORMAT_YV12:
+        fprintf(stderr, "YV12");
+        break;
+    case SDL_PIXELFORMAT_IYUV:
+        fprintf(stderr, "IYUV");
+        break;
+    case SDL_PIXELFORMAT_YUY2:
+        fprintf(stderr, "YUY2");
+        break;
+    case SDL_PIXELFORMAT_UYVY:
+        fprintf(stderr, "UYVY");
+        break;
+    case SDL_PIXELFORMAT_YVYU:
+        fprintf(stderr, "YVYU");
+        break;
+    default:
+        fprintf(stderr, "0x%8.8x", format);
+        break;
+    }
+}
+
+static void
+SDLTest_PrintRenderer(SDL_RendererInfo * info)
+{
+    int i, count;
+
+    fprintf(stderr, "  Renderer %s:\n", info->name);
+
+    fprintf(stderr, "    Flags: 0x%8.8X", info->flags);
+    fprintf(stderr, " (");
+    count = 0;
+    for (i = 0; i < sizeof(info->flags) * 8; ++i) {
+        Uint32 flag = (1 << i);
+        if (info->flags & flag) {
+            if (count > 0) {
+                fprintf(stderr, " | ");
+            }
+            SDLTest_PrintRendererFlag(flag);
+            ++count;
+        }
+    }
+    fprintf(stderr, ")\n");
+
+    fprintf(stderr, "    Texture formats (%d): ", info->num_texture_formats);
+    for (i = 0; i < (int) info->num_texture_formats; ++i) {
+        if (i > 0) {
+            fprintf(stderr, ", ");
+        }
+        SDLTest_PrintPixelFormat(info->texture_formats[i]);
+    }
+    fprintf(stderr, "\n");
+
+    if (info->max_texture_width || info->max_texture_height) {
+        fprintf(stderr, "    Max Texture Size: %dx%d\n",
+                info->max_texture_width, info->max_texture_height);
+    }
+}
+
+static SDL_Surface *
+SDLTest_LoadIcon(const char *file)
+{
+    SDL_Surface *icon;
+
+    /* Load the icon surface */
+    icon = SDL_LoadBMP(file);
+    if (icon == NULL) {
+        fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
+        return (NULL);
+    }
+
+    if (icon->format->palette) {
+        /* Set the colorkey */
+        SDL_SetColorKey(icon, 1, *((Uint8 *) icon->pixels));
+    }
+
+    return (icon);
+}
+
+SDL_bool
+SDLTest_CommonInit(SDLTest_CommonState * state)
+{
+    int i, j, m, n, w, h;
+    SDL_DisplayMode fullscreen_mode;
+
+    if (state->flags & SDL_INIT_VIDEO) {
+        if (state->verbose & VERBOSE_VIDEO) {
+            n = SDL_GetNumVideoDrivers();
+            if (n == 0) {
+                fprintf(stderr, "No built-in video drivers\n");
+            } else {
+                fprintf(stderr, "Built-in video drivers:");
+                for (i = 0; i < n; ++i) {
+                    if (i > 0) {
+                        fprintf(stderr, ",");
+                    }
+                    fprintf(stderr, " %s", SDL_GetVideoDriver(i));
+                }
+                fprintf(stderr, "\n");
+            }
+        }
+        if (SDL_VideoInit(state->videodriver) < 0) {
+            fprintf(stderr, "Couldn't initialize video driver: %s\n",
+                    SDL_GetError());
+            return SDL_FALSE;
+        }
+        if (state->verbose & VERBOSE_VIDEO) {
+            fprintf(stderr, "Video driver: %s\n",
+                    SDL_GetCurrentVideoDriver());
+        }
+
+        /* Upload GL settings */
+        SDL_GL_SetAttribute(SDL_GL_RED_SIZE, state->gl_red_size);
+        SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, state->gl_green_size);
+        SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, state->gl_blue_size);
+        SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, state->gl_alpha_size);
+        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, state->gl_double_buffer);
+        SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, state->gl_buffer_size);
+        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, state->gl_depth_size);
+        SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, state->gl_stencil_size);
+        SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, state->gl_accum_red_size);
+        SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, state->gl_accum_green_size);
+        SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, state->gl_accum_blue_size);
+        SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, state->gl_accum_alpha_size);
+        SDL_GL_SetAttribute(SDL_GL_STEREO, state->gl_stereo);
+        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, state->gl_multisamplebuffers);
+        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, state->gl_multisamplesamples);
+        if (state->gl_accelerated >= 0) {
+            SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,
+                                state->gl_accelerated);
+        }
+        SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, state->gl_retained_backing);
+        if (state->gl_major_version) {
+            SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, state->gl_major_version);
+            SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, state->gl_minor_version);
+        }
+        if (state->gl_debug) {
+            SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
+        }
+
+        if (state->verbose & VERBOSE_MODES) {
+            SDL_Rect bounds;
+            SDL_DisplayMode mode;
+            int bpp;
+            Uint32 Rmask, Gmask, Bmask, Amask;
+
+            n = SDL_GetNumVideoDisplays();
+            fprintf(stderr, "Number of displays: %d\n", n);
+            for (i = 0; i < n; ++i) {
+                fprintf(stderr, "Display %d: %s\n", i, SDL_GetDisplayName(i));
+
+                SDL_zero(bounds);
+                SDL_GetDisplayBounds(i, &bounds);
+                fprintf(stderr, "Bounds: %dx%d at %d,%d\n", bounds.w, bounds.h, bounds.x, bounds.y);
+
+                SDL_GetDesktopDisplayMode(i, &mode);
+                SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask, &Gmask,
+                                           &Bmask, &Amask);
+                fprintf(stderr,
+                        "  Current mode: %dx%d@%dHz, %d bits-per-pixel (%s)\n",
+                        mode.w, mode.h, mode.refresh_rate, bpp,
+                        SDL_GetPixelFormatName(mode.format));
+                if (Rmask || Gmask || Bmask) {
+                    fprintf(stderr, "      Red Mask   = 0x%.8x\n", Rmask);
+                    fprintf(stderr, "      Green Mask = 0x%.8x\n", Gmask);
+                    fprintf(stderr, "      Blue Mask  = 0x%.8x\n", Bmask);
+                    if (Amask)
+                        fprintf(stderr, "      Alpha Mask = 0x%.8x\n", Amask);
+                }
+
+                /* Print available fullscreen video modes */
+                m = SDL_GetNumDisplayModes(i);
+                if (m == 0) {
+                    fprintf(stderr, "No available fullscreen video modes\n");
+                } else {
+                    fprintf(stderr, "  Fullscreen video modes:\n");
+                    for (j = 0; j < m; ++j) {
+                        SDL_GetDisplayMode(i, j, &mode);
+                        SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask,
+                                                   &Gmask, &Bmask, &Amask);
+                        fprintf(stderr,
+                                "    Mode %d: %dx%d@%dHz, %d bits-per-pixel (%s)\n",
+                                j, mode.w, mode.h, mode.refresh_rate, bpp,
+                                SDL_GetPixelFormatName(mode.format));
+                        if (Rmask || Gmask || Bmask) {
+                            fprintf(stderr, "        Red Mask   = 0x%.8x\n",
+                                    Rmask);
+                            fprintf(stderr, "        Green Mask = 0x%.8x\n",
+                                    Gmask);
+                            fprintf(stderr, "        Blue Mask  = 0x%.8x\n",
+                                    Bmask);
+                            if (Amask)
+                                fprintf(stderr,
+                                        "        Alpha Mask = 0x%.8x\n",
+                                        Amask);
+                        }
+                    }
+                }
+            }
+        }
+
+        if (state->verbose & VERBOSE_RENDER) {
+            SDL_RendererInfo info;
+
+            n = SDL_GetNumRenderDrivers();
+            if (n == 0) {
+                fprintf(stderr, "No built-in render drivers\n");
+            } else {
+                fprintf(stderr, "Built-in render drivers:\n");
+                for (i = 0; i < n; ++i) {
+                    SDL_GetRenderDriverInfo(i, &info);
+                    SDLTest_PrintRenderer(&info);
+                }
+            }
+        }
+
+        SDL_zero(fullscreen_mode);
+        switch (state->depth) {
+        case 8:
+            fullscreen_mode.format = SDL_PIXELFORMAT_INDEX8;
+            break;
+        case 15:
+            fullscreen_mode.format = SDL_PIXELFORMAT_RGB555;
+            break;
+        case 16:
+            fullscreen_mode.format = SDL_PIXELFORMAT_RGB565;
+            break;
+        case 24:
+            fullscreen_mode.format = SDL_PIXELFORMAT_RGB24;
+            break;
+        default:
+            fullscreen_mode.format = SDL_PIXELFORMAT_RGB888;
+            break;
+        }
+        fullscreen_mode.refresh_rate = state->refresh_rate;
+
+        state->windows =
+            (SDL_Window **) SDL_malloc(state->num_windows *
+                                        sizeof(*state->windows));
+        state->renderers =
+            (SDL_Renderer **) SDL_malloc(state->num_windows *
+                                        sizeof(*state->renderers));
+        if (!state->windows || !state->renderers) {
+            fprintf(stderr, "Out of memory!\n");
+            return SDL_FALSE;
+        }
+        for (i = 0; i < state->num_windows; ++i) {
+            char title[1024];
+
+            if (state->num_windows > 1) {
+                SDL_snprintf(title, SDL_arraysize(title), "%s %d",
+                             state->window_title, i + 1);
+            } else {
+                SDL_strlcpy(title, state->window_title, SDL_arraysize(title));
+            }
+            state->windows[i] =
+                SDL_CreateWindow(title, state->window_x, state->window_y,
+                                 state->window_w, state->window_h,
+                                 state->window_flags);
+            if (!state->windows[i]) {
+                fprintf(stderr, "Couldn't create window: %s\n",
+                        SDL_GetError());
+                return SDL_FALSE;
+            }
+            if (state->window_minW || state->window_minH) {
+                SDL_SetWindowMinimumSize(state->windows[i], state->window_minW, state->window_minH);
+            }
+            if (state->window_maxW || state->window_maxH) {
+                SDL_SetWindowMaximumSize(state->windows[i], state->window_maxW, state->window_maxH);
+            }
+            SDL_GetWindowSize(state->windows[i], &w, &h);
+            if (!(state->window_flags & SDL_WINDOW_RESIZABLE) &&
+                (w != state->window_w || h != state->window_h)) {
+                printf("Window requested size %dx%d, got %dx%d\n", state->window_w, state->window_h, w, h);
+                state->window_w = w;
+                state->window_h = h;
+            }
+            if (SDL_SetWindowDisplayMode(state->windows[i], &fullscreen_mode) < 0) {
+                fprintf(stderr, "Can't set up fullscreen display mode: %s\n",
+                        SDL_GetError());
+                return SDL_FALSE;
+            }
+
+            if (state->window_icon) {
+                SDL_Surface *icon = SDLTest_LoadIcon(state->window_icon);
+                if (icon) {
+                    SDL_SetWindowIcon(state->windows[i], icon);
+                    SDL_FreeSurface(icon);
+                }
+            }
+
+            SDL_ShowWindow(state->windows[i]);
+
+            state->renderers[i] = NULL;
+
+            if (!state->skip_renderer
+                && (state->renderdriver
+                    || !(state->window_flags & SDL_WINDOW_OPENGL))) {
+                m = -1;
+                if (state->renderdriver) {
+                    SDL_RendererInfo info;
+                    n = SDL_GetNumRenderDrivers();
+                    for (j = 0; j < n; ++j) {
+                        SDL_GetRenderDriverInfo(j, &info);
+                        if (SDL_strcasecmp(info.name, state->renderdriver) ==
+                            0) {
+                            m = j;
+                            break;
+                        }
+                    }
+                    if (m == n) {
+                        fprintf(stderr,
+                                "Couldn't find render driver named %s",
+                                state->renderdriver);
+                        return SDL_FALSE;
+                    }
+                }
+                state->renderers[i] = SDL_CreateRenderer(state->windows[i],
+                                            m, state->render_flags);
+                if (!state->renderers[i]) {
+                    fprintf(stderr, "Couldn't create renderer: %s\n",
+                            SDL_GetError());
+                    return SDL_FALSE;
+                }
+                if (state->logical_w && state->logical_h) {
+                    SDL_RenderSetLogicalSize(state->renderers[i], state->logical_w, state->logical_h);
+                } else if (state->scale) {
+                    SDL_RenderSetScale(state->renderers[i], state->scale, state->scale);
+                }
+                if (state->verbose & VERBOSE_RENDER) {
+                    SDL_RendererInfo info;
+
+                    fprintf(stderr, "Current renderer:\n");
+                    SDL_GetRendererInfo(state->renderers[i], &info);
+                    SDLTest_PrintRenderer(&info);
+                }
+            }
+        }
+    }
+
+    if (state->flags & SDL_INIT_AUDIO) {
+        if (state->verbose & VERBOSE_AUDIO) {
+            n = SDL_GetNumAudioDrivers();
+            if (n == 0) {
+                fprintf(stderr, "No built-in audio drivers\n");
+            } else {
+                fprintf(stderr, "Built-in audio drivers:");
+                for (i = 0; i < n; ++i) {
+                    if (i > 0) {
+                        fprintf(stderr, ",");
+                    }
+                    fprintf(stderr, " %s", SDL_GetAudioDriver(i));
+                }
+                fprintf(stderr, "\n");
+            }
+        }
+        if (SDL_AudioInit(state->audiodriver) < 0) {
+            fprintf(stderr, "Couldn't initialize audio driver: %s\n",
+                    SDL_GetError());
+            return SDL_FALSE;
+        }
+        if (state->verbose & VERBOSE_VIDEO) {
+            fprintf(stderr, "Audio driver: %s\n",
+                    SDL_GetCurrentAudioDriver());
+        }
+
+        if (SDL_OpenAudio(&state->audiospec, NULL) < 0) {
+            fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
+            return SDL_FALSE;
+        }
+    }
+
+    return SDL_TRUE;
+}
+
+static void
+SDLTest_PrintEvent(SDL_Event * event)
+{
+    if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_FINGERMOTION)) {
+        /* Mouse and finger motion are really spammy */
+        return;
+    }
+
+    fprintf(stderr, "SDL EVENT: ");
+    switch (event->type) {
+    case SDL_WINDOWEVENT:
+        switch (event->window.event) {
+        case SDL_WINDOWEVENT_SHOWN:
+            fprintf(stderr, "Window %d shown", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_HIDDEN:
+            fprintf(stderr, "Window %d hidden", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_EXPOSED:
+            fprintf(stderr, "Window %d exposed", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_MOVED:
+            fprintf(stderr, "Window %d moved to %d,%d",
+                    event->window.windowID, event->window.data1,
+                    event->window.data2);
+            break;
+        case SDL_WINDOWEVENT_RESIZED:
+            fprintf(stderr, "Window %d resized to %dx%d",
+                    event->window.windowID, event->window.data1,
+                    event->window.data2);
+            break;
+        case SDL_WINDOWEVENT_SIZE_CHANGED:
+            fprintf(stderr, "Window %d changed size to %dx%d",
+                    event->window.windowID, event->window.data1,
+                    event->window.data2);
+            break;
+        case SDL_WINDOWEVENT_MINIMIZED:
+            fprintf(stderr, "Window %d minimized", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_MAXIMIZED:
+            fprintf(stderr, "Window %d maximized", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_RESTORED:
+            fprintf(stderr, "Window %d restored", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_ENTER:
+            fprintf(stderr, "Mouse entered window %d",
+                    event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_LEAVE:
+            fprintf(stderr, "Mouse left window %d", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_FOCUS_GAINED:
+            fprintf(stderr, "Window %d gained keyboard focus",
+                    event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_FOCUS_LOST:
+            fprintf(stderr, "Window %d lost keyboard focus",
+                    event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_CLOSE:
+            fprintf(stderr, "Window %d closed", event->window.windowID);
+            break;
+        default:
+            fprintf(stderr, "Window %d got unknown event %d",
+                    event->window.windowID, event->window.event);
+            break;
+        }
+        break;
+    case SDL_KEYDOWN:
+        fprintf(stderr,
+                "Keyboard: key pressed  in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
+                event->key.windowID,
+                event->key.keysym.scancode,
+                SDL_GetScancodeName(event->key.keysym.scancode),
+                event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
+        break;
+    case SDL_KEYUP:
+        fprintf(stderr,
+                "Keyboard: key released in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
+                event->key.windowID,
+                event->key.keysym.scancode,
+                SDL_GetScancodeName(event->key.keysym.scancode),
+                event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
+        break;
+    case SDL_TEXTINPUT:
+        fprintf(stderr, "Keyboard: text input \"%s\" in window %d",
+                event->text.text, event->text.windowID);
+        break;
+    case SDL_MOUSEMOTION:
+        fprintf(stderr, "Mouse: moved to %d,%d (%d,%d) in window %d",
+                event->motion.x, event->motion.y,
+                event->motion.xrel, event->motion.yrel,
+                event->motion.windowID);
+        break;
+    case SDL_MOUSEBUTTONDOWN:
+        fprintf(stderr, "Mouse: button %d pressed at %d,%d in window %d",
+                event->button.button, event->button.x, event->button.y,
+                event->button.windowID);
+        break;
+    case SDL_MOUSEBUTTONUP:
+        fprintf(stderr, "Mouse: button %d released at %d,%d in window %d",
+                event->button.button, event->button.x, event->button.y,
+                event->button.windowID);
+        break;
+    case SDL_MOUSEWHEEL:
+        fprintf(stderr,
+                "Mouse: wheel scrolled %d in x and %d in y in window %d",
+                event->wheel.x, event->wheel.y, event->wheel.windowID);
+        break;
+    case SDL_JOYBALLMOTION:
+        fprintf(stderr, "Joystick %d: ball %d moved by %d,%d",
+                event->jball.which, event->jball.ball, event->jball.xrel,
+                event->jball.yrel);
+        break;
+    case SDL_JOYHATMOTION:
+        fprintf(stderr, "Joystick %d: hat %d moved to ", event->jhat.which,
+                event->jhat.hat);
+        switch (event->jhat.value) {
+        case SDL_HAT_CENTERED:
+            fprintf(stderr, "CENTER");
+            break;
+        case SDL_HAT_UP:
+            fprintf(stderr, "UP");
+            break;
+        case SDL_HAT_RIGHTUP:
+            fprintf(stderr, "RIGHTUP");
+            break;
+        case SDL_HAT_RIGHT:
+            fprintf(stderr, "RIGHT");
+            break;
+        case SDL_HAT_RIGHTDOWN:
+            fprintf(stderr, "RIGHTDOWN");
+            break;
+        case SDL_HAT_DOWN:
+            fprintf(stderr, "DOWN");
+            break;
+        case SDL_HAT_LEFTDOWN:
+            fprintf(stderr, "LEFTDOWN");
+            break;
+        case SDL_HAT_LEFT:
+            fprintf(stderr, "LEFT");
+            break;
+        case SDL_HAT_LEFTUP:
+            fprintf(stderr, "LEFTUP");
+            break;
+        default:
+            fprintf(stderr, "UNKNOWN");
+            break;
+        }
+        break;
+    case SDL_JOYBUTTONDOWN:
+        fprintf(stderr, "Joystick %d: button %d pressed",
+                event->jbutton.which, event->jbutton.button);
+        break;
+    case SDL_JOYBUTTONUP:
+        fprintf(stderr, "Joystick %d: button %d released",
+                event->jbutton.which, event->jbutton.button);
+        break;
+    case SDL_CLIPBOARDUPDATE:
+        fprintf(stderr, "Clipboard updated");
+        break;
+
+    case SDL_FINGERDOWN:
+    case SDL_FINGERUP:
+        fprintf(stderr, "Finger: %s touch=%lld, finger=%lld, x=%f, y=%f, dx=%f, dy=%f, pressure=%f",
+                (event->type == SDL_FINGERDOWN) ? "down" : "up",
+                (long long) event->tfinger.touchId,
+                (long long) event->tfinger.fingerId,
+                event->tfinger.x, event->tfinger.y,
+                event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
+        break;
+
+    case SDL_QUIT:
+        fprintf(stderr, "Quit requested");
+        break;
+    case SDL_USEREVENT:
+        fprintf(stderr, "User event %d", event->user.code);
+        break;
+    default:
+        fprintf(stderr, "Unknown event %d", event->type);
+        break;
+    }
+    fprintf(stderr, "\n");
+}
+
+static void
+SDLTest_ScreenShot(SDL_Renderer *renderer)
+{
+    SDL_Rect viewport;
+    SDL_Surface *surface;
+
+    if (!renderer) {
+        return;
+    }
+
+    SDL_RenderGetViewport(renderer, &viewport);
+    surface = SDL_CreateRGBSurface(0, viewport.w, viewport.h, 24,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+                    0x00FF0000, 0x0000FF00, 0x000000FF,
+#else
+                    0x000000FF, 0x0000FF00, 0x00FF0000,
+#endif
+                    0x00000000);
+    if (!surface) {
+        fprintf(stderr, "Couldn't create surface: %s\n", SDL_GetError());
+        return;
+    }
+
+    if (SDL_RenderReadPixels(renderer, NULL, surface->format->format,
+                             surface->pixels, surface->pitch) < 0) {
+        fprintf(stderr, "Couldn't read screen: %s\n", SDL_GetError());
+        return;
+    }
+
+    if (SDL_SaveBMP(surface, "screenshot.bmp") < 0) {
+        fprintf(stderr, "Couldn't save screenshot.bmp: %s\n", SDL_GetError());
+        return;
+    }
+}
+
+static void
+FullscreenTo(int index, int windowId)
+{
+    Uint32 flags;
+    struct SDL_Rect rect = { 0, 0, 0, 0 };
+    SDL_Window *window = SDL_GetWindowFromID(windowId);
+    if (!window) {
+        return;
+    }
+
+    SDL_GetDisplayBounds( index, &rect );
+
+    flags = SDL_GetWindowFlags(window);
+    if (flags & SDL_WINDOW_FULLSCREEN) {
+        SDL_SetWindowFullscreen( window, SDL_FALSE );
+        SDL_Delay( 15 );
+    }
+
+    SDL_SetWindowPosition( window, rect.x, rect.y );
+    SDL_SetWindowFullscreen( window, SDL_TRUE );
+}
+
+void
+SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
+{
+    int i;
+    static SDL_MouseMotionEvent lastEvent;
+
+    if (state->verbose & VERBOSE_EVENT) {
+        SDLTest_PrintEvent(event);
+    }
+
+    switch (event->type) {
+    case SDL_WINDOWEVENT:
+        switch (event->window.event) {
+        case SDL_WINDOWEVENT_CLOSE:
+            {
+                SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
+                if (window) {
+                    SDL_DestroyWindow(window);
+                }
+            }
+            break;
+        }
+        break;
+    case SDL_KEYDOWN:
+        switch (event->key.keysym.sym) {
+            /* Add hotkeys here */
+        case SDLK_PRINTSCREEN: {
+                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+                if (window) {
+                    for (i = 0; i < state->num_windows; ++i) {
+                        if (window == state->windows[i]) {
+                            SDLTest_ScreenShot(state->renderers[i]);
+                        }
+                    }
+                }
+            }
+            break;
+        case SDLK_EQUALS:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-+ double the size of the window */
+                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+                if (window) {
+                    int w, h;
+                    SDL_GetWindowSize(window, &w, &h);
+                    SDL_SetWindowSize(window, w*2, h*2);
+                }
+            }
+            break;
+        case SDLK_MINUS:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-- half the size of the window */
+                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+                if (window) {
+                    int w, h;
+                    SDL_GetWindowSize(window, &w, &h);
+                    SDL_SetWindowSize(window, w/2, h/2);
+                }
+            }
+            break;
+        case SDLK_c:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-C copy awesome text! */
+                SDL_SetClipboardText("SDL rocks!\nYou know it!");
+                printf("Copied text to clipboard\n");
+            }
+            if (event->key.keysym.mod & KMOD_ALT) {
+                /* Alt-C toggle a render clip rectangle */
+                for (i = 0; i < state->num_windows; ++i) {
+                    int w, h;
+                    if (state->renderers[i]) {
+                        SDL_Rect clip;
+                        SDL_GetWindowSize(state->windows[i], &w, &h);
+                        SDL_RenderGetClipRect(state->renderers[i], &clip);
+                        if (SDL_RectEmpty(&clip)) {
+                            clip.x = w/4;
+                            clip.y = h/4;
+                            clip.w = w/2;
+                            clip.h = h/2;
+                            SDL_RenderSetClipRect(state->renderers[i], &clip);
+                        } else {
+                            SDL_RenderSetClipRect(state->renderers[i], NULL);
+                        }
+                    }
+                }
+            }
+            break;
+        case SDLK_v:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-V paste awesome text! */
+                char *text = SDL_GetClipboardText();
+                if (*text) {
+                    printf("Clipboard: %s\n", text);
+                } else {
+                    printf("Clipboard is empty\n");
+                }
+                SDL_free(text);
+            }
+            break;
+        case SDLK_g:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-G toggle grab */
+                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+                if (window) {
+                    SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window) ? SDL_TRUE : SDL_FALSE);
+                }
+            }
+            break;
+        case SDLK_m:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-M maximize */
+                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+                if (window) {
+                    Uint32 flags = SDL_GetWindowFlags(window);
+                    if (flags & SDL_WINDOW_MAXIMIZED) {
+                        SDL_RestoreWindow(window);
+                    } else {
+                        SDL_MaximizeWindow(window);
+                    }
+                }
+            }
+            break;
+        case SDLK_r:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-R toggle mouse relative mode */
+                SDL_SetRelativeMouseMode(!SDL_GetRelativeMouseMode() ? SDL_TRUE : SDL_FALSE);
+            }
+            break;
+        case SDLK_z:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-Z minimize */
+                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+                if (window) {
+                    SDL_MinimizeWindow(window);
+                }
+            }
+            break;
+        case SDLK_RETURN:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-Enter toggle fullscreen */
+                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+                if (window) {
+                    Uint32 flags = SDL_GetWindowFlags(window);
+                    if (flags & SDL_WINDOW_FULLSCREEN) {
+                        SDL_SetWindowFullscreen(window, SDL_FALSE);
+                    } else {
+                        SDL_SetWindowFullscreen(window, SDL_TRUE);
+                    }
+                }
+            } else if (event->key.keysym.mod & KMOD_ALT) {
+                /* Alt-Enter toggle fullscreen desktop */
+                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+                if (window) {
+                    Uint32 flags = SDL_GetWindowFlags(window);
+                    if (flags & SDL_WINDOW_FULLSCREEN) {
+                        SDL_SetWindowFullscreen(window, SDL_FALSE);
+                    } else {
+                        SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
+                    }
+                }
+            }
+            break;
+        case SDLK_b:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-B toggle window border */
+                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+                if (window) {
+                    const Uint32 flags = SDL_GetWindowFlags(window);
+                    const SDL_bool b = ((flags & SDL_WINDOW_BORDERLESS) != 0) ? SDL_TRUE : SDL_FALSE;
+                    SDL_SetWindowBordered(window, b);
+                }
+            }
+            break;
+        case SDLK_0:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+                SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Test Message", "You're awesome!", window);
+            }
+            break;
+        case SDLK_1:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                FullscreenTo(0, event->key.windowID);
+            }
+            break;
+        case SDLK_2:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                FullscreenTo(1, event->key.windowID);
+            }
+            break;
+        case SDLK_ESCAPE:
+            *done = 1;
+            break;
+        case SDLK_SPACE:
+        {
+            char message[256];
+            SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+
+            SDL_snprintf(message, sizeof(message), "(%i, %i), rel (%i, %i)\n", lastEvent.x, lastEvent.y, lastEvent.xrel, lastEvent.yrel);
+            SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Last mouse position", message, window);
+            break;
+        }
+        default:
+            break;
+        }
+        break;
+    case SDL_QUIT:
+        *done = 1;
+        break;
+    case SDL_MOUSEMOTION:
+        lastEvent = event->motion;
+        break;
+    }
+}
+
+void
+SDLTest_CommonQuit(SDLTest_CommonState * state)
+{
+    int i;
+
+    if (state->windows) {
+        SDL_free(state->windows);
+    }
+    if (state->renderers) {
+        for (i = 0; i < state->num_windows; ++i) {
+            if (state->renderers[i]) {
+                SDL_DestroyRenderer(state->renderers[i]);
+            }
+        }
+        SDL_free(state->renderers);
+    }
+    if (state->flags & SDL_INIT_VIDEO) {
+        SDL_VideoQuit();
+    }
+    if (state->flags & SDL_INIT_AUDIO) {
+        SDL_AudioQuit();
+    }
+    SDL_free(state);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 107 - 0
Source/ThirdParty/SDL/src/test/SDL_test_compare.c

@@ -0,0 +1,107 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+
+ Based on automated SDL_Surface tests originally written by Edgar Simo 'bobbens'.
+
+ Rewritten for test lib by Andreas Schiffler.
+
+*/
+
+#include "SDL_config.h"
+
+#include "SDL_test.h"
+
+
+/* Counter for _CompareSurface calls; used for filename creation when comparisons fail */
+static int _CompareSurfaceCount = 0;
+
+/* Compare surfaces */
+int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error)
+{
+   int ret;
+   int i,j;
+   int bpp, bpp_reference;
+   Uint8 *p, *p_reference;
+   int dist;
+   Uint8 R, G, B, A;
+   Uint8 Rd, Gd, Bd, Ad;
+   char imageFilename[128];
+   char referenceFilename[128];
+
+   /* Validate input surfaces */
+   if (surface == NULL || referenceSurface == NULL) {
+      return -1;
+   }
+
+   /* Make sure surface size is the same. */
+   if ((surface->w != referenceSurface->w) || (surface->h != referenceSurface->h)) {
+      return -2;
+   }
+
+   /* Sanitize input value */
+   if (allowable_error<0) {
+      allowable_error = 0;
+   }
+
+   SDL_LockSurface( surface );
+   SDL_LockSurface( referenceSurface );
+
+   ret = 0;
+   bpp = surface->format->BytesPerPixel;
+   bpp_reference = referenceSurface->format->BytesPerPixel;
+   /* Compare image - should be same format. */
+   for (j=0; j<surface->h; j++) {
+      for (i=0; i<surface->w; i++) {
+         p  = (Uint8 *)surface->pixels + j * surface->pitch + i * bpp;
+         p_reference = (Uint8 *)referenceSurface->pixels + j * referenceSurface->pitch + i * bpp_reference;
+
+         SDL_GetRGBA(*(Uint32*)p, surface->format, &R, &G, &B, &A);
+         SDL_GetRGBA(*(Uint32*)p_reference, referenceSurface->format, &Rd, &Gd, &Bd, &Ad);
+
+         dist = 0;
+         dist += (R-Rd)*(R-Rd);
+         dist += (G-Gd)*(G-Gd);
+         dist += (B-Bd)*(B-Bd);
+
+         /* Allow some difference in blending accuracy */
+         if (dist > allowable_error) {
+            ret++;
+         }
+      }
+   }
+
+   SDL_UnlockSurface( surface );
+   SDL_UnlockSurface( referenceSurface );
+
+   /* Save test image and reference for analysis on failures */
+   _CompareSurfaceCount++;
+   if (ret != 0) {
+      SDL_snprintf(imageFilename, 127, "CompareSurfaces%04d_TestOutput.bmp", _CompareSurfaceCount);
+      SDL_SaveBMP(surface, imageFilename);
+      SDL_snprintf(referenceFilename, 127, "CompareSurfaces%04d_Reference.bmp", _CompareSurfaceCount);
+      SDL_SaveBMP(referenceSurface, referenceFilename);
+      SDLTest_LogError("Surfaces from failed comparison saved as '%s' and '%s'", imageFilename, referenceFilename);
+   }
+
+   return ret;
+}

+ 165 - 0
Source/ThirdParty/SDL/src/test/SDL_test_crc32.c

@@ -0,0 +1,165 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+
+ Used by the test execution component.
+ Original source code contributed by A. Schiffler for GSOC project.
+
+*/
+
+#include "SDL_config.h"
+
+#include "SDL_test.h"
+
+
+int SDLTest_Crc32Init(SDLTest_Crc32Context *crcContext)
+{
+  int i,j;
+  CrcUint32 c;
+
+  /* Sanity check context pointer */
+  if (crcContext==NULL) {
+   return -1;
+  }
+
+  /*
+   * Build auxiliary table for parallel byte-at-a-time CRC-32
+   */
+#ifdef ORIGINAL_METHOD
+  for (i = 0; i < 256; ++i) {
+    for (c = i << 24, j = 8; j > 0; --j) {
+      c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
+    }
+    crcContext->crc32_table[i] = c;
+  }
+#else
+  for (i=0; i<256; i++) {
+   c = i;
+   for (j=8; j>0; j--) {
+    if (c & 1) {
+     c = (c >> 1) ^ CRC32_POLY;
+    } else {
+     c >>= 1;
+    }
+   }
+   crcContext->crc32_table[i] = c;
+  }
+#endif
+
+  return 0;
+}
+
+/* Complete CRC32 calculation on a memory block */
+
+int SDLTest_Crc32Calc(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32)
+{
+  if (SDLTest_Crc32CalcStart(crcContext,crc32)) {
+   return -1;
+  }
+
+  if (SDLTest_Crc32CalcBuffer(crcContext, inBuf, inLen, crc32)) {
+   return -1;
+  }
+
+  if (SDLTest_Crc32CalcEnd(crcContext, crc32)) {
+   return -1;
+  }
+
+  return 0;
+}
+
+/* Start crc calculation */
+
+int SDLTest_Crc32CalcStart(SDLTest_Crc32Context * crcContext, CrcUint32 *crc32)
+{
+  /* Sanity check pointers */
+  if (crcContext==NULL) {
+   *crc32=0;
+   return -1;
+  }
+
+  /*
+   * Preload shift register, per CRC-32 spec
+   */
+  *crc32 = 0xffffffff;
+
+  return 0;
+}
+
+/* Finish crc calculation */
+
+int SDLTest_Crc32CalcEnd(SDLTest_Crc32Context * crcContext, CrcUint32 *crc32)
+{
+  /* Sanity check pointers */
+  if (crcContext==NULL) {
+   *crc32=0;
+   return -1;
+  }
+
+  /*
+   * Return complement, per CRC-32 spec
+   */
+  *crc32 = (~(*crc32));
+
+  return 0;
+}
+
+/* Include memory block in crc */
+
+int SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32)
+{
+  CrcUint8    *p;
+  register CrcUint32    crc;
+
+  if (crcContext==NULL) {
+   *crc32=0;
+   return -1;
+  }
+
+  if (inBuf==NULL) {
+   return -1;
+  }
+
+  /*
+   * Calculate CRC from data
+   */
+  crc = *crc32;
+  for (p = inBuf; inLen > 0; ++p, --inLen) {
+#ifdef ORIGINAL_METHOD
+    crc = (crc << 8) ^ crcContext->crc32_table[(crc >> 24) ^ *p];
+#else
+    crc = ((crc >> 8) & 0x00FFFFFF) ^ crcContext->crc32_table[ (crc ^ *p) & 0xFF ];
+#endif
+  }
+  *crc32 = crc;
+
+  return 0;
+}
+
+int SDLTest_Crc32Done(SDLTest_Crc32Context * crcContext)
+{
+  if (crcContext==NULL) {
+     return -1;
+  }
+
+  return 0;
+}

+ 3238 - 0
Source/ThirdParty/SDL/src/test/SDL_test_font.c

@@ -0,0 +1,3238 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+#include "SDL_test.h"
+
+/* ---- 8x8 font definition ---- */
+
+/* Originally part of SDL2_gfx */
+
+/* ZLIB (c) A. Schiffler 2012 */
+
+#define SDL_TESTFONTDATAMAX (8*256)
+
+static unsigned char SDLTest_FontData[SDL_TESTFONTDATAMAX] = {
+
+    /*
+    * 0 0x00 '^@'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 1 0x01 '^A'
+    */
+    0x7e,           /* 01111110 */
+    0x81,           /* 10000001 */
+    0xa5,           /* 10100101 */
+    0x81,           /* 10000001 */
+    0xbd,           /* 10111101 */
+    0x99,           /* 10011001 */
+    0x81,           /* 10000001 */
+    0x7e,           /* 01111110 */
+
+    /*
+    * 2 0x02 '^B'
+    */
+    0x7e,           /* 01111110 */
+    0xff,           /* 11111111 */
+    0xdb,           /* 11011011 */
+    0xff,           /* 11111111 */
+    0xc3,           /* 11000011 */
+    0xe7,           /* 11100111 */
+    0xff,           /* 11111111 */
+    0x7e,           /* 01111110 */
+
+    /*
+    * 3 0x03 '^C'
+    */
+    0x6c,           /* 01101100 */
+    0xfe,           /* 11111110 */
+    0xfe,           /* 11111110 */
+    0xfe,           /* 11111110 */
+    0x7c,           /* 01111100 */
+    0x38,           /* 00111000 */
+    0x10,           /* 00010000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 4 0x04 '^D'
+    */
+    0x10,           /* 00010000 */
+    0x38,           /* 00111000 */
+    0x7c,           /* 01111100 */
+    0xfe,           /* 11111110 */
+    0x7c,           /* 01111100 */
+    0x38,           /* 00111000 */
+    0x10,           /* 00010000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 5 0x05 '^E'
+    */
+    0x38,           /* 00111000 */
+    0x7c,           /* 01111100 */
+    0x38,           /* 00111000 */
+    0xfe,           /* 11111110 */
+    0xfe,           /* 11111110 */
+    0xd6,           /* 11010110 */
+    0x10,           /* 00010000 */
+    0x38,           /* 00111000 */
+
+    /*
+    * 6 0x06 '^F'
+    */
+    0x10,           /* 00010000 */
+    0x38,           /* 00111000 */
+    0x7c,           /* 01111100 */
+    0xfe,           /* 11111110 */
+    0xfe,           /* 11111110 */
+    0x7c,           /* 01111100 */
+    0x10,           /* 00010000 */
+    0x38,           /* 00111000 */
+
+    /*
+    * 7 0x07 '^G'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 8 0x08 '^H'
+    */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xe7,           /* 11100111 */
+    0xc3,           /* 11000011 */
+    0xc3,           /* 11000011 */
+    0xe7,           /* 11100111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+
+    /*
+    * 9 0x09 '^I'
+    */
+    0x00,           /* 00000000 */
+    0x3c,           /* 00111100 */
+    0x66,           /* 01100110 */
+    0x42,           /* 01000010 */
+    0x42,           /* 01000010 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 10 0x0a '^J'
+    */
+    0xff,           /* 11111111 */
+    0xc3,           /* 11000011 */
+    0x99,           /* 10011001 */
+    0xbd,           /* 10111101 */
+    0xbd,           /* 10111101 */
+    0x99,           /* 10011001 */
+    0xc3,           /* 11000011 */
+    0xff,           /* 11111111 */
+
+    /*
+    * 11 0x0b '^K'
+    */
+    0x0f,           /* 00001111 */
+    0x07,           /* 00000111 */
+    0x0f,           /* 00001111 */
+    0x7d,           /* 01111101 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0x78,           /* 01111000 */
+
+    /*
+    * 12 0x0c '^L'
+    */
+    0x3c,           /* 00111100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 13 0x0d '^M'
+    */
+    0x3f,           /* 00111111 */
+    0x33,           /* 00110011 */
+    0x3f,           /* 00111111 */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x70,           /* 01110000 */
+    0xf0,           /* 11110000 */
+    0xe0,           /* 11100000 */
+
+    /*
+    * 14 0x0e '^N'
+    */
+    0x7f,           /* 01111111 */
+    0x63,           /* 01100011 */
+    0x7f,           /* 01111111 */
+    0x63,           /* 01100011 */
+    0x63,           /* 01100011 */
+    0x67,           /* 01100111 */
+    0xe6,           /* 11100110 */
+    0xc0,           /* 11000000 */
+
+    /*
+    * 15 0x0f '^O'
+    */
+    0x18,           /* 00011000 */
+    0xdb,           /* 11011011 */
+    0x3c,           /* 00111100 */
+    0xe7,           /* 11100111 */
+    0xe7,           /* 11100111 */
+    0x3c,           /* 00111100 */
+    0xdb,           /* 11011011 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 16 0x10 '^P'
+    */
+    0x80,           /* 10000000 */
+    0xe0,           /* 11100000 */
+    0xf8,           /* 11111000 */
+    0xfe,           /* 11111110 */
+    0xf8,           /* 11111000 */
+    0xe0,           /* 11100000 */
+    0x80,           /* 10000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 17 0x11 '^Q'
+    */
+    0x02,           /* 00000010 */
+    0x0e,           /* 00001110 */
+    0x3e,           /* 00111110 */
+    0xfe,           /* 11111110 */
+    0x3e,           /* 00111110 */
+    0x0e,           /* 00001110 */
+    0x02,           /* 00000010 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 18 0x12 '^R'
+    */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 19 0x13 '^S'
+    */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x00,           /* 00000000 */
+    0x66,           /* 01100110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 20 0x14 '^T'
+    */
+    0x7f,           /* 01111111 */
+    0xdb,           /* 11011011 */
+    0xdb,           /* 11011011 */
+    0x7b,           /* 01111011 */
+    0x1b,           /* 00011011 */
+    0x1b,           /* 00011011 */
+    0x1b,           /* 00011011 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 21 0x15 '^U'
+    */
+    0x3e,           /* 00111110 */
+    0x61,           /* 01100001 */
+    0x3c,           /* 00111100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+    0x86,           /* 10000110 */
+    0x7c,           /* 01111100 */
+
+    /*
+    * 22 0x16 '^V'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x7e,           /* 01111110 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 23 0x17 '^W'
+    */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0xff,           /* 11111111 */
+
+    /*
+    * 24 0x18 '^X'
+    */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 25 0x19 '^Y'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 26 0x1a '^Z'
+    */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0xfe,           /* 11111110 */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 27 0x1b '^['
+    */
+    0x00,           /* 00000000 */
+    0x30,           /* 00110000 */
+    0x60,           /* 01100000 */
+    0xfe,           /* 11111110 */
+    0x60,           /* 01100000 */
+    0x30,           /* 00110000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 28 0x1c '^\'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 29 0x1d '^]'
+    */
+    0x00,           /* 00000000 */
+    0x24,           /* 00100100 */
+    0x66,           /* 01100110 */
+    0xff,           /* 11111111 */
+    0x66,           /* 01100110 */
+    0x24,           /* 00100100 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 30 0x1e '^^'
+    */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x7e,           /* 01111110 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 31 0x1f '^_'
+    */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0x7e,           /* 01111110 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 32 0x20 ' '
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 33 0x21 '!'
+    */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 34 0x22 '"'
+    */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x24,           /* 00100100 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 35 0x23 '#'
+    */
+    0x6c,           /* 01101100 */
+    0x6c,           /* 01101100 */
+    0xfe,           /* 11111110 */
+    0x6c,           /* 01101100 */
+    0xfe,           /* 11111110 */
+    0x6c,           /* 01101100 */
+    0x6c,           /* 01101100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 36 0x24 '$'
+    */
+    0x18,           /* 00011000 */
+    0x3e,           /* 00111110 */
+    0x60,           /* 01100000 */
+    0x3c,           /* 00111100 */
+    0x06,           /* 00000110 */
+    0x7c,           /* 01111100 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 37 0x25 '%'
+    */
+    0x00,           /* 00000000 */
+    0xc6,           /* 11000110 */
+    0xcc,           /* 11001100 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x66,           /* 01100110 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 38 0x26 '&'
+    */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0x38,           /* 00111000 */
+    0x76,           /* 01110110 */
+    0xdc,           /* 11011100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 39 0x27 '''
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 40 0x28 '('
+    */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 41 0x29 ')'
+    */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0x0c,           /* 00001100 */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 42 0x2a '*'
+    */
+    0x00,           /* 00000000 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+    0xff,           /* 11111111 */
+    0x3c,           /* 00111100 */
+    0x66,           /* 01100110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 43 0x2b '+'
+    */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 44 0x2c ','
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+
+    /*
+    * 45 0x2d '-'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 46 0x2e '.'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 47 0x2f '/'
+    */
+    0x06,           /* 00000110 */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x60,           /* 01100000 */
+    0xc0,           /* 11000000 */
+    0x80,           /* 10000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 48 0x30 '0'
+    */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0xc6,           /* 11000110 */
+    0xd6,           /* 11010110 */
+    0xc6,           /* 11000110 */
+    0x6c,           /* 01101100 */
+    0x38,           /* 00111000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 49 0x31 '1'
+    */
+    0x18,           /* 00011000 */
+    0x38,           /* 00111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 50 0x32 '2'
+    */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0x06,           /* 00000110 */
+    0x1c,           /* 00011100 */
+    0x30,           /* 00110000 */
+    0x66,           /* 01100110 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 51 0x33 '3'
+    */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0x06,           /* 00000110 */
+    0x3c,           /* 00111100 */
+    0x06,           /* 00000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 52 0x34 '4'
+    */
+    0x1c,           /* 00011100 */
+    0x3c,           /* 00111100 */
+    0x6c,           /* 01101100 */
+    0xcc,           /* 11001100 */
+    0xfe,           /* 11111110 */
+    0x0c,           /* 00001100 */
+    0x1e,           /* 00011110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 53 0x35 '5'
+    */
+    0xfe,           /* 11111110 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0xfc,           /* 11111100 */
+    0x06,           /* 00000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 54 0x36 '6'
+    */
+    0x38,           /* 00111000 */
+    0x60,           /* 01100000 */
+    0xc0,           /* 11000000 */
+    0xfc,           /* 11111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 55 0x37 '7'
+    */
+    0xfe,           /* 11111110 */
+    0xc6,           /* 11000110 */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 56 0x38 '8'
+    */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 57 0x39 '9'
+    */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7e,           /* 01111110 */
+    0x06,           /* 00000110 */
+    0x0c,           /* 00001100 */
+    0x78,           /* 01111000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 58 0x3a ':'
+    */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 59 0x3b ';'
+    */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+
+    /*
+    * 60 0x3c '<'
+    */
+    0x06,           /* 00000110 */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0x06,           /* 00000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 61 0x3d '='
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 62 0x3e '>'
+    */
+    0x60,           /* 01100000 */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x60,           /* 01100000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 63 0x3f '?'
+    */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 64 0x40 '@'
+    */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xde,           /* 11011110 */
+    0xde,           /* 11011110 */
+    0xde,           /* 11011110 */
+    0xc0,           /* 11000000 */
+    0x78,           /* 01111000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 65 0x41 'A'
+    */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 66 0x42 'B'
+    */
+    0xfc,           /* 11111100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x7c,           /* 01111100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0xfc,           /* 11111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 67 0x43 'C'
+    */
+    0x3c,           /* 00111100 */
+    0x66,           /* 01100110 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 68 0x44 'D'
+    */
+    0xf8,           /* 11111000 */
+    0x6c,           /* 01101100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x6c,           /* 01101100 */
+    0xf8,           /* 11111000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 69 0x45 'E'
+    */
+    0xfe,           /* 11111110 */
+    0x62,           /* 01100010 */
+    0x68,           /* 01101000 */
+    0x78,           /* 01111000 */
+    0x68,           /* 01101000 */
+    0x62,           /* 01100010 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 70 0x46 'F'
+    */
+    0xfe,           /* 11111110 */
+    0x62,           /* 01100010 */
+    0x68,           /* 01101000 */
+    0x78,           /* 01111000 */
+    0x68,           /* 01101000 */
+    0x60,           /* 01100000 */
+    0xf0,           /* 11110000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 71 0x47 'G'
+    */
+    0x3c,           /* 00111100 */
+    0x66,           /* 01100110 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0xce,           /* 11001110 */
+    0x66,           /* 01100110 */
+    0x3a,           /* 00111010 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 72 0x48 'H'
+    */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 73 0x49 'I'
+    */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 74 0x4a 'J'
+    */
+    0x1e,           /* 00011110 */
+    0x0c,           /* 00001100 */
+    0x0c,           /* 00001100 */
+    0x0c,           /* 00001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0x78,           /* 01111000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 75 0x4b 'K'
+    */
+    0xe6,           /* 11100110 */
+    0x66,           /* 01100110 */
+    0x6c,           /* 01101100 */
+    0x78,           /* 01111000 */
+    0x6c,           /* 01101100 */
+    0x66,           /* 01100110 */
+    0xe6,           /* 11100110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 76 0x4c 'L'
+    */
+    0xf0,           /* 11110000 */
+    0x60,           /* 01100000 */
+    0x60,           /* 01100000 */
+    0x60,           /* 01100000 */
+    0x62,           /* 01100010 */
+    0x66,           /* 01100110 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 77 0x4d 'M'
+    */
+    0xc6,           /* 11000110 */
+    0xee,           /* 11101110 */
+    0xfe,           /* 11111110 */
+    0xfe,           /* 11111110 */
+    0xd6,           /* 11010110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 78 0x4e 'N'
+    */
+    0xc6,           /* 11000110 */
+    0xe6,           /* 11100110 */
+    0xf6,           /* 11110110 */
+    0xde,           /* 11011110 */
+    0xce,           /* 11001110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 79 0x4f 'O'
+    */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 80 0x50 'P'
+    */
+    0xfc,           /* 11111100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x7c,           /* 01111100 */
+    0x60,           /* 01100000 */
+    0x60,           /* 01100000 */
+    0xf0,           /* 11110000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 81 0x51 'Q'
+    */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xce,           /* 11001110 */
+    0x7c,           /* 01111100 */
+    0x0e,           /* 00001110 */
+
+    /*
+    * 82 0x52 'R'
+    */
+    0xfc,           /* 11111100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x7c,           /* 01111100 */
+    0x6c,           /* 01101100 */
+    0x66,           /* 01100110 */
+    0xe6,           /* 11100110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 83 0x53 'S'
+    */
+    0x3c,           /* 00111100 */
+    0x66,           /* 01100110 */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 84 0x54 'T'
+    */
+    0x7e,           /* 01111110 */
+    0x7e,           /* 01111110 */
+    0x5a,           /* 01011010 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 85 0x55 'U'
+    */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 86 0x56 'V'
+    */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x6c,           /* 01101100 */
+    0x38,           /* 00111000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 87 0x57 'W'
+    */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xd6,           /* 11010110 */
+    0xd6,           /* 11010110 */
+    0xfe,           /* 11111110 */
+    0x6c,           /* 01101100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 88 0x58 'X'
+    */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x6c,           /* 01101100 */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 89 0x59 'Y'
+    */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 90 0x5a 'Z'
+    */
+    0xfe,           /* 11111110 */
+    0xc6,           /* 11000110 */
+    0x8c,           /* 10001100 */
+    0x18,           /* 00011000 */
+    0x32,           /* 00110010 */
+    0x66,           /* 01100110 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 91 0x5b '['
+    */
+    0x3c,           /* 00111100 */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 92 0x5c '\'
+    */
+    0xc0,           /* 11000000 */
+    0x60,           /* 01100000 */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0x06,           /* 00000110 */
+    0x02,           /* 00000010 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 93 0x5d ']'
+    */
+    0x3c,           /* 00111100 */
+    0x0c,           /* 00001100 */
+    0x0c,           /* 00001100 */
+    0x0c,           /* 00001100 */
+    0x0c,           /* 00001100 */
+    0x0c,           /* 00001100 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 94 0x5e '^'
+    */
+    0x10,           /* 00010000 */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 95 0x5f '_'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+
+    /*
+    * 96 0x60 '`'
+    */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 97 0x61 'a'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x78,           /* 01111000 */
+    0x0c,           /* 00001100 */
+    0x7c,           /* 01111100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 98 0x62 'b'
+    */
+    0xe0,           /* 11100000 */
+    0x60,           /* 01100000 */
+    0x7c,           /* 01111100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0xdc,           /* 11011100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 99 0x63 'c'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc0,           /* 11000000 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 100 0x64 'd'
+    */
+    0x1c,           /* 00011100 */
+    0x0c,           /* 00001100 */
+    0x7c,           /* 01111100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 101 0x65 'e'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0xc0,           /* 11000000 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 102 0x66 'f'
+    */
+    0x3c,           /* 00111100 */
+    0x66,           /* 01100110 */
+    0x60,           /* 01100000 */
+    0xf8,           /* 11111000 */
+    0x60,           /* 01100000 */
+    0x60,           /* 01100000 */
+    0xf0,           /* 11110000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 103 0x67 'g'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x76,           /* 01110110 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0x7c,           /* 01111100 */
+    0x0c,           /* 00001100 */
+    0xf8,           /* 11111000 */
+
+    /*
+    * 104 0x68 'h'
+    */
+    0xe0,           /* 11100000 */
+    0x60,           /* 01100000 */
+    0x6c,           /* 01101100 */
+    0x76,           /* 01110110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0xe6,           /* 11100110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 105 0x69 'i'
+    */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x38,           /* 00111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 106 0x6a 'j'
+    */
+    0x06,           /* 00000110 */
+    0x00,           /* 00000000 */
+    0x06,           /* 00000110 */
+    0x06,           /* 00000110 */
+    0x06,           /* 00000110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+
+    /*
+    * 107 0x6b 'k'
+    */
+    0xe0,           /* 11100000 */
+    0x60,           /* 01100000 */
+    0x66,           /* 01100110 */
+    0x6c,           /* 01101100 */
+    0x78,           /* 01111000 */
+    0x6c,           /* 01101100 */
+    0xe6,           /* 11100110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 108 0x6c 'l'
+    */
+    0x38,           /* 00111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 109 0x6d 'm'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xec,           /* 11101100 */
+    0xfe,           /* 11111110 */
+    0xd6,           /* 11010110 */
+    0xd6,           /* 11010110 */
+    0xd6,           /* 11010110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 110 0x6e 'n'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xdc,           /* 11011100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 111 0x6f 'o'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 112 0x70 'p'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xdc,           /* 11011100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x7c,           /* 01111100 */
+    0x60,           /* 01100000 */
+    0xf0,           /* 11110000 */
+
+    /*
+    * 113 0x71 'q'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x76,           /* 01110110 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0x7c,           /* 01111100 */
+    0x0c,           /* 00001100 */
+    0x1e,           /* 00011110 */
+
+    /*
+    * 114 0x72 'r'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xdc,           /* 11011100 */
+    0x76,           /* 01110110 */
+    0x60,           /* 01100000 */
+    0x60,           /* 01100000 */
+    0xf0,           /* 11110000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 115 0x73 's'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0xc0,           /* 11000000 */
+    0x7c,           /* 01111100 */
+    0x06,           /* 00000110 */
+    0xfc,           /* 11111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 116 0x74 't'
+    */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0xfc,           /* 11111100 */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x36,           /* 00110110 */
+    0x1c,           /* 00011100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 117 0x75 'u'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 118 0x76 'v'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x6c,           /* 01101100 */
+    0x38,           /* 00111000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 119 0x77 'w'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xc6,           /* 11000110 */
+    0xd6,           /* 11010110 */
+    0xd6,           /* 11010110 */
+    0xfe,           /* 11111110 */
+    0x6c,           /* 01101100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 120 0x78 'x'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xc6,           /* 11000110 */
+    0x6c,           /* 01101100 */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 121 0x79 'y'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7e,           /* 01111110 */
+    0x06,           /* 00000110 */
+    0xfc,           /* 11111100 */
+
+    /*
+    * 122 0x7a 'z'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x4c,           /* 01001100 */
+    0x18,           /* 00011000 */
+    0x32,           /* 00110010 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 123 0x7b '{'
+    */
+    0x0e,           /* 00001110 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x70,           /* 01110000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x0e,           /* 00001110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 124 0x7c '|'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 125 0x7d '}'
+    */
+    0x70,           /* 01110000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x0e,           /* 00001110 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x70,           /* 01110000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 126 0x7e '~'
+    */
+    0x76,           /* 01110110 */
+    0xdc,           /* 11011100 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 127 0x7f ''
+    */
+    0x00,           /* 00000000 */
+    0x10,           /* 00010000 */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 128 0x80 '€'
+    */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x0c,           /* 00001100 */
+    0x78,           /* 01111000 */
+
+    /*
+    * 129 0x81 '�'
+    */
+    0xcc,           /* 11001100 */
+    0x00,           /* 00000000 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 130 0x82 '‚'
+    */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0xc0,           /* 11000000 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 131 0x83 'ƒ'
+    */
+    0x7c,           /* 01111100 */
+    0x82,           /* 10000010 */
+    0x78,           /* 01111000 */
+    0x0c,           /* 00001100 */
+    0x7c,           /* 01111100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 132 0x84 '„'
+    */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+    0x78,           /* 01111000 */
+    0x0c,           /* 00001100 */
+    0x7c,           /* 01111100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 133 0x85 '…'
+    */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x78,           /* 01111000 */
+    0x0c,           /* 00001100 */
+    0x7c,           /* 01111100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 134 0x86 '†'
+    */
+    0x30,           /* 00110000 */
+    0x30,           /* 00110000 */
+    0x78,           /* 01111000 */
+    0x0c,           /* 00001100 */
+    0x7c,           /* 01111100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 135 0x87 '‡'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0x7e,           /* 01111110 */
+    0x0c,           /* 00001100 */
+    0x38,           /* 00111000 */
+
+    /*
+    * 136 0x88 'ˆ'
+    */
+    0x7c,           /* 01111100 */
+    0x82,           /* 10000010 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0xc0,           /* 11000000 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 137 0x89 '‰'
+    */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0xc0,           /* 11000000 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 138 0x8a 'Š'
+    */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0xc0,           /* 11000000 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 139 0x8b '‹'
+    */
+    0x66,           /* 01100110 */
+    0x00,           /* 00000000 */
+    0x38,           /* 00111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 140 0x8c 'Œ'
+    */
+    0x7c,           /* 01111100 */
+    0x82,           /* 10000010 */
+    0x38,           /* 00111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 141 0x8d '�'
+    */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x38,           /* 00111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 142 0x8e 'Ž'
+    */
+    0xc6,           /* 11000110 */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 143 0x8f '�'
+    */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 144 0x90 '�'
+    */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0xfe,           /* 11111110 */
+    0xc0,           /* 11000000 */
+    0xf8,           /* 11111000 */
+    0xc0,           /* 11000000 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 145 0x91 '‘'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+    0xd8,           /* 11011000 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 146 0x92 '’'
+    */
+    0x3e,           /* 00111110 */
+    0x6c,           /* 01101100 */
+    0xcc,           /* 11001100 */
+    0xfe,           /* 11111110 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xce,           /* 11001110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 147 0x93 '“'
+    */
+    0x7c,           /* 01111100 */
+    0x82,           /* 10000010 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 148 0x94 '”'
+    */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 149 0x95 '•'
+    */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 150 0x96 '–'
+    */
+    0x78,           /* 01111000 */
+    0x84,           /* 10000100 */
+    0x00,           /* 00000000 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 151 0x97 '—'
+    */
+    0x60,           /* 01100000 */
+    0x30,           /* 00110000 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 152 0x98 '˜'
+    */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7e,           /* 01111110 */
+    0x06,           /* 00000110 */
+    0xfc,           /* 11111100 */
+
+    /*
+    * 153 0x99 '™'
+    */
+    0xc6,           /* 11000110 */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x6c,           /* 01101100 */
+    0x38,           /* 00111000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 154 0x9a 'š'
+    */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 155 0x9b '›'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 156 0x9c 'œ'
+    */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0x64,           /* 01100100 */
+    0xf0,           /* 11110000 */
+    0x60,           /* 01100000 */
+    0x66,           /* 01100110 */
+    0xfc,           /* 11111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 157 0x9d '�'
+    */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 158 0x9e 'ž'
+    */
+    0xf8,           /* 11111000 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xfa,           /* 11111010 */
+    0xc6,           /* 11000110 */
+    0xcf,           /* 11001111 */
+    0xc6,           /* 11000110 */
+    0xc7,           /* 11000111 */
+
+    /*
+    * 159 0x9f 'Ÿ'
+    */
+    0x0e,           /* 00001110 */
+    0x1b,           /* 00011011 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0xd8,           /* 11011000 */
+    0x70,           /* 01110000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 160 0xa0 ' '
+    */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x78,           /* 01111000 */
+    0x0c,           /* 00001100 */
+    0x7c,           /* 01111100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 161 0xa1 '¡'
+    */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x38,           /* 00111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 162 0xa2 '¢'
+    */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 163 0xa3 '£'
+    */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 164 0xa4 '¤'
+    */
+    0x76,           /* 01110110 */
+    0xdc,           /* 11011100 */
+    0x00,           /* 00000000 */
+    0xdc,           /* 11011100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 165 0xa5 '¥'
+    */
+    0x76,           /* 01110110 */
+    0xdc,           /* 11011100 */
+    0x00,           /* 00000000 */
+    0xe6,           /* 11100110 */
+    0xf6,           /* 11110110 */
+    0xde,           /* 11011110 */
+    0xce,           /* 11001110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 166 0xa6 '¦'
+    */
+    0x3c,           /* 00111100 */
+    0x6c,           /* 01101100 */
+    0x6c,           /* 01101100 */
+    0x3e,           /* 00111110 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 167 0xa7 '§'
+    */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0x6c,           /* 01101100 */
+    0x38,           /* 00111000 */
+    0x00,           /* 00000000 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 168 0xa8 '¨'
+    */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x63,           /* 01100011 */
+    0x3e,           /* 00111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 169 0xa9 '©'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xfe,           /* 11111110 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 170 0xaa 'ª'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xfe,           /* 11111110 */
+    0x06,           /* 00000110 */
+    0x06,           /* 00000110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 171 0xab '«'
+    */
+    0x63,           /* 01100011 */
+    0xe6,           /* 11100110 */
+    0x6c,           /* 01101100 */
+    0x7e,           /* 01111110 */
+    0x33,           /* 00110011 */
+    0x66,           /* 01100110 */
+    0xcc,           /* 11001100 */
+    0x0f,           /* 00001111 */
+
+    /*
+    * 172 0xac '¬'
+    */
+    0x63,           /* 01100011 */
+    0xe6,           /* 11100110 */
+    0x6c,           /* 01101100 */
+    0x7a,           /* 01111010 */
+    0x36,           /* 00110110 */
+    0x6a,           /* 01101010 */
+    0xdf,           /* 11011111 */
+    0x06,           /* 00000110 */
+
+    /*
+    * 173 0xad '­'
+    */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 174 0xae '®'
+    */
+    0x00,           /* 00000000 */
+    0x33,           /* 00110011 */
+    0x66,           /* 01100110 */
+    0xcc,           /* 11001100 */
+    0x66,           /* 01100110 */
+    0x33,           /* 00110011 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 175 0xaf '¯'
+    */
+    0x00,           /* 00000000 */
+    0xcc,           /* 11001100 */
+    0x66,           /* 01100110 */
+    0x33,           /* 00110011 */
+    0x66,           /* 01100110 */
+    0xcc,           /* 11001100 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 176 0xb0 '°'
+    */
+    0x22,           /* 00100010 */
+    0x88,           /* 10001000 */
+    0x22,           /* 00100010 */
+    0x88,           /* 10001000 */
+    0x22,           /* 00100010 */
+    0x88,           /* 10001000 */
+    0x22,           /* 00100010 */
+    0x88,           /* 10001000 */
+
+    /*
+    * 177 0xb1 '±'
+    */
+    0x55,           /* 01010101 */
+    0xaa,           /* 10101010 */
+    0x55,           /* 01010101 */
+    0xaa,           /* 10101010 */
+    0x55,           /* 01010101 */
+    0xaa,           /* 10101010 */
+    0x55,           /* 01010101 */
+    0xaa,           /* 10101010 */
+
+    /*
+    * 178 0xb2 '²'
+    */
+    0x77,           /* 01110111 */
+    0xdd,           /* 11011101 */
+    0x77,           /* 01110111 */
+    0xdd,           /* 11011101 */
+    0x77,           /* 01110111 */
+    0xdd,           /* 11011101 */
+    0x77,           /* 01110111 */
+    0xdd,           /* 11011101 */
+
+    /*
+    * 179 0xb3 '³'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 180 0xb4 '´'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0xf8,           /* 11111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 181 0xb5 'µ'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0xf8,           /* 11111000 */
+    0x18,           /* 00011000 */
+    0xf8,           /* 11111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 182 0xb6 '¶'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0xf6,           /* 11110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 183 0xb7 '·'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xfe,           /* 11111110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 184 0xb8 '¸'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xf8,           /* 11111000 */
+    0x18,           /* 00011000 */
+    0xf8,           /* 11111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 185 0xb9 '¹'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0xf6,           /* 11110110 */
+    0x06,           /* 00000110 */
+    0xf6,           /* 11110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 186 0xba 'º'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 187 0xbb '»'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xfe,           /* 11111110 */
+    0x06,           /* 00000110 */
+    0xf6,           /* 11110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 188 0xbc '¼'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0xf6,           /* 11110110 */
+    0x06,           /* 00000110 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 189 0xbd '½'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 190 0xbe '¾'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0xf8,           /* 11111000 */
+    0x18,           /* 00011000 */
+    0xf8,           /* 11111000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 191 0xbf '¿'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xf8,           /* 11111000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 192 0xc0 'À'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x1f,           /* 00011111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 193 0xc1 'Á'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 194 0xc2 'Â'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 195 0xc3 'Ã'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x1f,           /* 00011111 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 196 0xc4 'Ä'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 197 0xc5 'Å'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0xff,           /* 11111111 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 198 0xc6 'Æ'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x1f,           /* 00011111 */
+    0x18,           /* 00011000 */
+    0x1f,           /* 00011111 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 199 0xc7 'Ç'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x37,           /* 00110111 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 200 0xc8 'È'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x37,           /* 00110111 */
+    0x30,           /* 00110000 */
+    0x3f,           /* 00111111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 201 0xc9 'É'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x3f,           /* 00111111 */
+    0x30,           /* 00110000 */
+    0x37,           /* 00110111 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 202 0xca 'Ê'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0xf7,           /* 11110111 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 203 0xcb 'Ë'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0xf7,           /* 11110111 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 204 0xcc 'Ì'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x37,           /* 00110111 */
+    0x30,           /* 00110000 */
+    0x37,           /* 00110111 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 205 0xcd 'Í'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 206 0xce 'Î'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0xf7,           /* 11110111 */
+    0x00,           /* 00000000 */
+    0xf7,           /* 11110111 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 207 0xcf 'Ï'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 208 0xd0 'Ð'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 209 0xd1 'Ñ'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 210 0xd2 'Ò'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 211 0xd3 'Ó'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x3f,           /* 00111111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 212 0xd4 'Ô'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x1f,           /* 00011111 */
+    0x18,           /* 00011000 */
+    0x1f,           /* 00011111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 213 0xd5 'Õ'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x1f,           /* 00011111 */
+    0x18,           /* 00011000 */
+    0x1f,           /* 00011111 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 214 0xd6 'Ö'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x3f,           /* 00111111 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 215 0xd7 '×'
+    */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0xff,           /* 11111111 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+
+    /*
+    * 216 0xd8 'Ø'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0xff,           /* 11111111 */
+    0x18,           /* 00011000 */
+    0xff,           /* 11111111 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 217 0xd9 'Ù'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0xf8,           /* 11111000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 218 0xda 'Ú'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x1f,           /* 00011111 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 219 0xdb 'Û'
+    */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+
+    /*
+    * 220 0xdc 'Ü'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+
+    /*
+    * 221 0xdd 'Ý'
+    */
+    0xf0,           /* 11110000 */
+    0xf0,           /* 11110000 */
+    0xf0,           /* 11110000 */
+    0xf0,           /* 11110000 */
+    0xf0,           /* 11110000 */
+    0xf0,           /* 11110000 */
+    0xf0,           /* 11110000 */
+    0xf0,           /* 11110000 */
+
+    /*
+    * 222 0xde 'Þ'
+    */
+    0x0f,           /* 00001111 */
+    0x0f,           /* 00001111 */
+    0x0f,           /* 00001111 */
+    0x0f,           /* 00001111 */
+    0x0f,           /* 00001111 */
+    0x0f,           /* 00001111 */
+    0x0f,           /* 00001111 */
+    0x0f,           /* 00001111 */
+
+    /*
+    * 223 0xdf 'ß'
+    */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0xff,           /* 11111111 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 224 0xe0 'à'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x76,           /* 01110110 */
+    0xdc,           /* 11011100 */
+    0xc8,           /* 11001000 */
+    0xdc,           /* 11011100 */
+    0x76,           /* 01110110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 225 0xe1 'á'
+    */
+    0x78,           /* 01111000 */
+    0xcc,           /* 11001100 */
+    0xcc,           /* 11001100 */
+    0xd8,           /* 11011000 */
+    0xcc,           /* 11001100 */
+    0xc6,           /* 11000110 */
+    0xcc,           /* 11001100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 226 0xe2 'â'
+    */
+    0xfe,           /* 11111110 */
+    0xc6,           /* 11000110 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0xc0,           /* 11000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 227 0xe3 'ã'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0xfe,           /* 11111110 */
+    0x6c,           /* 01101100 */
+    0x6c,           /* 01101100 */
+    0x6c,           /* 01101100 */
+    0x6c,           /* 01101100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 228 0xe4 'ä'
+    */
+    0xfe,           /* 11111110 */
+    0xc6,           /* 11000110 */
+    0x60,           /* 01100000 */
+    0x30,           /* 00110000 */
+    0x60,           /* 01100000 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 229 0xe5 'å'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0xd8,           /* 11011000 */
+    0xd8,           /* 11011000 */
+    0xd8,           /* 11011000 */
+    0x70,           /* 01110000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 230 0xe6 'æ'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x7c,           /* 01111100 */
+    0xc0,           /* 11000000 */
+
+    /*
+    * 231 0xe7 'ç'
+    */
+    0x00,           /* 00000000 */
+    0x76,           /* 01110110 */
+    0xdc,           /* 11011100 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 232 0xe8 'è'
+    */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+    0x3c,           /* 00111100 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+
+    /*
+    * 233 0xe9 'é'
+    */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0xc6,           /* 11000110 */
+    0xfe,           /* 11111110 */
+    0xc6,           /* 11000110 */
+    0x6c,           /* 01101100 */
+    0x38,           /* 00111000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 234 0xea 'ê'
+    */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x6c,           /* 01101100 */
+    0x6c,           /* 01101100 */
+    0xee,           /* 11101110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 235 0xeb 'ë'
+    */
+    0x0e,           /* 00001110 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0x3e,           /* 00111110 */
+    0x66,           /* 01100110 */
+    0x66,           /* 01100110 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 236 0xec 'ì'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0xdb,           /* 11011011 */
+    0xdb,           /* 11011011 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 237 0xed 'í'
+    */
+    0x06,           /* 00000110 */
+    0x0c,           /* 00001100 */
+    0x7e,           /* 01111110 */
+    0xdb,           /* 11011011 */
+    0xdb,           /* 11011011 */
+    0x7e,           /* 01111110 */
+    0x60,           /* 01100000 */
+    0xc0,           /* 11000000 */
+
+    /*
+    * 238 0xee 'î'
+    */
+    0x1e,           /* 00011110 */
+    0x30,           /* 00110000 */
+    0x60,           /* 01100000 */
+    0x7e,           /* 01111110 */
+    0x60,           /* 01100000 */
+    0x30,           /* 00110000 */
+    0x1e,           /* 00011110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 239 0xef 'ï'
+    */
+    0x00,           /* 00000000 */
+    0x7c,           /* 01111100 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0xc6,           /* 11000110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 240 0xf0 'ð'
+    */
+    0x00,           /* 00000000 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+    0xfe,           /* 11111110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 241 0xf1 'ñ'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x7e,           /* 01111110 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 242 0xf2 'ò'
+    */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 243 0xf3 'ó'
+    */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x18,           /* 00011000 */
+    0x0c,           /* 00001100 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 244 0xf4 'ô'
+    */
+    0x0e,           /* 00001110 */
+    0x1b,           /* 00011011 */
+    0x1b,           /* 00011011 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+
+    /*
+    * 245 0xf5 'õ'
+    */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0xd8,           /* 11011000 */
+    0xd8,           /* 11011000 */
+    0x70,           /* 01110000 */
+
+    /*
+    * 246 0xf6 'ö'
+    */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x7e,           /* 01111110 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 247 0xf7 '÷'
+    */
+    0x00,           /* 00000000 */
+    0x76,           /* 01110110 */
+    0xdc,           /* 11011100 */
+    0x00,           /* 00000000 */
+    0x76,           /* 01110110 */
+    0xdc,           /* 11011100 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 248 0xf8 'ø'
+    */
+    0x38,           /* 00111000 */
+    0x6c,           /* 01101100 */
+    0x6c,           /* 01101100 */
+    0x38,           /* 00111000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 249 0xf9 'ù'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 250 0xfa 'ú'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x18,           /* 00011000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 251 0xfb 'û'
+    */
+    0x0f,           /* 00001111 */
+    0x0c,           /* 00001100 */
+    0x0c,           /* 00001100 */
+    0x0c,           /* 00001100 */
+    0xec,           /* 11101100 */
+    0x6c,           /* 01101100 */
+    0x3c,           /* 00111100 */
+    0x1c,           /* 00011100 */
+
+    /*
+    * 252 0xfc 'ü'
+    */
+    0x6c,           /* 01101100 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x36,           /* 00110110 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 253 0xfd 'ý'
+    */
+    0x78,           /* 01111000 */
+    0x0c,           /* 00001100 */
+    0x18,           /* 00011000 */
+    0x30,           /* 00110000 */
+    0x7c,           /* 01111100 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 254 0xfe 'þ'
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x3c,           /* 00111100 */
+    0x3c,           /* 00111100 */
+    0x3c,           /* 00111100 */
+    0x3c,           /* 00111100 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+    /*
+    * 255 0xff ' '
+    */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+    0x00,           /* 00000000 */
+
+};
+
+
+/* ---- Character */
+
+/*!
+\brief Global cache for 8x8 pixel font textures created at runtime.
+*/
+static SDL_Texture *SDLTest_CharTextureCache[256];
+
+int SDLTest_DrawCharacter(SDL_Renderer *renderer, int x, int y, char c)
+{
+    const Uint32 charWidth = 8;
+    const Uint32 charHeight = 8;
+    const Uint32 charSize = 8;
+    SDL_Rect srect;
+    SDL_Rect drect;
+    int result;
+    Uint32 ix, iy;
+    const unsigned char *charpos;
+    Uint8 *curpos;
+    Uint8 patt, mask;
+    Uint8 *linepos;
+    Uint32 pitch;
+    SDL_Surface *character;
+    Uint32 ci;
+    Uint8 r, g, b, a;
+
+    /*
+    * Setup source rectangle
+    */
+    srect.x = 0;
+    srect.y = 0;
+    srect.w = charWidth;
+    srect.h = charHeight;
+
+    /*
+    * Setup destination rectangle
+    */
+    drect.x = x;
+    drect.y = y;
+    drect.w = charWidth;
+    drect.h = charHeight;
+
+    /* Character index in cache */
+    ci = (unsigned char)c;
+
+    /*
+    * Create new charWidth x charHeight bitmap surface if not already present.
+    */
+    if (SDLTest_CharTextureCache[ci] == NULL) {
+        /*
+        * Redraw character into surface
+        */
+        character = SDL_CreateRGBSurface(SDL_SWSURFACE,
+            charWidth, charHeight, 32,
+            0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
+        if (character == NULL) {
+            return (-1);
+        }
+
+        charpos = SDLTest_FontData + ci * charSize;
+        linepos = (Uint8 *)character->pixels;
+        pitch = character->pitch;
+
+        /*
+        * Drawing loop
+        */
+        patt = 0;
+        for (iy = 0; iy < charWidth; iy++) {
+            mask = 0x00;
+            curpos = linepos;
+            for (ix = 0; ix < charWidth; ix++) {
+                if (!(mask >>= 1)) {
+                    patt = *charpos++;
+                    mask = 0x80;
+                }
+                if (patt & mask) {
+                    *(Uint32 *)curpos = 0xffffffff;
+                } else {
+                    *(Uint32 *)curpos = 0;
+                }
+                curpos += 4;
+            }
+            linepos += pitch;
+        }
+
+        /* Convert temp surface into texture */
+        SDLTest_CharTextureCache[ci] = SDL_CreateTextureFromSurface(renderer, character);
+        SDL_FreeSurface(character);
+
+        /*
+        * Check pointer
+        */
+        if (SDLTest_CharTextureCache[ci] == NULL) {
+            return (-1);
+        }
+    }
+
+    /*
+    * Set color
+    */
+    result = 0;
+    result |= SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a);
+    result |= SDL_SetTextureColorMod(SDLTest_CharTextureCache[ci], r, g, b);
+    result |= SDL_SetTextureAlphaMod(SDLTest_CharTextureCache[ci], a);
+
+    /*
+    * Draw texture onto destination
+    */
+    result |= SDL_RenderCopy(renderer, SDLTest_CharTextureCache[ci], &srect, &drect);
+
+    return (result);
+}
+
+int SDLTest_DrawString(SDL_Renderer * renderer, int x, int y, const char *s)
+{
+    const Uint32 charWidth = 8;
+    int result = 0;
+    int curx = x;
+    int cury = y;
+    const char *curchar = s;
+
+    while (*curchar && !result) {
+        result |= SDLTest_DrawCharacter(renderer, curx, cury, *curchar);
+        curx += charWidth;
+        curchar++;
+    }
+
+    return (result);
+}
+

+ 524 - 0
Source/ThirdParty/SDL/src/test/SDL_test_fuzzer.c

@@ -0,0 +1,524 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+
+  Data generators for fuzzing test data in a reproducible way.
+
+*/
+
+#include "SDL_config.h"
+
+/* Visual Studio 2008 doesn't have stdint.h */
+#if defined(_MSC_VER) && _MSC_VER <= 1500
+#define UINT8_MAX   ~(Uint8)0
+#define UINT16_MAX  ~(Uint16)0
+#define UINT32_MAX  ~(Uint32)0
+#define UINT64_MAX  ~(Uint64)0
+#else
+#include <stdint.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <float.h>
+
+#include "SDL_test.h"
+
+/**
+ * Counter for fuzzer invocations
+ */
+static int fuzzerInvocationCounter = 0;
+
+/**
+ * Context for shared random number generator
+ */
+static SDLTest_RandomContext rndContext;
+
+/*
+ * Note: doxygen documentation markup for functions is in the header file.
+ */
+
+void
+SDLTest_FuzzerInit(Uint64 execKey)
+{
+    Uint32 a = (execKey >> 32) & 0x00000000FFFFFFFF;
+    Uint32 b = execKey & 0x00000000FFFFFFFF;
+    SDL_memset((void *)&rndContext, 0, sizeof(SDLTest_RandomContext));
+    SDLTest_RandomInit(&rndContext, a, b);
+    fuzzerInvocationCounter = 0;
+}
+
+int
+SDLTest_GetFuzzerInvocationCount()
+{
+    return fuzzerInvocationCounter;
+}
+
+Uint8
+SDLTest_RandomUint8()
+{
+    fuzzerInvocationCounter++;
+
+    return (Uint8) SDLTest_RandomInt(&rndContext) & 0x000000FF;
+}
+
+Sint8
+SDLTest_RandomSint8()
+{
+    fuzzerInvocationCounter++;
+
+    return (Sint8) SDLTest_RandomInt(&rndContext) & 0x000000FF;
+}
+
+Uint16
+SDLTest_RandomUint16()
+{
+    fuzzerInvocationCounter++;
+
+    return (Uint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
+}
+
+Sint16
+SDLTest_RandomSint16()
+{
+    fuzzerInvocationCounter++;
+
+    return (Sint16) SDLTest_RandomInt(&rndContext) & 0x0000FFFF;
+}
+
+Sint32
+SDLTest_RandomSint32()
+{
+    fuzzerInvocationCounter++;
+
+    return (Sint32) SDLTest_RandomInt(&rndContext);
+}
+
+Uint32
+SDLTest_RandomUint32()
+{
+    fuzzerInvocationCounter++;
+
+    return (Uint32) SDLTest_RandomInt(&rndContext);
+}
+
+Uint64
+SDLTest_RandomUint64()
+{
+    Uint64 value = 0;
+    Uint32 *vp = (void *)&value;
+
+    fuzzerInvocationCounter++;
+
+    vp[0] = SDLTest_RandomSint32();
+    vp[1] = SDLTest_RandomSint32();
+
+    return value;
+}
+
+Sint64
+SDLTest_RandomSint64()
+{
+    Uint64 value = 0;
+    Uint32 *vp = (void *)&value;
+
+    fuzzerInvocationCounter++;
+
+    vp[0] = SDLTest_RandomSint32();
+    vp[1] = SDLTest_RandomSint32();
+
+    return value;
+}
+
+
+
+Sint32
+SDLTest_RandomIntegerInRange(Sint32 pMin, Sint32 pMax)
+{
+    Sint64 min = pMin;
+    Sint64 max = pMax;
+    Sint64 temp;
+    Sint64 number;
+
+    if(pMin > pMax) {
+        temp = min;
+        min = max;
+        max = temp;
+    } else if(pMin == pMax) {
+        return (Sint32)min;
+    }
+
+    number = SDLTest_RandomUint32();
+    /* invocation count increment in preceeding call */
+
+    return (Sint32)((number % ((max + 1) - min)) + min);
+}
+
+/*!
+ * Generates a unsigned boundary value between the given boundaries.
+ * Boundary values are inclusive. See the examples below.
+ * If boundary2 < boundary1, the values are swapped.
+ * If boundary1 == boundary2, value of boundary1 will be returned
+ *
+ * Generating boundary values for Uint8:
+ * BoundaryValues(UINT8_MAX, 10, 20, True) -> [10,11,19,20]
+ * BoundaryValues(UINT8_MAX, 10, 20, False) -> [9,21]
+ * BoundaryValues(UINT8_MAX, 0, 15, True) -> [0, 1, 14, 15]
+ * BoundaryValues(UINT8_MAX, 0, 15, False) -> [16]
+ * BoundaryValues(UINT8_MAX, 0, 0xFF, False) -> [0], error set
+ *
+ * Generator works the same for other types of unsigned integers.
+ *
+ * \param maxValue The biggest value that is acceptable for this data type.
+ *                  For instance, for Uint8 -> 255, Uint16 -> 65536 etc.
+ * \param boundary1 defines lower boundary
+ * \param boundary2 defines upper boundary
+ * \param validDomain Generate only for valid domain (for the data type)
+ *
+ * \returns Returns a random boundary value for the domain or 0 in case of error
+ */
+Uint64
+SDLTest_GenerateUnsignedBoundaryValues(const Uint64 maxValue, Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain)
+{
+        Uint64 b1, b2;
+    Uint64 delta;
+    Uint64 tempBuf[4];
+    Uint8 index;
+
+        /* Maybe swap */
+    if (boundary1 > boundary2) {
+        b1 = boundary2;
+        b2 = boundary1;
+    } else {
+        b1 = boundary1;
+        b2 = boundary2;
+        }
+
+    index = 0;
+    if (validDomain == SDL_TRUE) {
+            if (b1 == b2) {
+                return b1;
+            }
+
+            /* Generate up to 4 values within bounds */
+            delta = b2 - b1;
+            if (delta < 4) {
+                do {
+                tempBuf[index] = b1 + index;
+                index++;
+                    } while (index < delta);
+            } else {
+          tempBuf[index] = b1;
+          index++;
+          tempBuf[index] = b1 + 1;
+          index++;
+          tempBuf[index] = b2 - 1;
+          index++;
+          tempBuf[index] = b2;
+          index++;
+            }
+        } else {
+            /* Generate up to 2 values outside of bounds */
+        if (b1 > 0) {
+            tempBuf[index] = b1 - 1;
+            index++;
+        }
+
+        if (b2 < maxValue) {
+            tempBuf[index] = b2 + 1;
+            index++;
+        }
+    }
+
+    if (index == 0) {
+        /* There are no valid boundaries */
+        SDL_Unsupported();
+        return 0;
+    }
+
+    return tempBuf[SDLTest_RandomUint8() % index];
+}
+
+
+Uint8
+SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain)
+{
+    /* max value for Uint8 */
+    const Uint64 maxValue = UCHAR_MAX;
+    return (Uint8)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
+                (Uint64) boundary1, (Uint64) boundary2,
+                validDomain);
+}
+
+Uint16
+SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain)
+{
+    /* max value for Uint16 */
+    const Uint64 maxValue = USHRT_MAX;
+    return (Uint16)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
+                (Uint64) boundary1, (Uint64) boundary2,
+                validDomain);
+}
+
+Uint32
+SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain)
+{
+    /* max value for Uint32 */
+    #if ((ULONG_MAX) == (UINT_MAX))
+      const Uint64 maxValue = ULONG_MAX;
+        #else
+      const Uint64 maxValue = UINT_MAX;
+        #endif
+    return (Uint32)SDLTest_GenerateUnsignedBoundaryValues(maxValue,
+                (Uint64) boundary1, (Uint64) boundary2,
+                validDomain);
+}
+
+Uint64
+SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain)
+{
+    /* max value for Uint64 */
+    const Uint64 maxValue = ULLONG_MAX;
+    return SDLTest_GenerateUnsignedBoundaryValues(maxValue,
+                (Uint64) boundary1, (Uint64) boundary2,
+                validDomain);
+}
+
+/*!
+ * Generates a signed boundary value between the given boundaries.
+ * Boundary values are inclusive. See the examples below.
+ * If boundary2 < boundary1, the values are swapped.
+ * If boundary1 == boundary2, value of boundary1 will be returned
+ *
+ * Generating boundary values for Sint8:
+ * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, True) -> [-10,-9,19,20]
+ * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -10, 20, False) -> [-11,21]
+ * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -30, -15, True) -> [-30, -29, -16, -15]
+ * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 15, False) -> [16]
+ * SignedBoundaryValues(SCHAR_MIN, SCHAR_MAX, -127, 127, False) -> [0], error set
+ *
+ * Generator works the same for other types of signed integers.
+ *
+ * \param minValue The smallest value that is acceptable for this data type.
+ *                  For instance, for Uint8 -> -127, etc.
+ * \param maxValue The biggest value that is acceptable for this data type.
+ *                  For instance, for Uint8 -> 127, etc.
+ * \param boundary1 defines lower boundary
+ * \param boundary2 defines upper boundary
+ * \param validDomain Generate only for valid domain (for the data type)
+ *
+ * \returns Returns a random boundary value for the domain or 0 in case of error
+ */
+Sint64
+SDLTest_GenerateSignedBoundaryValues(const Sint64 minValue, const Sint64 maxValue, Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
+{
+        Sint64 b1, b2;
+    Sint64 delta;
+    Sint64 tempBuf[4];
+    Uint8 index;
+
+        /* Maybe swap */
+    if (boundary1 > boundary2) {
+        b1 = boundary2;
+        b2 = boundary1;
+    } else {
+        b1 = boundary1;
+        b2 = boundary2;
+        }
+
+    index = 0;
+    if (validDomain == SDL_TRUE) {
+            if (b1 == b2) {
+                return b1;
+            }
+
+            /* Generate up to 4 values within bounds */
+            delta = b2 - b1;
+            if (delta < 4) {
+                do {
+                tempBuf[index] = b1 + index;
+                index++;
+                    } while (index < delta);
+            } else {
+          tempBuf[index] = b1;
+          index++;
+          tempBuf[index] = b1 + 1;
+          index++;
+          tempBuf[index] = b2 - 1;
+          index++;
+          tempBuf[index] = b2;
+          index++;
+            }
+        } else {
+            /* Generate up to 2 values outside of bounds */
+        if (b1 > minValue) {
+            tempBuf[index] = b1 - 1;
+            index++;
+        }
+
+        if (b2 < maxValue) {
+            tempBuf[index] = b2 + 1;
+            index++;
+        }
+    }
+
+    if (index == 0) {
+        /* There are no valid boundaries */
+        SDL_Unsupported();
+        return minValue;
+    }
+
+    return tempBuf[SDLTest_RandomUint8() % index];
+}
+
+
+Sint8
+SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain)
+{
+    /* min & max values for Sint8 */
+    const Sint64 maxValue = SCHAR_MAX;
+    const Sint64 minValue = SCHAR_MIN;
+    return (Sint8)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
+                (Sint64) boundary1, (Sint64) boundary2,
+                validDomain);
+}
+
+Sint16
+SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain)
+{
+    /* min & max values for Sint16 */
+    const Sint64 maxValue = SHRT_MAX;
+    const Sint64 minValue = SHRT_MIN;
+    return (Sint16)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
+                (Sint64) boundary1, (Sint64) boundary2,
+                validDomain);
+}
+
+Sint32
+SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain)
+{
+    /* min & max values for Sint32 */
+    #if ((ULONG_MAX) == (UINT_MAX))
+      const Sint64 maxValue = LONG_MAX;
+      const Sint64 minValue = LONG_MIN;
+        #else
+      const Sint64 maxValue = INT_MAX;
+      const Sint64 minValue = INT_MIN;
+        #endif
+    return (Sint32)SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
+                (Sint64) boundary1, (Sint64) boundary2,
+                validDomain);
+}
+
+Sint64
+SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain)
+{
+    /* min & max values for Sint64 */
+    const Sint64 maxValue = LLONG_MAX;
+    const Sint64 minValue = LLONG_MIN;
+    return SDLTest_GenerateSignedBoundaryValues(minValue, maxValue,
+                boundary1, boundary2,
+                validDomain);
+}
+
+float
+SDLTest_RandomUnitFloat()
+{
+    return (float) SDLTest_RandomUint32() / UINT_MAX;
+}
+
+float
+SDLTest_RandomFloat()
+{
+        return (float) (SDLTest_RandomUnitDouble() * (double)2.0 * (double)FLT_MAX - (double)(FLT_MAX));
+}
+
+double
+SDLTest_RandomUnitDouble()
+{
+    return (double) (SDLTest_RandomUint64() >> 11) * (1.0/9007199254740992.0);
+}
+
+double
+SDLTest_RandomDouble()
+{
+    double r = 0.0;
+    double s = 1.0;
+    do {
+      s /= UINT_MAX + 1.0;
+      r += (double)SDLTest_RandomInt(&rndContext) * s;
+    } while (s > DBL_EPSILON);
+
+    fuzzerInvocationCounter++;
+
+    return r;
+}
+
+
+char *
+SDLTest_RandomAsciiString()
+{
+    return SDLTest_RandomAsciiStringWithMaximumLength(255);
+}
+
+char *
+SDLTest_RandomAsciiStringWithMaximumLength(int maxLength)
+{
+    int size;
+
+    if(maxLength < 1) {
+                SDL_InvalidParamError("maxLength");
+        return NULL;
+    }
+
+    size = (SDLTest_RandomUint32() % (maxLength + 1));
+
+    return SDLTest_RandomAsciiStringOfSize(size);
+}
+
+char *
+SDLTest_RandomAsciiStringOfSize(int size)
+{
+    char *string;
+    int counter;
+
+
+    if(size < 1) {
+                SDL_InvalidParamError("size");
+        return NULL;
+    }
+
+    string = (char *)SDL_malloc((size + 1) * sizeof(char));
+    if (string==NULL) {
+      return NULL;
+        }
+
+    for(counter = 0; counter < size; ++counter) {
+        string[counter] = (char)SDLTest_RandomIntegerInRange(32, 126);
+    }
+
+    string[counter] = '\0';
+
+    fuzzerInvocationCounter++;
+
+    return string;
+}

+ 635 - 0
Source/ThirdParty/SDL/src/test/SDL_test_harness.c

@@ -0,0 +1,635 @@
+/*
+Simple DirectMedia Layer
+Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_config.h"
+
+#include "SDL_test.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+/* Invalid test name/description message format */
+const char *SDLTest_InvalidNameFormat = "(Invalid)";
+
+/* Log summary message format */
+const char *SDLTest_LogSummaryFormat = "%s Summary: Total=%d Passed=%d Failed=%d Skipped=%d";
+
+/* Final result message format */
+const char *SDLTest_FinalResultFormat = ">>> %s '%s': %s\n";
+
+/*! \brief Timeout for single test case execution */
+static Uint32 SDLTest_TestCaseTimeout = 3600;
+
+/**
+* Generates a random run seed string for the harness. The generated seed
+* will contain alphanumeric characters (0-9A-Z).
+*
+* Note: The returned string needs to be deallocated by the caller.
+*
+* \param length The length of the seed string to generate
+*
+* \returns The generated seed string
+*/
+char *
+SDLTest_GenerateRunSeed(const int length)
+{
+    char *seed = NULL;
+    SDLTest_RandomContext randomContext;
+    int counter;
+
+    /* Sanity check input */
+    if (length <= 0) {
+        SDLTest_LogError("The length of the harness seed must be >0.");
+        return NULL;
+    }
+
+    /* Allocate output buffer */
+    seed = (char *)SDL_malloc((length + 1) * sizeof(char));
+    if (seed == NULL) {
+        SDLTest_LogError("SDL_malloc for run seed output buffer failed.");
+        return NULL;
+    }
+
+    /* Generate a random string of alphanumeric characters */
+    SDLTest_RandomInitTime(&randomContext);
+    for (counter = 0; counter < length - 1; ++counter) {
+        unsigned int number = SDLTest_Random(&randomContext);
+        char ch = (char) (number % (91 - 48)) + 48;
+        if (ch >= 58 && ch <= 64) {
+            ch = 65;
+        }
+        seed[counter] = ch;
+    }
+    seed[counter] = '\0';
+
+    return seed;
+}
+
+/**
+* Generates an execution key for the fuzzer.
+*
+* \param runSeed        The run seed to use
+* \param suiteName      The name of the test suite
+* \param testName       The name of the test
+* \param iteration      The iteration count
+*
+* \returns The generated execution key to initialize the fuzzer with.
+*
+*/
+Uint64
+SDLTest_GenerateExecKey(char *runSeed, char *suiteName, char *testName, int iteration)
+{
+    SDLTest_Md5Context md5Context;
+    Uint64 *keys;
+    char iterationString[16];
+    Uint32 runSeedLength;
+    Uint32 suiteNameLength;
+    Uint32 testNameLength;
+    Uint32 iterationStringLength;
+    Uint32 entireStringLength;
+    char *buffer;
+
+    if (runSeed == NULL || SDL_strlen(runSeed)==0) {
+        SDLTest_LogError("Invalid runSeed string.");
+        return -1;
+    }
+
+    if (suiteName == NULL || SDL_strlen(suiteName)==0) {
+        SDLTest_LogError("Invalid suiteName string.");
+        return -1;
+    }
+
+    if (testName == NULL || SDL_strlen(testName)==0) {
+        SDLTest_LogError("Invalid testName string.");
+        return -1;
+    }
+
+    if (iteration <= 0) {
+        SDLTest_LogError("Invalid iteration count.");
+        return -1;
+    }
+
+    /* Convert iteration number into a string */
+    SDL_memset(iterationString, 0, sizeof(iterationString));
+    SDL_snprintf(iterationString, sizeof(iterationString) - 1, "%d", iteration);
+
+    /* Combine the parameters into single string */
+    runSeedLength = SDL_strlen(runSeed);
+    suiteNameLength = SDL_strlen(suiteName);
+    testNameLength = SDL_strlen(testName);
+    iterationStringLength = SDL_strlen(iterationString);
+    entireStringLength  = runSeedLength + suiteNameLength + testNameLength + iterationStringLength + 1;
+    buffer = (char *)SDL_malloc(entireStringLength);
+    if (buffer == NULL) {
+        SDLTest_LogError("SDL_malloc failed to allocate buffer for execKey generation.");
+        return 0;
+    }
+    SDL_snprintf(buffer, entireStringLength, "%s%s%s%d", runSeed, suiteName, testName, iteration);
+
+    /* Hash string and use half of the digest as 64bit exec key */
+    SDLTest_Md5Init(&md5Context);
+    SDLTest_Md5Update(&md5Context, (unsigned char *)buffer, entireStringLength);
+    SDLTest_Md5Final(&md5Context);
+    SDL_free(buffer);
+    keys = (Uint64 *)md5Context.digest;
+
+    return keys[0];
+}
+
+/**
+* \brief Set timeout handler for test.
+*
+* Note: SDL_Init(SDL_INIT_TIMER) will be called if it wasn't done so before.
+*
+* \param timeout Timeout interval in seconds.
+* \param callback Function that will be called after timeout has elapsed.
+*
+* \return Timer id or -1 on failure.
+*/
+SDL_TimerID
+SDLTest_SetTestTimeout(int timeout, void (*callback)())
+{
+    Uint32 timeoutInMilliseconds;
+    SDL_TimerID timerID;
+
+    if (callback == NULL) {
+        SDLTest_LogError("Timeout callback can't be NULL");
+        return -1;
+    }
+
+    if (timeout < 0) {
+        SDLTest_LogError("Timeout value must be bigger than zero.");
+        return -1;
+    }
+
+    /* Init SDL timer if not initialized before */
+    if (SDL_WasInit(SDL_INIT_TIMER) == 0) {
+        if (SDL_InitSubSystem(SDL_INIT_TIMER)) {
+            SDLTest_LogError("Failed to init timer subsystem: %s", SDL_GetError());
+            return -1;
+        }
+    }
+
+    /* Set timer */
+    timeoutInMilliseconds = timeout * 1000;
+    timerID = SDL_AddTimer(timeoutInMilliseconds, (SDL_TimerCallback)callback, 0x0);
+    if (timerID == 0) {
+        SDLTest_LogError("Creation of SDL timer failed: %s", SDL_GetError());
+        return -1;
+    }
+
+    return timerID;
+}
+
+/**
+* \brief Timeout handler. Aborts test run and exits harness process.
+*/
+void
+    SDLTest_BailOut()
+{
+    SDLTest_LogError("TestCaseTimeout timer expired. Aborting test run.");
+    exit(TEST_ABORTED); /* bail out from the test */
+}
+
+/**
+* \brief Execute a test using the given execution key.
+*
+* \param testSuite Suite containing the test case.
+* \param testCase Case to execute.
+* \param execKey Execution key for the fuzzer.
+*
+* \returns Test case result.
+*/
+int
+SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, SDLTest_TestCaseReference *testCase, Uint64 execKey)
+{
+    SDL_TimerID timer = 0;
+    int testCaseResult = 0;
+    int testResult = 0;
+    int fuzzerCount;
+
+    if (testSuite==NULL || testCase==NULL || testSuite->name==NULL || testCase->name==NULL)
+    {
+        SDLTest_LogError("Setup failure: testSuite or testCase references NULL");
+        return TEST_RESULT_SETUP_FAILURE;
+    }
+
+    if (!testCase->enabled)
+    {
+        SDLTest_Log((char *)SDLTest_FinalResultFormat, "Test", testCase->name, "Skipped (Disabled)");
+        return TEST_RESULT_SKIPPED;
+    }
+
+
+    /* Initialize fuzzer */
+    SDLTest_FuzzerInit(execKey);
+
+    /* Reset assert tracker */
+    SDLTest_ResetAssertSummary();
+
+    /* Set timeout timer */
+    timer = SDLTest_SetTestTimeout(SDLTest_TestCaseTimeout, SDLTest_BailOut);
+
+    /* Maybe run suite initalizer function */
+    if (testSuite->testSetUp) {
+        testSuite->testSetUp(0x0);
+        if (SDLTest_AssertSummaryToTestResult() == TEST_RESULT_FAILED) {
+            SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Suite Setup", testSuite->name, "Failed");
+            return TEST_RESULT_SETUP_FAILURE;
+        }
+    }
+
+    /* Run test case function */
+    testCaseResult = testCase->testCase(0x0);
+
+    /* Convert test execution result into harness result */
+    if (testCaseResult == TEST_SKIPPED) {
+        /* Test was programatically skipped */
+        testResult = TEST_RESULT_SKIPPED;
+    } else if (testCaseResult == TEST_STARTED) {
+        /* Test did not return a TEST_COMPLETED value; assume it failed */
+        testResult = TEST_RESULT_FAILED;
+    } else if (testCaseResult == TEST_ABORTED) {
+        /* Test was aborted early; assume it failed */
+        testResult = TEST_RESULT_FAILED;
+    } else {
+        /* Perform failure analysis based on asserts */
+        testResult = SDLTest_AssertSummaryToTestResult();
+    }
+
+    /* Maybe run suite cleanup function (ignore failed asserts) */
+    if (testSuite->testTearDown) {
+        testSuite->testTearDown(0x0);
+    }
+
+    /* Cancel timeout timer */
+    if (timer) {
+        SDL_RemoveTimer(timer);
+    }
+
+    /* Report on asserts and fuzzer usage */
+    fuzzerCount = SDLTest_GetFuzzerInvocationCount();
+    if (fuzzerCount > 0) {
+        SDLTest_Log("Fuzzer invocations: %d", fuzzerCount);
+    }
+
+    /* Final log based on test execution result */
+    if (testCaseResult == TEST_SKIPPED) {
+        /* Test was programatically skipped */
+        SDLTest_Log((char *)SDLTest_FinalResultFormat, "Test", testCase->name, "Skipped (Programmatically)");
+    } else if (testCaseResult == TEST_STARTED) {
+        /* Test did not return a TEST_COMPLETED value; assume it failed */
+        SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Test", testCase->name, "Failed (test started, but did not return TEST_COMPLETED)");
+    } else if (testCaseResult == TEST_ABORTED) {
+        /* Test was aborted early; assume it failed */
+        SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Test", testCase->name, "Failed (Aborted)");
+    } else {
+        SDLTest_LogAssertSummary();
+    }
+
+    return testResult;
+}
+
+/* Prints summary of all suites/tests contained in the given reference */
+void SDLTest_LogTestSuiteSummary(SDLTest_TestSuiteReference *testSuites)
+{
+    int suiteCounter;
+    int testCounter;
+    SDLTest_TestSuiteReference *testSuite;
+    SDLTest_TestCaseReference *testCase;
+
+    /* Loop over all suites */
+    suiteCounter = 0;
+    while(&testSuites[suiteCounter]) {
+        testSuite=&testSuites[suiteCounter];
+        suiteCounter++;
+        SDLTest_Log("Test Suite %i - %s\n", suiteCounter,
+            (testSuite->name) ? testSuite->name : SDLTest_InvalidNameFormat);
+
+        /* Loop over all test cases */
+        testCounter = 0;
+        while(testSuite->testCases[testCounter])
+        {
+            testCase=(SDLTest_TestCaseReference *)testSuite->testCases[testCounter];
+            testCounter++;
+            SDLTest_Log("  Test Case %i - %s: %s", testCounter,
+                (testCase->name) ? testCase->name : SDLTest_InvalidNameFormat,
+                (testCase->description) ? testCase->description : SDLTest_InvalidNameFormat);
+        }
+    }
+}
+
+/* Gets a timer value in seconds */
+float GetClock()
+{
+    float currentClock = (float)clock();
+    return currentClock / (float)CLOCKS_PER_SEC;
+}
+
+/**
+* \brief Execute a test suite using the given run seend and execution key.
+*
+* The filter string is matched to the suite name (full comparison) to select a single suite,
+* or if no suite matches, it is matched to the test names (full comparison) to select a single test.
+*
+* \param testSuites Suites containing the test case.
+* \param userRunSeed Custom run seed provided by user, or NULL to autogenerate one.
+* \param userExecKey Custom execution key provided by user, or 0 to autogenerate one.
+* \param filter Filter specification. NULL disables. Case sensitive.
+* \param testIterations Number of iterations to run each test case.
+*
+* \returns Test run result; 0 when all tests passed, 1 if any tests failed.
+*/
+int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *userRunSeed, Uint64 userExecKey, const char *filter, int testIterations)
+{
+    int suiteCounter;
+    int testCounter;
+    int iterationCounter;
+    SDLTest_TestSuiteReference *testSuite;
+    SDLTest_TestCaseReference *testCase;
+    const char *runSeed = NULL;
+    char *currentSuiteName;
+    char *currentTestName;
+    Uint64 execKey;
+    float runStartSeconds;
+    float suiteStartSeconds;
+    float testStartSeconds;
+    float runEndSeconds;
+    float suiteEndSeconds;
+    float testEndSeconds;
+    float runtime;
+    int suiteFilter = 0;
+    char *suiteFilterName = NULL;
+    int testFilter = 0;
+    char *testFilterName = NULL;
+    int testResult = 0;
+    int runResult = 0;
+    Uint32 totalTestFailedCount = 0;
+    Uint32 totalTestPassedCount = 0;
+    Uint32 totalTestSkippedCount = 0;
+    Uint32 testFailedCount = 0;
+    Uint32 testPassedCount = 0;
+    Uint32 testSkippedCount = 0;
+    Uint32 countSum = 0;
+    char *logFormat = (char *)SDLTest_LogSummaryFormat;
+
+    /* Sanitize test iterations */
+    if (testIterations < 1) {
+        testIterations = 1;
+    }
+
+    /* Generate run see if we don't have one already */
+    if (userRunSeed == NULL || SDL_strlen(userRunSeed) == 0) {
+        runSeed = SDLTest_GenerateRunSeed(16);
+        if (runSeed == NULL) {
+            SDLTest_LogError("Generating a random seed failed");
+            return 2;
+        }
+    } else {
+        runSeed = userRunSeed;
+    }
+
+
+    /* Reset per-run counters */
+    totalTestFailedCount = 0;
+    totalTestPassedCount = 0;
+    totalTestSkippedCount = 0;
+
+    /* Take time - run start */
+    runStartSeconds = GetClock();
+
+    /* Log run with fuzzer parameters */
+    SDLTest_Log("::::: Test Run /w seed '%s' started\n", runSeed);
+
+    /* Initialize filtering */
+    if (filter != NULL && SDL_strlen(filter) > 0) {
+        /* Loop over all suites to check if we have a filter match */
+        suiteCounter = 0;
+        while (testSuites[suiteCounter] && suiteFilter == 0) {
+            testSuite=(SDLTest_TestSuiteReference *)testSuites[suiteCounter];
+            suiteCounter++;
+            if (testSuite->name != NULL && SDL_strcmp(filter, testSuite->name) == 0) {
+                /* Matched a suite name */
+                suiteFilter = 1;
+                suiteFilterName = testSuite->name;
+                SDLTest_Log("Filtering: running only suite '%s'", suiteFilterName);
+                break;
+            }
+
+            /* Within each suite, loop over all test cases to check if we have a filter match */
+            testCounter = 0;
+            while (testSuite->testCases[testCounter] && testFilter == 0)
+            {
+                testCase=(SDLTest_TestCaseReference *)testSuite->testCases[testCounter];
+                testCounter++;
+                if (testCase->name != NULL && SDL_strcmp(filter, testCase->name) == 0) {
+                    /* Matched a test name */
+                    suiteFilter = 1;
+                    suiteFilterName = testSuite->name;
+                    testFilter = 1;
+                    testFilterName = testCase->name;
+                    SDLTest_Log("Filtering: running only test '%s' in suite '%s'", testFilterName, suiteFilterName);
+                    break;
+                }
+            }
+        }
+
+        if (suiteFilter == 0 && testFilter == 0) {
+            SDLTest_LogError("Filter '%s' did not match any test suite/case.", filter);
+            SDLTest_Log("Exit code: 2");
+            return 2;
+        }
+    }
+
+    /* Loop over all suites */
+    suiteCounter = 0;
+    while(testSuites[suiteCounter]) {
+        testSuite=(SDLTest_TestSuiteReference *)testSuites[suiteCounter];
+        currentSuiteName = (char *)((testSuite->name) ? testSuite->name : SDLTest_InvalidNameFormat);
+        suiteCounter++;
+
+        /* Filter suite if flag set and we have a name */
+        if (suiteFilter == 1 && suiteFilterName != NULL && testSuite->name != NULL &&
+            SDL_strcmp(suiteFilterName, testSuite->name) != 0) {
+                /* Skip suite */
+                SDLTest_Log("===== Test Suite %i: '%s' skipped\n",
+                    suiteCounter,
+                    currentSuiteName);
+        } else {
+
+            /* Reset per-suite counters */
+            testFailedCount = 0;
+            testPassedCount = 0;
+            testSkippedCount = 0;
+
+            /* Take time - suite start */
+            suiteStartSeconds = GetClock();
+
+            /* Log suite started */
+            SDLTest_Log("===== Test Suite %i: '%s' started\n",
+                suiteCounter,
+                currentSuiteName);
+
+            /* Loop over all test cases */
+            testCounter = 0;
+            while(testSuite->testCases[testCounter])
+            {
+                testCase=(SDLTest_TestCaseReference *)testSuite->testCases[testCounter];
+                currentTestName = (char *)((testCase->name) ? testCase->name : SDLTest_InvalidNameFormat);
+                testCounter++;
+
+                /* Filter tests if flag set and we have a name */
+                if (testFilter == 1 && testFilterName != NULL && testCase->name != NULL &&
+                    SDL_strcmp(testFilterName, testCase->name) != 0) {
+                        /* Skip test */
+                        SDLTest_Log("===== Test Case %i.%i: '%s' skipped\n",
+                            suiteCounter,
+                            testCounter,
+                            currentTestName);
+                } else {
+                    /* Override 'disabled' flag if we specified a test filter (i.e. force run for debugging) */
+                    if (testFilter == 1 && !testCase->enabled) {
+                        SDLTest_Log("Force run of disabled test since test filter was set");
+                        testCase->enabled = 1;
+                    }
+
+                    /* Take time - test start */
+                    testStartSeconds = GetClock();
+
+                    /* Log test started */
+                    SDLTest_Log("----- Test Case %i.%i: '%s' started",
+                        suiteCounter,
+                        testCounter,
+                        currentTestName);
+                    if (testCase->description != NULL && SDL_strlen(testCase->description)>0) {
+                        SDLTest_Log("Test Description: '%s'",
+                            (testCase->description) ? testCase->description : SDLTest_InvalidNameFormat);
+                    }
+
+                    /* Loop over all iterations */
+                    iterationCounter = 0;
+                    while(iterationCounter < testIterations)
+                    {
+                        iterationCounter++;
+
+                        if (userExecKey != 0) {
+                            execKey = userExecKey;
+                        } else {
+                            execKey = SDLTest_GenerateExecKey((char *)runSeed, testSuite->name, testCase->name, iterationCounter);
+                        }
+
+                        SDLTest_Log("Test Iteration %i: execKey %llu", iterationCounter, execKey);
+                        testResult = SDLTest_RunTest(testSuite, testCase, execKey);
+
+                        if (testResult == TEST_RESULT_PASSED) {
+                            testPassedCount++;
+                            totalTestPassedCount++;
+                        } else if (testResult == TEST_RESULT_SKIPPED) {
+                            testSkippedCount++;
+                            totalTestSkippedCount++;
+                        } else {
+                            testFailedCount++;
+                            totalTestFailedCount++;
+                        }
+                    }
+
+                    /* Take time - test end */
+                    testEndSeconds = GetClock();
+                    runtime = testEndSeconds - testStartSeconds;
+                    if (runtime < 0.0f) runtime = 0.0f;
+
+                    if (testIterations > 1) {
+                        /* Log test runtime */
+                        SDLTest_Log("Runtime of %i iterations: %.1f sec", testIterations, runtime);
+                        SDLTest_Log("Average Test runtime: %.5f sec", runtime / (float)testIterations);
+                    } else {
+                        /* Log test runtime */
+                        SDLTest_Log("Total Test runtime: %.1f sec", runtime);
+                    }
+
+                    /* Log final test result */
+                    switch (testResult) {
+                    case TEST_RESULT_PASSED:
+                        SDLTest_Log((char *)SDLTest_FinalResultFormat, "Test", currentTestName, "Passed");
+                        break;
+                    case TEST_RESULT_FAILED:
+                        SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Test", currentTestName, "Failed");
+                        break;
+                    case TEST_RESULT_NO_ASSERT:
+                        SDLTest_LogError((char *)SDLTest_FinalResultFormat,"Test", currentTestName, "No Asserts");
+                        break;
+                    }
+
+                }
+            }
+
+            /* Take time - suite end */
+            suiteEndSeconds = GetClock();
+            runtime = suiteEndSeconds - suiteStartSeconds;
+            if (runtime < 0.0f) runtime = 0.0f;
+
+            /* Log suite runtime */
+            SDLTest_Log("Total Suite runtime: %.1f sec", runtime);
+
+            /* Log summary and final Suite result */
+            countSum = testPassedCount + testFailedCount + testSkippedCount;
+            if (testFailedCount == 0)
+            {
+                SDLTest_Log(logFormat, "Suite", countSum, testPassedCount, testFailedCount, testSkippedCount);
+                SDLTest_Log((char *)SDLTest_FinalResultFormat, "Suite", currentSuiteName, "Passed");
+            }
+            else
+            {
+                SDLTest_LogError(logFormat, "Suite", countSum, testPassedCount, testFailedCount, testSkippedCount);
+                SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Suite", currentSuiteName, "Failed");
+            }
+
+        }
+    }
+
+    /* Take time - run end */
+    runEndSeconds = GetClock();
+    runtime = runEndSeconds - runStartSeconds;
+    if (runtime < 0.0f) runtime = 0.0f;
+
+    /* Log total runtime */
+    SDLTest_Log("Total Run runtime: %.1f sec", runtime);
+
+    /* Log summary and final run result */
+    countSum = totalTestPassedCount + totalTestFailedCount + totalTestSkippedCount;
+    if (totalTestFailedCount == 0)
+    {
+        runResult = 0;
+        SDLTest_Log(logFormat, "Run", countSum, totalTestPassedCount, totalTestFailedCount, totalTestSkippedCount);
+        SDLTest_Log((char *)SDLTest_FinalResultFormat, "Run /w seed", runSeed, "Passed");
+    }
+    else
+    {
+        runResult = 1;
+        SDLTest_LogError(logFormat, "Run", countSum, totalTestPassedCount, totalTestFailedCount, totalTestSkippedCount);
+        SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Run /w seed", runSeed, "Failed");
+    }
+
+    SDLTest_Log("Exit code: %d", runResult);
+    return runResult;
+}

Some files were not shown because too many files changed in this diff