Split the XInput and DirectInput code so Windows RT can use the existing XInput support.
authorSam Lantinga <slouken@libsdl.org>
Thu, 03 Jul 2014 15:39:55 -0700
changeset 8972 dfc759d7486f
parent 8971 c30e826412d1
child 8973 47fb6a7e7f68
Split the XInput and DirectInput code so Windows RT can use the existing XInput support.
VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj
VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters
VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj
VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters
VisualC/SDL/SDL_VS2008.vcproj
VisualC/SDL/SDL_VS2010.vcxproj
VisualC/SDL/SDL_VS2012.vcxproj
VisualC/SDL/SDL_VS2013.vcxproj
configure
configure.in
include/SDL_config.h.in
include/SDL_config_windows.h
include/SDL_config_winrt.h
src/audio/directsound/SDL_directsound.h
src/audio/directsound/directx.h
src/core/windows/SDL_directx.h
src/core/windows/SDL_xinput.c
src/core/windows/SDL_xinput.h
src/haptic/windows/SDL_dinputhaptic.c
src/haptic/windows/SDL_dinputhaptic_c.h
src/haptic/windows/SDL_syshaptic.c
src/haptic/windows/SDL_syshaptic_c.h
src/haptic/windows/SDL_windowshaptic.c
src/haptic/windows/SDL_windowshaptic_c.h
src/haptic/windows/SDL_xinputhaptic.c
src/haptic/windows/SDL_xinputhaptic_c.h
src/joystick/SDL_gamecontroller.c
src/joystick/SDL_gamecontrollerdb.h
src/joystick/SDL_sysjoystick.h
src/joystick/windows/SDL_dinputjoystick.c
src/joystick/windows/SDL_dinputjoystick_c.h
src/joystick/windows/SDL_dxjoystick.c
src/joystick/windows/SDL_dxjoystick_c.h
src/joystick/windows/SDL_windowsjoystick.c
src/joystick/windows/SDL_windowsjoystick_c.h
src/joystick/windows/SDL_xinputjoystick.c
src/joystick/windows/SDL_xinputjoystick_c.h
src/joystick/winrt/SDL_xinputjoystick.c
--- a/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj	Thu Jul 03 17:36:08 2014 -0300
+++ b/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj	Thu Jul 03 15:39:55 2014 -0700
@@ -47,6 +47,7 @@
       <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsWinRT>
     </ClCompile>
     <ClCompile Include="..\..\src\core\windows\SDL_windows.c" />
+    <ClCompile Include="..\..\src\core\windows\SDL_xinput.c" />
     <ClCompile Include="..\..\src\core\winrt\SDL_winrtapp_common.cpp">
       <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</CompileAsWinRT>
       <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</CompileAsWinRT>
@@ -93,9 +94,14 @@
     <ClCompile Include="..\..\src\file\SDL_rwops.c" />
     <ClCompile Include="..\..\src\haptic\dummy\SDL_syshaptic.c" />
     <ClCompile Include="..\..\src\haptic\SDL_haptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
     <ClCompile Include="..\..\src\joystick\SDL_gamecontroller.c" />
     <ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
-    <ClCompile Include="..\..\src\joystick\winrt\SDL_xinputjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c" />
     <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
     <ClCompile Include="..\..\src\power\SDL_power.c" />
     <ClCompile Include="..\..\src\power\winrt\SDL_syspower.cpp" />
@@ -278,7 +284,9 @@
     <ClInclude Include="..\..\src\audio\SDL_sysaudio.h" />
     <ClInclude Include="..\..\src\audio\SDL_wave.h" />
     <ClInclude Include="..\..\src\audio\xaudio2\SDL_xaudio2_winrthelpers.h" />
+    <ClInclude Include="..\..\src\core\windows\SDL_directx.h" />
     <ClInclude Include="..\..\src\core\windows\SDL_windows.h" />
+    <ClInclude Include="..\..\src\core\windows\SDL_xinput.h" />
     <ClInclude Include="..\..\src\core\winrt\SDL_winrtapp_common.h" />
     <ClInclude Include="..\..\src\core\winrt\SDL_winrtapp_direct3d.h" />
     <ClInclude Include="..\..\src\core\winrt\SDL_winrtapp_xaml.h" />
@@ -297,9 +305,15 @@
     <ClInclude Include="..\..\src\events\SDL_windowevents_c.h" />
     <ClInclude Include="..\..\src\haptic\SDL_haptic_c.h" />
     <ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
     <ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" />
     <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
     <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_windowsjoystick_c.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h" />
     <ClInclude Include="..\..\src\render\direct3d11\SDL_render_winrt.h" />
     <ClInclude Include="..\..\src\render\mmx.h" />
     <ClInclude Include="..\..\src\render\opengles2\SDL_gles2funcs.h" />
--- a/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters	Thu Jul 03 17:36:08 2014 -0300
+++ b/VisualC-WinRT/WinRT80_VS2012/SDL-WinRT80.vcxproj.filters	Thu Jul 03 15:39:55 2014 -0700
@@ -247,9 +247,6 @@
     <ClCompile Include="..\..\src\video\winrt\SDL_winrtkeyboard.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\joystick\winrt\SDL_xinputjoystick.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\src\video\winrt\SDL_winrtpointerinput.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -298,6 +295,27 @@
     <ClCompile Include="..\..\src\video\winrt\SDL_winrtmessagebox.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\windows\SDL_xinput.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\begin_code.h">
@@ -672,6 +690,30 @@
     <ClInclude Include="..\..\src\video\winrt\SDL_winrtmessagebox.h">
       <Filter>Source Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\joystick\windows\SDL_windowsjoystick_c.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\core\windows\SDL_xinput.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\core\windows\SDL_directx.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="Header Files">
--- a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj	Thu Jul 03 17:36:08 2014 -0300
+++ b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj	Thu Jul 03 15:39:55 2014 -0700
@@ -86,7 +86,9 @@
     <ClInclude Include="..\..\src\audio\SDL_sysaudio.h" />
     <ClInclude Include="..\..\src\audio\SDL_wave.h" />
     <ClInclude Include="..\..\src\audio\xaudio2\SDL_xaudio2_winrthelpers.h" />
+    <ClInclude Include="..\..\src\core\windows\SDL_directx.h" />
     <ClInclude Include="..\..\src\core\windows\SDL_windows.h" />
+    <ClInclude Include="..\..\src\core\windows\SDL_xinput.h" />
     <ClInclude Include="..\..\src\core\winrt\SDL_winrtapp_common.h" />
     <ClInclude Include="..\..\src\core\winrt\SDL_winrtapp_direct3d.h" />
     <ClInclude Include="..\..\src\core\winrt\SDL_winrtapp_xaml.h" />
@@ -105,9 +107,15 @@
     <ClInclude Include="..\..\src\events\SDL_windowevents_c.h" />
     <ClInclude Include="..\..\src\haptic\SDL_haptic_c.h" />
     <ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
     <ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" />
     <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
     <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_windowsjoystick_c.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h" />
     <ClInclude Include="..\..\src\render\direct3d11\SDL_render_winrt.h" />
     <ClInclude Include="..\..\src\render\mmx.h" />
     <ClInclude Include="..\..\src\render\opengles2\SDL_gles2funcs.h" />
@@ -173,6 +181,7 @@
       <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsWinRT>
     </ClCompile>
     <ClCompile Include="..\..\src\core\windows\SDL_windows.c" />
+    <ClCompile Include="..\..\src\core\windows\SDL_xinput.c" />
     <ClCompile Include="..\..\src\core\winrt\SDL_winrtapp_common.cpp">
       <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</CompileAsWinRT>
       <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</CompileAsWinRT>
@@ -219,10 +228,15 @@
     <ClCompile Include="..\..\src\file\SDL_rwops.c" />
     <ClCompile Include="..\..\src\haptic\dummy\SDL_syshaptic.c" />
     <ClCompile Include="..\..\src\haptic\SDL_haptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
     <ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c" />
     <ClCompile Include="..\..\src\joystick\SDL_gamecontroller.c" />
     <ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
-    <ClCompile Include="..\..\src\joystick\winrt\SDL_xinputjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c" />
     <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
     <ClCompile Include="..\..\src\power\SDL_power.c" />
     <ClCompile Include="..\..\src\power\winrt\SDL_syspower.cpp" />
--- a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters	Thu Jul 03 17:36:08 2014 -0300
+++ b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters	Thu Jul 03 15:39:55 2014 -0700
@@ -381,6 +381,24 @@
     <ClInclude Include="..\..\src\video\winrt\SDL_winrtvideo_cpp.h">
       <Filter>Source Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\core\windows\SDL_directx.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\core\windows\SDL_xinput.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\joystick\windows\SDL_windowsjoystick_c.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\atomic\SDL_atomic.c">
@@ -485,9 +503,6 @@
     <ClCompile Include="..\..\src\joystick\SDL_joystick.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\joystick\winrt\SDL_xinputjoystick.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -683,5 +698,20 @@
     <ClCompile Include="..\..\src\video\winrt\SDL_winrtvideo.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\core\windows\SDL_xinput.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c" />
   </ItemGroup>
 </Project>
\ No newline at end of file
--- a/VisualC/SDL/SDL_VS2008.vcproj	Thu Jul 03 17:36:08 2014 -0300
+++ b/VisualC/SDL/SDL_VS2008.vcproj	Thu Jul 03 15:39:55 2014 -0700
@@ -372,6 +372,14 @@
 			Name="API Headers"
 			>
 			<File
+				RelativePath="..\..\include\begin_code.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\close_code.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\include\SDL.h"
 				>
 			</File>
@@ -420,10 +428,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\src\video\sdl_egl_c.h"
-				>
-			</File>
-			<File
 				RelativePath="..\..\include\SDL_endian.h"
 				>
 			</File>
@@ -500,10 +504,34 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\include\SDL_opengl_glext.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\include\SDL_opengles.h"
 				>
 			</File>
 			<File
+				RelativePath="..\..\include\SDL_opengles2.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_opengles2_gl2.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_opengles2_gl2ext.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_opengles2_gl2platform.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_opengles2_khrplatform.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\include\SDL_pixels.h"
 				>
 			</File>
@@ -560,6 +588,54 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\include\SDL_test.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_assert.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_common.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_compare.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_crc32.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_font.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_fuzzer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_harness.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_images.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_log.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_md5.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\include\SDL_test_random.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\include\SDL_thread.h"
 				>
 			</File>
@@ -583,10 +659,6 @@
 				RelativePath="..\..\include\SDL_video.h"
 				>
 			</File>
-			<File
-				RelativePath="..\..\src\video\windows\SDL_windowsopengles.h"
-				>
-			</File>
 		</Filter>
 		<File
 			RelativePath="..\..\src\events\blank_cursor.h"
@@ -597,10 +669,6 @@
 			>
 		</File>
 		<File
-			RelativePath="..\..\src\audio\directsound\directx.h"
-			>
-		</File>
-		<File
 			RelativePath="..\..\src\libm\e_atan2.c"
 			>
 		</File>
@@ -825,6 +893,22 @@
 			>
 		</File>
 		<File
+			RelativePath="..\..\src\haptic\windows\SDL_dinputhaptic.c"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\haptic\windows\SDL_dinputhaptic_c.h"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\joystick\windows\SDL_dinputjoystick.c"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\joystick\windows\SDL_dinputjoystick_c.h"
+			>
+		</File>
+		<File
 			RelativePath="..\..\src\audio\directsound\SDL_directsound.c"
 			>
 		</File>
@@ -833,6 +917,10 @@
 			>
 		</File>
 		<File
+			RelativePath="..\..\src\core\windows\SDL_directx.h"
+			>
+		</File>
+		<File
 			RelativePath="..\..\src\audio\disk\SDL_diskaudio.c"
 			>
 		</File>
@@ -877,10 +965,6 @@
 			>
 		</File>
 		<File
-			RelativePath="..\..\src\joystick\windows\SDL_dxjoystick.c"
-			>
-		</File>
-		<File
 			RelativePath="..\..\src\dynapi\SDL_dynapi.c"
 			>
 		</File>
@@ -1157,10 +1241,6 @@
 			>
 		</File>
 		<File
-			RelativePath="..\..\src\haptic\windows\SDL_syshaptic.c"
-			>
-		</File>
-		<File
 			RelativePath="..\..\src\haptic\SDL_syshaptic.h"
 			>
 		</File>
@@ -1297,6 +1377,22 @@
 			>
 		</File>
 		<File
+			RelativePath="..\..\src\haptic\windows\SDL_windowshaptic.c"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\haptic\windows\SDL_windowshaptic_c.h"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\joystick\windows\SDL_windowsjoystick.c"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\joystick\windows\SDL_windowsjoystick_c.h"
+			>
+		</File>
+		<File
 			RelativePath="..\..\src\video\windows\SDL_windowskeyboard.c"
 			>
 		</File>
@@ -1377,6 +1473,30 @@
 			>
 		</File>
 		<File
+			RelativePath="..\..\src\core\windows\SDL_xinput.c"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\core\windows\SDL_xinput.h"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\haptic\windows\SDL_xinputhaptic.c"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\haptic\windows\SDL_xinputhaptic_c.h"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\joystick\windows\SDL_xinputjoystick.c"
+			>
+		</File>
+		<File
+			RelativePath="..\..\src\joystick\windows\SDL_xinputjoystick_c.h"
+			>
+		</File>
+		<File
 			RelativePath="..\..\src\render\SDL_yuv_mmx.c"
 			>
 		</File>
--- a/VisualC/SDL/SDL_VS2010.vcxproj	Thu Jul 03 17:36:08 2014 -0300
+++ b/VisualC/SDL/SDL_VS2010.vcxproj	Thu Jul 03 15:39:55 2014 -0700
@@ -219,6 +219,8 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\include\begin_code.h" />
+    <ClInclude Include="..\..\include\close_code.h" />
     <ClInclude Include="..\..\include\SDL.h" />
     <ClInclude Include="..\..\include\SDL_assert.h" />
     <ClInclude Include="..\..\include\SDL_atomic.h" />
@@ -235,6 +237,7 @@
     <ClInclude Include="..\..\include\SDL_error.h" />
     <ClInclude Include="..\..\include\SDL_events.h" />
     <ClInclude Include="..\..\include\SDL_filesystem.h" />
+    <ClInclude Include="..\..\include\SDL_gamecontroller.h" />
     <ClInclude Include="..\..\include\SDL_gesture.h" />
     <ClInclude Include="..\..\include\SDL_haptic.h" />
     <ClInclude Include="..\..\include\SDL_hints.h" />
@@ -244,11 +247,18 @@
     <ClInclude Include="..\..\include\SDL_loadso.h" />
     <ClInclude Include="..\..\include\SDL_log.h" />
     <ClInclude Include="..\..\include\SDL_main.h" />
+    <ClInclude Include="..\..\include\SDL_messagebox.h" />
     <ClInclude Include="..\..\include\SDL_mouse.h" />
     <ClInclude Include="..\..\include\SDL_mutex.h" />
     <ClInclude Include="..\..\include\SDL_name.h" />
     <ClInclude Include="..\..\include\SDL_opengl.h" />
     <ClInclude Include="..\..\include\SDL_opengles.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_gl2.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_gl2ext.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_gl2platform.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_khrplatform.h" />
+    <ClInclude Include="..\..\include\SDL_opengl_glext.h" />
     <ClInclude Include="..\..\include\SDL_pixels.h" />
     <ClInclude Include="..\..\include\SDL_platform.h" />
     <ClInclude Include="..\..\include\SDL_power.h" />
@@ -263,23 +273,42 @@
     <ClInclude Include="..\..\include\SDL_surface.h" />
     <ClInclude Include="..\..\include\SDL_system.h" />
     <ClInclude Include="..\..\include\SDL_syswm.h" />
+    <ClInclude Include="..\..\include\SDL_test.h" />
+    <ClInclude Include="..\..\include\SDL_test_assert.h" />
+    <ClInclude Include="..\..\include\SDL_test_common.h" />
+    <ClInclude Include="..\..\include\SDL_test_compare.h" />
+    <ClInclude Include="..\..\include\SDL_test_crc32.h" />
+    <ClInclude Include="..\..\include\SDL_test_font.h" />
+    <ClInclude Include="..\..\include\SDL_test_fuzzer.h" />
+    <ClInclude Include="..\..\include\SDL_test_harness.h" />
+    <ClInclude Include="..\..\include\SDL_test_images.h" />
+    <ClInclude Include="..\..\include\SDL_test_log.h" />
+    <ClInclude Include="..\..\include\SDL_test_md5.h" />
+    <ClInclude Include="..\..\include\SDL_test_random.h" />
     <ClInclude Include="..\..\include\SDL_thread.h" />
     <ClInclude Include="..\..\include\SDL_timer.h" />
     <ClInclude Include="..\..\include\SDL_touch.h" />
     <ClInclude Include="..\..\include\SDL_types.h" />
     <ClInclude Include="..\..\include\SDL_version.h" />
     <ClInclude Include="..\..\include\SDL_video.h" />
-    <ClInclude Include="..\..\include\SDL_gamecontroller.h" />
+    <ClInclude Include="..\..\src\core\windows\SDL_directx.h" />
     <ClInclude Include="..\..\src\core\windows\SDL_windows.h" />
+    <ClInclude Include="..\..\src\core\windows\SDL_xinput.h" />
     <ClInclude Include="..\..\src\dynapi\SDL_dynapi.h" />
     <ClInclude Include="..\..\src\dynapi\SDL_dynapi_overrides.h" />
     <ClInclude Include="..\..\src\dynapi\SDL_dynapi_procs.h" />
     <ClInclude Include="..\..\src\events\blank_cursor.h" />
     <ClInclude Include="..\..\src\events\default_cursor.h" />
-    <ClInclude Include="..\..\src\audio\directsound\directx.h" />
     <ClInclude Include="..\..\src\events\SDL_clipboardevents_c.h" />
     <ClInclude Include="..\..\src\events\SDL_gesture_c.h" />
     <ClInclude Include="..\..\src\events\SDL_touch_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
+    <ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_windowsjoystick_c.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h" />
     <ClInclude Include="..\..\src\libm\math_libm.h" />
     <ClInclude Include="..\..\src\libm\math_private.h" />
     <ClInclude Include="..\..\src\render\mmx.h" />
@@ -322,7 +351,6 @@
     <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" />
     <ClInclude Include="..\..\src\audio\SDL_sysaudio.h" />
     <ClInclude Include="..\..\src\events\SDL_sysevents.h" />
-    <ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
     <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
     <ClInclude Include="..\..\src\thread\SDL_systhread.h" />
     <ClInclude Include="..\..\src\thread\windows\SDL_systhread_c.h" />
@@ -348,10 +376,17 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\core\windows\SDL_windows.c" />
+    <ClCompile Include="..\..\src\core\windows\SDL_xinput.c" />
     <ClCompile Include="..\..\src\dynapi\SDL_dynapi.c" />
     <ClCompile Include="..\..\src\events\SDL_clipboardevents.c" />
     <ClCompile Include="..\..\src\events\SDL_gesture.c" />
     <ClCompile Include="..\..\src\events\SDL_touch.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c" />
     <ClCompile Include="..\..\src\libm\e_atan2.c" />
     <ClCompile Include="..\..\src\libm\e_log.c" />
     <ClCompile Include="..\..\src\libm\e_pow.c" />
@@ -416,7 +451,6 @@
     <ClCompile Include="..\..\src\audio\directsound\SDL_directsound.c" />
     <ClCompile Include="..\..\src\events\SDL_dropevents.c" />
     <ClCompile Include="..\..\src\audio\xaudio2\SDL_xaudio2.c" />
-    <ClCompile Include="..\..\src\joystick\windows\SDL_dxjoystick.c" />
     <ClCompile Include="..\..\src\SDL_error.c" />
     <ClCompile Include="..\..\src\events\SDL_events.c" />
     <ClCompile Include="..\..\src\video\SDL_fillrect.c" />
@@ -444,7 +478,6 @@
     <ClCompile Include="..\..\src\video\SDL_surface.c" />
     <ClCompile Include="..\..\src\thread\generic\SDL_syscond.c" />
     <ClCompile Include="..\..\src\filesystem\windows\SDL_sysfilesystem.c" />
-    <ClCompile Include="..\..\src\haptic\windows\SDL_syshaptic.c" />
     <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
     <ClCompile Include="..\..\src\thread\windows\SDL_sysmutex.c" />
     <ClCompile Include="..\..\src\power\windows\SDL_syspower.c" />
--- a/VisualC/SDL/SDL_VS2012.vcxproj	Thu Jul 03 17:36:08 2014 -0300
+++ b/VisualC/SDL/SDL_VS2012.vcxproj	Thu Jul 03 15:39:55 2014 -0700
@@ -223,6 +223,8 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\include\begin_code.h" />
+    <ClInclude Include="..\..\include\close_code.h" />
     <ClInclude Include="..\..\include\SDL.h" />
     <ClInclude Include="..\..\include\SDL_assert.h" />
     <ClInclude Include="..\..\include\SDL_atomic.h" />
@@ -239,6 +241,7 @@
     <ClInclude Include="..\..\include\SDL_error.h" />
     <ClInclude Include="..\..\include\SDL_events.h" />
     <ClInclude Include="..\..\include\SDL_filesystem.h" />
+    <ClInclude Include="..\..\include\SDL_gamecontroller.h" />
     <ClInclude Include="..\..\include\SDL_gesture.h" />
     <ClInclude Include="..\..\include\SDL_haptic.h" />
     <ClInclude Include="..\..\include\SDL_hints.h" />
@@ -248,11 +251,18 @@
     <ClInclude Include="..\..\include\SDL_loadso.h" />
     <ClInclude Include="..\..\include\SDL_log.h" />
     <ClInclude Include="..\..\include\SDL_main.h" />
+    <ClInclude Include="..\..\include\SDL_messagebox.h" />
     <ClInclude Include="..\..\include\SDL_mouse.h" />
     <ClInclude Include="..\..\include\SDL_mutex.h" />
     <ClInclude Include="..\..\include\SDL_name.h" />
     <ClInclude Include="..\..\include\SDL_opengl.h" />
     <ClInclude Include="..\..\include\SDL_opengles.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_gl2.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_gl2ext.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_gl2platform.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_khrplatform.h" />
+    <ClInclude Include="..\..\include\SDL_opengl_glext.h" />
     <ClInclude Include="..\..\include\SDL_pixels.h" />
     <ClInclude Include="..\..\include\SDL_platform.h" />
     <ClInclude Include="..\..\include\SDL_power.h" />
@@ -267,23 +277,42 @@
     <ClInclude Include="..\..\include\SDL_surface.h" />
     <ClInclude Include="..\..\include\SDL_system.h" />
     <ClInclude Include="..\..\include\SDL_syswm.h" />
+    <ClInclude Include="..\..\include\SDL_test.h" />
+    <ClInclude Include="..\..\include\SDL_test_assert.h" />
+    <ClInclude Include="..\..\include\SDL_test_common.h" />
+    <ClInclude Include="..\..\include\SDL_test_compare.h" />
+    <ClInclude Include="..\..\include\SDL_test_crc32.h" />
+    <ClInclude Include="..\..\include\SDL_test_font.h" />
+    <ClInclude Include="..\..\include\SDL_test_fuzzer.h" />
+    <ClInclude Include="..\..\include\SDL_test_harness.h" />
+    <ClInclude Include="..\..\include\SDL_test_images.h" />
+    <ClInclude Include="..\..\include\SDL_test_log.h" />
+    <ClInclude Include="..\..\include\SDL_test_md5.h" />
+    <ClInclude Include="..\..\include\SDL_test_random.h" />
     <ClInclude Include="..\..\include\SDL_thread.h" />
     <ClInclude Include="..\..\include\SDL_timer.h" />
     <ClInclude Include="..\..\include\SDL_touch.h" />
     <ClInclude Include="..\..\include\SDL_types.h" />
     <ClInclude Include="..\..\include\SDL_version.h" />
     <ClInclude Include="..\..\include\SDL_video.h" />
-    <ClInclude Include="..\..\include\SDL_gamecontroller.h" />
+    <ClInclude Include="..\..\src\core\windows\SDL_directx.h" />
     <ClInclude Include="..\..\src\core\windows\SDL_windows.h" />
+    <ClInclude Include="..\..\src\core\windows\SDL_xinput.h" />
     <ClInclude Include="..\..\src\dynapi\SDL_dynapi.h" />
     <ClInclude Include="..\..\src\dynapi\SDL_dynapi_overrides.h" />
     <ClInclude Include="..\..\src\dynapi\SDL_dynapi_procs.h" />
     <ClInclude Include="..\..\src\events\blank_cursor.h" />
     <ClInclude Include="..\..\src\events\default_cursor.h" />
-    <ClInclude Include="..\..\src\audio\directsound\directx.h" />
     <ClInclude Include="..\..\src\events\SDL_clipboardevents_c.h" />
     <ClInclude Include="..\..\src\events\SDL_gesture_c.h" />
     <ClInclude Include="..\..\src\events\SDL_touch_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
+    <ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_windowsjoystick_c.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h" />
     <ClInclude Include="..\..\src\libm\math_libm.h" />
     <ClInclude Include="..\..\src\libm\math_private.h" />
     <ClInclude Include="..\..\src\render\mmx.h" />
@@ -326,7 +355,6 @@
     <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" />
     <ClInclude Include="..\..\src\audio\SDL_sysaudio.h" />
     <ClInclude Include="..\..\src\events\SDL_sysevents.h" />
-    <ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
     <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
     <ClInclude Include="..\..\src\thread\SDL_systhread.h" />
     <ClInclude Include="..\..\src\thread\windows\SDL_systhread_c.h" />
@@ -352,10 +380,17 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\core\windows\SDL_windows.c" />
+    <ClCompile Include="..\..\src\core\windows\SDL_xinput.c" />
     <ClCompile Include="..\..\src\dynapi\SDL_dynapi.c" />
     <ClCompile Include="..\..\src\events\SDL_clipboardevents.c" />
     <ClCompile Include="..\..\src\events\SDL_gesture.c" />
     <ClCompile Include="..\..\src\events\SDL_touch.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c" />
     <ClCompile Include="..\..\src\libm\e_atan2.c" />
     <ClCompile Include="..\..\src\libm\e_log.c" />
     <ClCompile Include="..\..\src\libm\e_pow.c" />
@@ -420,7 +455,6 @@
     <ClCompile Include="..\..\src\audio\directsound\SDL_directsound.c" />
     <ClCompile Include="..\..\src\events\SDL_dropevents.c" />
     <ClCompile Include="..\..\src\audio\xaudio2\SDL_xaudio2.c" />
-    <ClCompile Include="..\..\src\joystick\windows\SDL_dxjoystick.c" />
     <ClCompile Include="..\..\src\SDL_error.c" />
     <ClCompile Include="..\..\src\events\SDL_events.c" />
     <ClCompile Include="..\..\src\video\SDL_fillrect.c" />
@@ -448,7 +482,6 @@
     <ClCompile Include="..\..\src\video\SDL_surface.c" />
     <ClCompile Include="..\..\src\thread\generic\SDL_syscond.c" />
     <ClCompile Include="..\..\src\filesystem\windows\SDL_sysfilesystem.c" />
-    <ClCompile Include="..\..\src\haptic\windows\SDL_syshaptic.c" />
     <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
     <ClCompile Include="..\..\src\thread\windows\SDL_sysmutex.c" />
     <ClCompile Include="..\..\src\power\windows\SDL_syspower.c" />
--- a/VisualC/SDL/SDL_VS2013.vcxproj	Thu Jul 03 17:36:08 2014 -0300
+++ b/VisualC/SDL/SDL_VS2013.vcxproj	Thu Jul 03 15:39:55 2014 -0700
@@ -223,6 +223,8 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\include\begin_code.h" />
+    <ClInclude Include="..\..\include\close_code.h" />
     <ClInclude Include="..\..\include\SDL.h" />
     <ClInclude Include="..\..\include\SDL_assert.h" />
     <ClInclude Include="..\..\include\SDL_atomic.h" />
@@ -239,6 +241,7 @@
     <ClInclude Include="..\..\include\SDL_error.h" />
     <ClInclude Include="..\..\include\SDL_events.h" />
     <ClInclude Include="..\..\include\SDL_filesystem.h" />
+    <ClInclude Include="..\..\include\SDL_gamecontroller.h" />
     <ClInclude Include="..\..\include\SDL_gesture.h" />
     <ClInclude Include="..\..\include\SDL_haptic.h" />
     <ClInclude Include="..\..\include\SDL_hints.h" />
@@ -248,11 +251,18 @@
     <ClInclude Include="..\..\include\SDL_loadso.h" />
     <ClInclude Include="..\..\include\SDL_log.h" />
     <ClInclude Include="..\..\include\SDL_main.h" />
+    <ClInclude Include="..\..\include\SDL_messagebox.h" />
     <ClInclude Include="..\..\include\SDL_mouse.h" />
     <ClInclude Include="..\..\include\SDL_mutex.h" />
     <ClInclude Include="..\..\include\SDL_name.h" />
     <ClInclude Include="..\..\include\SDL_opengl.h" />
     <ClInclude Include="..\..\include\SDL_opengles.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_gl2.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_gl2ext.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_gl2platform.h" />
+    <ClInclude Include="..\..\include\SDL_opengles2_khrplatform.h" />
+    <ClInclude Include="..\..\include\SDL_opengl_glext.h" />
     <ClInclude Include="..\..\include\SDL_pixels.h" />
     <ClInclude Include="..\..\include\SDL_platform.h" />
     <ClInclude Include="..\..\include\SDL_power.h" />
@@ -267,23 +277,42 @@
     <ClInclude Include="..\..\include\SDL_surface.h" />
     <ClInclude Include="..\..\include\SDL_system.h" />
     <ClInclude Include="..\..\include\SDL_syswm.h" />
+    <ClInclude Include="..\..\include\SDL_test.h" />
+    <ClInclude Include="..\..\include\SDL_test_assert.h" />
+    <ClInclude Include="..\..\include\SDL_test_common.h" />
+    <ClInclude Include="..\..\include\SDL_test_compare.h" />
+    <ClInclude Include="..\..\include\SDL_test_crc32.h" />
+    <ClInclude Include="..\..\include\SDL_test_font.h" />
+    <ClInclude Include="..\..\include\SDL_test_fuzzer.h" />
+    <ClInclude Include="..\..\include\SDL_test_harness.h" />
+    <ClInclude Include="..\..\include\SDL_test_images.h" />
+    <ClInclude Include="..\..\include\SDL_test_log.h" />
+    <ClInclude Include="..\..\include\SDL_test_md5.h" />
+    <ClInclude Include="..\..\include\SDL_test_random.h" />
     <ClInclude Include="..\..\include\SDL_thread.h" />
     <ClInclude Include="..\..\include\SDL_timer.h" />
     <ClInclude Include="..\..\include\SDL_touch.h" />
     <ClInclude Include="..\..\include\SDL_types.h" />
     <ClInclude Include="..\..\include\SDL_version.h" />
     <ClInclude Include="..\..\include\SDL_video.h" />
-    <ClInclude Include="..\..\include\SDL_gamecontroller.h" />
+    <ClInclude Include="..\..\src\core\windows\SDL_directx.h" />
     <ClInclude Include="..\..\src\core\windows\SDL_windows.h" />
+    <ClInclude Include="..\..\src\core\windows\SDL_xinput.h" />
     <ClInclude Include="..\..\src\dynapi\SDL_dynapi.h" />
     <ClInclude Include="..\..\src\dynapi\SDL_dynapi_overrides.h" />
     <ClInclude Include="..\..\src\dynapi\SDL_dynapi_procs.h" />
     <ClInclude Include="..\..\src\events\blank_cursor.h" />
     <ClInclude Include="..\..\src\events\default_cursor.h" />
-    <ClInclude Include="..\..\src\audio\directsound\directx.h" />
     <ClInclude Include="..\..\src\events\SDL_clipboardevents_c.h" />
     <ClInclude Include="..\..\src\events\SDL_gesture_c.h" />
     <ClInclude Include="..\..\src\events\SDL_touch_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_windowshaptic_c.h" />
+    <ClInclude Include="..\..\src\haptic\windows\SDL_xinputhaptic_c.h" />
+    <ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_dinputjoystick_c.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_windowsjoystick_c.h" />
+    <ClInclude Include="..\..\src\joystick\windows\SDL_xinputjoystick_c.h" />
     <ClInclude Include="..\..\src\libm\math_libm.h" />
     <ClInclude Include="..\..\src\libm\math_private.h" />
     <ClInclude Include="..\..\src\render\mmx.h" />
@@ -326,7 +355,6 @@
     <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" />
     <ClInclude Include="..\..\src\audio\SDL_sysaudio.h" />
     <ClInclude Include="..\..\src\events\SDL_sysevents.h" />
-    <ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
     <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
     <ClInclude Include="..\..\src\thread\SDL_systhread.h" />
     <ClInclude Include="..\..\src\thread\windows\SDL_systhread_c.h" />
@@ -352,10 +380,17 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\core\windows\SDL_windows.c" />
+    <ClCompile Include="..\..\src\core\windows\SDL_xinput.c" />
     <ClCompile Include="..\..\src\dynapi\SDL_dynapi.c" />
     <ClCompile Include="..\..\src\events\SDL_clipboardevents.c" />
     <ClCompile Include="..\..\src\events\SDL_gesture.c" />
     <ClCompile Include="..\..\src\events\SDL_touch.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_windowshaptic.c" />
+    <ClCompile Include="..\..\src\haptic\windows\SDL_xinputhaptic.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_windowsjoystick.c" />
+    <ClCompile Include="..\..\src\joystick\windows\SDL_xinputjoystick.c" />
     <ClCompile Include="..\..\src\libm\e_atan2.c" />
     <ClCompile Include="..\..\src\libm\e_log.c" />
     <ClCompile Include="..\..\src\libm\e_pow.c" />
@@ -420,7 +455,6 @@
     <ClCompile Include="..\..\src\audio\directsound\SDL_directsound.c" />
     <ClCompile Include="..\..\src\events\SDL_dropevents.c" />
     <ClCompile Include="..\..\src\audio\xaudio2\SDL_xaudio2.c" />
-    <ClCompile Include="..\..\src\joystick\windows\SDL_dxjoystick.c" />
     <ClCompile Include="..\..\src\SDL_error.c" />
     <ClCompile Include="..\..\src\events\SDL_events.c" />
     <ClCompile Include="..\..\src\video\SDL_fillrect.c" />
@@ -448,7 +482,6 @@
     <ClCompile Include="..\..\src\video\SDL_surface.c" />
     <ClCompile Include="..\..\src\thread\generic\SDL_syscond.c" />
     <ClCompile Include="..\..\src\filesystem\windows\SDL_sysfilesystem.c" />
-    <ClCompile Include="..\..\src\haptic\windows\SDL_syshaptic.c" />
     <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
     <ClCompile Include="..\..\src\thread\windows\SDL_sysmutex.c" />
     <ClCompile Include="..\..\src\power\windows\SDL_syspower.c" />
--- a/configure	Thu Jul 03 17:36:08 2014 -0300
+++ b/configure	Thu Jul 03 15:39:55 2014 -0700
@@ -22112,18 +22112,50 @@
 fi
 
 
+        ac_fn_c_check_header_mongrel "$LINENO" "dxgi.h" "ac_cv_header_dxgi_h" "$ac_includes_default"
+if test "x$ac_cv_header_dxgi_h" = xyes; then :
+  have_dxgi=yes
+fi
+
+
         ac_fn_c_check_header_mongrel "$LINENO" "xaudio2.h" "ac_cv_header_xaudio2_h" "$ac_includes_default"
 if test "x$ac_cv_header_xaudio2_h" = xyes; then :
   have_xaudio2=yes
 fi
 
 
-        ac_fn_c_check_header_mongrel "$LINENO" "dxgi.h" "ac_cv_header_dxgi_h" "$ac_includes_default"
-if test "x$ac_cv_header_dxgi_h" = xyes; then :
-  have_dxgi=yes
-fi
-
-
+        ac_fn_c_check_header_mongrel "$LINENO" "xinput.h" "ac_cv_header_xinput_h" "$ac_includes_default"
+if test "x$ac_cv_header_xinput_h" = xyes; then :
+  have_xinput=yes
+fi
+
+
+
+        if test x$have_ddraw = xyes; then
+
+$as_echo "#define HAVE_DDRAW_H 1" >>confdefs.h
+
+        fi
+        if test x$have_dinput = xyes; then
+
+$as_echo "#define HAVE_DINPUT_H 1" >>confdefs.h
+
+        fi
+        if test x$have_dsound = xyes; then
+
+$as_echo "#define HAVE_DSOUND_H 1" >>confdefs.h
+
+        fi
+        if test x$have_dxgi = xyes; then
+
+$as_echo "#define HAVE_DXGI_H 1" >>confdefs.h
+
+        fi
+        if test x$have_xinput = xyes; then
+
+$as_echo "#define HAVE_XINPUT_H 1" >>confdefs.h
+
+        fi
 
         SUMMARY_video="${SUMMARY_video} directx"
         SUMMARY_audio="${SUMMARY_audio} directx"
@@ -22981,11 +23013,6 @@
 
             fi
         fi
-        if test x$have_dxgi = xyes; then
-
-$as_echo "#define HAVE_DXGI_H 1" >>confdefs.h
-
-        fi
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
 
@@ -23008,25 +23035,38 @@
         fi
         # Set up files for the joystick library
         if test x$enable_joystick = xyes; then
-            if test x$have_dinput = xyes; then
+            if test x$have_dinput = xyes -o x$have_xinput = xyes; then
+                if test x$have_xinput = xyes; then
+
+$as_echo "#define SDL_JOYSTICK_XINPUT 1" >>confdefs.h
+
+                fi
+                if test x$have_dinput = xyes; then
 
 $as_echo "#define SDL_JOYSTICK_DINPUT 1" >>confdefs.h
 
-                SOURCES="$SOURCES $srcdir/src/joystick/windows/SDL_dxjoystick.c"
-                EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldinput8 -ldxguid -ldxerr8"
+                    EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldinput8 -ldxguid -ldxerr8"
+                fi
             else
 
 $as_echo "#define SDL_JOYSTICK_WINMM 1" >>confdefs.h
 
-                SOURCES="$SOURCES $srcdir/src/joystick/windows/SDL_mmjoystick.c"
-            fi
+            fi
+            SOURCES="$SOURCES $srcdir/src/joystick/windows/*.c"
             have_joystick=yes
         fi
         if test x$enable_haptic = xyes; then
-            if test x$have_dinput = xyes; then
+            if test x$have_dinput = xyes -o x$have_xinput = xyes; then
+                if test x$have_xinput = xyes; then
+
+$as_echo "#define SDL_HAPTIC_XINPUT 1" >>confdefs.h
+
+                fi
+                if test x$have_dinput = xyes; then
 
 $as_echo "#define SDL_HAPTIC_DINPUT 1" >>confdefs.h
 
+                fi
                 SOURCES="$SOURCES $srcdir/src/haptic/windows/SDL_syshaptic.c"
                 have_haptic=yes
             fi
--- a/configure.in	Thu Jul 03 17:36:08 2014 -0300
+++ b/configure.in	Thu Jul 03 15:39:55 2014 -0700
@@ -2496,8 +2496,25 @@
         AC_CHECK_HEADER(ddraw.h, have_ddraw=yes)
         AC_CHECK_HEADER(dsound.h, have_dsound=yes)
         AC_CHECK_HEADER(dinput.h, have_dinput=yes)
+        AC_CHECK_HEADER(dxgi.h, have_dxgi=yes)
         AC_CHECK_HEADER(xaudio2.h, have_xaudio2=yes)
-        AC_CHECK_HEADER(dxgi.h, have_dxgi=yes)
+        AC_CHECK_HEADER(xinput.h, have_xinput=yes)
+
+        if test x$have_ddraw = xyes; then
+            AC_DEFINE(HAVE_DDRAW_H, 1, [ ])
+        fi
+        if test x$have_dinput = xyes; then
+            AC_DEFINE(HAVE_DINPUT_H, 1, [ ])
+        fi
+        if test x$have_dsound = xyes; then
+            AC_DEFINE(HAVE_DSOUND_H, 1, [ ])
+        fi
+        if test x$have_dxgi = xyes; then
+            AC_DEFINE(HAVE_DXGI_H, 1, [ ])
+        fi
+        if test x$have_xinput = xyes; then
+            AC_DEFINE(HAVE_XINPUT_H, 1, [ ])
+        fi
 
         SUMMARY_video="${SUMMARY_video} directx"
         SUMMARY_audio="${SUMMARY_audio} directx"
@@ -2927,9 +2944,6 @@
                 AC_DEFINE(SDL_VIDEO_RENDER_D3D11, 1, [ ])
             fi
         fi
-        if test x$have_dxgi = xyes; then
-            AC_DEFINE(HAVE_DXGI_H, 1, [ ])
-        fi
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
             AC_DEFINE(SDL_AUDIO_DRIVER_WINMM, 1, [ ])
@@ -2946,19 +2960,28 @@
         fi
         # Set up files for the joystick library
         if test x$enable_joystick = xyes; then
-            if test x$have_dinput = xyes; then
-                AC_DEFINE(SDL_JOYSTICK_DINPUT, 1, [ ])
-                SOURCES="$SOURCES $srcdir/src/joystick/windows/SDL_dxjoystick.c"
-                EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldinput8 -ldxguid -ldxerr8"
+            if test x$have_dinput = xyes -o x$have_xinput = xyes; then
+                if test x$have_xinput = xyes; then
+                    AC_DEFINE(SDL_JOYSTICK_XINPUT, 1, [ ])
+                fi
+                if test x$have_dinput = xyes; then
+                    AC_DEFINE(SDL_JOYSTICK_DINPUT, 1, [ ])
+                    EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldinput8 -ldxguid -ldxerr8"
+                fi
             else
                 AC_DEFINE(SDL_JOYSTICK_WINMM, 1, [ ])
-                SOURCES="$SOURCES $srcdir/src/joystick/windows/SDL_mmjoystick.c"
             fi
+            SOURCES="$SOURCES $srcdir/src/joystick/windows/*.c"
             have_joystick=yes
         fi
         if test x$enable_haptic = xyes; then
-            if test x$have_dinput = xyes; then
-                AC_DEFINE(SDL_HAPTIC_DINPUT, 1, [ ])
+            if test x$have_dinput = xyes -o x$have_xinput = xyes; then
+                if test x$have_xinput = xyes; then
+                    AC_DEFINE(SDL_HAPTIC_XINPUT, 1, [ ])
+                fi
+                if test x$have_dinput = xyes; then
+                    AC_DEFINE(SDL_HAPTIC_DINPUT, 1, [ ])
+                fi
                 SOURCES="$SOURCES $srcdir/src/haptic/windows/SDL_syshaptic.c"
                 have_haptic=yes
             fi
--- a/include/SDL_config.h.in	Thu Jul 03 17:36:08 2014 -0300
+++ b/include/SDL_config.h.in	Thu Jul 03 15:39:55 2014 -0700
@@ -51,7 +51,11 @@
 #undef HAVE_GCC_SYNC_LOCK_TEST_AND_SET
 #undef HAVE_PTHREAD_SPINLOCK
 
+#undef HAVE_DDRAW_H
+#undef HAVE_DINPUT_H
+#undef HAVE_DSOUND_H
 #undef HAVE_DXGI_H
+#undef HAVE_XINPUT_H
 
 /* Comment this if you want to build without any C library requirements */
 #undef HAVE_LIBC
@@ -232,6 +236,7 @@
 #undef SDL_INPUT_TSLIB
 #undef SDL_JOYSTICK_HAIKU
 #undef SDL_JOYSTICK_DINPUT
+#undef SDL_JOYSTICK_XINPUT
 #undef SDL_JOYSTICK_DUMMY
 #undef SDL_JOYSTICK_IOKIT
 #undef SDL_JOYSTICK_LINUX
@@ -243,6 +248,7 @@
 #undef SDL_HAPTIC_LINUX
 #undef SDL_HAPTIC_IOKIT
 #undef SDL_HAPTIC_DINPUT
+#undef SDL_HAPTIC_XINPUT
 
 /* Enable various shared object loading systems */
 #undef SDL_LOADSO_HAIKU
--- a/include/SDL_config_windows.h	Thu Jul 03 17:36:08 2014 -0300
+++ b/include/SDL_config_windows.h	Thu Jul 03 15:39:55 2014 -0700
@@ -76,7 +76,11 @@
 # define SIZEOF_VOIDP 4
 #endif
 
+#define HAVE_DDRAW_H 1
+#define HAVE_DINPUT_H 1
+#define HAVE_DSOUND_H 1
 #define HAVE_DXGI_H 1
+#define HAVE_XINPUT_H 1
 
 /* This is disabled by default to avoid C runtime dependencies and manifest requirements */
 #ifdef HAVE_LIBC
@@ -158,7 +162,9 @@
 
 /* Enable various input drivers */
 #define SDL_JOYSTICK_DINPUT 1
+#define SDL_JOYSTICK_XINPUT 1
 #define SDL_HAPTIC_DINPUT   1
+#define SDL_HAPTIC_XINPUT   1
 
 /* Enable various shared object loading systems */
 #define SDL_LOADSO_WINDOWS  1
--- a/include/SDL_config_winrt.h	Thu Jul 03 17:36:08 2014 -0300
+++ b/include/SDL_config_winrt.h	Thu Jul 03 15:39:55 2014 -0700
@@ -78,6 +78,7 @@
 
 /* Useful headers */
 #define HAVE_DXGI_H 1
+#define HAVE_XINPUT_H 1
 #define HAVE_LIBC 1
 #define HAVE_STDIO_H 1
 #define STDC_HEADERS 1
@@ -148,13 +149,12 @@
 #define SDL_AUDIO_DRIVER_DUMMY	1
 
 /* Enable various input drivers */
-// TODO, WinRT: Get haptic support working
-#define SDL_HAPTIC_DISABLED	1
-
 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
 #define SDL_JOYSTICK_DISABLED 1
+#define SDL_HAPTIC_DISABLED	1
 #else
 #define SDL_JOYSTICK_XINPUT 1
+#define SDL_HAPTIC_XINPUT   1
 #endif
 
 /* Enable various shared object loading systems */
--- a/src/audio/directsound/SDL_directsound.h	Thu Jul 03 17:36:08 2014 -0300
+++ b/src/audio/directsound/SDL_directsound.h	Thu Jul 03 15:39:55 2014 -0700
@@ -23,7 +23,7 @@
 #ifndef _SDL_directsound_h
 #define _SDL_directsound_h
 
-#include "directx.h"
+#include "../../core/windows/SDL_directx.h"
 
 #include "../SDL_sysaudio.h"
 
--- a/src/audio/directsound/directx.h	Thu Jul 03 17:36:08 2014 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef _directx_h
-#define _directx_h
-
-/* Include all of the DirectX 8.0 headers and adds any necessary tweaks */
-
-#include "../../core/windows/SDL_windows.h"
-#include <mmsystem.h>
-#ifndef WIN32
-#define WIN32
-#endif
-#undef  WINNT
-
-/* Far pointers don't exist in 32-bit code */
-#ifndef FAR
-#define FAR
-#endif
-
-/* Error codes not yet included in Win32 API header files */
-#ifndef MAKE_HRESULT
-#define MAKE_HRESULT(sev,fac,code) \
-    ((HRESULT)(((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))))
-#endif
-
-#ifndef S_OK
-#define S_OK        (HRESULT)0x00000000L
-#endif
-
-#ifndef SUCCEEDED
-#define SUCCEEDED(x)    ((HRESULT)(x) >= 0)
-#endif
-#ifndef FAILED
-#define FAILED(x)   ((HRESULT)(x)<0)
-#endif
-
-#ifndef E_FAIL
-#define E_FAIL      (HRESULT)0x80000008L
-#endif
-#ifndef E_NOINTERFACE
-#define E_NOINTERFACE   (HRESULT)0x80004002L
-#endif
-#ifndef E_OUTOFMEMORY
-#define E_OUTOFMEMORY   (HRESULT)0x8007000EL
-#endif
-#ifndef E_INVALIDARG
-#define E_INVALIDARG    (HRESULT)0x80070057L
-#endif
-#ifndef E_NOTIMPL
-#define E_NOTIMPL   (HRESULT)0x80004001L
-#endif
-#ifndef REGDB_E_CLASSNOTREG
-#define REGDB_E_CLASSNOTREG (HRESULT)0x80040154L
-#endif
-
-/* Severity codes */
-#ifndef SEVERITY_ERROR
-#define SEVERITY_ERROR  1
-#endif
-
-/* Error facility codes */
-#ifndef FACILITY_WIN32
-#define FACILITY_WIN32  7
-#endif
-
-#ifndef FIELD_OFFSET
-#define FIELD_OFFSET(type, field)    ((LONG)&(((type *)0)->field))
-#endif
-
-/* DirectX headers (if it isn't included, I haven't tested it yet)
- */
-/* We need these defines to mark what version of DirectX API we use */
-#define DIRECTDRAW_VERSION  0x0700
-#define DIRECTSOUND_VERSION 0x0800
-#define DIRECTINPUT_VERSION 0x0500
-
-#include <ddraw.h>
-#include <dsound.h>
-#include <dinput.h>
-
-#endif /* _directx_h */
-
-/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/windows/SDL_directx.h	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,111 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef _SDL_directx_h
+#define _SDL_directx_h
+
+/* Include all of the DirectX 8.0 headers and adds any necessary tweaks */
+
+#include "SDL_windows.h"
+#include <mmsystem.h>
+#ifndef WIN32
+#define WIN32
+#endif
+#undef  WINNT
+
+/* Far pointers don't exist in 32-bit code */
+#ifndef FAR
+#define FAR
+#endif
+
+/* Error codes not yet included in Win32 API header files */
+#ifndef MAKE_HRESULT
+#define MAKE_HRESULT(sev,fac,code) \
+    ((HRESULT)(((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))))
+#endif
+
+#ifndef S_OK
+#define S_OK        (HRESULT)0x00000000L
+#endif
+
+#ifndef SUCCEEDED
+#define SUCCEEDED(x)    ((HRESULT)(x) >= 0)
+#endif
+#ifndef FAILED
+#define FAILED(x)   ((HRESULT)(x)<0)
+#endif
+
+#ifndef E_FAIL
+#define E_FAIL      (HRESULT)0x80000008L
+#endif
+#ifndef E_NOINTERFACE
+#define E_NOINTERFACE   (HRESULT)0x80004002L
+#endif
+#ifndef E_OUTOFMEMORY
+#define E_OUTOFMEMORY   (HRESULT)0x8007000EL
+#endif
+#ifndef E_INVALIDARG
+#define E_INVALIDARG    (HRESULT)0x80070057L
+#endif
+#ifndef E_NOTIMPL
+#define E_NOTIMPL   (HRESULT)0x80004001L
+#endif
+#ifndef REGDB_E_CLASSNOTREG
+#define REGDB_E_CLASSNOTREG (HRESULT)0x80040154L
+#endif
+
+/* Severity codes */
+#ifndef SEVERITY_ERROR
+#define SEVERITY_ERROR  1
+#endif
+
+/* Error facility codes */
+#ifndef FACILITY_WIN32
+#define FACILITY_WIN32  7
+#endif
+
+#ifndef FIELD_OFFSET
+#define FIELD_OFFSET(type, field)    ((LONG)&(((type *)0)->field))
+#endif
+
+/* DirectX headers (if it isn't included, I haven't tested it yet)
+ */
+/* We need these defines to mark what version of DirectX API we use */
+#define DIRECTDRAW_VERSION  0x0700
+#define DIRECTSOUND_VERSION 0x0800
+#define DIRECTINPUT_VERSION 0x0800 /* Need version 7 for force feedback. Need version 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */
+
+#ifdef HAVE_DDRAW_H
+#include <ddraw.h>
+#endif
+#ifdef HAVE_DSOUND_H
+#include <dsound.h>
+#endif
+#ifdef HAVE_DINPUT_H
+#include <dinput.h>
+#else
+typedef struct { int unused; } DIDEVICEINSTANCE;
+#endif
+
+#endif /* _SDL_directx_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/windows/SDL_xinput.c	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,94 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_assert.h"
+#include "SDL_xinput.h"
+
+
+#ifdef HAVE_XINPUT_H
+
+XInputGetState_t SDL_XInputGetState = NULL;
+XInputSetState_t SDL_XInputSetState = NULL;
+XInputGetCapabilities_t SDL_XInputGetCapabilities = NULL;
+DWORD SDL_XInputVersion = 0;
+
+static HANDLE s_pXInputDLL = 0;
+static int s_XInputDLLRefCount = 0;
+
+
+int
+WIN_LoadXInputDLL(void)
+{
+    DWORD version = 0;
+
+    if (s_pXInputDLL) {
+        SDL_assert(s_XInputDLLRefCount > 0);
+        s_XInputDLLRefCount++;
+        return 0;  /* already loaded */
+    }
+
+    version = (1 << 16) | 4;
+    s_pXInputDLL = LoadLibrary(L"XInput1_4.dll");  /* 1.4 Ships with Windows 8. */
+    if (!s_pXInputDLL) {
+        version = (1 << 16) | 3;
+        s_pXInputDLL = LoadLibrary(L"XInput1_3.dll");  /* 1.3 Ships with Vista and Win7, can be installed as a redistributable component. */
+    }
+    if (!s_pXInputDLL) {
+        s_pXInputDLL = LoadLibrary(L"bin\\XInput1_3.dll");
+    }
+    if (!s_pXInputDLL) {
+        return -1;
+    }
+
+    SDL_assert(s_XInputDLLRefCount == 0);
+    SDL_XInputVersion = version;
+    s_XInputDLLRefCount = 1;
+
+    /* 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think... */
+    SDL_XInputGetState = (XInputGetState_t)GetProcAddress((HMODULE)s_pXInputDLL, (LPCSTR)100);
+    SDL_XInputSetState = (XInputSetState_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputSetState");
+    SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputGetCapabilities");
+    if (!SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities) {
+        WIN_UnloadXInputDLL();
+        return -1;
+    }
+
+    return 0;
+}
+
+void
+WIN_UnloadXInputDLL(void)
+{
+    if (s_pXInputDLL) {
+        SDL_assert(s_XInputDLLRefCount > 0);
+        if (--s_XInputDLLRefCount == 0) {
+            FreeLibrary(s_pXInputDLL);
+            s_pXInputDLL = NULL;
+        }
+    } else {
+        SDL_assert(s_XInputDLLRefCount == 0);
+    }
+}
+
+#endif /* HAVE_XINPUT_H */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/windows/SDL_xinput.h	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,134 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef _SDL_xinput_h
+#define _SDL_xinput_h
+
+#ifdef HAVE_XINPUT_H
+
+#include "SDL_windows.h"
+#include <xinput.h>
+
+#ifndef XUSER_MAX_COUNT
+#define XUSER_MAX_COUNT 4
+#endif
+#ifndef XUSER_INDEX_ANY
+#define XUSER_INDEX_ANY     0x000000FF
+#endif
+#ifndef XINPUT_CAPS_FFB_SUPPORTED
+#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
+#endif
+
+#ifndef XINPUT_DEVSUBTYPE_UNKNOWN
+#define XINPUT_DEVSUBTYPE_UNKNOWN 0x00
+#endif
+#ifndef XINPUT_DEVSUBTYPE_GAMEPAD
+#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01
+#endif
+#ifndef XINPUT_DEVSUBTYPE_WHEEL
+#define XINPUT_DEVSUBTYPE_WHEEL 0x02
+#endif
+#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
+#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
+#endif
+#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
+#define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
+#endif
+#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
+#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
+#endif
+#ifndef XINPUT_DEVSUBTYPE_GUITAR
+#define XINPUT_DEVSUBTYPE_GUITAR 0x06
+#endif
+#ifndef XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE
+#define XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE 0x07
+#endif
+#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
+#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
+#endif
+#ifndef XINPUT_DEVSUBTYPE_GUITAR_BASS
+#define XINPUT_DEVSUBTYPE_GUITAR_BASS 0x0B
+#endif
+#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
+#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
+#endif
+
+#ifndef XINPUT_GAMEPAD_GUIDE
+#define XINPUT_GAMEPAD_GUIDE 0x0400
+#endif
+
+/* typedef's for XInput structs we use */
+typedef struct
+{
+    WORD wButtons;
+    BYTE bLeftTrigger;
+    BYTE bRightTrigger;
+    SHORT sThumbLX;
+    SHORT sThumbLY;
+    SHORT sThumbRX;
+    SHORT sThumbRY;
+    DWORD dwPaddingReserved;
+} XINPUT_GAMEPAD_EX;
+
+typedef struct
+{
+    DWORD dwPacketNumber;
+    XINPUT_GAMEPAD_EX Gamepad;
+} XINPUT_STATE_EX;
+
+/* Forward decl's for XInput API's we load dynamically and use if available */
+typedef DWORD (WINAPI *XInputGetState_t)
+    (
+    DWORD         dwUserIndex,  /* [in] Index of the gamer associated with the device */
+    XINPUT_STATE_EX* pState     /* [out] Receives the current state */
+    );
+
+typedef DWORD (WINAPI *XInputSetState_t)
+    (
+    DWORD             dwUserIndex,  /* [in] Index of the gamer associated with the device */
+    XINPUT_VIBRATION* pVibration    /* [in, out] The vibration information to send to the controller */
+    );
+
+typedef DWORD (WINAPI *XInputGetCapabilities_t)
+    (
+    DWORD                dwUserIndex,   /* [in] Index of the gamer associated with the device */
+    DWORD                dwFlags,       /* [in] Input flags that identify the device type */
+    XINPUT_CAPABILITIES* pCapabilities  /* [out] Receives the capabilities */
+    );
+
+extern int WIN_LoadXInputDLL(void);
+extern void WIN_UnloadXInputDLL(void);
+
+extern XInputGetState_t SDL_XInputGetState;
+extern XInputSetState_t SDL_XInputSetState;
+extern XInputGetCapabilities_t SDL_XInputGetCapabilities;
+extern DWORD SDL_XInputVersion;  /* ((major << 16) & 0xFF00) | (minor & 0xFF) */
+
+#define XINPUTGETSTATE          SDL_XInputGetState
+#define XINPUTSETSTATE          SDL_XInputSetState
+#define XINPUTGETCAPABILITIES   SDL_XInputGetCapabilities
+
+#endif /* HAVE_XINPUT_H */
+
+#endif /* _SDL_xinput_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/haptic/windows/SDL_dinputhaptic.c	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,1293 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_error.h"
+#include "SDL_haptic.h"
+#include "SDL_timer.h"
+#include "SDL_windowshaptic_c.h"
+#include "SDL_dinputhaptic_c.h"
+#include "../SDL_syshaptic.h"
+#include "../../joystick/windows/SDL_windowsjoystick_c.h"
+
+
+#if SDL_HAPTIC_DINPUT
+
+/*
+ * External stuff.
+ */
+extern HWND SDL_HelperWindow;
+
+
+/*
+ * Internal stuff.
+ */
+static SDL_bool coinitialized = SDL_FALSE;
+static LPDIRECTINPUT8 dinput = NULL;
+
+
+/*
+ * Like SDL_SetError but for DX error codes.
+ */
+static int
+DI_SetError(const char *str, HRESULT err)
+{
+    /*
+       SDL_SetError("Haptic: %s - %s: %s", str,
+       DXGetErrorString8A(err), DXGetErrorDescription8A(err));
+     */
+    return SDL_SetError("Haptic error %s", str);
+}
+
+/*
+ * Checks to see if two GUID are the same.
+ */
+static int
+DI_GUIDIsSame(const GUID * a, const GUID * b)
+{
+    return (SDL_memcmp(a, b, sizeof (GUID)) == 0);
+}
+
+/*
+ * Callback to find the haptic devices.
+ */
+static BOOL CALLBACK
+EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
+{
+    (void) pContext;
+    SDL_DINPUT_MaybeAddDevice(pdidInstance);
+    return DIENUM_CONTINUE;  /* continue enumerating */
+}
+
+int
+SDL_DINPUT_HapticInit(void)
+{
+    HRESULT ret;
+    HINSTANCE instance;
+
+    if (dinput != NULL) {       /* Already open. */
+        return SDL_SetError("Haptic: SubSystem already open.");
+    }
+
+    ret = WIN_CoInitialize();
+    if (FAILED(ret)) {
+        return DI_SetError("Coinitialize", ret);
+    }
+
+    coinitialized = SDL_TRUE;
+
+    ret = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
+        &IID_IDirectInput8, (LPVOID)& dinput);
+    if (FAILED(ret)) {
+        SDL_SYS_HapticQuit();
+        return DI_SetError("CoCreateInstance", ret);
+    }
+
+    /* Because we used CoCreateInstance, we need to Initialize it, first. */
+    instance = GetModuleHandle(NULL);
+    if (instance == NULL) {
+        SDL_SYS_HapticQuit();
+        return SDL_SetError("GetModuleHandle() failed with error code %d.",
+            GetLastError());
+    }
+    ret = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
+    if (FAILED(ret)) {
+        SDL_SYS_HapticQuit();
+        return DI_SetError("Initializing DirectInput device", ret);
+    }
+
+    /* Look for haptic devices. */
+    ret = IDirectInput8_EnumDevices(dinput,
+        0,
+        EnumHapticsCallback,
+        NULL,
+        DIEDFL_FORCEFEEDBACK |
+        DIEDFL_ATTACHEDONLY);
+    if (FAILED(ret)) {
+        SDL_SYS_HapticQuit();
+        return DI_SetError("Enumerating DirectInput devices", ret);
+    }
+    return 0;
+}
+
+int
+SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
+{
+    HRESULT ret;
+    LPDIRECTINPUTDEVICE8 device;
+    const DWORD needflags = DIDC_ATTACHED | DIDC_FORCEFEEDBACK;
+    DIDEVCAPS capabilities;
+    SDL_hapticlist_item *item = NULL;
+
+    if (dinput == NULL) {
+        return -1;  /* not initialized. We'll pick these up on enumeration if we init later. */
+    }
+
+    /* Make sure we don't already have it */
+    for (item = SDL_hapticlist; item; item = item->next) {
+        if ((!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0)) {
+            return -1;  /* Already added */
+        }
+    }
+
+    /* Open the device */
+    ret = IDirectInput8_CreateDevice(dinput, &pdidInstance->guidInstance, &device, NULL);
+    if (FAILED(ret)) {
+        /* DI_SetError("Creating DirectInput device",ret); */
+        return -1;
+    }
+
+    /* Get capabilities. */
+    SDL_zero(capabilities);
+    capabilities.dwSize = sizeof(DIDEVCAPS);
+    ret = IDirectInputDevice8_GetCapabilities(device, &capabilities);
+    IDirectInputDevice8_Release(device);
+    if (FAILED(ret)) {
+        /* DI_SetError("Getting device capabilities",ret); */
+        return -1;
+    }
+
+    if ((capabilities.dwFlags & needflags) != needflags) {
+        return -1;  /* not a device we can use. */
+    }
+
+    item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item));
+    if (item == NULL) {
+        return SDL_OutOfMemory();
+    }
+
+    item->name = WIN_StringToUTF8(pdidInstance->tszProductName);
+    if (!item->name) {
+        SDL_free(item);
+        return -1;
+    }
+
+    /* Copy the instance over, useful for creating devices. */
+    SDL_memcpy(&item->instance, pdidInstance, sizeof(DIDEVICEINSTANCE));
+    SDL_memcpy(&item->capabilities, &capabilities, sizeof(capabilities));
+
+    return SDL_SYS_AddHapticDevice(item);
+}
+
+int
+SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
+{
+    SDL_hapticlist_item *item;
+    SDL_hapticlist_item *prev = NULL;
+
+    if (dinput == NULL) {
+        return -1;  /* not initialized, ignore this. */
+    }
+
+    for (item = SDL_hapticlist; item != NULL; item = item->next) {
+        if (!item->bXInputHaptic && SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) {
+            /* found it, remove it. */
+            return SDL_SYS_RemoveHapticDevice(prev, item);
+        }
+        prev = item;
+    }
+    return -1;
+}
+
+/*
+ * Callback to get supported axes.
+ */
+static BOOL CALLBACK
+DI_DeviceObjectCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
+{
+    SDL_Haptic *haptic = (SDL_Haptic *) pvRef;
+
+    if ((dev->dwType & DIDFT_AXIS) && (dev->dwFlags & DIDOI_FFACTUATOR)) {
+        const GUID *guid = &dev->guidType;
+        DWORD offset = 0;
+        if (DI_GUIDIsSame(guid, &GUID_XAxis)) {
+            offset = DIJOFS_X;
+        } else if (DI_GUIDIsSame(guid, &GUID_YAxis)) {
+            offset = DIJOFS_Y;
+        } else if (DI_GUIDIsSame(guid, &GUID_ZAxis)) {
+            offset = DIJOFS_Z;
+        } else if (DI_GUIDIsSame(guid, &GUID_RxAxis)) {
+            offset = DIJOFS_RX;
+        } else if (DI_GUIDIsSame(guid, &GUID_RyAxis)) {
+            offset = DIJOFS_RY;
+        } else if (DI_GUIDIsSame(guid, &GUID_RzAxis)) {
+            offset = DIJOFS_RZ;
+        } else {
+            return DIENUM_CONTINUE;   /* can't use this, go on. */
+        }
+
+        haptic->hwdata->axes[haptic->naxes] = offset;
+        haptic->naxes++;
+
+        /* Currently using the artificial limit of 3 axes. */
+        if (haptic->naxes >= 3) {
+            return DIENUM_STOP;
+        }
+    }
+
+    return DIENUM_CONTINUE;
+}
+
+/*
+ * Callback to get all supported effects.
+ */
+#define EFFECT_TEST(e,s)               \
+if (DI_GUIDIsSame(&pei->guid, &(e)))   \
+   haptic->supported |= (s)
+static BOOL CALLBACK
+DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv)
+{
+    /* Prepare the haptic device. */
+    SDL_Haptic *haptic = (SDL_Haptic *) pv;
+
+    /* Get supported. */
+    EFFECT_TEST(GUID_Spring, SDL_HAPTIC_SPRING);
+    EFFECT_TEST(GUID_Damper, SDL_HAPTIC_DAMPER);
+    EFFECT_TEST(GUID_Inertia, SDL_HAPTIC_INERTIA);
+    EFFECT_TEST(GUID_Friction, SDL_HAPTIC_FRICTION);
+    EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT);
+    EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM);
+    EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE);
+    /* !!! 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);
+    EFFECT_TEST(GUID_RampForce, SDL_HAPTIC_RAMP);
+
+    /* Check for more. */
+    return DIENUM_CONTINUE;
+}
+
+/*
+ * Opens the haptic device.
+ *
+ *    Steps:
+ *       - Set cooperative level.
+ *       - Set data format.
+ *       - Acquire exclusiveness.
+ *       - Reset actuators.
+ *       - Get supported features.
+ */
+static int
+SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic * haptic, LPDIRECTINPUTDEVICE8 device8, SDL_bool is_joystick)
+{
+    HRESULT ret;
+    DIPROPDWORD dipdw;
+
+    /* Allocate the hwdata */
+    haptic->hwdata = (struct haptic_hwdata *)SDL_malloc(sizeof(*haptic->hwdata));
+    if (haptic->hwdata == NULL) {
+        return SDL_OutOfMemory();
+    }
+    SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
+
+    /* We'll use the device8 from now on. */
+    haptic->hwdata->device = device8;
+    haptic->hwdata->is_joystick = is_joystick;
+
+    /* !!! FIXME: opening a haptic device here first will make an attempt to
+       !!! FIXME:  SDL_JoystickOpen() that same device fail later, since we
+       !!! FIXME:  have it open in exclusive mode. But this will allow
+       !!! FIXME:  SDL_JoystickOpen() followed by SDL_HapticOpenFromJoystick()
+       !!! FIXME:  to work, and that's probably the common case. Still,
+       !!! FIXME:  ideally, We need to unify the opening code. */
+
+    if (!is_joystick) {  /* if is_joystick, we already set this up elsewhere. */
+        /* Grab it exclusively to use force feedback stuff. */
+        ret = IDirectInputDevice8_SetCooperativeLevel(haptic->hwdata->device,
+                                                      SDL_HelperWindow,
+                                                      DISCL_EXCLUSIVE |
+                                                      DISCL_BACKGROUND);
+        if (FAILED(ret)) {
+            DI_SetError("Setting cooperative level to exclusive", ret);
+            goto acquire_err;
+        }
+
+        /* Set data format. */
+        ret = IDirectInputDevice8_SetDataFormat(haptic->hwdata->device,
+                                                &c_dfDIJoystick2);
+        if (FAILED(ret)) {
+            DI_SetError("Setting data format", ret);
+            goto acquire_err;
+        }
+
+        /* Get number of axes. */
+        ret = IDirectInputDevice8_EnumObjects(haptic->hwdata->device,
+                                              DI_DeviceObjectCallback,
+                                              haptic, DIDFT_AXIS);
+        if (FAILED(ret)) {
+            DI_SetError("Getting device axes", ret);
+            goto acquire_err;
+        }
+
+        /* Acquire the device. */
+        ret = IDirectInputDevice8_Acquire(haptic->hwdata->device);
+        if (FAILED(ret)) {
+            DI_SetError("Acquiring DirectInput device", ret);
+            goto acquire_err;
+        }
+    }
+
+    /* Reset all actuators - just in case. */
+    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
+                                                       DISFFC_RESET);
+    if (FAILED(ret)) {
+        DI_SetError("Resetting device", ret);
+        goto acquire_err;
+    }
+
+    /* Enabling actuators. */
+    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
+                                                       DISFFC_SETACTUATORSON);
+    if (FAILED(ret)) {
+        DI_SetError("Enabling actuators", ret);
+        goto acquire_err;
+    }
+
+    /* Get supported effects. */
+    ret = IDirectInputDevice8_EnumEffects(haptic->hwdata->device,
+                                          DI_EffectCallback, haptic,
+                                          DIEFT_ALL);
+    if (FAILED(ret)) {
+        DI_SetError("Enumerating supported effects", ret);
+        goto acquire_err;
+    }
+    if (haptic->supported == 0) {       /* Error since device supports nothing. */
+        SDL_SetError("Haptic: Internal error on finding supported effects.");
+        goto acquire_err;
+    }
+
+    /* Check autogain and autocenter. */
+    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
+    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+    dipdw.diph.dwObj = 0;
+    dipdw.diph.dwHow = DIPH_DEVICE;
+    dipdw.dwData = 10000;
+    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
+                                          DIPROP_FFGAIN, &dipdw.diph);
+    if (!FAILED(ret)) {         /* Gain is supported. */
+        haptic->supported |= SDL_HAPTIC_GAIN;
+    }
+    dipdw.diph.dwObj = 0;
+    dipdw.diph.dwHow = DIPH_DEVICE;
+    dipdw.dwData = DIPROPAUTOCENTER_OFF;
+    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
+                                          DIPROP_AUTOCENTER, &dipdw.diph);
+    if (!FAILED(ret)) {         /* Autocenter is supported. */
+        haptic->supported |= SDL_HAPTIC_AUTOCENTER;
+    }
+
+    /* Status is always supported. */
+    haptic->supported |= SDL_HAPTIC_STATUS | SDL_HAPTIC_PAUSE;
+
+    /* Check maximum effects. */
+    haptic->neffects = 128;     /* This is not actually supported as thus under windows,
+                                   there is no way to tell the number of EFFECTS that a
+                                   device can hold, so we'll just use a "random" number
+                                   instead and put warnings in SDL_haptic.h */
+    haptic->nplaying = 128;     /* Even more impossible to get this then neffects. */
+
+    /* Prepare effects memory. */
+    haptic->effects = (struct haptic_effect *)
+        SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
+    if (haptic->effects == NULL) {
+        SDL_OutOfMemory();
+        goto acquire_err;
+    }
+    /* Clear the memory */
+    SDL_memset(haptic->effects, 0,
+               sizeof(struct haptic_effect) * haptic->neffects);
+
+    return 0;
+
+    /* Error handling */
+  acquire_err:
+    IDirectInputDevice8_Unacquire(haptic->hwdata->device);
+    return -1;
+}
+
+int
+SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
+{
+    HRESULT ret;
+    LPDIRECTINPUTDEVICE8 device;
+    LPDIRECTINPUTDEVICE8 device8;
+
+    /* Open the device */
+    ret = IDirectInput8_CreateDevice(dinput, &item->instance.guidInstance,
+        &device, NULL);
+    if (FAILED(ret)) {
+        DI_SetError("Creating DirectInput device", ret);
+        return -1;
+    }
+
+    /* Now get the IDirectInputDevice8 interface, instead. */
+    ret = IDirectInputDevice8_QueryInterface(device,
+        &IID_IDirectInputDevice8,
+        (LPVOID *)&device8);
+    /* Done with the temporary one now. */
+    IDirectInputDevice8_Release(device);
+    if (FAILED(ret)) {
+        DI_SetError("Querying DirectInput interface", ret);
+        return -1;
+    }
+
+    if (SDL_DINPUT_HapticOpenFromDevice(haptic, device8, SDL_FALSE) < 0) {
+        IDirectInputDevice8_Release(device8);
+        return -1;
+    }
+    return 0;
+}
+
+int
+SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+    HRESULT ret;
+    DIDEVICEINSTANCE hap_instance, joy_instance;
+
+    hap_instance.dwSize = sizeof(DIDEVICEINSTANCE);
+    joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
+
+    /* Get the device instances. */
+    ret = IDirectInputDevice8_GetDeviceInfo(haptic->hwdata->device,
+        &hap_instance);
+    if (FAILED(ret)) {
+        return 0;
+    }
+    ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice,
+        &joy_instance);
+    if (FAILED(ret)) {
+        return 0;
+    }
+
+    return DI_GUIDIsSame(&hap_instance.guidInstance, &joy_instance.guidInstance);
+}
+
+int
+SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+    SDL_hapticlist_item *item;
+    int index = 0;
+    HRESULT ret;
+    DIDEVICEINSTANCE joy_instance;
+
+    joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
+    ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice, &joy_instance);
+    if (FAILED(ret)) {
+        return -1;
+    }
+
+    /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
+    for (item = SDL_hapticlist; item != NULL; item = item->next) {
+        if (!item->bXInputHaptic && DI_GUIDIsSame(&item->instance.guidInstance, &joy_instance.guidInstance)) {
+            haptic->index = index;
+            return SDL_DINPUT_HapticOpenFromDevice(haptic, joystick->hwdata->InputDevice, SDL_TRUE);
+        }
+        ++index;
+    }
+
+    SDL_SetError("Couldn't find joystick in haptic device list");
+    return -1;
+}
+
+void
+SDL_DINPUT_HapticClose(SDL_Haptic * haptic)
+{
+    IDirectInputDevice8_Unacquire(haptic->hwdata->device);
+
+    /* Only release if isn't grabbed by a joystick. */
+    if (haptic->hwdata->is_joystick == 0) {
+        IDirectInputDevice8_Release(haptic->hwdata->device);
+    }
+}
+
+void
+SDL_DINPUT_HapticQuit(void)
+{
+    if (dinput != NULL) {
+        IDirectInput8_Release(dinput);
+        dinput = NULL;
+    }
+
+    if (coinitialized) {
+        WIN_CoUninitialize();
+        coinitialized = SDL_FALSE;
+    }
+}
+
+/*
+ * Converts an SDL trigger button to an DIEFFECT trigger button.
+ */
+static DWORD
+DIGetTriggerButton(Uint16 button)
+{
+    DWORD dwTriggerButton;
+
+    dwTriggerButton = DIEB_NOTRIGGER;
+
+    if (button != 0) {
+        dwTriggerButton = DIJOFS_BUTTON(button - 1);
+    }
+
+    return dwTriggerButton;
+}
+
+
+/*
+ * Sets the direction.
+ */
+static int
+SDL_SYS_SetDirection(DIEFFECT * effect, SDL_HapticDirection * dir, int naxes)
+{
+    LONG *rglDir;
+
+    /* Handle no axes a part. */
+    if (naxes == 0) {
+        effect->dwFlags |= DIEFF_SPHERICAL;     /* Set as default. */
+        effect->rglDirection = NULL;
+        return 0;
+    }
+
+    /* Has axes. */
+    rglDir = SDL_malloc(sizeof(LONG) * naxes);
+    if (rglDir == NULL) {
+        return SDL_OutOfMemory();
+    }
+    SDL_memset(rglDir, 0, sizeof(LONG) * naxes);
+    effect->rglDirection = rglDir;
+
+    switch (dir->type) {
+    case SDL_HAPTIC_POLAR:
+        effect->dwFlags |= DIEFF_POLAR;
+        rglDir[0] = dir->dir[0];
+        return 0;
+    case SDL_HAPTIC_CARTESIAN:
+        effect->dwFlags |= DIEFF_CARTESIAN;
+        rglDir[0] = dir->dir[0];
+        if (naxes > 1)
+            rglDir[1] = dir->dir[1];
+        if (naxes > 2)
+            rglDir[2] = dir->dir[2];
+        return 0;
+    case SDL_HAPTIC_SPHERICAL:
+        effect->dwFlags |= DIEFF_SPHERICAL;
+        rglDir[0] = dir->dir[0];
+        if (naxes > 1)
+            rglDir[1] = dir->dir[1];
+        if (naxes > 2)
+            rglDir[2] = dir->dir[2];
+        return 0;
+
+    default:
+        return SDL_SetError("Haptic: Unknown direction type.");
+    }
+}
+
+#define CONVERT(x)   (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
+/*
+ * Creates the DIEFFECT from a SDL_HapticEffect.
+ */
+static int
+SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
+                   SDL_HapticEffect * src)
+{
+    int i;
+    DICONSTANTFORCE *constant;
+    DIPERIODIC *periodic;
+    DICONDITION *condition;     /* Actually an array of conditions - one per axis. */
+    DIRAMPFORCE *ramp;
+    DICUSTOMFORCE *custom;
+    DIENVELOPE *envelope;
+    SDL_HapticConstant *hap_constant;
+    SDL_HapticPeriodic *hap_periodic;
+    SDL_HapticCondition *hap_condition;
+    SDL_HapticRamp *hap_ramp;
+    SDL_HapticCustom *hap_custom;
+    DWORD *axes;
+
+    /* Set global stuff. */
+    SDL_memset(dest, 0, sizeof(DIEFFECT));
+    dest->dwSize = sizeof(DIEFFECT);    /* Set the structure size. */
+    dest->dwSamplePeriod = 0;   /* Not used by us. */
+    dest->dwGain = 10000;       /* Gain is set globally, not locally. */
+    dest->dwFlags = DIEFF_OBJECTOFFSETS;        /* Seems obligatory. */
+
+    /* Envelope. */
+    envelope = SDL_malloc(sizeof(DIENVELOPE));
+    if (envelope == NULL) {
+        return SDL_OutOfMemory();
+    }
+    SDL_memset(envelope, 0, sizeof(DIENVELOPE));
+    dest->lpEnvelope = envelope;
+    envelope->dwSize = sizeof(DIENVELOPE);      /* Always should be this. */
+
+    /* Axes. */
+    dest->cAxes = haptic->naxes;
+    if (dest->cAxes > 0) {
+        axes = SDL_malloc(sizeof(DWORD) * dest->cAxes);
+        if (axes == NULL) {
+            return SDL_OutOfMemory();
+        }
+        axes[0] = haptic->hwdata->axes[0];      /* Always at least one axis. */
+        if (dest->cAxes > 1) {
+            axes[1] = haptic->hwdata->axes[1];
+        }
+        if (dest->cAxes > 2) {
+            axes[2] = haptic->hwdata->axes[2];
+        }
+        dest->rgdwAxes = axes;
+    }
+
+    /* The big type handling switch, even bigger than Linux's version. */
+    switch (src->type) {
+    case SDL_HAPTIC_CONSTANT:
+        hap_constant = &src->constant;
+        constant = SDL_malloc(sizeof(DICONSTANTFORCE));
+        if (constant == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(constant, 0, sizeof(DICONSTANTFORCE));
+
+        /* Specifics */
+        constant->lMagnitude = CONVERT(hap_constant->level);
+        dest->cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
+        dest->lpvTypeSpecificParams = constant;
+
+        /* Generics */
+        dest->dwDuration = hap_constant->length * 1000; /* In microseconds. */
+        dest->dwTriggerButton = DIGetTriggerButton(hap_constant->button);
+        dest->dwTriggerRepeatInterval = hap_constant->interval;
+        dest->dwStartDelay = hap_constant->delay * 1000;        /* In microseconds. */
+
+        /* Direction. */
+        if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes) < 0) {
+            return -1;
+        }
+
+        /* Envelope */
+        if ((hap_constant->attack_length == 0)
+            && (hap_constant->fade_length == 0)) {
+            SDL_free(dest->lpEnvelope);
+            dest->lpEnvelope = NULL;
+        } else {
+            envelope->dwAttackLevel = CONVERT(hap_constant->attack_level);
+            envelope->dwAttackTime = hap_constant->attack_length * 1000;
+            envelope->dwFadeLevel = CONVERT(hap_constant->fade_level);
+            envelope->dwFadeTime = hap_constant->fade_length * 1000;
+        }
+
+        break;
+
+    case SDL_HAPTIC_SINE:
+    /* !!! 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:
+        hap_periodic = &src->periodic;
+        periodic = SDL_malloc(sizeof(DIPERIODIC));
+        if (periodic == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(periodic, 0, sizeof(DIPERIODIC));
+
+        /* Specifics */
+        periodic->dwMagnitude = CONVERT(hap_periodic->magnitude);
+        periodic->lOffset = CONVERT(hap_periodic->offset);
+        periodic->dwPhase = hap_periodic->phase;
+        periodic->dwPeriod = hap_periodic->period * 1000;
+        dest->cbTypeSpecificParams = sizeof(DIPERIODIC);
+        dest->lpvTypeSpecificParams = periodic;
+
+        /* Generics */
+        dest->dwDuration = hap_periodic->length * 1000; /* In microseconds. */
+        dest->dwTriggerButton = DIGetTriggerButton(hap_periodic->button);
+        dest->dwTriggerRepeatInterval = hap_periodic->interval;
+        dest->dwStartDelay = hap_periodic->delay * 1000;        /* In microseconds. */
+
+        /* Direction. */
+        if (SDL_SYS_SetDirection(dest, &hap_periodic->direction, dest->cAxes)
+            < 0) {
+            return -1;
+        }
+
+        /* Envelope */
+        if ((hap_periodic->attack_length == 0)
+            && (hap_periodic->fade_length == 0)) {
+            SDL_free(dest->lpEnvelope);
+            dest->lpEnvelope = NULL;
+        } else {
+            envelope->dwAttackLevel = CONVERT(hap_periodic->attack_level);
+            envelope->dwAttackTime = hap_periodic->attack_length * 1000;
+            envelope->dwFadeLevel = CONVERT(hap_periodic->fade_level);
+            envelope->dwFadeTime = hap_periodic->fade_length * 1000;
+        }
+
+        break;
+
+    case SDL_HAPTIC_SPRING:
+    case SDL_HAPTIC_DAMPER:
+    case SDL_HAPTIC_INERTIA:
+    case SDL_HAPTIC_FRICTION:
+        hap_condition = &src->condition;
+        condition = SDL_malloc(sizeof(DICONDITION) * dest->cAxes);
+        if (condition == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(condition, 0, sizeof(DICONDITION));
+
+        /* Specifics */
+        for (i = 0; i < (int) dest->cAxes; i++) {
+            condition[i].lOffset = CONVERT(hap_condition->center[i]);
+            condition[i].lPositiveCoefficient =
+                CONVERT(hap_condition->right_coeff[i]);
+            condition[i].lNegativeCoefficient =
+                CONVERT(hap_condition->left_coeff[i]);
+            condition[i].dwPositiveSaturation =
+                CONVERT(hap_condition->right_sat[i]);
+            condition[i].dwNegativeSaturation =
+                CONVERT(hap_condition->left_sat[i]);
+            condition[i].lDeadBand = CONVERT(hap_condition->deadband[i]);
+        }
+        dest->cbTypeSpecificParams = sizeof(DICONDITION) * dest->cAxes;
+        dest->lpvTypeSpecificParams = condition;
+
+        /* Generics */
+        dest->dwDuration = hap_condition->length * 1000;        /* In microseconds. */
+        dest->dwTriggerButton = DIGetTriggerButton(hap_condition->button);
+        dest->dwTriggerRepeatInterval = hap_condition->interval;
+        dest->dwStartDelay = hap_condition->delay * 1000;       /* In microseconds. */
+
+        /* Direction. */
+        if (SDL_SYS_SetDirection(dest, &hap_condition->direction, dest->cAxes)
+            < 0) {
+            return -1;
+        }
+
+        /* Envelope - Not actually supported by most CONDITION implementations. */
+        SDL_free(dest->lpEnvelope);
+        dest->lpEnvelope = NULL;
+
+        break;
+
+    case SDL_HAPTIC_RAMP:
+        hap_ramp = &src->ramp;
+        ramp = SDL_malloc(sizeof(DIRAMPFORCE));
+        if (ramp == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(ramp, 0, sizeof(DIRAMPFORCE));
+
+        /* Specifics */
+        ramp->lStart = CONVERT(hap_ramp->start);
+        ramp->lEnd = CONVERT(hap_ramp->end);
+        dest->cbTypeSpecificParams = sizeof(DIRAMPFORCE);
+        dest->lpvTypeSpecificParams = ramp;
+
+        /* Generics */
+        dest->dwDuration = hap_ramp->length * 1000;     /* In microseconds. */
+        dest->dwTriggerButton = DIGetTriggerButton(hap_ramp->button);
+        dest->dwTriggerRepeatInterval = hap_ramp->interval;
+        dest->dwStartDelay = hap_ramp->delay * 1000;    /* In microseconds. */
+
+        /* Direction. */
+        if (SDL_SYS_SetDirection(dest, &hap_ramp->direction, dest->cAxes) < 0) {
+            return -1;
+        }
+
+        /* Envelope */
+        if ((hap_ramp->attack_length == 0) && (hap_ramp->fade_length == 0)) {
+            SDL_free(dest->lpEnvelope);
+            dest->lpEnvelope = NULL;
+        } else {
+            envelope->dwAttackLevel = CONVERT(hap_ramp->attack_level);
+            envelope->dwAttackTime = hap_ramp->attack_length * 1000;
+            envelope->dwFadeLevel = CONVERT(hap_ramp->fade_level);
+            envelope->dwFadeTime = hap_ramp->fade_length * 1000;
+        }
+
+        break;
+
+    case SDL_HAPTIC_CUSTOM:
+        hap_custom = &src->custom;
+        custom = SDL_malloc(sizeof(DICUSTOMFORCE));
+        if (custom == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(custom, 0, sizeof(DICUSTOMFORCE));
+
+        /* Specifics */
+        custom->cChannels = hap_custom->channels;
+        custom->dwSamplePeriod = hap_custom->period * 1000;
+        custom->cSamples = hap_custom->samples;
+        custom->rglForceData =
+            SDL_malloc(sizeof(LONG) * custom->cSamples * custom->cChannels);
+        for (i = 0; i < hap_custom->samples * hap_custom->channels; i++) {      /* Copy data. */
+            custom->rglForceData[i] = CONVERT(hap_custom->data[i]);
+        }
+        dest->cbTypeSpecificParams = sizeof(DICUSTOMFORCE);
+        dest->lpvTypeSpecificParams = custom;
+
+        /* Generics */
+        dest->dwDuration = hap_custom->length * 1000;   /* In microseconds. */
+        dest->dwTriggerButton = DIGetTriggerButton(hap_custom->button);
+        dest->dwTriggerRepeatInterval = hap_custom->interval;
+        dest->dwStartDelay = hap_custom->delay * 1000;  /* In microseconds. */
+
+        /* Direction. */
+        if (SDL_SYS_SetDirection(dest, &hap_custom->direction, dest->cAxes) < 0) {
+            return -1;
+        }
+
+        /* Envelope */
+        if ((hap_custom->attack_length == 0)
+            && (hap_custom->fade_length == 0)) {
+            SDL_free(dest->lpEnvelope);
+            dest->lpEnvelope = NULL;
+        } else {
+            envelope->dwAttackLevel = CONVERT(hap_custom->attack_level);
+            envelope->dwAttackTime = hap_custom->attack_length * 1000;
+            envelope->dwFadeLevel = CONVERT(hap_custom->fade_level);
+            envelope->dwFadeTime = hap_custom->fade_length * 1000;
+        }
+
+        break;
+
+    default:
+        return SDL_SetError("Haptic: Unknown effect type.");
+    }
+
+    return 0;
+}
+
+
+/*
+ * Frees an DIEFFECT allocated by SDL_SYS_ToDIEFFECT.
+ */
+static void
+SDL_SYS_HapticFreeDIEFFECT(DIEFFECT * effect, int type)
+{
+    DICUSTOMFORCE *custom;
+
+    SDL_free(effect->lpEnvelope);
+    effect->lpEnvelope = NULL;
+    SDL_free(effect->rgdwAxes);
+    effect->rgdwAxes = NULL;
+    if (effect->lpvTypeSpecificParams != NULL) {
+        if (type == SDL_HAPTIC_CUSTOM) {        /* Must free the custom data. */
+            custom = (DICUSTOMFORCE *) effect->lpvTypeSpecificParams;
+            SDL_free(custom->rglForceData);
+            custom->rglForceData = NULL;
+        }
+        SDL_free(effect->lpvTypeSpecificParams);
+        effect->lpvTypeSpecificParams = NULL;
+    }
+    SDL_free(effect->rglDirection);
+    effect->rglDirection = NULL;
+}
+
+/*
+ * Gets the effect type from the generic SDL haptic effect wrapper.
+ */
+static REFGUID
+SDL_SYS_HapticEffectType(SDL_HapticEffect * effect)
+{
+    switch (effect->type) {
+    case SDL_HAPTIC_CONSTANT:
+        return &GUID_ConstantForce;
+
+    case SDL_HAPTIC_RAMP:
+        return &GUID_RampForce;
+
+    /* !!! 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;
+
+    case SDL_HAPTIC_TRIANGLE:
+        return &GUID_Triangle;
+
+    case SDL_HAPTIC_SAWTOOTHUP:
+        return &GUID_SawtoothUp;
+
+    case SDL_HAPTIC_SAWTOOTHDOWN:
+        return &GUID_SawtoothDown;
+
+    case SDL_HAPTIC_SPRING:
+        return &GUID_Spring;
+
+    case SDL_HAPTIC_DAMPER:
+        return &GUID_Damper;
+
+    case SDL_HAPTIC_INERTIA:
+        return &GUID_Inertia;
+
+    case SDL_HAPTIC_FRICTION:
+        return &GUID_Friction;
+
+    case SDL_HAPTIC_CUSTOM:
+        return &GUID_CustomForce;
+
+    default:
+        return NULL;
+    }
+}
+int
+SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
+{
+    HRESULT ret;
+    REFGUID type = SDL_SYS_HapticEffectType(base);
+
+    if (type == NULL) {
+        SDL_SetError("Haptic: Unknown effect type.");
+        return -1;
+    }
+
+    /* Get the effect. */
+    if (SDL_SYS_ToDIEFFECT(haptic, &effect->hweffect->effect, base) < 0) {
+        goto err_effectdone;
+    }
+
+    /* Create the actual effect. */
+    ret = IDirectInputDevice8_CreateEffect(haptic->hwdata->device, type,
+        &effect->hweffect->effect,
+        &effect->hweffect->ref, NULL);
+    if (FAILED(ret)) {
+        DI_SetError("Unable to create effect", ret);
+        goto err_effectdone;
+    }
+
+    return 0;
+
+err_effectdone:
+    SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, base->type);
+    return -1;
+}
+
+int
+SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
+{
+    HRESULT ret;
+    DWORD flags;
+    DIEFFECT temp;
+
+    /* Get the effect. */
+    SDL_memset(&temp, 0, sizeof(DIEFFECT));
+    if (SDL_SYS_ToDIEFFECT(haptic, &temp, data) < 0) {
+        goto err_update;
+    }
+
+    /* Set the flags.  Might be worthwhile to diff temp with loaded effect and
+    *  only change those parameters. */
+    flags = DIEP_DIRECTION |
+        DIEP_DURATION |
+        DIEP_ENVELOPE |
+        DIEP_STARTDELAY |
+        DIEP_TRIGGERBUTTON |
+        DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS;
+
+    /* Create the actual effect. */
+    ret =
+        IDirectInputEffect_SetParameters(effect->hweffect->ref, &temp, flags);
+    if (FAILED(ret)) {
+        DI_SetError("Unable to update effect", ret);
+        goto err_update;
+    }
+
+    /* Copy it over. */
+    SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, data->type);
+    SDL_memcpy(&effect->hweffect->effect, &temp, sizeof(DIEFFECT));
+
+    return 0;
+
+err_update:
+    SDL_SYS_HapticFreeDIEFFECT(&temp, data->type);
+    return -1;
+}
+
+int
+SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
+{
+    HRESULT ret;
+    DWORD iter;
+
+    /* Check if it's infinite. */
+    if (iterations == SDL_HAPTIC_INFINITY) {
+        iter = INFINITE;
+    } else {
+        iter = iterations;
+    }
+
+    /* Run the effect. */
+    ret = IDirectInputEffect_Start(effect->hweffect->ref, iter, 0);
+    if (FAILED(ret)) {
+        return DI_SetError("Running the effect", ret);
+    }
+    return 0;
+}
+
+int
+SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    HRESULT ret;
+
+    ret = IDirectInputEffect_Stop(effect->hweffect->ref);
+    if (FAILED(ret)) {
+        return DI_SetError("Unable to stop effect", ret);
+    }
+    return 0;
+}
+
+void
+SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    HRESULT ret;
+
+    ret = IDirectInputEffect_Unload(effect->hweffect->ref);
+    if (FAILED(ret)) {
+        DI_SetError("Removing effect from the device", ret);
+    }
+    SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, effect->effect.type);
+}
+
+int
+SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    HRESULT ret;
+    DWORD status;
+
+    ret = IDirectInputEffect_GetEffectStatus(effect->hweffect->ref, &status);
+    if (FAILED(ret)) {
+        return DI_SetError("Getting effect status", ret);
+    }
+
+    if (status == 0)
+        return SDL_FALSE;
+    return SDL_TRUE;
+}
+
+int
+SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
+{
+    HRESULT ret;
+    DIPROPDWORD dipdw;
+
+    /* Create the weird structure thingy. */
+    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
+    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+    dipdw.diph.dwObj = 0;
+    dipdw.diph.dwHow = DIPH_DEVICE;
+    dipdw.dwData = gain * 100;  /* 0 to 10,000 */
+
+    /* Try to set the autocenter. */
+    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
+        DIPROP_FFGAIN, &dipdw.diph);
+    if (FAILED(ret)) {
+        return DI_SetError("Setting gain", ret);
+    }
+    return 0;
+}
+
+int
+SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
+{
+    HRESULT ret;
+    DIPROPDWORD dipdw;
+
+    /* Create the weird structure thingy. */
+    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
+    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+    dipdw.diph.dwObj = 0;
+    dipdw.diph.dwHow = DIPH_DEVICE;
+    dipdw.dwData = (autocenter == 0) ? DIPROPAUTOCENTER_OFF :
+        DIPROPAUTOCENTER_ON;
+
+    /* Try to set the autocenter. */
+    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
+        DIPROP_AUTOCENTER, &dipdw.diph);
+    if (FAILED(ret)) {
+        return DI_SetError("Setting autocenter", ret);
+    }
+    return 0;
+}
+
+int
+SDL_DINPUT_HapticPause(SDL_Haptic * haptic)
+{
+    HRESULT ret;
+
+    /* Pause the device. */
+    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
+        DISFFC_PAUSE);
+    if (FAILED(ret)) {
+        return DI_SetError("Pausing the device", ret);
+    }
+    return 0;
+}
+
+int
+SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic)
+{
+    HRESULT ret;
+
+    /* Unpause the device. */
+    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
+        DISFFC_CONTINUE);
+    if (FAILED(ret)) {
+        return DI_SetError("Pausing the device", ret);
+    }
+    return 0;
+}
+
+int
+SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic)
+{
+    HRESULT ret;
+
+    /* Try to stop the effects. */
+    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
+        DISFFC_STOPALL);
+    if (FAILED(ret)) {
+        return DI_SetError("Stopping the device", ret);
+    }
+    return 0;
+}
+
+#else /* !SDL_HAPTIC_DINPUT */
+
+
+int
+SDL_DINPUT_HapticInit(void)
+{
+    return 0;
+}
+
+int
+SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+    return SDL_Unsupported();
+}
+
+void
+SDL_DINPUT_HapticClose(SDL_Haptic * haptic)
+{
+}
+
+void
+SDL_DINPUT_HapticQuit(void)
+{
+}
+
+int
+SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    return SDL_Unsupported();
+}
+
+void
+SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+}
+
+int
+SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticPause(SDL_Haptic * haptic)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic)
+{
+    return SDL_Unsupported();
+}
+
+#endif /* SDL_HAPTIC_DINPUT */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/haptic/windows/SDL_dinputhaptic_c.h	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,47 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_haptic.h"
+#include "SDL_windowshaptic_c.h"
+
+
+extern int SDL_DINPUT_HapticInit(void);
+extern int SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance);
+extern int SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance);
+extern int SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item);
+extern int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick);
+extern int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick);
+extern void SDL_DINPUT_HapticClose(SDL_Haptic * haptic);
+extern void SDL_DINPUT_HapticQuit(void);
+extern int SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base);
+extern int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data);
+extern int SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations);
+extern int SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern void SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern int SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern int SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain);
+extern int SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter);
+extern int SDL_DINPUT_HapticPause(SDL_Haptic * haptic);
+extern int SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic);
+extern int SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic);
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/haptic/windows/SDL_syshaptic.c	Thu Jul 03 17:36:08 2014 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1812 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-#include "../../SDL_internal.h"
-
-#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"
-#include "SDL_joystick.h"
-#include "../../joystick/SDL_sysjoystick.h"     /* For the real SDL_Joystick */
-#include "../../joystick/windows/SDL_dxjoystick_c.h"      /* For joystick hwdata */
-
-#include "SDL_syshaptic_c.h"
-
-/*
- * List of available haptic devices.
- */
-typedef struct SDL_hapticlist_item
-{
-    DIDEVICEINSTANCE instance;
-    char *name;
-    SDL_Haptic *haptic;
-    DIDEVCAPS capabilities;
-    Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
-    Uint8 userid; /* XInput userid index for this joystick */
-    struct SDL_hapticlist_item *next;
-} SDL_hapticlist_item;
-
-
-/*
- * Haptic system hardware data.
- */
-struct haptic_hwdata
-{
-    LPDIRECTINPUTDEVICE8 device;
-    DWORD axes[3];              /* Axes to use. */
-    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;
-};
-
-
-/*
- * Haptic system effect data.
- */
-struct haptic_hweffect
-{
-    DIEFFECT effect;
-    LPDIRECTINPUTEFFECT ref;
-    XINPUT_VIBRATION vibration;
-};
-
-
-/*
- * Internal stuff.
- */
-static SDL_bool coinitialized = SDL_FALSE;
-static LPDIRECTINPUT8 dinput = NULL;
-static SDL_bool loaded_xinput = SDL_FALSE;
-static SDL_hapticlist_item *SDL_hapticlist = NULL;
-static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
-static int numhaptics = 0;
-
-/*
- * External stuff.
- */
-extern HWND SDL_HelperWindow;
-
-
-/*
- * Prototypes.
- */
-static int DI_SetError(const char *str, HRESULT err);
-static int DI_GUIDIsSame(const GUID * a, const GUID * b);
-static int SDL_SYS_HapticOpenFromInstance(SDL_Haptic * haptic,
-                                          DIDEVICEINSTANCE instance);
-static int SDL_SYS_HapticOpenFromDevice8(SDL_Haptic * haptic,
-                                         LPDIRECTINPUTDEVICE8 device8,
-                                         SDL_bool is_joystick);
-static int SDL_SYS_HapticOpenFromXInput(SDL_Haptic * haptic, const Uint8 userid);
-static DWORD DIGetTriggerButton(Uint16 button);
-static int SDL_SYS_SetDirection(DIEFFECT * effect, SDL_HapticDirection * dir,
-                                int naxes);
-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);
-static BOOL CALLBACK DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv);
-
-
-/*
- * Like SDL_SetError but for DX error codes.
- */
-static int
-DI_SetError(const char *str, HRESULT err)
-{
-    /*
-       SDL_SetError("Haptic: %s - %s: %s", str,
-       DXGetErrorString8A(err), DXGetErrorDescription8A(err));
-     */
-    return SDL_SetError("Haptic error %s", str);
-}
-
-
-/*
- * Checks to see if two GUID are the same.
- */
-static int
-DI_GUIDIsSame(const GUID * a, const GUID * b)
-{
-    return (SDL_memcmp(a, b, sizeof (GUID)) == 0);
-}
-
-
-/*
- * Initializes the haptic subsystem.
- */
-int
-SDL_SYS_HapticInit(void)
-{
-    const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
-    HRESULT ret;
-    HINSTANCE instance;
-
-    if (dinput != NULL) {       /* Already open. */
-        return SDL_SetError("Haptic: SubSystem already open.");
-    }
-
-    ret = WIN_CoInitialize();
-    if (FAILED(ret)) {
-        return DI_SetError("Coinitialize", ret);
-    }
-
-    coinitialized = SDL_TRUE;
-
-    ret = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
-                           &IID_IDirectInput8, (LPVOID) & dinput);
-    if (FAILED(ret)) {
-        SDL_SYS_HapticQuit();
-        return DI_SetError("CoCreateInstance", ret);
-    }
-
-    /* Because we used CoCreateInstance, we need to Initialize it, first. */
-    instance = GetModuleHandle(NULL);
-    if (instance == NULL) {
-        SDL_SYS_HapticQuit();
-        return SDL_SetError("GetModuleHandle() failed with error code %d.",
-                            GetLastError());
-    }
-    ret = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
-    if (FAILED(ret)) {
-        SDL_SYS_HapticQuit();
-        return DI_SetError("Initializing DirectInput device", ret);
-    }
-
-    /* Look for haptic devices. */
-    ret = IDirectInput8_EnumDevices(dinput,
-                                   0,
-                                   EnumHapticsCallback,
-                                   NULL,
-                                   DIEDFL_FORCEFEEDBACK |
-                                   DIEDFL_ATTACHEDONLY);
-    if (FAILED(ret)) {
-        SDL_SYS_HapticQuit();
-        return DI_SetError("Enumerating DirectInput devices", ret);
-    }
-
-    if (!env || SDL_atoi(env)) {
-        loaded_xinput = (WIN_LoadXInputDLL() == 0);
-    }
-
-    if (loaded_xinput) {
-        DWORD i;
-        for (i = 0; i < SDL_XINPUT_MAX_DEVICES; i++) {
-            XInputHaptic_MaybeAddDevice(i);
-        }
-    }
-
-    return numhaptics;
-}
-
-
-int
-DirectInputHaptic_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
-{
-    HRESULT ret;
-    LPDIRECTINPUTDEVICE8 device;
-    const DWORD needflags = DIDC_ATTACHED | DIDC_FORCEFEEDBACK;
-    DIDEVCAPS capabilities;
-    SDL_hapticlist_item *item = NULL;
-
-    if (dinput == NULL) {
-        return -1;  /* not initialized. We'll pick these up on enumeration if we init later. */
-    }
-
-    /* Make sure we don't already have it */
-    for (item = SDL_hapticlist; item; item = item->next) {
-        if ( (!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof (*pdidInstance)) == 0) ) {
-            return -1;  /* Already added */
-        }
-    }
-
-    /* Open the device */
-    ret = IDirectInput8_CreateDevice(dinput, &pdidInstance->guidInstance, &device, NULL);
-    if (FAILED(ret)) {
-        /* DI_SetError("Creating DirectInput device",ret); */
-        return -1;
-    }
-
-    /* Get capabilities. */
-    SDL_zero(capabilities);
-    capabilities.dwSize = sizeof (DIDEVCAPS);
-    ret = IDirectInputDevice8_GetCapabilities(device, &capabilities);
-    IDirectInputDevice8_Release(device);
-    if (FAILED(ret)) {
-        /* DI_SetError("Getting device capabilities",ret); */
-        return -1;
-    }
-
-    if ((capabilities.dwFlags & needflags) != needflags) {
-        return -1;  /* not a device we can use. */
-    }
-
-    item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item));
-    if (item == NULL) {
-        return SDL_OutOfMemory();
-    }
-
-    item->name = WIN_StringToUTF8(pdidInstance->tszProductName);
-    if (!item->name) {
-        SDL_free(item);
-        return -1;
-    }
-
-    /* Copy the instance over, useful for creating devices. */
-    SDL_memcpy(&item->instance, pdidInstance, sizeof (DIDEVICEINSTANCE));
-    SDL_memcpy(&item->capabilities, &capabilities, sizeof (capabilities));
-
-    if (SDL_hapticlist_tail == NULL) {
-        SDL_hapticlist = SDL_hapticlist_tail = item;
-    } else {
-        SDL_hapticlist_tail->next = item;
-        SDL_hapticlist_tail = item;
-    }
-
-    /* Device has been added. */
-    ++numhaptics;
-
-    return numhaptics;
-}
-
-
-int
-DirectInputHaptic_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
-{
-    SDL_hapticlist_item *item;
-    SDL_hapticlist_item *prev = NULL;
-
-    if (dinput == NULL) {
-        return -1;  /* not initialized, ignore this. */
-    }
-
-    for (item = SDL_hapticlist; item != NULL; item = item->next) {
-        if ( (!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof (*pdidInstance)) == 0) ) {
-            /* found it, remove it. */
-            const int retval = item->haptic ? item->haptic->index : -1;
-            if (prev != NULL) {
-                prev->next = item->next;
-            } else {
-                SDL_assert(SDL_hapticlist == item);
-                SDL_hapticlist = item->next;
-            }
-            if (item == SDL_hapticlist_tail) {
-                SDL_hapticlist_tail = prev;
-            }
-            --numhaptics;
-            /* !!! TODO: Send a haptic remove event? */
-            SDL_free(item);
-            return retval;
-        }
-        prev = item;
-    }
-
-    return -1;
-}
-
-
-int
-XInputHaptic_MaybeAddDevice(const DWORD dwUserid)
-{
-    const Uint8 userid = (Uint8) dwUserid;
-    SDL_hapticlist_item *item;
-    XINPUT_VIBRATION state;
-
-    if ((!loaded_xinput) || (dwUserid >= SDL_XINPUT_MAX_DEVICES)) {
-        return -1;
-    }
-
-    /* Make sure we don't already have it */
-    for (item = SDL_hapticlist; item; item = item->next) {
-        if ((item->bXInputHaptic) && (item->userid == userid)) {
-            return -1;  /* Already added */
-        }
-    }
-
-    SDL_zero(state);
-    if (XINPUTSETSTATE(dwUserid, &state) != ERROR_SUCCESS) {
-        return -1;  /* no force feedback on this device. */
-    }
-
-    item = (SDL_hapticlist_item *)SDL_malloc( sizeof(SDL_hapticlist_item));
-    if (item == NULL) {
-        return SDL_OutOfMemory();
-    }
-
-    SDL_zerop(item);
-
-    /* !!! FIXME: I'm not bothering to query for a real name right now (can we even?) */
-    {
-        char buf[64];
-        SDL_snprintf(buf, sizeof (buf), "XInput Controller #%u", (unsigned int) (userid+1));
-        item->name = SDL_strdup(buf);
-    }
-
-    if (!item->name) {
-        SDL_free(item);
-        return -1;
-    }
-
-    /* Copy the instance over, useful for creating devices. */
-    item->bXInputHaptic = 1;
-    item->userid = userid;
-
-    if (SDL_hapticlist_tail == NULL) {
-        SDL_hapticlist = SDL_hapticlist_tail = item;
-    } else {
-        SDL_hapticlist_tail->next = item;
-        SDL_hapticlist_tail = item;
-    }
-
-    /* Device has been added. */
-    ++numhaptics;
-
-    return numhaptics;
-}
-
-
-int
-XInputHaptic_MaybeRemoveDevice(const DWORD dwUserid)
-{
-    const Uint8 userid = (Uint8) dwUserid;
-    SDL_hapticlist_item *item;
-    SDL_hapticlist_item *prev = NULL;
-
-    if ((!loaded_xinput) || (dwUserid >= SDL_XINPUT_MAX_DEVICES)) {
-        return -1;
-    }
-
-    for (item = SDL_hapticlist; item != NULL; item = item->next) {
-        if ((item->bXInputHaptic) && (item->userid == userid)) {
-            /* found it, remove it. */
-            const int retval = item->haptic ? item->haptic->index : -1;
-            if (prev != NULL) {
-                prev->next = item->next;
-            } else {
-                SDL_assert(SDL_hapticlist == item);
-                SDL_hapticlist = item->next;
-            }
-            if (item == SDL_hapticlist_tail) {
-                SDL_hapticlist_tail = prev;
-            }
-            --numhaptics;
-            /* !!! TODO: Send a haptic remove event? */
-            SDL_free(item);
-            return retval;
-        }
-        prev = item;
-    }
-
-    return -1;
-}
-
-
-/*
- * Callback to find the haptic devices.
- */
-static BOOL CALLBACK
-EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
-{
-    (void) pContext;
-    DirectInputHaptic_MaybeAddDevice(pdidInstance);
-    return DIENUM_CONTINUE;  /* continue enumerating */
-}
-
-
-int
-SDL_SYS_NumHaptics()
-{
-    return numhaptics;
-}
-
-static SDL_hapticlist_item *
-HapticByDevIndex(int device_index)
-{
-    SDL_hapticlist_item *item = SDL_hapticlist;
-
-    if ((device_index < 0) || (device_index >= numhaptics)) {
-        return NULL;
-    }
-
-    while (device_index > 0) {
-        SDL_assert(item != NULL);
-        --device_index;
-        item = item->next;
-    }
-
-    return item;
-}
-
-/*
- * Return the name of a haptic device, does not need to be opened.
- */
-const char *
-SDL_SYS_HapticName(int index)
-{
-    SDL_hapticlist_item *item = HapticByDevIndex(index);
-    return item->name;
-}
-
-
-/*
- * Callback to get all supported effects.
- */
-#define EFFECT_TEST(e,s)               \
-if (DI_GUIDIsSame(&pei->guid, &(e)))   \
-   haptic->supported |= (s)
-static BOOL CALLBACK
-DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv)
-{
-    /* Prepare the haptic device. */
-    SDL_Haptic *haptic = (SDL_Haptic *) pv;
-
-    /* Get supported. */
-    EFFECT_TEST(GUID_Spring, SDL_HAPTIC_SPRING);
-    EFFECT_TEST(GUID_Damper, SDL_HAPTIC_DAMPER);
-    EFFECT_TEST(GUID_Inertia, SDL_HAPTIC_INERTIA);
-    EFFECT_TEST(GUID_Friction, SDL_HAPTIC_FRICTION);
-    EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT);
-    EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM);
-    EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE);
-    /* !!! 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);
-    EFFECT_TEST(GUID_RampForce, SDL_HAPTIC_RAMP);
-
-    /* Check for more. */
-    return DIENUM_CONTINUE;
-}
-
-
-/*
- * Callback to get supported axes.
- */
-static BOOL CALLBACK
-DI_DeviceObjectCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
-{
-    SDL_Haptic *haptic = (SDL_Haptic *) pvRef;
-
-    if ((dev->dwType & DIDFT_AXIS) && (dev->dwFlags & DIDOI_FFACTUATOR)) {
-        const GUID *guid = &dev->guidType;
-        DWORD offset = 0;
-        if (DI_GUIDIsSame(guid, &GUID_XAxis)) {
-            offset = DIJOFS_X;
-        } else if (DI_GUIDIsSame(guid, &GUID_YAxis)) {
-            offset = DIJOFS_Y;
-        } else if (DI_GUIDIsSame(guid, &GUID_ZAxis)) {
-            offset = DIJOFS_Z;
-        } else if (DI_GUIDIsSame(guid, &GUID_RxAxis)) {
-            offset = DIJOFS_RX;
-        } else if (DI_GUIDIsSame(guid, &GUID_RyAxis)) {
-            offset = DIJOFS_RY;
-        } else if (DI_GUIDIsSame(guid, &GUID_RzAxis)) {
-            offset = DIJOFS_RZ;
-        } else {
-            return DIENUM_CONTINUE;   /* can't use this, go on. */
-        }
-
-        haptic->hwdata->axes[haptic->naxes] = offset;
-        haptic->naxes++;
-
-        /* Currently using the artificial limit of 3 axes. */
-        if (haptic->naxes >= 3) {
-            return DIENUM_STOP;
-        }
-    }
-
-    return DIENUM_CONTINUE;
-}
-
-
-/*
- * Opens the haptic device from the file descriptor.
- *
- *    Steps:
- *       - Open temporary DirectInputDevice interface.
- *       - Create DirectInputDevice8 interface.
- *       - Release DirectInputDevice interface.
- *       - Call SDL_SYS_HapticOpenFromDevice8
- */
-static int
-SDL_SYS_HapticOpenFromInstance(SDL_Haptic * haptic, DIDEVICEINSTANCE instance)
-{
-    HRESULT ret;
-    int ret2;
-    LPDIRECTINPUTDEVICE8 device;
-    LPDIRECTINPUTDEVICE8 device8;
-
-    /* Open the device */
-    ret = IDirectInput8_CreateDevice(dinput, &instance.guidInstance,
-                                    &device, NULL);
-    if (FAILED(ret)) {
-        DI_SetError("Creating DirectInput device", ret);
-        return -1;
-    }
-
-    /* Now get the IDirectInputDevice8 interface, instead. */
-    ret = IDirectInputDevice8_QueryInterface(device,
-                                            &IID_IDirectInputDevice8,
-                                            (LPVOID *) &device8);
-    /* Done with the temporary one now. */
-    IDirectInputDevice8_Release(device);
-    if (FAILED(ret)) {
-        DI_SetError("Querying DirectInput interface", ret);
-        return -1;
-    }
-
-    ret2 = SDL_SYS_HapticOpenFromDevice8(haptic, device8, SDL_FALSE);
-    if (ret2 < 0) {
-        IDirectInputDevice8_Release(device8);
-        return -1;
-    }
-
-    return 0;
-}
-
-static int
-SDL_SYS_HapticOpenFromXInput(SDL_Haptic *haptic, const Uint8 userid)
-{
-    char threadName[32];
-    XINPUT_VIBRATION vibration = { 0, 0 };  /* stop any current vibration */
-    XINPUTSETSTATE(userid, &vibration);
-
-    haptic->supported = SDL_HAPTIC_LEFTRIGHT;
-
-    haptic->neffects = 1;
-    haptic->nplaying = 1;
-
-    /* Prepare effects memory. */
-    haptic->effects = (struct haptic_effect *)
-        SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
-    if (haptic->effects == NULL) {
-        return SDL_OutOfMemory();
-    }
-    /* Clear the memory */
-    SDL_memset(haptic->effects, 0,
-               sizeof(struct haptic_effect) * haptic->neffects);
-
-    haptic->hwdata = (struct haptic_hwdata *) SDL_malloc(sizeof(*haptic->hwdata));
-    if (haptic->hwdata == NULL) {
-        SDL_free(haptic->effects);
-        haptic->effects = NULL;
-        return SDL_OutOfMemory();
-    }
-    SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
-
-    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
-    #if SDL_DYNAMIC_API
-    haptic->hwdata->thread = SDL_CreateThread_REAL(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
-    #else
-    haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
-    #endif
-#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;
- }
-
-/*
- * Opens the haptic device from the file descriptor.
- *
- *    Steps:
- *       - Set cooperative level.
- *       - Set data format.
- *       - Acquire exclusiveness.
- *       - Reset actuators.
- *       - Get supported features.
- */
-static int
-SDL_SYS_HapticOpenFromDevice8(SDL_Haptic * haptic,
-                              LPDIRECTINPUTDEVICE8 device8, SDL_bool is_joystick)
-{
-    HRESULT ret;
-    DIPROPDWORD dipdw;
-
-    /* Allocate the hwdata */
-    haptic->hwdata = (struct haptic_hwdata *)SDL_malloc(sizeof(*haptic->hwdata));
-    if (haptic->hwdata == NULL) {
-        return SDL_OutOfMemory();
-    }
-    SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
-
-    /* We'll use the device8 from now on. */
-    haptic->hwdata->device = device8;
-    haptic->hwdata->is_joystick = is_joystick;
-
-    /* !!! FIXME: opening a haptic device here first will make an attempt to
-       !!! FIXME:  SDL_JoystickOpen() that same device fail later, since we
-       !!! FIXME:  have it open in exclusive mode. But this will allow
-       !!! FIXME:  SDL_JoystickOpen() followed by SDL_HapticOpenFromJoystick()
-       !!! FIXME:  to work, and that's probably the common case. Still,
-       !!! FIXME:  ideally, We need to unify the opening code. */
-
-    if (!is_joystick) {  /* if is_joystick, we already set this up elsewhere. */
-        /* Grab it exclusively to use force feedback stuff. */
-        ret = IDirectInputDevice8_SetCooperativeLevel(haptic->hwdata->device,
-                                                      SDL_HelperWindow,
-                                                      DISCL_EXCLUSIVE |
-                                                      DISCL_BACKGROUND);
-        if (FAILED(ret)) {
-            DI_SetError("Setting cooperative level to exclusive", ret);
-            goto acquire_err;
-        }
-
-        /* Set data format. */
-        ret = IDirectInputDevice8_SetDataFormat(haptic->hwdata->device,
-                                                &c_dfDIJoystick2);
-        if (FAILED(ret)) {
-            DI_SetError("Setting data format", ret);
-            goto acquire_err;
-        }
-
-        /* Get number of axes. */
-        ret = IDirectInputDevice8_EnumObjects(haptic->hwdata->device,
-                                              DI_DeviceObjectCallback,
-                                              haptic, DIDFT_AXIS);
-        if (FAILED(ret)) {
-            DI_SetError("Getting device axes", ret);
-            goto acquire_err;
-        }
-
-        /* Acquire the device. */
-        ret = IDirectInputDevice8_Acquire(haptic->hwdata->device);
-        if (FAILED(ret)) {
-            DI_SetError("Acquiring DirectInput device", ret);
-            goto acquire_err;
-        }
-    }
-
-    /* Reset all actuators - just in case. */
-    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
-                                                       DISFFC_RESET);
-    if (FAILED(ret)) {
-        DI_SetError("Resetting device", ret);
-        goto acquire_err;
-    }
-
-    /* Enabling actuators. */
-    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
-                                                       DISFFC_SETACTUATORSON);
-    if (FAILED(ret)) {
-        DI_SetError("Enabling actuators", ret);
-        goto acquire_err;
-    }
-
-    /* Get supported effects. */
-    ret = IDirectInputDevice8_EnumEffects(haptic->hwdata->device,
-                                          DI_EffectCallback, haptic,
-                                          DIEFT_ALL);
-    if (FAILED(ret)) {
-        DI_SetError("Enumerating supported effects", ret);
-        goto acquire_err;
-    }
-    if (haptic->supported == 0) {       /* Error since device supports nothing. */
-        SDL_SetError("Haptic: Internal error on finding supported effects.");
-        goto acquire_err;
-    }
-
-    /* Check autogain and autocenter. */
-    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
-    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
-    dipdw.diph.dwObj = 0;
-    dipdw.diph.dwHow = DIPH_DEVICE;
-    dipdw.dwData = 10000;
-    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
-                                          DIPROP_FFGAIN, &dipdw.diph);
-    if (!FAILED(ret)) {         /* Gain is supported. */
-        haptic->supported |= SDL_HAPTIC_GAIN;
-    }
-    dipdw.diph.dwObj = 0;
-    dipdw.diph.dwHow = DIPH_DEVICE;
-    dipdw.dwData = DIPROPAUTOCENTER_OFF;
-    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
-                                          DIPROP_AUTOCENTER, &dipdw.diph);
-    if (!FAILED(ret)) {         /* Autocenter is supported. */
-        haptic->supported |= SDL_HAPTIC_AUTOCENTER;
-    }
-
-    /* Status is always supported. */
-    haptic->supported |= SDL_HAPTIC_STATUS | SDL_HAPTIC_PAUSE;
-
-    /* Check maximum effects. */
-    haptic->neffects = 128;     /* This is not actually supported as thus under windows,
-                                   there is no way to tell the number of EFFECTS that a
-                                   device can hold, so we'll just use a "random" number
-                                   instead and put warnings in SDL_haptic.h */
-    haptic->nplaying = 128;     /* Even more impossible to get this then neffects. */
-
-    /* Prepare effects memory. */
-    haptic->effects = (struct haptic_effect *)
-        SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
-    if (haptic->effects == NULL) {
-        SDL_OutOfMemory();
-        goto acquire_err;
-    }
-    /* Clear the memory */
-    SDL_memset(haptic->effects, 0,
-               sizeof(struct haptic_effect) * haptic->neffects);
-
-    return 0;
-
-    /* Error handling */
-  acquire_err:
-    IDirectInputDevice8_Unacquire(haptic->hwdata->device);
-    return -1;
-
-}
-
-
-/*
- * Opens a haptic device for usage.
- */
-int
-SDL_SYS_HapticOpen(SDL_Haptic * haptic)
-{
-    SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
-    return (item->bXInputHaptic) ? SDL_SYS_HapticOpenFromXInput(haptic, item->userid) : SDL_SYS_HapticOpenFromInstance(haptic, item->instance);
-}
-
-
-/*
- * Opens a haptic device from first mouse it finds for usage.
- */
-int
-SDL_SYS_HapticMouse(void)
-{
-    SDL_hapticlist_item *item;
-    int index = 0;
-
-    /* Grab the first mouse haptic device we find. */
-    for (item = SDL_hapticlist; item != NULL; item = item->next) {
-        SDL_assert(index >= 0);
-        if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER ) {
-            return index;
-        }
-        ++index;
-    }
-
-    return -1;
-}
-
-
-/*
- * Checks to see if a joystick has haptic features.
- */
-int
-SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
-{
-    const struct joystick_hwdata *hwdata = joystick->hwdata;
-    return ( (hwdata->bXInputHaptic) ||
-             ((hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) != 0) );
-}
-
-
-/*
- * Checks to see if the haptic device and joystick are in reality the same.
- */
-int
-SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
-{
-    if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
-        return 0;  /* one is XInput, one is not; not the same device. */
-    } else if (joystick->hwdata->bXInputHaptic) {  /* XInput */
-        return (haptic->hwdata->userid == joystick->hwdata->userid);
-    } else {  /* DirectInput */
-        HRESULT ret;
-        DIDEVICEINSTANCE hap_instance, joy_instance;
-
-        hap_instance.dwSize = sizeof(DIDEVICEINSTANCE);
-        joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
-
-        /* Get the device instances. */
-        ret = IDirectInputDevice8_GetDeviceInfo(haptic->hwdata->device,
-                                            &hap_instance);
-        if (FAILED(ret)) {
-            return 0;
-        }
-        ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice,
-                                                &joy_instance);
-        if (FAILED(ret)) {
-            return 0;
-        }
-
-        if (DI_GUIDIsSame(&hap_instance.guidInstance, &joy_instance.guidInstance))
-            return 1;
-    }
-
-    return 0;
-}
-
-
-/*
- * Opens a SDL_Haptic from a SDL_Joystick.
- */
-int
-SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
-{
-    SDL_hapticlist_item *item;
-    int index = 0;
-
-    /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
-    if (joystick->hwdata->bXInputDevice) {
-        const Uint8 userid = joystick->hwdata->userid;
-        for (item = SDL_hapticlist; item != NULL; item = item->next) {
-            if ((item->bXInputHaptic) && (item->userid == userid)) {
-                SDL_assert(joystick->hwdata->bXInputHaptic);
-                haptic->index = index;
-                return SDL_SYS_HapticOpenFromXInput(haptic, userid);
-            }
-            ++index;
-        }
-    } else {
-        HRESULT idret;
-        DIDEVICEINSTANCE joy_instance;
-
-        joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
-        idret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice, &joy_instance);
-        if (FAILED(idret)) {
-            return -1;
-        }
-
-        for (item = SDL_hapticlist; item != NULL; item = item->next) {
-            if (DI_GUIDIsSame(&item->instance.guidInstance, &joy_instance.guidInstance)) {
-                haptic->index = index;
-                return SDL_SYS_HapticOpenFromDevice8(haptic, joystick->hwdata->InputDevice, SDL_TRUE);
-            }
-            ++index;
-        }
-    }
-
-    /* No match to our haptic list */
-    return -1;
-}
-
-
-/*
- * Closes the haptic device.
- */
-void
-SDL_SYS_HapticClose(SDL_Haptic * haptic)
-{
-    if (haptic->hwdata) {
-
-        /* Free effects. */
-        SDL_free(haptic->effects);
-        haptic->effects = NULL;
-        haptic->neffects = 0;
-
-        /* Clean up */
-        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) {
-                IDirectInputDevice8_Release(haptic->hwdata->device);
-            }
-        }
-
-        /* Free */
-        SDL_free(haptic->hwdata);
-        haptic->hwdata = NULL;
-    }
-}
-
-
-/*
- * Clean up after system specific haptic stuff
- */
-void
-SDL_SYS_HapticQuit(void)
-{
-    SDL_hapticlist_item *item;
-    SDL_hapticlist_item *next = NULL;
-    SDL_Haptic *hapticitem = NULL;
-
-    extern SDL_Haptic *SDL_haptics;
-    for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
-        if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
-            /* we _have_ to stop the thread before we free the XInput DLL! */
-            hapticitem->hwdata->stopThread = 1;
-            SDL_WaitThread(hapticitem->hwdata->thread, NULL);
-            hapticitem->hwdata->thread = NULL;
-        }
-    }
-
-    for (item = SDL_hapticlist; item; item = next) {
-        /* Opened and not closed haptics are leaked, this is on purpose.
-         * Close your haptic devices after usage. */
-        /* !!! FIXME: (...is leaking on purpose a good idea?) */
-        next = item->next;
-        SDL_free(item->name);
-        SDL_free(item);
-    }
-
-    if (loaded_xinput) {
-        WIN_UnloadXInputDLL();
-        loaded_xinput = SDL_FALSE;
-    }
-
-    if (dinput != NULL) {
-        IDirectInput8_Release(dinput);
-        dinput = NULL;
-    }
-
-    if (coinitialized) {
-        WIN_CoUninitialize();
-        coinitialized = SDL_FALSE;
-    }
-}
-
-
-/*
- * Converts an SDL trigger button to an DIEFFECT trigger button.
- */
-static DWORD
-DIGetTriggerButton(Uint16 button)
-{
-    DWORD dwTriggerButton;
-
-    dwTriggerButton = DIEB_NOTRIGGER;
-
-    if (button != 0) {
-        dwTriggerButton = DIJOFS_BUTTON(button - 1);
-    }
-
-    return dwTriggerButton;
-}
-
-
-/*
- * Sets the direction.
- */
-static int
-SDL_SYS_SetDirection(DIEFFECT * effect, SDL_HapticDirection * dir, int naxes)
-{
-    LONG *rglDir;
-
-    /* Handle no axes a part. */
-    if (naxes == 0) {
-        effect->dwFlags |= DIEFF_SPHERICAL;     /* Set as default. */
-        effect->rglDirection = NULL;
-        return 0;
-    }
-
-    /* Has axes. */
-    rglDir = SDL_malloc(sizeof(LONG) * naxes);
-    if (rglDir == NULL) {
-        return SDL_OutOfMemory();
-    }
-    SDL_memset(rglDir, 0, sizeof(LONG) * naxes);
-    effect->rglDirection = rglDir;
-
-    switch (dir->type) {
-    case SDL_HAPTIC_POLAR:
-        effect->dwFlags |= DIEFF_POLAR;
-        rglDir[0] = dir->dir[0];
-        return 0;
-    case SDL_HAPTIC_CARTESIAN:
-        effect->dwFlags |= DIEFF_CARTESIAN;
-        rglDir[0] = dir->dir[0];
-        if (naxes > 1)
-            rglDir[1] = dir->dir[1];
-        if (naxes > 2)
-            rglDir[2] = dir->dir[2];
-        return 0;
-    case SDL_HAPTIC_SPHERICAL:
-        effect->dwFlags |= DIEFF_SPHERICAL;
-        rglDir[0] = dir->dir[0];
-        if (naxes > 1)
-            rglDir[1] = dir->dir[1];
-        if (naxes > 2)
-            rglDir[2] = dir->dir[2];
-        return 0;
-
-    default:
-        return SDL_SetError("Haptic: Unknown direction type.");
-    }
-}
-
-#define CONVERT(x)   (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
-/*
- * Creates the DIEFFECT from a SDL_HapticEffect.
- */
-static int
-SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
-                   SDL_HapticEffect * src)
-{
-    int i;
-    DICONSTANTFORCE *constant;
-    DIPERIODIC *periodic;
-    DICONDITION *condition;     /* Actually an array of conditions - one per axis. */
-    DIRAMPFORCE *ramp;
-    DICUSTOMFORCE *custom;
-    DIENVELOPE *envelope;
-    SDL_HapticConstant *hap_constant;
-    SDL_HapticPeriodic *hap_periodic;
-    SDL_HapticCondition *hap_condition;
-    SDL_HapticRamp *hap_ramp;
-    SDL_HapticCustom *hap_custom;
-    DWORD *axes;
-
-    /* Set global stuff. */
-    SDL_memset(dest, 0, sizeof(DIEFFECT));
-    dest->dwSize = sizeof(DIEFFECT);    /* Set the structure size. */
-    dest->dwSamplePeriod = 0;   /* Not used by us. */
-    dest->dwGain = 10000;       /* Gain is set globally, not locally. */
-    dest->dwFlags = DIEFF_OBJECTOFFSETS;        /* Seems obligatory. */
-
-    /* Envelope. */
-    envelope = SDL_malloc(sizeof(DIENVELOPE));
-    if (envelope == NULL) {
-        return SDL_OutOfMemory();
-    }
-    SDL_memset(envelope, 0, sizeof(DIENVELOPE));
-    dest->lpEnvelope = envelope;
-    envelope->dwSize = sizeof(DIENVELOPE);      /* Always should be this. */
-
-    /* Axes. */
-    dest->cAxes = haptic->naxes;
-    if (dest->cAxes > 0) {
-        axes = SDL_malloc(sizeof(DWORD) * dest->cAxes);
-        if (axes == NULL) {
-            return SDL_OutOfMemory();
-        }
-        axes[0] = haptic->hwdata->axes[0];      /* Always at least one axis. */
-        if (dest->cAxes > 1) {
-            axes[1] = haptic->hwdata->axes[1];
-        }
-        if (dest->cAxes > 2) {
-            axes[2] = haptic->hwdata->axes[2];
-        }
-        dest->rgdwAxes = axes;
-    }
-
-
-    /* The big type handling switch, even bigger then Linux's version. */
-    switch (src->type) {
-    case SDL_HAPTIC_CONSTANT:
-        hap_constant = &src->constant;
-        constant = SDL_malloc(sizeof(DICONSTANTFORCE));
-        if (constant == NULL) {
-            return SDL_OutOfMemory();
-        }
-        SDL_memset(constant, 0, sizeof(DICONSTANTFORCE));
-
-        /* Specifics */
-        constant->lMagnitude = CONVERT(hap_constant->level);
-        dest->cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
-        dest->lpvTypeSpecificParams = constant;
-
-        /* Generics */
-        dest->dwDuration = hap_constant->length * 1000; /* In microseconds. */
-        dest->dwTriggerButton = DIGetTriggerButton(hap_constant->button);
-        dest->dwTriggerRepeatInterval = hap_constant->interval;
-        dest->dwStartDelay = hap_constant->delay * 1000;        /* In microseconds. */
-
-        /* Direction. */
-        if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes)
-            < 0) {
-            return -1;
-        }
-
-        /* Envelope */
-        if ((hap_constant->attack_length == 0)
-            && (hap_constant->fade_length == 0)) {
-            SDL_free(dest->lpEnvelope);
-            dest->lpEnvelope = NULL;
-        } else {
-            envelope->dwAttackLevel = CONVERT(hap_constant->attack_level);
-            envelope->dwAttackTime = hap_constant->attack_length * 1000;
-            envelope->dwFadeLevel = CONVERT(hap_constant->fade_level);
-            envelope->dwFadeTime = hap_constant->fade_length * 1000;
-        }
-
-        break;
-
-    case SDL_HAPTIC_SINE:
-    /* !!! 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:
-        hap_periodic = &src->periodic;
-        periodic = SDL_malloc(sizeof(DIPERIODIC));
-        if (periodic == NULL) {
-            return SDL_OutOfMemory();
-        }
-        SDL_memset(periodic, 0, sizeof(DIPERIODIC));
-
-        /* Specifics */
-        periodic->dwMagnitude = CONVERT(hap_periodic->magnitude);
-        periodic->lOffset = CONVERT(hap_periodic->offset);
-        periodic->dwPhase = hap_periodic->phase;
-        periodic->dwPeriod = hap_periodic->period * 1000;
-        dest->cbTypeSpecificParams = sizeof(DIPERIODIC);
-        dest->lpvTypeSpecificParams = periodic;
-
-        /* Generics */
-        dest->dwDuration = hap_periodic->length * 1000; /* In microseconds. */
-        dest->dwTriggerButton = DIGetTriggerButton(hap_periodic->button);
-        dest->dwTriggerRepeatInterval = hap_periodic->interval;
-        dest->dwStartDelay = hap_periodic->delay * 1000;        /* In microseconds. */
-
-        /* Direction. */
-        if (SDL_SYS_SetDirection(dest, &hap_periodic->direction, dest->cAxes)
-            < 0) {
-            return -1;
-        }
-
-        /* Envelope */
-        if ((hap_periodic->attack_length == 0)
-            && (hap_periodic->fade_length == 0)) {
-            SDL_free(dest->lpEnvelope);
-            dest->lpEnvelope = NULL;
-        } else {
-            envelope->dwAttackLevel = CONVERT(hap_periodic->attack_level);
-            envelope->dwAttackTime = hap_periodic->attack_length * 1000;
-            envelope->dwFadeLevel = CONVERT(hap_periodic->fade_level);
-            envelope->dwFadeTime = hap_periodic->fade_length * 1000;
-        }
-
-        break;
-
-    case SDL_HAPTIC_SPRING:
-    case SDL_HAPTIC_DAMPER:
-    case SDL_HAPTIC_INERTIA:
-    case SDL_HAPTIC_FRICTION:
-        hap_condition = &src->condition;
-        condition = SDL_malloc(sizeof(DICONDITION) * dest->cAxes);
-        if (condition == NULL) {
-            return SDL_OutOfMemory();
-        }
-        SDL_memset(condition, 0, sizeof(DICONDITION));
-
-        /* Specifics */
-        for (i = 0; i < (int) dest->cAxes; i++) {
-            condition[i].lOffset = CONVERT(hap_condition->center[i]);
-            condition[i].lPositiveCoefficient =
-                CONVERT(hap_condition->right_coeff[i]);
-            condition[i].lNegativeCoefficient =
-                CONVERT(hap_condition->left_coeff[i]);
-            condition[i].dwPositiveSaturation =
-                CONVERT(hap_condition->right_sat[i]);
-            condition[i].dwNegativeSaturation =
-                CONVERT(hap_condition->left_sat[i]);
-            condition[i].lDeadBand = CONVERT(hap_condition->deadband[i]);
-        }
-        dest->cbTypeSpecificParams = sizeof(DICONDITION) * dest->cAxes;
-        dest->lpvTypeSpecificParams = condition;
-
-        /* Generics */
-        dest->dwDuration = hap_condition->length * 1000;        /* In microseconds. */
-        dest->dwTriggerButton = DIGetTriggerButton(hap_condition->button);
-        dest->dwTriggerRepeatInterval = hap_condition->interval;
-        dest->dwStartDelay = hap_condition->delay * 1000;       /* In microseconds. */
-
-        /* Direction. */
-        if (SDL_SYS_SetDirection(dest, &hap_condition->direction, dest->cAxes)
-            < 0) {
-            return -1;
-        }
-
-        /* Envelope - Not actually supported by most CONDITION implementations. */
-        SDL_free(dest->lpEnvelope);
-        dest->lpEnvelope = NULL;
-
-        break;
-
-    case SDL_HAPTIC_RAMP:
-        hap_ramp = &src->ramp;
-        ramp = SDL_malloc(sizeof(DIRAMPFORCE));
-        if (ramp == NULL) {
-            return SDL_OutOfMemory();
-        }
-        SDL_memset(ramp, 0, sizeof(DIRAMPFORCE));
-
-        /* Specifics */
-        ramp->lStart = CONVERT(hap_ramp->start);
-        ramp->lEnd = CONVERT(hap_ramp->end);
-        dest->cbTypeSpecificParams = sizeof(DIRAMPFORCE);
-        dest->lpvTypeSpecificParams = ramp;
-
-        /* Generics */
-        dest->dwDuration = hap_ramp->length * 1000;     /* In microseconds. */
-        dest->dwTriggerButton = DIGetTriggerButton(hap_ramp->button);
-        dest->dwTriggerRepeatInterval = hap_ramp->interval;
-        dest->dwStartDelay = hap_ramp->delay * 1000;    /* In microseconds. */
-
-        /* Direction. */
-        if (SDL_SYS_SetDirection(dest, &hap_ramp->direction, dest->cAxes) < 0) {
-            return -1;
-        }
-
-        /* Envelope */
-        if ((hap_ramp->attack_length == 0) && (hap_ramp->fade_length == 0)) {
-            SDL_free(dest->lpEnvelope);
-            dest->lpEnvelope = NULL;
-        } else {
-            envelope->dwAttackLevel = CONVERT(hap_ramp->attack_level);
-            envelope->dwAttackTime = hap_ramp->attack_length * 1000;
-            envelope->dwFadeLevel = CONVERT(hap_ramp->fade_level);
-            envelope->dwFadeTime = hap_ramp->fade_length * 1000;
-        }
-
-        break;
-
-    case SDL_HAPTIC_CUSTOM:
-        hap_custom = &src->custom;
-        custom = SDL_malloc(sizeof(DICUSTOMFORCE));
-        if (custom == NULL) {
-            return SDL_OutOfMemory();
-        }
-        SDL_memset(custom, 0, sizeof(DICUSTOMFORCE));
-
-        /* Specifics */
-        custom->cChannels = hap_custom->channels;
-        custom->dwSamplePeriod = hap_custom->period * 1000;
-        custom->cSamples = hap_custom->samples;
-        custom->rglForceData =
-            SDL_malloc(sizeof(LONG) * custom->cSamples * custom->cChannels);
-        for (i = 0; i < hap_custom->samples * hap_custom->channels; i++) {      /* Copy data. */
-            custom->rglForceData[i] = CONVERT(hap_custom->data[i]);
-        }
-        dest->cbTypeSpecificParams = sizeof(DICUSTOMFORCE);
-        dest->lpvTypeSpecificParams = custom;
-
-        /* Generics */
-        dest->dwDuration = hap_custom->length * 1000;   /* In microseconds. */
-        dest->dwTriggerButton = DIGetTriggerButton(hap_custom->button);
-        dest->dwTriggerRepeatInterval = hap_custom->interval;
-        dest->dwStartDelay = hap_custom->delay * 1000;  /* In microseconds. */
-
-        /* Direction. */
-        if (SDL_SYS_SetDirection(dest, &hap_custom->direction, dest->cAxes) <
-            0) {
-            return -1;
-        }
-
-        /* Envelope */
-        if ((hap_custom->attack_length == 0)
-            && (hap_custom->fade_length == 0)) {
-            SDL_free(dest->lpEnvelope);
-            dest->lpEnvelope = NULL;
-        } else {
-            envelope->dwAttackLevel = CONVERT(hap_custom->attack_level);
-            envelope->dwAttackTime = hap_custom->attack_length * 1000;
-            envelope->dwFadeLevel = CONVERT(hap_custom->fade_level);
-            envelope->dwFadeTime = hap_custom->fade_length * 1000;
-        }
-
-        break;
-
-
-    default:
-        return SDL_SetError("Haptic: Unknown effect type.");
-    }
-
-    return 0;
-}
-
-
-/*
- * Frees an DIEFFECT allocated by SDL_SYS_ToDIEFFECT.
- */
-static void
-SDL_SYS_HapticFreeDIEFFECT(DIEFFECT * effect, int type)
-{
-    DICUSTOMFORCE *custom;
-
-    SDL_free(effect->lpEnvelope);
-    effect->lpEnvelope = NULL;
-    SDL_free(effect->rgdwAxes);
-    effect->rgdwAxes = NULL;
-    if (effect->lpvTypeSpecificParams != NULL) {
-        if (type == SDL_HAPTIC_CUSTOM) {        /* Must free the custom data. */
-            custom = (DICUSTOMFORCE *) effect->lpvTypeSpecificParams;
-            SDL_free(custom->rglForceData);
-            custom->rglForceData = NULL;
-        }
-        SDL_free(effect->lpvTypeSpecificParams);
-        effect->lpvTypeSpecificParams = NULL;
-    }
-    SDL_free(effect->rglDirection);
-    effect->rglDirection = NULL;
-}
-
-
-/*
- * Gets the effect type from the generic SDL haptic effect wrapper.
- */
-static REFGUID
-SDL_SYS_HapticEffectType(SDL_HapticEffect * effect)
-{
-    switch (effect->type) {
-    case SDL_HAPTIC_CONSTANT:
-        return &GUID_ConstantForce;
-
-    case SDL_HAPTIC_RAMP:
-        return &GUID_RampForce;
-
-    /* !!! 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;
-
-    case SDL_HAPTIC_TRIANGLE:
-        return &GUID_Triangle;
-
-    case SDL_HAPTIC_SAWTOOTHUP:
-        return &GUID_SawtoothUp;
-
-    case SDL_HAPTIC_SAWTOOTHDOWN:
-        return &GUID_SawtoothDown;
-
-    case SDL_HAPTIC_SPRING:
-        return &GUID_Spring;
-
-    case SDL_HAPTIC_DAMPER:
-        return &GUID_Damper;
-
-    case SDL_HAPTIC_INERTIA:
-        return &GUID_Inertia;
-
-    case SDL_HAPTIC_FRICTION:
-        return &GUID_Friction;
-
-    case SDL_HAPTIC_CUSTOM:
-        return &GUID_CustomForce;
-
-    default:
-        return NULL;
-    }
-}
-
-
-/*
- * Creates a new haptic effect.
- */
-int
-SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
-                        SDL_HapticEffect * base)
-{
-    HRESULT ret;
-    REFGUID type = SDL_SYS_HapticEffectType(base);
-
-    if ((type == NULL) && (!haptic->hwdata->bXInputHaptic)) {
-        SDL_SetError("Haptic: Unknown effect type.");
-        goto err_hweffect;
-    }
-
-    /* Alloc the effect. */
-    effect->hweffect = (struct haptic_hweffect *)
-        SDL_malloc(sizeof(struct haptic_hweffect));
-    if (effect->hweffect == NULL) {
-        SDL_OutOfMemory();
-        goto err_hweffect;
-    }
-
-    SDL_zerop(effect->hweffect);
-
-    if (haptic->hwdata->bXInputHaptic) {
-        SDL_assert(base->type == SDL_HAPTIC_LEFTRIGHT);  /* should catch this at higher level */
-        return SDL_SYS_HapticUpdateEffect(haptic, effect, base);
-    }
-
-    /* Get the effect. */
-    if (SDL_SYS_ToDIEFFECT(haptic, &effect->hweffect->effect, base) < 0) {
-        goto err_effectdone;
-    }
-
-    /* Create the actual effect. */
-    ret = IDirectInputDevice8_CreateEffect(haptic->hwdata->device, type,
-                                           &effect->hweffect->effect,
-                                           &effect->hweffect->ref, NULL);
-    if (FAILED(ret)) {
-        DI_SetError("Unable to create effect", ret);
-        goto err_effectdone;
-    }
-
-    return 0;
-
-  err_effectdone:
-    SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, base->type);
-  err_hweffect:
-    SDL_free(effect->hweffect);
-    effect->hweffect = NULL;
-    return -1;
-}
-
-
-/*
- * Updates an effect.
- */
-int
-SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
-                           struct haptic_effect *effect,
-                           SDL_HapticEffect * data)
-{
-    HRESULT ret;
-    DWORD flags;
-    DIEFFECT temp;
-
-    if (haptic->hwdata->bXInputHaptic) {
-        XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
-        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;
-    }
-
-    /* Get the effect. */
-    SDL_memset(&temp, 0, sizeof(DIEFFECT));
-    if (SDL_SYS_ToDIEFFECT(haptic, &temp, data) < 0) {
-        goto err_update;
-    }
-
-    /* Set the flags.  Might be worthwhile to diff temp with loaded effect and
-     *  only change those parameters. */
-    flags = DIEP_DIRECTION |
-        DIEP_DURATION |
-        DIEP_ENVELOPE |
-        DIEP_STARTDELAY |
-        DIEP_TRIGGERBUTTON |
-        DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS;
-
-    /* Create the actual effect. */
-    ret =
-        IDirectInputEffect_SetParameters(effect->hweffect->ref, &temp, flags);
-    if (FAILED(ret)) {
-        DI_SetError("Unable to update effect", ret);
-        goto err_update;
-    }
-
-    /* Copy it over. */
-    SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, data->type);
-    SDL_memcpy(&effect->hweffect->effect, &temp, sizeof(DIEFFECT));
-
-    return 0;
-
-  err_update:
-    SDL_SYS_HapticFreeDIEFFECT(&temp, data->type);
-    return -1;
-}
-
-
-/*
- * Runs an effect.
- */
-int
-SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
-                        Uint32 iterations)
-{
-    HRESULT ret;
-    DWORD iter;
-
-    if (haptic->hwdata->bXInputHaptic) {
-        XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
-        SDL_assert(effect->effect.type == SDL_HAPTIC_LEFTRIGHT);  /* should catch this at higher level */
-        SDL_LockMutex(haptic->hwdata->mutex);
-        if(effect->effect.leftright.length == SDL_HAPTIC_INFINITY || iterations == SDL_HAPTIC_INFINITY) {
-            haptic->hwdata->stopTicks = SDL_HAPTIC_INFINITY;
-        } else if ((!effect->effect.leftright.length) || (!iterations)) {
-            /* do nothing. Effect runs for zero milliseconds. */
-        } else {
-            haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations);
-            if ((haptic->hwdata->stopTicks == SDL_HAPTIC_INFINITY) || (haptic->hwdata->stopTicks == 0)) {
-                haptic->hwdata->stopTicks = 1;  /* fix edge cases. */
-            }
-        }
-        SDL_UnlockMutex(haptic->hwdata->mutex);
-        return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1;
-    }
-
-    /* Check if it's infinite. */
-    if (iterations == SDL_HAPTIC_INFINITY) {
-        iter = INFINITE;
-    } else
-        iter = iterations;
-
-    /* Run the effect. */
-    ret = IDirectInputEffect_Start(effect->hweffect->ref, iter, 0);
-    if (FAILED(ret)) {
-        return DI_SetError("Running the effect", ret);
-    }
-
-    return 0;
-}
-
-
-/*
- * Stops an effect.
- */
-int
-SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
-{
-    HRESULT ret;
-
-    if (haptic->hwdata->bXInputHaptic) {
-        XINPUT_VIBRATION vibration = { 0, 0 };
-        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);
-    if (FAILED(ret)) {
-        return DI_SetError("Unable to stop effect", ret);
-    }
-
-    return 0;
-}
-
-
-/*
- * Frees the effect.
- */
-void
-SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
-{
-    HRESULT ret;
-
-    if (haptic->hwdata->bXInputHaptic) {
-        SDL_SYS_HapticStopEffect(haptic, effect);
-    } else {
-        ret = IDirectInputEffect_Unload(effect->hweffect->ref);
-        if (FAILED(ret)) {
-            DI_SetError("Removing effect from the device", ret);
-        }
-        SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect,
-                                   effect->effect.type);
-    }
-    SDL_free(effect->hweffect);
-    effect->hweffect = NULL;
-}
-
-
-/*
- * Gets the status of a haptic effect.
- */
-int
-SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
-                              struct haptic_effect *effect)
-{
-    HRESULT ret;
-    DWORD status;
-
-    ret = IDirectInputEffect_GetEffectStatus(effect->hweffect->ref, &status);
-    if (FAILED(ret)) {
-        return DI_SetError("Getting effect status", ret);
-    }
-
-    if (status == 0)
-        return SDL_FALSE;
-    return SDL_TRUE;
-}
-
-
-/*
- * Sets the gain.
- */
-int
-SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
-{
-    HRESULT ret;
-    DIPROPDWORD dipdw;
-
-    /* Create the weird structure thingy. */
-    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
-    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
-    dipdw.diph.dwObj = 0;
-    dipdw.diph.dwHow = DIPH_DEVICE;
-    dipdw.dwData = gain * 100;  /* 0 to 10,000 */
-
-    /* Try to set the autocenter. */
-    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
-                                          DIPROP_FFGAIN, &dipdw.diph);
-    if (FAILED(ret)) {
-        return DI_SetError("Setting gain", ret);
-    }
-
-    return 0;
-}
-
-
-/*
- * Sets the autocentering.
- */
-int
-SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
-{
-    HRESULT ret;
-    DIPROPDWORD dipdw;
-
-    /* Create the weird structure thingy. */
-    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
-    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
-    dipdw.diph.dwObj = 0;
-    dipdw.diph.dwHow = DIPH_DEVICE;
-    dipdw.dwData = (autocenter == 0) ? DIPROPAUTOCENTER_OFF :
-        DIPROPAUTOCENTER_ON;
-
-    /* Try to set the autocenter. */
-    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
-                                          DIPROP_AUTOCENTER, &dipdw.diph);
-    if (FAILED(ret)) {
-        return DI_SetError("Setting autocenter", ret);
-    }
-
-    return 0;
-}
-
-
-/*
- * Pauses the device.
- */
-int
-SDL_SYS_HapticPause(SDL_Haptic * haptic)
-{
-    HRESULT ret;
-
-    /* Pause the device. */
-    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
-                                                       DISFFC_PAUSE);
-    if (FAILED(ret)) {
-        return DI_SetError("Pausing the device", ret);
-    }
-
-    return 0;
-}
-
-
-/*
- * Pauses the device.
- */
-int
-SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
-{
-    HRESULT ret;
-
-    /* Unpause the device. */
-    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
-                                                       DISFFC_CONTINUE);
-    if (FAILED(ret)) {
-        return DI_SetError("Pausing the device", ret);
-    }
-
-    return 0;
-}
-
-
-/*
- * Stops all the playing effects on the device.
- */
-int
-SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
-{
-    HRESULT ret;
-
-    if (haptic->hwdata->bXInputHaptic) {
-        XINPUT_VIBRATION vibration = { 0, 0 };
-        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. */
-    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
-                                                       DISFFC_STOPALL);
-    if (FAILED(ret)) {
-        return DI_SetError("Stopping the device", ret);
-    }
-
-    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) {
-            if ((hwdata->stopTicks != SDL_HAPTIC_INFINITY) && SDL_TICKS_PASSED(SDL_GetTicks(), hwdata->stopTicks)) {
-                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: */
--- a/src/haptic/windows/SDL_syshaptic_c.h	Thu Jul 03 17:36:08 2014 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-extern int DirectInputHaptic_MaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance);
-extern int DirectInputHaptic_MaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance);
-extern int XInputHaptic_MaybeAddDevice(const DWORD dwUserid);
-extern int XInputHaptic_MaybeRemoveDevice(const DWORD dwUserid);
-
-/* vi: set ts=4 sw=4 expandtab: */
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/haptic/windows/SDL_windowshaptic.c	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,445 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT
+
+#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"
+#include "SDL_joystick.h"
+#include "../../joystick/SDL_sysjoystick.h"     /* For the real SDL_Joystick */
+#include "../../joystick/windows/SDL_windowsjoystick_c.h"      /* For joystick hwdata */
+#include "../../joystick/windows/SDL_xinputjoystick_c.h"      /* For xinput rumble */
+
+#include "SDL_windowshaptic_c.h"
+#include "SDL_dinputhaptic_c.h"
+#include "SDL_xinputhaptic_c.h"
+
+
+/*
+ * Internal stuff.
+ */
+SDL_hapticlist_item *SDL_hapticlist = NULL;
+static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
+static int numhaptics = 0;
+
+
+/*
+ * Initializes the haptic subsystem.
+ */
+int
+SDL_SYS_HapticInit(void)
+{
+    if (SDL_DINPUT_HapticInit() < 0) {
+        return -1;
+    }
+    if (SDL_XINPUT_HapticInit() < 0) {
+        return -1;
+    }
+    return numhaptics;
+}
+
+int
+SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
+{
+    if (SDL_hapticlist_tail == NULL) {
+        SDL_hapticlist = SDL_hapticlist_tail = item;
+    } else {
+        SDL_hapticlist_tail->next = item;
+        SDL_hapticlist_tail = item;
+    }
+
+    /* Device has been added. */
+    ++numhaptics;
+
+    return numhaptics;
+}
+
+int
+SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
+{
+    const int retval = item->haptic ? item->haptic->index : -1;
+    if (prev != NULL) {
+        prev->next = item->next;
+    } else {
+        SDL_assert(SDL_hapticlist == item);
+        SDL_hapticlist = item->next;
+    }
+    if (item == SDL_hapticlist_tail) {
+        SDL_hapticlist_tail = prev;
+    }
+    --numhaptics;
+    /* !!! TODO: Send a haptic remove event? */
+    SDL_free(item);
+    return retval;
+}
+
+int
+SDL_SYS_NumHaptics()
+{
+    return numhaptics;
+}
+
+static SDL_hapticlist_item *
+HapticByDevIndex(int device_index)
+{
+    SDL_hapticlist_item *item = SDL_hapticlist;
+
+    if ((device_index < 0) || (device_index >= numhaptics)) {
+        return NULL;
+    }
+
+    while (device_index > 0) {
+        SDL_assert(item != NULL);
+        --device_index;
+        item = item->next;
+    }
+    return item;
+}
+
+/*
+ * Return the name of a haptic device, does not need to be opened.
+ */
+const char *
+SDL_SYS_HapticName(int index)
+{
+    SDL_hapticlist_item *item = HapticByDevIndex(index);
+    return item->name;
+}
+
+/*
+ * Opens a haptic device for usage.
+ */
+int
+SDL_SYS_HapticOpen(SDL_Haptic * haptic)
+{
+    SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
+    if (item->bXInputHaptic) {
+        return SDL_XINPUT_HapticOpen(haptic, item);
+    } else {
+        return SDL_DINPUT_HapticOpen(haptic, item);
+    }
+}
+
+
+/*
+ * Opens a haptic device from first mouse it finds for usage.
+ */
+int
+SDL_SYS_HapticMouse(void)
+{
+#if SDL_HAPTIC_DINPUT
+    SDL_hapticlist_item *item;
+    int index = 0;
+
+    /* Grab the first mouse haptic device we find. */
+    for (item = SDL_hapticlist; item != NULL; item = item->next) {
+        if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER ) {
+            return index;
+        }
+        ++index;
+    }
+#endif /* SDL_HAPTIC_DINPUT */
+    return -1;
+}
+
+
+/*
+ * Checks to see if a joystick has haptic features.
+ */
+int
+SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
+{
+    const struct joystick_hwdata *hwdata = joystick->hwdata;
+#if SDL_HAPTIC_XINPUT
+    if (hwdata->bXInputHaptic) {
+        return 1;
+    }
+#endif
+#if SDL_HAPTIC_DINPUT
+    if (hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
+        return 1;
+    }
+#endif
+    return 0;
+}
+
+/*
+ * Checks to see if the haptic device and joystick are in reality the same.
+ */
+int
+SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+    if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
+        return 0;  /* one is XInput, one is not; not the same device. */
+    } else if (joystick->hwdata->bXInputHaptic) {
+        return SDL_XINPUT_JoystickSameHaptic(haptic, joystick);
+    } else {
+        return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
+    }
+}
+
+/*
+ * Opens a SDL_Haptic from a SDL_Joystick.
+ */
+int
+SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+    if (joystick->hwdata->bXInputDevice) {
+        return SDL_XINPUT_HapticOpenFromJoystick(haptic, joystick);
+    } else {
+        return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);
+    }
+}
+
+/*
+ * Closes the haptic device.
+ */
+void
+SDL_SYS_HapticClose(SDL_Haptic * haptic)
+{
+    if (haptic->hwdata) {
+
+        /* Free effects. */
+        SDL_free(haptic->effects);
+        haptic->effects = NULL;
+        haptic->neffects = 0;
+
+        /* Clean up */
+        if (haptic->hwdata->bXInputHaptic) {
+            SDL_XINPUT_HapticClose(haptic);
+        } else {
+            SDL_DINPUT_HapticClose(haptic);
+        }
+
+        /* Free */
+        SDL_free(haptic->hwdata);
+        haptic->hwdata = NULL;
+    }
+}
+
+/*
+ * Clean up after system specific haptic stuff
+ */
+void
+SDL_SYS_HapticQuit(void)
+{
+    SDL_hapticlist_item *item;
+    SDL_hapticlist_item *next = NULL;
+    SDL_Haptic *hapticitem = NULL;
+
+    extern SDL_Haptic *SDL_haptics;
+    for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
+        if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
+            /* we _have_ to stop the thread before we free the XInput DLL! */
+            hapticitem->hwdata->stopThread = 1;
+            SDL_WaitThread(hapticitem->hwdata->thread, NULL);
+            hapticitem->hwdata->thread = NULL;
+        }
+    }
+
+    for (item = SDL_hapticlist; item; item = next) {
+        /* Opened and not closed haptics are leaked, this is on purpose.
+         * Close your haptic devices after usage. */
+        /* !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not. */
+        next = item->next;
+        SDL_free(item->name);
+        SDL_free(item);
+    }
+
+    SDL_XINPUT_HapticQuit();
+    SDL_DINPUT_HapticQuit();
+}
+
+/*
+ * Creates a new haptic effect.
+ */
+int
+SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
+                        SDL_HapticEffect * base)
+{
+    int result;
+
+    /* Alloc the effect. */
+    effect->hweffect = (struct haptic_hweffect *)
+        SDL_malloc(sizeof(struct haptic_hweffect));
+    if (effect->hweffect == NULL) {
+        SDL_OutOfMemory();
+        return -1;
+    }
+    SDL_zerop(effect->hweffect);
+
+    if (haptic->hwdata->bXInputHaptic) {
+        result = SDL_XINPUT_HapticNewEffect(haptic, effect, base);
+    } else {
+        result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
+    }
+    if (result < 0) {
+        SDL_free(effect->hweffect);
+        effect->hweffect = NULL;
+    }
+    return result;
+}
+
+/*
+ * Updates an effect.
+ */
+int
+SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
+                           struct haptic_effect *effect,
+                           SDL_HapticEffect * data)
+{
+    if (haptic->hwdata->bXInputHaptic) {
+        return SDL_XINPUT_HapticUpdateEffect(haptic, effect, data);
+    } else {
+        return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
+    }
+}
+
+/*
+ * Runs an effect.
+ */
+int
+SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
+                        Uint32 iterations)
+{
+    if (haptic->hwdata->bXInputHaptic) {
+        return SDL_XINPUT_HapticRunEffect(haptic, effect, iterations);
+    } else {
+        return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
+    }
+}
+
+/*
+ * Stops an effect.
+ */
+int
+SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    if (haptic->hwdata->bXInputHaptic) {
+        return SDL_XINPUT_HapticStopEffect(haptic, effect);
+    } else {
+        return SDL_DINPUT_HapticStopEffect(haptic, effect);
+    }
+}
+
+/*
+ * Frees the effect.
+ */
+void
+SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    if (haptic->hwdata->bXInputHaptic) {
+        SDL_XINPUT_HapticDestroyEffect(haptic, effect);
+    } else {
+        SDL_DINPUT_HapticDestroyEffect(haptic, effect);
+    }
+    SDL_free(effect->hweffect);
+    effect->hweffect = NULL;
+}
+
+/*
+ * Gets the status of a haptic effect.
+ */
+int
+SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
+                              struct haptic_effect *effect)
+{
+    if (haptic->hwdata->bXInputHaptic) {
+        return SDL_XINPUT_HapticGetEffectStatus(haptic, effect);
+    } else {
+        return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
+    }
+}
+
+/*
+ * Sets the gain.
+ */
+int
+SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
+{
+    if (haptic->hwdata->bXInputHaptic) {
+        return SDL_XINPUT_HapticSetGain(haptic, gain);
+    } else {
+        return SDL_DINPUT_HapticSetGain(haptic, gain);
+    }
+}
+
+/*
+ * Sets the autocentering.
+ */
+int
+SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
+{
+    if (haptic->hwdata->bXInputHaptic) {
+        return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter);
+    } else {
+        return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
+    }
+}
+
+/*
+ * Pauses the device.
+ */
+int
+SDL_SYS_HapticPause(SDL_Haptic * haptic)
+{
+    if (haptic->hwdata->bXInputHaptic) {
+        return SDL_XINPUT_HapticPause(haptic);
+    } else {
+        return SDL_DINPUT_HapticPause(haptic);
+    }
+}
+
+/*
+ * Pauses the device.
+ */
+int
+SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
+{
+    if (haptic->hwdata->bXInputHaptic) {
+        return SDL_XINPUT_HapticUnpause(haptic);
+    } else {
+        return SDL_DINPUT_HapticUnpause(haptic);
+    }
+}
+
+/*
+ * Stops all the playing effects on the device.
+ */
+int
+SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
+{
+    if (haptic->hwdata->bXInputHaptic) {
+        return SDL_XINPUT_HapticStopAll(haptic);
+    } else {
+        return SDL_DINPUT_HapticStopAll(haptic);
+    }
+}
+
+#endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/haptic/windows/SDL_windowshaptic_c.h	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,88 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef _SDL_windowshaptic_c_h
+#define _SDL_windowshaptic_c_h
+
+#include "SDL_thread.h"
+
+#include "../../core/windows/SDL_directx.h"
+#include "../../core/windows/SDL_xinput.h"
+
+/*
+ * Haptic system hardware data.
+ */
+struct haptic_hwdata
+{
+#if SDL_HAPTIC_DINPUT
+    LPDIRECTINPUTDEVICE8 device;
+#endif
+    DWORD axes[3];              /* Axes to use. */
+    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;
+};
+
+
+/*
+ * Haptic system effect data.
+ */
+struct haptic_hweffect
+{
+#if SDL_HAPTIC_DINPUT
+    DIEFFECT effect;
+    LPDIRECTINPUTEFFECT ref;
+#endif
+#if SDL_HAPTIC_XINPUT
+    XINPUT_VIBRATION vibration;
+#endif
+};
+
+/*
+* List of available haptic devices.
+*/
+typedef struct SDL_hapticlist_item
+{
+    char *name;
+    SDL_Haptic *haptic;
+#if SDL_HAPTIC_DINPUT
+    DIDEVICEINSTANCE instance;
+    DIDEVCAPS capabilities;
+#endif
+    SDL_bool bXInputHaptic; /* Supports force feedback via XInput. */
+    Uint8 userid; /* XInput userid index for this joystick */
+    struct SDL_hapticlist_item *next;
+} SDL_hapticlist_item;
+
+extern SDL_hapticlist_item *SDL_hapticlist;
+
+extern int SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item);
+extern int SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item);
+
+#endif /* _SDL_windowshaptic_c_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/haptic/windows/SDL_xinputhaptic.c	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,491 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_assert.h"
+#include "SDL_error.h"
+#include "SDL_haptic.h"
+#include "SDL_hints.h"
+#include "SDL_timer.h"
+#include "SDL_windowshaptic_c.h"
+#include "SDL_xinputhaptic_c.h"
+#include "../SDL_syshaptic.h"
+#include "../../core/windows/SDL_xinput.h"
+#include "../../joystick/windows/SDL_windowsjoystick_c.h"
+
+
+#if SDL_HAPTIC_XINPUT
+
+/*
+ * Internal stuff.
+ */
+static SDL_bool loaded_xinput = SDL_FALSE;
+
+
+int
+SDL_XINPUT_HapticInit(void)
+{
+    const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
+    if (!env || SDL_atoi(env)) {
+        loaded_xinput = (WIN_LoadXInputDLL() == 0);
+    }
+
+    if (loaded_xinput) {
+        DWORD i;
+        for (i = 0; i < XUSER_MAX_COUNT; i++) {
+            SDL_XINPUT_MaybeAddDevice(i);
+        }
+    }
+    return 0;
+}
+
+int
+SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid)
+{
+    const Uint8 userid = (Uint8)dwUserid;
+    SDL_hapticlist_item *item;
+    XINPUT_VIBRATION state;
+
+    if ((!loaded_xinput) || (dwUserid >= XUSER_MAX_COUNT)) {
+        return -1;
+    }
+
+    /* Make sure we don't already have it */
+    for (item = SDL_hapticlist; item; item = item->next) {
+        if (item->bXInputHaptic && item->userid == userid) {
+            return -1;  /* Already added */
+        }
+    }
+
+    SDL_zero(state);
+    if (XINPUTSETSTATE(dwUserid, &state) != ERROR_SUCCESS) {
+        return -1;  /* no force feedback on this device. */
+    }
+
+    item = (SDL_hapticlist_item *)SDL_malloc(sizeof(SDL_hapticlist_item));
+    if (item == NULL) {
+        return SDL_OutOfMemory();
+    }
+
+    SDL_zerop(item);
+
+    /* !!! FIXME: I'm not bothering to query for a real name right now (can we even?) */
+    {
+        char buf[64];
+        SDL_snprintf(buf, sizeof(buf), "XInput Controller #%u", (unsigned int)(userid + 1));
+        item->name = SDL_strdup(buf);
+    }
+
+    if (!item->name) {
+        SDL_free(item);
+        return -1;
+    }
+
+    /* Copy the instance over, useful for creating devices. */
+    item->bXInputHaptic = SDL_TRUE;
+    item->userid = userid;
+
+    return SDL_SYS_AddHapticDevice(item);
+}
+
+int
+SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid)
+{
+    const Uint8 userid = (Uint8)dwUserid;
+    SDL_hapticlist_item *item;
+    SDL_hapticlist_item *prev = NULL;
+
+    if ((!loaded_xinput) || (dwUserid >= XUSER_MAX_COUNT)) {
+        return -1;
+    }
+
+    for (item = SDL_hapticlist; item != NULL; item = item->next) {
+        if (item->bXInputHaptic && item->userid == userid) {
+            /* found it, remove it. */
+            return SDL_SYS_RemoveHapticDevice(prev, item);
+        }
+        prev = item;
+    }
+    return -1;
+}
+
+/* !!! 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) {
+            if ((hwdata->stopTicks != SDL_HAPTIC_INFINITY) && SDL_TICKS_PASSED(SDL_GetTicks(), hwdata->stopTicks)) {
+                XINPUT_VIBRATION vibration = { 0, 0 };
+                hwdata->stopTicks = 0;
+                XINPUTSETSTATE(hwdata->userid, &vibration);
+            }
+        }
+        SDL_UnlockMutex(hwdata->mutex);
+    }
+
+    return 0;
+}
+
+static int
+SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 userid)
+{
+    char threadName[32];
+    XINPUT_VIBRATION vibration = { 0, 0 };  /* stop any current vibration */
+    XINPUTSETSTATE(userid, &vibration);
+
+    haptic->supported = SDL_HAPTIC_LEFTRIGHT;
+
+    haptic->neffects = 1;
+    haptic->nplaying = 1;
+
+    /* Prepare effects memory. */
+    haptic->effects = (struct haptic_effect *)
+        SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
+    if (haptic->effects == NULL) {
+        return SDL_OutOfMemory();
+    }
+    /* Clear the memory */
+    SDL_memset(haptic->effects, 0,
+        sizeof(struct haptic_effect) * haptic->neffects);
+
+    haptic->hwdata = (struct haptic_hwdata *) SDL_malloc(sizeof(*haptic->hwdata));
+    if (haptic->hwdata == NULL) {
+        SDL_free(haptic->effects);
+        haptic->effects = NULL;
+        return SDL_OutOfMemory();
+    }
+    SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
+
+    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
+#if SDL_DYNAMIC_API
+    haptic->hwdata->thread = SDL_CreateThread_REAL(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
+#else
+    haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
+#endif
+#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;
+}
+
+int
+SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
+{
+    return SDL_XINPUT_HapticOpenFromUserIndex(haptic, item->userid);
+}
+
+int
+SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+    return (haptic->hwdata->userid == joystick->hwdata->userid);
+}
+
+int
+SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+    SDL_hapticlist_item *item;
+    int index = 0;
+
+    /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
+    for (item = SDL_hapticlist; item != NULL; item = item->next) {
+        if (item->bXInputHaptic && item->userid == joystick->hwdata->userid) {
+            haptic->index = index;
+            return SDL_XINPUT_HapticOpenFromUserIndex(haptic, joystick->hwdata->userid);
+        }
+        ++index;
+    }
+
+    SDL_SetError("Couldn't find joystick in haptic device list");
+    return -1;
+}
+
+void
+SDL_XINPUT_HapticClose(SDL_Haptic * haptic)
+{
+    haptic->hwdata->stopThread = 1;
+    SDL_WaitThread(haptic->hwdata->thread, NULL);
+    SDL_DestroyMutex(haptic->hwdata->mutex);
+}
+
+void
+SDL_XINPUT_HapticQuit(void)
+{
+    if (loaded_xinput) {
+        WIN_UnloadXInputDLL();
+        loaded_xinput = SDL_FALSE;
+    }
+}
+
+int
+SDL_XINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
+{
+    SDL_assert(base->type == SDL_HAPTIC_LEFTRIGHT);  /* should catch this at higher level */
+    return SDL_XINPUT_HapticUpdateEffect(haptic, effect, base);
+}
+
+int
+SDL_XINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
+{
+    XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
+    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;
+}
+
+int
+SDL_XINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
+{
+    XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
+    SDL_assert(effect->effect.type == SDL_HAPTIC_LEFTRIGHT);  /* should catch this at higher level */
+    SDL_LockMutex(haptic->hwdata->mutex);
+    if (effect->effect.leftright.length == SDL_HAPTIC_INFINITY || iterations == SDL_HAPTIC_INFINITY) {
+        haptic->hwdata->stopTicks = SDL_HAPTIC_INFINITY;
+    } else if ((!effect->effect.leftright.length) || (!iterations)) {
+        /* do nothing. Effect runs for zero milliseconds. */
+    } else {
+        haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations);
+        if ((haptic->hwdata->stopTicks == SDL_HAPTIC_INFINITY) || (haptic->hwdata->stopTicks == 0)) {
+            haptic->hwdata->stopTicks = 1;  /* fix edge cases. */
+        }
+    }
+    SDL_UnlockMutex(haptic->hwdata->mutex);
+    return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1;
+}
+
+int
+SDL_XINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    XINPUT_VIBRATION vibration = { 0, 0 };
+    SDL_LockMutex(haptic->hwdata->mutex);
+    haptic->hwdata->stopTicks = 0;
+    SDL_UnlockMutex(haptic->hwdata->mutex);
+    return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
+}
+
+void
+SDL_XINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    SDL_XINPUT_HapticStopEffect(haptic, effect);
+}
+
+int
+SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticPause(SDL_Haptic * haptic)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticUnpause(SDL_Haptic * haptic)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticStopAll(SDL_Haptic * haptic)
+{
+    XINPUT_VIBRATION vibration = { 0, 0 };
+    SDL_LockMutex(haptic->hwdata->mutex);
+    haptic->hwdata->stopTicks = 0;
+    SDL_UnlockMutex(haptic->hwdata->mutex);
+    return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
+}
+
+#else /* !SDL_HAPTIC_XINPUT */
+
+
+int
+SDL_XINPUT_HapticInit(void)
+{
+    return 0;
+}
+
+int
+SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
+{
+    return SDL_Unsupported();
+}
+
+void
+SDL_XINPUT_HapticClose(SDL_Haptic * haptic)
+{
+}
+
+void
+SDL_XINPUT_HapticQuit(void)
+{
+}
+
+int
+SDL_XINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    return SDL_Unsupported();
+}
+
+void
+SDL_XINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+}
+
+int
+SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticPause(SDL_Haptic * haptic)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticUnpause(SDL_Haptic * haptic)
+{
+    return SDL_Unsupported();
+}
+
+int
+SDL_XINPUT_HapticStopAll(SDL_Haptic * haptic)
+{
+    return SDL_Unsupported();
+}
+
+#endif /* SDL_HAPTIC_XINPUT */
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/haptic/windows/SDL_xinputhaptic_c.h	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,47 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_haptic.h"
+#include "SDL_windowshaptic_c.h"
+
+
+extern int SDL_XINPUT_HapticInit(void);
+extern int SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid);
+extern int SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid);
+extern int SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item);
+extern int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick);
+extern int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick);
+extern void SDL_XINPUT_HapticClose(SDL_Haptic * haptic);
+extern void SDL_XINPUT_HapticQuit(void);
+extern int SDL_XINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base);
+extern int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data);
+extern int SDL_XINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations);
+extern int SDL_XINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect);
+extern int SDL_XINPUT_HapticSetGain(SDL_Haptic * haptic, int gain);
+extern int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter);
+extern int SDL_XINPUT_HapticPause(SDL_Haptic * haptic);
+extern int SDL_XINPUT_HapticUnpause(SDL_Haptic * haptic);
+extern int SDL_XINPUT_HapticStopAll(SDL_Haptic * haptic);
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/joystick/SDL_gamecontroller.c	Thu Jul 03 17:36:08 2014 -0300
+++ b/src/joystick/SDL_gamecontroller.c	Thu Jul 03 15:39:55 2014 -0700
@@ -88,9 +88,7 @@
 } ControllerMapping_t;
 
 static ControllerMapping_t *s_pSupportedControllers = NULL;
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
 static ControllerMapping_t *s_pXInputMapping = NULL;
-#endif
 
 /* The SDL game controller structure */
 struct _SDL_GameController
@@ -260,12 +258,10 @@
  */
 ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
 {
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
     if (SDL_SYS_IsXInputGamepad_DeviceIndex(device_index) && s_pXInputMapping) {
         return s_pXInputMapping;
     }
     else
-#endif
     {
         SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID(device_index);
         return SDL_PrivateGetControllerMappingForGUID(&jGUID);
@@ -669,19 +665,15 @@
     char *pchMapping;
     SDL_JoystickGUID jGUID;
     ControllerMapping_t *pControllerMapping;
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
     SDL_bool is_xinput_mapping = SDL_FALSE;
-#endif
 
     pchGUID = SDL_PrivateGetControllerGUIDFromMappingString(mappingString);
     if (!pchGUID) {
         return SDL_SetError("Couldn't parse GUID from %s", mappingString);
     }
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
     if (!SDL_strcasecmp(pchGUID, "xinput")) {
         is_xinput_mapping = SDL_TRUE;
     }
-#endif
     jGUID = SDL_JoystickGetGUIDFromString(pchGUID);
     SDL_free(pchGUID);
 
@@ -714,11 +706,9 @@
             SDL_free(pchMapping);
             return SDL_OutOfMemory();
         }
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
         if (is_xinput_mapping) {
             s_pXInputMapping = pControllerMapping;
         }
-#endif
         pControllerMapping->guid = jGUID;
         pControllerMapping->name = pchName;
         pControllerMapping->mapping = pchMapping;
--- a/src/joystick/SDL_gamecontrollerdb.h	Thu Jul 03 17:36:08 2014 -0300
+++ b/src/joystick/SDL_gamecontrollerdb.h	Thu Jul 03 15:39:55 2014 -0700
@@ -31,7 +31,10 @@
  */
 static const char *s_ControllerMappings [] =
 {
-#ifdef SDL_JOYSTICK_DINPUT
+#if SDL_JOYSTICK_XINPUT
+    "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+#endif
+#if 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,",
@@ -41,10 +44,8 @@
     "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,",
     "4c05c405000000000000504944564944,PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
-    "xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
-#elif defined(SDL_JOYSTICK_XINPUT)
-	"xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
-#elif defined(__MACOSX__)
+#endif
+#if 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,",
@@ -53,7 +54,8 @@
     "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,",
     "4c05000000000000c405000000000000,PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
     "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__)
+#endif
+#if 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,",
@@ -70,7 +72,8 @@
     "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,",
     "030000005e0400009102000007010000,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,",
-#elif defined(__ANDROID__)
+#endif
+#if defined(__ANDROID__)
     "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
 #endif
     NULL
--- a/src/joystick/SDL_sysjoystick.h	Thu Jul 03 17:36:08 2014 -0300
+++ b/src/joystick/SDL_sysjoystick.h	Thu Jul 03 15:39:55 2014 -0700
@@ -20,6 +20,9 @@
 */
 #include "../SDL_internal.h"
 
+#ifndef _SDL_sysjoystick_h
+#define _SDL_sysjoystick_h
+
 /* This is the system specific header for the SDL joystick API */
 
 #include "SDL_joystick.h"
@@ -105,9 +108,9 @@
 /* Function to return the stable GUID for a opened joystick */
 extern SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick);
 
-#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
 /* Function returns SDL_TRUE if this device is an XInput gamepad */
-extern SDL_bool SDL_SYS_IsXInputGamepad_DeviceIndex( int device_index );
-#endif
+extern SDL_bool SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index);
+
+#endif /* _SDL_sysjoystick_h */
 
 /* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/joystick/windows/SDL_dinputjoystick.c	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,900 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "../SDL_sysjoystick.h"
+#include "SDL_windowsjoystick_c.h"
+#include "SDL_dinputjoystick_c.h"
+#include "SDL_xinputjoystick_c.h"
+
+
+#if SDL_JOYSTICK_DINPUT
+
+#ifndef DIDFT_OPTIONAL
+#define DIDFT_OPTIONAL      0x80000000
+#endif
+
+#define INPUT_QSIZE 32      /* Buffer up to 32 input messages */
+#define AXIS_MIN    -32768  /* minimum value for axis coordinate */
+#define AXIS_MAX    32767   /* maximum value for axis coordinate */
+#define JOY_AXIS_THRESHOLD  (((AXIS_MAX)-(AXIS_MIN))/100)   /* 1% motion */
+
+/* external variables referenced. */
+extern HWND SDL_HelperWindow;
+
+/* local variables */
+static SDL_bool coinitialized = SDL_FALSE;
+static LPDIRECTINPUT8 dinput = NULL;
+static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
+static UINT SDL_RawDevListCount = 0;
+
+/* Taken from Wine - Thanks! */
+static DIOBJECTDATAFORMAT dfDIJoystick2[] = {
+        { &GUID_XAxis, DIJOFS_X, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_YAxis, DIJOFS_Y, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_ZAxis, DIJOFS_Z, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RxAxis, DIJOFS_RX, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RyAxis, DIJOFS_RY, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RzAxis, DIJOFS_RZ, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_POV, DIJOFS_POV(0), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_POV, DIJOFS_POV(1), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_POV, DIJOFS_POV(2), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_POV, DIJOFS_POV(3), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(0), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(1), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(2), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(3), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(4), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(5), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(6), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(7), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(8), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(9), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(10), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(11), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(12), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(13), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(14), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(15), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(16), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(17), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(18), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(19), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(20), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(21), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(22), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(23), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(24), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(25), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(26), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(27), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(28), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(29), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(30), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(31), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(32), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(33), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(34), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(35), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(36), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(37), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(38), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(39), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(40), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(41), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(42), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(43), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(44), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(45), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(46), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(47), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(48), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(49), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(50), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(51), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(52), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(53), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(54), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(55), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(56), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(57), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(58), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(59), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(60), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(61), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(62), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(63), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(64), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(65), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(66), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(67), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(68), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(69), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(70), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(71), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(72), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(73), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(74), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(75), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(76), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(77), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(78), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(79), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(80), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(81), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(82), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(83), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(84), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(85), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(86), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(87), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(88), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(89), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(90), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(91), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(92), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(93), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(94), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(95), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(96), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(97), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(98), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(99), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(100), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(101), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(102), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(103), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(104), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(105), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(106), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(107), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(108), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(109), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(110), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(111), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(112), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(113), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(114), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(115), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(116), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(117), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(118), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(119), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(120), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(121), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(122), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(123), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(124), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(125), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(126), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { NULL, DIJOFS_BUTTON(127), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lVX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lVY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lVZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lVRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lVRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lVRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lAX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lAY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lAZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lARx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lARy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lARz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lFX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lFY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lFZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lFRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lFRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lFRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+        { &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
+};
+
+const DIDATAFORMAT c_dfDIJoystick2 = {
+    sizeof(DIDATAFORMAT),
+    sizeof(DIOBJECTDATAFORMAT),
+    DIDF_ABSAXIS,
+    sizeof(DIJOYSTATE2),
+    SDL_arraysize(dfDIJoystick2),
+    dfDIJoystick2
+};
+
+/* Convert a DirectInput return code to a text message */
+static int
+SetDIerror(const char *function, HRESULT code)
+{
+    /*
+    return SDL_SetError("%s() [%s]: %s", function,
+    DXGetErrorString9A(code), DXGetErrorDescription9A(code));
+    */
+    return SDL_SetError("%s() DirectX error %d", function, code);
+}
+
+static SDL_bool
+SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
+{
+    static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+    static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+    static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+
+    static const GUID *s_XInputProductGUID[] = {
+        &IID_ValveStreamingGamepad,
+        &IID_X360WiredGamepad,   /* Microsoft's wired X360 controller for Windows. */
+        &IID_X360WirelessGamepad /* Microsoft's wireless X360 controller for Windows. */
+    };
+
+    size_t iDevice;
+    UINT i;
+
+    if (!SDL_XINPUT_Enabled()) {
+        return SDL_FALSE;
+    }
+
+    /* Check for well known XInput device GUIDs */
+    /* This lets us skip RAWINPUT for popular devices. Also, we need to do this for the Valve Streaming Gamepad because it's virtualized and doesn't show up in the device list. */
+    for (iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice) {
+        if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
+            return SDL_TRUE;
+        }
+    }
+
+    /* Go through RAWINPUT (WinXP and later) to find HID devices. */
+    /* Cache this if we end up using it. */
+    if (SDL_RawDevList == NULL) {
+        if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
+            return SDL_FALSE;  /* oh well. */
+        }
+
+        SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount);
+        if (SDL_RawDevList == NULL) {
+            SDL_OutOfMemory();
+            return SDL_FALSE;
+        }
+
+        if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) {
+            SDL_free(SDL_RawDevList);
+            SDL_RawDevList = NULL;
+            return SDL_FALSE;  /* oh well. */
+        }
+    }
+
+    for (i = 0; i < SDL_RawDevListCount; i++) {
+        RID_DEVICE_INFO rdi;
+        char devName[128];
+        UINT rdiSize = sizeof(rdi);
+        UINT nameSize = SDL_arraysize(devName);
+
+        rdi.cbSize = sizeof(rdi);
+        if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
+            (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
+            (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
+            (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
+            (SDL_strstr(devName, "IG_") != NULL)) {
+            return SDL_TRUE;
+        }
+    }
+
+    return SDL_FALSE;
+}
+
+int
+SDL_DINPUT_JoystickInit(void)
+{
+    HRESULT result;
+    HINSTANCE instance;
+
+    result = WIN_CoInitialize();
+    if (FAILED(result)) {
+        return SetDIerror("CoInitialize", result);
+    }
+
+    coinitialized = SDL_TRUE;
+
+    result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
+        &IID_IDirectInput8, (LPVOID)&dinput);
+
+    if (FAILED(result)) {
+        return SetDIerror("CoCreateInstance", result);
+    }
+
+    /* Because we used CoCreateInstance, we need to Initialize it, first. */
+    instance = GetModuleHandle(NULL);
+    if (instance == NULL) {
+        return SDL_SetError("GetModuleHandle() failed with error code %d.", GetLastError());
+    }
+    result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
+
+    if (FAILED(result)) {
+        return SetDIerror("IDirectInput::Initialize", result);
+    }
+    return 0;
+}
+
+/* helper function for direct input, gets called for each connected joystick */
+static BOOL CALLBACK
+EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
+{
+    JoyStick_DeviceData *pNewJoystick;
+    JoyStick_DeviceData *pPrevJoystick = NULL;
+
+    if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) {
+        return DIENUM_CONTINUE;  /* ignore XInput devices here, keep going. */
+    }
+
+    pNewJoystick = *(JoyStick_DeviceData **)pContext;
+    while (pNewJoystick) {
+        if (!SDL_memcmp(&pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance))) {
+            /* if we are replacing the front of the list then update it */
+            if (pNewJoystick == *(JoyStick_DeviceData **)pContext) {
+                *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
+            } else if (pPrevJoystick) {
+                pPrevJoystick->pNext = pNewJoystick->pNext;
+            }
+
+            pNewJoystick->pNext = SYS_Joystick;
+            SYS_Joystick = pNewJoystick;
+
+            return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
+        }
+
+        pPrevJoystick = pNewJoystick;
+        pNewJoystick = pNewJoystick->pNext;
+    }
+
+    pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
+    if (!pNewJoystick) {
+        return DIENUM_CONTINUE; /* better luck next time? */
+    }
+
+    SDL_zerop(pNewJoystick);
+    pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
+    if (!pNewJoystick->joystickname) {
+        SDL_free(pNewJoystick);
+        return DIENUM_CONTINUE; /* better luck next time? */
+    }
+
+    SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
+        sizeof(DIDEVICEINSTANCE));
+
+    SDL_memcpy(&pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid));
+    SDL_SYS_AddJoystickDevice(pNewJoystick);
+
+    return DIENUM_CONTINUE; /* get next device, please */
+}
+
+void
+SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
+{
+    IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, pContext, DIEDFL_ATTACHEDONLY);
+
+    if (SDL_RawDevList) {
+        SDL_free(SDL_RawDevList);  /* in case we used this in DirectInput detection */
+        SDL_RawDevList = NULL;
+    }
+    SDL_RawDevListCount = 0;
+}
+
+static BOOL CALLBACK
+EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
+{
+    SDL_Joystick *joystick = (SDL_Joystick *)pvRef;
+    HRESULT result;
+    input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
+
+    if (dev->dwType & DIDFT_BUTTON) {
+        in->type = BUTTON;
+        in->num = joystick->nbuttons;
+        in->ofs = DIJOFS_BUTTON(in->num);
+        joystick->nbuttons++;
+    } else if (dev->dwType & DIDFT_POV) {
+        in->type = HAT;
+        in->num = joystick->nhats;
+        in->ofs = DIJOFS_POV(in->num);
+        joystick->nhats++;
+    } else if (dev->dwType & DIDFT_AXIS) {
+        DIPROPRANGE diprg;
+        DIPROPDWORD dilong;
+
+        in->type = AXIS;
+        in->num = joystick->naxes;
+        if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType)))
+            in->ofs = DIJOFS_X;
+        else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType)))
+            in->ofs = DIJOFS_Y;
+        else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType)))
+            in->ofs = DIJOFS_Z;
+        else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType)))
+            in->ofs = DIJOFS_RX;
+        else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType)))
+            in->ofs = DIJOFS_RY;
+        else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType)))
+            in->ofs = DIJOFS_RZ;
+        else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) {
+            in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders);
+            ++joystick->hwdata->NumSliders;
+        } else {
+            return DIENUM_CONTINUE; /* not an axis we can grok */
+        }
+
+        diprg.diph.dwSize = sizeof(diprg);
+        diprg.diph.dwHeaderSize = sizeof(diprg.diph);
+        diprg.diph.dwObj = dev->dwType;
+        diprg.diph.dwHow = DIPH_BYID;
+        diprg.lMin = AXIS_MIN;
+        diprg.lMax = AXIS_MAX;
+
+        result =
+            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
+            DIPROP_RANGE, &diprg.diph);
+        if (FAILED(result)) {
+            return DIENUM_CONTINUE;     /* don't use this axis */
+        }
+
+        /* Set dead zone to 0. */
+        dilong.diph.dwSize = sizeof(dilong);
+        dilong.diph.dwHeaderSize = sizeof(dilong.diph);
+        dilong.diph.dwObj = dev->dwType;
+        dilong.diph.dwHow = DIPH_BYID;
+        dilong.dwData = 0;
+        result =
+            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
+            DIPROP_DEADZONE, &dilong.diph);
+        if (FAILED(result)) {
+            return DIENUM_CONTINUE;     /* don't use this axis */
+        }
+
+        joystick->naxes++;
+    } else {
+        /* not supported at this time */
+        return DIENUM_CONTINUE;
+    }
+
+    joystick->hwdata->NumInputs++;
+
+    if (joystick->hwdata->NumInputs == MAX_INPUTS) {
+        return DIENUM_STOP;     /* too many */
+    }
+
+    return DIENUM_CONTINUE;
+}
+
+/* Sort using the data offset into the DInput struct.
+ * This gives a reasonable ordering for the inputs.
+ */
+static int
+SortDevFunc(const void *a, const void *b)
+{
+    const input_t *inputA = (const input_t*)a;
+    const input_t *inputB = (const input_t*)b;
+
+    if (inputA->ofs < inputB->ofs)
+        return -1;
+    if (inputA->ofs > inputB->ofs)
+        return 1;
+    return 0;
+}
+
+/* Sort the input objects and recalculate the indices for each input. */
+static void
+SortDevObjects(SDL_Joystick *joystick)
+{
+    input_t *inputs = joystick->hwdata->Inputs;
+    int nButtons = 0;
+    int nHats = 0;
+    int nAxis = 0;
+    int n;
+
+    SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
+
+    for (n = 0; n < joystick->hwdata->NumInputs; n++) {
+        switch (inputs[n].type) {
+        case BUTTON:
+            inputs[n].num = nButtons;
+            nButtons++;
+            break;
+
+        case HAT:
+            inputs[n].num = nHats;
+            nHats++;
+            break;
+
+        case AXIS:
+            inputs[n].num = nAxis;
+            nAxis++;
+            break;
+        }
+    }
+}
+
+int
+SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
+{
+    HRESULT result;
+    LPDIRECTINPUTDEVICE8 device;
+    DIPROPDWORD dipdw;
+
+    joystick->hwdata->buffered = SDL_TRUE;
+    joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
+
+    SDL_zero(dipdw);
+    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
+    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+
+    result =
+        IDirectInput8_CreateDevice(dinput,
+        &(joystickdevice->dxdevice.guidInstance), &device, NULL);
+    if (FAILED(result)) {
+        return SetDIerror("IDirectInput::CreateDevice", result);
+    }
+
+    /* Now get the IDirectInputDevice8 interface, instead. */
+    result = IDirectInputDevice8_QueryInterface(device,
+        &IID_IDirectInputDevice8,
+        (LPVOID *)& joystick->
+        hwdata->InputDevice);
+    /* We are done with this object.  Use the stored one from now on. */
+    IDirectInputDevice8_Release(device);
+
+    if (FAILED(result)) {
+        return SetDIerror("IDirectInputDevice8::QueryInterface", result);
+    }
+
+    /* Acquire shared access. Exclusive access is required for forces,
+    * though. */
+    result =
+        IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
+        InputDevice, SDL_HelperWindow,
+        DISCL_EXCLUSIVE |
+        DISCL_BACKGROUND);
+    if (FAILED(result)) {
+        return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result);
+    }
+
+    /* Use the extended data structure: DIJOYSTATE2. */
+    result =
+        IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
+        &c_dfDIJoystick2);
+    if (FAILED(result)) {
+        return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
+    }
+
+    /* Get device capabilities */
+    result =
+        IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
+        &joystick->hwdata->Capabilities);
+    if (FAILED(result)) {
+        return SetDIerror("IDirectInputDevice8::GetCapabilities", result);
+    }
+
+    /* Force capable? */
+    if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
+
+        result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
+        if (FAILED(result)) {
+            return SetDIerror("IDirectInputDevice8::Acquire", result);
+        }
+
+        /* reset all actuators. */
+        result =
+            IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
+            InputDevice,
+            DISFFC_RESET);
+
+        /* Not necessarily supported, ignore if not supported.
+        if (FAILED(result)) {
+        return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result);
+        }
+        */
+
+        result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
+
+        if (FAILED(result)) {
+            return SetDIerror("IDirectInputDevice8::Unacquire", result);
+        }
+
+        /* Turn on auto-centering for a ForceFeedback device (until told
+        * otherwise). */
+        dipdw.diph.dwObj = 0;
+        dipdw.diph.dwHow = DIPH_DEVICE;
+        dipdw.dwData = DIPROPAUTOCENTER_ON;
+
+        result =
+            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
+            DIPROP_AUTOCENTER, &dipdw.diph);
+
+        /* Not necessarily supported, ignore if not supported.
+        if (FAILED(result)) {
+        return SetDIerror("IDirectInputDevice8::SetProperty", result);
+        }
+        */
+    }
+
+    /* What buttons and axes does it have? */
+    IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
+        EnumDevObjectsCallback, joystick,
+        DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
+
+    /* Reorder the input objects. Some devices do not report the X axis as
+    * the first axis, for example. */
+    SortDevObjects(joystick);
+
+    dipdw.diph.dwObj = 0;
+    dipdw.diph.dwHow = DIPH_DEVICE;
+    dipdw.dwData = INPUT_QSIZE;
+
+    /* Set the buffer size */
+    result =
+        IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
+        DIPROP_BUFFERSIZE, &dipdw.diph);
+
+    if (result == DI_POLLEDDEVICE) {
+        /* This device doesn't support buffering, so we're forced
+         * to use less reliable polling. */
+        joystick->hwdata->buffered = SDL_FALSE;
+    } else if (FAILED(result)) {
+        return SetDIerror("IDirectInputDevice8::SetProperty", result);
+    }
+    return 0;
+}
+
+static Uint8
+TranslatePOV(DWORD value)
+{
+    const int HAT_VALS[] = {
+        SDL_HAT_UP,
+        SDL_HAT_UP | SDL_HAT_RIGHT,
+        SDL_HAT_RIGHT,
+        SDL_HAT_DOWN | SDL_HAT_RIGHT,
+        SDL_HAT_DOWN,
+        SDL_HAT_DOWN | SDL_HAT_LEFT,
+        SDL_HAT_LEFT,
+        SDL_HAT_UP | SDL_HAT_LEFT
+    };
+
+    if (LOWORD(value) == 0xFFFF)
+        return SDL_HAT_CENTERED;
+
+    /* Round the value up: */
+    value += 4500 / 2;
+    value %= 36000;
+    value /= 4500;
+
+    if (value >= 8)
+        return SDL_HAT_CENTERED;        /* shouldn't happen */
+
+    return HAT_VALS[value];
+}
+
+static void
+UpdateDINPUTJoystickState_Buffered(SDL_Joystick * joystick)
+{
+    int i;
+    HRESULT result;
+    DWORD numevents;
+    DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
+
+    numevents = INPUT_QSIZE;
+    result =
+        IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
+        sizeof(DIDEVICEOBJECTDATA), evtbuf,
+        &numevents, 0);
+    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
+        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
+        result =
+            IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
+            sizeof(DIDEVICEOBJECTDATA),
+            evtbuf, &numevents, 0);
+    }
+
+    /* Handle the events or punt */
+    if (FAILED(result)) {
+        joystick->hwdata->send_remove_event = SDL_TRUE;
+        joystick->hwdata->removed = SDL_TRUE;
+        return;
+    }
+
+    for (i = 0; i < (int)numevents; ++i) {
+        int j;
+
+        for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
+            const input_t *in = &joystick->hwdata->Inputs[j];
+
+            if (evtbuf[i].dwOfs != in->ofs)
+                continue;
+
+            switch (in->type) {
+            case AXIS:
+                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData);
+                break;
+            case BUTTON:
+                SDL_PrivateJoystickButton(joystick, in->num,
+                    (Uint8)(evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED));
+                break;
+            case HAT:
+                {
+                    Uint8 pos = TranslatePOV(evtbuf[i].dwData);
+                    SDL_PrivateJoystickHat(joystick, in->num, pos);
+                }
+                break;
+            }
+        }
+    }
+}
+
+/* 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.
+ */
+static void
+UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick)
+{
+    DIJOYSTATE2 state;
+    HRESULT result;
+    int i;
+
+    result =
+        IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
+        sizeof(DIJOYSTATE2), &state);
+    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
+        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
+        result =
+            IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
+            sizeof(DIJOYSTATE2), &state);
+    }
+
+    if (result != DI_OK) {
+        joystick->hwdata->send_remove_event = SDL_TRUE;
+        joystick->hwdata->removed = SDL_TRUE;
+        return;
+    }
+
+    /* Set each known axis, button and POV. */
+    for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
+        const input_t *in = &joystick->hwdata->Inputs[i];
+
+        switch (in->type) {
+        case AXIS:
+            switch (in->ofs) {
+            case DIJOFS_X:
+                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX);
+                break;
+            case DIJOFS_Y:
+                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY);
+                break;
+            case DIJOFS_Z:
+                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ);
+                break;
+            case DIJOFS_RX:
+                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx);
+                break;
+            case DIJOFS_RY:
+                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy);
+                break;
+            case DIJOFS_RZ:
+                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz);
+                break;
+            case DIJOFS_SLIDER(0):
+                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]);
+                break;
+            case DIJOFS_SLIDER(1):
+                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]);
+                break;
+            }
+            break;
+
+        case BUTTON:
+            SDL_PrivateJoystickButton(joystick, in->num,
+                (Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
+            break;
+        case HAT:
+        {
+            Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
+            SDL_PrivateJoystickHat(joystick, in->num, pos);
+            break;
+        }
+        }
+    }
+}
+
+void
+SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
+{
+    HRESULT result;
+
+    result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
+    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
+        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
+        IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
+    }
+
+    if (joystick->hwdata->buffered) {
+        UpdateDINPUTJoystickState_Buffered(joystick);
+    } else {
+        UpdateDINPUTJoystickState_Polled(joystick);
+    }
+}
+
+void
+SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
+{
+    IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
+    IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
+}
+
+void
+SDL_DINPUT_JoystickQuit(void)
+{
+    if (dinput != NULL) {
+        IDirectInput8_Release(dinput);
+        dinput = NULL;
+    }
+
+    if (coinitialized) {
+        WIN_CoUninitialize();
+        coinitialized = SDL_FALSE;
+    }
+}
+
+#else /* !SDL_JOYSTICK_DINPUT */
+
+
+int
+SDL_DINPUT_JoystickInit(void)
+{
+    return 0;
+}
+
+void
+SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
+{
+}
+
+int
+SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
+{
+    return SDL_Unsupported();
+}
+
+void
+SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
+{
+}
+
+void
+SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
+{
+}
+
+void
+SDL_DINPUT_JoystickQuit(void)
+{
+}
+
+#endif /* SDL_JOYSTICK_DINPUT */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/joystick/windows/SDL_dinputjoystick_c.h	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,30 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+extern int SDL_DINPUT_JoystickInit(void);
+extern void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext);
+extern int SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice);
+extern void SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick);
+extern void SDL_DINPUT_JoystickClose(SDL_Joystick * joystick);
+extern void SDL_DINPUT_JoystickQuit(void);
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/joystick/windows/SDL_dxjoystick.c	Thu Jul 03 17:36:08 2014 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1661 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-#include "../../SDL_internal.h"
-
-#ifdef SDL_JOYSTICK_DINPUT
-
-/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
- * A. Formiga's WINMM driver.
- *
- * Hats and sliders are completely untested; the app I'm writing this for mostly
- * doesn't use them and I don't own any joysticks with them.
- *
- * We don't bother to use event notification here.  It doesn't seem to work
- * with polled devices, and it's fine to call IDirectInputDevice8_GetDeviceData and
- * let it return 0 events. */
-
-#include "SDL_error.h"
-#include "SDL_assert.h"
-#include "SDL_events.h"
-#include "SDL_thread.h"
-#include "SDL_timer.h"
-#include "SDL_mutex.h"
-#include "SDL_events.h"
-#include "SDL_hints.h"
-#include "SDL_joystick.h"
-#include "../SDL_sysjoystick.h"
-#if !SDL_EVENTS_DISABLED
-#include "../../events/SDL_events_c.h"
-#endif
-#include "../../core/windows/SDL_windows.h"
-
-#define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
-#include "SDL_dxjoystick_c.h"
-
-#if SDL_HAPTIC_DINPUT
-#include "../../haptic/windows/SDL_syshaptic_c.h"    /* For haptic hot plugging */
-#endif
-
-#ifndef DIDFT_OPTIONAL
-#define DIDFT_OPTIONAL      0x80000000
-#endif
-
-DEFINE_GUID(GUID_DEVINTERFACE_HID, 0x4D1E55B2L, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30);
-
-
-#define INPUT_QSIZE 32      /* Buffer up to 32 input messages */
-#define AXIS_MIN    -32768  /* minimum value for axis coordinate */
-#define AXIS_MAX    32767   /* maximum value for axis coordinate */
-#define JOY_AXIS_THRESHOLD  (((AXIS_MAX)-(AXIS_MIN))/100)   /* 1% motion */
-
-/* external variables referenced. */
-extern HWND SDL_HelperWindow;
-
-
-/* local variables */
-static SDL_bool coinitialized = SDL_FALSE;
-static LPDIRECTINPUT8 dinput = NULL;
-static SDL_bool s_bDeviceAdded = SDL_FALSE;
-static SDL_bool s_bDeviceRemoved = SDL_FALSE;
-static SDL_JoystickID s_nInstanceID = -1;
-static SDL_cond *s_condJoystickThread = NULL;
-static SDL_mutex *s_mutexJoyStickEnum = NULL;
-static SDL_Thread *s_threadJoystick = NULL;
-static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
-static SDL_bool s_bXInputEnabled = SDL_TRUE;
-
-XInputGetState_t SDL_XInputGetState = NULL;
-XInputSetState_t SDL_XInputSetState = NULL;
-XInputGetCapabilities_t SDL_XInputGetCapabilities = NULL;
-DWORD SDL_XInputVersion = 0;
-
-static HANDLE s_pXInputDLL = 0;
-static int s_XInputDLLRefCount = 0;
-
-int
-WIN_LoadXInputDLL(void)
-{
-    DWORD version = 0;
-
-    if (s_pXInputDLL) {
-        SDL_assert(s_XInputDLLRefCount > 0);
-        s_XInputDLLRefCount++;
-        return 0;  /* already loaded */
-    }
-
-    version = (1 << 16) | 4;
-    s_pXInputDLL = LoadLibrary(L"XInput1_4.dll");  /* 1.4 Ships with Windows 8. */
-    if (!s_pXInputDLL) {
-        version = (1 << 16) | 3;
-        s_pXInputDLL = LoadLibrary(L"XInput1_3.dll");  /* 1.3 Ships with Vista and Win7, can be installed as a redistributable component. */
-    }
-    if (!s_pXInputDLL) {
-        s_pXInputDLL = LoadLibrary(L"bin\\XInput1_3.dll");
-    }
-    if (!s_pXInputDLL) {
-        return -1;
-    }
-
-    SDL_assert(s_XInputDLLRefCount == 0);
-    SDL_XInputVersion = version;
-    s_XInputDLLRefCount = 1;
-
-    /* 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think... */
-    SDL_XInputGetState = (XInputGetState_t)GetProcAddress((HMODULE)s_pXInputDLL, (LPCSTR)100);
-    SDL_XInputSetState = (XInputSetState_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputSetState");
-    SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputGetCapabilities");
-    if (!SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities) {
-        WIN_UnloadXInputDLL();
-        return -1;
-    }
-
-    return 0;
-}
-
-void
-WIN_UnloadXInputDLL(void)
-{
-    if (s_pXInputDLL) {
-        SDL_assert(s_XInputDLLRefCount > 0);
-        if (--s_XInputDLLRefCount == 0) {
-            FreeLibrary(s_pXInputDLL);
-            s_pXInputDLL = NULL;
-        }
-    } else {
-        SDL_assert(s_XInputDLLRefCount == 0);
-    }
-}
-
-
-extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
-                                       LPDIRECTINPUT * ppDI,
-                                       LPUNKNOWN punkOuter);
-struct JoyStick_DeviceData_
-{
-    SDL_JoystickGUID guid;
-    DIDEVICEINSTANCE dxdevice;
-    char *joystickname;
-    Uint8 send_add_event;
-    SDL_JoystickID nInstanceID;
-    SDL_bool bXInputDevice;
-    BYTE SubType;
-    Uint8 XInputUserId;
-    struct JoyStick_DeviceData_ *pNext;
-};
-
-typedef struct JoyStick_DeviceData_ JoyStick_DeviceData;
-
-static JoyStick_DeviceData *SYS_Joystick;    /* array to hold joystick ID values */
-
-/* local prototypes */
-static int SetDIerror(const char *function, HRESULT code);
-static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE *
-                                           pdidInstance, VOID * pContext);
-static BOOL CALLBACK EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev,
-                                            LPVOID pvRef);
-static void SortDevObjects(SDL_Joystick *joystick);
-static Uint8 TranslatePOV(DWORD value);
-
-/* Taken from Wine - Thanks! */
-DIOBJECTDATAFORMAT dfDIJoystick2[] = {
-  { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_POV,DIJOFS_POV(0),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
-  { &GUID_POV,DIJOFS_POV(1),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
-  { &GUID_POV,DIJOFS_POV(2),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
-  { &GUID_POV,DIJOFS_POV(3),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(11),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(12),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(13),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(14),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(15),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(16),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(17),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(18),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(19),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(20),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(21),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(22),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(23),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(24),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(25),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(26),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(27),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(28),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(29),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(30),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(31),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(32),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(33),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(34),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(35),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(36),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(37),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(38),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(39),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(40),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(41),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(42),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(43),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(44),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(45),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(46),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(47),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(48),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(49),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(50),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(51),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(52),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(53),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(54),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(55),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(56),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(57),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(58),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(59),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(60),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(61),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(62),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(63),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(64),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(65),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(66),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(67),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(68),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(69),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(70),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(71),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(72),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(73),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(74),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(75),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(76),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(77),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(78),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(79),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(80),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(81),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(82),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(83),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(84),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(85),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(86),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(87),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(88),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(89),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(90),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(91),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(92),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(93),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(94),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(95),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(96),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(97),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(98),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(99),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(100),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(101),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(102),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(103),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(104),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(105),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(106),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(107),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(108),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(109),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(110),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(111),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(112),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(113),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(114),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(115),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(116),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(117),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(118),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(119),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(120),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(121),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(122),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(123),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(124),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(125),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(126),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { NULL,DIJOFS_BUTTON(127),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
-  { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lVX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lVY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lVZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lVRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lVRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lVRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lAX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lAY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lAZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lARx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lARy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lARz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lFX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lFY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lFZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lFRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lFRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lFRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-  { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
-};
-
-const DIDATAFORMAT c_dfDIJoystick2 = {
-    sizeof(DIDATAFORMAT),
-    sizeof(DIOBJECTDATAFORMAT),
-    DIDF_ABSAXIS,
-    sizeof(DIJOYSTATE2),
-    SDL_arraysize(dfDIJoystick2),
-    dfDIJoystick2
-};
-
-
-/* Convert a DirectInput return code to a text message */
-static int
-SetDIerror(const char *function, HRESULT code)
-{
-    /*
-    return SDL_SetError("%s() [%s]: %s", function,
-                 DXGetErrorString9A(code), DXGetErrorDescription9A(code));
-     */
-    return SDL_SetError("%s() DirectX error %d", function, code);
-}
-
-
-#define SAFE_RELEASE(p)                             \
-{                                                   \
-    if (p) {                                        \
-        (p)->lpVtbl->Release((p));                  \
-        (p) = 0;                                    \
-    }                                               \
-}
-
-DEFINE_GUID(IID_ValveStreamingGamepad,  MAKELONG(0x28DE, 0x11FF),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
-DEFINE_GUID(IID_X360WiredGamepad,  MAKELONG(0x045E, 0x02A1),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
-DEFINE_GUID(IID_X360WirelessGamepad,  MAKELONG(0x045E, 0x028E),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
-
-static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
-static UINT SDL_RawDevListCount = 0;
-
-static SDL_bool
-SDL_XInputUseOldJoystickMapping()
-{
-	static int s_XInputUseOldJoystickMapping = -1;
-	if (s_XInputUseOldJoystickMapping < 0) {
-		const char *hint = SDL_GetHint(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING);
-		s_XInputUseOldJoystickMapping = (hint && *hint == '1') ? 1 : 0;
-	}
-	return (s_XInputUseOldJoystickMapping > 0);
-}
-
-static SDL_bool
-SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
-{
-    static const GUID *s_XInputProductGUID[] = {
-        &IID_ValveStreamingGamepad,
-        &IID_X360WiredGamepad,   /* Microsoft's wired X360 controller for Windows. */
-        &IID_X360WirelessGamepad /* Microsoft's wireless X360 controller for Windows. */
-    };
-
-    size_t iDevice;
-    UINT i;
-
-    if (!s_bXInputEnabled) {
-        return SDL_FALSE;
-    }
-
-    /* Check for well known XInput device GUIDs */
-    /* This lets us skip RAWINPUT for popular devices. Also, we need to do this for the Valve Streaming Gamepad because it's virtualized and doesn't show up in the device list. */
-    for (iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice) {
-        if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
-            return SDL_TRUE;
-        }
-    }
-
-    /* Go through RAWINPUT (WinXP and later) to find HID devices. */
-    /* Cache this if we end up using it. */
-    if (SDL_RawDevList == NULL) {
-        if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof (RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
-            return SDL_FALSE;  /* oh well. */
-        }
-
-        SDL_RawDevList = (PRAWINPUTDEVICELIST) SDL_malloc(sizeof (RAWINPUTDEVICELIST) * SDL_RawDevListCount);
-        if (SDL_RawDevList == NULL) {
-            SDL_OutOfMemory();
-            return SDL_FALSE;
-        }
-
-        if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof (RAWINPUTDEVICELIST)) == -1) {
-             SDL_free(SDL_RawDevList);
-             SDL_RawDevList = NULL;
-             return SDL_FALSE;  /* oh well. */
-        }
-    }
-
-    for (i = 0; i < SDL_RawDevListCount; i++) {
-        RID_DEVICE_INFO rdi;
-        char devName[128];
-        UINT rdiSize = sizeof (rdi);
-        UINT nameSize = SDL_arraysize(devName);
-
-        rdi.cbSize = sizeof (rdi);
-        if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
-             (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
-             (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
-             (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
-             (SDL_strstr(devName, "IG_") != NULL)) {
-             return SDL_TRUE;
-        }
-    }
-
-    return SDL_FALSE;
-}
-
-
-static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
-
-/* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal
- */
-LRESULT CALLBACK SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
-    switch (message) {
-    case WM_DEVICECHANGE:
-        switch (wParam) {
-        case DBT_DEVICEARRIVAL:
-            if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
-                s_bWindowsDeviceChanged = SDL_TRUE;
-            }
-            break;
-        case DBT_DEVICEREMOVECOMPLETE:
-            if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
-                s_bWindowsDeviceChanged = SDL_TRUE;
-            }
-            break;
-        }
-        return 0;
-    }
-
-    return DefWindowProc (hwnd, message, wParam, lParam);
-}
-
-
-DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \
-    0xC0, 0x4F, 0xB9, 0x51, 0xED);
-
-/* Function/thread to scan the system for joysticks.
- */
-static int
-SDL_JoystickThread(void *_data)
-{
-    HWND messageWindow = 0;
-    HDEVNOTIFY hNotify = 0;
-    DEV_BROADCAST_DEVICEINTERFACE dbh;
-    SDL_bool bOpenedXInputDevices[SDL_XINPUT_MAX_DEVICES];
-    WNDCLASSEX wincl;
-
-    SDL_zero(bOpenedXInputDevices);
-
-    WIN_CoInitialize();
-
-    SDL_memset(&wincl, 0x0, sizeof(wincl));
-    wincl.hInstance = GetModuleHandle(NULL);
-    wincl.lpszClassName = L"Message";
-    wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc;      /* This function is called by windows */
-    wincl.cbSize = sizeof (WNDCLASSEX);
-
-    if (!RegisterClassEx (&wincl)) {
-        return WIN_SetError("Failed to create register class for joystick autodetect");
-    }
-
-    messageWindow = (HWND)CreateWindowEx(0,  L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
-    if (!messageWindow) {
-        return WIN_SetError("Failed to create message window for joystick autodetect");
-    }
-
-    SDL_zero(dbh);
-
-    dbh.dbcc_size = sizeof(dbh);
-    dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
-    dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
-
-    hNotify = RegisterDeviceNotification(messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE);
-    if (!hNotify) {
-        return WIN_SetError("Failed to create notify device for joystick autodetect");
-    }
-
-    SDL_LockMutex(s_mutexJoyStickEnum);
-    while (s_bJoystickThreadQuit == SDL_FALSE) {
-        MSG messages;
-        SDL_bool bXInputChanged = SDL_FALSE;
-
-        SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 300);
-
-        while (s_bJoystickThreadQuit == SDL_FALSE && PeekMessage(&messages, messageWindow, 0, 0, PM_NOREMOVE)) {
-            if (GetMessage(&messages, messageWindow, 0, 0) != 0)  {
-                TranslateMessage(&messages);
-                DispatchMessage(&messages);
-            }
-        }
-
-        if (s_bXInputEnabled && XINPUTGETCAPABILITIES) {
-            /* scan for any change in XInput devices */
-            Uint8 userId;
-            for (userId = 0; userId < SDL_XINPUT_MAX_DEVICES; userId++) {
-                XINPUT_CAPABILITIES capabilities;
-                const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
-                const SDL_bool available = (result == ERROR_SUCCESS);
-                if (bOpenedXInputDevices[userId] != available) {
-                    bXInputChanged = SDL_TRUE;
-                    bOpenedXInputDevices[userId] = available;
-                }
-            }
-        }
-
-        if (s_bWindowsDeviceChanged || bXInputChanged) {
-            SDL_UnlockMutex(s_mutexJoyStickEnum);  /* let main thread go while we SDL_Delay(). */
-            SDL_Delay(300); /* wait for direct input to find out about this device */
-            SDL_LockMutex(s_mutexJoyStickEnum);
-
-            s_bDeviceRemoved = SDL_TRUE;
-            s_bDeviceAdded = SDL_TRUE;
-            s_bWindowsDeviceChanged = SDL_FALSE;
-        }
-    }
-    SDL_UnlockMutex(s_mutexJoyStickEnum);
-
-    if (hNotify)
-        UnregisterDeviceNotification(hNotify);
-
-    if (messageWindow)
-        DestroyWindow(messageWindow);
-
-    UnregisterClass(wincl.lpszClassName, wincl.hInstance);
-    messageWindow = 0;
-    WIN_CoUninitialize();
-    return 1;
-}
-
-
-/* Function to scan the system for joysticks.
- * This function should set SDL_numjoysticks to the number of available
- * joysticks.  Joystick 0 should be the system default joystick.
- * It should return 0, or -1 on an unrecoverable fatal error.
- */
-int
-SDL_SYS_JoystickInit(void)
-{
-    HRESULT result;
-    HINSTANCE instance;
-    const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
-    if (env && !SDL_atoi(env)) {
-        s_bXInputEnabled = SDL_FALSE;
-    }
-
-    result = WIN_CoInitialize();
-    if (FAILED(result)) {
-        return SetDIerror("CoInitialize", result);
-    }
-
-    coinitialized = SDL_TRUE;
-
-    result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
-                              &IID_IDirectInput8, (LPVOID)&dinput);
-
-    if (FAILED(result)) {
-        SDL_SYS_JoystickQuit();
-        return SetDIerror("CoCreateInstance", result);
-    }
-
-    /* Because we used CoCreateInstance, we need to Initialize it, first. */
-    instance = GetModuleHandle(NULL);
-    if (instance == NULL) {
-        SDL_SYS_JoystickQuit();
-        return SDL_SetError("GetModuleHandle() failed with error code %d.", GetLastError());
-    }
-    result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
-
-    if (FAILED(result)) {
-        SDL_SYS_JoystickQuit();
-        return SetDIerror("IDirectInput::Initialize", result);
-    }
-
-    if ((s_bXInputEnabled) && (WIN_LoadXInputDLL() == -1)) {
-        s_bXInputEnabled = SDL_FALSE;  /* oh well. */
-    }
-
-    s_mutexJoyStickEnum = SDL_CreateMutex();
-    s_condJoystickThread = SDL_CreateCond();
-    s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
-
-    SDL_SYS_JoystickDetect();
-
-    if (!s_threadJoystick) {
-        s_bJoystickThreadQuit = SDL_FALSE;
-        /* spin up the thread to detect hotplug of devices */
-#if defined(__WIN32__) && !defined(HAVE_LIBC)
-#undef SDL_CreateThread
-#if SDL_DYNAMIC_API
-        s_threadJoystick= SDL_CreateThread_REAL(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
-#else
-        s_threadJoystick= SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
-#endif
-#else
-        s_threadJoystick = SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL);
-#endif
-    }
-        return SDL_SYS_NumJoysticks();
-}
-
-/* return the number of joysticks that are connected right now */
-int SDL_SYS_NumJoysticks()
-{
-    int nJoysticks = 0;
-    JoyStick_DeviceData *device = SYS_Joystick;
-    while (device) {
-        nJoysticks++;
-        device = device->pNext;
-    }
-
-    return nJoysticks;
-}
-
-/* helper function for direct input, gets called for each connected joystick */
-static BOOL CALLBACK
-EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
-{
-    JoyStick_DeviceData *pNewJoystick;
-    JoyStick_DeviceData *pPrevJoystick = NULL;
-
-    if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) {
-        return DIENUM_CONTINUE;  /* ignore XInput devices here, keep going. */
-    }
-
-    pNewJoystick = *(JoyStick_DeviceData **)pContext;
-    while (pNewJoystick) {
-        if (!SDL_memcmp(&pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance))) {
-            /* if we are replacing the front of the list then update it */
-            if (pNewJoystick == *(JoyStick_DeviceData **)pContext) {
-                *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
-            } else if (pPrevJoystick) {
-                pPrevJoystick->pNext = pNewJoystick->pNext;
-            }
-
-            pNewJoystick->pNext = SYS_Joystick;
-            SYS_Joystick = pNewJoystick;
-
-            return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
-        }
-
-        pPrevJoystick = pNewJoystick;
-        pNewJoystick = pNewJoystick->pNext;
-    }
-
-    pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
-    if (!pNewJoystick) {
-        return DIENUM_CONTINUE; /* better luck next time? */
-    }
-
-    SDL_zerop(pNewJoystick);
-    pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
-    if (!pNewJoystick->joystickname) {
-        SDL_free(pNewJoystick);
-        return DIENUM_CONTINUE; /* better luck next time? */
-    }
-
-    SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
-        sizeof(DIDEVICEINSTANCE));
-
-    pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
-    pNewJoystick->send_add_event = SDL_TRUE;
-    pNewJoystick->nInstanceID = ++s_nInstanceID;
-    SDL_memcpy(&pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid));
-    pNewJoystick->pNext = SYS_Joystick;
-    SYS_Joystick = pNewJoystick;
-
-    s_bDeviceAdded = SDL_TRUE;
-
-    return DIENUM_CONTINUE; /* get next device, please */
-}
-
-static char *
-GetXInputName(const Uint8 userid, BYTE SubType)
-{
-    char name[32];
-
-	if (SDL_XInputUseOldJoystickMapping()) {
-		SDL_snprintf(name, sizeof(name), "X360 Controller #%u", 1 + userid);
-	} else {
-		switch (SubType) {
-		case XINPUT_DEVSUBTYPE_GAMEPAD:
-			SDL_snprintf(name, sizeof(name), "XInput Controller #%u", 1 + userid);
-			break;
-		case XINPUT_DEVSUBTYPE_WHEEL:
-			SDL_snprintf(name, sizeof(name), "XInput Wheel #%u", 1 + userid);
-			break;
-		case XINPUT_DEVSUBTYPE_ARCADE_STICK:
-			SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%u", 1 + userid);
-			break;
-		case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
-			SDL_snprintf(name, sizeof(name), "XInput FlightStick #%u", 1 + userid);
-			break;
-		case XINPUT_DEVSUBTYPE_DANCE_PAD:
-			SDL_snprintf(name, sizeof(name), "XInput DancePad #%u", 1 + userid);
-			break;
-		case XINPUT_DEVSUBTYPE_GUITAR:
-		case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
-		case XINPUT_DEVSUBTYPE_GUITAR_BASS:
-			SDL_snprintf(name, sizeof(name), "XInput Guitar #%u", 1 + userid);
-			break;
-		case XINPUT_DEVSUBTYPE_DRUM_KIT:
-			SDL_snprintf(name, sizeof(name), "XInput DrumKit #%u", 1 + userid);
-			break;
-		case XINPUT_DEVSUBTYPE_ARCADE_PAD:
-			SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%u", 1 + userid);
-			break;
-		default:
-			SDL_snprintf(name, sizeof(name), "XInput Device #%u", 1 + userid);
-			break;
-		}
-	}
-    return SDL_strdup(name);
-}
-
-static void
-AddXInputDevice(const Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
-{
-    JoyStick_DeviceData *pPrevJoystick = NULL;
-	JoyStick_DeviceData *pNewJoystick = *pContext;
-
-	if (SDL_XInputUseOldJoystickMapping() && SubType != XINPUT_DEVSUBTYPE_GAMEPAD)
-		return;
-
-    if (SubType == XINPUT_DEVSUBTYPE_UNKNOWN)
-		return;
-
-    while (pNewJoystick) {
-        if (pNewJoystick->bXInputDevice && (pNewJoystick->XInputUserId == userid) && (pNewJoystick->SubType == SubType)) {
-            /* if we are replacing the front of the list then update it */
-            if (pNewJoystick == *pContext) {
-                *pContext = pNewJoystick->pNext;
-            } else if (pPrevJoystick) {
-                pPrevJoystick->pNext = pNewJoystick->pNext;
-            }
-
-            pNewJoystick->pNext = SYS_Joystick;
-            SYS_Joystick = pNewJoystick;
-            return;   /* already in the list. */
-        }
-
-        pPrevJoystick = pNewJoystick;
-        pNewJoystick = pNewJoystick->pNext;
-    }
-
-    pNewJoystick = (JoyStick_DeviceData *) SDL_malloc(sizeof (JoyStick_DeviceData));
-    if (!pNewJoystick) {
-        return; /* better luck next time? */
-    }
-    SDL_zerop(pNewJoystick);
-
-    pNewJoystick->joystickname = GetXInputName(userid,SubType);
-    if (!pNewJoystick->joystickname) {
-        SDL_free(pNewJoystick);
-        return; /* better luck next time? */
-    }
-
-    pNewJoystick->bXInputDevice = SDL_TRUE;
-	if (SDL_XInputUseOldJoystickMapping()) {
-		SDL_zero(pNewJoystick->guid);
-	} else {
-		pNewJoystick->guid.data[0] = 'x';
-		pNewJoystick->guid.data[1] = 'i';
-		pNewJoystick->guid.data[2] = 'n';
-		pNewJoystick->guid.data[3] = 'p';
-		pNewJoystick->guid.data[4] = 'u';
-		pNewJoystick->guid.data[5] = 't';
-		pNewJoystick->guid.data[6] = SubType;
-	}
-	pNewJoystick->SubType = SubType;
-	pNewJoystick->XInputUserId = userid;
-    pNewJoystick->send_add_event = SDL_TRUE;
-    pNewJoystick->nInstanceID = ++s_nInstanceID;
-    pNewJoystick->pNext = SYS_Joystick;
-    SYS_Joystick = pNewJoystick;
-
-    s_bDeviceAdded = SDL_TRUE;
-}
-
-static void
-EnumXInputDevices(JoyStick_DeviceData **pContext)
-{
-    if (s_bXInputEnabled) {
-        int iuserid;
-        /* iterate in reverse, so these are in the final list in ascending numeric order. */
-        for (iuserid = SDL_XINPUT_MAX_DEVICES-1; iuserid >= 0; iuserid--) {
-            const Uint8 userid = (Uint8) iuserid;
-            XINPUT_CAPABILITIES capabilities;
-            if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
-                AddXInputDevice(userid, capabilities.SubType, pContext);
-            }
-        }
-    }
-}
-
-
-/* detect any new joysticks being inserted into the system */
-void SDL_SYS_JoystickDetect()
-{
-    JoyStick_DeviceData *pCurList = NULL;
-#if !SDL_EVENTS_DISABLED
-    SDL_Event event;
-#endif
-
-    /* only enum the devices if the joystick thread told us something changed */
-    if (!s_bDeviceAdded && !s_bDeviceRemoved) {
-        return;  /* thread hasn't signaled, nothing to do right now. */
-    }
-
-    SDL_LockMutex(s_mutexJoyStickEnum);
-
-    s_bDeviceAdded = SDL_FALSE;
-    s_bDeviceRemoved = SDL_FALSE;
-
-    pCurList = SYS_Joystick;
-    SYS_Joystick = NULL;
-
-    /* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
-    IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, &pCurList, DIEDFL_ATTACHEDONLY);
-
-    SDL_free(SDL_RawDevList);  /* in case we used this in DirectInput enumerator. */
-    SDL_RawDevList = NULL;
-    SDL_RawDevListCount = 0;
-
-    /* Look for XInput devices. Do this last, so they're first in the final list. */
-    EnumXInputDevices(&pCurList);
-
-    SDL_UnlockMutex(s_mutexJoyStickEnum);
-
-    while (pCurList) {
-        JoyStick_DeviceData *pListNext = NULL;
-
-#if SDL_HAPTIC_DINPUT
-        if (pCurList->bXInputDevice) {
-            XInputHaptic_MaybeRemoveDevice(pCurList->XInputUserId);
-        } else {
-            DirectInputHaptic_MaybeRemoveDevice(&pCurList->dxdevice);
-        }
-#endif
-
-#if !SDL_EVENTS_DISABLED
-        SDL_zero(event);
-        event.type = SDL_JOYDEVICEREMOVED;
-
-        if (SDL_GetEventState(event.type) == SDL_ENABLE) {
-            event.jdevice.which = pCurList->nInstanceID;
-            if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
-                SDL_PushEvent(&event);
-            }
-        }
-#endif /* !SDL_EVENTS_DISABLED */
-
-        pListNext = pCurList->pNext;
-        SDL_free(pCurList->joystickname);
-        SDL_free(pCurList);
-        pCurList = pListNext;
-    }
-
-    if (s_bDeviceAdded) {
-        JoyStick_DeviceData *pNewJoystick;
-        int device_index = 0;
-        s_bDeviceAdded = SDL_FALSE;
-        pNewJoystick = SYS_Joystick;
-        while (pNewJoystick) {
-            if (pNewJoystick->send_add_event) {
-#if SDL_HAPTIC_DINPUT
-                if (pNewJoystick->bXInputDevice) {
-                    XInputHaptic_MaybeAddDevice(pNewJoystick->XInputUserId);
-                } else {
-                    DirectInputHaptic_MaybeAddDevice(&pNewJoystick->dxdevice);
-                }
-#endif
-
-#if !SDL_EVENTS_DISABLED
-                SDL_zero(event);
-                event.type = SDL_JOYDEVICEADDED;
-
-                if (SDL_GetEventState(event.type) == SDL_ENABLE) {
-                    event.jdevice.which = device_index;
-                    if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
-                        SDL_PushEvent(&event);
-                    }
-                }
-#endif /* !SDL_EVENTS_DISABLED */
-                pNewJoystick->send_add_event = SDL_FALSE;
-            }
-            device_index++;
-            pNewJoystick = pNewJoystick->pNext;
-        }
-    }
-}
-
-/* Function to get the device-dependent name of a joystick */
-const char *
-SDL_SYS_JoystickNameForDeviceIndex(int device_index)
-{
-    JoyStick_DeviceData *device = SYS_Joystick;
-
-    for (; device_index > 0; device_index--)
-        device = device->pNext;
-
-    return device->joystickname;
-}
-
-/* Function to perform the mapping between current device instance and this joysticks instance id */
-SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
-{
-    JoyStick_DeviceData *device = SYS_Joystick;
-    int index;
-
-    for (index = device_index; index > 0; index--)
-        device = device->pNext;
-
-    return device->nInstanceID;
-}
-
-/* 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)
-{
-    HRESULT result;
-    JoyStick_DeviceData *joystickdevice = SYS_Joystick;
-
-    for (; device_index > 0; device_index--)
-        joystickdevice = joystickdevice->pNext;
-
-    /* allocate memory for system specific hardware data */
-    joystick->instance_id = joystickdevice->nInstanceID;
-    joystick->closed = SDL_FALSE;
-    joystick->hwdata =
-        (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
-    if (joystick->hwdata == NULL) {
-        return SDL_OutOfMemory();
-    }
-    SDL_zerop(joystick->hwdata);
-    joystick->hwdata->guid = joystickdevice->guid;
-
-    if (joystickdevice->bXInputDevice) {
-        const Uint8 userId = joystickdevice->XInputUserId;
-        XINPUT_CAPABILITIES capabilities;
-        XINPUT_VIBRATION state;
-
-        SDL_assert(s_bXInputEnabled);
-        SDL_assert(XINPUTGETCAPABILITIES);
-        SDL_assert(XINPUTSETSTATE);
-        SDL_assert(userId >= 0);
-        SDL_assert(userId < SDL_XINPUT_MAX_DEVICES);
-
-        joystick->hwdata->bXInputDevice = SDL_TRUE;
-
-        if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
-            SDL_free(joystick->hwdata);
-            joystick->hwdata = NULL;
-            return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?");
-        }
-        SDL_zero(state);
-        joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &state) == ERROR_SUCCESS);
-        joystick->hwdata->userid = userId;
-
-        /* The XInput API has a hard coded button/axis mapping, so we just match it */
-		if (SDL_XInputUseOldJoystickMapping()) {
-			joystick->naxes = 6;
-			joystick->nbuttons = 15;
-		} else {
-			joystick->naxes = 6;
-			joystick->nbuttons = 11;
-			joystick->nhats = 1;
-		}
-    } else {  /* use DirectInput, not XInput. */
-        LPDIRECTINPUTDEVICE8 device;
-        DIPROPDWORD dipdw;
-
-        joystick->hwdata->buffered = 1;
-        joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
-
-        SDL_zero(dipdw);
-        dipdw.diph.dwSize = sizeof(DIPROPDWORD);
-        dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
-
-        result =
-            IDirectInput8_CreateDevice(dinput,
-                                      &(joystickdevice->dxdevice.guidInstance), &device, NULL);
-        if (FAILED(result)) {
-            return SetDIerror("IDirectInput::CreateDevice", result);
-        }
-
-        /* Now get the IDirectInputDevice8 interface, instead. */
-        result = IDirectInputDevice8_QueryInterface(device,
-                                                   &IID_IDirectInputDevice8,
-                                                   (LPVOID *) & joystick->
-                                                   hwdata->InputDevice);
-        /* We are done with this object.  Use the stored one from now on. */
-        IDirectInputDevice8_Release(device);
-
-        if (FAILED(result)) {
-            return SetDIerror("IDirectInputDevice8::QueryInterface", result);
-        }
-
-        /* Acquire shared access. Exclusive access is required for forces,
-         * though. */
-        result =
-            IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
-                                                    InputDevice, SDL_HelperWindow,
-                                                    DISCL_EXCLUSIVE |
-                                                    DISCL_BACKGROUND);
-        if (FAILED(result)) {
-            return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result);
-        }
-
-        /* Use the extended data structure: DIJOYSTATE2. */
-        result =
-            IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
-                                              &c_dfDIJoystick2);
-        if (FAILED(result)) {
-            return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
-        }
-
-        /* Get device capabilities */
-        result =
-            IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
-                                                &joystick->hwdata->Capabilities);
-
-        if (FAILED(result)) {
-            return SetDIerror("IDirectInputDevice8::GetCapabilities", result);
-        }
-
-        /* Force capable? */
-        if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
-
-            result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
-
-            if (FAILED(result)) {
-                return SetDIerror("IDirectInputDevice8::Acquire", result);
-            }
-
-            /* reset all actuators. */
-            result =
-                IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
-                                                             InputDevice,
-                                                             DISFFC_RESET);
-
-            /* Not necessarily supported, ignore if not supported.
-            if (FAILED(result)) {
-                return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result);
-            }
-            */
-
-            result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
-
-            if (FAILED(result)) {
-                return SetDIerror("IDirectInputDevice8::Unacquire", result);
-            }
-
-            /* Turn on auto-centering for a ForceFeedback device (until told
-             * otherwise). */
-            dipdw.diph.dwObj = 0;
-            dipdw.diph.dwHow = DIPH_DEVICE;
-            dipdw.dwData = DIPROPAUTOCENTER_ON;
-
-            result =
-                IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
-                                                DIPROP_AUTOCENTER, &dipdw.diph);
-
-            /* Not necessarily supported, ignore if not supported.
-            if (FAILED(result)) {
-                return SetDIerror("IDirectInputDevice8::SetProperty", result);
-            }
-            */
-        }
-
-        /* What buttons and axes does it have? */
-        IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
-                                        EnumDevObjectsCallback, joystick,
-                                        DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
-
-        /* Reorder the input objects. Some devices do not report the X axis as
-         * the first axis, for example. */
-        SortDevObjects(joystick);
-
-        dipdw.diph.dwObj = 0;
-        dipdw.diph.dwHow = DIPH_DEVICE;
-        dipdw.dwData = INPUT_QSIZE;
-
-        /* Set the buffer size */
-        result =
-            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
-                                            DIPROP_BUFFERSIZE, &dipdw.diph);
-
-        if (result == DI_POLLEDDEVICE) {
-            /* This device doesn't support buffering, so we're forced
-             * to use less reliable polling. */
-            joystick->hwdata->buffered = 0;
-        } else if (FAILED(result)) {
-            return SetDIerror("IDirectInputDevice8::SetProperty", result);
-        }
-    }
-    return (0);
-}
-
-/* return true if this joystick is plugged in right now */
-SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
-{
-    return !joystick->closed && !joystick->hwdata->removed;
-}
-
-
-/* Sort using the data offset into the DInput struct.
- * This gives a reasonable ordering for the inputs. */
-static int
-SortDevFunc(const void *a, const void *b)
-{
-    const input_t *inputA = (const input_t*)a;
-    const input_t *inputB = (const input_t*)b;
-
-    if (inputA->ofs < inputB->ofs)
-        return -1;
-    if (inputA->ofs > inputB->ofs)
-        return 1;
-    return 0;
-}
-
-/* Sort the input objects and recalculate the indices for each input. */
-static void
-SortDevObjects(SDL_Joystick *joystick)
-{
-    input_t *inputs = joystick->hwdata->Inputs;
-    int nButtons = 0;
-    int nHats = 0;
-    int nAxis = 0;
-    int n;
-
-    SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
-
-    for (n = 0; n < joystick->hwdata->NumInputs; n++) {
-        switch (inputs[n].type) {
-        case BUTTON:
-            inputs[n].num = nButtons;
-            nButtons++;
-            break;
-
-        case HAT:
-            inputs[n].num = nHats;
-            nHats++;
-            break;
-
-        case AXIS:
-            inputs[n].num = nAxis;
-            nAxis++;
-            break;
-        }
-    }
-}
-
-static BOOL CALLBACK
-EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
-{
-    SDL_Joystick *joystick = (SDL_Joystick *) pvRef;
-    HRESULT result;
-    input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
-
-    if (dev->dwType & DIDFT_BUTTON) {
-        in->type = BUTTON;
-        in->num = joystick->nbuttons;
-        in->ofs = DIJOFS_BUTTON(in->num);
-        joystick->nbuttons++;
-    } else if (dev->dwType & DIDFT_POV) {
-        in->type = HAT;
-        in->num = joystick->nhats;
-        in->ofs = DIJOFS_POV(in->num);
-        joystick->nhats++;
-    } else if (dev->dwType & DIDFT_AXIS) {
-        DIPROPRANGE diprg;
-        DIPROPDWORD dilong;
-
-        in->type = AXIS;
-        in->num = joystick->naxes;
-        if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType)))
-            in->ofs = DIJOFS_X;
-        else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType)))
-            in->ofs = DIJOFS_Y;
-        else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType)))
-            in->ofs = DIJOFS_Z;
-        else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType)))
-            in->ofs = DIJOFS_RX;
-        else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType)))
-            in->ofs = DIJOFS_RY;
-        else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType)))
-            in->ofs = DIJOFS_RZ;
-        else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) {
-            in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders);
-            ++joystick->hwdata->NumSliders;
-        } else {
-             return DIENUM_CONTINUE; /* not an axis we can grok */
-        }
-
-        diprg.diph.dwSize = sizeof(diprg);
-        diprg.diph.dwHeaderSize = sizeof(diprg.diph);
-        diprg.diph.dwObj = dev->dwType;
-        diprg.diph.dwHow = DIPH_BYID;
-        diprg.lMin = AXIS_MIN;
-        diprg.lMax = AXIS_MAX;
-
-        result =
-            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
-                                            DIPROP_RANGE, &diprg.diph);
-        if (FAILED(result)) {
-            return DIENUM_CONTINUE;     /* don't use this axis */
-        }
-
-        /* Set dead zone to 0. */
-        dilong.diph.dwSize = sizeof(dilong);
-        dilong.diph.dwHeaderSize = sizeof(dilong.diph);
-        dilong.diph.dwObj = dev->dwType;
-        dilong.diph.dwHow = DIPH_BYID;
-        dilong.dwData = 0;
-        result =
-            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
-                                            DIPROP_DEADZONE, &dilong.diph);
-        if (FAILED(result)) {
-            return DIENUM_CONTINUE;     /* don't use this axis */
-        }
-
-        joystick->naxes++;
-    } else {
-        /* not supported at this time */
-        return DIENUM_CONTINUE;
-    }
-
-    joystick->hwdata->NumInputs++;
-
-    if (joystick->hwdata->NumInputs == MAX_INPUTS) {
-        return DIENUM_STOP;     /* too many */
-    }
-
-    return DIENUM_CONTINUE;
-}
-
-/* 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_Polled(SDL_Joystick * joystick)
-{
-    DIJOYSTATE2 state;
-    HRESULT result;
-    int i;
-
-    result =
-        IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
-                                           sizeof(DIJOYSTATE2), &state);
-    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
-        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
-        result =
-            IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
-                                               sizeof(DIJOYSTATE2), &state);
-    }
-
-    if (result != DI_OK) {
-        joystick->hwdata->send_remove_event = SDL_TRUE;
-        joystick->hwdata->removed = SDL_TRUE;
-        return;
-    }
-
-    /* Set each known axis, button and POV. */
-    for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
-        const input_t *in = &joystick->hwdata->Inputs[i];
-
-        switch (in->type) {
-        case AXIS:
-            switch (in->ofs) {
-            case DIJOFS_X:
-                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lX);
-                break;
-            case DIJOFS_Y:
-                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lY);
-                break;
-            case DIJOFS_Z:
-                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lZ);
-                break;
-            case DIJOFS_RX:
-                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lRx);
-                break;
-            case DIJOFS_RY:
-                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lRy);
-                break;
-            case DIJOFS_RZ:
-                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.lRz);
-                break;
-            case DIJOFS_SLIDER(0):
-                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.rglSlider[0]);
-                break;
-            case DIJOFS_SLIDER(1):
-                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) state.rglSlider[1]);
-                break;
-            }
-            break;
-
-        case BUTTON:
-            SDL_PrivateJoystickButton(joystick, in->num,
-                (Uint8) (state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
-            break;
-        case HAT:
-            {
-                Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
-                SDL_PrivateJoystickHat(joystick, in->num, pos);
-                break;
-            }
-        }
-    }
-}
-
-void
-SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick * joystick)
-{
-    int i;
-    HRESULT result;
-    DWORD numevents;
-    DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
-
-    numevents = INPUT_QSIZE;
-    result =
-        IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
-                                          sizeof(DIDEVICEOBJECTDATA), evtbuf,
-                                          &numevents, 0);
-    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
-        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
-        result =
-            IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
-                                              sizeof(DIDEVICEOBJECTDATA),
-                                              evtbuf, &numevents, 0);
-    }
-
-    /* Handle the events or punt */
-    if (FAILED(result)) {
-        joystick->hwdata->send_remove_event = SDL_TRUE;
-        joystick->hwdata->removed = SDL_TRUE;
-        return;
-    }
-
-    for (i = 0; i < (int) numevents; ++i) {
-        int j;
-
-        for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
-            const input_t *in = &joystick->hwdata->Inputs[j];
-
-            if (evtbuf[i].dwOfs != in->ofs)
-                continue;
-
-            switch (in->type) {
-            case AXIS:
-                SDL_PrivateJoystickAxis(joystick, in->num, (Sint16) evtbuf[i].dwData);
-                break;
-            case BUTTON:
-                SDL_PrivateJoystickButton(joystick, in->num,
-                    (Uint8) (evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED));
-                break;
-            case HAT:
-                {
-                    Uint8 pos = TranslatePOV(evtbuf[i].dwData);
-                    SDL_PrivateJoystickHat(joystick, in->num, pos);
-                }
-            }
-        }
-    }
-}
-
-static void
-UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
-{
-	static WORD s_XInputButtons[] = {
-		XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
-		XINPUT_GAMEPAD_START, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
-		XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER,
-		XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
-		XINPUT_GAMEPAD_GUIDE
-	};
-	WORD wButtons = pXInputState->Gamepad.wButtons;
-	Uint8 button;
-	Uint8 hat = SDL_HAT_CENTERED;
-
-	SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
-	SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
-	SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX);
-	SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
-	SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
-	SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
-
-	for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
-		SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
-	}
-}
-
-static void
-UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
-{
-	static WORD s_XInputButtons[] = {
-		XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
-		XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_START,
-		XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
-		XINPUT_GAMEPAD_GUIDE
-	};
-	WORD wButtons = pXInputState->Gamepad.wButtons;
-	Uint8 button;
-	Uint8 hat = SDL_HAT_CENTERED;
-
-	SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
-	SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
-	SDL_PrivateJoystickAxis(joystick, 2, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
-	SDL_PrivateJoystickAxis(joystick, 3, (Sint16)pXInputState->Gamepad.sThumbRX);
-	SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
-	SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
-
-	for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
-		SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
-	}
-
-	if (wButtons & XINPUT_GAMEPAD_DPAD_UP) {
-		hat |= SDL_HAT_UP;
-	}
-	if (wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {
-		hat |= SDL_HAT_DOWN;
-	}
-	if (wButtons & XINPUT_GAMEPAD_DPAD_LEFT) {
-		hat |= SDL_HAT_LEFT;
-	}
-	if (wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {
-		hat |= SDL_HAT_RIGHT;
-	}
-	SDL_PrivateJoystickHat(joystick, 0, hat);
-}
-
-/* Function to update the state of a XInput style joystick.
-*/
-void
-SDL_SYS_JoystickUpdate_XInput(SDL_Joystick * joystick)
-{
-    HRESULT result;
-	XINPUT_STATE_EX XInputState;
-
-    if (!XINPUTGETSTATE)
-        return;
-
-	result = XINPUTGETSTATE(joystick->hwdata->userid, &XInputState);
-    if (result == ERROR_DEVICE_NOT_CONNECTED) {
-        joystick->hwdata->send_remove_event = SDL_TRUE;
-        joystick->hwdata->removed = SDL_TRUE;
-        return;
-    }
-
-    /* only fire events if the data changed from last time */
-	if (XInputState.dwPacketNumber && XInputState.dwPacketNumber != joystick->hwdata->dwPacketNumber) {
-		if (SDL_XInputUseOldJoystickMapping()) {
-			UpdateXInputJoystickState_OLD(joystick, &XInputState);
-		} else {
-			UpdateXInputJoystickState(joystick, &XInputState);
-		}
-		joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber;
-    }
-}
-
-static Uint8
-TranslatePOV(DWORD value)
-{
-    const int HAT_VALS[] = {
-        SDL_HAT_UP,
-        SDL_HAT_UP | SDL_HAT_RIGHT,
-        SDL_HAT_RIGHT,
-        SDL_HAT_DOWN | SDL_HAT_RIGHT,
-        SDL_HAT_DOWN,
-        SDL_HAT_DOWN | SDL_HAT_LEFT,
-        SDL_HAT_LEFT,
-        SDL_HAT_UP | SDL_HAT_LEFT
-    };
-
-    if (LOWORD(value) == 0xFFFF)
-        return SDL_HAT_CENTERED;
-
-    /* Round the value up: */
-    value += 4500 / 2;
-    value %= 36000;
-    value /= 4500;
-
-    if (value >= 8)
-        return SDL_HAT_CENTERED;        /* shouldn't happen */
-
-    return HAT_VALS[value];
-}
-
-void
-SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
-{
-    HRESULT result;
-
-    if (joystick->closed || !joystick->hwdata)
-        return;
-
-    if (joystick->hwdata->bXInputDevice) {
-        SDL_SYS_JoystickUpdate_XInput(joystick);
-    } else {
-        result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
-        if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
-            IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
-            IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
-        }
-
-        if (joystick->hwdata->buffered)
-            SDL_SYS_JoystickUpdate_Buffered(joystick);
-        else
-            SDL_SYS_JoystickUpdate_Polled(joystick);
-    }
-
-    if (joystick->hwdata->removed) {
-        joystick->closed = SDL_TRUE;
-        joystick->uncentered = SDL_TRUE;
-    }
-}
-
-/* Function to close a joystick after use */
-void
-SDL_SYS_JoystickClose(SDL_Joystick * joystick)
-{
-    if (!joystick->hwdata->bXInputDevice) {
-        IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
-        IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
-    }
-
-    /* free system specific hardware data */
-    SDL_free(joystick->hwdata);
-
-    joystick->closed = SDL_TRUE;
-}
-
-/* Function to perform any system-specific joystick related cleanup */
-void
-SDL_SYS_JoystickQuit(void)
-{
-    JoyStick_DeviceData *device = SYS_Joystick;
-
-    while (device) {
-        JoyStick_DeviceData *device_next = device->pNext;
-        SDL_free(device->joystickname);
-        SDL_free(device);
-        device = device_next;
-    }
-    SYS_Joystick = NULL;
-
-    if (s_threadJoystick) {
-        SDL_LockMutex(s_mutexJoyStickEnum);
-        s_bJoystickThreadQuit = SDL_TRUE;
-        SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
-        SDL_UnlockMutex(s_mutexJoyStickEnum);
-        SDL_WaitThread(s_threadJoystick, NULL); /* wait for it to bugger off */
-
-        SDL_DestroyMutex(s_mutexJoyStickEnum);
-        SDL_DestroyCond(s_condJoystickThread);
-        s_condJoystickThread= NULL;
-        s_mutexJoyStickEnum = NULL;
-        s_threadJoystick = NULL;
-    }
-
-    if (dinput != NULL) {
-        IDirectInput8_Release(dinput);
-        dinput = NULL;
-    }
-
-    if (coinitialized) {
-        WIN_CoUninitialize();
-        coinitialized = SDL_FALSE;
-    }
-
-    if (s_bXInputEnabled) {
-        WIN_UnloadXInputDLL();
-    }
-}
-
-/* return the stable device guid for this device index */
-SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)
-{
-    JoyStick_DeviceData *device = SYS_Joystick;
-    int index;
-
-    for (index = device_index; index > 0; index--)
-        device = device->pNext;
-
-    return device->guid;
-}
-
-SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
-{
-    return joystick->hwdata->guid;
-}
-
-SDL_bool SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index)
-{
-    JoyStick_DeviceData *device = SYS_Joystick;
-    int index;
-
-    for (index = device_index; index > 0; index--)
-        device = device->pNext;
-
-    return (device->SubType == XINPUT_DEVSUBTYPE_GAMEPAD);
-}
-
-#endif /* SDL_JOYSTICK_DINPUT */
-
-/* vi: set ts=4 sw=4 expandtab: */
--- a/src/joystick/windows/SDL_dxjoystick_c.h	Thu Jul 03 17:36:08 2014 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-#include "../../SDL_internal.h"
-
-#ifndef SDL_JOYSTICK_DINPUT_H
-
-/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
- * A. Formiga's WINMM driver.
- *
- * Hats and sliders are completely untested; the app I'm writing this for mostly
- * doesn't use them and I don't own any joysticks with them.
- *
- * We don't bother to use event notification here.  It doesn't seem to work
- * with polled devices, and it's fine to call IDirectInputDevice2_GetDeviceData and
- * let it return 0 events. */
-
-#include "../../core/windows/SDL_windows.h"
-
-#define DIRECTINPUT_VERSION 0x0800      /* Need version 7 for force feedback. Need version 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */
-#include <dinput.h>
-#define COBJMACROS
-#include <wbemcli.h>
-#include <oleauto.h>
-#include <xinput.h>
-#include <devguid.h>
-#include <dbt.h>
-
-
-#ifndef XUSER_MAX_COUNT
-#define XUSER_MAX_COUNT 4
-#endif
-#ifndef XUSER_INDEX_ANY
-#define XUSER_INDEX_ANY     0x000000FF
-#endif
-#ifndef XINPUT_CAPS_FFB_SUPPORTED
-#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
-#endif
-
-#ifndef XINPUT_DEVSUBTYPE_UNKNOWN
-#define XINPUT_DEVSUBTYPE_UNKNOWN 0x00
-#endif
-#ifndef XINPUT_DEVSUBTYPE_GAMEPAD
-#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01
-#endif
-#ifndef XINPUT_DEVSUBTYPE_WHEEL
-#define XINPUT_DEVSUBTYPE_WHEEL 0x02
-#endif
-#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
-#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
-#endif
-#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
-#define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
-#endif
-#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
-#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
-#endif
-#ifndef XINPUT_DEVSUBTYPE_GUITAR
-#define XINPUT_DEVSUBTYPE_GUITAR 0x06
-#endif
-#ifndef XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE
-#define XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE 0x07
-#endif
-#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
-#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
-#endif
-#ifndef XINPUT_DEVSUBTYPE_GUITAR_BASS
-#define XINPUT_DEVSUBTYPE_GUITAR_BASS 0x0B
-#endif
-#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
-#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
-#endif
-
-#ifndef XINPUT_GAMEPAD_GUIDE
-#define XINPUT_GAMEPAD_GUIDE 0x0400
-#endif
-
-/* typedef's for XInput structs we use */
-typedef struct
-{
-    WORD wButtons;
-    BYTE bLeftTrigger;
-    BYTE bRightTrigger;
-    SHORT sThumbLX;
-    SHORT sThumbLY;
-    SHORT sThumbRX;
-    SHORT sThumbRY;
-    DWORD dwPaddingReserved;
-} XINPUT_GAMEPAD_EX;
-
-typedef struct
-{
-    DWORD dwPacketNumber;
-    XINPUT_GAMEPAD_EX Gamepad;
-} XINPUT_STATE_EX;
-
-/* Forward decl's for XInput API's we load dynamically and use if available */
-typedef DWORD (WINAPI *XInputGetState_t)
-    (
-    DWORD         dwUserIndex,  /* [in] Index of the gamer associated with the device */
-    XINPUT_STATE_EX* pState     /* [out] Receives the current state */
-    );
-
-typedef DWORD (WINAPI *XInputSetState_t)
-    (
-    DWORD             dwUserIndex,  /* [in] Index of the gamer associated with the device */
-    XINPUT_VIBRATION* pVibration    /* [in, out] The vibration information to send to the controller */
-    );
-
-typedef DWORD (WINAPI *XInputGetCapabilities_t)
-    (
-    DWORD                dwUserIndex,   /* [in] Index of the gamer associated with the device */
-    DWORD                dwFlags,       /* [in] Input flags that identify the device type */
-    XINPUT_CAPABILITIES* pCapabilities  /* [out] Receives the capabilities */
-    );
-
-extern int WIN_LoadXInputDLL(void);
-extern void WIN_UnloadXInputDLL(void);
-
-extern XInputGetState_t SDL_XInputGetState;
-extern XInputSetState_t SDL_XInputSetState;
-extern XInputGetCapabilities_t SDL_XInputGetCapabilities;
-extern DWORD SDL_XInputVersion;  /* ((major << 16) & 0xFF00) | (minor & 0xFF) */
-
-#define XINPUTGETSTATE          SDL_XInputGetState
-#define XINPUTSETSTATE          SDL_XInputSetState
-#define XINPUTGETCAPABILITIES   SDL_XInputGetCapabilities
-#define INVALID_XINPUT_USERID   XUSER_INDEX_ANY
-#define SDL_XINPUT_MAX_DEVICES  XUSER_MAX_COUNT
-
-#define MAX_INPUTS  256     /* each joystick can have up to 256 inputs */
-
-
-/* local types */
-typedef enum Type
-{ BUTTON, AXIS, HAT } Type;
-
-typedef struct input_t
-{
-    /* DirectInput offset for this input type: */
-    DWORD ofs;
-
-    /* Button, axis or hat: */
-    Type type;
-
-    /* SDL input offset: */
-    Uint8 num;
-} input_t;
-
-/* The private structure used to keep track of a joystick */
-struct joystick_hwdata
-{
-    LPDIRECTINPUTDEVICE8 InputDevice;
-    DIDEVCAPS Capabilities;
-    int buffered;
-    SDL_JoystickGUID guid;
-
-    input_t Inputs[MAX_INPUTS];
-    int NumInputs;
-    int NumSliders;
-	SDL_bool removed;
-	SDL_bool send_remove_event;
-	SDL_bool bXInputDevice; /* SDL_TRUE if this device supports using the xinput API rather than DirectInput */
-	SDL_bool bXInputHaptic; /* Supports force feedback via XInput. */
-    Uint8 userid; /* XInput userid index for this joystick */
-	DWORD dwPacketNumber;
-};
-
-#endif /* SDL_JOYSTICK_DINPUT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/joystick/windows/SDL_windowsjoystick.c	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,569 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT
+
+/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
+ * A. Formiga's WINMM driver.
+ *
+ * Hats and sliders are completely untested; the app I'm writing this for mostly
+ * doesn't use them and I don't own any joysticks with them.
+ *
+ * We don't bother to use event notification here.  It doesn't seem to work
+ * with polled devices, and it's fine to call IDirectInputDevice8_GetDeviceData and
+ * let it return 0 events. */
+
+#include "SDL_error.h"
+#include "SDL_assert.h"
+#include "SDL_events.h"
+#include "SDL_thread.h"
+#include "SDL_timer.h"
+#include "SDL_mutex.h"
+#include "SDL_events.h"
+#include "SDL_hints.h"
+#include "SDL_joystick.h"
+#include "../SDL_sysjoystick.h"
+#if !SDL_EVENTS_DISABLED
+#include "../../events/SDL_events_c.h"
+#endif
+#include "../../core/windows/SDL_windows.h"
+#include <dbt.h>
+
+#define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
+#include "SDL_windowsjoystick_c.h"
+#include "SDL_dinputjoystick_c.h"
+#include "SDL_xinputjoystick_c.h"
+
+#include "../../haptic/windows/SDL_dinputhaptic_c.h"    /* For haptic hot plugging */
+#include "../../haptic/windows/SDL_xinputhaptic_c.h"    /* For haptic hot plugging */
+
+
+/* local variables */
+static SDL_bool s_bDeviceAdded = SDL_FALSE;
+static SDL_bool s_bDeviceRemoved = SDL_FALSE;
+static SDL_JoystickID s_nInstanceID = -1;
+static SDL_cond *s_condJoystickThread = NULL;
+static SDL_mutex *s_mutexJoyStickEnum = NULL;
+static SDL_Thread *s_threadJoystick = NULL;
+static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
+
+JoyStick_DeviceData *SYS_Joystick;    /* array to hold joystick ID values */
+
+static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
+
+#ifdef __WINRT__
+
+typedef struct
+{
+    int unused;
+} SDL_DeviceNotificationData;
+
+static void
+SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
+{
+}
+
+static int
+SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
+{
+    return 0;
+}
+
+static void
+SDL_CheckDeviceNotification(SDL_DeviceNotificationData *data)
+{
+}
+
+#else /* !__WINRT__ */
+
+typedef struct
+{
+    HRESULT coinitialized;
+    WNDCLASSEX wincl;
+    HWND messageWindow;
+    HDEVNOTIFY hNotify;
+} SDL_DeviceNotificationData;
+
+
+/* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal */
+static LRESULT CALLBACK
+SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    switch (message) {
+    case WM_DEVICECHANGE:
+        switch (wParam) {
+        case DBT_DEVICEARRIVAL:
+            if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
+                s_bWindowsDeviceChanged = SDL_TRUE;
+            }
+            break;
+        case DBT_DEVICEREMOVECOMPLETE:
+            if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
+                s_bWindowsDeviceChanged = SDL_TRUE;
+            }
+            break;
+        }
+        return 0;
+    }
+
+    return DefWindowProc (hwnd, message, wParam, lParam);
+}
+
+static void
+SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
+{
+    if (data->hNotify)
+        UnregisterDeviceNotification(data->hNotify);
+
+    if (data->messageWindow)
+        DestroyWindow(data->messageWindow);
+
+    UnregisterClass(data->wincl.lpszClassName, data->wincl.hInstance);
+
+    if (data->coinitialized == S_OK) {
+        WIN_CoUninitialize();
+    }
+}
+
+static int
+SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
+{
+    DEV_BROADCAST_DEVICEINTERFACE dbh;
+    GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
+
+    SDL_zerop(data);
+
+    data->coinitialized = WIN_CoInitialize();
+
+    data->wincl.hInstance = GetModuleHandle(NULL);
+    data->wincl.lpszClassName = L"Message";
+    data->wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc;      /* This function is called by windows */
+    data->wincl.cbSize = sizeof (WNDCLASSEX);
+
+    if (!RegisterClassEx(&data->wincl)) {
+        WIN_SetError("Failed to create register class for joystick autodetect");
+        SDL_CleanupDeviceNotification(data);
+        return -1;
+    }
+
+    data->messageWindow = (HWND)CreateWindowEx(0,  L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
+    if (!data->messageWindow) {
+        WIN_SetError("Failed to create message window for joystick autodetect");
+        SDL_CleanupDeviceNotification(data);
+        return -1;
+    }
+
+    SDL_zero(dbh);
+    dbh.dbcc_size = sizeof(dbh);
+    dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+    dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
+
+    data->hNotify = RegisterDeviceNotification(data->messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE);
+    if (!data->hNotify) {
+        WIN_SetError("Failed to create notify device for joystick autodetect");
+        SDL_CleanupDeviceNotification(data);
+        return -1;
+    }
+    return 0;
+}
+
+static void
+SDL_CheckDeviceNotification(SDL_DeviceNotificationData *data)
+{
+    MSG msg;
+
+    if (!data->messageWindow) {
+        return;
+    }
+
+    while (PeekMessage(&msg, data->messageWindow, 0, 0, PM_NOREMOVE)) {
+        if (GetMessage(&msg, data->messageWindow, 0, 0) != 0)  {
+            TranslateMessage(&msg);
+            DispatchMessage(&msg);
+        }
+    }
+}
+
+#endif /* __WINRT__ */
+
+/* Function/thread to scan the system for joysticks. */
+static int
+SDL_JoystickThread(void *_data)
+{
+    SDL_DeviceNotificationData notification_data;
+
+#if SDL_JOYSTICK_XINPUT
+    SDL_bool bOpenedXInputDevices[XUSER_MAX_COUNT];
+    SDL_zero(bOpenedXInputDevices);
+#endif
+
+    if (SDL_CreateDeviceNotification(&notification_data) < 0) {
+        return -1;
+    }
+
+    SDL_LockMutex(s_mutexJoyStickEnum);
+    while (s_bJoystickThreadQuit == SDL_FALSE) {
+        SDL_bool bXInputChanged = SDL_FALSE;
+
+        SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 300);
+
+        SDL_CheckDeviceNotification(&notification_data);
+
+#if SDL_JOYSTICK_XINPUT
+        if (SDL_XINPUT_Enabled() && XINPUTGETCAPABILITIES) {
+            /* scan for any change in XInput devices */
+            Uint8 userId;
+            for (userId = 0; userId < XUSER_MAX_COUNT; userId++) {
+                XINPUT_CAPABILITIES capabilities;
+                const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
+                const SDL_bool available = (result == ERROR_SUCCESS);
+                if (bOpenedXInputDevices[userId] != available) {
+                    bXInputChanged = SDL_TRUE;
+                    bOpenedXInputDevices[userId] = available;
+                }
+            }
+        }
+#endif /* SDL_JOYSTICK_XINPUT */
+
+        if (s_bWindowsDeviceChanged || bXInputChanged) {
+            SDL_UnlockMutex(s_mutexJoyStickEnum);  /* let main thread go while we SDL_Delay(). */
+            SDL_Delay(300); /* wait for direct input to find out about this device */
+            SDL_LockMutex(s_mutexJoyStickEnum);
+
+            s_bDeviceRemoved = SDL_TRUE;
+            s_bDeviceAdded = SDL_TRUE;
+            s_bWindowsDeviceChanged = SDL_FALSE;
+        }
+    }
+    SDL_UnlockMutex(s_mutexJoyStickEnum);
+
+    SDL_CleanupDeviceNotification(&notification_data);
+
+    return 1;
+}
+
+void SDL_SYS_AddJoystickDevice(JoyStick_DeviceData *device)
+{
+    device->send_add_event = SDL_TRUE;
+    device->nInstanceID = ++s_nInstanceID;
+    device->pNext = SYS_Joystick;
+    SYS_Joystick = device;
+
+    s_bDeviceAdded = SDL_TRUE;
+}
+
+/* Function to scan the system for joysticks.
+ * This function should set SDL_numjoysticks to the number of available
+ * joysticks.  Joystick 0 should be the system default joystick.
+ * It should return 0, or -1 on an unrecoverable fatal error.
+ */
+int
+SDL_SYS_JoystickInit(void)
+{
+    if (SDL_DINPUT_JoystickInit() < 0) {
+        SDL_SYS_JoystickQuit();
+        return -1;
+    }
+
+    if (SDL_XINPUT_JoystickInit() < 0) {
+        SDL_SYS_JoystickQuit();
+        return -1;
+    }
+
+    s_mutexJoyStickEnum = SDL_CreateMutex();
+    s_condJoystickThread = SDL_CreateCond();
+    s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
+
+    SDL_SYS_JoystickDetect();
+
+    if (!s_threadJoystick) {
+        s_bJoystickThreadQuit = SDL_FALSE;
+        /* spin up the thread to detect hotplug of devices */
+#if defined(__WIN32__) && !defined(HAVE_LIBC)
+#undef SDL_CreateThread
+#if SDL_DYNAMIC_API
+        s_threadJoystick= SDL_CreateThread_REAL(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
+#else
+        s_threadJoystick= SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
+#endif
+#else
+        s_threadJoystick = SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL);
+#endif
+    }
+    return SDL_SYS_NumJoysticks();
+}
+
+/* return the number of joysticks that are connected right now */
+int
+SDL_SYS_NumJoysticks()
+{
+    int nJoysticks = 0;
+    JoyStick_DeviceData *device = SYS_Joystick;
+    while (device) {
+        nJoysticks++;
+        device = device->pNext;
+    }
+
+    return nJoysticks;
+}
+
+/* detect any new joysticks being inserted into the system */
+void
+SDL_SYS_JoystickDetect()
+{
+    JoyStick_DeviceData *pCurList = NULL;
+#if !SDL_EVENTS_DISABLED
+    SDL_Event event;
+#endif
+
+    /* only enum the devices if the joystick thread told us something changed */
+    if (!s_bDeviceAdded && !s_bDeviceRemoved) {
+        return;  /* thread hasn't signaled, nothing to do right now. */
+    }
+
+    SDL_LockMutex(s_mutexJoyStickEnum);
+
+    s_bDeviceAdded = SDL_FALSE;
+    s_bDeviceRemoved = SDL_FALSE;
+
+    pCurList = SYS_Joystick;
+    SYS_Joystick = NULL;
+
+    /* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
+    SDL_DINPUT_JoystickDetect(&pCurList);
+
+    /* Look for XInput devices. Do this last, so they're first in the final list. */
+    SDL_XINPUT_JoystickDetect(&pCurList);
+
+    SDL_UnlockMutex(s_mutexJoyStickEnum);
+
+    while (pCurList) {
+        JoyStick_DeviceData *pListNext = NULL;
+
+        if (pCurList->bXInputDevice) {
+            SDL_XINPUT_MaybeRemoveDevice(pCurList->XInputUserId);
+        } else {
+            SDL_DINPUT_MaybeRemoveDevice(&pCurList->dxdevice);
+        }
+
+#if !SDL_EVENTS_DISABLED
+        SDL_zero(event);
+        event.type = SDL_JOYDEVICEREMOVED;
+
+        if (SDL_GetEventState(event.type) == SDL_ENABLE) {
+            event.jdevice.which = pCurList->nInstanceID;
+            if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
+                SDL_PushEvent(&event);
+            }
+        }
+#endif /* !SDL_EVENTS_DISABLED */
+
+        pListNext = pCurList->pNext;
+        SDL_free(pCurList->joystickname);
+        SDL_free(pCurList);
+        pCurList = pListNext;
+    }
+
+    if (s_bDeviceAdded) {
+        JoyStick_DeviceData *pNewJoystick;
+        int device_index = 0;
+        s_bDeviceAdded = SDL_FALSE;
+        pNewJoystick = SYS_Joystick;
+        while (pNewJoystick) {
+            if (pNewJoystick->send_add_event) {
+                if (pNewJoystick->bXInputDevice) {
+                    SDL_XINPUT_MaybeAddDevice(pNewJoystick->XInputUserId);
+                } else {
+                    SDL_DINPUT_MaybeAddDevice(&pNewJoystick->dxdevice);
+                }
+
+#if !SDL_EVENTS_DISABLED
+                SDL_zero(event);
+                event.type = SDL_JOYDEVICEADDED;
+
+                if (SDL_GetEventState(event.type) == SDL_ENABLE) {
+                    event.jdevice.which = device_index;
+                    if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
+                        SDL_PushEvent(&event);
+                    }
+                }
+#endif /* !SDL_EVENTS_DISABLED */
+                pNewJoystick->send_add_event = SDL_FALSE;
+            }
+            device_index++;
+            pNewJoystick = pNewJoystick->pNext;
+        }
+    }
+}
+
+/* Function to get the device-dependent name of a joystick */
+const char *
+SDL_SYS_JoystickNameForDeviceIndex(int device_index)
+{
+    JoyStick_DeviceData *device = SYS_Joystick;
+
+    for (; device_index > 0; device_index--)
+        device = device->pNext;
+
+    return device->joystickname;
+}
+
+/* Function to perform the mapping between current device instance and this joysticks instance id */
+SDL_JoystickID
+SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
+{
+    JoyStick_DeviceData *device = SYS_Joystick;
+    int index;
+
+    for (index = device_index; index > 0; index--)
+        device = device->pNext;
+
+    return device->nInstanceID;
+}
+
+/* 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_DeviceData *joystickdevice = SYS_Joystick;
+
+    for (; device_index > 0; device_index--)
+        joystickdevice = joystickdevice->pNext;
+
+    /* allocate memory for system specific hardware data */
+    joystick->instance_id = joystickdevice->nInstanceID;
+    joystick->closed = SDL_FALSE;
+    joystick->hwdata =
+        (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
+    if (joystick->hwdata == NULL) {
+        return SDL_OutOfMemory();
+    }
+    SDL_zerop(joystick->hwdata);
+    joystick->hwdata->guid = joystickdevice->guid;
+
+    if (joystickdevice->bXInputDevice) {
+        return SDL_XINPUT_JoystickOpen(joystick, joystickdevice);
+    } else {
+        return SDL_DINPUT_JoystickOpen(joystick, joystickdevice);
+    }
+}
+
+/* return true if this joystick is plugged in right now */
+SDL_bool 
+SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
+{
+    return !joystick->closed && !joystick->hwdata->removed;
+}
+
+void
+SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
+{
+    if (joystick->closed || !joystick->hwdata) {
+        return;
+    }
+
+    if (joystick->hwdata->bXInputDevice) {
+        SDL_XINPUT_JoystickUpdate(joystick);
+    } else {
+        SDL_DINPUT_JoystickUpdate(joystick);
+    }
+
+    if (joystick->hwdata->removed) {
+        joystick->closed = SDL_TRUE;
+        joystick->uncentered = SDL_TRUE;
+    }
+}
+
+/* Function to close a joystick after use */
+void
+SDL_SYS_JoystickClose(SDL_Joystick * joystick)
+{
+    if (joystick->hwdata->bXInputDevice) {
+        SDL_XINPUT_JoystickClose(joystick);
+    } else {
+        SDL_DINPUT_JoystickClose(joystick);
+    }
+
+    /* free system specific hardware data */
+    SDL_free(joystick->hwdata);
+
+    joystick->closed = SDL_TRUE;
+}
+
+/* Function to perform any system-specific joystick related cleanup */
+void
+SDL_SYS_JoystickQuit(void)
+{
+    JoyStick_DeviceData *device = SYS_Joystick;
+
+    while (device) {
+        JoyStick_DeviceData *device_next = device->pNext;
+        SDL_free(device->joystickname);
+        SDL_free(device);
+        device = device_next;
+    }
+    SYS_Joystick = NULL;
+
+    if (s_threadJoystick) {
+        SDL_LockMutex(s_mutexJoyStickEnum);
+        s_bJoystickThreadQuit = SDL_TRUE;
+        SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
+        SDL_UnlockMutex(s_mutexJoyStickEnum);
+        SDL_WaitThread(s_threadJoystick, NULL); /* wait for it to bugger off */
+
+        SDL_DestroyMutex(s_mutexJoyStickEnum);
+        SDL_DestroyCond(s_condJoystickThread);
+        s_condJoystickThread= NULL;
+        s_mutexJoyStickEnum = NULL;
+        s_threadJoystick = NULL;
+    }
+
+    SDL_DINPUT_JoystickQuit();
+    SDL_XINPUT_JoystickQuit();
+}
+
+/* return the stable device guid for this device index */
+SDL_JoystickGUID
+SDL_SYS_JoystickGetDeviceGUID(int device_index)
+{
+    JoyStick_DeviceData *device = SYS_Joystick;
+    int index;
+
+    for (index = device_index; index > 0; index--)
+        device = device->pNext;
+
+    return device->guid;
+}
+
+SDL_JoystickGUID
+SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
+{
+    return joystick->hwdata->guid;
+}
+
+#endif /* SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/joystick/windows/SDL_windowsjoystick_c.h	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,89 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_events.h"
+#include "SDL_joystick.h"
+#include "../SDL_sysjoystick.h"
+#include "../../core/windows/SDL_windows.h"
+#include "../../core/windows/SDL_directx.h"
+
+#define MAX_INPUTS  256     /* each joystick can have up to 256 inputs */
+
+typedef struct JoyStick_DeviceData
+{
+    SDL_JoystickGUID guid;
+    char *joystickname;
+    Uint8 send_add_event;
+    SDL_JoystickID nInstanceID;
+    SDL_bool bXInputDevice;
+    BYTE SubType;
+    Uint8 XInputUserId;
+    DIDEVICEINSTANCE dxdevice;
+    struct JoyStick_DeviceData *pNext;
+} JoyStick_DeviceData;
+
+extern JoyStick_DeviceData *SYS_Joystick;    /* array to hold joystick ID values */
+
+typedef enum Type
+{
+    BUTTON,
+    AXIS,
+    HAT
+} Type;
+
+typedef struct input_t
+{
+    /* DirectInput offset for this input type: */
+    DWORD ofs;
+
+    /* Button, axis or hat: */
+    Type type;
+
+    /* SDL input offset: */
+    Uint8 num;
+} input_t;
+
+/* The private structure used to keep track of a joystick */
+struct joystick_hwdata
+{
+    SDL_JoystickGUID guid;
+    SDL_bool removed;
+    SDL_bool send_remove_event;
+
+#if SDL_JOYSTICK_DINPUT
+    LPDIRECTINPUTDEVICE8 InputDevice;
+    DIDEVCAPS Capabilities;
+    SDL_bool buffered;
+    input_t Inputs[MAX_INPUTS];
+    int NumInputs;
+    int NumSliders;
+#endif
+
+    SDL_bool bXInputDevice; /* SDL_TRUE if this device supports using the xinput API rather than DirectInput */
+    SDL_bool bXInputHaptic; /* Supports force feedback via XInput. */
+    Uint8 userid; /* XInput userid index for this joystick */
+    DWORD dwPacketNumber;
+};
+
+extern void SDL_SYS_AddJoystickDevice(JoyStick_DeviceData *device);
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/joystick/windows/SDL_xinputjoystick.c	Thu Jul 03 15:39:55 2014 -0700
@@ -0,0 +1,390 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "SDL_assert.h"
+#include "SDL_hints.h"
+#include "../SDL_sysjoystick.h"
+#include "SDL_windowsjoystick_c.h"
+#include "SDL_xinputjoystick_c.h"
+
+
+#if SDL_JOYSTICK_XINPUT
+
+/*
+ * Internal stuff.
+ */
+static SDL_bool s_bXInputEnabled = SDL_TRUE;
+
+
+static SDL_bool
+SDL_XInputUseOldJoystickMapping()
+{
+    static int s_XInputUseOldJoystickMapping = -1;
+    if (s_XInputUseOldJoystickMapping < 0) {
+        const char *hint = SDL_GetHint(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING);
+        s_XInputUseOldJoystickMapping = (hint && *hint == '1') ? 1 : 0;
+    }
+    return (s_XInputUseOldJoystickMapping > 0);
+}
+
+SDL_bool SDL_XINPUT_Enabled(void)
+{
+    return s_bXInputEnabled;
+}
+
+int
+SDL_XINPUT_JoystickInit(void)
+{
+    const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
+    if (env && !SDL_atoi(env)) {
+        s_bXInputEnabled = SDL_FALSE;
+    }
+
+    if (s_bXInputEnabled && WIN_LoadXInputDLL() < 0) {
+        s_bXInputEnabled = SDL_FALSE;  /* oh well. */
+    }
+    return 0;
+}
+
+static char *
+GetXInputName(const Uint8 userid, BYTE SubType)
+{
+    char name[32];
+
+    if (SDL_XInputUseOldJoystickMapping()) {
+        SDL_snprintf(name, sizeof(name), "X360 Controller #%u", 1 + userid);
+    } else {
+        switch (SubType) {
+        case XINPUT_DEVSUBTYPE_GAMEPAD:
+            SDL_snprintf(name, sizeof(name), "XInput Controller #%u", 1 + userid);
+            break;
+        case XINPUT_DEVSUBTYPE_WHEEL:
+            SDL_snprintf(name, sizeof(name), "XInput Wheel #%u", 1 + userid);
+            break;
+        case XINPUT_DEVSUBTYPE_ARCADE_STICK:
+            SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%u", 1 + userid);
+            break;
+        case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
+            SDL_snprintf(name, sizeof(name), "XInput FlightStick #%u", 1 + userid);
+            break;
+        case XINPUT_DEVSUBTYPE_DANCE_PAD:
+            SDL_snprintf(name, sizeof(name), "XInput DancePad #%u", 1 + u