Added hotplug joystick support and simplified game controller API, courtesy of Alfred Reynolds
authorSam Lantinga <slouken@libsdl.org>
Mon, 26 Nov 2012 16:37:54 -0800
changeset 66909548c8a58103
parent 6689 e2fc3ae07582
child 6691 3b8cda6d238b
Added hotplug joystick support and simplified game controller API, courtesy of Alfred Reynolds
Makefile.in
VisualC/SDL/SDL_VS2010.vcxproj
VisualC/tests/testgamecontroller/testgamecontroller_VS2010.vcxproj
Xcode/SDL/SDL.xcodeproj/project.pbxproj
Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj
Xcode/SDLTest/testgamecontroller-Info.plist
include/SDL.h
include/SDL_events.h
include/SDL_gamecontroller.h
include/SDL_hints.h
include/SDL_joystick.h
src/SDL.c
src/events/SDL_events.c
src/haptic/SDL_haptic.c
src/haptic/windows/SDL_syshaptic.c
src/joystick/SDL_gamecontroller.c
src/joystick/SDL_joystick.c
src/joystick/SDL_joystick_c.h
src/joystick/SDL_sysjoystick.h
src/joystick/beos/SDL_bejoystick.cc
src/joystick/darwin/SDL_sysjoystick.c
src/joystick/darwin/SDL_sysjoystick_c.h
src/joystick/iphoneos/SDLUIAccelerationDelegate.m
src/joystick/iphoneos/SDL_sysjoystick.m
src/joystick/linux/SDL_sysjoystick.c
src/joystick/windows/SDL_dxjoystick.c
src/joystick/windows/SDL_dxjoystick_c.h
test/Makefile.in
test/testgamecontroller.c
test/testjoystick.c
     1.1 --- a/Makefile.in	Mon Nov 26 14:59:07 2012 -0800
     1.2 +++ b/Makefile.in	Mon Nov 26 16:37:54 2012 -0800
     1.3 @@ -53,6 +53,7 @@
     1.4  	SDL_endian.h \
     1.5  	SDL_error.h \
     1.6  	SDL_events.h \
     1.7 +	SDL_gamecontroller.h \
     1.8  	SDL_gesture.h \
     1.9  	SDL_haptic.h \
    1.10  	SDL_hints.h \
     2.1 --- a/VisualC/SDL/SDL_VS2010.vcxproj	Mon Nov 26 14:59:07 2012 -0800
     2.2 +++ b/VisualC/SDL/SDL_VS2010.vcxproj	Mon Nov 26 16:37:54 2012 -0800
     2.3 @@ -98,7 +98,7 @@
     2.4        <Culture>0x0409</Culture>
     2.5      </ResourceCompile>
     2.6      <Link>
     2.7 -      <AdditionalDependencies>winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
     2.8 +      <AdditionalDependencies>winmm.lib;imm32.lib;oleaut32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
     2.9        <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
    2.10        <GenerateDebugInformation>true</GenerateDebugInformation>
    2.11        <SubSystem>Windows</SubSystem>
    2.12 @@ -129,7 +129,7 @@
    2.13        <Culture>0x0409</Culture>
    2.14      </ResourceCompile>
    2.15      <Link>
    2.16 -      <AdditionalDependencies>winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
    2.17 +      <AdditionalDependencies>winmm.lib;imm32.lib;oleaut32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
    2.18        <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
    2.19        <GenerateDebugInformation>true</GenerateDebugInformation>
    2.20        <SubSystem>Windows</SubSystem>
    2.21 @@ -165,7 +165,7 @@
    2.22        <Culture>0x0409</Culture>
    2.23      </ResourceCompile>
    2.24      <Link>
    2.25 -      <AdditionalDependencies>winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
    2.26 +      <AdditionalDependencies>winmm.lib;imm32.lib;oleaut32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
    2.27        <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
    2.28        <SubSystem>Windows</SubSystem>
    2.29        <AdditionalLibraryDirectories>$(DXSDK_DIR)\lib\x86</AdditionalLibraryDirectories>
    2.30 @@ -196,7 +196,7 @@
    2.31        <Culture>0x0409</Culture>
    2.32      </ResourceCompile>
    2.33      <Link>
    2.34 -      <AdditionalDependencies>winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
    2.35 +      <AdditionalDependencies>winmm.lib;imm32.lib;oleaut32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
    2.36        <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
    2.37        <SubSystem>Windows</SubSystem>
    2.38        <AdditionalLibraryDirectories>$(DXSDK_DIR)\lib\x64</AdditionalLibraryDirectories>
    2.39 @@ -221,6 +221,7 @@
    2.40      <ClInclude Include="..\..\include\SDL_hints.h" />
    2.41      <ClInclude Include="..\..\include\SDL_input.h" />
    2.42      <ClInclude Include="..\..\include\SDL_joystick.h" />
    2.43 +    <ClInclude Include="..\..\include\SDL_gamecontroller.h" />
    2.44      <ClInclude Include="..\..\include\SDL_keyboard.h" />
    2.45      <ClInclude Include="..\..\include\SDL_keycode.h" />
    2.46      <ClInclude Include="..\..\include\SDL_loadso.h" />
    2.47 @@ -399,6 +400,7 @@
    2.48      <ClCompile Include="..\..\src\haptic\SDL_haptic.c" />
    2.49      <ClCompile Include="..\..\src\stdlib\SDL_iconv.c" />
    2.50      <ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
    2.51 +    <ClCompile Include="..\..\src\joystick\SDL_gamecontroller.c" />
    2.52      <ClCompile Include="..\..\src\events\SDL_keyboard.c" />
    2.53      <ClCompile Include="..\..\src\stdlib\SDL_malloc.c" />
    2.54      <ClCompile Include="..\..\src\audio\SDL_mixer.c" />
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/VisualC/tests/testgamecontroller/testgamecontroller_VS2010.vcxproj	Mon Nov 26 16:37:54 2012 -0800
     3.3 @@ -0,0 +1,227 @@
     3.4 +<?xml version="1.0" encoding="utf-8"?>
     3.5 +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     3.6 +  <ItemGroup Label="ProjectConfigurations">
     3.7 +    <ProjectConfiguration Include="Debug|Win32">
     3.8 +      <Configuration>Debug</Configuration>
     3.9 +      <Platform>Win32</Platform>
    3.10 +    </ProjectConfiguration>
    3.11 +    <ProjectConfiguration Include="Debug|x64">
    3.12 +      <Configuration>Debug</Configuration>
    3.13 +      <Platform>x64</Platform>
    3.14 +    </ProjectConfiguration>
    3.15 +    <ProjectConfiguration Include="Release|Win32">
    3.16 +      <Configuration>Release</Configuration>
    3.17 +      <Platform>Win32</Platform>
    3.18 +    </ProjectConfiguration>
    3.19 +    <ProjectConfiguration Include="Release|x64">
    3.20 +      <Configuration>Release</Configuration>
    3.21 +      <Platform>x64</Platform>
    3.22 +    </ProjectConfiguration>
    3.23 +  </ItemGroup>
    3.24 +  <PropertyGroup Label="Globals">
    3.25 +    <ProjectName>testgamecontroller</ProjectName>
    3.26 +    <RootNamespace>testgamecontroller</RootNamespace>
    3.27 +    <ProjectGuid>{55812185-D13C-4022-9C81-32E0F4A08336}</ProjectGuid>
    3.28 +  </PropertyGroup>
    3.29 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
    3.30 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    3.31 +    <ConfigurationType>Application</ConfigurationType>
    3.32 +    <UseOfMfc>false</UseOfMfc>
    3.33 +  </PropertyGroup>
    3.34 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    3.35 +    <ConfigurationType>Application</ConfigurationType>
    3.36 +    <UseOfMfc>false</UseOfMfc>
    3.37 +    <CharacterSet>MultiByte</CharacterSet>
    3.38 +  </PropertyGroup>
    3.39 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    3.40 +    <ConfigurationType>Application</ConfigurationType>
    3.41 +    <UseOfMfc>false</UseOfMfc>
    3.42 +  </PropertyGroup>
    3.43 +  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    3.44 +    <ConfigurationType>Application</ConfigurationType>
    3.45 +    <UseOfMfc>false</UseOfMfc>
    3.46 +  </PropertyGroup>
    3.47 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
    3.48 +  <ImportGroup Label="ExtensionSettings">
    3.49 +  </ImportGroup>
    3.50 +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
    3.51 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    3.52 +    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
    3.53 +  </ImportGroup>
    3.54 +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
    3.55 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    3.56 +    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
    3.57 +  </ImportGroup>
    3.58 +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
    3.59 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    3.60 +    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
    3.61 +  </ImportGroup>
    3.62 +  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
    3.63 +    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    3.64 +    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
    3.65 +  </ImportGroup>
    3.66 +  <PropertyGroup Label="UserMacros" />
    3.67 +  <PropertyGroup>
    3.68 +    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
    3.69 +    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</OutDir>
    3.70 +    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</OutDir>
    3.71 +    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>
    3.72 +    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
    3.73 +    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
    3.74 +    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
    3.75 +    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</OutDir>
    3.76 +    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</OutDir>
    3.77 +    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>
    3.78 +    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
    3.79 +    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
    3.80 +    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
    3.81 +  </PropertyGroup>
    3.82 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    3.83 +    <Midl>
    3.84 +      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    3.85 +      <MkTypLibCompatible>true</MkTypLibCompatible>
    3.86 +      <SuppressStartupBanner>true</SuppressStartupBanner>
    3.87 +      <TargetEnvironment>Win32</TargetEnvironment>
    3.88 +    </Midl>
    3.89 +    <ClCompile>
    3.90 +      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
    3.91 +      <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    3.92 +      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    3.93 +      <StringPooling>true</StringPooling>
    3.94 +      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
    3.95 +      <FunctionLevelLinking>true</FunctionLevelLinking>
    3.96 +      <PrecompiledHeader>
    3.97 +      </PrecompiledHeader>
    3.98 +      <WarningLevel>Level3</WarningLevel>
    3.99 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.100 +      <CompileAs>Default</CompileAs>
   3.101 +    </ClCompile>
   3.102 +    <ResourceCompile>
   3.103 +      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   3.104 +      <Culture>0x0409</Culture>
   3.105 +    </ResourceCompile>
   3.106 +    <Link>
   3.107 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.108 +      <SubSystem>Windows</SubSystem>
   3.109 +    </Link>
   3.110 +    <PostBuildEvent>
   3.111 +      <Command>copy "$(SolutionDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDir)\SDL.dll"</Command>
   3.112 +    </PostBuildEvent>
   3.113 +    <PostBuildEvent>
   3.114 +      <Message>Copy SDL</Message>
   3.115 +    </PostBuildEvent>
   3.116 +  </ItemDefinitionGroup>
   3.117 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
   3.118 +    <Midl>
   3.119 +      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   3.120 +      <MkTypLibCompatible>true</MkTypLibCompatible>
   3.121 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.122 +    </Midl>
   3.123 +    <ClCompile>
   3.124 +      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
   3.125 +      <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
   3.126 +      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   3.127 +      <StringPooling>true</StringPooling>
   3.128 +      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
   3.129 +      <FunctionLevelLinking>true</FunctionLevelLinking>
   3.130 +      <PrecompiledHeader>
   3.131 +      </PrecompiledHeader>
   3.132 +      <WarningLevel>Level3</WarningLevel>
   3.133 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.134 +      <CompileAs>Default</CompileAs>
   3.135 +    </ClCompile>
   3.136 +    <ResourceCompile>
   3.137 +      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   3.138 +      <Culture>0x0409</Culture>
   3.139 +    </ResourceCompile>
   3.140 +    <Link>
   3.141 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.142 +      <SubSystem>Windows</SubSystem>
   3.143 +    </Link>
   3.144 +    <PostBuildEvent>
   3.145 +      <Command>copy "$(SolutionDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDir)\SDL.dll"</Command>
   3.146 +    </PostBuildEvent>
   3.147 +    <PostBuildEvent>
   3.148 +      <Message>Copy SDL</Message>
   3.149 +    </PostBuildEvent>
   3.150 +  </ItemDefinitionGroup>
   3.151 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
   3.152 +    <Midl>
   3.153 +      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   3.154 +      <MkTypLibCompatible>true</MkTypLibCompatible>
   3.155 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.156 +      <TargetEnvironment>Win32</TargetEnvironment>
   3.157 +    </Midl>
   3.158 +    <ClCompile>
   3.159 +      <Optimization>Disabled</Optimization>
   3.160 +      <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
   3.161 +      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   3.162 +      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
   3.163 +      <PrecompiledHeader>
   3.164 +      </PrecompiledHeader>
   3.165 +      <WarningLevel>Level3</WarningLevel>
   3.166 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.167 +      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
   3.168 +      <CompileAs>Default</CompileAs>
   3.169 +    </ClCompile>
   3.170 +    <ResourceCompile>
   3.171 +      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   3.172 +      <Culture>0x0409</Culture>
   3.173 +    </ResourceCompile>
   3.174 +    <Link>
   3.175 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.176 +      <GenerateDebugInformation>true</GenerateDebugInformation>
   3.177 +      <SubSystem>Windows</SubSystem>
   3.178 +    </Link>
   3.179 +    <PostBuildEvent>
   3.180 +      <Command>copy "$(SolutionDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDir)\SDL.dll"</Command>
   3.181 +    </PostBuildEvent>
   3.182 +    <PostBuildEvent>
   3.183 +      <Message>Copy SDL</Message>
   3.184 +    </PostBuildEvent>
   3.185 +  </ItemDefinitionGroup>
   3.186 +  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
   3.187 +    <Midl>
   3.188 +      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   3.189 +      <MkTypLibCompatible>true</MkTypLibCompatible>
   3.190 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.191 +    </Midl>
   3.192 +    <ClCompile>
   3.193 +      <Optimization>Disabled</Optimization>
   3.194 +      <AdditionalIncludeDirectories>..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
   3.195 +      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   3.196 +      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
   3.197 +      <PrecompiledHeader>
   3.198 +      </PrecompiledHeader>
   3.199 +      <WarningLevel>Level3</WarningLevel>
   3.200 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.201 +      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
   3.202 +      <CompileAs>Default</CompileAs>
   3.203 +    </ClCompile>
   3.204 +    <ResourceCompile>
   3.205 +      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   3.206 +      <Culture>0x0409</Culture>
   3.207 +    </ResourceCompile>
   3.208 +    <Link>
   3.209 +      <SuppressStartupBanner>true</SuppressStartupBanner>
   3.210 +      <GenerateDebugInformation>true</GenerateDebugInformation>
   3.211 +      <SubSystem>Windows</SubSystem>
   3.212 +    </Link>
   3.213 +    <PostBuildEvent>
   3.214 +      <Command>copy "$(SolutionDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDir)\SDL.dll"</Command>
   3.215 +    </PostBuildEvent>
   3.216 +    <PostBuildEvent>
   3.217 +      <Message>Copy SDL</Message>
   3.218 +    </PostBuildEvent>
   3.219 +  </ItemDefinitionGroup>
   3.220 +  <ItemGroup>
   3.221 +    <Library Include="..\..\Sdl\$(Platform)\$(Configuration)\SDL.lib" />
   3.222 +    <Library Include="..\..\SDLmain\$(Platform)\$(Configuration)\SDLmain.lib" />
   3.223 +  </ItemGroup>
   3.224 +  <ItemGroup>
   3.225 +    <ClCompile Include="..\..\..\test\testgamecontroller.c" />
   3.226 +  </ItemGroup>
   3.227 +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   3.228 +  <ImportGroup Label="ExtensionTargets">
   3.229 +  </ImportGroup>
   3.230 +</Project>
   3.231 \ No newline at end of file
     4.1 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj	Mon Nov 26 14:59:07 2012 -0800
     4.2 +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj	Mon Nov 26 16:37:54 2012 -0800
     4.3 @@ -546,6 +546,8 @@
     4.4  		AABCC38E164063D200AB8930 /* SDL_cocoamessagebox.h in Headers */ = {isa = PBXBuildFile; fileRef = AABCC38B164063D200AB8930 /* SDL_cocoamessagebox.h */; };
     4.5  		AABCC38F164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */ = {isa = PBXBuildFile; fileRef = AABCC38C164063D200AB8930 /* SDL_cocoamessagebox.m */; };
     4.6  		AABCC390164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */ = {isa = PBXBuildFile; fileRef = AABCC38C164063D200AB8930 /* SDL_cocoamessagebox.m */; };
     4.7 +		BBFC088B164C6514003E6A99 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */; };
     4.8 +		BBFC088D164C6647003E6A99 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */; };
     4.9  /* End PBXBuildFile section */
    4.10  
    4.11  /* Begin PBXContainerItemProxy section */
    4.12 @@ -891,6 +893,7 @@
    4.13  		AA9FF9591637CBF9000DF050 /* SDL_messagebox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_messagebox.h; sourceTree = "<group>"; };
    4.14  		AABCC38B164063D200AB8930 /* SDL_cocoamessagebox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoamessagebox.h; sourceTree = "<group>"; };
    4.15  		AABCC38C164063D200AB8930 /* SDL_cocoamessagebox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoamessagebox.m; sourceTree = "<group>"; };
    4.16 +		BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gamecontroller.c; sourceTree = "<group>"; };
    4.17  		BECDF66B0761BA81005FE872 /* Info-Framework.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Framework.plist"; sourceTree = "<group>"; };
    4.18  		BECDF66C0761BA81005FE872 /* SDL2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDL2.framework; sourceTree = BUILT_PRODUCTS_DIR; };
    4.19  		BECDF6B30761BA81005FE872 /* libSDL2.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDL2.a; sourceTree = BUILT_PRODUCTS_DIR; };
    4.20 @@ -1325,6 +1328,7 @@
    4.21  				04BDFE0612E6671700899322 /* darwin */,
    4.22  				04BDFE1612E6671700899322 /* SDL_joystick.c */,
    4.23  				04BDFE1712E6671700899322 /* SDL_joystick_c.h */,
    4.24 +				BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */,
    4.25  				04BDFE1812E6671700899322 /* SDL_sysjoystick.h */,
    4.26  			);
    4.27  			name = joystick;
    4.28 @@ -2306,6 +2310,7 @@
    4.29  				04BD027612E6671800899322 /* SDL_syshaptic.c in Sources */,
    4.30  				04BD027A12E6671800899322 /* SDL_haptic.c in Sources */,
    4.31  				04BD028112E6671800899322 /* SDL_sysjoystick.c in Sources */,
    4.32 +				BBFC088D164C6647003E6A99 /* SDL_gamecontroller.c in Sources */,
    4.33  				04BD028B12E6671800899322 /* SDL_joystick.c in Sources */,
    4.34  				04BD02A312E6671800899322 /* SDL_sysloadso.c in Sources */,
    4.35  				04BD02AE12E6671800899322 /* SDL_syspower.c in Sources */,
     5.1 --- a/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj	Mon Nov 26 14:59:07 2012 -0800
     5.2 +++ b/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj	Mon Nov 26 16:37:54 2012 -0800
     5.3 @@ -559,6 +559,18 @@
     5.4  		00794F8709D2413B003FC8A1 /* sample.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00794E6109D20839003FC8A1 /* sample.bmp */; };
     5.5  		4537749F12091551002F0F45 /* libsdlcommon.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BEC567FF0761D90600A33029 /* libsdlcommon.a */; };
     5.6  		453774A5120915E3002F0F45 /* testshape.c in Sources */ = {isa = PBXBuildFile; fileRef = 453774A4120915E3002F0F45 /* testshape.c */; };
     5.7 +		BBFC08BF164C6862003E6A99 /* libsdlcommon.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BEC567FF0761D90600A33029 /* libsdlcommon.a */; };
     5.8 +		BBFC08C0164C6862003E6A99 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002F33A709CA188600EBEB88 /* Cocoa.framework */; };
     5.9 +		BBFC08C1164C6862003E6A99 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002A863B10730545007319AE /* CoreAudio.framework */; };
    5.10 +		BBFC08C2164C6862003E6A99 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002A863C10730545007319AE /* ForceFeedback.framework */; };
    5.11 +		BBFC08C3164C6862003E6A99 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002A863D10730545007319AE /* IOKit.framework */; };
    5.12 +		BBFC08C4164C6862003E6A99 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002A869F10730593007319AE /* AudioToolbox.framework */; };
    5.13 +		BBFC08C5164C6862003E6A99 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002A86A010730593007319AE /* CoreFoundation.framework */; };
    5.14 +		BBFC08C6164C6862003E6A99 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002A86F2107305CE007319AE /* OpenGL.framework */; };
    5.15 +		BBFC08C7164C6862003E6A99 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002A871410730623007319AE /* AudioUnit.framework */; };
    5.16 +		BBFC08C8164C6862003E6A99 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002A873910730675007319AE /* Carbon.framework */; };
    5.17 +		BBFC08C9164C6862003E6A99 /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 003FA645093FFD41000C53B3 /* libSDL2.a */; };
    5.18 +		BBFC08D0164C6876003E6A99 /* testgamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088E164C6820003E6A99 /* testgamecontroller.c */; };
    5.19  		BEC566B10761D90300A33029 /* checkkeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 092D6D10FFB30A2C7F000001 /* checkkeys.c */; };
    5.20  		BEC566BE0761D90300A33029 /* graywin.c in Sources */ = {isa = PBXBuildFile; fileRef = 092D6D1BFFB30C237F000001 /* graywin.c */; };
    5.21  		BEC566CB0761D90300A33029 /* loopwave.c in Sources */ = {isa = PBXBuildFile; fileRef = 083E4872006D84C97F000001 /* loopwave.c */; };
    5.22 @@ -1098,6 +1110,13 @@
    5.23  			remoteGlobalIDString = BEC567F70761D90600A33029;
    5.24  			remoteInfo = sdlcommon;
    5.25  		};
    5.26 +		BBFC08B9164C6862003E6A99 /* PBXContainerItemProxy */ = {
    5.27 +			isa = PBXContainerItemProxy;
    5.28 +			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
    5.29 +			proxyType = 1;
    5.30 +			remoteGlobalIDString = BEC567F70761D90600A33029;
    5.31 +			remoteInfo = "libsdlmain.a (Upgraded)";
    5.32 +		};
    5.33  		BEC568300761D90600A33029 /* PBXContainerItemProxy */ = {
    5.34  			isa = PBXContainerItemProxy;
    5.35  			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
    5.36 @@ -1452,6 +1471,21 @@
    5.37  		4537749212091504002F0F45 /* testshape.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testshape.app; sourceTree = BUILT_PRODUCTS_DIR; };
    5.38  		453774A4120915E3002F0F45 /* testshape.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = testshape.c; path = ../../test/testshape.c; sourceTree = SOURCE_ROOT; };
    5.39  		B207FF2404E1B19600A80002 /* sdlcommon_prefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sdlcommon_prefix.h; sourceTree = "<group>"; };
    5.40 +		BBFC088E164C6820003E6A99 /* testgamecontroller.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = testgamecontroller.c; path = ../../test/testgamecontroller.c; sourceTree = "<group>"; };
    5.41 +		BBFC089C164C684D003E6A99 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
    5.42 +		BBFC089F164C684D003E6A99 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
    5.43 +		BBFC08A0164C684D003E6A99 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
    5.44 +		BBFC08A1164C684D003E6A99 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
    5.45 +		BBFC08A4164C684D003E6A99 /* testgamecontroller-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "testgamecontroller-Info.plist"; sourceTree = "<group>"; };
    5.46 +		BBFC08A6164C684D003E6A99 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
    5.47 +		BBFC08A8164C684D003E6A99 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
    5.48 +		BBFC08AA164C684D003E6A99 /* testgamecontroller-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "testgamecontroller-Prefix.pch"; sourceTree = "<group>"; };
    5.49 +		BBFC08AC164C684D003E6A99 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
    5.50 +		BBFC08AE164C684D003E6A99 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
    5.51 +		BBFC08AF164C684D003E6A99 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
    5.52 +		BBFC08B2164C684D003E6A99 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = "<group>"; };
    5.53 +		BBFC08CD164C6862003E6A99 /* testgamecontroller.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testgamecontroller.app; sourceTree = BUILT_PRODUCTS_DIR; };
    5.54 +		BBFC08CF164C6863003E6A99 /* testjoystick copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "testjoystick copy-Info.plist"; path = "/Users/alfred/valve/steam3_rel_Client/src/external/SDL2/build/Xcode/SDLTest/testjoystick copy-Info.plist"; sourceTree = "<absolute>"; };
    5.55  		BEC566B60761D90300A33029 /* checkkeys.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = checkkeys.app; sourceTree = BUILT_PRODUCTS_DIR; };
    5.56  		BEC566C30761D90300A33029 /* graywin.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = graywin.app; sourceTree = BUILT_PRODUCTS_DIR; };
    5.57  		BEC566D10761D90300A33029 /* loopwave.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = loopwave.app; sourceTree = BUILT_PRODUCTS_DIR; };
    5.58 @@ -1848,6 +1882,24 @@
    5.59  			);
    5.60  			runOnlyForDeploymentPostprocessing = 0;
    5.61  		};
    5.62 +		BBFC08BE164C6862003E6A99 /* Frameworks */ = {
    5.63 +			isa = PBXFrameworksBuildPhase;
    5.64 +			buildActionMask = 2147483647;
    5.65 +			files = (
    5.66 +				BBFC08BF164C6862003E6A99 /* libsdlcommon.a in Frameworks */,
    5.67 +				BBFC08C0164C6862003E6A99 /* Cocoa.framework in Frameworks */,
    5.68 +				BBFC08C1164C6862003E6A99 /* CoreAudio.framework in Frameworks */,
    5.69 +				BBFC08C2164C6862003E6A99 /* ForceFeedback.framework in Frameworks */,
    5.70 +				BBFC08C3164C6862003E6A99 /* IOKit.framework in Frameworks */,
    5.71 +				BBFC08C4164C6862003E6A99 /* AudioToolbox.framework in Frameworks */,
    5.72 +				BBFC08C5164C6862003E6A99 /* CoreFoundation.framework in Frameworks */,
    5.73 +				BBFC08C6164C6862003E6A99 /* OpenGL.framework in Frameworks */,
    5.74 +				BBFC08C7164C6862003E6A99 /* AudioUnit.framework in Frameworks */,
    5.75 +				BBFC08C8164C6862003E6A99 /* Carbon.framework in Frameworks */,
    5.76 +				BBFC08C9164C6862003E6A99 /* libSDL2.a in Frameworks */,
    5.77 +			);
    5.78 +			runOnlyForDeploymentPostprocessing = 0;
    5.79 +		};
    5.80  		BEC566B20761D90300A33029 /* Frameworks */ = {
    5.81  			isa = PBXFrameworksBuildPhase;
    5.82  			buildActionMask = 2147483647;
    5.83 @@ -2330,7 +2382,10 @@
    5.84  				B207FF2404E1B19600A80002 /* sdlcommon_prefix.h */,
    5.85  				002F33A209CA183B00EBEB88 /* Linked Frameworks */,
    5.86  				00794E4609D207B4003FC8A1 /* Resources */,
    5.87 +				BBFC08A2164C684D003E6A99 /* testgamecontroller */,
    5.88 +				BBFC089B164C684D003E6A99 /* Frameworks */,
    5.89  				1AB674ADFE9D54B511CA2CBB /* Products */,
    5.90 +				BBFC08CF164C6863003E6A99 /* testjoystick copy-Info.plist */,
    5.91  			);
    5.92  			comments = "I made these tests link against our \"default\" framework which includes X11 stuff. If you didn't install the X11 headers with Xcode, you might have problems building the SDL.framework (which is a dependency). You can swap the dependencies around to get around this, or you can modify the default SDL.framework target to not include X11 stuff. (Go into its target build options and remove all the Preprocessor macros.)\n\n\n\nWe are sort of in a half-way state at the moment. Going \"all-the-way\" means we copy the SDL.framework inside the app bundle so we can run the test without the step of the user \"installing\" the framework. But there is an oversight/bug in Xcode that doesn't correctly find the location of the framework when in an embedded/nested Xcode project. We could probably try to hack this with a shell script that checks multiple directories for existence, but this is messier and more work than I prefer, so I rather just wait for Apple to fix this. In the meantime...\n\nThe \"All\" target will build the SDL framework from the Xcode project. The other targets do not have this dependency set (for flexibility reasons in case we make changes). If you have not built the framework, you will probably be unable to link. You will either need to build the framework, or you need to add \"-framework SDL\" to the link options and make sure you have the SDL.framework installed somewhere where it can be seen (like /Library/Frameworks...I think we already set this one up.) \n\nTo run though, you should have a copy of the SDL.framework in /Library/Frameworks or ~/Library/Frameworks.\n\n\n\n\ntestgl and testdyngl need -DHAVE_OPENGL\ntestgl needs to link against OpenGL.framework\n\n";
    5.93  			name = SDLTest;
    5.94 @@ -2363,6 +2418,7 @@
    5.95  				00179791107432FA00F5D044 /* testime.c */,
    5.96  				001797B31074339C00F5D044 /* testintersections.c */,
    5.97  				092D6D62FFB312AA7F000001 /* testjoystick.c */,
    5.98 +				BBFC088E164C6820003E6A99 /* testgamecontroller.c */,
    5.99  				092D6D6CFFB313437F000001 /* testkeys.c */,
   5.100  				001797D31074343E00F5D044 /* testloadso.c */,
   5.101  				092D6D75FFB313BB7F000001 /* testlock.c */,
   5.102 @@ -2440,10 +2496,53 @@
   5.103  				0017991610743F1000F5D044 /* testsprite2.app */,
   5.104  				0017993810743FB700F5D044 /* testwm2.app */,
   5.105  				4537749212091504002F0F45 /* testshape.app */,
   5.106 +				BBFC08CD164C6862003E6A99 /* testgamecontroller.app */,
   5.107  			);
   5.108  			name = Products;
   5.109  			sourceTree = "<group>";
   5.110  		};
   5.111 +		BBFC089B164C684D003E6A99 /* Frameworks */ = {
   5.112 +			isa = PBXGroup;
   5.113 +			children = (
   5.114 +				BBFC089C164C684D003E6A99 /* Cocoa.framework */,
   5.115 +				BBFC089E164C684D003E6A99 /* Other Frameworks */,
   5.116 +			);
   5.117 +			name = Frameworks;
   5.118 +			sourceTree = "<group>";
   5.119 +		};
   5.120 +		BBFC089E164C684D003E6A99 /* Other Frameworks */ = {
   5.121 +			isa = PBXGroup;
   5.122 +			children = (
   5.123 +				BBFC089F164C684D003E6A99 /* AppKit.framework */,
   5.124 +				BBFC08A0164C684D003E6A99 /* CoreData.framework */,
   5.125 +				BBFC08A1164C684D003E6A99 /* Foundation.framework */,
   5.126 +			);
   5.127 +			name = "Other Frameworks";
   5.128 +			sourceTree = "<group>";
   5.129 +		};
   5.130 +		BBFC08A2164C684D003E6A99 /* testgamecontroller */ = {
   5.131 +			isa = PBXGroup;
   5.132 +			children = (
   5.133 +				BBFC08AE164C684D003E6A99 /* AppDelegate.h */,
   5.134 +				BBFC08AF164C684D003E6A99 /* AppDelegate.m */,
   5.135 +				BBFC08B1164C684D003E6A99 /* MainMenu.xib */,
   5.136 +				BBFC08A3164C684D003E6A99 /* Supporting Files */,
   5.137 +			);
   5.138 +			path = testgamecontroller;
   5.139 +			sourceTree = "<group>";
   5.140 +		};
   5.141 +		BBFC08A3164C684D003E6A99 /* Supporting Files */ = {
   5.142 +			isa = PBXGroup;
   5.143 +			children = (
   5.144 +				BBFC08A4164C684D003E6A99 /* testgamecontroller-Info.plist */,
   5.145 +				BBFC08A5164C684D003E6A99 /* InfoPlist.strings */,
   5.146 +				BBFC08A8164C684D003E6A99 /* main.m */,
   5.147 +				BBFC08AA164C684D003E6A99 /* testgamecontroller-Prefix.pch */,
   5.148 +				BBFC08AB164C684D003E6A99 /* Credits.rtf */,
   5.149 +			);
   5.150 +			name = "Supporting Files";
   5.151 +			sourceTree = "<group>";
   5.152 +		};
   5.153  /* End PBXGroup section */
   5.154  
   5.155  /* Begin PBXHeadersBuildPhase section */
   5.156 @@ -2588,6 +2687,13 @@
   5.157  			);
   5.158  			runOnlyForDeploymentPostprocessing = 0;
   5.159  		};
   5.160 +		BBFC08BA164C6862003E6A99 /* Headers */ = {
   5.161 +			isa = PBXHeadersBuildPhase;
   5.162 +			buildActionMask = 2147483647;
   5.163 +			files = (
   5.164 +			);
   5.165 +			runOnlyForDeploymentPostprocessing = 0;
   5.166 +		};
   5.167  		BEC566AD0761D90300A33029 /* Headers */ = {
   5.168  			isa = PBXHeadersBuildPhase;
   5.169  			buildActionMask = 2147483647;
   5.170 @@ -3182,6 +3288,26 @@
   5.171  			productReference = 4537749212091504002F0F45 /* testshape.app */;
   5.172  			productType = "com.apple.product-type.application";
   5.173  		};
   5.174 +		BBFC08B7164C6862003E6A99 /* testgamecontroller */ = {
   5.175 +			isa = PBXNativeTarget;
   5.176 +			buildConfigurationList = BBFC08CA164C6862003E6A99 /* Build configuration list for PBXNativeTarget "testgamecontroller" */;
   5.177 +			buildPhases = (
   5.178 +				BBFC08BA164C6862003E6A99 /* Headers */,
   5.179 +				BBFC08BB164C6862003E6A99 /* Resources */,
   5.180 +				BBFC08BC164C6862003E6A99 /* Sources */,
   5.181 +				BBFC08BE164C6862003E6A99 /* Frameworks */,
   5.182 +			);
   5.183 +			buildRules = (
   5.184 +			);
   5.185 +			dependencies = (
   5.186 +				BBFC08B8164C6862003E6A99 /* PBXTargetDependency */,
   5.187 +			);
   5.188 +			name = testgamecontroller;
   5.189 +			productInstallPath = "$(USER_APPS_DIR)";
   5.190 +			productName = testjoystick;
   5.191 +			productReference = BBFC08CD164C6862003E6A99 /* testgamecontroller.app */;
   5.192 +			productType = "com.apple.product-type.application";
   5.193 +		};
   5.194  		BEC566AB0761D90300A33029 /* checkkeys */ = {
   5.195  			isa = PBXNativeTarget;
   5.196  			buildConfigurationList = 001B593808BDB826006539E9 /* Build configuration list for PBXNativeTarget "checkkeys" */;
   5.197 @@ -3686,6 +3812,7 @@
   5.198  				Japanese,
   5.199  				French,
   5.200  				German,
   5.201 +				en,
   5.202  			);
   5.203  			mainGroup = 08FB7794FE84155DC02AAC07 /* SDLTest */;
   5.204  			projectDirPath = "";
   5.205 @@ -3743,6 +3870,7 @@
   5.206  				BEC567EA0761D90600A33029 /* torturethread */,
   5.207  				BEC567F70761D90600A33029 /* sdlcommon */,
   5.208  				4537749112091504002F0F45 /* testshape */,
   5.209 +				BBFC08B7164C6862003E6A99 /* testgamecontroller */,
   5.210  			);
   5.211  		};
   5.212  /* End PBXProject section */
   5.213 @@ -3933,6 +4061,13 @@
   5.214  			);
   5.215  			runOnlyForDeploymentPostprocessing = 0;
   5.216  		};
   5.217 +		BBFC08BB164C6862003E6A99 /* Resources */ = {
   5.218 +			isa = PBXResourcesBuildPhase;
   5.219 +			buildActionMask = 2147483647;
   5.220 +			files = (
   5.221 +			);
   5.222 +			runOnlyForDeploymentPostprocessing = 0;
   5.223 +		};
   5.224  		BEC566AE0761D90300A33029 /* Resources */ = {
   5.225  			isa = PBXResourcesBuildPhase;
   5.226  			buildActionMask = 2147483647;
   5.227 @@ -4277,6 +4412,14 @@
   5.228  			);
   5.229  			runOnlyForDeploymentPostprocessing = 0;
   5.230  		};
   5.231 +		BBFC08BC164C6862003E6A99 /* Sources */ = {
   5.232 +			isa = PBXSourcesBuildPhase;
   5.233 +			buildActionMask = 2147483647;
   5.234 +			files = (
   5.235 +				BBFC08D0164C6876003E6A99 /* testgamecontroller.c in Sources */,
   5.236 +			);
   5.237 +			runOnlyForDeploymentPostprocessing = 0;
   5.238 +		};
   5.239  		BEC566B00761D90300A33029 /* Sources */ = {
   5.240  			isa = PBXSourcesBuildPhase;
   5.241  			buildActionMask = 2147483647;
   5.242 @@ -4797,6 +4940,11 @@
   5.243  			target = BEC567F70761D90600A33029 /* sdlcommon */;
   5.244  			targetProxy = 4537749D1209152D002F0F45 /* PBXContainerItemProxy */;
   5.245  		};
   5.246 +		BBFC08B8164C6862003E6A99 /* PBXTargetDependency */ = {
   5.247 +			isa = PBXTargetDependency;
   5.248 +			target = BEC567F70761D90600A33029 /* sdlcommon */;
   5.249 +			targetProxy = BBFC08B9164C6862003E6A99 /* PBXContainerItemProxy */;
   5.250 +		};
   5.251  		BEC568310761D90600A33029 /* PBXTargetDependency */ = {
   5.252  			isa = PBXTargetDependency;
   5.253  			target = BEC567F70761D90600A33029 /* sdlcommon */;
   5.254 @@ -4914,6 +5062,33 @@
   5.255  		};
   5.256  /* End PBXTargetDependency section */
   5.257  
   5.258 +/* Begin PBXVariantGroup section */
   5.259 +		BBFC08A5164C684D003E6A99 /* InfoPlist.strings */ = {
   5.260 +			isa = PBXVariantGroup;
   5.261 +			children = (
   5.262 +				BBFC08A6164C684D003E6A99 /* en */,
   5.263 +			);
   5.264 +			name = InfoPlist.strings;
   5.265 +			sourceTree = "<group>";
   5.266 +		};
   5.267 +		BBFC08AB164C684D003E6A99 /* Credits.rtf */ = {
   5.268 +			isa = PBXVariantGroup;
   5.269 +			children = (
   5.270 +				BBFC08AC164C684D003E6A99 /* en */,
   5.271 +			);
   5.272 +			name = Credits.rtf;
   5.273 +			sourceTree = "<group>";
   5.274 +		};
   5.275 +		BBFC08B1164C684D003E6A99 /* MainMenu.xib */ = {
   5.276 +			isa = PBXVariantGroup;
   5.277 +			children = (
   5.278 +				BBFC08B2164C684D003E6A99 /* en */,
   5.279 +			);
   5.280 +			name = MainMenu.xib;
   5.281 +			sourceTree = "<group>";
   5.282 +		};
   5.283 +/* End PBXVariantGroup section */
   5.284 +
   5.285  /* Begin XCBuildConfiguration section */
   5.286  		0017958910741F7900F5D044 /* Debug */ = {
   5.287  			isa = XCBuildConfiguration;
   5.288 @@ -5830,6 +6005,24 @@
   5.289  			};
   5.290  			name = Release;
   5.291  		};
   5.292 +		BBFC08CB164C6862003E6A99 /* Debug */ = {
   5.293 +			isa = XCBuildConfiguration;
   5.294 +			buildSettings = {
   5.295 +				INFOPLIST_FILE = "testgamecontroller-Info.plist";
   5.296 +				PRODUCT_NAME = testgamecontroller;
   5.297 +				WRAPPER_EXTENSION = app;
   5.298 +			};
   5.299 +			name = Debug;
   5.300 +		};
   5.301 +		BBFC08CC164C6862003E6A99 /* Release */ = {
   5.302 +			isa = XCBuildConfiguration;
   5.303 +			buildSettings = {
   5.304 +				INFOPLIST_FILE = "testgamecontroller-Info.plist";
   5.305 +				PRODUCT_NAME = testgamecontroller;
   5.306 +				WRAPPER_EXTENSION = app;
   5.307 +			};
   5.308 +			name = Release;
   5.309 +		};
   5.310  /* End XCBuildConfiguration section */
   5.311  
   5.312  /* Begin XCConfigurationList section */
   5.313 @@ -6256,6 +6449,15 @@
   5.314  			defaultConfigurationIsVisible = 0;
   5.315  			defaultConfigurationName = Debug;
   5.316  		};
   5.317 +		BBFC08CA164C6862003E6A99 /* Build configuration list for PBXNativeTarget "testgamecontroller" */ = {
   5.318 +			isa = XCConfigurationList;
   5.319 +			buildConfigurations = (
   5.320 +				BBFC08CB164C6862003E6A99 /* Debug */,
   5.321 +				BBFC08CC164C6862003E6A99 /* Release */,
   5.322 +			);
   5.323 +			defaultConfigurationIsVisible = 0;
   5.324 +			defaultConfigurationName = Debug;
   5.325 +		};
   5.326  /* End XCConfigurationList section */
   5.327  	};
   5.328  	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/Xcode/SDLTest/testgamecontroller-Info.plist	Mon Nov 26 16:37:54 2012 -0800
     6.3 @@ -0,0 +1,32 @@
     6.4 +<?xml version="1.0" encoding="UTF-8"?>
     6.5 +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     6.6 +<plist version="1.0">
     6.7 +<dict>
     6.8 +	<key>CFBundleDevelopmentRegion</key>
     6.9 +	<string>English</string>
    6.10 +	<key>CFBundleExecutable</key>
    6.11 +	<string>testgamecontroller</string>
    6.12 +	<key>CFBundleGetInfoString</key>
    6.13 +	<string></string>
    6.14 +	<key>CFBundleIconFile</key>
    6.15 +	<string></string>
    6.16 +	<key>CFBundleIdentifier</key>
    6.17 +	<string></string>
    6.18 +	<key>CFBundleInfoDictionaryVersion</key>
    6.19 +	<string>6.0</string>
    6.20 +	<key>CFBundleName</key>
    6.21 +	<string></string>
    6.22 +	<key>CFBundlePackageType</key>
    6.23 +	<string>APPL</string>
    6.24 +	<key>CFBundleShortVersionString</key>
    6.25 +	<string></string>
    6.26 +	<key>CFBundleSignature</key>
    6.27 +	<string>????</string>
    6.28 +	<key>CFBundleVersion</key>
    6.29 +	<string>0.0.1d1</string>
    6.30 +	<key>NSMainNibFile</key>
    6.31 +	<string>SDLMain.nib</string>
    6.32 +	<key>NSPrincipalClass</key>
    6.33 +	<string>NSApplication</string>
    6.34 +</dict>
    6.35 +</plist>
     7.1 --- a/include/SDL.h	Mon Nov 26 14:59:07 2012 -0800
     7.2 +++ b/include/SDL.h	Mon Nov 26 16:37:54 2012 -0800
     7.3 @@ -79,6 +79,7 @@
     7.4  #include "SDL_endian.h"
     7.5  #include "SDL_error.h"
     7.6  #include "SDL_events.h"
     7.7 +#include "SDL_gamecontroller.h"
     7.8  #include "SDL_hints.h"
     7.9  #include "SDL_loadso.h"
    7.10  #include "SDL_log.h"
    7.11 @@ -115,6 +116,7 @@
    7.12  #define SDL_INIT_VIDEO          0x00000020
    7.13  #define SDL_INIT_JOYSTICK       0x00000200
    7.14  #define SDL_INIT_HAPTIC         0x00001000
    7.15 +#define SDL_INIT_GAMECONTROLLER 0x00002000		/**< turn on game controller also implicitly does JOYSTICK */
    7.16  #define SDL_INIT_NOPARACHUTE    0x00100000      /**< Don't catch fatal signals */
    7.17  #define SDL_INIT_EVERYTHING     0x0000FFFF
    7.18  /*@}*/
     8.1 --- a/include/SDL_events.h	Mon Nov 26 14:59:07 2012 -0800
     8.2 +++ b/include/SDL_events.h	Mon Nov 26 16:37:54 2012 -0800
     8.3 @@ -34,6 +34,7 @@
     8.4  #include "SDL_keyboard.h"
     8.5  #include "SDL_mouse.h"
     8.6  #include "SDL_joystick.h"
     8.7 +#include "SDL_gamecontroller.h"
     8.8  #include "SDL_quit.h"
     8.9  #include "SDL_gesture.h"
    8.10  #include "SDL_touch.h"
    8.11 @@ -90,6 +91,15 @@
    8.12      SDL_JOYHATMOTION,           /**< Joystick hat position change */
    8.13      SDL_JOYBUTTONDOWN,          /**< Joystick button pressed */
    8.14      SDL_JOYBUTTONUP,            /**< Joystick button released */
    8.15 +    SDL_JOYDEVICEADDED,         /**< A new joystick has been inserted into the system */
    8.16 +    SDL_JOYDEVICEREMOVED,       /**< An opened joystick has been removed */
    8.17 +
    8.18 +	/* Game controller events */
    8.19 +	SDL_CONTROLLERAXISMOTION  = 0x650, /**< Game controller axis motion */
    8.20 +	SDL_CONTROLLERBUTTONDOWN,          /**< Game controller button pressed */
    8.21 +	SDL_CONTROLLERBUTTONUP,            /**< Game controller button released */
    8.22 +	SDL_CONTROLLERDEVICEADDED,         /**< A new Game controller has been inserted into the system */
    8.23 +	SDL_CONTROLLERDEVICEREMOVED,       /**< An opened Game controller has been removed */
    8.24  
    8.25      /* Touch events */
    8.26      SDL_FINGERDOWN      = 0x700,
    8.27 @@ -231,7 +241,7 @@
    8.28  {
    8.29      Uint32 type;        /**< ::SDL_JOYAXISMOTION */
    8.30      Uint32 timestamp;
    8.31 -    Uint8 which;        /**< The joystick device index */
    8.32 +    Uint8 which;        /**< The joystick instance id */
    8.33      Uint8 axis;         /**< The joystick axis index */
    8.34      Uint8 padding1;
    8.35      Uint8 padding2;
    8.36 @@ -245,7 +255,7 @@
    8.37  {
    8.38      Uint32 type;        /**< ::SDL_JOYBALLMOTION */
    8.39      Uint32 timestamp;
    8.40 -    Uint8 which;        /**< The joystick device index */
    8.41 +    Uint8 which;        /**< The joystick instance id */
    8.42      Uint8 ball;         /**< The joystick trackball index */
    8.43      Uint8 padding1;
    8.44      Uint8 padding2;
    8.45 @@ -260,7 +270,7 @@
    8.46  {
    8.47      Uint32 type;        /**< ::SDL_JOYHATMOTION */
    8.48      Uint32 timestamp;
    8.49 -    Uint8 which;        /**< The joystick device index */
    8.50 +    Uint8 which;        /**< The joystick instance id */
    8.51      Uint8 hat;          /**< The joystick hat index */
    8.52      Uint8 value;        /**< The hat position value.
    8.53                           *   \sa ::SDL_HAT_LEFTUP ::SDL_HAT_UP ::SDL_HAT_RIGHTUP
    8.54 @@ -279,12 +289,59 @@
    8.55  {
    8.56      Uint32 type;        /**< ::SDL_JOYBUTTONDOWN or ::SDL_JOYBUTTONUP */
    8.57      Uint32 timestamp;
    8.58 -    Uint8 which;        /**< The joystick device index */
    8.59 +    Uint8 which;        /**< The joystick instance id */
    8.60      Uint8 button;       /**< The joystick button index */
    8.61      Uint8 state;        /**< ::SDL_PRESSED or ::SDL_RELEASED */
    8.62      Uint8 padding1;
    8.63  } SDL_JoyButtonEvent;
    8.64  
    8.65 +/**
    8.66 + *  \brief Joystick device event structure (event.jdevice.*)
    8.67 + */
    8.68 +typedef struct SDL_JoyDeviceEvent
    8.69 +{
    8.70 +	Uint32 type;        /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */
    8.71 +	Uint32 timestamp;
    8.72 +	Uint32 which;        /**< The joystick device index for ADD, instance_id for REMOVE*/
    8.73 +} SDL_JoyDeviceEvent;
    8.74 +
    8.75 +
    8.76 +/**
    8.77 + *  \brief Game controller axis motion event structure (event.caxis.*)
    8.78 + */
    8.79 +typedef struct SDL_ControllerAxisEvent
    8.80 +{
    8.81 +    Uint32 type;        /**< ::SDL_CONTROLLERAXISMOTION */
    8.82 +    Uint32 timestamp;
    8.83 +    Uint8 which;        /**< The joystick instance id */
    8.84 +    SDL_CONTROLLER_AXIS axis;         /**< The joystick axis index */
    8.85 +    int value;          /**< The axis value (range: -32768 to 32767) */
    8.86 +} SDL_ControllerAxisEvent;
    8.87 +
    8.88 +
    8.89 +/**
    8.90 + *  \brief Game controller button event structure (event.cbutton.*)
    8.91 + */
    8.92 +typedef struct SDL_ControllerButtonEvent
    8.93 +{
    8.94 +    Uint32 type;        /**< ::SDL_CONTROLLERBUTTONDOWN or ::SDL_CONTROLLERBUTTONUP */
    8.95 +    Uint32 timestamp;
    8.96 +    Uint8 which;        /**< The joystick instance id */
    8.97 +    SDL_CONTROLLER_BUTTON button;       /**< The joystick button index */
    8.98 +    Uint8 state;        /**< ::SDL_PRESSED or ::SDL_RELEASED */
    8.99 +} SDL_ControllerButtonEvent;
   8.100 +
   8.101 +
   8.102 +/**
   8.103 + *  \brief Controller device event structure (event.cdevice.*)
   8.104 + */
   8.105 +typedef struct SDL_ControllerDeviceEvent
   8.106 +{
   8.107 +	Uint32 type;        /**< ::SDL_CONTROLLERDEVICEADDED or ::SDL_CONTROLLERDEVICEREMOVED */
   8.108 +	Uint32 timestamp;
   8.109 +	Uint32 which;        /**< The joystick device index for ADD, instance_id for REMOVE*/
   8.110 +} SDL_ControllerDeviceEvent;
   8.111 +
   8.112  
   8.113  /**
   8.114   *  \brief Touch finger motion/finger event structure (event.tfinger.*)
   8.115 @@ -430,6 +487,10 @@
   8.116      SDL_JoyBallEvent jball;         /**< Joystick ball event data */
   8.117      SDL_JoyHatEvent jhat;           /**< Joystick hat event data */
   8.118      SDL_JoyButtonEvent jbutton;     /**< Joystick button event data */
   8.119 +    SDL_JoyDeviceEvent jdevice;     /**< Joystick device change event data */
   8.120 +	SDL_ControllerAxisEvent caxis;		/**< Game Controller button event data */
   8.121 +	SDL_ControllerButtonEvent cbutton;  /**< Game Controller button event data */
   8.122 +	SDL_ControllerDeviceEvent cdevice;  /**< Game Controller device event data */
   8.123      SDL_QuitEvent quit;             /**< Quit request event data */
   8.124      SDL_UserEvent user;             /**< Custom event data */
   8.125      SDL_SysWMEvent syswm;           /**< System dependent window event data */
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/include/SDL_gamecontroller.h	Mon Nov 26 16:37:54 2012 -0800
     9.3 @@ -0,0 +1,257 @@
     9.4 +/*
     9.5 +  Simple DirectMedia Layer
     9.6 +  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     9.7 +
     9.8 +  This software is provided 'as-is', without any express or implied
     9.9 +  warranty.  In no event will the authors be held liable for any damages
    9.10 +  arising from the use of this software.
    9.11 +
    9.12 +  Permission is granted to anyone to use this software for any purpose,
    9.13 +  including commercial applications, and to alter it and redistribute it
    9.14 +  freely, subject to the following restrictions:
    9.15 +
    9.16 +  1. The origin of this software must not be misrepresented; you must not
    9.17 +     claim that you wrote the original software. If you use this software
    9.18 +     in a product, an acknowledgment in the product documentation would be
    9.19 +     appreciated but is not required.
    9.20 +  2. Altered source versions must be plainly marked as such, and must not be
    9.21 +     misrepresented as being the original software.
    9.22 +  3. This notice may not be removed or altered from any source distribution.
    9.23 +*/
    9.24 +
    9.25 +/**
    9.26 + *  \file SDL_gamecontroller.h
    9.27 + *  
    9.28 + *  Include file for SDL game controller event handling
    9.29 + */
    9.30 +
    9.31 +#ifndef _SDL_gamecontroller_h
    9.32 +#define _SDL_gamecontroller_h
    9.33 +
    9.34 +#include "SDL_stdinc.h"
    9.35 +#include "SDL_error.h"
    9.36 +#include "SDL_joystick.h"
    9.37 +
    9.38 +#include "begin_code.h"
    9.39 +/* Set up for C function definitions, even when using C++ */
    9.40 +#ifdef __cplusplus
    9.41 +/* *INDENT-OFF* */
    9.42 +extern "C" {
    9.43 +/* *INDENT-ON* */
    9.44 +#endif
    9.45 +
    9.46 +/**
    9.47 + *  \file SDL_gamecontroller.h
    9.48 + *
    9.49 + *  In order to use these functions, SDL_Init() must have been called
    9.50 + *  with the ::SDL_INIT_JOYSTICK flag.  This causes SDL to scan the system
    9.51 + *  for game controllers, and load appropriate drivers.
    9.52 + */
    9.53 +
    9.54 +/* The gamecontroller structure used to identify an SDL game controller */
    9.55 +struct _SDL_GameController;
    9.56 +typedef struct _SDL_GameController SDL_GameController;
    9.57 +
    9.58 +
    9.59 +typedef enum 
    9.60 +{
    9.61 +	SDL_CONTROLLER_BINDTYPE_NONE = 0,
    9.62 +	SDL_CONTROLLER_BINDTYPE_BUTTON,
    9.63 +	SDL_CONTROLLER_BINDTYPE_AXIS,
    9.64 +	SDL_CONTROLLER_BINDTYPE_HAT,
    9.65 +} SDL_CONTROLLER_BINDTYPE;
    9.66 +/**
    9.67 + *  get the sdl joystick layer binding for this controller button/axis mapping
    9.68 + */
    9.69 +struct _SDL_GameControllerHatBind
    9.70 +{
    9.71 +	int hat;
    9.72 +	int hat_mask;
    9.73 +};
    9.74 +
    9.75 +typedef struct _SDL_GameControllerButtonBind
    9.76 +{
    9.77 +	SDL_CONTROLLER_BINDTYPE m_eBindType;
    9.78 +	union
    9.79 +	{
    9.80 +		int button;
    9.81 +		int axis;
    9.82 +		struct _SDL_GameControllerHatBind hat;
    9.83 +	};
    9.84 +
    9.85 +} SDL_GameControllerButtonBind;
    9.86 +
    9.87 +
    9.88 +/**
    9.89 + *  To count the number of game controllers in the system for the following:
    9.90 + *	int nJoysticks = SDL_NumJoysticks();
    9.91 + *	int nGameControllers = 0;
    9.92 + *	for ( int i = 0; i < nJoysticks; i++ ) {
    9.93 + *		if ( SDL_IsGameController(i) ) {
    9.94 + *			nGameControllers++;
    9.95 + *		}
    9.96 + *  }
    9.97 + *
    9.98 + *  Using the SDL_HINT_GAMECONTROLLERCONFIG hint you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is:
    9.99 + *	guid,name,mappings
   9.100 + *
   9.101 + *  Where GUID is the string value from SDL_JoystickGetGUIDString(), name is the human readable string for the device and mappings are controller mappings to joystick ones.
   9.102 + *  Under Windows there is a reserved GUID of "xinput" that covers any XInput devices.
   9.103 + *	The mapping format for joystick is: 
   9.104 + *		bX - a joystick button, index X
   9.105 + *		hX.Y - hat X with value Y
   9.106 + *		aX - axis X of the joystick
   9.107 + *  Buttons can be used as a controller axis and vice versa.
   9.108 + *
   9.109 + *  This string shows an example of a valid mapping for a controller
   9.110 + * 	"341a3608000000000000504944564944,Aferglow PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7",
   9.111 + *
   9.112 + */
   9.113 +
   9.114 +
   9.115 +/**
   9.116 + *  Is the joystick on this index supported by the game controller interface?
   9.117 + *		returns 1 if supported, 0 otherwise.
   9.118 + */
   9.119 +extern DECLSPEC int SDLCALL SDL_IsGameController(int joystick_index);
   9.120 +
   9.121 +
   9.122 +/**
   9.123 + *  Get the implementation dependent name of a game controller.
   9.124 + *  This can be called before any controllers are opened.
   9.125 + *  If no name can be found, this function returns NULL.
   9.126 + */
   9.127 +extern DECLSPEC const char *SDLCALL SDL_GameControllerNameForIndex(int joystick_index);
   9.128 +
   9.129 +/**
   9.130 + *  Open a game controller for use.  
   9.131 + *  The index passed as an argument refers to the N'th game controller on the system.  
   9.132 + *  This index is the value which will identify this controller in future controller
   9.133 + *  events.
   9.134 + *  
   9.135 + *  \return A controller identifier, or NULL if an error occurred.
   9.136 + */
   9.137 +extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerOpen(int joystick_index);
   9.138 +
   9.139 +/**
   9.140 + *  Return the name for this currently opened controller
   9.141 + */
   9.142 +extern DECLSPEC const char *SDLCALL SDL_GameControllerName(SDL_GameController * gamecontroller);
   9.143 +	
   9.144 +/**
   9.145 + *  Returns 1 if the controller has been opened and currently connected, or 0 if it has not.
   9.146 + */
   9.147 +extern DECLSPEC int SDLCALL SDL_GameControllerGetAttached(SDL_GameController * gamecontroller);
   9.148 +
   9.149 +/**
   9.150 + *  Get the underlying joystick object used by a controller
   9.151 + */
   9.152 +extern DECLSPEC SDL_Joystick *SDLCALL SDL_GameControllerGetJoystick(SDL_GameController * gamecontroller);
   9.153 +
   9.154 +/**
   9.155 + *  Enable/disable controller event polling.
   9.156 + *  
   9.157 + *  If controller events are disabled, you must call SDL_GameControllerUpdate()
   9.158 + *  yourself and check the state of the controller when you want controller
   9.159 + *  information.
   9.160 + *  
   9.161 + *  The state can be one of ::SDL_QUERY, ::SDL_ENABLE or ::SDL_IGNORE.
   9.162 + */
   9.163 +extern DECLSPEC int SDLCALL SDL_GameControllerEventState(int state);
   9.164 +
   9.165 +/**
   9.166 + *  The list of axii available from a controller
   9.167 + */
   9.168 +typedef enum 
   9.169 +{
   9.170 +	SDL_CONTROLLER_AXIS_INVALID = -1,
   9.171 +	SDL_CONTROLLER_AXIS_LEFTX,
   9.172 +	SDL_CONTROLLER_AXIS_LEFTY,
   9.173 +	SDL_CONTROLLER_AXIS_RIGHTX,
   9.174 +	SDL_CONTROLLER_AXIS_RIGHTY,
   9.175 +	SDL_CONTROLLER_AXIS_TRIGGERLEFT,
   9.176 +	SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
   9.177 +	SDL_CONTROLLER_AXIS_MAX
   9.178 +} SDL_CONTROLLER_AXIS;
   9.179 +
   9.180 +/**
   9.181 + *  turn this string into a axis mapping
   9.182 + */
   9.183 +extern DECLSPEC SDL_CONTROLLER_AXIS SDLCALL SDL_GameControllerGetAxisFromString(const char *pchString);
   9.184 +
   9.185 +/**
   9.186 + *  get the sdl joystick layer binding for this controller button mapping
   9.187 + */
   9.188 +extern DECLSPEC SDL_GameControllerButtonBind SDLCALL SDL_GameControllerGetBindForAxis(SDL_GameController * gamecontroller, SDL_CONTROLLER_AXIS button);
   9.189 +
   9.190 +/**
   9.191 + *  Get the current state of an axis control on a game controller.
   9.192 + *  
   9.193 + *  The state is a value ranging from -32768 to 32767.
   9.194 + *  
   9.195 + *  The axis indices start at index 0.
   9.196 + */
   9.197 +extern DECLSPEC Sint16 SDLCALL SDL_GameControllerGetAxis(SDL_GameController * gamecontroller,
   9.198 +                                                   SDL_CONTROLLER_AXIS axis);
   9.199 +
   9.200 +/**
   9.201 + *  The list of buttons available from a controller
   9.202 + */
   9.203 +typedef enum
   9.204 +{
   9.205 +	SDL_CONTROLLER_BUTTON_INVALID = -1,
   9.206 +	SDL_CONTROLLER_BUTTON_A,
   9.207 +	SDL_CONTROLLER_BUTTON_B,
   9.208 +	SDL_CONTROLLER_BUTTON_X,
   9.209 +	SDL_CONTROLLER_BUTTON_Y,
   9.210 +	SDL_CONTROLLER_BUTTON_BACK,
   9.211 +	SDL_CONTROLLER_BUTTON_GUIDE,
   9.212 +	SDL_CONTROLLER_BUTTON_START,
   9.213 +	SDL_CONTROLLER_BUTTON_LEFTSTICK,
   9.214 +	SDL_CONTROLLER_BUTTON_RIGHTSTICK,
   9.215 +	SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
   9.216 +	SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
   9.217 +	SDL_CONTROLLER_BUTTON_DPAD_UP,
   9.218 +	SDL_CONTROLLER_BUTTON_DPAD_DOWN,
   9.219 +	SDL_CONTROLLER_BUTTON_DPAD_LEFT,
   9.220 +	SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
   9.221 +	SDL_CONTROLLER_BUTTON_MAX
   9.222 +} SDL_CONTROLLER_BUTTON;
   9.223 +
   9.224 +/**
   9.225 + *  turn this string into a button mapping
   9.226 + */
   9.227 +extern DECLSPEC SDL_CONTROLLER_BUTTON SDLCALL SDL_GameControllerGetButtonFromString(const char *pchString);
   9.228 +
   9.229 +
   9.230 +/**
   9.231 + *  get the sdl joystick layer binding for this controller button mapping
   9.232 + */
   9.233 +extern DECLSPEC SDL_GameControllerButtonBind SDLCALL SDL_GameControllerGetBindForButton(SDL_GameController * gamecontroller, SDL_CONTROLLER_BUTTON button);
   9.234 +
   9.235 +
   9.236 +/**
   9.237 + *  Get the current state of a button on a game controller.
   9.238 + *  
   9.239 + *  The button indices start at index 0.
   9.240 + */
   9.241 +extern DECLSPEC Uint8 SDLCALL SDL_GameControllerGetButton(SDL_GameController * gamecontroller,
   9.242 +                                                    SDL_CONTROLLER_BUTTON button);
   9.243 +
   9.244 +/**
   9.245 + *  Close a controller previously opened with SDL_GameControllerOpen().
   9.246 + */
   9.247 +extern DECLSPEC void SDLCALL SDL_GameControllerClose(SDL_GameController * gamecontrollerk);
   9.248 +
   9.249 +
   9.250 +/* Ends C function definitions when using C++ */
   9.251 +#ifdef __cplusplus
   9.252 +/* *INDENT-OFF* */
   9.253 +}
   9.254 +/* *INDENT-ON* */
   9.255 +#endif
   9.256 +#include "close_code.h"
   9.257 +
   9.258 +#endif /* _SDL_gamecontroller_h */
   9.259 +
   9.260 +/* vi: set ts=4 sw=4 expandtab: */
    10.1 --- a/include/SDL_hints.h	Mon Nov 26 14:59:07 2012 -0800
    10.2 +++ b/include/SDL_hints.h	Mon Nov 26 16:37:54 2012 -0800
    10.3 @@ -190,6 +190,14 @@
    10.4  
    10.5  
    10.6  /**
    10.7 + *  \brief  A variable that lets you manually hint extra gamecontroller db entries
    10.8 + *
    10.9 + *  The variable expected newline delimited rows of gamecontroller config data, see SDL_gamecontroller.h
   10.10 + */
   10.11 +#define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG"
   10.12 +
   10.13 +
   10.14 +/**
   10.15   *  \brief  An enumeration of hint priorities
   10.16   */
   10.17  typedef enum
    11.1 --- a/include/SDL_joystick.h	Mon Nov 26 14:59:07 2012 -0800
    11.2 +++ b/include/SDL_joystick.h	Mon Nov 26 16:37:54 2012 -0800
    11.3 @@ -23,6 +23,17 @@
    11.4   *  \file SDL_joystick.h
    11.5   *  
    11.6   *  Include file for SDL joystick event handling
    11.7 + *
    11.8 + * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks, with the exact joystick
    11.9 + *   behind a device_index changing as joysticks are plugged and unplugged.
   11.10 + *
   11.11 + * The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted
   11.12 + *   then it will get a new instance_id, instance_id's are monotonically increasing identifiers of a joystick plugged in.
   11.13 + *
   11.14 + * The term JoystickGUID is a stable 128-bit identifier for a joystick device that does not change over time, it identifies class of 
   11.15 + *   the device (a X360 wired controller for example). This identifier is platform dependent.
   11.16 + *
   11.17 + *
   11.18   */
   11.19  
   11.20  #ifndef _SDL_joystick_h
   11.21 @@ -51,10 +62,11 @@
   11.22  struct _SDL_Joystick;
   11.23  typedef struct _SDL_Joystick SDL_Joystick;
   11.24  
   11.25 -
   11.26 +typedef int SDL_JoystickID;
   11.27 +	
   11.28  /* Function prototypes */
   11.29  /**
   11.30 - *  Count the number of joysticks attached to the system
   11.31 + *  Count the number of joysticks attached to the system right now
   11.32   */
   11.33  extern DECLSPEC int SDLCALL SDL_NumJoysticks(void);
   11.34  
   11.35 @@ -63,7 +75,7 @@
   11.36   *  This can be called before any joysticks are opened.
   11.37   *  If no name can be found, this function returns NULL.
   11.38   */
   11.39 -extern DECLSPEC const char *SDLCALL SDL_JoystickName(int device_index);
   11.40 +extern DECLSPEC const char *SDLCALL SDL_JoystickNameForIndex(int device_index);
   11.41  
   11.42  /**
   11.43   *  Open a joystick for use.  
   11.44 @@ -76,14 +88,47 @@
   11.45  extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickOpen(int device_index);
   11.46  
   11.47  /**
   11.48 - *  Returns 1 if the joystick has been opened, or 0 if it has not.
   11.49 + *  Return the name for this currently opened joystick.
   11.50 + *  If no name can be found, this function returns NULL.
   11.51   */
   11.52 -extern DECLSPEC int SDLCALL SDL_JoystickOpened(int device_index);
   11.53 +extern DECLSPEC const char *SDLCALL SDL_JoystickName(SDL_Joystick * joystick);
   11.54 +	
   11.55 +/* A structure that encodes the stable unique id for a joystick device */
   11.56 +typedef struct
   11.57 +{
   11.58 +	Uint8 data[16];
   11.59 +} JoystickGUID;
   11.60 +
   11.61 +/**
   11.62 + *  Return the GUID for the joystick at this index
   11.63 + */
   11.64 +extern DECLSPEC JoystickGUID SDLCALL SDL_JoystickGetDeviceGUID(int device_index);
   11.65 +
   11.66 +/**
   11.67 + *  Return the GUID for this opened joystick
   11.68 + */
   11.69 +extern DECLSPEC JoystickGUID SDLCALL SDL_JoystickGetGUID(SDL_Joystick * joystick);
   11.70 +
   11.71 +/**
   11.72 + *  Return a string representation for this guid. You are responsible for freeing memory from this call
   11.73 + */
   11.74 +extern DECLSPEC char *SDLCALL SDL_JoystickGetGUIDString(JoystickGUID guid);
   11.75 +
   11.76 +/**
   11.77 + *  convert a string into a joystick formatted guid
   11.78 + */
   11.79 +extern DECLSPEC JoystickGUID SDLCALL SDL_JoystickGetGUIDFromString(const char *pchGUID);
   11.80 +
   11.81 +
   11.82 +/**
   11.83 + *  Returns 1 if the joystick has been opened and currently connected, or 0 if it has not.
   11.84 + */
   11.85 +extern DECLSPEC int SDLCALL SDL_JoystickGetAttached(SDL_Joystick * joystick);
   11.86  
   11.87  /**
   11.88   *  Get the device index of an opened joystick.
   11.89   */
   11.90 -extern DECLSPEC int SDLCALL SDL_JoystickIndex(SDL_Joystick * joystick);
   11.91 +extern DECLSPEC SDL_JoystickID SDLCALL SDL_JoystickInstanceID(SDL_Joystick * joystick);
   11.92  
   11.93  /**
   11.94   *  Get the number of general axis controls on a joystick.
    12.1 --- a/src/SDL.c	Mon Nov 26 14:59:07 2012 -0800
    12.2 +++ b/src/SDL.c	Mon Nov 26 16:37:54 2012 -0800
    12.3 @@ -44,7 +44,20 @@
    12.4  /* The initialized subsystems */
    12.5  static Uint32 SDL_initialized = 0;
    12.6  static Uint32 ticks_started = 0;
    12.7 +static SDL_bool SDL_bInMainQuit = SDL_FALSE;
    12.8 +static Uint8 SDL_SubsystemRefCount[ 32 ]; // keep a per subsystem init
    12.9  
   12.10 +/* helper func to return the index of the MSB in an int */
   12.11 +int msb32_idx( Uint32 n)
   12.12 +{
   12.13 +	int b = 0;
   12.14 +	if (!n) return -1;
   12.15 +
   12.16 +#define step(x) if (n >= ((Uint32)1) << x) b += x, n >>= x
   12.17 +	step(16); step(8); step(4); step(2); step(1);
   12.18 +#undef step
   12.19 +	return b;
   12.20 +}
   12.21  
   12.22  int
   12.23  SDL_InitSubSystem(Uint32 flags)
   12.24 @@ -55,11 +68,16 @@
   12.25          SDL_StartTicks();
   12.26          ticks_started = 1;
   12.27      }
   12.28 -    if ((flags & SDL_INIT_TIMER) && !(SDL_initialized & SDL_INIT_TIMER)) {
   12.29 -        if (SDL_TimerInit() < 0) {
   12.30 -            return (-1);
   12.31 -        }
   12.32 -        SDL_initialized |= SDL_INIT_TIMER;
   12.33 +
   12.34 +    if ((flags & SDL_INIT_TIMER) ){
   12.35 +		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_TIMER) ]++;
   12.36 +		SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_TIMER) ] < 254 );
   12.37 +		if ( !(SDL_initialized & SDL_INIT_TIMER)) {
   12.38 +			if (SDL_TimerInit() < 0) {
   12.39 +				return (-1);
   12.40 +			}
   12.41 +			SDL_initialized |= SDL_INIT_TIMER;
   12.42 +		}
   12.43      }
   12.44  #else
   12.45      if (flags & SDL_INIT_TIMER) {
   12.46 @@ -70,11 +88,15 @@
   12.47  
   12.48  #if !SDL_VIDEO_DISABLED
   12.49      /* Initialize the video/event subsystem */
   12.50 -    if ((flags & SDL_INIT_VIDEO) && !(SDL_initialized & SDL_INIT_VIDEO)) {
   12.51 -        if (SDL_VideoInit(NULL) < 0) {
   12.52 -            return (-1);
   12.53 -        }
   12.54 -        SDL_initialized |= SDL_INIT_VIDEO;
   12.55 +    if ((flags & SDL_INIT_VIDEO) ) {
   12.56 +		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_VIDEO) ]++;
   12.57 +		SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_VIDEO) ] < 254 );
   12.58 +		if ( !(SDL_initialized & SDL_INIT_VIDEO)) {
   12.59 +			if (SDL_VideoInit(NULL) < 0) {
   12.60 +				return (-1);
   12.61 +			}
   12.62 +			SDL_initialized |= SDL_INIT_VIDEO;
   12.63 +		}
   12.64      }
   12.65  #else
   12.66      if (flags & SDL_INIT_VIDEO) {
   12.67 @@ -85,11 +107,15 @@
   12.68  
   12.69  #if !SDL_AUDIO_DISABLED
   12.70      /* Initialize the audio subsystem */
   12.71 -    if ((flags & SDL_INIT_AUDIO) && !(SDL_initialized & SDL_INIT_AUDIO)) {
   12.72 -        if (SDL_AudioInit(NULL) < 0) {
   12.73 -            return (-1);
   12.74 -        }
   12.75 -        SDL_initialized |= SDL_INIT_AUDIO;
   12.76 +    if ((flags & SDL_INIT_AUDIO) ) {
   12.77 +		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_AUDIO) ]++;
   12.78 +		SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_AUDIO) ] < 254 );
   12.79 +		if ( !(SDL_initialized & SDL_INIT_AUDIO)) {
   12.80 +			if (SDL_AudioInit(NULL) < 0) {
   12.81 +				return (-1);
   12.82 +			}
   12.83 +			SDL_initialized |= SDL_INIT_AUDIO;
   12.84 +		}
   12.85      }
   12.86  #else
   12.87      if (flags & SDL_INIT_AUDIO) {
   12.88 @@ -100,10 +126,23 @@
   12.89  
   12.90  #if !SDL_JOYSTICK_DISABLED
   12.91      /* Initialize the joystick subsystem */
   12.92 -    if ((flags & SDL_INIT_JOYSTICK) && !(SDL_initialized & SDL_INIT_JOYSTICK)) {
   12.93 -        if (SDL_JoystickInit() < 0) {
   12.94 +    if ( ( (flags & SDL_INIT_JOYSTICK)  ) || ((flags & SDL_INIT_GAMECONTROLLER) ) ) { // game controller implies joystick
   12.95 +		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_JOYSTICK) ]++;
   12.96 +		SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_JOYSTICK) ] < 254 );
   12.97 +        if ( !(SDL_initialized & SDL_INIT_JOYSTICK) && SDL_JoystickInit() < 0) {
   12.98              return (-1);
   12.99          }
  12.100 +
  12.101 +		if ((flags & SDL_INIT_GAMECONTROLLER) ) {
  12.102 +			SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_GAMECONTROLLER) ]++;
  12.103 +			SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_GAMECONTROLLER) ] < 254 );
  12.104 +			if ( !(SDL_initialized & SDL_INIT_GAMECONTROLLER)) {
  12.105 +				if (SDL_GameControllerInit() < 0) {
  12.106 +					return (-1);
  12.107 +				}
  12.108 +				SDL_initialized |= SDL_INIT_GAMECONTROLLER;
  12.109 +			}
  12.110 +		}
  12.111          SDL_initialized |= SDL_INIT_JOYSTICK;
  12.112      }
  12.113  #else
  12.114 @@ -115,11 +154,15 @@
  12.115  
  12.116  #if !SDL_HAPTIC_DISABLED
  12.117      /* Initialize the haptic subsystem */
  12.118 -    if ((flags & SDL_INIT_HAPTIC) && !(SDL_initialized & SDL_INIT_HAPTIC)) {
  12.119 -        if (SDL_HapticInit() < 0) {
  12.120 -            return (-1);
  12.121 -        }
  12.122 -        SDL_initialized |= SDL_INIT_HAPTIC;
  12.123 +    if ((flags & SDL_INIT_HAPTIC) ) {
  12.124 +		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_HAPTIC) ]++;
  12.125 +		SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_HAPTIC) ] < 254 );
  12.126 +		if ( !(SDL_initialized & SDL_INIT_HAPTIC)) {
  12.127 +			if (SDL_HapticInit() < 0) {
  12.128 +				return (-1);
  12.129 +			}
  12.130 +			SDL_initialized |= SDL_INIT_HAPTIC;
  12.131 +		}
  12.132      }
  12.133  #else
  12.134      if (flags & SDL_INIT_HAPTIC) {
  12.135 @@ -156,6 +199,7 @@
  12.136          SDL_InstallParachute();
  12.137      }
  12.138  
  12.139 +	SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
  12.140      return (0);
  12.141  }
  12.142  
  12.143 @@ -164,33 +208,62 @@
  12.144  {
  12.145      /* Shut down requested initialized subsystems */
  12.146  #if !SDL_JOYSTICK_DISABLED
  12.147 -    if ((flags & SDL_initialized & SDL_INIT_JOYSTICK)) {
  12.148 -        SDL_JoystickQuit();
  12.149 -        SDL_initialized &= ~SDL_INIT_JOYSTICK;
  12.150 +    if ((flags & SDL_initialized & SDL_INIT_JOYSTICK) || (flags & SDL_initialized & SDL_INIT_GAMECONTROLLER)) {
  12.151 +		if ( (flags & SDL_initialized & SDL_INIT_GAMECONTROLLER) ) {
  12.152 +			SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_GAMECONTROLLER) ]--;
  12.153 +			if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_GAMECONTROLLER) ] == 0 ) {
  12.154 +				SDL_GameControllerQuit();
  12.155 +				SDL_initialized &= ~SDL_INIT_GAMECONTROLLER;
  12.156 +			}
  12.157 +		}
  12.158 +
  12.159 +		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_JOYSTICK) ]--;
  12.160 +		if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_JOYSTICK) ] == 0 )
  12.161 +		{
  12.162 +			SDL_JoystickQuit();
  12.163 +			SDL_initialized &= ~SDL_INIT_JOYSTICK;
  12.164 +		}
  12.165 +
  12.166      }
  12.167  #endif
  12.168  #if !SDL_HAPTIC_DISABLED
  12.169      if ((flags & SDL_initialized & SDL_INIT_HAPTIC)) {
  12.170 -        SDL_HapticQuit();
  12.171 -        SDL_initialized &= ~SDL_INIT_HAPTIC;
  12.172 +		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_HAPTIC) ]--;
  12.173 +		if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_HAPTIC) ] == 0 )
  12.174 +		{
  12.175 +			SDL_HapticQuit();
  12.176 +			SDL_initialized &= ~SDL_INIT_HAPTIC;
  12.177 +		}
  12.178      }
  12.179  #endif
  12.180  #if !SDL_AUDIO_DISABLED
  12.181      if ((flags & SDL_initialized & SDL_INIT_AUDIO)) {
  12.182 -        SDL_AudioQuit();
  12.183 -        SDL_initialized &= ~SDL_INIT_AUDIO;
  12.184 +		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_AUDIO) ]--;
  12.185 +		if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_AUDIO) ] == 0 )
  12.186 +		{
  12.187 +			SDL_AudioQuit();
  12.188 +			SDL_initialized &= ~SDL_INIT_AUDIO;
  12.189 +		}
  12.190      }
  12.191  #endif
  12.192  #if !SDL_VIDEO_DISABLED
  12.193      if ((flags & SDL_initialized & SDL_INIT_VIDEO)) {
  12.194 -        SDL_VideoQuit();
  12.195 -        SDL_initialized &= ~SDL_INIT_VIDEO;
  12.196 +		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_VIDEO) ]--;
  12.197 +		if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_VIDEO) ] == 0 )
  12.198 +		{
  12.199 +			SDL_VideoQuit();
  12.200 +			SDL_initialized &= ~SDL_INIT_VIDEO;
  12.201 +		}
  12.202      }
  12.203  #endif
  12.204  #if !SDL_TIMERS_DISABLED
  12.205      if ((flags & SDL_initialized & SDL_INIT_TIMER)) {
  12.206 -        SDL_TimerQuit();
  12.207 -        SDL_initialized &= ~SDL_INIT_TIMER;
  12.208 +		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_TIMER) ]--;
  12.209 +		if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_TIMER) ] == 0 )
  12.210 +		{
  12.211 +			SDL_TimerQuit();
  12.212 +			SDL_initialized &= ~SDL_INIT_TIMER;
  12.213 +		}
  12.214      }
  12.215  #endif
  12.216  }
  12.217 @@ -207,6 +280,7 @@
  12.218  void
  12.219  SDL_Quit(void)
  12.220  {
  12.221 +	SDL_bInMainQuit = SDL_TRUE;
  12.222      /* Quit all subsystems */
  12.223  #if defined(__WIN32__)
  12.224      SDL_HelperWindowDestroy();
  12.225 @@ -219,6 +293,9 @@
  12.226      SDL_ClearHints();
  12.227      SDL_AssertionsQuit();
  12.228      SDL_LogResetPriorities();
  12.229 +
  12.230 +	SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
  12.231 +	SDL_bInMainQuit = SDL_FALSE;
  12.232  }
  12.233  
  12.234  /* Get the library version number */
    13.1 --- a/src/events/SDL_events.c	Mon Nov 26 14:59:07 2012 -0800
    13.2 +++ b/src/events/SDL_events.c	Mon Nov 26 16:37:54 2012 -0800
    13.3 @@ -70,7 +70,7 @@
    13.4  SDL_ShouldPollJoystick()
    13.5  {
    13.6  #if !SDL_JOYSTICK_DISABLED
    13.7 -    if (SDL_numjoysticks &&
    13.8 +    if (SDL_PrivateJoystickNeedsPolling() &&
    13.9          (!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] ||
   13.10           SDL_JoystickEventState(SDL_QUERY))) {
   13.11          return SDL_TRUE;
    14.1 --- a/src/haptic/SDL_haptic.c	Mon Nov 26 14:59:07 2012 -0800
    14.2 +++ b/src/haptic/SDL_haptic.c	Mon Nov 26 16:37:54 2012 -0800
    14.3 @@ -238,7 +238,7 @@
    14.4      int ret;
    14.5  
    14.6      /* Must be a valid joystick */
    14.7 -    if (!SDL_PrivateJoystickValid(&joystick)) {
    14.8 +    if (!SDL_PrivateJoystickValid(joystick)) {
    14.9          return -1;
   14.10      }
   14.11  
   14.12 @@ -263,7 +263,7 @@
   14.13      SDL_Haptic *haptic;
   14.14  
   14.15      /* Must be a valid joystick */
   14.16 -    if (!SDL_PrivateJoystickValid(&joystick)) {
   14.17 +    if (!SDL_PrivateJoystickValid(joystick)) {
   14.18          SDL_SetError("Haptic: Joystick isn't valid.");
   14.19          return NULL;
   14.20      }
    15.1 --- a/src/haptic/windows/SDL_syshaptic.c	Mon Nov 26 14:59:07 2012 -0800
    15.2 +++ b/src/haptic/windows/SDL_syshaptic.c	Mon Nov 26 16:37:54 2012 -0800
    15.3 @@ -520,7 +520,7 @@
    15.4  
    15.5      /* Grab the first mouse haptic device we find. */
    15.6      for (i = 0; i < SDL_numhaptics; i++) {
    15.7 -        if (SDL_hapticlist[i].capabilities.dwDevType == DIDEVTYPE_MOUSE) {
    15.8 +        if (SDL_hapticlist[i].capabilities.dwDevType == DI8DEVCLASS_POINTER ) {
    15.9              return i;
   15.10          }
   15.11      }
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/joystick/SDL_gamecontroller.c	Mon Nov 26 16:37:54 2012 -0800
    16.3 @@ -0,0 +1,1125 @@
    16.4 +/*
    16.5 +  Simple DirectMedia Layer
    16.6 +  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
    16.7 +
    16.8 +  This software is provided 'as-is', without any express or implied
    16.9 +  warranty.  In no event will the authors be held liable for any damages
   16.10 +  arising from the use of this software.
   16.11 +
   16.12 +  Permission is granted to anyone to use this software for any purpose,
   16.13 +  including commercial applications, and to alter it and redistribute it
   16.14 +  freely, subject to the following restrictions:
   16.15 +
   16.16 +  1. The origin of this software must not be misrepresented; you must not
   16.17 +     claim that you wrote the original software. If you use this software
   16.18 +     in a product, an acknowledgment in the product documentation would be
   16.19 +     appreciated but is not required.
   16.20 +  2. Altered source versions must be plainly marked as such, and must not be
   16.21 +     misrepresented as being the original software.
   16.22 +  3. This notice may not be removed or altered from any source distribution.
   16.23 +*/
   16.24 +#include "SDL_config.h"
   16.25 +
   16.26 +/* This is the game controller API for Simple DirectMedia Layer */
   16.27 +
   16.28 +#include "SDL_events.h"
   16.29 +#include "SDL_assert.h"
   16.30 +#include "SDL_sysjoystick.h"
   16.31 +#include "SDL_hints.h"
   16.32 +
   16.33 +#if !SDL_EVENTS_DISABLED
   16.34 +#include "../events/SDL_events_c.h"
   16.35 +#endif
   16.36 +#define ABS(_x) ((_x) < 0 ? -(_x) : (_x))
   16.37 +
   16.38 +
   16.39 +/* a list of currently opened game controllers */
   16.40 +static SDL_GameController *SDL_gamecontrollers = NULL;
   16.41 +
   16.42 +/* keep track of the hat and mask value that transforms this hat movement into a button press */
   16.43 +struct _SDL_HatAsButton
   16.44 +{
   16.45 +	int hat;
   16.46 +	Uint8 mask;
   16.47 +};
   16.48 +
   16.49 +#define k_nMaxReverseEntries 20
   16.50 +
   16.51 +/* our in memory mapping db between joystick objects and controller mappings*/
   16.52 +struct _SDL_ControllerMapping
   16.53 +{
   16.54 +	JoystickGUID guid;
   16.55 +	const char *name;
   16.56 +
   16.57 +	// mapping of axis/button id to controller version
   16.58 +	int axes[SDL_CONTROLLER_AXIS_MAX];
   16.59 +	int buttons[SDL_CONTROLLER_BUTTON_MAX];
   16.60 +
   16.61 +	int axesasbutton[SDL_CONTROLLER_BUTTON_MAX];
   16.62 +	struct _SDL_HatAsButton hatasbutton[SDL_CONTROLLER_BUTTON_MAX];
   16.63 +	int buttonasaxis[SDL_CONTROLLER_AXIS_MAX];
   16.64 +
   16.65 +	// reverse mapping, joystick indices to buttons
   16.66 +	SDL_CONTROLLER_AXIS raxes[k_nMaxReverseEntries];
   16.67 +	SDL_CONTROLLER_BUTTON rbuttons[k_nMaxReverseEntries];
   16.68 +	SDL_CONTROLLER_BUTTON raxesasbutton[k_nMaxReverseEntries];
   16.69 +	struct _SDL_HatAsButton rhatasbutton[k_nMaxReverseEntries];
   16.70 +	SDL_CONTROLLER_AXIS rbuttonasaxis[k_nMaxReverseEntries];
   16.71 +};
   16.72 +
   16.73 +
   16.74 +/* our hard coded list of mapping support */
   16.75 +typedef struct _ControllerMapping_t
   16.76 +{
   16.77 +	JoystickGUID guid;
   16.78 +	char *name;
   16.79 +	const char *mapping;
   16.80 +	struct _ControllerMapping_t *next;
   16.81 +} ControllerMapping_t;
   16.82 +
   16.83 +
   16.84 +/* default mappings we support */
   16.85 +const char *s_ControllerMappings [] =
   16.86 +{
   16.87 +#ifdef __WIN32__
   16.88 +	"xinput,X360 Controller,a:b10,b:b11,y:b13,x:b12,start:b4,guide:b14,back:b5,dpup:b0,dpleft:b2,dpdown:b1,dpright:b3,leftshoulder:b8,rightshoulder:b9,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5",
   16.89 +	"341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7",
   16.90 +	"88880803000000000000504944564944,PS3,a:b2,b:b1,x:b0,y:b3,start:b11,back:b8,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.4,dpdown:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,guide:b12",
   16.91 +	"25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,x:b0,y:b3,start:b8,guide:,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.4,dpdown:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5",
   16.92 +#elif defined(__MACOSX__)
   16.93 +	"5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftshoulder:b4,rightshoulder:b5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5",
   16.94 +	"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,x:b12,y:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b6,dpdown:b7,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9",
   16.95 +#elif defined(__LINUX__)
   16.96 +	
   16.97 +#endif
   16.98 +	NULL
   16.99 +};
  16.100 +
  16.101 +static ControllerMapping_t *s_pSupportedControllers = NULL;
  16.102 +static ControllerMapping_t *s_pXInputMapping = NULL;
  16.103 +
  16.104 +/* The SDL game controller structure */
  16.105 +struct _SDL_GameController
  16.106 +{
  16.107 +	SDL_Joystick *joystick;	/* underlying joystick device */
  16.108 +	int ref_count;
  16.109 +	struct _SDL_ControllerMapping mapping; /* the mapping object for this controller */
  16.110 +	struct _SDL_GameController *next; /* pointer to next game controller we have allocated */
  16.111 +};
  16.112 +
  16.113 +
  16.114 +int SDL_PrivateGameControllerAxis(SDL_GameController * gamecontroller, SDL_CONTROLLER_AXIS axis, Sint16 value);
  16.115 +int	SDL_PrivateGameControllerButton(SDL_GameController * gamecontroller, SDL_CONTROLLER_BUTTON button, Uint8 state);
  16.116 +
  16.117 +/*
  16.118 + * Event filter to fire controller events from joystick ones
  16.119 + */
  16.120 +int SDL_GameControllerEventWatcher(void *userdata, SDL_Event * event)
  16.121 +{
  16.122 +	switch( event->type )
  16.123 +	{
  16.124 +	case SDL_JOYAXISMOTION:
  16.125 +		{
  16.126 +			SDL_GameController *controllerlist = SDL_gamecontrollers;
  16.127 +			while ( controllerlist )
  16.128 +			{
  16.129 +				if ( controllerlist->joystick->instance_id == event->jaxis.which )
  16.130 +				{
  16.131 +					if ( controllerlist->mapping.raxes[event->jaxis.axis] >= 0 ) // simple axis to axis, send it through
  16.132 +					{
  16.133 +						SDL_PrivateGameControllerAxis( controllerlist, controllerlist->mapping.raxes[event->jaxis.axis], event->jaxis.value );
  16.134 +					}
  16.135 +					else if ( controllerlist->mapping.raxesasbutton[event->jaxis.axis] >= 0 ) // simlate an axis as a button
  16.136 +					{
  16.137 +						SDL_PrivateGameControllerButton( controllerlist, controllerlist->mapping.raxesasbutton[event->jaxis.axis], ABS(event->jaxis.value) > 32768/2 ? 1 : 0 );
  16.138 +					}
  16.139 +					break;
  16.140 +				}
  16.141 +				controllerlist = controllerlist->next;
  16.142 +			}
  16.143 +		}
  16.144 +		break;
  16.145 +	case SDL_JOYBUTTONDOWN:
  16.146 +	case SDL_JOYBUTTONUP:
  16.147 +		{
  16.148 +			SDL_GameController *controllerlist = SDL_gamecontrollers;
  16.149 +			while ( controllerlist )
  16.150 +			{
  16.151 +				if ( controllerlist->joystick->instance_id == event->jbutton.which )
  16.152 +				{
  16.153 +					if ( controllerlist->mapping.rbuttons[event->jbutton.button] >= 0 ) // simple button as button
  16.154 +					{
  16.155 +						SDL_PrivateGameControllerButton( controllerlist, controllerlist->mapping.rbuttons[event->jbutton.button], event->jbutton.state );
  16.156 +					}
  16.157 +					else if ( controllerlist->mapping.rbuttonasaxis[event->jbutton.button] >= 0 ) // an button pretending to be an axis
  16.158 +					{
  16.159 +						SDL_PrivateGameControllerAxis( controllerlist, controllerlist->mapping.rbuttonasaxis[event->jbutton.button], event->jbutton.state > 0 ? 32768 : 0 );
  16.160 +					}
  16.161 +					break;
  16.162 +				}
  16.163 +				controllerlist = controllerlist->next;
  16.164 +			}
  16.165 +		}
  16.166 +		break;
  16.167 +	case SDL_JOYHATMOTION:
  16.168 +		{
  16.169 +			if ( event->jhat.hat == 0 ) // BUGBUG - multiple hat support??
  16.170 +			{
  16.171 +				SDL_GameController *controllerlist = SDL_gamecontrollers;
  16.172 +				while ( controllerlist )
  16.173 +				{
  16.174 +					if ( controllerlist->joystick->instance_id == event->jhat.which )
  16.175 +					{
  16.176 +						static Uint8 bHatsDown = 0;
  16.177 +						if ( event->jhat.value == 0 )
  16.178 +						{
  16.179 +							if ( bHatsDown & SDL_HAT_DOWN )
  16.180 +								SDL_PrivateGameControllerButton( controllerlist, SDL_CONTROLLER_BUTTON_DPAD_DOWN, 0 );
  16.181 +							if ( bHatsDown & SDL_HAT_UP )
  16.182 +								SDL_PrivateGameControllerButton( controllerlist, SDL_CONTROLLER_BUTTON_DPAD_UP, 0 );
  16.183 +							if ( bHatsDown & SDL_HAT_LEFT )
  16.184 +								SDL_PrivateGameControllerButton( controllerlist, SDL_CONTROLLER_BUTTON_DPAD_LEFT, 0 );
  16.185 +							if ( bHatsDown & SDL_HAT_RIGHT )
  16.186 +								SDL_PrivateGameControllerButton( controllerlist, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, 0 );
  16.187 +							bHatsDown = 0;
  16.188 +						}
  16.189 +						else if ( controllerlist->mapping.rhatasbutton[event->jhat.value].hat >= 0 )
  16.190 +						{
  16.191 +							bHatsDown |= event->jhat.value;
  16.192 +							SDL_PrivateGameControllerButton( controllerlist, controllerlist->mapping.rhatasbutton[event->jhat.value].hat, (event->jhat.value & controllerlist->mapping.rhatasbutton[event->jhat.value].mask) > 0 ? 1 : 0 );
  16.193 +						}
  16.194 +						break;
  16.195 +					}
  16.196 +					controllerlist = controllerlist->next;
  16.197 +				}
  16.198 +			}
  16.199 +		}
  16.200 +		break;
  16.201 +	case SDL_JOYDEVICEADDED:
  16.202 +		{
  16.203 +			if ( SDL_IsGameController(event->jdevice.which ) )
  16.204 +			{
  16.205 +				SDL_Event deviceevent;
  16.206 +				deviceevent.type = SDL_CONTROLLERDEVICEADDED;
  16.207 +				deviceevent.cdevice.which = event->jdevice.which;
  16.208 +				SDL_PushEvent(&deviceevent);
  16.209 +			}
  16.210 +		}
  16.211 +		break;
  16.212 +	case SDL_JOYDEVICEREMOVED:
  16.213 +		{
  16.214 +			SDL_GameController *controllerlist = SDL_gamecontrollers;
  16.215 +			while ( controllerlist )
  16.216 +			{
  16.217 +				if ( controllerlist->joystick->instance_id == event->jdevice.which )
  16.218 +				{
  16.219 +					SDL_Event deviceevent;
  16.220 +					deviceevent.type = SDL_CONTROLLERDEVICEREMOVED;
  16.221 +					deviceevent.cdevice.which = event->jdevice.which;
  16.222 +					SDL_PushEvent(&deviceevent);
  16.223 +					break;
  16.224 +				}
  16.225 +				controllerlist = controllerlist->next;
  16.226 +			}
  16.227 +		}
  16.228 +		break;
  16.229 +	default:
  16.230 +		break;
  16.231 +	}
  16.232 +
  16.233 +	return 1;
  16.234 +}
  16.235 +
  16.236 +/*
  16.237 + * Helper function to determine pre-caclulated offset to certain joystick mappings
  16.238 + */
  16.239 +ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
  16.240 +{
  16.241 +#ifdef __WIN32__
  16.242 +	if ( SDL_SYS_IsXInputDeviceIndex(device_index) && s_pXInputMapping )
  16.243 +	{
  16.244 +		return s_pXInputMapping;
  16.245 +	}
  16.246 +#endif
  16.247 +	return NULL;
  16.248 +}
  16.249 +
  16.250 +
  16.251 +/*
  16.252 + * convert a string to its enum equivalent
  16.253 + */
  16.254 +SDL_CONTROLLER_AXIS SDL_GameControllerGetAxisFromString( const char *pchString )
  16.255 +{
  16.256 +	if ( !pchString || !pchString[0] )
  16.257 +		return SDL_CONTROLLER_AXIS_INVALID;
  16.258 +
  16.259 +	if ( !SDL_strcasecmp( pchString, "leftx" ) )
  16.260 +		return SDL_CONTROLLER_AXIS_LEFTX;
  16.261 +	else if ( !SDL_strcasecmp( pchString, "lefty" ) )
  16.262 +		return SDL_CONTROLLER_AXIS_LEFTY;
  16.263 +	else if ( !SDL_strcasecmp( pchString, "rightx" ) )
  16.264 +		return SDL_CONTROLLER_AXIS_RIGHTX;
  16.265 +	else if ( !SDL_strcasecmp( pchString, "righty" ) )
  16.266 +		return SDL_CONTROLLER_AXIS_RIGHTY;
  16.267 +	else if ( !SDL_strcasecmp( pchString, "lefttrigger" ) )
  16.268 +		return SDL_CONTROLLER_AXIS_TRIGGERLEFT;
  16.269 +	else if ( !SDL_strcasecmp( pchString, "righttrigger" ) )
  16.270 +		return SDL_CONTROLLER_AXIS_TRIGGERRIGHT;
  16.271 +	else
  16.272 +		return SDL_CONTROLLER_AXIS_INVALID;
  16.273 +}
  16.274 +
  16.275 +
  16.276 +/*
  16.277 + * convert a string to its enum equivalent
  16.278 + */
  16.279 +SDL_CONTROLLER_BUTTON SDL_GameControllerGetButtonFromString( const char *pchString )
  16.280 +{
  16.281 +	if ( !pchString || !pchString[0] )
  16.282 +		return SDL_CONTROLLER_BUTTON_INVALID;
  16.283 +
  16.284 +	if ( !SDL_strcasecmp( pchString, "a" ) )
  16.285 +		return SDL_CONTROLLER_BUTTON_A;
  16.286 +	else if ( !SDL_strcasecmp( pchString, "b" ) )
  16.287 +		return SDL_CONTROLLER_BUTTON_B;
  16.288 +	else if ( !SDL_strcasecmp( pchString, "x" ) )
  16.289 +		return SDL_CONTROLLER_BUTTON_X;
  16.290 +	else if ( !SDL_strcasecmp( pchString, "y" ) )
  16.291 +		return SDL_CONTROLLER_BUTTON_Y;
  16.292 +	else if ( !SDL_strcasecmp( pchString, "start" ) )
  16.293 +		return SDL_CONTROLLER_BUTTON_START;
  16.294 +	else if ( !SDL_strcasecmp( pchString, "guide" ) )
  16.295 +		return SDL_CONTROLLER_BUTTON_GUIDE;
  16.296 +	else if ( !SDL_strcasecmp( pchString, "back" ) )
  16.297 +		return SDL_CONTROLLER_BUTTON_BACK;
  16.298 +	else if ( !SDL_strcasecmp( pchString, "dpup" ) )
  16.299 +		return SDL_CONTROLLER_BUTTON_DPAD_UP;
  16.300 +	else if ( !SDL_strcasecmp( pchString, "dpdown" ) )
  16.301 +		return SDL_CONTROLLER_BUTTON_DPAD_DOWN;
  16.302 +	else if ( !SDL_strcasecmp( pchString, "dpleft" ) )
  16.303 +		return SDL_CONTROLLER_BUTTON_DPAD_LEFT;
  16.304 +	else if ( !SDL_strcasecmp( pchString, "dpright" ) )
  16.305 +		return SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
  16.306 +	else if ( !SDL_strcasecmp( pchString, "leftshoulder" ) )
  16.307 +		return SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
  16.308 +	else if ( !SDL_strcasecmp( pchString, "rightshoulder" ) )
  16.309 +		return SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
  16.310 +	else if ( !SDL_strcasecmp( pchString, "leftstick" ) )
  16.311 +		return SDL_CONTROLLER_BUTTON_LEFTSTICK;
  16.312 +	else if ( !SDL_strcasecmp( pchString, "rightstick" ) )
  16.313 +		return SDL_CONTROLLER_BUTTON_RIGHTSTICK;
  16.314 +	else
  16.315 +		return SDL_CONTROLLER_BUTTON_INVALID;
  16.316 +}
  16.317 +
  16.318 +
  16.319 +/*
  16.320 + * given a controller button name and a joystick name update our mapping structure with it
  16.321 + */
  16.322 +void SDL_PrivateGameControllerParseButton( const char *szGameButton, const char *szJoystickButton, struct _SDL_ControllerMapping *pMapping )
  16.323 +{
  16.324 +	int iSDLButton = 0;
  16.325 +	SDL_CONTROLLER_BUTTON button;
  16.326 +	SDL_CONTROLLER_AXIS axis;
  16.327 +	button = SDL_GameControllerGetButtonFromString( szGameButton );
  16.328 +	axis = SDL_GameControllerGetAxisFromString( szGameButton );
  16.329 +	iSDLButton = SDL_atoi( &szJoystickButton[1] );
  16.330 +
  16.331 +	if ( iSDLButton >= k_nMaxReverseEntries )
  16.332 +	{
  16.333 +		SDL_SetError("Button index too large: %d", iSDLButton );
  16.334 +		return;
  16.335 +	}
  16.336 +
  16.337 +	if ( szJoystickButton[0] == 'a' )
  16.338 +	{
  16.339 +		if ( axis != SDL_CONTROLLER_AXIS_INVALID )
  16.340 +		{
  16.341 +			pMapping->axes[ axis ] = iSDLButton;
  16.342 +			pMapping->raxes[ iSDLButton ] = axis;
  16.343 +		}
  16.344 +		else if ( button != SDL_CONTROLLER_BUTTON_INVALID )
  16.345 +		{
  16.346 +			pMapping->buttonasaxis[ button ] = iSDLButton;
  16.347 +			pMapping->rbuttonasaxis[ iSDLButton ] = button;
  16.348 +		}
  16.349 +		else
  16.350 +		{
  16.351 +			SDL_assert( !"How did we get here?" );
  16.352 +		}
  16.353 +
  16.354 +	}
  16.355 +	else if ( szJoystickButton[0] == 'b' )
  16.356 +	{
  16.357 +		if ( button != SDL_CONTROLLER_BUTTON_INVALID )
  16.358 +		{
  16.359 +			pMapping->buttons[ button ] = iSDLButton;
  16.360 +			pMapping->rbuttons[ iSDLButton ] = button;
  16.361 +		}
  16.362 +		else if ( axis != SDL_CONTROLLER_AXIS_INVALID )
  16.363 +		{
  16.364 +			pMapping->buttonasaxis[ axis ] = iSDLButton;
  16.365 +			pMapping->rbuttonasaxis[ iSDLButton ] = axis;
  16.366 +		}
  16.367 +		else
  16.368 +		{
  16.369 +			SDL_assert( !"How did we get here?" );
  16.370 +		}
  16.371 +	}
  16.372 +	else if ( szJoystickButton[0] == 'h' )
  16.373 +	{
  16.374 +		int hat = SDL_atoi( &szJoystickButton[1] );
  16.375 +		int mask = SDL_atoi( &szJoystickButton[3] );
  16.376 +
  16.377 +		if ( button != SDL_CONTROLLER_BUTTON_INVALID )
  16.378 +		{
  16.379 +			pMapping->hatasbutton[ button ].hat = hat;
  16.380 +			pMapping->hatasbutton[ button ].mask = mask;
  16.381 +			pMapping->rhatasbutton[ mask ].hat = button;
  16.382 +			pMapping->rhatasbutton[ mask ].mask = mask;
  16.383 +		}
  16.384 +		else if ( axis != SDL_CONTROLLER_AXIS_INVALID )
  16.385 +		{
  16.386 +			SDL_assert( !"Support hat as axis" );
  16.387 +		}
  16.388 +		else
  16.389 +		{
  16.390 +			SDL_assert( !"How did we get here?" );
  16.391 +		}
  16.392 +	}
  16.393 +
  16.394 +}
  16.395 +
  16.396 +
  16.397 +/*
  16.398 + * given a controller mapping string update our mapping object
  16.399 + */
  16.400 +static void
  16.401 +SDL_PrivateGameControllerParseControllerConfigString( struct _SDL_ControllerMapping *pMapping, const char *pchString )
  16.402 +{
  16.403 +	char szGameButton[20];
  16.404 +	char szJoystickButton[20];
  16.405 +	SDL_bool bGameButton = SDL_TRUE;
  16.406 +	int i = 0;
  16.407 +	const char *pchPos = pchString;
  16.408 +
  16.409 +	SDL_memset( szGameButton, 0x0, sizeof(szGameButton) );
  16.410 +	SDL_memset( szJoystickButton, 0x0, sizeof(szJoystickButton) );
  16.411 +
  16.412 +	while ( pchPos && *pchPos )
  16.413 +	{
  16.414 +		if ( *pchPos == ':' )
  16.415 +		{
  16.416 +			i = 0;
  16.417 +			bGameButton = SDL_FALSE;
  16.418 +		}
  16.419 +		else if ( *pchPos == ' ' )
  16.420 +		{
  16.421 +
  16.422 +		}
  16.423 +		else if ( *pchPos == ',' )
  16.424 +		{
  16.425 +			i = 0;
  16.426 +			bGameButton = SDL_TRUE;
  16.427 +			SDL_PrivateGameControllerParseButton( szGameButton, szJoystickButton, pMapping );
  16.428 +			SDL_memset( szGameButton, 0x0, sizeof(szGameButton) );
  16.429 +			SDL_memset( szJoystickButton, 0x0, sizeof(szJoystickButton) );
  16.430 +
  16.431 +		}
  16.432 +		else if ( bGameButton )
  16.433 +		{
  16.434 +			if ( i >=  sizeof(szGameButton))
  16.435 +			{
  16.436 +				SDL_SetError( "Button name too large: %s", szGameButton );
  16.437 +				return;
  16.438 +			}
  16.439 +			szGameButton[i] = *pchPos;
  16.440 +			i++;
  16.441 +		}
  16.442 +		else
  16.443 +		{
  16.444 +			if ( i >=  sizeof(szJoystickButton))
  16.445 +			{
  16.446 +				SDL_SetError( "Joystick button name too large: %s", szJoystickButton );
  16.447 +				return;
  16.448 +			}
  16.449 +			szJoystickButton[i] = *pchPos;
  16.450 +			i++;
  16.451 +		}
  16.452 +		pchPos++;
  16.453 +	}
  16.454 +
  16.455 +	SDL_PrivateGameControllerParseButton( szGameButton, szJoystickButton, pMapping );
  16.456 +
  16.457 +}
  16.458 +
  16.459 +/*
  16.460 + * Make a new button mapping struct
  16.461 + */
  16.462 +void SDL_PrivateLoadButtonMapping( struct _SDL_ControllerMapping *pMapping, JoystickGUID guid, const char *pchName, const char *pchMapping )
  16.463 +{
  16.464 +	int j;
  16.465 +
  16.466 +	pMapping->guid = guid;
  16.467 +	pMapping->name = pchName;
  16.468 +
  16.469 +	// set all the button mappings to non defaults
  16.470 +	for ( j = 0; j < SDL_CONTROLLER_AXIS_MAX; j++ )
  16.471 +	{
  16.472 +		pMapping->axes[j] = -1;
  16.473 +		pMapping->buttonasaxis[j] = -1;
  16.474 +	}
  16.475 +	for ( j = 0; j < SDL_CONTROLLER_BUTTON_MAX; j++ )
  16.476 +	{
  16.477 +		pMapping->buttons[j] = -1;
  16.478 +		pMapping->axesasbutton[j] = -1;
  16.479 +		pMapping->hatasbutton[j].hat = -1;
  16.480 +	}
  16.481 +
  16.482 +	for ( j = 0; j < k_nMaxReverseEntries; j++ )
  16.483 +	{
  16.484 +		pMapping->raxes[j] = SDL_CONTROLLER_AXIS_INVALID;
  16.485 +		pMapping->rbuttons[j] = SDL_CONTROLLER_BUTTON_INVALID;
  16.486 +		pMapping->raxesasbutton[j] = SDL_CONTROLLER_BUTTON_INVALID;
  16.487 +		pMapping->rhatasbutton[j].hat = -1;
  16.488 +		pMapping->rbuttonasaxis[j] = SDL_CONTROLLER_AXIS_INVALID;
  16.489 +	}
  16.490 +
  16.491 +	SDL_PrivateGameControllerParseControllerConfigString( pMapping, pchMapping );
  16.492 +}
  16.493 +
  16.494 +
  16.495 +/*
  16.496 + * grab the guid string from a mapping string
  16.497 + */
  16.498 +char *SDL_PrivateGetControllerGUIDFromMappingString( const char *pMapping )
  16.499 +{
  16.500 +	const char *pFirstComma = SDL_strchr( pMapping, ',' );
  16.501 +	if ( pFirstComma )
  16.502 +	{
  16.503 +		char *pchGUID = SDL_malloc( pFirstComma - pMapping + 1 );
  16.504 +		if ( !pchGUID )
  16.505 +		{
  16.506 +			SDL_OutOfMemory();
  16.507 +			return NULL;
  16.508 +		}
  16.509 +		SDL_memcpy( pchGUID, pMapping, pFirstComma - pMapping );
  16.510 +		pchGUID[ pFirstComma - pMapping ] = 0;
  16.511 +		return pchGUID;
  16.512 +	}
  16.513 +	return NULL;
  16.514 +}
  16.515 +
  16.516 +
  16.517 +/*
  16.518 + * grab the name string from a mapping string
  16.519 + */
  16.520 +char *SDL_PrivateGetControllerNameFromMappingString( const char *pMapping )
  16.521 +{
  16.522 +	const char *pFirstComma = SDL_strchr( pMapping, ',' );
  16.523 +	const char *pSecondComma = SDL_strchr( pFirstComma + 1, ',' );
  16.524 +	if ( pFirstComma && pSecondComma )
  16.525 +	{
  16.526 +		char *pchName = SDL_malloc( pSecondComma - pFirstComma );
  16.527 +		if ( !pchName )
  16.528 +		{
  16.529 +			SDL_OutOfMemory();
  16.530 +			return NULL;
  16.531 +		}
  16.532 +		SDL_memcpy( pchName, pFirstComma + 1, pSecondComma - pFirstComma );
  16.533 +		pchName[ pSecondComma - pFirstComma - 1 ] = 0;
  16.534 +		return pchName;
  16.535 +	}
  16.536 +	return NULL;
  16.537 +}
  16.538 +
  16.539 +
  16.540 +/*
  16.541 + * grab the button mapping string from a mapping string
  16.542 + */
  16.543 +const char *SDL_PrivateGetControllerMappingFromMappingString( const char *pMapping )
  16.544 +{
  16.545 +	const char *pFirstComma = SDL_strchr( pMapping, ',' );
  16.546 +	const char *pSecondComma = SDL_strchr( pFirstComma + 1, ',' );
  16.547 +	if ( pSecondComma )
  16.548 +		return pSecondComma + 1; // mapping is everything after the 3rd comma, no need to malloc it
  16.549 +	else
  16.550 +		return NULL;
  16.551 +}
  16.552 +
  16.553 +
  16.554 +/*
  16.555 + * Initialize the game controller system, mostly load our DB of controller config mappings
  16.556 + */
  16.557 +int
  16.558 +SDL_GameControllerInit(void)
  16.559 +{
  16.560 +	int i = 0;
  16.561 +	const char *pMappingString = NULL;
  16.562 +	s_pSupportedControllers = NULL;
  16.563 +	pMappingString = s_ControllerMappings[i];
  16.564 +	while ( pMappingString )
  16.565 +	{
  16.566 +		ControllerMapping_t *pControllerMapping;
  16.567 +		char *pchGUID;
  16.568 +		char *pchName;
  16.569 +		const char *pchMapping;
  16.570 +		pControllerMapping = SDL_malloc( sizeof(*pControllerMapping) );
  16.571 +		if ( !pControllerMapping )
  16.572 +		{
  16.573 +			SDL_OutOfMemory();
  16.574 +			return -1;
  16.575 +		}
  16.576 +
  16.577 +		pchGUID = SDL_PrivateGetControllerGUIDFromMappingString( pMappingString );
  16.578 +		pchName = SDL_PrivateGetControllerNameFromMappingString( pMappingString );
  16.579 +		pchMapping = SDL_PrivateGetControllerMappingFromMappingString( pMappingString );
  16.580 +		if ( pchGUID && pchName )
  16.581 +		{
  16.582 +#ifdef __WIN32__
  16.583 +			if ( !SDL_strcasecmp( pchGUID, "xinput" ) )
  16.584 +			{
  16.585 +				s_pXInputMapping = pControllerMapping;
  16.586 +			}
  16.587 +#endif
  16.588 +			pControllerMapping->guid = SDL_JoystickGetGUIDFromString( pchGUID );
  16.589 +			pControllerMapping->name = pchName;
  16.590 +			pControllerMapping->mapping = pchMapping;
  16.591 +			pControllerMapping->next = s_pSupportedControllers;
  16.592 +			s_pSupportedControllers = pControllerMapping;
  16.593 +
  16.594 +			SDL_free( pchGUID );
  16.595 +		}
  16.596 +
  16.597 +		i++;
  16.598 +		pMappingString = s_ControllerMappings[i];
  16.599 +	}
  16.600 +
  16.601 +	// load in any user supplied config
  16.602 +	{
  16.603 +		const char *hint = SDL_GetHint(SDL_HINT_GAMECONTROLLERCONFIG);
  16.604 +		if ( hint && hint[0] )
  16.605 +		{
  16.606 +			int nchHints = SDL_strlen( hint );
  16.607 +			char *pUserMappings = SDL_malloc( nchHints + 1 );
  16.608 +			SDL_memcpy( pUserMappings, hint, nchHints );
  16.609 +			while ( pUserMappings )
  16.610 +			{
  16.611 +				char *pchGUID;
  16.612 +				char *pchName;
  16.613 +				const char *pchMapping;
  16.614 +				char *pchNewLine = NULL;
  16.615 +				ControllerMapping_t *pControllerMapping;
  16.616 +
  16.617 +				pchNewLine = SDL_strchr( pUserMappings, '\n' );
  16.618 +				if ( pchNewLine )
  16.619 +					*pchNewLine = '\0';
  16.620 +
  16.621 +				pControllerMapping = SDL_malloc( sizeof(*pControllerMapping) );
  16.622 +				if ( !pControllerMapping )
  16.623 +				{
  16.624 +					SDL_OutOfMemory();
  16.625 +					return -1;
  16.626 +				}
  16.627 +
  16.628 +				pchGUID = SDL_PrivateGetControllerGUIDFromMappingString( pUserMappings );
  16.629 +				pchName = SDL_PrivateGetControllerNameFromMappingString( pUserMappings );
  16.630 +				pchMapping = SDL_PrivateGetControllerMappingFromMappingString( pUserMappings );
  16.631 +
  16.632 +				if ( pchGUID && pchName )
  16.633 +				{
  16.634 +#ifdef __WIN32__
  16.635 +					if ( !SDL_strcasecmp( pchGUID, "xinput" ) )
  16.636 +					{
  16.637 +						s_pXInputMapping = pControllerMapping;
  16.638 +					}
  16.639 +#endif
  16.640 +
  16.641 +					pControllerMapping->guid = SDL_JoystickGetGUIDFromString( pchGUID );
  16.642 +					pControllerMapping->name = pchName;
  16.643 +					pControllerMapping->mapping = pchMapping;
  16.644 +					pControllerMapping->next = s_pSupportedControllers;
  16.645 +					s_pSupportedControllers = pControllerMapping;
  16.646 +
  16.647 +					SDL_free( pchGUID );
  16.648 +				}
  16.649 +
  16.650 +				if ( pchNewLine )
  16.651 +					pUserMappings = pchNewLine + 1;
  16.652 +				else
  16.653 +					pUserMappings = NULL;
  16.654 +			}
  16.655 +		}
  16.656 +	}
  16.657 +
  16.658 +	/* watch for joy events and fire controller ones if needed */
  16.659 +	SDL_AddEventWatch( SDL_GameControllerEventWatcher, NULL );
  16.660 +	return (0);
  16.661 +}
  16.662 +
  16.663 +
  16.664 +/*
  16.665 + * Get the implementation dependent name of a controller
  16.666 + */
  16.667 +const char *
  16.668 +SDL_GameControllerNameForIndex(int device_index)
  16.669 +{
  16.670 +	ControllerMapping_t *pSupportedController =  SDL_PrivateGetControllerMapping(device_index);
  16.671 +	if ( pSupportedController )
  16.672 +	{
  16.673 +		return pSupportedController->name;
  16.674 +	}
  16.675 +	else
  16.676 +	{
  16.677 +		JoystickGUID jGUID = SDL_JoystickGetDeviceGUID( device_index );
  16.678 +		pSupportedController = s_pSupportedControllers;
  16.679 +		while ( pSupportedController )
  16.680 +		{
  16.681 +			if ( !SDL_memcmp( &jGUID, &pSupportedController->guid, sizeof(jGUID) ) )
  16.682 +			{
  16.683 +				return pSupportedController->name;
  16.684 +			}
  16.685 +			pSupportedController = pSupportedController->next;
  16.686 +		}
  16.687 +	}
  16.688 +    return NULL;
  16.689 +}
  16.690 +
  16.691 +
  16.692 +/*
  16.693 + * Return 1 if the joystick at this device index is a supported controller
  16.694 + */
  16.695 +int SDL_IsGameController(int device_index)
  16.696 +{
  16.697 +	ControllerMapping_t *pSupportedController =  SDL_PrivateGetControllerMapping(device_index);
  16.698 +	if ( pSupportedController )
  16.699 +	{
  16.700 +		return 1;
  16.701 +	}
  16.702 +	else
  16.703 +	{
  16.704 +		JoystickGUID jGUID = SDL_JoystickGetDeviceGUID( device_index );
  16.705 +		pSupportedController = s_pSupportedControllers;
  16.706 +		// debug code to help get the guid string for a new joystick
  16.707 +		/*const char *pchGUID = SDL_JoystickGetGUIDString( jGUID );
  16.708 +		printf( "%s\n", pchGUID );
  16.709 +		SDL_free( pchGUID );*/
  16.710 +		while ( pSupportedController )
  16.711 +		{
  16.712 +			if ( !SDL_memcmp( &jGUID, &pSupportedController->guid, sizeof(jGUID) ) )
  16.713 +			{
  16.714 +				return 1;
  16.715 +			}
  16.716 +			pSupportedController = pSupportedController->next;
  16.717 +		}
  16.718 +	}
  16.719 +	return 0;
  16.720 +}
  16.721 +
  16.722 +/*
  16.723 + * Open a controller for use - the index passed as an argument refers to
  16.724 + * the N'th controller on the system.  This index is the value which will
  16.725 + * identify this controller in future controller events.
  16.726 + *
  16.727 + * This function returns a controller identifier, or NULL if an error occurred.
  16.728 + */
  16.729 +SDL_GameController *
  16.730 +SDL_GameControllerOpen(int device_index)
  16.731 +{
  16.732 +    SDL_GameController *gamecontroller;
  16.733 +	SDL_GameController *gamecontrollerlist;
  16.734 +	ControllerMapping_t *pSupportedController = NULL;
  16.735 +
  16.736 +	int deviceMappingIndex = -1;
  16.737 +
  16.738 +    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
  16.739 +        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
  16.740 +        return (NULL);
  16.741 +    }
  16.742 +
  16.743 +	gamecontrollerlist = SDL_gamecontrollers;
  16.744 +    // If the controller is already open, return it 
  16.745 +	while ( gamecontrollerlist )
  16.746 +	{
  16.747 +		if ( SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == gamecontrollerlist->joystick->instance_id ) {
  16.748 +				gamecontroller = gamecontrollerlist;
  16.749 +				++gamecontroller->ref_count;
  16.750 +				return (gamecontroller);
  16.751 +		}
  16.752 +		gamecontrollerlist = gamecontrollerlist->next;
  16.753 +    }
  16.754 +
  16.755 +    // Create and initialize the joystick 
  16.756 +    gamecontroller = (SDL_GameController *) SDL_malloc((sizeof *gamecontroller));
  16.757 +    if (gamecontroller == NULL) {
  16.758 +        SDL_OutOfMemory();
  16.759 +        return NULL;
  16.760 +    }
  16.761 +
  16.762 +	pSupportedController =  SDL_PrivateGetControllerMapping(device_index);
  16.763 +	if ( !pSupportedController )
  16.764 +	{
  16.765 +		JoystickGUID jGUID;
  16.766 +
  16.767 +		jGUID = SDL_JoystickGetDeviceGUID( device_index );
  16.768 +		pSupportedController = s_pSupportedControllers;
  16.769 +		while ( pSupportedController )
  16.770 +		{
  16.771 +			if ( !SDL_memcmp( &jGUID, &pSupportedController->guid, sizeof(jGUID) ) )
  16.772 +			{
  16.773 +				break;
  16.774 +			}
  16.775 +
  16.776 +			pSupportedController = pSupportedController->next;
  16.777 +		}
  16.778 +	}
  16.779 +
  16.780 +	if ( !pSupportedController )
  16.781 +	{
  16.782 +		SDL_SetError("Couldn't find mapping for device (%d)", device_index );
  16.783 +		return (NULL);
  16.784 +	}
  16.785 +
  16.786 +    SDL_memset(gamecontroller, 0, (sizeof *gamecontroller));
  16.787 +    gamecontroller->joystick = SDL_JoystickOpen(device_index);
  16.788 +	if ( !gamecontroller->joystick ) {
  16.789 +        SDL_free(gamecontroller);
  16.790 +        return NULL;
  16.791 +    }
  16.792 +
  16.793 +	SDL_PrivateLoadButtonMapping( &gamecontroller->mapping, pSupportedController->guid, pSupportedController->name, pSupportedController->mapping );
  16.794 +
  16.795 +    // Add joystick to list 
  16.796 +    ++gamecontroller->ref_count;
  16.797 +	// Link the joystick in the list 
  16.798 +	gamecontroller->next = SDL_gamecontrollers;
  16.799 +	SDL_gamecontrollers = gamecontroller;
  16.800 +
  16.801 +	SDL_SYS_JoystickUpdate( gamecontroller->joystick );
  16.802 +
  16.803 +    return (gamecontroller);
  16.804 +}
  16.805 +
  16.806 +
  16.807 +/*
  16.808 + * Get the current state of an axis control on a controller
  16.809 + */
  16.810 +Sint16
  16.811 +SDL_GameControllerGetAxis(SDL_GameController * gamecontroller, SDL_CONTROLLER_AXIS axis)
  16.812 +{
  16.813 +	if ( !gamecontroller )
  16.814 +		return 0;
  16.815 +
  16.816 +	if (gamecontroller->mapping.axes[axis] >= 0 )
  16.817 +	{
  16.818 +		return ( SDL_JoystickGetAxis( gamecontroller->joystick, gamecontroller->mapping.axes[axis]) );
  16.819 +	}
  16.820 +	else if (gamecontroller->mapping.buttonasaxis[axis] >= 0 )
  16.821 +	{
  16.822 +		Uint8 value;
  16.823 +		value = SDL_JoystickGetButton( gamecontroller->joystick, gamecontroller->mapping.buttonasaxis[axis] );
  16.824 +		if ( value > 0 )
  16.825 +			return 32767;
  16.826 +		return 0;
  16.827 +	}
  16.828 +	return 0;
  16.829 +}
  16.830 +
  16.831 +
  16.832 +/*
  16.833 + * Get the current state of a button on a controller
  16.834 + */
  16.835 +Uint8
  16.836 +SDL_GameControllerGetButton(SDL_GameController * gamecontroller, SDL_CONTROLLER_BUTTON button)
  16.837 +{
  16.838 +	if ( !gamecontroller )
  16.839 +		return 0;
  16.840 +
  16.841 +	if ( gamecontroller->mapping.buttons[button] >= 0 )
  16.842 +	{
  16.843 +		return ( SDL_JoystickGetButton( gamecontroller->joystick, gamecontroller->mapping.buttons[button] ) );
  16.844 +	}
  16.845 +	else if ( gamecontroller->mapping.axesasbutton[button] >= 0 )
  16.846 +	{
  16.847 +		Sint16 value;
  16.848 +		value = SDL_JoystickGetAxis( gamecontroller->joystick, gamecontroller->mapping.axesasbutton[button] );
  16.849 +		if ( ABS(value) > 32768/2 )
  16.850 +			return 1;
  16.851 +		return 0;
  16.852 +	}
  16.853 +	else if ( gamecontroller->mapping.hatasbutton[button].hat >= 0 )
  16.854 +	{
  16.855 +		Uint8 value;
  16.856 +		value = SDL_JoystickGetHat( gamecontroller->joystick, gamecontroller->mapping.hatasbutton[button].hat );
  16.857 +		
  16.858 +		if ( value & gamecontroller->mapping.hatasbutton[button].mask )
  16.859 +			return 1;
  16.860 +		return 0;
  16.861 +	}
  16.862 +
  16.863 +	return 0;
  16.864 +}
  16.865 +
  16.866 +/*
  16.867 + * Return if the joystick in question is currently attached to the system,
  16.868 + *  \return 0 if not plugged in, 1 if still present.
  16.869 + */
  16.870 +int
  16.871 +SDL_GameControllerGetAttached( SDL_GameController * gamecontroller )
  16.872 +{
  16.873 +	if ( !gamecontroller )
  16.874 +		return 0;
  16.875 +
  16.876 +	return SDL_JoystickGetAttached(gamecontroller->joystick);
  16.877 +}
  16.878 +
  16.879 +
  16.880 +/*
  16.881 + * Get the number of multi-dimensional axis controls on a joystick
  16.882 + */
  16.883 +const char *
  16.884 +SDL_GameControllerName(SDL_GameController * gamecontroller)
  16.885 +{
  16.886 +	if ( !gamecontroller )
  16.887 +		return NULL;
  16.888 +
  16.889 +    return (gamecontroller->mapping.name);
  16.890 +}
  16.891 +
  16.892 +
  16.893 +/*
  16.894 + * Get the joystick for this controller
  16.895 + */
  16.896 +SDL_Joystick *SDL_GameControllerGetJoystick(SDL_GameController * gamecontroller)
  16.897 +{
  16.898 +	if ( !gamecontroller )
  16.899 +		return NULL;
  16.900 +
  16.901 +	return gamecontroller->joystick;
  16.902 +}
  16.903 +
  16.904 +/**
  16.905 + *  get the sdl joystick layer binding for this controller axi mapping
  16.906 + */
  16.907 +SDL_GameControllerButtonBind SDL_GameControllerGetBindForAxis( SDL_GameController * gamecontroller, SDL_CONTROLLER_AXIS axis )
  16.908 +{
  16.909 +	SDL_GameControllerButtonBind bind;
  16.910 +	SDL_memset( &bind, 0x0, sizeof(bind) );
  16.911 +
  16.912 +	if ( !gamecontroller || axis == SDL_CONTROLLER_AXIS_INVALID )
  16.913 +		return bind;
  16.914 +
  16.915 +	if (gamecontroller->mapping.axes[axis] >= 0 )
  16.916 +	{
  16.917 +		bind.m_eBindType = SDL_CONTROLLER_BINDTYPE_AXIS;
  16.918 +		bind.button = gamecontroller->mapping.axes[axis];
  16.919 +	}
  16.920 +	else if (gamecontroller->mapping.buttonasaxis[axis] >= 0 )
  16.921 +	{
  16.922 +		bind.m_eBindType = SDL_CONTROLLER_BINDTYPE_BUTTON;
  16.923 +		bind.button = gamecontroller->mapping.buttonasaxis[axis];
  16.924 +	}
  16.925 +
  16.926 +	return bind;
  16.927 +}
  16.928 +
  16.929 +
  16.930 +/**
  16.931 + *  get the sdl joystick layer binding for this controller button mapping
  16.932 + */
  16.933 +SDL_GameControllerButtonBind SDL_GameControllerGetBindForButton( SDL_GameController * gamecontroller, SDL_CONTROLLER_BUTTON button )
  16.934 +{
  16.935 +	SDL_GameControllerButtonBind bind;
  16.936 +	SDL_memset( &bind, 0x0, sizeof(bind) );
  16.937 +
  16.938 +	if ( !gamecontroller || button == SDL_CONTROLLER_BUTTON_INVALID )
  16.939 +		return bind;
  16.940 +
  16.941 +	if ( gamecontroller->mapping.buttons[button] >= 0 )
  16.942 +	{
  16.943 +		bind.m_eBindType = SDL_CONTROLLER_BINDTYPE_BUTTON;
  16.944 +		bind.button = gamecontroller->mapping.buttons[button];
  16.945 +	}
  16.946 +	else if ( gamecontroller->mapping.axesasbutton[button] >= 0 )
  16.947 +	{
  16.948 +		bind.m_eBindType = SDL_CONTROLLER_BINDTYPE_AXIS;
  16.949 +		bind.axis = gamecontroller->mapping.axesasbutton[button];
  16.950 +	}
  16.951 +	else if ( gamecontroller->mapping.hatasbutton[button].hat >= 0 )
  16.952 +	{
  16.953 +		bind.m_eBindType = SDL_CONTROLLER_BINDTYPE_HAT;
  16.954 +		bind.hat.hat = gamecontroller->mapping.hatasbutton[button].hat;
  16.955 +		bind.hat.hat_mask = gamecontroller->mapping.hatasbutton[button].mask;
  16.956 +	}
  16.957 +
  16.958 +	return bind;
  16.959 +}
  16.960 +
  16.961 +
  16.962 +/*
  16.963 + * Close a joystick previously opened with SDL_JoystickOpen()
  16.964 + */
  16.965 +void
  16.966 +SDL_GameControllerClose(SDL_GameController * gamecontroller)
  16.967 +{
  16.968 +	SDL_GameController *gamecontrollerlist, *gamecontrollerlistprev;
  16.969 +
  16.970 +	if ( !gamecontroller )
  16.971 +		return;
  16.972 +
  16.973 +	// First decrement ref count 
  16.974 +    if (--gamecontroller->ref_count > 0) {
  16.975 +        return;
  16.976 +    }
  16.977 +
  16.978 +	SDL_JoystickClose( gamecontroller->joystick );
  16.979 +	
  16.980 +	gamecontrollerlist = SDL_gamecontrollers;
  16.981 +	gamecontrollerlistprev = NULL;
  16.982 +	while ( gamecontrollerlist )
  16.983 +	{
  16.984 +		if (gamecontroller == gamecontrollerlist) 
  16.985 +		{
  16.986 +			if ( gamecontrollerlistprev )
  16.987 +			{
  16.988 +				// unlink this entry
  16.989 +				gamecontrollerlistprev->next = gamecontrollerlist->next;
  16.990 +			}
  16.991 +			else
  16.992 +			{
  16.993 +				SDL_gamecontrollers = gamecontroller->next;
  16.994 +			}
  16.995 +
  16.996 +			break;
  16.997 +		}
  16.998 +		gamecontrollerlistprev = gamecontrollerlist;
  16.999 +		gamecontrollerlist = gamecontrollerlist->next;
 16.1000 +	}
 16.1001 + 
 16.1002 +    SDL_free(gamecontroller);
 16.1003 +}
 16.1004 +
 16.1005 +
 16.1006 +/*
 16.1007 + * Quit the controller subsystem
 16.1008 + */
 16.1009 +void
 16.1010 +SDL_GameControllerQuit(void)
 16.1011 +{
 16.1012 +	ControllerMapping_t *pControllerMap;
 16.1013 +	while ( SDL_gamecontrollers )
 16.1014 +	{
 16.1015 +		SDL_gamecontrollers->ref_count = 1;
 16.1016 +        SDL_GameControllerClose(SDL_gamecontrollers);
 16.1017 + 	}
 16.1018 +
 16.1019 +	pControllerMap = s_pSupportedControllers;
 16.1020 +	while ( s_pSupportedControllers )
 16.1021 +	{
 16.1022 +		pControllerMap = s_pSupportedControllers;
 16.1023 +		s_pSupportedControllers = s_pSupportedControllers->next;
 16.1024 +		SDL_free( pControllerMap->name );
 16.1025 +		SDL_free( pControllerMap );
 16.1026 +	}
 16.1027 +
 16.1028 +	SDL_DelEventWatch( SDL_GameControllerEventWatcher, NULL );
 16.1029 +
 16.1030 +}
 16.1031 +
 16.1032 +/*
 16.1033 + * Event filter to transform joystick events into appropriate game controller ones
 16.1034 + */
 16.1035 +int
 16.1036 +SDL_PrivateGameControllerAxis(SDL_GameController * gamecontroller, SDL_CONTROLLER_AXIS axis, Sint16 value)
 16.1037 +{
 16.1038 +	int posted;
 16.1039 +
 16.1040 +    /* translate the event, if desired */
 16.1041 +    posted = 0;
 16.1042 +#if !SDL_EVENTS_DISABLED
 16.1043 +    if (SDL_GetEventState(SDL_CONTROLLERAXISMOTION) == SDL_ENABLE) {
 16.1044 +        SDL_Event event;
 16.1045 +        event.type = SDL_CONTROLLERAXISMOTION;
 16.1046 +        event.caxis.which = gamecontroller->joystick->instance_id;
 16.1047 +        event.caxis.axis = axis;
 16.1048 +        event.caxis.value = value;
 16.1049 +		posted = SDL_PushEvent(&event) == 1;
 16.1050 +    }
 16.1051 +#endif /* !SDL_EVENTS_DISABLED */
 16.1052 +    return (posted);
 16.1053 +}
 16.1054 +
 16.1055 +
 16.1056 +/*
 16.1057 + * Event filter to transform joystick events into appropriate game controller ones
 16.1058 + */
 16.1059 +int
 16.1060 +SDL_PrivateGameControllerButton(SDL_GameController * gamecontroller, SDL_CONTROLLER_BUTTON button, Uint8 state)
 16.1061 +{
 16.1062 +    int posted;
 16.1063 +#if !SDL_EVENTS_DISABLED
 16.1064 +	SDL_Event event;
 16.1065 +
 16.1066 +    switch (state) {
 16.1067 +    case SDL_PRESSED:
 16.1068 +        event.type = SDL_CONTROLLERBUTTONDOWN;
 16.1069 +        break;
 16.1070 +    case SDL_RELEASED:
 16.1071 +        event.type = SDL_CONTROLLERBUTTONUP;
 16.1072 +        break;
 16.1073 +    default:
 16.1074 +        /* Invalid state -- bail */
 16.1075 +        return (0);
 16.1076 +    }
 16.1077 +#endif /* !SDL_EVENTS_DISABLED */
 16.1078 +
 16.1079 +    /* translate the event, if desired */
 16.1080 +    posted = 0;
 16.1081 +#if !SDL_EVENTS_DISABLED
 16.1082 +    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
 16.1083 +        event.cbutton.which = gamecontroller->joystick->instance_id;
 16.1084 +        event.cbutton.button = button;
 16.1085 +        event.cbutton.state = state;
 16.1086 +		posted = SDL_PushEvent(&event) == 1;
 16.1087 +    }
 16.1088 +#endif /* !SDL_EVENTS_DISABLED */
 16.1089 +    return (posted);
 16.1090 +}
 16.1091 +
 16.1092 +/*
 16.1093 + * Turn off controller events
 16.1094 + */
 16.1095 +int
 16.1096 +SDL_GameControllerEventState(int state)
 16.1097 +{
 16.1098 +#if SDL_EVENTS_DISABLED
 16.1099 +    return SDL_IGNORE;
 16.1100 +#else
 16.1101 +    const Uint32 event_list[] = {
 16.1102 +        SDL_CONTROLLERAXISMOTION, SDL_CONTROLLERBUTTONDOWN, SDL_CONTROLLERBUTTONUP,
 16.1103 +        SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMOVED,
 16.1104 +    };
 16.1105 +    unsigned int i;
 16.1106 +
 16.1107 +    switch (state) {
 16.1108 +    case SDL_QUERY:
 16.1109 +        state = SDL_IGNORE;
 16.1110 +        for (i = 0; i < SDL_arraysize(event_list); ++i) {
 16.1111 +            state = SDL_EventState(event_list[i], SDL_QUERY);
 16.1112 +            if (state == SDL_ENABLE) {
 16.1113 +                break;
 16.1114 +            }
 16.1115 +        }
 16.1116 +        break;
 16.1117 +    default:
 16.1118 +        for (i = 0; i < SDL_arraysize(event_list); ++i) {
 16.1119 +            SDL_EventState(event_list[i], state);
 16.1120 +        }
 16.1121 +        break;
 16.1122 +    }
 16.1123 +    return (state);
 16.1124 +#endif /* SDL_EVENTS_DISABLED */
 16.1125 +}
 16.1126 +
 16.1127 +
 16.1128 +/* vi: set ts=4 sw=4 expandtab: */
    17.1 --- a/src/joystick/SDL_joystick.c	Mon Nov 26 14:59:07 2012 -0800
    17.2 +++ b/src/joystick/SDL_joystick.c	Mon Nov 26 16:37:54 2012 -0800
    17.3 @@ -24,34 +24,22 @@
    17.4  
    17.5  #include "SDL_events.h"
    17.6  #include "SDL_sysjoystick.h"
    17.7 -#include "SDL_joystick_c.h"
    17.8  #include "SDL_assert.h"
    17.9  
   17.10  #if !SDL_EVENTS_DISABLED
   17.11  #include "../events/SDL_events_c.h"
   17.12  #endif
   17.13  
   17.14 -Uint8 SDL_numjoysticks = 0;
   17.15 -SDL_Joystick **SDL_joysticks = NULL;
   17.16 +SDL_Joystick *SDL_joysticks = NULL;
   17.17  
   17.18  int
   17.19  SDL_JoystickInit(void)
   17.20  {
   17.21 -    int arraylen;
   17.22      int status;
   17.23  
   17.24 -    SDL_numjoysticks = 0;
   17.25      status = SDL_SYS_JoystickInit();
   17.26      if (status >= 0) {
   17.27 -        arraylen = (status + 1) * sizeof(*SDL_joysticks);
   17.28 -        SDL_joysticks = (SDL_Joystick **) SDL_malloc(arraylen);
   17.29 -        if (SDL_joysticks == NULL) {
   17.30 -            SDL_numjoysticks = 0;
   17.31 -        } else {
   17.32 -            SDL_memset(SDL_joysticks, 0, arraylen);
   17.33 -            SDL_numjoysticks = status;
   17.34 -        }
   17.35 -        status = 0;
   17.36 +      status = 0;
   17.37      }
   17.38      return (status);
   17.39  }
   17.40 @@ -62,20 +50,20 @@
   17.41  int
   17.42  SDL_NumJoysticks(void)
   17.43  {
   17.44 -    return SDL_numjoysticks;
   17.45 +    return SDL_SYS_NumJoysticks();
   17.46  }
   17.47  
   17.48  /*
   17.49   * Get the implementation dependent name of a joystick
   17.50   */
   17.51  const char *
   17.52 -SDL_JoystickName(int device_index)
   17.53 +SDL_JoystickNameForIndex(int device_index)
   17.54  {
   17.55 -    if ((device_index < 0) || (device_index >= SDL_numjoysticks)) {
   17.56 -        SDL_SetError("There are %d joysticks available", SDL_numjoysticks);
   17.57 +    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
   17.58 +        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
   17.59          return (NULL);
   17.60      }
   17.61 -    return (SDL_SYS_JoystickName(device_index));
   17.62 +    return (SDL_SYS_JoystickNameForIndex(device_index));
   17.63  }
   17.64  
   17.65  /*
   17.66 @@ -88,21 +76,27 @@
   17.67  SDL_Joystick *
   17.68  SDL_JoystickOpen(int device_index)
   17.69  {
   17.70 -    int i;
   17.71      SDL_Joystick *joystick;
   17.72 +	SDL_Joystick *joysticklist;
   17.73 +	const char *joystickname = NULL;
   17.74  
   17.75 -    if ((device_index < 0) || (device_index >= SDL_numjoysticks)) {
   17.76 -        SDL_SetError("There are %d joysticks available", SDL_numjoysticks);
   17.77 +    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
   17.78 +        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
   17.79          return (NULL);
   17.80      }
   17.81  
   17.82 -    /* If the joystick is already open, return it */
   17.83 -    for (i = 0; SDL_joysticks[i]; ++i) {
   17.84 -        if (device_index == SDL_joysticks[i]->index) {
   17.85 -            joystick = SDL_joysticks[i];
   17.86 -            ++joystick->ref_count;
   17.87 -            return (joystick);
   17.88 -        }
   17.89 +	joysticklist = SDL_joysticks;
   17.90 +    /* If the joystick is already open, return it 
   17.91 +	* it is important that we have a single joystick * for each instance id 
   17.92 +	*/
   17.93 +	while ( joysticklist )
   17.94 +	{
   17.95 +		if ( SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id ) {
   17.96 +				joystick = joysticklist;
   17.97 +				++joystick->ref_count;
   17.98 +				return (joystick);
   17.99 +		}
  17.100 +		joysticklist = joysticklist->next;
  17.101      }
  17.102  
  17.103      /* Create and initialize the joystick */
  17.104 @@ -113,11 +107,17 @@
  17.105      }
  17.106  
  17.107      SDL_memset(joystick, 0, (sizeof *joystick));
  17.108 -    joystick->index = device_index;
  17.109 -    if (SDL_SYS_JoystickOpen(joystick) < 0) {
  17.110 +    if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) {
  17.111          SDL_free(joystick);
  17.112          return NULL;
  17.113      }
  17.114 +
  17.115 +	joystickname = SDL_SYS_JoystickNameForIndex( device_index );
  17.116 +	if ( joystickname )
  17.117 +		joystick->name = SDL_strdup( joystickname );
  17.118 +	else
  17.119 +		joystick->name = NULL;
  17.120 +
  17.121      if (joystick->naxes > 0) {
  17.122          joystick->axes = (Sint16 *) SDL_malloc
  17.123              (joystick->naxes * sizeof(Sint16));
  17.124 @@ -158,68 +158,46 @@
  17.125  
  17.126      /* Add joystick to list */
  17.127      ++joystick->ref_count;
  17.128 -    for (i = 0; SDL_joysticks[i]; ++i)
  17.129 -        /* Skip to next joystick */ ;
  17.130 -    SDL_joysticks[i] = joystick;
  17.131 +	/* Link the joystick in the list */
  17.132 +	joystick->next = SDL_joysticks;
  17.133 +	SDL_joysticks = joystick;
  17.134 +
  17.135 +	SDL_SYS_JoystickUpdate( joystick );
  17.136  
  17.137      return (joystick);
  17.138  }
  17.139  
  17.140 -/*
  17.141 - * Returns 1 if the joystick has been opened, or 0 if it has not.
  17.142 - */
  17.143 -int
  17.144 -SDL_JoystickOpened(int device_index)
  17.145 -{
  17.146 -    int i, opened;
  17.147 -
  17.148 -    opened = 0;
  17.149 -    for (i = 0; SDL_joysticks[i]; ++i) {
  17.150 -        if (SDL_joysticks[i]->index == (Uint8) device_index) {
  17.151 -            opened = 1;
  17.152 -            break;
  17.153 -        }
  17.154 -    }
  17.155 -    return (opened);
  17.156 -}
  17.157 -
  17.158  
  17.159  /*
  17.160   * Checks to make sure the joystick is valid.
  17.161   */
  17.162  int
  17.163 -SDL_PrivateJoystickValid(SDL_Joystick ** joystick)
  17.164 +SDL_PrivateJoystickValid(SDL_Joystick * joystick)
  17.165  {
  17.166      int valid;
  17.167  
  17.168 -    if (*joystick == NULL) {
  17.169 +    if ( joystick == NULL ) {
  17.170          SDL_SetError("Joystick hasn't been opened yet");
  17.171          valid = 0;
  17.172      } else {
  17.173          valid = 1;
  17.174      }
  17.175 +	
  17.176 +	if ( joystick && joystick->closed )
  17.177 +	{
  17.178 +		valid = 0;
  17.179 +	}
  17.180 +	
  17.181      return valid;
  17.182  }
  17.183  
  17.184  /*
  17.185 - * Get the device index of an opened joystick.
  17.186 - */
  17.187 -int
  17.188 -SDL_JoystickIndex(SDL_Joystick * joystick)
  17.189 -{
  17.190 -    if (!SDL_PrivateJoystickValid(&joystick)) {
  17.191 -        return (-1);
  17.192 -    }
  17.193 -    return (joystick->index);
  17.194 -}
  17.195 -
  17.196 -/*
  17.197   * Get the number of multi-dimensional axis controls on a joystick
  17.198   */
  17.199  int
  17.200  SDL_JoystickNumAxes(SDL_Joystick * joystick)
  17.201  {
  17.202 -    if (!SDL_PrivateJoystickValid(&joystick)) {
  17.203 +    if (!SDL_PrivateJoystickValid(joystick)) {
  17.204          return (-1);
  17.205      }
  17.206      return (joystick->naxes);
  17.207 @@ -231,7 +209,7 @@
  17.208  int
  17.209  SDL_JoystickNumHats(SDL_Joystick * joystick)
  17.210  {
  17.211 -    if (!SDL_PrivateJoystickValid(&joystick)) {
  17.212 +    if (!SDL_PrivateJoystickValid(joystick)) {
  17.213          return (-1);
  17.214      }
  17.215      return (joystick->nhats);
  17.216 @@ -243,7 +221,7 @@
  17.217  int
  17.218  SDL_JoystickNumBalls(SDL_Joystick * joystick)
  17.219  {
  17.220 -    if (!SDL_PrivateJoystickValid(&joystick)) {
  17.221 +    if (!SDL_PrivateJoystickValid(joystick)) {
  17.222          return (-1);
  17.223      }
  17.224      return (joystick->nballs);
  17.225 @@ -255,7 +233,7 @@
  17.226  int
  17.227  SDL_JoystickNumButtons(SDL_Joystick * joystick)
  17.228  {
  17.229 -    if (!SDL_PrivateJoystickValid(&joystick)) {
  17.230 +    if (!SDL_PrivateJoystickValid(joystick)) {
  17.231          return (-1);
  17.232      }
  17.233      return (joystick->nbuttons);
  17.234 @@ -269,7 +247,7 @@
  17.235  {
  17.236      Sint16 state;
  17.237  
  17.238 -    if (!SDL_PrivateJoystickValid(&joystick)) {
  17.239 +    if (!SDL_PrivateJoystickValid(joystick)) {
  17.240          return (0);
  17.241      }
  17.242      if (axis < joystick->naxes) {
  17.243 @@ -289,7 +267,7 @@
  17.244  {
  17.245      Uint8 state;
  17.246  
  17.247 -    if (!SDL_PrivateJoystickValid(&joystick)) {
  17.248 +    if (!SDL_PrivateJoystickValid(joystick)) {
  17.249          return (0);
  17.250      }
  17.251      if (hat < joystick->nhats) {
  17.252 @@ -309,7 +287,7 @@
  17.253  {
  17.254      int retval;
  17.255  
  17.256 -    if (!SDL_PrivateJoystickValid(&joystick)) {
  17.257 +    if (!SDL_PrivateJoystickValid(joystick)) {
  17.258          return (-1);
  17.259      }
  17.260  
  17.261 @@ -338,7 +316,7 @@
  17.262  {
  17.263      Uint8 state;
  17.264  
  17.265 -    if (!SDL_PrivateJoystickValid(&joystick)) {
  17.266 +    if (!SDL_PrivateJoystickValid(joystick)) {
  17.267          return (0);
  17.268      }
  17.269      if (button < joystick->nbuttons) {
  17.270 @@ -351,14 +329,55 @@
  17.271  }
  17.272  
  17.273  /*
  17.274 + * Return if the joystick in question is currently attached to the system,
  17.275 + *  \return 0 if not plugged in, 1 if still present.
  17.276 + */
  17.277 +int
  17.278 +SDL_JoystickGetAttached( SDL_Joystick * joystick )
  17.279 +{
  17.280 +	if (!SDL_PrivateJoystickValid(joystick)) {
  17.281 +        return (0);
  17.282 +    }
  17.283 +
  17.284 +	return SDL_SYS_JoystickAttached(joystick);
  17.285 +}
  17.286 +
  17.287 +/*
  17.288 + * Get the instance id for this opened joystick
  17.289 + */
  17.290 +SDL_JoystickID 
  17.291 +SDL_JoystickInstanceID( SDL_Joystick * joystick )
  17.292 +{
  17.293 +	if (!SDL_PrivateJoystickValid(joystick)) {
  17.294 +        return (-1);
  17.295 +    }
  17.296 +
  17.297 +	return (joystick->instance_id);
  17.298 +}
  17.299 +
  17.300 +/*
  17.301 + * Get the friendly name of this joystick
  17.302 + */
  17.303 +const char *
  17.304 +SDL_JoystickName(SDL_Joystick * joystick)
  17.305 +{
  17.306 +    if (!SDL_PrivateJoystickValid(joystick)) {
  17.307 +        return (NULL);
  17.308 +    }
  17.309 +	
  17.310 +    return (joystick->name);
  17.311 +}
  17.312 +
  17.313 +/*
  17.314   * Close a joystick previously opened with SDL_JoystickOpen()
  17.315   */
  17.316  void
  17.317  SDL_JoystickClose(SDL_Joystick * joystick)
  17.318  {
  17.319 -    int i;
  17.320 +	SDL_Joystick *joysticklist;
  17.321 +	SDL_Joystick *joysticklistprev;
  17.322  
  17.323 -    if (!SDL_PrivateJoystickValid(&joystick)) {
  17.324 +    if (!joystick) {
  17.325          return;
  17.326      }
  17.327  
  17.328 @@ -368,15 +387,31 @@
  17.329      }
  17.330  
  17.331      SDL_SYS_JoystickClose(joystick);
  17.332 +	
  17.333 +	joysticklist = SDL_joysticks;
  17.334 +	joysticklistprev = NULL;
  17.335 +	while ( joysticklist )
  17.336 +	{
  17.337 +		if (joystick == joysticklist) 
  17.338 +		{
  17.339 +			if ( joysticklistprev )
  17.340 +			{
  17.341 +				// unlink this entry
  17.342 +				joysticklistprev->next = joysticklist->next;
  17.343 +			}
  17.344 +			else
  17.345 +			{
  17.346 +				SDL_joysticks = joystick->next;
  17.347 +			}
  17.348  
  17.349 -    /* Remove joystick from list */
  17.350 -    for (i = 0; SDL_joysticks[i]; ++i) {
  17.351 -        if (joystick == SDL_joysticks[i]) {
  17.352 -            SDL_memmove(&SDL_joysticks[i], &SDL_joysticks[i + 1],
  17.353 -                        (SDL_numjoysticks - i) * sizeof(joystick));
  17.354 -            break;
  17.355 -        }
  17.356 -    }
  17.357 +			break;
  17.358 +		}
  17.359 +		joysticklistprev = joysticklist;
  17.360 +		joysticklist = joysticklist->next;
  17.361 +	}
  17.362 +	
  17.363 +	if (joystick->name)
  17.364 +		SDL_free(joystick->name);
  17.365  
  17.366      /* Free the data associated with this joystick */
  17.367      if (joystick->axes) {
  17.368 @@ -397,26 +432,15 @@
  17.369  void
  17.370  SDL_JoystickQuit(void)
  17.371  {
  17.372 -    const int numsticks = SDL_numjoysticks;
  17.373 -    int i;
  17.374 -
  17.375      /* Stop the event polling */
  17.376 -    SDL_numjoysticks = 0;
  17.377 -
  17.378 -    for (i = numsticks; i--; ) {
  17.379 -        SDL_Joystick *stick = SDL_joysticks[i];
  17.380 -        if (stick && (stick->ref_count >= 1)) {
  17.381 -            stick->ref_count = 1;
  17.382 -            SDL_JoystickClose(stick);
  17.383 -        }
  17.384 -    }
  17.385 +	while ( SDL_joysticks )
  17.386 +	{
  17.387 +		SDL_joysticks->ref_count = 1;
  17.388 +        SDL_JoystickClose(SDL_joysticks);
  17.389 + 	}
  17.390  
  17.391      /* Quit the joystick setup */
  17.392      SDL_SYS_JoystickQuit();
  17.393 -    if (SDL_joysticks) {
  17.394 -        SDL_free(SDL_joysticks);
  17.395 -        SDL_joysticks = NULL;
  17.396 -    }
  17.397  }
  17.398  
  17.399  
  17.400 @@ -441,14 +465,10 @@
  17.401      if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
  17.402          SDL_Event event;
  17.403          event.type = SDL_JOYAXISMOTION;
  17.404 -        event.jaxis.which = joystick->index;
  17.405 +        event.jaxis.which = joystick->instance_id;
  17.406          event.jaxis.axis = axis;
  17.407          event.jaxis.value = value;
  17.408 -        if ((SDL_EventOK == NULL)
  17.409 -            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
  17.410 -            posted = 1;
  17.411 -            SDL_PushEvent(&event);
  17.412 -        }
  17.413 +        posted = SDL_PushEvent(&event) == 1;
  17.414      }
  17.415  #endif /* !SDL_EVENTS_DISABLED */
  17.416      return (posted);
  17.417 @@ -473,14 +493,10 @@
  17.418      if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
  17.419          SDL_Event event;
  17.420          event.jhat.type = SDL_JOYHATMOTION;
  17.421 -        event.jhat.which = joystick->index;
  17.422 +        event.jhat.which = joystick->instance_id;
  17.423          event.jhat.hat = hat;
  17.424          event.jhat.value = value;
  17.425 -        if ((SDL_EventOK == NULL)
  17.426 -            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
  17.427 -            posted = 1;
  17.428 -            SDL_PushEvent(&event);
  17.429 -        }
  17.430 +        posted = SDL_PushEvent(&event) == 1;
  17.431      }
  17.432  #endif /* !SDL_EVENTS_DISABLED */
  17.433      return (posted);
  17.434 @@ -507,15 +523,11 @@
  17.435      if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
  17.436          SDL_Event event;
  17.437          event.jball.type = SDL_JOYBALLMOTION;
  17.438 -        event.jball.which = joystick->index;
  17.439 +        event.jball.which = joystick->instance_id;
  17.440          event.jball.ball = ball;
  17.441          event.jball.xrel = xrel;
  17.442          event.jball.yrel = yrel;
  17.443 -        if ((SDL_EventOK == NULL)
  17.444 -            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
  17.445 -            posted = 1;
  17.446 -            SDL_PushEvent(&event);
  17.447 -        }
  17.448 +        posted = SDL_PushEvent(&event) == 1;
  17.449      }
  17.450  #endif /* !SDL_EVENTS_DISABLED */
  17.451      return (posted);
  17.452 @@ -553,14 +565,10 @@
  17.453      posted = 0;
  17.454  #if !SDL_EVENTS_DISABLED
  17.455      if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  17.456 -        event.jbutton.which = joystick->index;
  17.457 +        event.jbutton.which = joystick->instance_id;
  17.458          event.jbutton.button = button;
  17.459          event.jbutton.state = state;
  17.460 -        if ((SDL_EventOK == NULL)
  17.461 -            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
  17.462 -            posted = 1;
  17.463 -            SDL_PushEvent(&event);
  17.464 -        }
  17.465 +        posted = SDL_PushEvent(&event) == 1;
  17.466      }
  17.467  #endif /* !SDL_EVENTS_DISABLED */
  17.468      return (posted);
  17.469 @@ -569,11 +577,39 @@
  17.470  void
  17.471  SDL_JoystickUpdate(void)
  17.472  {
  17.473 -    int i;
  17.474 +	SDL_Joystick *joystick;
  17.475 +		
  17.476 +	joystick = SDL_joysticks;
  17.477 +	while ( joystick )
  17.478 +	{
  17.479 +		SDL_Joystick *joysticknext;
  17.480 +		/* save off the next pointer, the Update call may cause a joystick removed event
  17.481 +		 * and cause our joystick pointer to be freed
  17.482 +		 */
  17.483 +		joysticknext = joystick->next;
  17.484  
  17.485 -    for (i = 0; SDL_joysticks[i]; ++i) {
  17.486 -        SDL_SYS_JoystickUpdate(SDL_joysticks[i]);
  17.487 -    }
  17.488 +        SDL_SYS_JoystickUpdate( joystick );
  17.489 +
  17.490 +		if ( joystick->closed && joystick->uncentered )
  17.491 +		{
  17.492 +			int i;
  17.493 +			joystick->uncentered = 0;
  17.494 +
  17.495 +            // Tell the app that everything is centered/unpressed... 
  17.496 +            for (i = 0; i < joystick->naxes; i++)
  17.497 +                SDL_PrivateJoystickAxis(joystick, i, 0);
  17.498 +
  17.499 +            for (i = 0; i < joystick->nbuttons; i++)
  17.500 +                SDL_PrivateJoystickButton(joystick, i, 0);
  17.501 +
  17.502 +            for (i = 0; i < joystick->nhats; i++)
  17.503 +                SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
  17.504 +		}
  17.505 +
  17.506 +		joystick = joysticknext;
  17.507 +	}
  17.508 +
  17.509 +	SDL_SYS_JoystickDetect();
  17.510  }
  17.511  
  17.512  int
  17.513 @@ -584,7 +620,7 @@
  17.514  #else
  17.515      const Uint32 event_list[] = {
  17.516          SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
  17.517 -        SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP,
  17.518 +        SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED
  17.519      };
  17.520      unsigned int i;
  17.521  
  17.522 @@ -608,4 +644,121 @@
  17.523  #endif /* SDL_EVENTS_DISABLED */
  17.524  }
  17.525  
  17.526 +/* return 1 if you want to run the joystick update loop this frame, used by hotplug support */
  17.527 +int 
  17.528 +SDL_PrivateJoystickNeedsPolling()
  17.529 +{
  17.530 +	if ( SDL_SYS_JoystickNeedsPolling() )
  17.531 +	{
  17.532 +		// sys layer needs us to think
  17.533 +		return 1;
  17.534 +	}
  17.535 +	else
  17.536 +	{
  17.537 +		// otherwise only do it if a joystick is opened
  17.538 +		return SDL_joysticks != NULL; 
  17.539 +	}
  17.540 +}
  17.541 +
  17.542 +
  17.543 +/* return the guid for this index*/
  17.544 +JoystickGUID SDL_JoystickGetDeviceGUID( int device_index )
  17.545 +{
  17.546 +	return SDL_SYS_PrivateJoystickGetDeviceID( device_index );
  17.547 +}
  17.548 +
  17.549 +/* return the guid for this openeded device*/
  17.550 +JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
  17.551 +{
  17.552 +	return SDL_SYS_PrivateJoystickGetGUID( joystick );
  17.553 +
  17.554 +}
  17.555 +
  17.556 +/* convert the guid to a printable string */
  17.557 +char *SDL_JoystickGetGUIDString(JoystickGUID guid)
  17.558 +{
  17.559 +	static const char k_rgchHexToASCII[] = "0123456789abcdef";
  17.560 +	char *pchOut = NULL;
  17.561 +	char *pchString = NULL;
  17.562 +	int i;
  17.563 +	pchString = SDL_malloc(33); // 16 bytes
  17.564 +	if ( !pchString )
  17.565 +	{
  17.566 +		SDL_OutOfMemory();
  17.567 +		return NULL;
  17.568 +	}
  17.569 +	
  17.570 +	pchOut = pchString;
  17.571 +
  17.572 +	for ( i = 0; i < sizeof(guid); i++ )
  17.573 +	{
  17.574 +		// each input byte writes 2 ascii chars, and might write a null byte.
  17.575 +		// If we don't have room for next input byte, stop
  17.576 +		unsigned char c = guid.data[i];
  17.577 +
  17.578 +		*pchOut++ = k_rgchHexToASCII[ c >> 4 ];
  17.579 +		*pchOut++ = k_rgchHexToASCII[ c & 0x0F ];
  17.580 +	}
  17.581 +	*pchOut = '\0';
  17.582 +	return pchString;
  17.583 +}
  17.584 +
  17.585 +
  17.586 +//-----------------------------------------------------------------------------
  17.587 +// Purpose: Returns the 4 bit nibble for a hex character
  17.588 +// Input  : c - 
  17.589 +// Output : unsigned char
  17.590 +//-----------------------------------------------------------------------------
  17.591 +static unsigned char nibble( char c )
  17.592 +{
  17.593 +	if ( ( c >= '0' ) &&
  17.594 +		( c <= '9' ) )
  17.595 +	{
  17.596 +		return (unsigned char)(c - '0');
  17.597 +	}
  17.598 +
  17.599 +	if ( ( c >= 'A' ) &&
  17.600 +		( c <= 'F' ) )
  17.601 +	{
  17.602 +		return (unsigned char)(c - 'A' + 0x0a);
  17.603 +	}
  17.604 +
  17.605 +	if ( ( c >= 'a' ) &&
  17.606 +		( c <= 'f' ) )
  17.607 +	{
  17.608 +		return (unsigned char)(c - 'a' + 0x0a);
  17.609 +	}
  17.610 +
  17.611 +	// received an invalid character, and no real way to return an error
  17.612 +	// AssertMsg1( false, "Q_nibble invalid hex character '%c' ", c );
  17.613 +	return 0;
  17.614 +}
  17.615 +
  17.616 +
  17.617 +/* convert the string version of a joystick guid to the struct */
  17.618 +JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
  17.619 +{
  17.620 +	JoystickGUID guid;
  17.621 +	int maxoutputbytes= sizeof(guid);
  17.622 +	int len = SDL_strlen( pchGUID );
  17.623 +	Uint8 *p;
  17.624 +	int i;
  17.625 +
  17.626 +	// Make sure it's even
  17.627 +	len = ( len ) & ~0x1;
  17.628 +
  17.629 +	SDL_memset( &guid, 0x00, sizeof(guid) );
  17.630 +
  17.631 +	p = (Uint8 *)&guid;
  17.632 +	for ( i = 0; 
  17.633 +		( i < len ) && ( ( p - (Uint8 *)&guid ) < maxoutputbytes ); 
  17.634 +		i+=2, p++ )
  17.635 +	{
  17.636 +		*p = ( nibble( pchGUID[i] ) << 4 ) | nibble( pchGUID[i+1] );		
  17.637 +	}
  17.638 +
  17.639 +	return guid;
  17.640 +}
  17.641 +
  17.642 +
  17.643  /* vi: set ts=4 sw=4 expandtab: */
    18.1 --- a/src/joystick/SDL_joystick_c.h	Mon Nov 26 14:59:07 2012 -0800
    18.2 +++ b/src/joystick/SDL_joystick_c.h	Mon Nov 26 16:37:54 2012 -0800
    18.3 @@ -23,13 +23,15 @@
    18.4  /* Useful functions and variables from SDL_joystick.c */
    18.5  #include "SDL_joystick.h"
    18.6  
    18.7 -/* The number of available joysticks on the system */
    18.8 -extern Uint8 SDL_numjoysticks;
    18.9 -
   18.10  /* Initialization and shutdown functions */
   18.11  extern int SDL_JoystickInit(void);
   18.12  extern void SDL_JoystickQuit(void);
   18.13  
   18.14 +/* Initialization and shutdown functions */
   18.15 +extern int SDL_GameControllerInit(void);
   18.16 +extern void SDL_GameControllerQuit(void);
   18.17 +
   18.18 +
   18.19  /* Internal event queueing functions */
   18.20  extern int SDL_PrivateJoystickAxis(SDL_Joystick * joystick,
   18.21                                     Uint8 axis, Sint16 value);
   18.22 @@ -39,8 +41,11 @@
   18.23                                    Uint8 hat, Uint8 value);
   18.24  extern int SDL_PrivateJoystickButton(SDL_Joystick * joystick,
   18.25                                       Uint8 button, Uint8 state);
   18.26 +									 
   18.27 +/* Helper function to let lower sys layer tell the event system if the joystick code needs to think */
   18.28 +extern int SDL_PrivateJoystickNeedsPolling();
   18.29  
   18.30  /* Internal sanity checking functions */
   18.31 -extern int SDL_PrivateJoystickValid(SDL_Joystick ** joystick);
   18.32 +extern int SDL_PrivateJoystickValid(SDL_Joystick * joystick);
   18.33  
   18.34  /* vi: set ts=4 sw=4 expandtab: */
    19.1 --- a/src/joystick/SDL_sysjoystick.h	Mon Nov 26 14:59:07 2012 -0800
    19.2 +++ b/src/joystick/SDL_sysjoystick.h	Mon Nov 26 16:37:54 2012 -0800
    19.3 @@ -23,12 +23,13 @@
    19.4  /* This is the system specific header for the SDL joystick API */
    19.5  
    19.6  #include "SDL_joystick.h"
    19.7 +#include "SDL_joystick_c.h"
    19.8  
    19.9  /* The SDL joystick structure */
   19.10  struct _SDL_Joystick
   19.11  {
   19.12 -    Uint8 index;                /* Device index */
   19.13 -    const char *name;           /* Joystick name - system dependent */
   19.14 +    int instance_id;                /* Device instance, monotonically increasing from 0 */
   19.15 +    char *name;          		 /* Joystick name - system dependent */
   19.16  
   19.17      int naxes;                  /* Number of axis controls on the joystick */
   19.18      Sint16 *axes;               /* Current axis states */
   19.19 @@ -49,6 +50,10 @@
   19.20      struct joystick_hwdata *hwdata;     /* Driver dependent information */
   19.21  
   19.22      int ref_count;              /* Reference count for multiple opens */
   19.23 +	
   19.24 +	Uint8 closed;				/* 1 if this device is no longer valid */
   19.25 +	Uint8 uncentered;			/* 1 if this device needs to have its state reset to 0 */
   19.26 +	struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */
   19.27  };
   19.28  
   19.29  /* Function to scan the system for joysticks.
   19.30 @@ -59,14 +64,17 @@
   19.31  extern int SDL_SYS_JoystickInit(void);
   19.32  
   19.33  /* Function to get the device-dependent name of a joystick */
   19.34 -extern const char *SDL_SYS_JoystickName(int index);
   19.35 +extern const char *SDL_SYS_JoystickNameForIndex(int index);
   19.36 +
   19.37 +/* Function to get the current instance id of the joystick located at device_index */
   19.38 +extern SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex( int device_index );
   19.39  
   19.40  /* Function to open a joystick for use.
   19.41     The joystick to open is specified by the index field of the joystick.
   19.42     This should fill the nbuttons and naxes fields of the joystick structure.
   19.43     It returns 0, or -1 if there is an error.
   19.44   */
   19.45 -extern int SDL_SYS_JoystickOpen(SDL_Joystick * joystick);
   19.46 +extern int SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index );
   19.47  
   19.48  /* Function to update the state of a joystick - called as a device poll.
   19.49   * This function shouldn't update the joystick structure directly,
   19.50 @@ -81,4 +89,32 @@
   19.51  /* Function to perform any system-specific joystick related cleanup */
   19.52  extern void SDL_SYS_JoystickQuit(void);
   19.53  
   19.54 +/* Function to query if the joystick is currently attached
   19.55 + *   It returns 1 if attached, 0 otherwise.
   19.56 + */
   19.57 +extern int SDL_SYS_JoystickAttached(SDL_Joystick * joystick);
   19.58 +
   19.59 +/* Function to return the number of joystick devices plugged in right now*/
   19.60 +extern int SDL_SYS_NumJoysticks();
   19.61 +
   19.62 +/* Function to cause any queued joystick insertions to be processed
   19.63 + */
   19.64 +extern void SDL_SYS_JoystickDetect();
   19.65 +
   19.66 +/* Function to determine if the joystick loop needs to run right now
   19.67 + */
   19.68 +extern int SDL_SYS_JoystickNeedsPolling();
   19.69 +
   19.70 +/* Function to return the stable GUID for a plugged in device
   19.71 + */
   19.72 +extern JoystickGUID SDL_SYS_PrivateJoystickGetDeviceID( int device_index );
   19.73 +
   19.74 +/* Function to return the stable GUID for a opened joystick
   19.75 + */
   19.76 +extern JoystickGUID SDL_SYS_PrivateJoystickGetGUID(SDL_Joystick * joystick);
   19.77 +
   19.78 +#ifdef __WIN32__
   19.79 +/* Function to get the current instance id of the joystick located at device_index */
   19.80 +extern int SDL_SYS_IsXInputDeviceIndex( int device_index );
   19.81 +#endif
   19.82  /* vi: set ts=4 sw=4 expandtab: */
    20.1 --- a/src/joystick/darwin/SDL_sysjoystick.c	Mon Nov 26 14:59:07 2012 -0800
    20.2 +++ b/src/joystick/darwin/SDL_sysjoystick.c	Mon Nov 26 16:37:54 2012 -0800
    20.3 @@ -42,6 +42,7 @@
    20.4  #include <IOKit/hid/IOHIDKeys.h>
    20.5  #include <CoreFoundation/CoreFoundation.h>
    20.6  #include <Carbon/Carbon.h>      /* for NewPtrClear, DisposePtr */
    20.7 +#include <IOKit/IOMessage.h>
    20.8  
    20.9  /* For force feedback testing. */
   20.10  #include <ForceFeedback/ForceFeedback.h>
   20.11 @@ -51,11 +52,21 @@
   20.12  #include "../SDL_sysjoystick.h"
   20.13  #include "../SDL_joystick_c.h"
   20.14  #include "SDL_sysjoystick_c.h"
   20.15 +#include "SDL_events.h"
   20.16 +#if !SDL_EVENTS_DISABLED
   20.17 +#include "../../events/SDL_events_c.h"
   20.18 +#endif
   20.19  
   20.20  
   20.21  /* Linked list of all available devices */
   20.22  static recDevice *gpDeviceList = NULL;
   20.23 +/* OSX reference to the notification object that tells us about device insertion/removal */
   20.24 +IONotificationPortRef notificationPort = 0;
   20.25 +/* if 1 then a device was added since the last update call */
   20.26 +Uint8 s_bDeviceAdded = 0;
   20.27  
   20.28 +/* static incrementing counter for new joystick devices seen on the system. Devices should start with index 0 */
   20.29 +static int s_joystick_instance_id = -1;
   20.30  
   20.31  static void
   20.32  HIDReportErrorNum(char *strError, long numError)
   20.33 @@ -115,10 +126,20 @@
   20.34  {
   20.35      recDevice *device = (recDevice *) refcon;
   20.36      device->removed = 1;
   20.37 -    device->uncentered = 1;
   20.38  }
   20.39  
   20.40  
   20.41 +/* Called by the io port notifier on removal of this device
   20.42 + */
   20.43 +void JoystickDeviceWasRemovedCallback( void * refcon, io_service_t service, natural_t messageType, void * messageArgument )
   20.44 +{
   20.45 +    if( messageType == kIOMessageServiceIsTerminated && refcon )
   20.46 +    {
   20.47 +		recDevice *device = (recDevice *) refcon;
   20.48 +		device->removed = 1;
   20.49 +	}
   20.50 +}
   20.51 +
   20.52  
   20.53  /* Create and open an interface to device, required prior to extracting values or building queues.
   20.54   * Note: appliction now owns the device and must close and release it prior to exiting
   20.55 @@ -162,9 +183,33 @@
   20.56              HIDReportErrorNum
   20.57                  ("Failed to open pDevice->interface via open.", result);
   20.58          else
   20.59 +		{
   20.60 +			pDevice->portIterator = 0;
   20.61 +
   20.62 +			// It's okay if this fails, we have another detection method below
   20.63              (*(pDevice->interface))->setRemovalCallback(pDevice->interface,
   20.64                                                          HIDRemovalCallback,
   20.65                                                          pDevice, pDevice);
   20.66 +			
   20.67 +			/* now connect notification for new devices */
   20.68 +			pDevice->notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
   20.69 +			
   20.70 +			CFRunLoopAddSource(CFRunLoopGetCurrent(), 
   20.71 +							   IONotificationPortGetRunLoopSource(pDevice->notificationPort), 
   20.72 +							   kCFRunLoopDefaultMode);
   20.73 +			
   20.74 +			// Register for notifications when a serial port is added to the system
   20.75 +			result = IOServiceAddInterestNotification(pDevice->notificationPort,
   20.76 +													  hidDevice,
   20.77 +													  kIOGeneralInterest,
   20.78 +													  JoystickDeviceWasRemovedCallback,
   20.79 +													  pDevice,           
   20.80 +													  &pDevice->portIterator);
   20.81 +        	if (kIOReturnSuccess != result) {
   20.82 +            	HIDReportErrorNum
   20.83 +                	("Failed to register for removal callback.", result);		
   20.84 +			}	
   20.85 +		}
   20.86  
   20.87      }
   20.88      return result;
   20.89 @@ -195,6 +240,12 @@
   20.90              HIDReportErrorNum("Failed to release IOHIDDeviceInterface.",
   20.91                                result);
   20.92          pDevice->interface = NULL;
   20.93 +		
   20.94 +		if ( pDevice->portIterator )
   20.95 +		{
   20.96 +			IOObjectRelease( pDevice->portIterator );
   20.97 +			pDevice->portIterator = 0;
   20.98 +		}
   20.99      }
  20.100      return result;
  20.101  }
  20.102 @@ -461,6 +512,26 @@
  20.103                              ("CFNumberGetValue error retrieving pDevice->usage.");
  20.104              }
  20.105  
  20.106 +			refCF =
  20.107 +			CFDictionaryGetValue(hidProperties,
  20.108 +								 CFSTR(kIOHIDVendorIDKey));
  20.109 +            if (refCF) {
  20.110 +                if (!CFNumberGetValue
  20.111 +                    (refCF, kCFNumberLongType, &pDevice->guid.data[0]))
  20.112 +                    SDL_SetError
  20.113 +					("CFNumberGetValue error retrieving pDevice->guid.");
  20.114 +            }
  20.115 +			refCF =
  20.116 +			CFDictionaryGetValue(hidProperties,
  20.117 +								 CFSTR(kIOHIDProductIDKey));
  20.118 +            if (refCF) {
  20.119 +                if (!CFNumberGetValue
  20.120 +                    (refCF, kCFNumberLongType, &pDevice->guid.data[8]))
  20.121 +                    SDL_SetError
  20.122 +					("CFNumberGetValue error retrieving pDevice->guid[8].");
  20.123 +            }
  20.124 +
  20.125 +			
  20.126              if (NULL == refCF) {        /* get top level element HID usage page or usage */
  20.127                  /* use top level element instead */
  20.128                  CFTypeRef refCFTopElement = 0;
  20.129 @@ -505,6 +576,7 @@
  20.130              if (kIOReturnSuccess == result) {
  20.131                  HIDGetDeviceInfo(hidDevice, hidProperties, pDevice);    /* hidDevice used to find parents in registry tree */
  20.132                  HIDGetCollectionElements(hidProperties, pDevice);
  20.133 +				pDevice->instance_id = ++s_joystick_instance_id;
  20.134              } else {
  20.135                  DisposePtr((Ptr) pDevice);
  20.136                  pDevice = NULL;
  20.137 @@ -569,6 +641,79 @@
  20.138  }
  20.139  
  20.140  
  20.141 +/* Given an io_object_t from OSX adds a joystick device to our list if appropriate
  20.142 + */
  20.143 +int 
  20.144 +AddDeviceHelper( io_object_t ioHIDDeviceObject )
  20.145 +{
  20.146 +    recDevice *device;
  20.147 +	
  20.148 +	/* build a device record */
  20.149 +	device = HIDBuildDevice(ioHIDDeviceObject);
  20.150 +	if (!device)
  20.151 +		return 0;
  20.152 +	
  20.153 +	/* Filter device list to non-keyboard/mouse stuff */
  20.154 +	if ((device->usagePage != kHIDPage_GenericDesktop) ||
  20.155 +		((device->usage != kHIDUsage_GD_Joystick &&
  20.156 +		  device->usage != kHIDUsage_GD_GamePad &&
  20.157 +		  device->usage != kHIDUsage_GD_MultiAxisController))) {
  20.158 +		
  20.159 +		/* release memory for the device */
  20.160 +		HIDDisposeDevice(&device);
  20.161 +		DisposePtr((Ptr) device);
  20.162 +		return 0;
  20.163 +	}
  20.164 +	
  20.165 +	/* We have to do some storage of the io_service_t for
  20.166 +	 * SDL_HapticOpenFromJoystick */
  20.167 +	if (FFIsForceFeedback(ioHIDDeviceObject) == FF_OK) {
  20.168 +		device->ffservice = ioHIDDeviceObject;
  20.169 +	} else {
  20.170 +		device->ffservice = 0;
  20.171 +	}
  20.172 +	
  20.173 +	device->send_open_event = 1;
  20.174 +	s_bDeviceAdded = 1;
  20.175 +	
  20.176 +	/* Add device to the end of the list */
  20.177 +	if ( !gpDeviceList )
  20.178 +	{
  20.179 +		gpDeviceList = device;
  20.180 +	}
  20.181 +	else
  20.182 +	{
  20.183 +		recDevice *curdevice;
  20.184 +		
  20.185 +		curdevice = gpDeviceList;
  20.186 +		while ( curdevice->pNext )
  20.187 +		{
  20.188 +			curdevice = curdevice->pNext;
  20.189 +		}
  20.190 +		curdevice->pNext = device;
  20.191 +	}
  20.192 +	
  20.193 +	return 1;
  20.194 +}
  20.195 +
  20.196 +
  20.197 +/* Called by our IO port notifier on the master port when a HID device is inserted, we iterate
  20.198 + *  and check for new joysticks
  20.199 + */
  20.200 +void JoystickDeviceWasAddedCallback( void *refcon, io_iterator_t iterator )
  20.201 +{
  20.202 +    io_object_t ioHIDDeviceObject = 0;
  20.203 +	
  20.204 +	while ( ( ioHIDDeviceObject = IOIteratorNext(iterator) ) )
  20.205 +	{
  20.206 +		if ( ioHIDDeviceObject )
  20.207 +		{
  20.208 +			AddDeviceHelper( ioHIDDeviceObject );			
  20.209 +		}
  20.210 +	}
  20.211 +}
  20.212 +				
  20.213 +
  20.214  /* Function to scan the system for joysticks.
  20.215   * Joystick 0 should be the system default joystick.
  20.216   * This function should return the number of available joysticks, or -1
  20.217 @@ -581,10 +726,8 @@
  20.218      mach_port_t masterPort = 0;
  20.219      io_iterator_t hidObjectIterator = 0;
  20.220      CFMutableDictionaryRef hidMatchDictionary = NULL;
  20.221 -    recDevice *device, *lastDevice;
  20.222      io_object_t ioHIDDeviceObject = 0;
  20.223 -
  20.224 -    SDL_numjoysticks = 0;
  20.225 +	io_iterator_t portIterator = 0;
  20.226  
  20.227      if (gpDeviceList) {
  20.228          SDL_SetError("Joystick: Device list already inited.");
  20.229 @@ -629,70 +772,49 @@
  20.230      }
  20.231      if (!hidObjectIterator) {   /* there are no joysticks */
  20.232          gpDeviceList = NULL;
  20.233 -        SDL_numjoysticks = 0;
  20.234          return 0;
  20.235      }
  20.236      /* IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. */
  20.237  
  20.238      /* build flat linked list of devices from device iterator */
  20.239  
  20.240 -    gpDeviceList = lastDevice = NULL;
  20.241 +    gpDeviceList = NULL;
  20.242  
  20.243      while ((ioHIDDeviceObject = IOIteratorNext(hidObjectIterator))) {
  20.244 -        /* build a device record */
  20.245 -        device = HIDBuildDevice(ioHIDDeviceObject);
  20.246 -        if (!device)
  20.247 -            continue;
  20.248 -
  20.249 -        /* Filter device list to non-keyboard/mouse stuff */
  20.250 -        if ((device->usagePage != kHIDPage_GenericDesktop) ||
  20.251 -            ((device->usage != kHIDUsage_GD_Joystick &&
  20.252 -              device->usage != kHIDUsage_GD_GamePad &&
  20.253 -              device->usage != kHIDUsage_GD_MultiAxisController))) {
  20.254 -
  20.255 -            /* release memory for the device */
  20.256 -            HIDDisposeDevice(&device);
  20.257 -            DisposePtr((Ptr) device);
  20.258 -            continue;
  20.259 -        }
  20.260 -
  20.261 -        /* We have to do some storage of the io_service_t for
  20.262 -         * SDL_HapticOpenFromJoystick */
  20.263 -        if (FFIsForceFeedback(ioHIDDeviceObject) == FF_OK) {
  20.264 -            device->ffservice = ioHIDDeviceObject;
  20.265 -        } else {
  20.266 -            device->ffservice = 0;
  20.267 -        }
  20.268 -
  20.269 -        /* Add device to the end of the list */
  20.270 -        if (lastDevice)
  20.271 -            lastDevice->pNext = device;
  20.272 -        else
  20.273 -            gpDeviceList = device;
  20.274 -        lastDevice = device;
  20.275 +		AddDeviceHelper( ioHIDDeviceObject );
  20.276      }
  20.277      result = IOObjectRelease(hidObjectIterator);        /* release the iterator */
  20.278 +	
  20.279 +	/* now connect notification for new devices */
  20.280 +	notificationPort = IONotificationPortCreate(masterPort);
  20.281 +	hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey);
  20.282  
  20.283 -    /* Count the total number of devices we found */
  20.284 -    device = gpDeviceList;
  20.285 -    while (device) {
  20.286 -        SDL_numjoysticks++;
  20.287 -        device = device->pNext;
  20.288 -    }
  20.289 +	CFRunLoopAddSource(CFRunLoopGetCurrent(), 
  20.290 +					   IONotificationPortGetRunLoopSource(notificationPort), 
  20.291 +					   kCFRunLoopDefaultMode);
  20.292 +	
  20.293 +	// Register for notifications when a serial port is added to the system
  20.294 +	result = IOServiceAddMatchingNotification(notificationPort,
  20.295 +															kIOFirstMatchNotification,
  20.296 +															hidMatchDictionary,
  20.297 +															JoystickDeviceWasAddedCallback,
  20.298 +															NULL,           
  20.299 +															&portIterator);
  20.300 +	while (IOIteratorNext(portIterator)) {}; // Run out the iterator or notifications won't start (you can also use it to iterate the available devices).
  20.301  
  20.302 -    return SDL_numjoysticks;
  20.303 +    return SDL_SYS_NumJoysticks();
  20.304  }
  20.305  
  20.306  /* Function to get the device-dependent name of a joystick */
  20.307  const char *
  20.308 -SDL_SYS_JoystickName(int index)
  20.309 +SDL_SYS_JoystickNameForIndex(int index)
  20.310  {
  20.311      recDevice *device = gpDeviceList;
  20.312  
  20.313      for (; index > 0; index--)
  20.314          device = device->pNext;
  20.315  
  20.316 -    return device->product;
  20.317 +	return device->product;
  20.318  }
  20.319  
  20.320  /* Function to open a joystick for use.
  20.321 @@ -701,25 +823,77 @@
  20.322   * It returns 0, or -1 if there is an error.
  20.323   */
  20.324  int
  20.325 -SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
  20.326 +SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
  20.327  {
  20.328      recDevice *device = gpDeviceList;
  20.329      int index;
  20.330  
  20.331 -    for (index = joystick->index; index > 0; index--)
  20.332 +    for (index = device_index; index > 0; index--)
  20.333          device = device->pNext;
  20.334  
  20.335      joystick->hwdata = device;
  20.336 -    joystick->name = device->product;
  20.337 +	joystick->instance_id = device->instance_id;
  20.338 +	joystick->name = device->product;
  20.339  
  20.340 -    joystick->naxes = device->axes;
  20.341 -    joystick->nhats = device->hats;
  20.342 -    joystick->nballs = 0;
  20.343 -    joystick->nbuttons = device->buttons;
  20.344 -
  20.345 +	joystick->naxes = device->axes;
  20.346 +	joystick->nhats = device->hats;
  20.347 +	joystick->nballs = 0;
  20.348 +	joystick->nbuttons = device->buttons;
  20.349      return 0;
  20.350  }
  20.351  
  20.352 +
  20.353 +/* Function to return the instance id of the joystick at device_index
  20.354 + */
  20.355 +SDL_JoystickID
  20.356 +SDL_SYS_GetInstanceIdOfDeviceIndex( int device_index )
  20.357 +{
  20.358 +    recDevice *device = gpDeviceList;
  20.359 +    int index;
  20.360 +	
  20.361 +    for (index = device_index; index > 0; index--)
  20.362 +        device = device->pNext;
  20.363 +
  20.364 +	return device->instance_id;
  20.365 +}
  20.366 +
  20.367 +
  20.368 +/* Function to cause any queued joystick insertions to be processed
  20.369 + */
  20.370 +void
  20.371 +SDL_SYS_JoystickDetect()
  20.372 +{
  20.373 +	if ( s_bDeviceAdded )
  20.374 +	{
  20.375 +		recDevice *device = gpDeviceList;
  20.376 +		s_bDeviceAdded = 0;
  20.377 +		int device_index = 0;
  20.378 +		// send notifications
  20.379 +		while ( device )
  20.380 +		{
  20.381 +			if ( device->send_open_event )
  20.382 +			{
  20.383 +				device->send_open_event = 0;
  20.384 +#if !SDL_EVENTS_DISABLED
  20.385 +				SDL_Event event;
  20.386 +				event.type = SDL_JOYDEVICEADDED;
  20.387 +				
  20.388 +				if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  20.389 +					event.jdevice.which = device_index;
  20.390 +					if ((SDL_EventOK == NULL)
  20.391 +						|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
  20.392 +						SDL_PushEvent(&event);
  20.393 +					}
  20.394 +				}
  20.395 +#endif /* !SDL_EVENTS_DISABLED */
  20.396 +			}
  20.397 +			device_index++;
  20.398 +			device = device->pNext;
  20.399 +		}
  20.400 +	}
  20.401 +}
  20.402 +
  20.403 +
  20.404  /* Function to update the state of a joystick - called as a device poll.
  20.405   * This function shouldn't update the joystick structure directly,
  20.406   * but instead should call SDL_PrivateJoystick*() to deliver events
  20.407 @@ -728,26 +902,49 @@
  20.408  void
  20.409  SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
  20.410  {
  20.411 -    recDevice *device = joystick->hwdata;
  20.412 +	recDevice *device = joystick->hwdata;
  20.413      recElement *element;
  20.414      SInt32 value, range;
  20.415      int i;
  20.416  
  20.417 +	if ( !device )
  20.418 +		return;
  20.419 +
  20.420      if (device->removed) {      /* device was unplugged; ignore it. */
  20.421 -        if (device->uncentered) {
  20.422 -            device->uncentered = 0;
  20.423 +		recDevice *devicelist = gpDeviceList;
  20.424 +		joystick->closed = 1;
  20.425 +		joystick->uncentered = 1;
  20.426 +		
  20.427 +		if ( devicelist == device )
  20.428 +		{
  20.429 +			gpDeviceList = device->pNext;
  20.430 +		}
  20.431 +		else
  20.432 +		{
  20.433 +			while ( devicelist->pNext != device )
  20.434 +			{
  20.435 +				devicelist = devicelist->pNext;
  20.436 +			}
  20.437 +			
  20.438 +			devicelist->pNext = device->pNext;
  20.439 +		}
  20.440 +		
  20.441 +		DisposePtr((Ptr) device);
  20.442 +		joystick->hwdata = NULL;
  20.443  
  20.444 -            /* Tell the app that everything is centered/unpressed... */
  20.445 -            for (i = 0; i < device->axes; i++)
  20.446 -                SDL_PrivateJoystickAxis(joystick, i, 0);
  20.447 -
  20.448 -            for (i = 0; i < device->buttons; i++)
  20.449 -                SDL_PrivateJoystickButton(joystick, i, 0);
  20.450 -
  20.451 -            for (i = 0; i < device->hats; i++)
  20.452 -                SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
  20.453 -        }
  20.454 -
  20.455 +#if !SDL_EVENTS_DISABLED
  20.456 +		SDL_Event event;
  20.457 +		event.type = SDL_JOYDEVICEREMOVED;
  20.458 +		
  20.459 +		if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  20.460 +			event.jdevice.which = joystick->instance_id;
  20.461 +			if ((SDL_EventOK == NULL)
  20.462 +				|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
  20.463 +				SDL_PushEvent(&event);
  20.464 +			}
  20.465 +		}
  20.466 +#endif /* !SDL_EVENTS_DISABLED */
  20.467 +		
  20.468          return;
  20.469      }
  20.470  
  20.471 @@ -826,12 +1023,33 @@
  20.472      return;
  20.473  }
  20.474  
  20.475 +
  20.476 +/* Function to query if the joystick is currently attached
  20.477 + *   It returns 1 if attached, 0 otherwise.
  20.478 + */
  20.479 +int
  20.480 +SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
  20.481 +{
  20.482 +	recDevice *device = gpDeviceList;
  20.483 +    int index;
  20.484 +	
  20.485 +	while ( device )
  20.486 +	{
  20.487 +		if ( joystick->instance_id == device->instance_id )
  20.488 +			return (1);
  20.489 +		
  20.490 +        device = device->pNext;
  20.491 +	}
  20.492 +	
  20.493 +	return 0;
  20.494 +}
  20.495 +
  20.496 +
  20.497  /* Function to close a joystick after use */
  20.498  void
  20.499  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
  20.500 -{
  20.501 -    /* Should we do anything here? */
  20.502 -    return;
  20.503 +{	
  20.504 +	joystick->closed = 1;
  20.505  }
  20.506  
  20.507  /* Function to perform any system-specific joystick related cleanup */
  20.508 @@ -840,6 +1058,51 @@
  20.509  {
  20.510      while (NULL != gpDeviceList)
  20.511          gpDeviceList = HIDDisposeDevice(&gpDeviceList);
  20.512 +	
  20.513 +	if ( notificationPort )
  20.514 +	{
  20.515 +		IONotificationPortDestroy( notificationPort );
  20.516 +		notificationPort = 0;
  20.517 +	}
  20.518 +}
  20.519 +
  20.520 +
  20.521 +/* Function to return the number of joystick devices plugged in right now*/
  20.522 +int
  20.523 +SDL_SYS_NumJoysticks()
  20.524 +{
  20.525 +	recDevice *device = gpDeviceList;
  20.526 +    int nJoySticks = 0;
  20.527 +	
  20.528 +	while ( device )
  20.529 +	{
  20.530 +		nJoySticks++;
  20.531 +        device = device->pNext;
  20.532 +	}
  20.533 +
  20.534 +	return nJoySticks;
  20.535 +}
  20.536 +
  20.537 +int
  20.538 +SDL_SYS_JoystickNeedsPolling()
  20.539 +{
  20.540 +	return s_bDeviceAdded;
  20.541 +}
  20.542 +
  20.543 +JoystickGUID SDL_SYS_PrivateJoystickGetDeviceID( int device_index )
  20.544 +{
  20.545 +    recDevice *device = gpDeviceList;
  20.546 +    int index;
  20.547 +	
  20.548 +    for (index = device_index; index > 0; index--)
  20.549 +        device = device->pNext;
  20.550 +	
  20.551 +	return device->guid;	
  20.552 +}
  20.553 +
  20.554 +JoystickGUID SDL_SYS_PrivateJoystickGetGUID(SDL_Joystick *joystick)
  20.555 +{
  20.556 +	return joystick->hwdata->guid;
  20.557  }
  20.558  
  20.559  #endif /* SDL_JOYSTICK_IOKIT */
    21.1 --- a/src/joystick/darwin/SDL_sysjoystick_c.h	Mon Nov 26 14:59:07 2012 -0800
    21.2 +++ b/src/joystick/darwin/SDL_sysjoystick_c.h	Mon Nov 26 16:37:54 2012 -0800
    21.3 @@ -25,6 +25,7 @@
    21.4  
    21.5  #include <IOKit/hid/IOHIDLib.h>
    21.6  #include <IOKit/hid/IOHIDKeys.h>
    21.7 +#include <IOKit/IOKitLib.h>
    21.8  
    21.9  
   21.10  struct recElement
   21.11 @@ -58,7 +59,9 @@
   21.12  {
   21.13      io_service_t ffservice;     /* Interface for force feedback, 0 = no ff */
   21.14      IOHIDDeviceInterface **interface;   /* interface to device, NULL = no interface */
   21.15 -
   21.16 +	IONotificationPortRef notificationPort; /* port to be notified on joystick removal */
   21.17 +	io_iterator_t portIterator; /* iterator for removal callback */
   21.18 +	
   21.19      char product[256];          /* name of product */
   21.20      long usage;                 /* usage page from IOUSBHID Parser.h which defines general usage */
   21.21      long usagePage;             /* usage within above page from IOUSBHID Parser.h which defines specific usage */
   21.22 @@ -74,6 +77,10 @@
   21.23  
   21.24      int removed;
   21.25      int uncentered;
   21.26 +	
   21.27 +	int instance_id;
   21.28 +	JoystickGUID guid;
   21.29 +	Uint8 send_open_event;		/* 1 if we need to send an Added event for this device */
   21.30  
   21.31      struct joystick_hwdata *pNext;      /* next device */
   21.32  };
    22.1 --- a/src/joystick/linux/SDL_sysjoystick.c	Mon Nov 26 14:59:07 2012 -0800
    22.2 +++ b/src/joystick/linux/SDL_sysjoystick.c	Mon Nov 26 16:37:54 2012 -0800
    22.3 @@ -298,7 +298,7 @@
    22.4      ret = 0;
    22.5  
    22.6      for (i = 0; i < max; i++) {
    22.7 -        name = SDL_SYS_JoystickName(i);
    22.8 +        name = SDL_SYS_JoystickNameForIndex(i);
    22.9  
   22.10          fd = open(SDL_joylist[i].fname, O_RDONLY, 0);
   22.11          if (fd >= 0) {
   22.12 @@ -390,6 +390,8 @@
   22.13  
   22.14  #endif /* SDL_INPUT_LINUXEV */
   22.15  
   22.16 +int SDL_SYS_numjoysticks = 0;
   22.17 +
   22.18  /* Function to scan the system for joysticks */
   22.19  int
   22.20  SDL_SYS_JoystickInit(void)
   22.21 @@ -491,7 +493,7 @@
   22.22             will be duplicates but without extra information about their
   22.23             hats or balls. Unfortunately, the event devices can't
   22.24             currently be calibrated, so it's a win-lose situation.
   22.25 -           So : /dev/input/eventX = /dev/input/jsY = /dev/jsY
   22.26 +           So : /dev/input/eventX = /dev/input/jsY = /dev/js
   22.27           */
   22.28          if ((i == 0) && (numjoysticks > 0))
   22.29              break;
   22.30 @@ -501,12 +503,13 @@
   22.31      numjoysticks += CountLogicalJoysticks(numjoysticks);
   22.32  #endif
   22.33  
   22.34 +    SDL_SYS_numjoysticks = numjoysticks;
   22.35      return (numjoysticks);
   22.36  }
   22.37  
   22.38  /* Function to get the device-dependent name of a joystick */
   22.39  const char *
   22.40 -SDL_SYS_JoystickName(int index)
   22.41 +SDL_SYS_JoystickNameForIndex(int index)
   22.42  {
   22.43      int fd;
   22.44      static char namebuf[128];
   22.45 @@ -601,7 +604,7 @@
   22.46          joystick->nbuttons = n;
   22.47      }
   22.48  
   22.49 -    name = SDL_SYS_JoystickName(joystick->index);
   22.50 +    name = SDL_SYS_JoystickNameForIndex(joystick->instance_id);
   22.51  
   22.52      /* Generic analog joystick support */
   22.53      if (SDL_strstr(name, "Analog") == name && SDL_strstr(name, "-hat")) {
   22.54 @@ -774,8 +777,8 @@
   22.55  {
   22.56      struct joystick_logical_layout *layout;
   22.57  
   22.58 -    layout = SDL_joylist[joystick->index].map->layout +
   22.59 -        SDL_joylist[joystick->index].logicalno;
   22.60 +    layout = SDL_joylist[joystick->instance_id].map->layout +
   22.61 +        SDL_joylist[joystick->instance_id].logicalno;
   22.62  
   22.63      joystick->nbuttons = layout->nbuttons;
   22.64      joystick->nhats = layout->nhats;
   22.65 @@ -791,7 +794,7 @@
   22.66     It returns 0, or -1 if there is an error.
   22.67   */
   22.68  int
   22.69 -SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
   22.70 +SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
   22.71  {
   22.72      int fd;
   22.73      char *fname;
   22.74 @@ -800,8 +803,8 @@
   22.75  
   22.76      /* Open the joystick and set the joystick file descriptor */
   22.77  #ifndef NO_LOGICAL_JOYSTICKS
   22.78 -    if (SDL_joylist[joystick->index].fname == NULL) {
   22.79 -        SDL_joylist_head(realindex, joystick->index);
   22.80 +    if (SDL_joylist[joystick->instance_id].fname == NULL) {
   22.81 +        SDL_joylist_head(realindex, joystick->instance_id);
   22.82          realjoy = SDL_JoystickOpen(realindex);
   22.83  
   22.84          if (realjoy == NULL)
   22.85 @@ -811,17 +814,17 @@
   22.86          fname = realjoy->hwdata->fname;
   22.87  
   22.88      } else {
   22.89 -        fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
   22.90 -        fname = SDL_joylist[joystick->index].fname;
   22.91 +        fd = open(SDL_joylist[joystick->instance_id].fname, O_RDONLY, 0);
   22.92 +        fname = SDL_joylist[joystick->instance_id].fname;
   22.93      }
   22.94 -    SDL_joylist[joystick->index].joy = joystick;
   22.95 +    SDL_joylist[joystick->instance_id].joy = joystick;
   22.96  #else
   22.97 -    fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
   22.98 -    fname = SDL_joylist[joystick->index].fname;
   22.99 +    fd = open(SDL_joylist[joystick->instance_id].fname, O_RDONLY, 0);
  22.100 +    fname = SDL_joylist[joystick->instance_id].fname;
  22.101  #endif
  22.102  
  22.103      if (fd < 0) {
  22.104 -        SDL_SetError("Unable to open %s\n", SDL_joylist[joystick->index]);
  22.105 +        SDL_SetError("Unable to open %s\n", SDL_joylist[joystick->instance_id]);
  22.106          return (-1);
  22.107      }
  22.108      joystick->hwdata = (struct joystick_hwdata *)
  22.109 @@ -834,6 +837,7 @@
  22.110      SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
  22.111      joystick->hwdata->fd = fd;
  22.112      joystick->hwdata->fname = fname;
  22.113 +    joystick->instance_id = device_index;
  22.114  
  22.115      /* Set the joystick to non-blocking read mode */
  22.116      fcntl(fd, F_SETFL, O_NONBLOCK);
  22.117 @@ -861,7 +865,7 @@
  22.118      SDL_Joystick *logicaljoy;
  22.119      register int i;
  22.120  
  22.121 -    i = joystick->index;
  22.122 +    i = joystick->instance_id;
  22.123      logicaljoy = NULL;
  22.124  
  22.125      /* get the fake joystick that will receive the event
  22.126 @@ -891,12 +895,12 @@
  22.127  
  22.128      /* if there's no map then this is just a regular joystick
  22.129       */
  22.130 -    if (SDL_joylist[joystick->index].map == NULL)
  22.131 +    if (SDL_joylist[joystick->instance_id].map == NULL)
  22.132          return 0;
  22.133  
  22.134      /* get the logical joystick that will receive the event
  22.135       */
  22.136 -    buttons = SDL_joylist[joystick->index].map->buttonmap + button;
  22.137 +    buttons = SDL_joylist[joystick->instance_id].map->buttonmap + button;
  22.138      logicaljoy = FindLogicalJoystick(joystick, buttons);
  22.139  
  22.140      if (logicaljoy == NULL)
  22.141 @@ -915,12 +919,12 @@
  22.142  
  22.143      /* if there's no map then this is just a regular joystick
  22.144       */
  22.145 -    if (SDL_joylist[joystick->index].map == NULL)
  22.146 +    if (SDL_joylist[joystick->instance_id].map == NULL)
  22.147          return 0;
  22.148  
  22.149      /* get the logical joystick that will receive the event
  22.150       */
  22.151 -    axes = SDL_joylist[joystick->index].map->axismap + axis;
  22.152 +    axes = SDL_joylist[joystick->instance_id].map->axismap + axis;
  22.153      logicaljoy = FindLogicalJoystick(joystick, axes);
  22.154  
  22.155      if (logicaljoy == NULL)
  22.156 @@ -958,11 +962,11 @@
  22.157  #ifndef NO_LOGICAL_JOYSTICKS
  22.158          /* if there's no map then this is just a regular joystick
  22.159           */
  22.160 -        if (SDL_joylist[stick->index].map != NULL) {
  22.161 +        if (SDL_joylist[stick->instance_id].map != NULL) {
  22.162  
  22.163              /* get the fake joystick that will receive the event
  22.164               */
  22.165 -            hats = SDL_joylist[stick->index].map->hatmap + hat;
  22.166 +            hats = SDL_joylist[stick->instance_id].map->hatmap + hat;
  22.167              logicaljoy = FindLogicalJoystick(stick, hats);
  22.168          }
  22.169  
  22.170 @@ -997,8 +1001,8 @@
  22.171      Uint8 other_axis;
  22.172  
  22.173  #ifndef NO_LOGICAL_JOYSTICKS
  22.174 -    if (SDL_joylist[joystick->index].fname == NULL) {
  22.175 -        SDL_joylist_head(i, joystick->index);
  22.176 +    if (SDL_joylist[joystick->instance_id].fname == NULL) {
  22.177 +        SDL_joylist_head(i, joystick->instance_id);
  22.178          JS_HandleEvents(SDL_joylist[i].joy);
  22.179          return;
  22.180      }
  22.181 @@ -1089,8 +1093,8 @@
  22.182      int code;
  22.183  
  22.184  #ifndef NO_LOGICAL_JOYSTICKS
  22.185 -    if (SDL_joylist[joystick->index].fname == NULL) {
  22.186 -        SDL_joylist_head(i, joystick->index);
  22.187 +    if (SDL_joylist[joystick->instance_id].fname == NULL) {
  22.188 +        SDL_joylist_head(i, joystick->instance_id);
  22.189          return EV_HandleEvents(SDL_joylist[i].joy);
  22.190      }
  22.191  #endif
  22.192 @@ -1198,15 +1202,15 @@
  22.193  {
  22.194  #ifndef NO_LOGICAL_JOYSTICKS
  22.195      register int i;
  22.196 -    if (SDL_joylist[joystick->index].fname == NULL) {
  22.197 -        SDL_joylist_head(i, joystick->index);
  22.198 +    if (SDL_joylist[joystick->instance_id].fname == NULL) {
  22.199 +        SDL_joylist_head(i, joystick->instance_id);
  22.200          SDL_JoystickClose(SDL_joylist[i].joy);
  22.201      }
  22.202  #endif
  22.203  
  22.204      if (joystick->hwdata) {
  22.205  #ifndef NO_LOGICAL_JOYSTICKS
  22.206 -        if (SDL_joylist[joystick->index].fname != NULL)
  22.207 +        if (SDL_joylist[joystick->instance_id].fname != NULL)
  22.208  #endif
  22.209              close(joystick->hwdata->fd);
  22.210          if (joystick->hwdata->hats) {
  22.211 @@ -1218,6 +1222,7 @@
  22.212          SDL_free(joystick->hwdata);
  22.213          joystick->hwdata = NULL;
  22.214      }
  22.215 +    joystick->closed = 1;
  22.216  }
  22.217  
  22.218  /* Function to perform any system-specific joystick related cleanup */
  22.219 @@ -1234,5 +1239,50 @@
  22.220      }
  22.221  }
  22.222  
  22.223 +/* Function to perform the mapping from device index to the instance id for this index */
  22.224 +SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int index)
  22.225 +{
  22.226 +    return index;
  22.227 +}
  22.228 +
  22.229 +/* Function to determine is this joystick is attached to the system right now */
  22.230 +int SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
  22.231 +{
  22.232 +    return joystick->closed;
  22.233 +}
  22.234 +
  22.235 +int SDL_SYS_NumJoysticks()
  22.236 +{
  22.237 +    return SDL_SYS_numjoysticks;
  22.238 +}
  22.239 +
  22.240 +int SDL_SYS_JoystickNeedsPolling()
  22.241 +{
  22.242 +    return 0;
  22.243 +}
  22.244 +
  22.245 +void SDL_SYS_JoystickDetect()
  22.246 +{
  22.247 +}
  22.248 +
  22.249 +JoystickGUID SDL_SYS_PrivateJoystickGetDeviceID( int device_index )
  22.250 +{
  22.251 +    static JoystickGUID guid;
  22.252 +    // the GUID is just the first 16 chars of the name for now
  22.253 +    const char *name = SDL_SYS_JoystickNameForIndex( device_index );
  22.254 +    SDL_memcpy( &guid, name, sizeof(guid) );
  22.255 +    return guid;
  22.256 +}
  22.257 +
  22.258 +
  22.259 +JoystickGUID SDL_SYS_PrivateJoystickGetGUID(SDL_Joystick * joystick)
  22.260 +{
  22.261 +    static JoystickGUID guid;
  22.262 +    // the GUID is just the first 16 chars of the name for now
  22.263 +    const char *name = SDL_SYS_JoystickNameForIndex( joystick->name );
  22.264 +    SDL_memcpy( &guid, name, sizeof(guid) );
  22.265 +    return guid;
  22.266 +}
  22.267 +
  22.268  #endif /* SDL_JOYSTICK_LINUX */
  22.269  /* vi: set ts=4 sw=4 expandtab: */
    23.1 --- a/src/joystick/windows/SDL_dxjoystick.c	Mon Nov 26 14:59:07 2012 -0800
    23.2 +++ b/src/joystick/windows/SDL_dxjoystick.c	Mon Nov 26 16:37:54 2012 -0800
    23.3 @@ -29,17 +29,22 @@
    23.4   * doesn't use them and I don't own any joysticks with them. 
    23.5   *
    23.6   * We don't bother to use event notification here.  It doesn't seem to work
    23.7 - * with polled devices, and it's fine to call IDirectInputDevice2_GetDeviceData and
    23.8 + * with polled devices, and it's fine to call IDirectInputDevice8_GetDeviceData and
    23.9   * let it return 0 events. */
   23.10  
   23.11  #include "SDL_error.h"
   23.12  #include "SDL_events.h"
   23.13  #include "SDL_joystick.h"
   23.14  #include "../SDL_sysjoystick.h"
   23.15 -#include "../SDL_joystick_c.h"
   23.16  #define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
   23.17  #include "SDL_dxjoystick_c.h"
   23.18 -
   23.19 +#include "SDL_thread.h"
   23.20 +#include "SDL_timer.h"
   23.21 +#include "SDL_mutex.h"
   23.22 +#include "SDL_events.h"
   23.23 +#if !SDL_EVENTS_DISABLED
   23.24 +#include "../../events/SDL_events_c.h"
   23.25 +#endif
   23.26  
   23.27  #ifndef DIDFT_OPTIONAL
   23.28  #define DIDFT_OPTIONAL		0x80000000
   23.29 @@ -47,7 +52,7 @@
   23.30  
   23.31  
   23.32  #define INPUT_QSIZE	32      /* Buffer up to 32 input messages */
   23.33 -#define MAX_JOYSTICKS	8
   23.34 +#define MAX_JOYSTICKS 8
   23.35  #define AXIS_MIN	-32768  /* minimum value for axis coordinate */
   23.36  #define AXIS_MAX	32767   /* maximum value for axis coordinate */
   23.37  #define JOY_AXIS_THRESHOLD	(((AXIS_MAX)-(AXIS_MIN))/100)   /* 1% motion */
   23.38 @@ -59,14 +64,65 @@
   23.39  /* local variables */
   23.40  static SDL_bool coinitialized = SDL_FALSE;
   23.41  static LPDIRECTINPUT dinput = NULL;
   23.42 +static SDL_bool s_bDeviceAdded = SDL_FALSE;
   23.43 +static SDL_bool s_bDeviceRemoved = SDL_FALSE;
   23.44 +static int s_nInstanceID = -1;
   23.45 +static GUID *s_pKnownJoystickGUIDs = NULL;
   23.46 +static SDL_cond *s_condJoystickThread = NULL;
   23.47 +static SDL_mutex *s_mutexJoyStickEnum = NULL;
   23.48 +static SDL_Thread *s_threadJoystick = NULL;
   23.49 +static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
   23.50 +static HANDLE s_pXInputDLL = 0;
   23.51 +
   23.52  extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
   23.53                                         LPDIRECTINPUT * ppDI,
   23.54                                         LPUNKNOWN punkOuter);
   23.55 -static DIDEVICEINSTANCE SYS_Joystick[MAX_JOYSTICKS];    /* array to hold joystick ID values */
   23.56 -static char *SYS_JoystickNames[MAX_JOYSTICKS];
   23.57 -static int SYS_NumJoysticks;
   23.58 +struct JoyStick_DeviceData_
   23.59 +{
   23.60 +	JoystickGUID guid;
   23.61 +	DIDEVICEINSTANCE dxdevice;
   23.62 +	char *joystickname;
   23.63 +	Uint8 send_add_event;
   23.64 +	int nInstanceID;
   23.65 +	Uint8 bXInputDevice;
   23.66 +	Uint8 XInputUserId;
   23.67 +	struct JoyStick_DeviceData_ *pNext;
   23.68 +};
   23.69  
   23.70  
   23.71 +/* Forward decl's for XInput API's we load dynamically and use if available */
   23.72 +typedef DWORD (WINAPI *XInputGetState_t)
   23.73 +	(
   23.74 +	DWORD         dwUserIndex,  // [in] Index of the gamer associated with the device
   23.75 +	XINPUT_STATE_EX* pState        // [out] Receives the current state
   23.76 +	);
   23.77 +
   23.78 +typedef DWORD (WINAPI *XInputSetState_t)
   23.79 +	(
   23.80 +	DWORD             dwUserIndex,  // [in] Index of the gamer associated with the device
   23.81 +	XINPUT_VIBRATION* pVibration    // [in, out] The vibration information to send to the controller
   23.82 +	);
   23.83 +
   23.84 +typedef DWORD (WINAPI *XInputGetCapabilities_t)
   23.85 +	(
   23.86 +	DWORD                dwUserIndex,   // [in] Index of the gamer associated with the device
   23.87 +	DWORD                dwFlags,       // [in] Input flags that identify the device type
   23.88 +	XINPUT_CAPABILITIES* pCapabilities  // [out] Receives the capabilities
   23.89 +	);
   23.90 +
   23.91 +XInputGetState_t PC_XInputGetState;
   23.92 +XInputSetState_t PC_XInputSetState;
   23.93 +XInputGetCapabilities_t PC_XInputGetCapabilities;
   23.94 +
   23.95 +#define XINPUTGETSTATE			PC_XInputGetState
   23.96 +#define XINPUTSETSTATE			PC_XInputSetState
   23.97 +#define XINPUTGETCAPABILITIES	PC_XInputGetCapabilities
   23.98 +#define INVALID_XINPUT_USERID 255
   23.99 +
  23.100 +typedef struct JoyStick_DeviceData_ JoyStick_DeviceData;
  23.101 +
  23.102 +static JoyStick_DeviceData *SYS_Joystick;    /* array to hold joystick ID values */
  23.103 +
  23.104  /* local prototypes */
  23.105  static void SetDIerror(const char *function, HRESULT code);
  23.106  static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE *
  23.107 @@ -82,7 +138,7 @@
  23.108  static int SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick,
  23.109                                           Uint8 button, Uint8 state);
  23.110  
  23.111 -/* Taken from Wine - Thanks! */
  23.112 +// Taken from Wine - Thanks! 
  23.113  DIOBJECTDATAFORMAT dfDIJoystick2[] = {
  23.114    { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
  23.115    { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
  23.116 @@ -272,6 +328,270 @@
  23.117  }
  23.118  
  23.119  
  23.120 +#define SAFE_RELEASE(p)                             \
  23.121 +{                                                   \
  23.122 +	if (p) {                                        \
  23.123 +	(p)->lpVtbl->Release((p));                  \
  23.124 +	(p) = 0;                                    \
  23.125 +	}                                               \
  23.126 +}
  23.127 +
  23.128 +
  23.129 +DEFINE_GUID(CLSID_WbemLocator,   0x4590f811,0x1d3a,0x11d0,0x89,0x1F,0x00,0xaa,0x00,0x4b,0x2e,0x24);
  23.130 +DEFINE_GUID(IID_IWbemLocator,    0xdc12a687,0x737f,0x11cf,0x88,0x4d,0x00,0xaa,0x00,0x4b,0x2e,0x24);
  23.131 +
  23.132 +//-----------------------------------------------------------------------------
  23.133 +//
  23.134 +// code from MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014(v=vs.85).aspx
  23.135 +//
  23.136 +// Enum each PNP device using WMI and check each device ID to see if it contains 
  23.137 +// "IG_" (ex. "VID_045E&PID_028E&IG_00").  If it does, then it's an XInput device
  23.138 +// Unfortunately this information can not be found by just using DirectInput 
  23.139 +//-----------------------------------------------------------------------------
  23.140 +BOOL IsXInputDevice( const GUID* pGuidProductFromDirectInput )
  23.141 +{
  23.142 +	IWbemLocator*           pIWbemLocator  = NULL;
  23.143 +	IEnumWbemClassObject*   pEnumDevices   = NULL;
  23.144 +	IWbemClassObject*       pDevices[20];
  23.145 +	IWbemServices*          pIWbemServices = NULL;
  23.146 +	DWORD                   uReturned      = 0;
  23.147 +	BSTR                    bstrNamespace  = NULL;
  23.148 +	BSTR                    bstrDeviceID   = NULL;
  23.149 +	BSTR                    bstrClassName  = NULL;
  23.150 +	SDL_bool                bIsXinputDevice= SDL_FALSE;
  23.151 +	UINT                    iDevice        = 0;
  23.152 +	VARIANT                 var;
  23.153 +	HRESULT                 hr;
  23.154 +	DWORD bCleanupCOM;
  23.155 +
  23.156 +	SDL_memset( pDevices, 0x0, sizeof(pDevices) );
  23.157 +
  23.158 +	// CoInit if needed
  23.159 +	hr = CoInitialize(NULL);
  23.160 +	bCleanupCOM = SUCCEEDED(hr);
  23.161 +
  23.162 +	// Create WMI
  23.163 +	hr = CoCreateInstance( &CLSID_WbemLocator,
  23.164 +		NULL,
  23.165 +		CLSCTX_INPROC_SERVER,
  23.166 +		&IID_IWbemLocator,
  23.167 +		(LPVOID*) &pIWbemLocator);
  23.168 +	if( FAILED(hr) || pIWbemLocator == NULL )
  23.169 +		goto LCleanup;
  23.170 +
  23.171 +	bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );if( bstrNamespace == NULL ) goto LCleanup;        
  23.172 +	bstrClassName = SysAllocString( L"Win32_PNPEntity" );   if( bstrClassName == NULL ) goto LCleanup;        
  23.173 +	bstrDeviceID  = SysAllocString( L"DeviceID" );          if( bstrDeviceID == NULL )  goto LCleanup;        
  23.174 +	
  23.175 +	// Connect to WMI 
  23.176 +	hr = IWbemLocator_ConnectServer( pIWbemLocator, bstrNamespace, NULL, NULL, 0L, 
  23.177 +		0L, NULL, NULL, &pIWbemServices );
  23.178 +	if( FAILED(hr) || pIWbemServices == NULL )
  23.179 +		goto LCleanup;
  23.180 +
  23.181 +	// Switch security level to IMPERSONATE. 
  23.182 +	CoSetProxyBlanket( (IUnknown *)pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, 
  23.183 +		RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );                    
  23.184 +
  23.185 +	hr = IWbemServices_CreateInstanceEnum( pIWbemServices, bstrClassName, 0, NULL, &pEnumDevices ); 
  23.186 +	if( FAILED(hr) || pEnumDevices == NULL )
  23.187 +		goto LCleanup;
  23.188 +
  23.189 +	// Loop over all devices
  23.190 +	for( ;; )
  23.191 +	{
  23.192 +		// Get 20 at a time
  23.193 +		hr = IEnumWbemClassObject_Next( pEnumDevices, 10000, 20, pDevices, &uReturned );
  23.194 +		if( FAILED(hr) )
  23.195 +			goto LCleanup;
  23.196 +		if( uReturned == 0 )
  23.197 +			break;
  23.198 +
  23.199 +		for( iDevice=0; iDevice<uReturned; iDevice++ )
  23.200 +		{
  23.201 +			// For each device, get its device ID
  23.202 +			hr = IWbemClassObject_Get( pDevices[iDevice], bstrDeviceID, 0L, &var, NULL, NULL );
  23.203 +			if(  SUCCEEDED( hr ) && var.vt == VT_BSTR && var.bstrVal != NULL )
  23.204 +			{
  23.205 +				// Check if the device ID contains "IG_".  If it does, then it's an XInput device
  23.206 +				// This information can not be found from DirectInput 
  23.207 +				char *pDeviceString = WIN_StringToUTF8( var.bstrVal );
  23.208 +				if( SDL_strstr( pDeviceString, "IG_" ) )
  23.209 +				{
  23.210 +					// If it does, then get the VID/PID from var.bstrVal
  23.211 +					long dwPid = 0, dwVid = 0;
  23.212 +					char * strPid = NULL;
  23.213 +					DWORD dwVidPid = 0;
  23.214 +					char * strVid = SDL_strstr( pDeviceString, "VID_" );
  23.215 +					if( strVid )
  23.216 +					{
  23.217 +						dwVid = SDL_strtol( strVid + 4, NULL, 16 );
  23.218 +					}
  23.219 +					strPid = SDL_strstr( pDeviceString, "PID_" );
  23.220 +					if( strPid  )
  23.221 +					{
  23.222 +						dwPid = SDL_strtol( strPid + 4, NULL, 16 );
  23.223 +					}
  23.224 +
  23.225 +					// Compare the VID/PID to the DInput device
  23.226 +					dwVidPid = MAKELONG( dwVid, dwPid );
  23.227 +					if( dwVidPid == pGuidProductFromDirectInput->Data1 )
  23.228 +					{
  23.229 +						bIsXinputDevice = SDL_TRUE;
  23.230 +					}
  23.231 +				}
  23.232 +				if ( pDeviceString )
  23.233 +					SDL_free( pDeviceString );
  23.234 +
  23.235 +				if ( bIsXinputDevice )
  23.236 +					break;
  23.237 +			}   
  23.238 +			SAFE_RELEASE( pDevices[iDevice] );
  23.239 +		}
  23.240 +	}
  23.241 +	
  23.242 +LCleanup:
  23.243 +
  23.244 +	for( iDevice=0; iDevice<20; iDevice++ )
  23.245 +		SAFE_RELEASE( pDevices[iDevice] );
  23.246 +	SAFE_RELEASE( pEnumDevices );
  23.247 +	SAFE_RELEASE( pIWbemLocator );
  23.248 +	SAFE_RELEASE( pIWbemServices );
  23.249 +
  23.250 +	if ( bstrNamespace )
  23.251 +		SysFreeString( bstrNamespace );
  23.252 +	if ( bstrClassName )
  23.253 +		SysFreeString( bstrClassName );
  23.254 +	if ( bstrDeviceID )
  23.255 +		SysFreeString( bstrDeviceID );
  23.256 +
  23.257 +	if( bCleanupCOM )
  23.258 +		CoUninitialize();
  23.259 +		
  23.260 +	return bIsXinputDevice;
  23.261 +}
  23.262 +
  23.263 +
  23.264 +static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
  23.265 +
  23.266 +/* windowproc for our joystick detect thread message only window, to detect any usb device addition/removal
  23.267 + */
  23.268 +LRESULT CALLBACK SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)    {
  23.269 +	switch (message)    {
  23.270 +	case WM_DEVICECHANGE:
  23.271 +		switch (wParam) {
  23.272 +		case DBT_DEVICEARRIVAL:
  23.273 +			if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)    {
  23.274 +				s_bWindowsDeviceChanged = SDL_TRUE;
  23.275 +			}
  23.276 +			break;
  23.277 +		case DBT_DEVICEREMOVECOMPLETE:
  23.278 +			if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)    {
  23.279 +				s_bWindowsDeviceChanged = SDL_TRUE;
  23.280 +			}
  23.281 +			break;
  23.282 +		}
  23.283 +		return 0;
  23.284 +	}
  23.285 +
  23.286 +	return DefWindowProc (hwnd, message, wParam, lParam);
  23.287 +}
  23.288 +
  23.289 +
  23.290 +/*  helper func to create a hidden, message only window for the joystick detect thread
  23.291 + */
  23.292 +HWND CreateHiddenJoystickDetectWindow() {
  23.293 +	WNDCLASSEX wincl;
  23.294 +	HWND hMessageWindow = 0;
  23.295 +	SDL_memset( &wincl, 0x0, sizeof(wincl) );
  23.296 +	wincl.hInstance = GetModuleHandle( NULL );
  23.297 +	wincl.lpszClassName = L"Message";
  23.298 +	wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc;      // This function is called by windows
  23.299 +	wincl.cbSize = sizeof (WNDCLASSEX);
  23.300 +
  23.301 +	if (!RegisterClassEx (&wincl))
  23.302 +		return 0;
  23.303 +
  23.304 +	hMessageWindow = (HWND)CreateWindowEx( 0,  L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
  23.305 +	return hMessageWindow;
  23.306 +}
  23.307 +
  23.308 +DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \
  23.309 +	0xC0, 0x4F, 0xB9, 0x51, 0xED);
  23.310 +
  23.311 +/* Function/thread to scan the system for joysticks.
  23.312 + */
  23.313 +static int
  23.314 +SDL_JoystickThread(void *_data)
  23.315 +{
  23.316 +	int nDevicesLast = 0;
  23.317 +	HRESULT result = S_OK;	
  23.318 +	HWND messageWindow = 0;
  23.319 +	HDEVNOTIFY hNotify = 0;
  23.320 +	DEV_BROADCAST_DEVICEINTERFACE dbh;
  23.321 +
  23.322 +	result = WIN_CoInitialize();
  23.323 +
  23.324 +	messageWindow = CreateHiddenJoystickDetectWindow();
  23.325 +	if ( !messageWindow )
  23.326 +	{
  23.327 +		SDL_SetError("Failed to create message window for joystick autodetect.",
  23.328 +			GetLastError());
  23.329 +		return -1;
  23.330 +	}
  23.331 +
  23.332 +	SDL_memset(&dbh, 0x0, sizeof(dbh));
  23.333 +
  23.334 +	dbh.dbcc_size = sizeof(dbh);
  23.335 +	dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  23.336 +	dbh.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
  23.337 +
  23.338 +	hNotify = RegisterDeviceNotification( messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE );
  23.339 +	if ( !hNotify )
  23.340 +	{
  23.341 +		SDL_SetError("Failed to create notify device for joystick autodetect.",
  23.342 +			GetLastError());
  23.343 +		return -1;
  23.344 +	}
  23.345 +
  23.346 +	SDL_LockMutex( s_mutexJoyStickEnum );
  23.347 +	while ( s_bJoystickThreadQuit == SDL_FALSE )
  23.348 +	{
  23.349 +		MSG messages;
  23.350 +		SDL_CondWaitTimeout( s_condJoystickThread, s_mutexJoyStickEnum, 300 );
  23.351 +
  23.352 +		while ( s_bJoystickThreadQuit == SDL_FALSE && PeekMessage(&messages, messageWindow, 0, 0, PM_NOREMOVE) )
  23.353 +		{
  23.354 +			if ( GetMessage(&messages, messageWindow, 0, 0) != 0 )  {
  23.355 +				TranslateMessage(&messages);
  23.356 +				DispatchMessage(&messages);
  23.357 +			}
  23.358 +		}
  23.359 +
  23.360 +		if ( s_pKnownJoystickGUIDs && s_bWindowsDeviceChanged )
  23.361 +		{
  23.362 +			int nDevices = 0;
  23.363 +
  23.364 +			SDL_Delay( 300 ); // wait for direct input to find out about this device
  23.365 +
  23.366 +			s_bDeviceRemoved = SDL_TRUE;
  23.367 +			s_bDeviceAdded = SDL_TRUE;
  23.368 +			s_bWindowsDeviceChanged = SDL_FALSE;
  23.369 +		}
  23.370 +	}
  23.371 +	SDL_UnlockMutex( s_mutexJoyStickEnum );
  23.372 +
  23.373 +	if ( hNotify )
  23.374 +		UnregisterDeviceNotification( hNotify );
  23.375 +
  23.376 +	if ( messageWindow )
  23.377 +		DestroyWindow( messageWindow );
  23.378 +	messageWindow = 0;
  23.379 +	WIN_CoUninitialize();
  23.380 +	return 1;
  23.381 +}
  23.382 +
  23.383 +
  23.384  /* Function to scan the system for joysticks.
  23.385   * This function should set SDL_numjoysticks to the number of available
  23.386   * joysticks.  Joystick 0 should be the system default joystick.
  23.387 @@ -283,8 +603,6 @@
  23.388      HRESULT result;
  23.389      HINSTANCE instance;
  23.390  
  23.391 -    SYS_NumJoysticks = 0;
  23.392 -
  23.393      result = WIN_CoInitialize();
  23.394      if (FAILED(result)) {
  23.395          SetDIerror("CoInitialize", result);
  23.396 @@ -293,8 +611,8 @@
  23.397  
  23.398      coinitialized = SDL_TRUE;
  23.399  
  23.400 -    result = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
  23.401 -                              &IID_IDirectInput, (LPVOID)&dinput);
  23.402 +    result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
  23.403 +                              &IID_IDirectInput8, (LPVOID)&dinput);
  23.404  
  23.405      if (FAILED(result)) {
  23.406          SDL_SYS_JoystickQuit();
  23.407 @@ -310,7 +628,7 @@
  23.408                       GetLastError());
  23.409          return (-1);
  23.410      }
  23.411 -    result = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION);
  23.412 +    result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
  23.413  
  23.414      if (FAILED(result)) {
  23.415          SDL_SYS_JoystickQuit();
  23.416 @@ -318,34 +636,54 @@
  23.417          return (-1);
  23.418      }
  23.419  
  23.420 -    /* Look for joysticks, wheels, head trackers, gamepads, etc.. */
  23.421 -    result = IDirectInput_EnumDevices(dinput,
  23.422 -                                      DIDEVTYPE_JOYSTICK,
  23.423 -                                      EnumJoysticksCallback,
  23.424 -                                      NULL, DIEDFL_ATTACHEDONLY);
  23.425 +	s_mutexJoyStickEnum = SDL_CreateMutex();
  23.426 +	s_condJoystickThread = SDL_CreateCond();
  23.427 +	s_bDeviceAdded = SDL_TRUE; // force a scan of the system for joysticks this first time
  23.428 +	SDL_SYS_JoystickDetect();
  23.429  
  23.430 -    return SYS_NumJoysticks;
  23.431 -}
  23.432 +	// try to load XInput support if available
  23.433 +	s_pXInputDLL = LoadLibrary( L"XInput1_3.dll" );
  23.434 +	if ( !s_pXInputDLL )
  23.435 +		s_pXInputDLL = LoadLibrary( L"bin\\XInput1_3.dll" );
  23.436 +	if ( s_pXInputDLL )
  23.437 +	{
  23.438 +		// 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...
  23.439 +		PC_XInputGetState = (XInputGetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, (LPCSTR)100 );
  23.440 +		PC_XInputSetState = (XInputSetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputSetState" );
  23.441 +		PC_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputGetCapabilities" );
  23.442 +		if ( !PC_XInputGetState || !PC_XInputSetState || !PC_XInputGetCapabilities )
  23.443 +		{
  23.444 +			SDL_SYS_JoystickQuit();
  23.445 +			SDL_SetError("GetProcAddress() failed when loading XInput.", GetLastError());
  23.446 +			return (-1);
  23.447 +		}
  23.448 +	}
  23.449  
  23.450 -static BOOL CALLBACK
  23.451 -EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
  23.452 -{
  23.453 -    SDL_memcpy(&SYS_Joystick[SYS_NumJoysticks], pdidInstance,
  23.454 -               sizeof(DIDEVICEINSTANCE));
  23.455 -    SYS_JoystickNames[SYS_NumJoysticks] = WIN_StringToUTF8(pdidInstance->tszProductName);
  23.456 -    SYS_NumJoysticks++;
  23.457  
  23.458 -    if (SYS_NumJoysticks >= MAX_JOYSTICKS)
  23.459 -        return DIENUM_STOP;
  23.460 -
  23.461 -    return DIENUM_CONTINUE;
  23.462 +	if ( !s_threadJoystick )
  23.463 +	{
  23.464 +		s_bJoystickThreadQuit = SDL_FALSE;
  23.465 +		/* spin up the thread to detect hotplug of devices */
  23.466 +#if defined(__WIN32__) && !defined(HAVE_LIBC)
  23.467 +#undef SDL_CreateThread
  23.468 +		s_threadJoystick= SDL_CreateThread( SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL );
  23.469 +#else
  23.470 +		s_threadJoystick = SDL_CreateThread( SDL_JoystickThread, "SDL_joystick", NULL );
  23.471 +#endif
  23.472 +	}
  23.473 +	    return SDL_SYS_NumJoysticks();
  23.474  }
  23.475  
  23.476  /* Function to get the device-dependent name of a joystick */
  23.477  const char *
  23.478 -SDL_SYS_JoystickName(int index)
  23.479 +SDL_SYS_JoystickNameForIndex(int index)
  23.480  {
  23.481 -    return SYS_JoystickNames[index];
  23.482 +	JoyStick_DeviceData *device = SYS_Joystick;
  23.483 +
  23.484 +	for (; index > 0; index--)
  23.485 +		device = device->pNext;
  23.486 +
  23.487 +	return device->joystickname;
  23.488  }
  23.489  
  23.490  /* Function to open a joystick for use.
  23.491 @@ -354,17 +692,20 @@
  23.492     It returns 0, or -1 if there is an error.
  23.493   */
  23.494  int
  23.495 -SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
  23.496 +SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
  23.497  {
  23.498      HRESULT result;
  23.499      LPDIRECTINPUTDEVICE device;
  23.500      DIPROPDWORD dipdw;
  23.501 +	JoyStick_DeviceData *joystickdevice = SYS_Joystick;
  23.502 +
  23.503 +	for (; device_index > 0; device_index--)
  23.504 +		joystickdevice = joystickdevice->pNext;
  23.505  
  23.506      SDL_memset(&dipdw, 0, sizeof(DIPROPDWORD));
  23.507      dipdw.diph.dwSize = sizeof(DIPROPDWORD);
  23.508      dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  23.509  
  23.510 -
  23.511      /* allocate memory for system specific hardware data */
  23.512      joystick->hwdata =
  23.513          (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
  23.514 @@ -374,137 +715,195 @@
  23.515      }
  23.516      SDL_memset(joystick->hwdata, 0, sizeof(struct joystick_hwdata));
  23.517      joystick->hwdata->buffered = 1;
  23.518 +	joystick->hwdata->removed = 0;
  23.519 +	joystick->instance_id = joystickdevice->nInstanceID;
  23.520      joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
  23.521 +	joystick->hwdata->guid = joystickdevice->guid;
  23.522  
  23.523 -    result =
  23.524 -        IDirectInput_CreateDevice(dinput,
  23.525 -                                  &SYS_Joystick[joystick->index].
  23.526 -                                  guidInstance, &device, NULL);
  23.527 -    if (FAILED(result)) {
  23.528 -        SetDIerror("IDirectInput::CreateDevice", result);
  23.529 -        return (-1);
  23.530 -    }
  23.531 +	if ( joystickdevice->bXInputDevice )
  23.532 +	{
  23.533 +		XINPUT_CAPABILITIES	capabilities;
  23.534 +		Uint8 userId = 0;
  23.535 +		DWORD result;
  23.536 +		JoyStick_DeviceData *joysticklist = SYS_Joystick;
  23.537 +		// scan the opened joysticks and pick the next free xinput userid for this one
  23.538 +		for( ; joysticklist; joysticklist = joysticklist->pNext)
  23.539 +		{
  23.540 +			if ( joysticklist->bXInputDevice && joysticklist->XInputUserId == userId )
  23.541 +				userId++;
  23.542 +		}
  23.543  
  23.544 -    /* Now get the IDirectInputDevice2 interface, instead. */
  23.545 -    result = IDirectInputDevice_QueryInterface(device,
  23.546 -                                               &IID_IDirectInputDevice2,
  23.547 -                                               (LPVOID *) & joystick->
  23.548 -                                               hwdata->InputDevice);
  23.549 -    /* We are done with this object.  Use the stored one from now on. */
  23.550 -    IDirectInputDevice_Release(device);
  23.551 +		if ( XINPUTGETCAPABILITIES )
  23.552 +		{
  23.553 +			result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
  23.554 +			if ( result == ERROR_SUCCESS )
  23.555 +			{
  23.556 +				SDL_bool bIsSupported = SDL_FALSE;
  23.557 +				// Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad.
  23.558 +				bIsSupported = ( capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD );
  23.559  
  23.560 -    if (FAILED(result)) {
  23.561 -        SetDIerror("IDirectInputDevice::QueryInterface", result);
  23.562 -        return (-1);
  23.563 -    }
  23.564 +				if ( !bIsSupported )
  23.565 +				{
  23.566 +					joystickdevice->bXInputDevice = SDL_FALSE;
  23.567 +				}
  23.568 +				else
  23.569 +				{
  23.570 +					// valid
  23.571 +					joystick->hwdata->bXInputDevice = SDL_TRUE;
  23.572 +					SDL_memset( joystick->hwdata->XInputState, 0x0, sizeof(joystick->hwdata->XInputState) );
  23.573 +					joystickdevice->XInputUserId = userId;
  23.574 +					joystick->hwdata->userid = userId;
  23.575 +					joystick->hwdata->currentXInputSlot = 0;
  23.576 +					// The XInput API has a hard coded button/axis mapping, so we just match it
  23.577 +					joystick->naxes = 6;
  23.578 +					joystick->nbuttons = 15;
  23.579 +					joystick->nballs = 0;
  23.580 +					joystick->nhats = 0;
  23.581 +				}
  23.582 +			}
  23.583 +			else
  23.584 +			{
  23.585 +				joystickdevice->bXInputDevice = SDL_FALSE;
  23.586 +			}
  23.587 +		}
  23.588 +		else
  23.589 +		{
  23.590 +			joystickdevice->bXInputDevice = SDL_FALSE;
  23.591 +		}
  23.592 +	}
  23.593  
  23.594 -    /* Aquire shared access. Exclusive access is required for forces,
  23.595 -     * though. */
  23.596 -    result =
  23.597 -        IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata->
  23.598 -                                                InputDevice, SDL_HelperWindow,
  23.599 -                                                DISCL_EXCLUSIVE |
  23.600 -                                                DISCL_BACKGROUND);
  23.601 -    if (FAILED(result)) {
  23.602 -        SetDIerror("IDirectInputDevice2::SetCooperativeLevel", result);
  23.603 -        return (-1);
  23.604 -    }
  23.605 +	if ( joystickdevice->bXInputDevice == SDL_FALSE )
  23.606 +	{
  23.607 +		joystick->hwdata->bXInputDevice = SDL_FALSE;
  23.608  
  23.609 -    /* Use the extended data structure: DIJOYSTATE2. */
  23.610 -    result =
  23.611 -        IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice,
  23.612 -                                          &c_dfDIJoystick2);
  23.613 -    if (FAILED(result)) {
  23.614 -        SetDIerror("IDirectInputDevice2::SetDataFormat", result);
  23.615 -        return (-1);
  23.616 -    }
  23.617 +		result =
  23.618 +			IDirectInput8_CreateDevice(dinput,
  23.619 +									  &(joystickdevice->dxdevice.guidInstance), &device, NULL);
  23.620 +		if (FAILED(result)) {
  23.621 +			SetDIerror("IDirectInput::CreateDevice", result);
  23.622 +			return (-1);
  23.623 +		}
  23.624  
  23.625 -    /* Get device capabilities */
  23.626 -    result =
  23.627 -        IDirectInputDevice2_GetCapabilities(joystick->hwdata->InputDevice,
  23.628 -                                            &joystick->hwdata->Capabilities);
  23.629 +		/* Now get the IDirectInputDevice2 interface, instead. */
  23.630 +		result = IDirectInputDevice8_QueryInterface(device,
  23.631 +												   &IID_IDirectInputDevice8,
  23.632 +												   (LPVOID *) & joystick->
  23.633 +												   hwdata->InputDevice);
  23.634 +		/* We are done with this object.  Use the stored one from now on. */
  23.635 +		IDirectInputDevice8_Release(device);
  23.636  
  23.637 -    if (FAILED(result)) {
  23.638 -        SetDIerror("IDirectInputDevice2::GetCapabilities", result);
  23.639 -        return (-1);
  23.640 -    }
  23.641 +		if (FAILED(result)) {
  23.642 +			SetDIerror("IDirectInputDevice::QueryInterface", result);
  23.643 +			return (-1);
  23.644 +		}
  23.645  
  23.646 -    /* Force capable? */
  23.647 -    if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
  23.648 +		/* Aquire shared access. Exclusive access is required for forces,
  23.649 +		 * though. */
  23.650 +		result =
  23.651 +			IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
  23.652 +													InputDevice, SDL_HelperWindow,
  23.653 +													DISCL_NONEXCLUSIVE |
  23.654 +													DISCL_BACKGROUND);
  23.655 +		if (FAILED(result)) {
  23.656 +			SetDIerror("IDirectInputDevice2::SetCooperativeLevel", result);
  23.657 +			return (-1);
  23.658 +		}
  23.659  
  23.660 -        result = IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
  23.661 +		/* Use the extended data structure: DIJOYSTATE2. */
  23.662 +		result =
  23.663 +			IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
  23.664 +											  &c_dfDIJoystick2);
  23.665 +		if (FAILED(result)) {
  23.666 +			SetDIerror("IDirectInputDevice2::SetDataFormat", result);
  23.667 +			return (-1);
  23.668 +		}
  23.669  
  23.670 -        if (FAILED(result)) {
  23.671 -            SetDIerror("IDirectInputDevice2::Acquire", result);
  23.672 -            return (-1);
  23.673 -        }
  23.674 +		/* Get device capabilities */
  23.675 +		result =
  23.676 +			IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
  23.677 +												&joystick->hwdata->Capabilities);
  23.678  
  23.679 -        /* reset all accuators. */
  23.680 -        result =
  23.681 -            IDirectInputDevice2_SendForceFeedbackCommand(joystick->hwdata->
  23.682 -                                                         InputDevice,
  23.683 -                                                         DISFFC_RESET);
  23.684 +		if (FAILED(result)) {
  23.685 +			SetDIerror("IDirectInputDevice2::GetCapabilities", result);
  23.686 +			return (-1);
  23.687 +		}
  23.688  
  23.689 -        /* Not necessarily supported, ignore if not supported.
  23.690 -        if (FAILED(result)) {
  23.691 -            SetDIerror("IDirectInputDevice2::SendForceFeedbackCommand",
  23.692 -                       result);
  23.693 -            return (-1);
  23.694 -        }
  23.695 -        */
  23.696 +		/* Force capable? */
  23.697 +		if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
  23.698  
  23.699 -        result = IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice);
  23.700 +			result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
  23.701  
  23.702 -        if (FAILED(result)) {
  23.703 -            SetDIerror("IDirectInputDevice2::Unacquire", result);
  23.704 -            return (-1);
  23.705 -        }
  23.706 +			if (FAILED(result)) {
  23.707 +				SetDIerror("IDirectInputDevice2::Acquire", result);
  23.708 +				return (-1);
  23.709 +			}
  23.710  
  23.711 -        /* Turn on auto-centering for a ForceFeedback device (until told
  23.712 -         * otherwise). */
  23.713 -        dipdw.diph.dwObj = 0;
  23.714 -        dipdw.diph.dwHow = DIPH_DEVICE;
  23.715 -        dipdw.dwData = DIPROPAUTOCENTER_ON;
  23.716 +			/* reset all accuators. */
  23.717 +			result =
  23.718 +				IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
  23.719 +															 InputDevice,
  23.720 +															 DISFFC_RESET);
  23.721  
  23.722 -        result =
  23.723 -            IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
  23.724 -                                            DIPROP_AUTOCENTER, &dipdw.diph);
  23.725 +			/* Not necessarily supported, ignore if not supported.
  23.726 +			if (FAILED(result)) {
  23.727 +				SetDIerror("IDirectInputDevice2::SendForceFeedbackCommand",
  23.728 +						   result);
  23.729 +				return (-1);
  23.730 +			}
  23.731 +			*/
  23.732  
  23.733 -        /* Not necessarily supported, ignore if not supported.
  23.734 -        if (FAILED(result)) {
  23.735 -            SetDIerror("IDirectInputDevice2::SetProperty", result);
  23.736 -            return (-1);
  23.737 -        }
  23.738 -        */
  23.739 -    }
  23.740 +			result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
  23.741  
  23.742 -    /* What buttons and axes does it have? */
  23.743 -    IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice,
  23.744 -                                    EnumDevObjectsCallback, joystick,
  23.745 -                                    DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
  23.746 +			if (FAILED(result)) {
  23.747 +				SetDIerror("IDirectInputDevice2::Unacquire", result);
  23.748 +				return (-1);
  23.749 +			}
  23.750  
  23.751 -	/* Reorder the input objects. Some devices do not report the X axis as
  23.752 -	 * the first axis, for example. */
  23.753 -	SortDevObjects(joystick);
  23.754 +			/* Turn on auto-centering for a ForceFeedback device (until told
  23.755 +			 * otherwise). */
  23.756 +			dipdw.diph.dwObj = 0;
  23.757 +			dipdw.diph.dwHow = DIPH_DEVICE;
  23.758 +			dipdw.dwData = DIPROPAUTOCENTER_ON;
  23.759  
  23.760 -    dipdw.diph.dwObj = 0;
  23.761 -    dipdw.diph.dwHow = DIPH_DEVICE;
  23.762 -    dipdw.dwData = INPUT_QSIZE;
  23.763 +			result =
  23.764 +				IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
  23.765 +												DIPROP_AUTOCENTER, &dipdw.diph);
  23.766  
  23.767 -    /* Set the buffer size */
  23.768 -    result =
  23.769 -        IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
  23.770 -                                        DIPROP_BUFFERSIZE, &dipdw.diph);
  23.771 +			/* Not necessarily supported, ignore if not supported.
  23.772 +			if (FAILED(result)) {
  23.773 +				SetDIerror("IDirectInputDevice2::SetProperty", result);
  23.774 +				return (-1);
  23.775 +			}
  23.776 +			*/
  23.777 +		}
  23.778  
  23.779 -    if (result == DI_POLLEDDEVICE) {
  23.780 -        /* This device doesn't support buffering, so we're forced
  23.781 -         * to use less reliable polling. */
  23.782 -        joystick->hwdata->buffered = 0;
  23.783 -    } else if (FAILED(result)) {
  23.784 -        SetDIerror("IDirectInputDevice2::SetProperty", result);
  23.785 -        return (-1);
  23.786 -    }
  23.787 +		/* What buttons and axes does it have? */
  23.788 +		IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
  23.789 +										EnumDevObjectsCallback, joystick,
  23.790 +										DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
  23.791  
  23.792 +		/* Reorder the input objects. Some devices do not report the X axis as
  23.793 +		 * the first axis, for example. */
  23.794 +		SortDevObjects(joystick);
  23.795 +
  23.796 +		dipdw.diph.dwObj = 0;
  23.797 +		dipdw.diph.dwHow = DIPH_DEVICE;
  23.798 +		dipdw.dwData = INPUT_QSIZE;
  23.799 +
  23.800 +		/* Set the buffer size */
  23.801 +		result =
  23.802 +			IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
  23.803 +											DIPROP_BUFFERSIZE, &dipdw.diph);
  23.804 +
  23.805 +		if (result == DI_POLLEDDEVICE) {
  23.806 +			/* This device doesn't support buffering, so we're forced
  23.807 +			 * to use less reliable polling. */
  23.808 +			joystick->hwdata->buffered = 0;
  23.809 +		} else if (FAILED(result)) {
  23.810 +			SetDIerror("IDirectInputDevice2::SetProperty", result);
  23.811 +			return (-1);
  23.812 +		}
  23.813 +	}
  23.814      return (0);
  23.815  }
  23.816  
  23.817 @@ -564,15 +963,15 @@
  23.818      HRESULT result;
  23.819      input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
  23.820  
  23.821 -    in->ofs = dev->dwOfs;
  23.822 -
  23.823      if (dev->dwType & DIDFT_BUTTON) {
  23.824          in->type = BUTTON;
  23.825          in->num = joystick->nbuttons;
  23.826 +		in->ofs = DIJOFS_BUTTON( in->num );
  23.827          joystick->nbuttons++;
  23.828      } else if (dev->dwType & DIDFT_POV) {
  23.829          in->type = HAT;
  23.830          in->num = joystick->nhats;
  23.831 +		in->ofs = DIJOFS_POV( in->num );
  23.832          joystick->nhats++;
  23.833      } else if (dev->dwType & DIDFT_AXIS) {
  23.834          DIPROPRANGE diprg;
  23.835 @@ -580,16 +979,38 @@
  23.836  
  23.837          in->type = AXIS;
  23.838          in->num = joystick->naxes;
  23.839 +		// work our the axis this guy maps too, thanks for the code icculus!
  23.840 +		if ( !SDL_memcmp( &dev->guidType, &GUID_XAxis, sizeof(dev->guidType) ) )
  23.841 +			in->ofs = DIJOFS_X;
  23.842 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_YAxis, sizeof(dev->guidType) ) )
  23.843 +			in->ofs = DIJOFS_Y;
  23.844 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_ZAxis, sizeof(dev->guidType) ) )
  23.845 +			in->ofs = DIJOFS_Z;
  23.846 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_RxAxis, sizeof(dev->guidType) ) )
  23.847 +			in->ofs = DIJOFS_RX;
  23.848 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_RyAxis, sizeof(dev->guidType) ) )
  23.849 +			in->ofs = DIJOFS_RY;
  23.850 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_RzAxis, sizeof(dev->guidType) ) )
  23.851 +			in->ofs = DIJOFS_RZ;
  23.852 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_Slider, sizeof(dev->guidType) ) )
  23.853 +		{
  23.854 +			in->ofs = DIJOFS_SLIDER( joystick->hwdata->NumSliders );
  23.855 +			++joystick->hwdata->NumSliders;
  23.856 +		}
  23.857 +		else 
  23.858 +		{
  23.859 +			 return DIENUM_CONTINUE; // not an axis we can grok
  23.860 +		}
  23.861  
  23.862          diprg.diph.dwSize = sizeof(diprg);
  23.863          diprg.diph.dwHeaderSize = sizeof(diprg.diph);
  23.864 -        diprg.diph.dwObj = dev->dwOfs;
  23.865 -        diprg.diph.dwHow = DIPH_BYOFFSET;
  23.866 +        diprg.diph.dwObj = dev->dwType;
  23.867 +        diprg.diph.dwHow = DIPH_BYID;
  23.868          diprg.lMin = AXIS_MIN;
  23.869          diprg.lMax = AXIS_MAX;
  23.870  
  23.871          result =
  23.872 -            IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
  23.873 +            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
  23.874                                              DIPROP_RANGE, &diprg.diph);
  23.875          if (FAILED(result)) {
  23.876              return DIENUM_CONTINUE;     /* don't use this axis */
  23.877 @@ -598,11 +1019,11 @@
  23.878          /* Set dead zone to 0. */
  23.879          dilong.diph.dwSize = sizeof(dilong);
  23.880          dilong.diph.dwHeaderSize = sizeof(dilong.diph);
  23.881 -        dilong.diph.dwObj = dev->dwOfs;
  23.882 -        dilong.diph.dwHow = DIPH_BYOFFSET;
  23.883 +        dilong.diph.dwObj = dev->dwType;
  23.884 +        dilong.diph.dwHow = DIPH_BYID;
  23.885          dilong.dwData = 0;
  23.886          result =
  23.887 -            IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
  23.888 +            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
  23.889                                              DIPROP_DEADZONE, &dilong.diph);
  23.890          if (FAILED(result)) {
  23.891              return DIENUM_CONTINUE;     /* don't use this axis */
  23.892 @@ -636,15 +1057,22 @@
  23.893      int i;
  23.894  
  23.895      result =
  23.896 -        IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
  23.897 +        IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
  23.898                                             sizeof(DIJOYSTATE2), &state);
  23.899      if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
  23.900 -        IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
  23.901 +        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
  23.902          result =
  23.903 -            IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
  23.904 +            IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
  23.905                                                 sizeof(DIJOYSTATE2), &state);
  23.906      }
  23.907  
  23.908 +	if ( result != DI_OK )
  23.909 +	{
  23.910 +		joystick->hwdata->send_remove_event = 1;
  23.911 +		joystick->hwdata->removed = 1;
  23.912 +		return;
  23.913 +	}
  23.914 +
  23.915      /* Set each known axis, button and POV. */
  23.916      for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
  23.917          const input_t *in = &joystick->hwdata->Inputs[i];
  23.918 @@ -717,20 +1145,24 @@
  23.919  
  23.920      numevents = INPUT_QSIZE;
  23.921      result =
  23.922 -        IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
  23.923 +        IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
  23.924                                            sizeof(DIDEVICEOBJECTDATA), evtbuf,
  23.925                                            &numevents, 0);
  23.926      if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
  23.927 -        IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
  23.928 +        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
  23.929          result =
  23.930 -            IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
  23.931 +            IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
  23.932                                                sizeof(DIDEVICEOBJECTDATA),
  23.933                                                evtbuf, &numevents, 0);
  23.934      }
  23.935  
  23.936      /* Handle the events or punt */
  23.937      if (FAILED(result))
  23.938 +	{
  23.939 +		joystick->hwdata->send_remove_event = 1;
  23.940 +		joystick->hwdata->removed = 1;
  23.941          return;
  23.942 +	}
  23.943  
  23.944      for (i = 0; i < (int) numevents; ++i) {
  23.945          int j;
  23.946 @@ -763,6 +1195,82 @@
  23.947  }
  23.948  
  23.949  
  23.950 +/* Function to return > 0 if a bit array of buttons differs after applying a mask
  23.951 +*/
  23.952 +int ButtonChanged( int ButtonsNow, int ButtonsPrev, int ButtonMask )
  23.953 +{
  23.954 +	return ( ButtonsNow & ButtonMask ) != ( ButtonsPrev & ButtonMask );
  23.955 +}
  23.956 +
  23.957 +/* Function to update the state of a XInput style joystick.
  23.958 +*/
  23.959 +void
  23.960 +SDL_SYS_JoystickUpdate_XInput(SDL_Joystick * joystick)
  23.961 +{
  23.962 +	HRESULT result;
  23.963 +
  23.964 +	if ( !XINPUTGETSTATE )
  23.965 +		return;
  23.966 +
  23.967 +	result = XINPUTGETSTATE( joystick->hwdata->userid, &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot] );
  23.968 +	if ( result == ERROR_DEVICE_NOT_CONNECTED )
  23.969 +	{
  23.970 +		joystick->hwdata->send_remove_event = 1;
  23.971 +		joystick->hwdata->removed = 1;
  23.972 +		return;
  23.973 +	}
  23.974 +
  23.975 +	// only fire events if the data changed from last time
  23.976 +	if ( joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot].dwPacketNumber != 0 
  23.977 +		&& joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot].dwPacketNumber != joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot^1].dwPacketNumber )
  23.978 +	{
  23.979 +		XINPUT_STATE_EX *pXInputState = &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot];
  23.980 +		XINPUT_STATE_EX *pXInputStatePrev = &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot ^ 1];
  23.981 +
  23.982 +		SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX );
  23.983 +		SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-1*pXInputState->Gamepad.sThumbLY-1) );
  23.984 +		SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX );
  23.985 +		SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-1*pXInputState->Gamepad.sThumbRY-1) );
  23.986 +		SDL_PrivateJoystickAxis(joystick, 4, (Sint16)((int)pXInputState->Gamepad.bLeftTrigger*32767/255) );
  23.987 +		SDL_PrivateJoystickAxis(joystick, 5, (Sint16)((int)pXInputState->Gamepad.bRightTrigger*32767/255) );
  23.988 +
  23.989 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_UP ) )
  23.990 +			SDL_PrivateJoystickButton(joystick, 0, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ? SDL_PRESSED :	SDL_RELEASED );
  23.991 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_DOWN ) )
  23.992 +			SDL_PrivateJoystickButton(joystick, 1, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ? SDL_PRESSED :	SDL_RELEASED );
  23.993 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_LEFT ) )
  23.994 +			SDL_PrivateJoystickButton(joystick, 2, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ? SDL_PRESSED :	SDL_RELEASED );
  23.995 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_RIGHT ) )
  23.996 +			SDL_PrivateJoystickButton(joystick, 3, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ? SDL_PRESSED :	SDL_RELEASED );
  23.997 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_START ) )
  23.998 +			SDL_PrivateJoystickButton(joystick, 4, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_START ? SDL_PRESSED :	SDL_RELEASED );
  23.999 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_BACK ) )
 23.1000 +			SDL_PrivateJoystickButton(joystick, 5, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_BACK ? SDL_PRESSED :	SDL_RELEASED );
 23.1001 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_THUMB ) )
 23.1002 +			SDL_PrivateJoystickButton(joystick, 6, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ? SDL_PRESSED :	SDL_RELEASED );
 23.1003 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_THUMB ) )
 23.1004 +			SDL_PrivateJoystickButton(joystick, 7, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ? SDL_PRESSED :	SDL_RELEASED );
 23.1005 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_SHOULDER ) )
 23.1006 +			SDL_PrivateJoystickButton(joystick, 8, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER ? SDL_PRESSED :	SDL_RELEASED );
 23.1007 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_SHOULDER ) )
 23.1008 +			SDL_PrivateJoystickButton(joystick, 9, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER ? SDL_PRESSED :	SDL_RELEASED );
 23.1009 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_A ) )
 23.1010 +			SDL_PrivateJoystickButton(joystick, 10, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_A ? SDL_PRESSED :	SDL_RELEASED );
 23.1011 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_B ) )
 23.1012 +			SDL_PrivateJoystickButton(joystick, 11, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_B ? SDL_PRESSED :	SDL_RELEASED );
 23.1013 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_X ) )
 23.1014 +			SDL_PrivateJoystickButton(joystick, 12, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_X ? SDL_PRESSED :	SDL_RELEASED );
 23.1015 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_Y ) )
 23.1016 +			SDL_PrivateJoystickButton(joystick, 13, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_Y ? SDL_PRESSED :	SDL_RELEASED );
 23.1017 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons,  0x400 ) )
 23.1018 +			SDL_PrivateJoystickButton(joystick, 14, pXInputState->Gamepad.wButtons & 0x400 ? SDL_PRESSED :	SDL_RELEASED ); // 0x400 is the undocumented code for the guide button
 23.1019 +
 23.1020 +		joystick->hwdata->currentXInputSlot ^= 1;
 23.1021 +
 23.1022 +	}
 23.1023 +}
 23.1024 +
 23.1025 +
 23.1026  static Uint8
 23.1027  TranslatePOV(DWORD value)
 23.1028  {
 23.1029 @@ -823,46 +1331,97 @@
 23.1030  {
 23.1031      HRESULT result;
 23.1032  
 23.1033 -    result = IDirectInputDevice2_Poll(joystick->hwdata->InputDevice);
 23.1034 -    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
 23.1035 -        IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
 23.1036 -        IDirectInputDevice2_Poll(joystick->hwdata->InputDevice);
 23.1037 -    }
 23.1038 +	if ( joystick->closed || !joystick->hwdata )
 23.1039 +		return;
 23.1040  
 23.1041 -    if (joystick->hwdata->buffered)
 23.1042 -        SDL_SYS_JoystickUpdate_Buffered(joystick);
 23.1043 -    else
 23.1044 -        SDL_SYS_JoystickUpdate_Polled(joystick);
 23.1045 +	if (joystick->hwdata->bXInputDevice)
 23.1046 +	{
 23.1047 +		SDL_SYS_JoystickUpdate_XInput(joystick);
 23.1048 +	}
 23.1049 +	else
 23.1050 +	{
 23.1051 +		result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
 23.1052 +		if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
 23.1053 +			IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
 23.1054 +			IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
 23.1055 +		}
 23.1056 +
 23.1057 +		if (joystick->hwdata->buffered)
 23.1058 +			SDL_SYS_JoystickUpdate_Buffered(joystick);
 23.1059 +		else
 23.1060 +			SDL_SYS_JoystickUpdate_Polled(joystick);
 23.1061 +	}
 23.1062 +
 23.1063 +	if ( joystick->hwdata->removed )
 23.1064 +	{
 23.1065 +		joystick->closed = 1;
 23.1066 +		joystick->uncentered = 1;
 23.1067 +	}
 23.1068  }
 23.1069  
 23.1070  /* Function to close a joystick after use */
 23.1071  void
 23.1072  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
 23.1073  {
 23.1074 -    IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice);
 23.1075 -    IDirectInputDevice2_Release(joystick->hwdata->InputDevice);
 23.1076 +	if ( joystick->hwdata->bXInputDevice )
 23.1077 +	{
 23.1078 +		JoyStick_DeviceData *joysticklist = SYS_Joystick;
 23.1079 +		// scan the opened joysticks and clear the userid for this instance
 23.1080 +		for( ; joysticklist; joysticklist = joysticklist->pNext)
 23.1081 +		{
 23.1082 +			if ( joysticklist->bXInputDevice && joysticklist->nInstanceID == joystick->instance_id )
 23.1083 +			{
 23.1084 +				joysticklist->XInputUserId = INVALID_XINPUT_USERID;
 23.1085 +			}
 23.1086 +		}
 23.1087 +
 23.1088 +	}
 23.1089 +	else
 23.1090 +	{
 23.1091 +	    IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
 23.1092 +	    IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
 23.1093 +	}
 23.1094  
 23.1095      if (joystick->hwdata != NULL) {
 23.1096          /* free system specific hardware data */
 23.1097          SDL_free(joystick->hwdata);
 23.1098      }
 23.1099 +
 23.1100 +	joystick->closed = 1;
 23.1101  }
 23.1102  
 23.1103  /* Function to perform any system-specific joystick related cleanup */
 23.1104  void
 23.1105  SDL_SYS_JoystickQuit(void)
 23.1106  {
 23.1107 -    int i;
 23.1108 +	JoyStick_DeviceData *device = SYS_Joystick;
 23.1109  
 23.1110 -    for (i = 0; i < SDL_arraysize(SYS_JoystickNames); ++i) {
 23.1111 -        if (SYS_JoystickNames[i]) {
 23.1112 -            SDL_free(SYS_JoystickNames[i]);
 23.1113 -            SYS_JoystickNames[i] = NULL;
 23.1114 -        }
 23.1115 -    }
 23.1116 +	while ( device )
 23.1117 +	{
 23.1118 +		JoyStick_DeviceData *device_next = device->pNext;
 23.1119 +		SDL_free(device->joystickname);
 23.1120 +		SDL_free(device);
 23.1121 +		device = device_next;
 23.1122 +	}
 23.1123 +	SYS_Joystick = NULL;
 23.1124 +
 23.1125 +	if ( s_threadJoystick )
 23.1126 +	{
 23.1127 +		SDL_LockMutex( s_mutexJoyStickEnum );
 23.1128 +		s_bJoystickThreadQuit = SDL_TRUE;
 23.1129 +		SDL_CondBroadcast( s_condJoystickThread ); // signal the joystick thread to quit
 23.1130 +		SDL_UnlockMutex( s_mutexJoyStickEnum );
 23.1131 +		SDL_WaitThread( s_threadJoystick, NULL ); // wait for it to bugger off
 23.1132 +
 23.1133 +		SDL_DestroyMutex( s_mutexJoyStickEnum );
 23.1134 +		SDL_DestroyCond( s_condJoystickThread );
 23.1135 +		s_condJoystickThread= NULL;
 23.1136 +		s_mutexJoyStickEnum = NULL;
 23.1137 +		s_threadJoystick = NULL;
 23.1138 +	}
 23.1139  
 23.1140      if (dinput != NULL) {
 23.1141 -        IDirectInput_Release(dinput);
 23.1142 +        IDirectInput8_Release(dinput);
 23.1143          dinput = NULL;
 23.1144      }
 23.1145  
 23.1146 @@ -870,6 +1429,254 @@
 23.1147          WIN_CoUninitialize();
 23.1148          coinitialized = SDL_FALSE;
 23.1149      }
 23.1150 +
 23.1151 +	if ( s_pKnownJoystickGUIDs )
 23.1152 +	{
 23.1153 +		SDL_free( s_pKnownJoystickGUIDs );
 23.1154 +		s_pKnownJoystickGUIDs = NULL;
 23.1155 +	}
 23.1156 +
 23.1157 +	if ( s_pXInputDLL )
 23.1158 +	{
 23.1159 +		FreeLibrary( s_pXInputDLL );
 23.1160 +		s_pXInputDLL = NULL;
 23.1161 +	}
 23.1162 +}
 23.1163 +
 23.1164 +
 23.1165 +/* Function to perform the mapping between current device instance and this joysticks instance id */
 23.1166 +SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
 23.1167 +{
 23.1168 +	JoyStick_DeviceData *device = SYS_Joystick;
 23.1169 +	int index;
 23.1170 +
 23.1171 +	for (index = device_index; index > 0; index--)
 23.1172 +		device = device->pNext;
 23.1173 +
 23.1174 +	return device->nInstanceID;
 23.1175 +}
 23.1176 +
 23.1177 +/* return true if this joystick is plugged in right now */
 23.1178 +int SDL_SYS_JoystickAttached( SDL_Joystick * joystick )
 23.1179 +{
 23.1180 +	return joystick->closed == 0 && joystick->hwdata->removed == 0;
 23.1181 +}
 23.1182 +
 23.1183 +
 23.1184 +/* return the number of joysticks that are connected right now */
 23.1185 +int SDL_SYS_NumJoysticks()
 23.1186 +{
 23.1187 +	int nJoysticks = 0;
 23.1188 +	JoyStick_DeviceData *device = SYS_Joystick;
 23.1189 +	while ( device )
 23.1190 +	{
 23.1191 +		nJoysticks++;
 23.1192 +		device = device->pNext;
 23.1193 +	}
 23.1194 +
 23.1195 +	return nJoysticks;
 23.1196 +}
 23.1197 +
 23.1198 +static int s_iNewGUID = 0;
 23.1199 +
 23.1200 +/* helper function for direct input, gets called for each connected joystick */
 23.1201 +static BOOL CALLBACK
 23.1202 +	EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
 23.1203 +{
 23.1204 +	JoyStick_DeviceData *pNewJoystick;
 23.1205 +	SDL_bool bXInputDevice;
 23.1206 +	pNewJoystick = *(JoyStick_DeviceData **)pContext;
 23.1207 +	while ( pNewJoystick )
 23.1208 +	{
 23.1209 +		if ( !SDL_memcmp( &pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance) ) )
 23.1210 +		{
 23.1211 +			if ( SYS_Joystick )
 23.1212 +			{
 23.1213 +				pNewJoystick->pNext = SYS_Joystick;
 23.1214 +			}
 23.1215 +			SYS_Joystick = pNewJoystick;
 23.1216 +			/* if we are replacing the front of the list then update it */
 23.1217 +			if ( pNewJoystick == *(JoyStick_DeviceData **)pContext ) 
 23.1218 +			{
 23.1219 +				*(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
 23.1220 +			}
 23.1221 +
 23.1222 +			s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
 23.1223 +			s_iNewGUID++;
 23.1224 +			if ( s_iNewGUID < MAX_JOYSTICKS )
 23.1225 +				return DIENUM_CONTINUE; // already have this joystick loaded, just keep going
 23.1226 +			else
 23.1227 +				return DIENUM_STOP; 
 23.1228 +		}
 23.1229 +
 23.1230 +		pNewJoystick = pNewJoystick->pNext;
 23.1231 +	}
 23.1232 +
 23.1233 +	s_bDeviceAdded = SDL_TRUE;
 23.1234 +
 23.1235 +	bXInputDevice = IsXInputDevice( &pdidInstance->guidProduct );
 23.1236 +
 23.1237 +	pNewJoystick = (JoyStick_DeviceData *)SDL_malloc( sizeof(JoyStick_DeviceData) );
 23.1238 +
 23.1239 +	if ( bXInputDevice )
 23.1240 +	{
 23.1241 +		SDL_memset(&(pNewJoystick->dxdevice), 0x0,
 23.1242 +			sizeof(DIDEVICEINSTANCE));
 23.1243 +		pNewJoystick->bXInputDevice = 1;
 23.1244 +		pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
 23.1245 +	}
 23.1246 +	else
 23.1247 +	{
 23.1248 +		pNewJoystick->bXInputDevice = 0;
 23.1249 +		SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
 23.1250 +			sizeof(DIDEVICEINSTANCE));
 23.1251 +	}
 23.1252 +	pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
 23.1253 +	pNewJoystick->send_add_event = 1;
 23.1254 +	pNewJoystick->nInstanceID = ++s_nInstanceID;
 23.1255 +	SDL_memcpy( &pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid) );
 23.1256 +	pNewJoystick->pNext = NULL;
 23.1257 +
 23.1258 +	if ( SYS_Joystick )
 23.1259 +	{
 23.1260 +		pNewJoystick->pNext = SYS_Joystick;
 23.1261 +	}
 23.1262 +	SYS_Joystick = pNewJoystick;
 23.1263 +
 23.1264 +	s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
 23.1265 +	s_iNewGUID++;
 23.1266 +
 23.1267 +	if ( s_iNewGUID < MAX_JOYSTICKS )
 23.1268 +		return DIENUM_CONTINUE; // already have this joystick loaded, just keep going
 23.1269 +	else
 23.1270 +		return DIENUM_STOP; 
 23.1271 +}
 23.1272 +
 23.1273 +
 23.1274 +/* detect any new joysticks being inserted into the system */
 23.1275 +void SDL_SYS_JoystickDetect()
 23.1276 +{
 23.1277 +	HRESULT result;
 23.1278 +	JoyStick_DeviceData *pCurList = NULL;
 23.1279 +	/* only enum the devices if the joystick thread told us something changed */
 23.1280 +	if ( s_bDeviceAdded || s_bDeviceRemoved )
 23.1281 +	{
 23.1282 +		s_bDeviceAdded = SDL_FALSE;
 23.1283 +		s_bDeviceRemoved = SDL_FALSE;
 23.1284 +
 23.1285 +		pCurList = SYS_Joystick;
 23.1286 +		SYS_Joystick = NULL;
 23.1287 +		s_iNewGUID = 0;
 23.1288 +		SDL_mutexP( s_mutexJoyStickEnum );
 23.1289 +
 23.1290 +		if ( !s_pKnownJoystickGUIDs )
 23.1291 +			s_pKnownJoystickGUIDs = SDL_malloc( sizeof(GUID)*MAX_JOYSTICKS );
 23.1292 +				
 23.1293 +		SDL_memset( s_pKnownJoystickGUIDs, 0x0, sizeof(GUID)*MAX_JOYSTICKS );
 23.1294 +
 23.1295 +		/* Look for joysticks, wheels, head trackers, gamepads, etc.. */
 23.1296 +		result = IDirectInput8_EnumDevices(dinput,
 23.1297 +			DI8DEVCLASS_GAMECTRL,
 23.1298 +			EnumJoysticksCallback,
 23.1299 +			&pCurList, DIEDFL_ATTACHEDONLY);
 23.1300 +
 23.1301 +		SDL_mutexV( s_mutexJoyStickEnum );
 23.1302 +	}
 23.1303 +
 23.1304 +	if ( pCurList )
 23.1305 +	{
 23.1306 +		while ( pCurList )
 23.1307 +		{
 23.1308 +			JoyStick_DeviceData *pListNext = NULL;
 23.1309 +#if !SDL_EVENTS_DISABLED
 23.1310 +			SDL_Event event;
 23.1311 +			event.type = SDL_JOYDEVICEREMOVED;
 23.1312 +
 23.1313 +			if (SDL_GetEventState(event.type) == SDL_ENABLE) {
 23.1314 +				event.jdevice.which = pCurList->nInstanceID;
 23.1315 +				if ((SDL_EventOK == NULL)
 23.1316 +					|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
 23.1317 +						SDL_PushEvent(&event);
 23.1318 +				}
 23.1319 +			}
 23.1320 +#endif // !SDL_EVENTS_DISABLED 
 23.1321 +
 23.1322 +			pListNext = pCurList->pNext;
 23.1323 +			SDL_free(pCurList->joystickname);
 23.1324 +			SDL_free( pCurList );
 23.1325 +			pCurList = pListNext;
 23.1326 +		}
 23.1327 +
 23.1328 +	}
 23.1329 +
 23.1330 +	if ( s_bDeviceAdded )
 23.1331 +	{
 23.1332 +		JoyStick_DeviceData *pNewJoystick;
 23.1333 +		int device_index = 0;
 23.1334 +		s_bDeviceAdded = SDL_FALSE;
 23.1335 +		pNewJoystick = SYS_Joystick;
 23.1336 +		while ( pNewJoystick )
 23.1337 +		{
 23.1338 +			if ( pNewJoystick->send_add_event )
 23.1339 +			{
 23.1340 +#if !SDL_EVENTS_DISABLED
 23.1341 +				SDL_Event event;
 23.1342 +				event.type = SDL_JOYDEVICEADDED;
 23.1343 +
 23.1344 +				if (SDL_GetEventState(event.type) == SDL_ENABLE) {
 23.1345 +					event.jdevice.which = device_index;
 23.1346 +					if ((SDL_EventOK == NULL)
 23.1347 +						|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
 23.1348 +							SDL_PushEvent(&event);
 23.1349 +					}
 23.1350 +				}
 23.1351 +#endif /* !SDL_EVENTS_DISABLED */
 23.1352 +				pNewJoystick->send_add_event = 0;
 23.1353 +			}
 23.1354 +			device_index++;
 23.1355 +			pNewJoystick = pNewJoystick->pNext;
 23.1356 +		}
 23.1357 +	}
 23.1358 +}
 23.1359 +
 23.1360 +
 23.1361 +/* we need to poll if we have pending hotplug device changes or connected devices */
 23.1362 +int SDL_SYS_JoystickNeedsPolling()
 23.1363 +{
 23.1364 +	/* we have a new device or one was pulled, we need to think this frame please */
 23.1365 +	if ( s_bDeviceAdded || s_bDeviceRemoved )
 23.1366 +		return 1;
 23.1367 +
 23.1368 +	return 0;
 23.1369 +}
 23.1370 +
 23.1371 +/* return the stable device guid for this device index */
 23.1372 +JoystickGUID SDL_SYS_PrivateJoystickGetDeviceID( int device_index )
 23.1373 +{
 23.1374 +	JoyStick_DeviceData *device = SYS_Joystick;
 23.1375 +	int index;
 23.1376 +
 23.1377 +	for (index = device_index; index > 0; index--)
 23.1378 +		device = device->pNext;
 23.1379 +
 23.1380 +	return device->guid;
 23.1381 +}
 23.1382 +
 23.1383 +/* return 1 if this device is using XInput */
 23.1384 +int SDL_SYS_IsXInputDeviceIndex( int device_index )
 23.1385 +{
 23.1386 +	JoyStick_DeviceData *device = SYS_Joystick;
 23.1387 +	int index;
 23.1388 +
 23.1389 +	for (index = device_index; index > 0; index--)
 23.1390 +		device = device->pNext;
 23.1391 +
 23.1392 +	return device->bXInputDevice;
 23.1393 +}
 23.1394 +
 23.1395 +JoystickGUID SDL_SYS_PrivateJoystickGetGUID(SDL_Joystick * joystick)
 23.1396 +{
 23.1397 +	return joystick->hwdata->guid;
 23.1398  }
 23.1399  
 23.1400  #endif /* SDL_JOYSTICK_DINPUT */
    24.1 --- a/src/joystick/windows/SDL_dxjoystick_c.h	Mon Nov 26 14:59:07 2012 -0800
    24.2 +++ b/src/joystick/windows/SDL_dxjoystick_c.h	Mon Nov 26 16:37:54 2012 -0800
    24.3 @@ -34,9 +34,14 @@
    24.4  
    24.5  #include "../../core/windows/SDL_windows.h"
    24.6  
    24.7 -#define DIRECTINPUT_VERSION 0x0700      /* Need version 7 for force feedback. */
    24.8 +#define DIRECTINPUT_VERSION 0x0800      /* Need version 7 for force feedback. Need verison 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */
    24.9  #include <dinput.h>
   24.10 -
   24.11 +#define COBJMACROS
   24.12 +#include <wbemcli.h>
   24.13 +#include <oleauto.h>
   24.14 +#include <xinput.h>
   24.15 +#include <devguid.h>
   24.16 +#include <dbt.h>
   24.17  
   24.18  #define MAX_INPUTS	256     /* each joystick can have up to 256 inputs */
   24.19  
   24.20 @@ -57,15 +62,42 @@
   24.21      Uint8 num;
   24.22  } input_t;
   24.23  
   24.24 +/* typedef's for XInput structs we use */
   24.25 +typedef struct
   24.26 +{
   24.27 +	WORD                                wButtons;
   24.28 +	BYTE                                bLeftTrigger;
   24.29 +	BYTE                                bRightTrigger;
   24.30 +	SHORT                               sThumbLX;
   24.31 +	SHORT                               sThumbLY;
   24.32 +	SHORT                               sThumbRX;
   24.33 +	SHORT                               sThumbRY;
   24.34 +	DWORD								dwPaddingReserved;
   24.35 +} XINPUT_GAMEPAD_EX;
   24.36 +
   24.37 +typedef struct 
   24.38 +{
   24.39 +	DWORD                               dwPacketNumber;
   24.40 +	XINPUT_GAMEPAD_EX                   Gamepad;
   24.41 +} XINPUT_STATE_EX;
   24.42 +
   24.43  /* The private structure used to keep track of a joystick */
   24.44  struct joystick_hwdata
   24.45  {
   24.46      LPDIRECTINPUTDEVICE2 InputDevice;
   24.47      DIDEVCAPS Capabilities;
   24.48      int buffered;
   24.49 +	JoystickGUID guid;
   24.50  
   24.51      input_t Inputs[MAX_INPUTS];
   24.52      int NumInputs;
   24.53 +	int NumSliders;
   24.54 +	Uint8 removed;
   24.55 +	Uint8 send_remove_event;
   24.56 +	Uint8 bXInputDevice; // 1 if this device supports using the xinput API rather than DirectInput
   24.57 +	Uint8 userid; // XInput userid index for this joystick
   24.58 +	Uint8 currentXInputSlot; // the current position to write to in XInputState below, used so we can compare old and new values
   24.59 +	XINPUT_STATE_EX	XInputState[2];
   24.60  };
   24.61  
   24.62  #endif /* SDL_JOYSTICK_DINPUT_H */
    25.1 --- a/test/Makefile.in	Mon Nov 26 14:59:07 2012 -0800
    25.2 +++ b/test/Makefile.in	Mon Nov 26 16:37:54 2012 -0800
    25.3 @@ -14,6 +14,7 @@
    25.4  	testdraw2$(EXE) \
    25.5  	testerror$(EXE) \
    25.6  	testfile$(EXE) \
    25.7 +	testgamecontroller$(EXE) \
    25.8  	testgesture$(EXE) \
    25.9  	testgl2$(EXE) \
   25.10  	testgles$(EXE) \
   25.11 @@ -87,6 +88,9 @@
   25.12  testfile$(EXE): $(srcdir)/testfile.c
   25.13  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
   25.14  
   25.15 +testgamecontroller$(EXE): $(srcdir)/testgamecontroller.c
   25.16 +	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
   25.17 + 
   25.18  testgesture$(EXE): $(srcdir)/testgesture.c
   25.19  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@
   25.20   
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/test/testgamecontroller.c	Mon Nov 26 16:37:54 2012 -0800
    26.3 @@ -0,0 +1,205 @@
    26.4 +/*
    26.5 +  Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
    26.6 +
    26.7 +  This software is provided 'as-is', without any express or implied
    26.8 +  warranty.  In no event will the authors be held liable for any damages
    26.9 +  arising from the use of this software.
   26.10 +
   26.11 +  Permission is granted to anyone to use this software for any purpose,
   26.12 +  including commercial applications, and to alter it and redistribute it
   26.13 +  freely.
   26.14 +*/
   26.15 +
   26.16 +/* Simple program to test the SDL game controller routines */
   26.17 +
   26.18 +#include <stdio.h>
   26.19 +#include <stdlib.h>
   26.20 +#include <string.h>
   26.21 +
   26.22 +#include "SDL.h"
   26.23 +
   26.24 +#ifdef __IPHONEOS__
   26.25 +#define SCREEN_WIDTH	320
   26.26 +#define SCREEN_HEIGHT	480
   26.27 +#else
   26.28 +#define SCREEN_WIDTH	640
   26.29 +#define SCREEN_HEIGHT	480
   26.30 +#endif
   26.31 +
   26.32 +#define MAX_NUM_AXES 6
   26.33 +#define MAX_NUM_HATS 2
   26.34 +
   26.35 +static SDL_bool s_ForceQuit = SDL_FALSE;
   26.36 +
   26.37 +static void
   26.38 +DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h)
   26.39 +{
   26.40 +    const SDL_Rect area = { x, y, w, h };
   26.41 +    SDL_RenderFillRect(r, &area);
   26.42 +}
   26.43 +
   26.44 +void
   26.45 +WatchGameController(SDL_GameController * gamecontroller)
   26.46 +{
   26.47 +    SDL_Window *window = NULL;
   26.48 +    SDL_Renderer *screen = NULL;
   26.49 +    const char *name = NULL;
   26.50 +    int done = 0;
   26.51 +    SDL_Event event;
   26.52 +    int i;
   26.53 +
   26.54 +    /* Create a window to display controller axis position */
   26.55 +    window = SDL_CreateWindow("Game Controller Test", SDL_WINDOWPOS_CENTERED,
   26.56 +                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
   26.57 +                              SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
   26.58 +    if (window == NULL) {
   26.59 +        fprintf(stderr, "Couldn't create window: %s\n", SDL_GetError());
   26.60 +        return;
   26.61 +    }
   26.62 +
   26.63 +    screen = SDL_CreateRenderer(window, -1, 0);
   26.64 +    if (screen == NULL) {
   26.65 +        fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError());
   26.66 +        SDL_DestroyWindow(window);
   26.67 +        return;
   26.68 +    }
   26.69 +
   26.70 +    SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   26.71 +    SDL_RenderClear(screen);
   26.72 +    SDL_RenderPresent(screen);
   26.73 +	SDL_RaiseWindow(window);
   26.74 +
   26.75 +    /* Print info about the controller we are watching */
   26.76 +    name = SDL_GameControllerName(gamecontroller);
   26.77 +    printf("Watching controller %s\n",  name ? name : "Unknown Controller");
   26.78 +    
   26.79 +    /* Loop, getting controller events! */
   26.80 +    while (!done) {
   26.81 +        /* blank screen, set up for drawing this frame. */
   26.82 +        SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   26.83 +        SDL_RenderClear(screen);
   26.84 +
   26.85 +        while (SDL_PollEvent(&event)) {
   26.86 +            switch (event.type) {
   26.87 +            case SDL_CONTROLLERAXISMOTION:
   26.88 +                printf("Controller %d axis %d value: %d\n",
   26.89 +                       event.caxis.which,
   26.90 +                       event.caxis.axis, event.caxis.value);
   26.91 +                break;
   26.92 +            case SDL_CONTROLLERBUTTONDOWN:
   26.93 +                printf("Controller %d button %d down\n",
   26.94 +                       event.cbutton.which, event.cbutton.button);
   26.95 +                break;
   26.96 +            case SDL_CONTROLLERBUTTONUP:
   26.97 +                printf("Controller %d button %d up\n",
   26.98 +                       event.cbutton.which, event.cbutton.button);
   26.99 +                break;
  26.100 +            case SDL_KEYDOWN:
  26.101 +                if (event.key.keysym.sym != SDLK_ESCAPE) {
  26.102 +                    break;
  26.103 +                }
  26.104 +                /* Fall through to signal quit */
  26.105 +            case SDL_QUIT:
  26.106 +                done = 1;
  26.107 +				s_ForceQuit = SDL_TRUE;
  26.108 +                break;
  26.109 +            default:
  26.110 +                break;
  26.111 +            }
  26.112 +        }
  26.113 +        /* Update visual controller state */
  26.114 +        SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE);
  26.115 +        for (i = 0; i <SDL_CONTROLLER_BUTTON_MAX; ++i) {
  26.116 +            if (SDL_GameControllerGetButton(gamecontroller, i) == SDL_PRESSED) {
  26.117 +                DrawRect(screen, i * 34, SCREEN_HEIGHT - 34, 32, 32);
  26.118 +            }
  26.119 +        }
  26.120 +
  26.121 +        SDL_SetRenderDrawColor(screen, 0xFF, 0x00, 0x00, SDL_ALPHA_OPAQUE);
  26.122 +        for (i = 0; i < SDL_CONTROLLER_AXIS_MAX / 2; ++i) {
  26.123 +            /* Draw the X/Y axis */
  26.124 +            int x, y;
  26.125 +            x = (((int) SDL_GameControllerGetAxis(gamecontroller, i * 2 + 0)) + 32768);
  26.126 +            x *= SCREEN_WIDTH;
  26.127 +            x /= 65535;
  26.128 +            if (x < 0) {
  26.129 +                x = 0;
  26.130 +            } else if (x > (SCREEN_WIDTH - 16)) {
  26.131 +                x = SCREEN_WIDTH - 16;
  26.132 +            }
  26.133 +            y = (((int) SDL_GameControllerGetAxis(gamecontroller, i * 2 + 1)) + 32768);
  26.134 +            y *= SCREEN_HEIGHT;
  26.135 +            y /= 65535;
  26.136 +            if (y < 0) {
  26.137 +                y = 0;
  26.138 +            } else if (y > (SCREEN_HEIGHT - 16)) {
  26.139 +                y = SCREEN_HEIGHT - 16;
  26.140 +            }
  26.141 +
  26.142 +            DrawRect(screen, x, y, 16, 16);
  26.143 +        }
  26.144 +
  26.145 +        SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0xFF, SDL_ALPHA_OPAQUE);
  26.146 +
  26.147 +        SDL_RenderPresent(screen);
  26.148 +		
  26.149 +		if ( !done )
  26.150 +			done = SDL_GameControllerGetAttached( gamecontroller ) == 0;
  26.151 +    }
  26.152 +
  26.153 +    SDL_DestroyRenderer(screen);
  26.154 +    SDL_DestroyWindow(window);
  26.155 +}
  26.156 +
  26.157 +int
  26.158 +main(int argc, char *argv[])
  26.159 +{
  26.160 +    const char *name;
  26.161 +    int i;
  26.162 +	int nController = 0;
  26.163 +    SDL_GameController *gamecontroller;
  26.164 +
  26.165 +	SDL_SetHint( SDL_HINT_GAMECONTROLLERCONFIG, "341a3608000000000000504944564944,Aferglow PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7" );
  26.166 +    /* Initialize SDL (Note: video is required to start event loop) */
  26.167 +    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER ) < 0) {
  26.168 +        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
  26.169 +        exit(1);
  26.170 +    }
  26.171 +
  26.172 +    /* Print information about the controller */
  26.173 +    for (i = 0; i < SDL_NumJoysticks(); ++i) {
  26.174 +		if ( SDL_IsGameController(i) )
  26.175 +		{
  26.176 +			nController++;
  26.177 +			name = SDL_GameControllerNameForIndex(i);
  26.178 +			printf("Game Controller %d: %s\n", i, name ? name : "Unknown Controller");
  26.179 +		}
  26.180 +    }
  26.181 +	printf("There are %d game controllers attached\n", nController);
  26.182 +
  26.183 +    if (argv[1]) {
  26.184 +		int nreportederror = 0;
  26.185 +		SDL_Event event;
  26.186 +		gamecontroller = SDL_GameControllerOpen(atoi(argv[1]));
  26.187 +		while ( s_ForceQuit == SDL_FALSE ) {
  26.188 +			if (gamecontroller == NULL) {
  26.189 +				if ( nreportederror == 0 ) {
  26.190 +					printf("Couldn't open joystick %d: %s\n", atoi(argv[1]), SDL_GetError());
  26.191 +					nreportederror = 1;
  26.192 +				}
  26.193 +			} else {
  26.194 +				nreportederror = 0;
  26.195 +				WatchGameController(gamecontroller);
  26.196 +				SDL_GameControllerClose(gamecontroller);
  26.197 +			}
  26.198 +			
  26.199 +			gamecontroller = NULL;
  26.200 +			SDL_WaitEvent( &event );
  26.201 +			if ( event.type == SDL_JOYDEVICEADDED )
  26.202 +				gamecontroller = SDL_GameControllerOpen(atoi(argv[1]));
  26.203 +		}
  26.204 +	}
  26.205 +    SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER );
  26.206 +
  26.207 +    return (0);
  26.208 +}
    27.1 --- a/test/testjoystick.c	Mon Nov 26 14:59:07 2012 -0800
    27.2 +++ b/test/testjoystick.c	Mon Nov 26 16:37:54 2012 -0800
    27.3 @@ -17,10 +17,14 @@
    27.4  #include <string.h>
    27.5  
    27.6  #include "SDL.h"
    27.7 -#include "common.h"
    27.8  
    27.9 -static CommonState *state;
   27.10 -static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE;
   27.11 +#ifdef __IPHONEOS__
   27.12 +#define SCREEN_WIDTH	320
   27.13 +#define SCREEN_HEIGHT	480
   27.14 +#else
   27.15 +#define SCREEN_WIDTH	640
   27.16 +#define SCREEN_HEIGHT	480
   27.17 +#endif
   27.18  
   27.19  #define MAX_NUM_AXES 6
   27.20  #define MAX_NUM_HATS 2
   27.21 @@ -37,16 +41,35 @@
   27.22  {
   27.23      SDL_Window *window = NULL;
   27.24      SDL_Renderer *screen = NULL;
   27.25 -    SDL_Rect viewport;
   27.26 -    SDL_Event event;
   27.27 -
   27.28      const char *name = NULL;
   27.29      int done = 0;
   27.30 +    SDL_Event event;
   27.31      int i;
   27.32  
   27.33 +    /* Create a window to display joystick axis position */
   27.34 +    window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
   27.35 +                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
   27.36 +                              SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
   27.37 +    if (window == NULL) {
   27.38 +        fprintf(stderr, "Couldn't create window: %s\n", SDL_GetError());
   27.39 +        return;
   27.40 +    }
   27.41 +
   27.42 +    screen = SDL_CreateRenderer(window, -1, 0);
   27.43 +    if (screen == NULL) {
   27.44 +        fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError());
   27.45 +        SDL_DestroyWindow(window);
   27.46 +        return;
   27.47 +    }
   27.48 +
   27.49 +    SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   27.50 +    SDL_RenderClear(screen);
   27.51 +    SDL_RenderPresent(screen);
   27.52 +	SDL_RaiseWindow(window);
   27.53 +
   27.54      /* Print info about the joystick we are watching */
   27.55 -    name = SDL_JoystickName(SDL_JoystickIndex(joystick));
   27.56 -    printf("Watching joystick %d: (%s)\n", SDL_JoystickIndex(joystick),
   27.57 +    name = SDL_JoystickName(joystick);
   27.58 +    printf("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
   27.59             name ? name : "Unknown Joystick");
   27.60      printf("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
   27.61             SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
   27.62 @@ -54,6 +77,10 @@
   27.63  
   27.64      /* Loop, getting joystick events! */
   27.65      while (!done) {
   27.66 +        /* blank screen, set up for drawing this frame. */
   27.67 +        SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   27.68 +        SDL_RenderClear(screen);
   27.69 +
   27.70          while (SDL_PollEvent(&event)) {
   27.71              switch (event.type) {
   27.72              case SDL_JOYAXISMOTION:
   27.73 @@ -101,100 +128,86 @@
   27.74                  break;
   27.75              }
   27.76          }
   27.77 +        /* Update visual joystick state */
   27.78 +        SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE);
   27.79 +        for (i = 0; i < SDL_JoystickNumButtons(joystick); ++i) {
   27.80 +            if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) {
   27.81 +                DrawRect(screen, i * 34, SCREEN_HEIGHT - 34, 32, 32);
   27.82 +            }
   27.83 +        }
   27.84  
   27.85 -        /* Update visual joystick state */
   27.86 -        for (i = 0; i < state->num_windows; ++i) {
   27.87 -            screen = state->renderers[i];
   27.88 -
   27.89 -            /* Erase previous axes */
   27.90 -            SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   27.91 -            SDL_RenderClear(screen);
   27.92 -
   27.93 -            /* Query the sizes */
   27.94 -            SDL_RenderGetViewport(screen, &viewport);
   27.95 -
   27.96 -            SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE);
   27.97 -            for (i = 0; i < SDL_JoystickNumButtons(joystick); ++i) {
   27.98 -                if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) {
   27.99 -                    DrawRect(screen, i * 34, viewport.h - 34, 32, 32);
  27.100 -                }
  27.101 +        SDL_SetRenderDrawColor(screen, 0xFF, 0x00, 0x00, SDL_ALPHA_OPAQUE);
  27.102 +        for (i = 0; i < SDL_JoystickNumAxes(joystick) / 2; ++i) {
  27.103 +            /* Draw the X/Y axis */
  27.104 +            int x, y;
  27.105 +            x = (((int) SDL_JoystickGetAxis(joystick, i * 2 + 0)) + 32768);
  27.106 +            x *= SCREEN_WIDTH;
  27.107 +            x /= 65535;
  27.108 +            if (x < 0) {
  27.109 +                x = 0;
  27.110 +            } else if (x > (SCREEN_WIDTH - 16)) {
  27.111 +                x = SCREEN_WIDTH - 16;
  27.112 +            }
  27.113 +            y = (((int) SDL_JoystickGetAxis(joystick, i * 2 + 1)) + 32768);
  27.114 +            y *= SCREEN_HEIGHT;
  27.115 +            y /= 65535;
  27.116 +            if (y < 0) {
  27.117 +                y = 0;
  27.118 +            } else if (y > (SCREEN_HEIGHT - 16)) {
  27.119 +                y = SCREEN_HEIGHT - 16;
  27.120              }
  27.121  
  27.122 -            SDL_SetRenderDrawColor(screen, 0xFF, 0x00, 0x00, SDL_ALPHA_OPAQUE);
  27.123 -            for (i = 0; i < SDL_JoystickNumAxes(joystick) / 2; ++i) {
  27.124 -                /* Draw the X/Y axis */
  27.125 -                int x, y;
  27.126 -                x = (((int) SDL_JoystickGetAxis(joystick, i * 2 + 0)) + 32768);
  27.127 -                x *= viewport.w ;
  27.128 -                x /= 65535;
  27.129 -                if (x < 0) {
  27.130 -                    x = 0;
  27.131 -                } else if (x > (viewport.w - 16)) {
  27.132 -                    x = viewport.w - 16;
  27.133 -                }
  27.134 -                y = (((int) SDL_JoystickGetAxis(joystick, i * 2 + 1)) + 32768);
  27.135 -                y *= viewport.h;
  27.136 -                y /= 65535;
  27.137 -                if (y < 0) {
  27.138 -                    y = 0;
  27.139 -                } else if (y > (viewport.h - 16)) {
  27.140 -                    y = viewport.h - 16;
  27.141 -                }
  27.142 +            DrawRect(screen, x, y, 16, 16);
  27.143 +        }
  27.144  
  27.145 -                DrawRect(screen, x, y, 16, 16);
  27.146 +        SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0xFF, SDL_ALPHA_OPAQUE);
  27.147 +        for (i = 0; i < SDL_JoystickNumHats(joystick); ++i) {
  27.148 +            /* Derive the new position */
  27.149 +            int x = SCREEN_WIDTH/2;
  27.150 +            int y = SCREEN_HEIGHT/2;
  27.151 +            const Uint8 hat_pos = SDL_JoystickGetHat(joystick, i);
  27.152 +
  27.153 +            if (hat_pos & SDL_HAT_UP) {
  27.154 +                y = 0;
  27.155 +            } else if (hat_pos & SDL_HAT_DOWN) {
  27.156 +                y = SCREEN_HEIGHT-8;
  27.157              }
  27.158  
  27.159 -            SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0xFF, SDL_ALPHA_OPAQUE);
  27.160 -            for (i = 0; i < SDL_JoystickNumHats(joystick); ++i) {
  27.161 -                /* Derive the new position */
  27.162 -                int x = viewport.w/2;
  27.163 -                int y = viewport.h/2;
  27.164 -                const Uint8 hat_pos = SDL_JoystickGetHat(joystick, i);
  27.165 -
  27.166 -                if (hat_pos & SDL_HAT_UP) {
  27.167 -                    y = 0;
  27.168 -                } else if (hat_pos & SDL_HAT_DOWN) {
  27.169 -                    y = viewport.h-8;
  27.170 -                }
  27.171 -
  27.172 -                if (hat_pos & SDL_HAT_LEFT) {
  27.173 -                    x = 0;
  27.174 -                } else if (hat_pos & SDL_HAT_RIGHT) {
  27.175 -                    x = viewport.w-8;
  27.176 -                }
  27.177 -
  27.178 -                DrawRect(screen, x, y, 8, 8);
  27.179 +            if (hat_pos & SDL_HAT_LEFT) {
  27.180 +                x = 0;
  27.181 +            } else if (hat_pos & SDL_HAT_RIGHT) {
  27.182 +                x = SCREEN_WIDTH-8;
  27.183              }
  27.184  
  27.185 -            SDL_RenderPresent(screen);
  27.186 +            DrawRect(screen, x, y, 8, 8);
  27.187          }
  27.188 +
  27.189 +        SDL_RenderPresent(screen);
  27.190 +		
  27.191 +		done = SDL_JoystickGetAttached( joystick ) == 0;
  27.192      }
  27.193 +
  27.194 +    SDL_DestroyRenderer(screen);
  27.195 +    SDL_DestroyWindow(window);
  27.196  }
  27.197  
  27.198  int
  27.199  main(int argc, char *argv[])
  27.200  {
  27.201      const char *name;
  27.202 -    int i, joy=-1;
  27.203 +    int i;
  27.204      SDL_Joystick *joystick;
  27.205  
  27.206      /* Initialize SDL (Note: video is required to start event loop) */
  27.207 -    if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
  27.208 +    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
  27.209          fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
  27.210          exit(1);
  27.211      }
  27.212  
  27.213 -    /* Initialize test framework */
  27.214 -    state = CommonCreateState(argv, SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
  27.215 -    if (!state) {
  27.216 -        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
  27.217 -        return 1;
  27.218 -    }
  27.219 -
  27.220      /* Print information about the joysticks */
  27.221      printf("There are %d joysticks attached\n", SDL_NumJoysticks());
  27.222      for (i = 0; i < SDL_NumJoysticks(); ++i) {
  27.223 -        name = SDL_JoystickName(i);
  27.224 +        name = SDL_JoystickNameForIndex(i);
  27.225          printf("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
  27.226          joystick = SDL_JoystickOpen(i);
  27.227          if (joystick == NULL) {
  27.228 @@ -205,42 +218,34 @@
  27.229              printf("      balls: %d\n", SDL_JoystickNumBalls(joystick));
  27.230              printf("       hats: %d\n", SDL_JoystickNumHats(joystick));
  27.231              printf("    buttons: %d\n", SDL_JoystickNumButtons(joystick));
  27.232 +            printf("instance id: %d\n", SDL_JoystickInstanceID(joystick));
  27.233              SDL_JoystickClose(joystick);
  27.234          }
  27.235      }
  27.236  
  27.237 -    for (i = 1; i < argc;) {
  27.238 -        int consumed;
  27.239 -
  27.240 -        consumed = CommonArg(state, i);
  27.241 -        if (consumed == 0) {
  27.242 -            consumed = -1;
  27.243 -            if (SDL_isdigit(*argv[i])) {
  27.244 -                joy = SDL_atoi(argv[i]);
  27.245 -                consumed = 1;
  27.246 -            }
  27.247 -        }
  27.248 -        if (consumed < 0) {
  27.249 -            return 1;
  27.250 -        }
  27.251 -        i += consumed;
  27.252 -    }
  27.253 -    if (!CommonInit(state)) {
  27.254 -        return 2;
  27.255 -    }
  27.256 -
  27.257 -    if (joy > -1) {
  27.258 -        joystick = SDL_JoystickOpen(joy);
  27.259 -        if (joystick == NULL) {
  27.260 -            printf("Couldn't open joystick %d: %s\n", joy,
  27.261 -                   SDL_GetError());
  27.262 -        } else {
  27.263 -            WatchJoystick(joystick);
  27.264 -            SDL_JoystickClose(joystick);
  27.265 -        }
  27.266 -    }
  27.267 -    SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
  27.268 -    CommonQuit(state);
  27.269 +    if (argv[1]) {
  27.270 +		int nreportederror = 0;
  27.271 +		SDL_Event event;
  27.272 +		joystick = SDL_JoystickOpen(atoi(argv[1]));
  27.273 +		while ( 1 ) {
  27.274 +			if (joystick == NULL) {
  27.275 +				if ( nreportederror == 0 ) {
  27.276 +					printf("Couldn't open joystick %d: %s\n", atoi(argv[1]), SDL_GetError());
  27.277 +					nreportederror = 1;
  27.278 +				}
  27.279 +			} else {
  27.280 +				nreportederror = 0;
  27.281 +				WatchJoystick(joystick);
  27.282 +				SDL_JoystickClose(joystick);
  27.283 +			}
  27.284 +			
  27.285 +			joystick = NULL;
  27.286 +			SDL_WaitEvent( &event );
  27.287 +			if ( event.type == SDL_JOYDEVICEADDED )
  27.288 +				joystick = SDL_JoystickOpen(atoi(argv[1]));
  27.289 +		}
  27.290 +	}
  27.291 +    SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
  27.292  
  27.293      return (0);
  27.294  }