Added hotplug joystick support and simplified game controller API, courtesy of Alfred Reynolds
authorSam Lantinga
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 const char *SDLCALL SDL_JoystickName(SDL_Joystick * joystick);
   11.53 +	
   11.54 +/* A structure that encodes the stable unique id for a joystick device */
   11.55 +typedef struct
   11.56 +{
   11.57 +	Uint8 data[16];
   11.58 +} JoystickGUID;
   11.59 +
   11.60 +/**
   11.61 + *  Return the GUID for the joystick at this index
   11.62   */
   11.63 -extern DECLSPEC int SDLCALL SDL_JoystickOpened(int device_index);
   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 +        SDL_SYS_JoystickUpdate( joystick );
  17.486  
  17.487 -    for (i = 0; SDL_joysticks[i]; ++i) {
  17.488 -        SDL_SYS_JoystickUpdate(SDL_joysticks[i]);
  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: */
    21.1 --- a/src/joystick/darwin/SDL_sysjoystick.c	Mon Nov 26 14:59:07 2012 -0800
    21.2 +++ b/src/joystick/darwin/SDL_sysjoystick.c	Mon Nov 26 16:37:54 2012 -0800
    21.3 @@ -42,6 +42,7 @@
    21.4  #include <IOKit/hid/IOHIDKeys.h>
    21.5  #include <CoreFoundation/CoreFoundation.h>
    21.6  #include <Carbon/Carbon.h>      /* for NewPtrClear, DisposePtr */
    21.7 +#include <IOKit/IOMessage.h>
    21.8  
    21.9  /* For force feedback testing. */
   21.10  #include <ForceFeedback/ForceFeedback.h>
   21.11 @@ -51,11 +52,21 @@
   21.12  #include "../SDL_sysjoystick.h"
   21.13  #include "../SDL_joystick_c.h"
   21.14  #include "SDL_sysjoystick_c.h"
   21.15 +#include "SDL_events.h"
   21.16 +#if !SDL_EVENTS_DISABLED
   21.17 +#include "../../events/SDL_events_c.h"
   21.18 +#endif
   21.19  
   21.20  
   21.21  /* Linked list of all available devices */
   21.22  static recDevice *gpDeviceList = NULL;
   21.23 +/* OSX reference to the notification object that tells us about device insertion/removal */
   21.24 +IONotificationPortRef notificationPort = 0;
   21.25 +/* if 1 then a device was added since the last update call */
   21.26 +Uint8 s_bDeviceAdded = 0;
   21.27  
   21.28 +/* static incrementing counter for new joystick devices seen on the system. Devices should start with index 0 */
   21.29 +static int s_joystick_instance_id = -1;
   21.30  
   21.31  static void
   21.32  HIDReportErrorNum(char *strError, long numError)
   21.33 @@ -115,10 +126,20 @@
   21.34  {
   21.35      recDevice *device = (recDevice *) refcon;
   21.36      device->removed = 1;
   21.37 -    device->uncentered = 1;
   21.38  }
   21.39  
   21.40  
   21.41 +/* Called by the io port notifier on removal of this device
   21.42 + */
   21.43 +void JoystickDeviceWasRemovedCallback( void * refcon, io_service_t service, natural_t messageType, void * messageArgument )
   21.44 +{
   21.45 +    if( messageType == kIOMessageServiceIsTerminated && refcon )
   21.46 +    {
   21.47 +		recDevice *device = (recDevice *) refcon;
   21.48 +		device->removed = 1;
   21.49 +	}
   21.50 +}
   21.51 +
   21.52  
   21.53  /* Create and open an interface to device, required prior to extracting values or building queues.
   21.54   * Note: appliction now owns the device and must close and release it prior to exiting
   21.55 @@ -162,9 +183,33 @@
   21.56              HIDReportErrorNum
   21.57                  ("Failed to open pDevice->interface via open.", result);
   21.58          else
   21.59 +		{
   21.60 +			pDevice->portIterator = 0;
   21.61 +
   21.62 +			// It's okay if this fails, we have another detection method below
   21.63              (*(pDevice->interface))->setRemovalCallback(pDevice->interface,
   21.64                                                          HIDRemovalCallback,
   21.65                                                          pDevice, pDevice);
   21.66 +			
   21.67 +			/* now connect notification for new devices */
   21.68 +			pDevice->notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
   21.69 +			
   21.70 +			CFRunLoopAddSource(CFRunLoopGetCurrent(), 
   21.71 +							   IONotificationPortGetRunLoopSource(pDevice->notificationPort), 
   21.72 +							   kCFRunLoopDefaultMode);
   21.73 +			
   21.74 +			// Register for notifications when a serial port is added to the system
   21.75 +			result = IOServiceAddInterestNotification(pDevice->notificationPort,
   21.76 +													  hidDevice,
   21.77 +													  kIOGeneralInterest,
   21.78 +													  JoystickDeviceWasRemovedCallback,
   21.79 +													  pDevice,           
   21.80 +													  &pDevice->portIterator);
   21.81 +        	if (kIOReturnSuccess != result) {
   21.82 +            	HIDReportErrorNum
   21.83 +                	("Failed to register for removal callback.", result);		
   21.84 +			}	
   21.85 +		}
   21.86  
   21.87      }
   21.88      return result;
   21.89 @@ -195,6 +240,12 @@
   21.90              HIDReportErrorNum("Failed to release IOHIDDeviceInterface.",
   21.91                                result);
   21.92          pDevice->interface = NULL;
   21.93 +		
   21.94 +		if ( pDevice->portIterator )
   21.95 +		{
   21.96 +			IOObjectRelease( pDevice->portIterator );
   21.97 +			pDevice->portIterator = 0;
   21.98 +		}
   21.99      }
  21.100      return result;
  21.101  }
  21.102 @@ -461,6 +512,26 @@
  21.103                              ("CFNumberGetValue error retrieving pDevice->usage.");
  21.104              }
  21.105  
  21.106 +			refCF =
  21.107 +			CFDictionaryGetValue(hidProperties,
  21.108 +								 CFSTR(kIOHIDVendorIDKey));
  21.109 +            if (refCF) {
  21.110 +                if (!CFNumberGetValue
  21.111 +                    (refCF, kCFNumberLongType, &pDevice->guid.data[0]))
  21.112 +                    SDL_SetError
  21.113 +					("CFNumberGetValue error retrieving pDevice->guid.");
  21.114 +            }
  21.115 +			refCF =
  21.116 +			CFDictionaryGetValue(hidProperties,
  21.117 +								 CFSTR(kIOHIDProductIDKey));
  21.118 +            if (refCF) {
  21.119 +                if (!CFNumberGetValue
  21.120 +                    (refCF, kCFNumberLongType, &pDevice->guid.data[8]))
  21.121 +                    SDL_SetError
  21.122 +					("CFNumberGetValue error retrieving pDevice->guid[8].");
  21.123 +            }
  21.124 +
  21.125 +			
  21.126              if (NULL == refCF) {        /* get top level element HID usage page or usage */
  21.127                  /* use top level element instead */
  21.128                  CFTypeRef refCFTopElement = 0;
  21.129 @@ -505,6 +576,7 @@
  21.130              if (kIOReturnSuccess == result) {
  21.131                  HIDGetDeviceInfo(hidDevice, hidProperties, pDevice);    /* hidDevice used to find parents in registry tree */
  21.132                  HIDGetCollectionElements(hidProperties, pDevice);
  21.133 +				pDevice->instance_id = ++s_joystick_instance_id;
  21.134              } else {
  21.135                  DisposePtr((Ptr) pDevice);
  21.136                  pDevice = NULL;
  21.137 @@ -569,6 +641,79 @@
  21.138  }
  21.139  
  21.140  
  21.141 +/* Given an io_object_t from OSX adds a joystick device to our list if appropriate
  21.142 + */
  21.143 +int 
  21.144 +AddDeviceHelper( io_object_t ioHIDDeviceObject )
  21.145 +{
  21.146 +    recDevice *device;
  21.147 +	
  21.148 +	/* build a device record */
  21.149 +	device = HIDBuildDevice(ioHIDDeviceObject);
  21.150 +	if (!device)
  21.151 +		return 0;
  21.152 +	
  21.153 +	/* Filter device list to non-keyboard/mouse stuff */
  21.154 +	if ((device->usagePage != kHIDPage_GenericDesktop) ||
  21.155 +		((device->usage != kHIDUsage_GD_Joystick &&
  21.156 +		  device->usage != kHIDUsage_GD_GamePad &&
  21.157 +		  device->usage != kHIDUsage_GD_MultiAxisController))) {
  21.158 +		
  21.159 +		/* release memory for the device */
  21.160 +		HIDDisposeDevice(&device);
  21.161 +		DisposePtr((Ptr) device);
  21.162 +		return 0;
  21.163 +	}
  21.164 +	
  21.165 +	/* We have to do some storage of the io_service_t for
  21.166 +	 * SDL_HapticOpenFromJoystick */
  21.167 +	if (FFIsForceFeedback(ioHIDDeviceObject) == FF_OK) {
  21.168 +		device->ffservice = ioHIDDeviceObject;
  21.169 +	} else {
  21.170 +		device->ffservice = 0;
  21.171 +	}
  21.172 +	
  21.173 +	device->send_open_event = 1;
  21.174 +	s_bDeviceAdded = 1;
  21.175 +	
  21.176 +	/* Add device to the end of the list */
  21.177 +	if ( !gpDeviceList )
  21.178 +	{
  21.179 +		gpDeviceList = device;
  21.180 +	}
  21.181 +	else
  21.182 +	{
  21.183 +		recDevice *curdevice;
  21.184 +		
  21.185 +		curdevice = gpDeviceList;
  21.186 +		while ( curdevice->pNext )
  21.187 +		{
  21.188 +			curdevice = curdevice->pNext;
  21.189 +		}
  21.190 +		curdevice->pNext = device;
  21.191 +	}
  21.192 +	
  21.193 +	return 1;
  21.194 +}
  21.195 +
  21.196 +
  21.197 +/* Called by our IO port notifier on the master port when a HID device is inserted, we iterate
  21.198 + *  and check for new joysticks
  21.199 + */
  21.200 +void JoystickDeviceWasAddedCallback( void *refcon, io_iterator_t iterator )
  21.201 +{
  21.202 +    io_object_t ioHIDDeviceObject = 0;
  21.203 +	
  21.204 +	while ( ( ioHIDDeviceObject = IOIteratorNext(iterator) ) )
  21.205 +	{
  21.206 +		if ( ioHIDDeviceObject )
  21.207 +		{
  21.208 +			AddDeviceHelper( ioHIDDeviceObject );			
  21.209 +		}
  21.210 +	}
  21.211 +}
  21.212 +				
  21.213 +
  21.214  /* Function to scan the system for joysticks.
  21.215   * Joystick 0 should be the system default joystick.
  21.216   * This function should return the number of available joysticks, or -1
  21.217 @@ -581,10 +726,8 @@
  21.218      mach_port_t masterPort = 0;
  21.219      io_iterator_t hidObjectIterator = 0;
  21.220      CFMutableDictionaryRef hidMatchDictionary = NULL;
  21.221 -    recDevice *device, *lastDevice;
  21.222      io_object_t ioHIDDeviceObject = 0;
  21.223 -
  21.224 -    SDL_numjoysticks = 0;
  21.225 +	io_iterator_t portIterator = 0;
  21.226  
  21.227      if (gpDeviceList) {
  21.228          SDL_SetError("Joystick: Device list already inited.");
  21.229 @@ -629,70 +772,49 @@
  21.230      }
  21.231      if (!hidObjectIterator) {   /* there are no joysticks */
  21.232          gpDeviceList = NULL;
  21.233 -        SDL_numjoysticks = 0;
  21.234          return 0;
  21.235      }
  21.236      /* IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. */
  21.237  
  21.238      /* build flat linked list of devices from device iterator */
  21.239  
  21.240 -    gpDeviceList = lastDevice = NULL;
  21.241 +    gpDeviceList = NULL;
  21.242  
  21.243      while ((ioHIDDeviceObject = IOIteratorNext(hidObjectIterator))) {
  21.244 -        /* build a device record */
  21.245 -        device = HIDBuildDevice(ioHIDDeviceObject);
  21.246 -        if (!device)
  21.247 -            continue;
  21.248 -
  21.249 -        /* Filter device list to non-keyboard/mouse stuff */
  21.250 -        if ((device->usagePage != kHIDPage_GenericDesktop) ||
  21.251 -            ((device->usage != kHIDUsage_GD_Joystick &&
  21.252 -              device->usage != kHIDUsage_GD_GamePad &&
  21.253 -              device->usage != kHIDUsage_GD_MultiAxisController))) {
  21.254 -
  21.255 -            /* release memory for the device */
  21.256 -            HIDDisposeDevice(&device);
  21.257 -            DisposePtr((Ptr) device);
  21.258 -            continue;
  21.259 -        }
  21.260 -
  21.261 -        /* We have to do some storage of the io_service_t for
  21.262 -         * SDL_HapticOpenFromJoystick */
  21.263 -        if (FFIsForceFeedback(ioHIDDeviceObject) == FF_OK) {
  21.264 -            device->ffservice = ioHIDDeviceObject;
  21.265 -        } else {
  21.266 -            device->ffservice = 0;
  21.267 -        }
  21.268 -
  21.269 -        /* Add device to the end of the list */
  21.270 -        if (lastDevice)
  21.271 -            lastDevice->pNext = device;
  21.272 -        else
  21.273 -            gpDeviceList = device;
  21.274 -        lastDevice = device;
  21.275 +		AddDeviceHelper( ioHIDDeviceObject );
  21.276      }
  21.277      result = IOObjectRelease(hidObjectIterator);        /* release the iterator */
  21.278 +	
  21.279 +	/* now connect notification for new devices */
  21.280 +	notificationPort = IONotificationPortCreate(masterPort);
  21.281 +	hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey);
  21.282  
  21.283 -    /* Count the total number of devices we found */
  21.284 -    device = gpDeviceList;
  21.285 -    while (device) {
  21.286 -        SDL_numjoysticks++;
  21.287 -        device = device->pNext;
  21.288 -    }
  21.289 +	CFRunLoopAddSource(CFRunLoopGetCurrent(), 
  21.290 +					   IONotificationPortGetRunLoopSource(notificationPort), 
  21.291 +					   kCFRunLoopDefaultMode);
  21.292 +	
  21.293 +	// Register for notifications when a serial port is added to the system
  21.294 +	result = IOServiceAddMatchingNotification(notificationPort,
  21.295 +															kIOFirstMatchNotification,
  21.296 +															hidMatchDictionary,
  21.297 +															JoystickDeviceWasAddedCallback,
  21.298 +															NULL,           
  21.299 +															&portIterator);
  21.300 +	while (IOIteratorNext(portIterator)) {}; // Run out the iterator or notifications won't start (you can also use it to iterate the available devices).
  21.301  
  21.302 -    return SDL_numjoysticks;
  21.303 +    return SDL_SYS_NumJoysticks();
  21.304  }
  21.305  
  21.306  /* Function to get the device-dependent name of a joystick */
  21.307  const char *
  21.308 -SDL_SYS_JoystickName(int index)
  21.309 +SDL_SYS_JoystickNameForIndex(int index)
  21.310  {
  21.311      recDevice *device = gpDeviceList;
  21.312  
  21.313      for (; index > 0; index--)
  21.314          device = device->pNext;
  21.315  
  21.316 -    return device->product;
  21.317 +	return device->product;
  21.318  }
  21.319  
  21.320  /* Function to open a joystick for use.
  21.321 @@ -701,25 +823,77 @@
  21.322   * It returns 0, or -1 if there is an error.
  21.323   */
  21.324  int
  21.325 -SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
  21.326 +SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
  21.327  {
  21.328      recDevice *device = gpDeviceList;
  21.329      int index;
  21.330  
  21.331 -    for (index = joystick->index; index > 0; index--)
  21.332 +    for (index = device_index; index > 0; index--)
  21.333          device = device->pNext;
  21.334  
  21.335      joystick->hwdata = device;
  21.336 -    joystick->name = device->product;
  21.337 +	joystick->instance_id = device->instance_id;
  21.338 +	joystick->name = device->product;
  21.339  
  21.340 -    joystick->naxes = device->axes;
  21.341 -    joystick->nhats = device->hats;
  21.342 -    joystick->nballs = 0;
  21.343 -    joystick->nbuttons = device->buttons;
  21.344 -
  21.345 +	joystick->naxes = device->axes;
  21.346 +	joystick->nhats = device->hats;
  21.347 +	joystick->nballs = 0;
  21.348 +	joystick->nbuttons = device->buttons;
  21.349      return 0;
  21.350  }
  21.351  
  21.352 +
  21.353 +/* Function to return the instance id of the joystick at device_index
  21.354 + */
  21.355 +SDL_JoystickID
  21.356 +SDL_SYS_GetInstanceIdOfDeviceIndex( int device_index )
  21.357 +{
  21.358 +    recDevice *device = gpDeviceList;
  21.359 +    int index;
  21.360 +	
  21.361 +    for (index = device_index; index > 0; index--)
  21.362 +        device = device->pNext;
  21.363 +
  21.364 +	return device->instance_id;
  21.365 +}
  21.366 +
  21.367 +
  21.368 +/* Function to cause any queued joystick insertions to be processed
  21.369 + */
  21.370 +void
  21.371 +SDL_SYS_JoystickDetect()
  21.372 +{
  21.373 +	if ( s_bDeviceAdded )
  21.374 +	{
  21.375 +		recDevice *device = gpDeviceList;
  21.376 +		s_bDeviceAdded = 0;
  21.377 +		int device_index = 0;
  21.378 +		// send notifications
  21.379 +		while ( device )
  21.380 +		{
  21.381 +			if ( device->send_open_event )
  21.382 +			{
  21.383 +				device->send_open_event = 0;
  21.384 +#if !SDL_EVENTS_DISABLED
  21.385 +				SDL_Event event;
  21.386 +				event.type = SDL_JOYDEVICEADDED;
  21.387 +				
  21.388 +				if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  21.389 +					event.jdevice.which = device_index;
  21.390 +					if ((SDL_EventOK == NULL)
  21.391 +						|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
  21.392 +						SDL_PushEvent(&event);
  21.393 +					}
  21.394 +				}
  21.395 +#endif /* !SDL_EVENTS_DISABLED */
  21.396 +			}
  21.397 +			device_index++;
  21.398 +			device = device->pNext;
  21.399 +		}
  21.400 +	}
  21.401 +}
  21.402 +
  21.403 +
  21.404  /* Function to update the state of a joystick - called as a device poll.
  21.405   * This function shouldn't update the joystick structure directly,
  21.406   * but instead should call SDL_PrivateJoystick*() to deliver events
  21.407 @@ -728,26 +902,49 @@
  21.408  void
  21.409  SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
  21.410  {
  21.411 -    recDevice *device = joystick->hwdata;
  21.412 +	recDevice *device = joystick->hwdata;
  21.413      recElement *element;
  21.414      SInt32 value, range;
  21.415      int i;
  21.416  
  21.417 -    if (device->removed) {      /* device was unplugged; ignore it. */
  21.418 -        if (device->uncentered) {
  21.419 -            device->uncentered = 0;
  21.420 -
  21.421 -            /* Tell the app that everything is centered/unpressed... */
  21.422 -            for (i = 0; i < device->axes; i++)
  21.423 -                SDL_PrivateJoystickAxis(joystick, i, 0);
  21.424 +	if ( !device )
  21.425 +		return;
  21.426  
  21.427 -            for (i = 0; i < device->buttons; i++)
  21.428 -                SDL_PrivateJoystickButton(joystick, i, 0);
  21.429 +    if (device->removed) {      /* device was unplugged; ignore it. */
  21.430 +		recDevice *devicelist = gpDeviceList;
  21.431 +		joystick->closed = 1;
  21.432 +		joystick->uncentered = 1;
  21.433 +		
  21.434 +		if ( devicelist == device )
  21.435 +		{
  21.436 +			gpDeviceList = device->pNext;
  21.437 +		}
  21.438 +		else
  21.439 +		{
  21.440 +			while ( devicelist->pNext != device )
  21.441 +			{
  21.442 +				devicelist = devicelist->pNext;
  21.443 +			}
  21.444 +			
  21.445 +			devicelist->pNext = device->pNext;
  21.446 +		}
  21.447 +		
  21.448 +		DisposePtr((Ptr) device);
  21.449 +		joystick->hwdata = NULL;
  21.450  
  21.451 -            for (i = 0; i < device->hats; i++)
  21.452 -                SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
  21.453 -        }
  21.454 -
  21.455 +#if !SDL_EVENTS_DISABLED
  21.456 +		SDL_Event event;
  21.457 +		event.type = SDL_JOYDEVICEREMOVED;
  21.458 +		
  21.459 +		if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  21.460 +			event.jdevice.which = joystick->instance_id;
  21.461 +			if ((SDL_EventOK == NULL)
  21.462 +				|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
  21.463 +				SDL_PushEvent(&event);
  21.464 +			}
  21.465 +		}
  21.466 +#endif /* !SDL_EVENTS_DISABLED */
  21.467 +		
  21.468          return;
  21.469      }
  21.470  
  21.471 @@ -826,12 +1023,33 @@
  21.472      return;
  21.473  }
  21.474  
  21.475 +
  21.476 +/* Function to query if the joystick is currently attached
  21.477 + *   It returns 1 if attached, 0 otherwise.
  21.478 + */
  21.479 +int
  21.480 +SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
  21.481 +{
  21.482 +	recDevice *device = gpDeviceList;
  21.483 +    int index;
  21.484 +	
  21.485 +	while ( device )
  21.486 +	{
  21.487 +		if ( joystick->instance_id == device->instance_id )
  21.488 +			return (1);
  21.489 +		
  21.490 +        device = device->pNext;
  21.491 +	}
  21.492 +	
  21.493 +	return 0;
  21.494 +}
  21.495 +
  21.496 +
  21.497  /* Function to close a joystick after use */
  21.498  void
  21.499  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
  21.500 -{
  21.501 -    /* Should we do anything here? */
  21.502 -    return;
  21.503 +{	
  21.504 +	joystick->closed = 1;
  21.505  }
  21.506  
  21.507  /* Function to perform any system-specific joystick related cleanup */
  21.508 @@ -840,6 +1058,51 @@
  21.509  {
  21.510      while (NULL != gpDeviceList)
  21.511          gpDeviceList = HIDDisposeDevice(&gpDeviceList);
  21.512 +	
  21.513 +	if ( notificationPort )
  21.514 +	{
  21.515 +		IONotificationPortDestroy( notificationPort );
  21.516 +		notificationPort = 0;
  21.517 +	}
  21.518 +}
  21.519 +
  21.520 +
  21.521 +/* Function to return the number of joystick devices plugged in right now*/
  21.522 +int
  21.523 +SDL_SYS_NumJoysticks()
  21.524 +{
  21.525 +	recDevice *device = gpDeviceList;
  21.526 +    int nJoySticks = 0;
  21.527 +	
  21.528 +	while ( device )
  21.529 +	{
  21.530 +		nJoySticks++;
  21.531 +        device = device->pNext;
  21.532 +	}
  21.533 +
  21.534 +	return nJoySticks;
  21.535 +}
  21.536 +
  21.537 +int
  21.538 +SDL_SYS_JoystickNeedsPolling()
  21.539 +{
  21.540 +	return s_bDeviceAdded;
  21.541 +}
  21.542 +
  21.543 +JoystickGUID SDL_SYS_PrivateJoystickGetDeviceID( int device_index )
  21.544 +{
  21.545 +    recDevice *device = gpDeviceList;
  21.546 +    int index;
  21.547 +	
  21.548 +    for (index = device_index; index > 0; index--)
  21.549 +        device = device->pNext;
  21.550 +	
  21.551 +	return device->guid;	
  21.552 +}
  21.553 +
  21.554 +JoystickGUID SDL_SYS_PrivateJoystickGetGUID(SDL_Joystick *joystick)
  21.555 +{
  21.556 +	return joystick->hwdata->guid;
  21.557  }
  21.558  
  21.559  #endif /* SDL_JOYSTICK_IOKIT */
    22.1 --- a/src/joystick/darwin/SDL_sysjoystick_c.h	Mon Nov 26 14:59:07 2012 -0800
    22.2 +++ b/src/joystick/darwin/SDL_sysjoystick_c.h	Mon Nov 26 16:37:54 2012 -0800
    22.3 @@ -25,6 +25,7 @@
    22.4  
    22.5  #include <IOKit/hid/IOHIDLib.h>
    22.6  #include <IOKit/hid/IOHIDKeys.h>
    22.7 +#include <IOKit/IOKitLib.h>
    22.8  
    22.9  
   22.10  struct recElement
   22.11 @@ -58,7 +59,9 @@
   22.12  {
   22.13      io_service_t ffservice;     /* Interface for force feedback, 0 = no ff */
   22.14      IOHIDDeviceInterface **interface;   /* interface to device, NULL = no interface */
   22.15 -
   22.16 +	IONotificationPortRef notificationPort; /* port to be notified on joystick removal */
   22.17 +	io_iterator_t portIterator; /* iterator for removal callback */
   22.18 +	
   22.19      char product[256];          /* name of product */
   22.20      long usage;                 /* usage page from IOUSBHID Parser.h which defines general usage */
   22.21      long usagePage;             /* usage within above page from IOUSBHID Parser.h which defines specific usage */
   22.22 @@ -74,6 +77,10 @@
   22.23  
   22.24      int removed;
   22.25      int uncentered;
   22.26 +	
   22.27 +	int instance_id;
   22.28 +	JoystickGUID guid;
   22.29 +	Uint8 send_open_event;		/* 1 if we need to send an Added event for this device */
   22.30  
   22.31      struct joystick_hwdata *pNext;      /* next device */
   22.32  };
    25.1 --- a/src/joystick/linux/SDL_sysjoystick.c	Mon Nov 26 14:59:07 2012 -0800
    25.2 +++ b/src/joystick/linux/SDL_sysjoystick.c	Mon Nov 26 16:37:54 2012 -0800
    25.3 @@ -298,7 +298,7 @@
    25.4      ret = 0;
    25.5  
    25.6      for (i = 0; i < max; i++) {
    25.7 -        name = SDL_SYS_JoystickName(i);
    25.8 +        name = SDL_SYS_JoystickNameForIndex(i);
    25.9  
   25.10          fd = open(SDL_joylist[i].fname, O_RDONLY, 0);
   25.11          if (fd >= 0) {
   25.12 @@ -390,6 +390,8 @@
   25.13  
   25.14  #endif /* SDL_INPUT_LINUXEV */
   25.15  
   25.16 +int SDL_SYS_numjoysticks = 0;
   25.17 +
   25.18  /* Function to scan the system for joysticks */
   25.19  int
   25.20  SDL_SYS_JoystickInit(void)
   25.21 @@ -491,7 +493,7 @@
   25.22             will be duplicates but without extra information about their
   25.23             hats or balls. Unfortunately, the event devices can't
   25.24             currently be calibrated, so it's a win-lose situation.
   25.25 -           So : /dev/input/eventX = /dev/input/jsY = /dev/jsY
   25.26 +           So : /dev/input/eventX = /dev/input/jsY = /dev/js
   25.27           */
   25.28          if ((i == 0) && (numjoysticks > 0))
   25.29              break;
   25.30 @@ -501,12 +503,13 @@
   25.31      numjoysticks += CountLogicalJoysticks(numjoysticks);
   25.32  #endif
   25.33  
   25.34 +    SDL_SYS_numjoysticks = numjoysticks;
   25.35      return (numjoysticks);
   25.36  }
   25.37  
   25.38  /* Function to get the device-dependent name of a joystick */
   25.39  const char *
   25.40 -SDL_SYS_JoystickName(int index)
   25.41 +SDL_SYS_JoystickNameForIndex(int index)
   25.42  {
   25.43      int fd;
   25.44      static char namebuf[128];
   25.45 @@ -601,7 +604,7 @@
   25.46          joystick->nbuttons = n;
   25.47      }
   25.48  
   25.49 -    name = SDL_SYS_JoystickName(joystick->index);
   25.50 +    name = SDL_SYS_JoystickNameForIndex(joystick->instance_id);
   25.51  
   25.52      /* Generic analog joystick support */
   25.53      if (SDL_strstr(name, "Analog") == name && SDL_strstr(name, "-hat")) {
   25.54 @@ -774,8 +777,8 @@
   25.55  {
   25.56      struct joystick_logical_layout *layout;
   25.57  
   25.58 -    layout = SDL_joylist[joystick->index].map->layout +
   25.59 -        SDL_joylist[joystick->index].logicalno;
   25.60 +    layout = SDL_joylist[joystick->instance_id].map->layout +
   25.61 +        SDL_joylist[joystick->instance_id].logicalno;
   25.62  
   25.63      joystick->nbuttons = layout->nbuttons;
   25.64      joystick->nhats = layout->nhats;
   25.65 @@ -791,7 +794,7 @@
   25.66     It returns 0, or -1 if there is an error.
   25.67   */
   25.68  int
   25.69 -SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
   25.70 +SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
   25.71  {
   25.72      int fd;
   25.73      char *fname;
   25.74 @@ -800,8 +803,8 @@
   25.75  
   25.76      /* Open the joystick and set the joystick file descriptor */
   25.77  #ifndef NO_LOGICAL_JOYSTICKS
   25.78 -    if (SDL_joylist[joystick->index].fname == NULL) {
   25.79 -        SDL_joylist_head(realindex, joystick->index);
   25.80 +    if (SDL_joylist[joystick->instance_id].fname == NULL) {
   25.81 +        SDL_joylist_head(realindex, joystick->instance_id);
   25.82          realjoy = SDL_JoystickOpen(realindex);
   25.83  
   25.84          if (realjoy == NULL)
   25.85 @@ -811,17 +814,17 @@
   25.86          fname = realjoy->hwdata->fname;
   25.87  
   25.88      } else {
   25.89 -        fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
   25.90 -        fname = SDL_joylist[joystick->index].fname;
   25.91 +        fd = open(SDL_joylist[joystick->instance_id].fname, O_RDONLY, 0);
   25.92 +        fname = SDL_joylist[joystick->instance_id].fname;
   25.93      }
   25.94 -    SDL_joylist[joystick->index].joy = joystick;
   25.95 +    SDL_joylist[joystick->instance_id].joy = joystick;
   25.96  #else
   25.97 -    fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
   25.98 -    fname = SDL_joylist[joystick->index].fname;
   25.99 +    fd = open(SDL_joylist[joystick->instance_id].fname, O_RDONLY, 0);
  25.100 +    fname = SDL_joylist[joystick->instance_id].fname;
  25.101  #endif
  25.102  
  25.103      if (fd < 0) {
  25.104 -        SDL_SetError("Unable to open %s\n", SDL_joylist[joystick->index]);
  25.105 +        SDL_SetError("Unable to open %s\n", SDL_joylist[joystick->instance_id]);
  25.106          return (-1);
  25.107      }
  25.108      joystick->hwdata = (struct joystick_hwdata *)
  25.109 @@ -834,6 +837,7 @@
  25.110      SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
  25.111      joystick->hwdata->fd = fd;
  25.112      joystick->hwdata->fname = fname;
  25.113 +    joystick->instance_id = device_index;
  25.114  
  25.115      /* Set the joystick to non-blocking read mode */
  25.116      fcntl(fd, F_SETFL, O_NONBLOCK);
  25.117 @@ -861,7 +865,7 @@
  25.118      SDL_Joystick *logicaljoy;
  25.119      register int i;
  25.120  
  25.121 -    i = joystick->index;
  25.122 +    i = joystick->instance_id;
  25.123      logicaljoy = NULL;
  25.124  
  25.125      /* get the fake joystick that will receive the event
  25.126 @@ -891,12 +895,12 @@
  25.127  
  25.128      /* if there's no map then this is just a regular joystick
  25.129       */
  25.130 -    if (SDL_joylist[joystick->index].map == NULL)
  25.131 +    if (SDL_joylist[joystick->instance_id].map == NULL)
  25.132          return 0;
  25.133  
  25.134      /* get the logical joystick that will receive the event
  25.135       */
  25.136 -    buttons = SDL_joylist[joystick->index].map->buttonmap + button;
  25.137 +    buttons = SDL_joylist[joystick->instance_id].map->buttonmap + button;
  25.138      logicaljoy = FindLogicalJoystick(joystick, buttons);
  25.139  
  25.140      if (logicaljoy == NULL)
  25.141 @@ -915,12 +919,12 @@
  25.142  
  25.143      /* if there's no map then this is just a regular joystick
  25.144       */
  25.145 -    if (SDL_joylist[joystick->index].map == NULL)
  25.146 +    if (SDL_joylist[joystick->instance_id].map == NULL)
  25.147          return 0;
  25.148  
  25.149      /* get the logical joystick that will receive the event
  25.150       */
  25.151 -    axes = SDL_joylist[joystick->index].map->axismap + axis;
  25.152 +    axes = SDL_joylist[joystick->instance_id].map->axismap + axis;
  25.153      logicaljoy = FindLogicalJoystick(joystick, axes);
  25.154  
  25.155      if (logicaljoy == NULL)
  25.156 @@ -958,11 +962,11 @@
  25.157  #ifndef NO_LOGICAL_JOYSTICKS
  25.158          /* if there's no map then this is just a regular joystick
  25.159           */
  25.160 -        if (SDL_joylist[stick->index].map != NULL) {
  25.161 +        if (SDL_joylist[stick->instance_id].map != NULL) {
  25.162  
  25.163              /* get the fake joystick that will receive the event
  25.164               */
  25.165 -            hats = SDL_joylist[stick->index].map->hatmap + hat;
  25.166 +            hats = SDL_joylist[stick->instance_id].map->hatmap + hat;
  25.167              logicaljoy = FindLogicalJoystick(stick, hats);
  25.168          }
  25.169  
  25.170 @@ -997,8 +1001,8 @@
  25.171      Uint8 other_axis;
  25.172  
  25.173  #ifndef NO_LOGICAL_JOYSTICKS
  25.174 -    if (SDL_joylist[joystick->index].fname == NULL) {
  25.175 -        SDL_joylist_head(i, joystick->index);
  25.176 +    if (SDL_joylist[joystick->instance_id].fname == NULL) {
  25.177 +        SDL_joylist_head(i, joystick->instance_id);
  25.178          JS_HandleEvents(SDL_joylist[i].joy);
  25.179          return;
  25.180      }
  25.181 @@ -1089,8 +1093,8 @@
  25.182      int code;
  25.183  
  25.184  #ifndef NO_LOGICAL_JOYSTICKS
  25.185 -    if (SDL_joylist[joystick->index].fname == NULL) {
  25.186 -        SDL_joylist_head(i, joystick->index);
  25.187 +    if (SDL_joylist[joystick->instance_id].fname == NULL) {
  25.188 +        SDL_joylist_head(i, joystick->instance_id);
  25.189          return EV_HandleEvents(SDL_joylist[i].joy);
  25.190      }
  25.191  #endif
  25.192 @@ -1198,15 +1202,15 @@
  25.193  {
  25.194  #ifndef NO_LOGICAL_JOYSTICKS
  25.195      register int i;
  25.196 -    if (SDL_joylist[joystick->index].fname == NULL) {
  25.197 -        SDL_joylist_head(i, joystick->index);
  25.198 +    if (SDL_joylist[joystick->instance_id].fname == NULL) {
  25.199 +        SDL_joylist_head(i, joystick->instance_id);
  25.200          SDL_JoystickClose(SDL_joylist[i].joy);
  25.201      }
  25.202  #endif
  25.203  
  25.204      if (joystick->hwdata) {
  25.205  #ifndef NO_LOGICAL_JOYSTICKS
  25.206 -        if (SDL_joylist[joystick->index].fname != NULL)
  25.207 +        if (SDL_joylist[joystick->instance_id].fname != NULL)
  25.208  #endif
  25.209              close(joystick->hwdata->fd);
  25.210          if (joystick->hwdata->hats) {
  25.211 @@ -1218,6 +1222,7 @@
  25.212          SDL_free(joystick->hwdata);
  25.213          joystick->hwdata = NULL;
  25.214      }
  25.215 +    joystick->closed = 1;
  25.216  }
  25.217  
  25.218  /* Function to perform any system-specific joystick related cleanup */
  25.219 @@ -1234,5 +1239,50 @@
  25.220      }
  25.221  }
  25.222  
  25.223 +/* Function to perform the mapping from device index to the instance id for this index */
  25.224 +SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int index)
  25.225 +{
  25.226 +    return index;
  25.227 +}
  25.228 +
  25.229 +/* Function to determine is this joystick is attached to the system right now */
  25.230 +int SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
  25.231 +{
  25.232 +    return joystick->closed;
  25.233 +}
  25.234 +
  25.235 +int SDL_SYS_NumJoysticks()
  25.236 +{
  25.237 +    return SDL_SYS_numjoysticks;
  25.238 +}
  25.239 +
  25.240 +int SDL_SYS_JoystickNeedsPolling()
  25.241 +{
  25.242 +    return 0;
  25.243 +}
  25.244 +
  25.245 +void SDL_SYS_JoystickDetect()
  25.246 +{
  25.247 +}
  25.248 +
  25.249 +JoystickGUID SDL_SYS_PrivateJoystickGetDeviceID( int device_index )
  25.250 +{
  25.251 +    static JoystickGUID guid;
  25.252 +    // the GUID is just the first 16 chars of the name for now
  25.253 +    const char *name = SDL_SYS_JoystickNameForIndex( device_index );
  25.254 +    SDL_memcpy( &guid, name, sizeof(guid) );
  25.255 +    return guid;
  25.256 +}
  25.257 +
  25.258 +
  25.259 +JoystickGUID SDL_SYS_PrivateJoystickGetGUID(SDL_Joystick * joystick)
  25.260 +{
  25.261 +    static JoystickGUID guid;
  25.262 +    // the GUID is just the first 16 chars of the name for now
  25.263 +    const char *name = SDL_SYS_JoystickNameForIndex( joystick->name );
  25.264 +    SDL_memcpy( &guid, name, sizeof(guid) );
  25.265 +    return guid;
  25.266 +}
  25.267 +
  25.268  #endif /* SDL_JOYSTICK_LINUX */
  25.269  /* vi: set ts=4 sw=4 expandtab: */
    26.1 --- a/src/joystick/windows/SDL_dxjoystick.c	Mon Nov 26 14:59:07 2012 -0800
    26.2 +++ b/src/joystick/windows/SDL_dxjoystick.c	Mon Nov 26 16:37:54 2012 -0800
    26.3 @@ -29,17 +29,22 @@
    26.4   * doesn't use them and I don't own any joysticks with them. 
    26.5   *
    26.6   * We don't bother to use event notification here.  It doesn't seem to work
    26.7 - * with polled devices, and it's fine to call IDirectInputDevice2_GetDeviceData and
    26.8 + * with polled devices, and it's fine to call IDirectInputDevice8_GetDeviceData and
    26.9   * let it return 0 events. */
   26.10  
   26.11  #include "SDL_error.h"
   26.12  #include "SDL_events.h"
   26.13  #include "SDL_joystick.h"
   26.14  #include "../SDL_sysjoystick.h"
   26.15 -#include "../SDL_joystick_c.h"
   26.16  #define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
   26.17  #include "SDL_dxjoystick_c.h"
   26.18 -
   26.19 +#include "SDL_thread.h"
   26.20 +#include "SDL_timer.h"
   26.21 +#include "SDL_mutex.h"
   26.22 +#include "SDL_events.h"
   26.23 +#if !SDL_EVENTS_DISABLED
   26.24 +#include "../../events/SDL_events_c.h"
   26.25 +#endif
   26.26  
   26.27  #ifndef DIDFT_OPTIONAL
   26.28  #define DIDFT_OPTIONAL		0x80000000
   26.29 @@ -47,7 +52,7 @@
   26.30  
   26.31  
   26.32  #define INPUT_QSIZE	32      /* Buffer up to 32 input messages */
   26.33 -#define MAX_JOYSTICKS	8
   26.34 +#define MAX_JOYSTICKS 8
   26.35  #define AXIS_MIN	-32768  /* minimum value for axis coordinate */
   26.36  #define AXIS_MAX	32767   /* maximum value for axis coordinate */
   26.37  #define JOY_AXIS_THRESHOLD	(((AXIS_MAX)-(AXIS_MIN))/100)   /* 1% motion */
   26.38 @@ -59,13 +64,64 @@
   26.39  /* local variables */
   26.40  static SDL_bool coinitialized = SDL_FALSE;
   26.41  static LPDIRECTINPUT dinput = NULL;
   26.42 +static SDL_bool s_bDeviceAdded = SDL_FALSE;
   26.43 +static SDL_bool s_bDeviceRemoved = SDL_FALSE;
   26.44 +static int s_nInstanceID = -1;
   26.45 +static GUID *s_pKnownJoystickGUIDs = NULL;
   26.46 +static SDL_cond *s_condJoystickThread = NULL;
   26.47 +static SDL_mutex *s_mutexJoyStickEnum = NULL;
   26.48 +static SDL_Thread *s_threadJoystick = NULL;
   26.49 +static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
   26.50 +static HANDLE s_pXInputDLL = 0;
   26.51 +
   26.52  extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
   26.53                                         LPDIRECTINPUT * ppDI,
   26.54                                         LPUNKNOWN punkOuter);
   26.55 -static DIDEVICEINSTANCE SYS_Joystick[MAX_JOYSTICKS];    /* array to hold joystick ID values */
   26.56 -static char *SYS_JoystickNames[MAX_JOYSTICKS];
   26.57 -static int SYS_NumJoysticks;
   26.58 +struct JoyStick_DeviceData_
   26.59 +{
   26.60 +	JoystickGUID guid;
   26.61 +	DIDEVICEINSTANCE dxdevice;
   26.62 +	char *joystickname;
   26.63 +	Uint8 send_add_event;
   26.64 +	int nInstanceID;
   26.65 +	Uint8 bXInputDevice;
   26.66 +	Uint8 XInputUserId;
   26.67 +	struct JoyStick_DeviceData_ *pNext;
   26.68 +};
   26.69 +
   26.70 +
   26.71 +/* Forward decl's for XInput API's we load dynamically and use if available */
   26.72 +typedef DWORD (WINAPI *XInputGetState_t)
   26.73 +	(
   26.74 +	DWORD         dwUserIndex,  // [in] Index of the gamer associated with the device
   26.75 +	XINPUT_STATE_EX* pState        // [out] Receives the current state
   26.76 +	);
   26.77  
   26.78 +typedef DWORD (WINAPI *XInputSetState_t)
   26.79 +	(
   26.80 +	DWORD             dwUserIndex,  // [in] Index of the gamer associated with the device
   26.81 +	XINPUT_VIBRATION* pVibration    // [in, out] The vibration information to send to the controller
   26.82 +	);
   26.83 +
   26.84 +typedef DWORD (WINAPI *XInputGetCapabilities_t)
   26.85 +	(
   26.86 +	DWORD                dwUserIndex,   // [in] Index of the gamer associated with the device
   26.87 +	DWORD                dwFlags,       // [in] Input flags that identify the device type
   26.88 +	XINPUT_CAPABILITIES* pCapabilities  // [out] Receives the capabilities
   26.89 +	);
   26.90 +
   26.91 +XInputGetState_t PC_XInputGetState;
   26.92 +XInputSetState_t PC_XInputSetState;
   26.93 +XInputGetCapabilities_t PC_XInputGetCapabilities;
   26.94 +
   26.95 +#define XINPUTGETSTATE			PC_XInputGetState
   26.96 +#define XINPUTSETSTATE			PC_XInputSetState
   26.97 +#define XINPUTGETCAPABILITIES	PC_XInputGetCapabilities
   26.98 +#define INVALID_XINPUT_USERID 255
   26.99 +
  26.100 +typedef struct JoyStick_DeviceData_ JoyStick_DeviceData;
  26.101 +
  26.102 +static JoyStick_DeviceData *SYS_Joystick;    /* array to hold joystick ID values */
  26.103  
  26.104  /* local prototypes */
  26.105  static void SetDIerror(const char *function, HRESULT code);
  26.106 @@ -82,7 +138,7 @@
  26.107  static int SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick,
  26.108                                           Uint8 button, Uint8 state);
  26.109  
  26.110 -/* Taken from Wine - Thanks! */
  26.111 +// Taken from Wine - Thanks! 
  26.112  DIOBJECTDATAFORMAT dfDIJoystick2[] = {
  26.113    { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
  26.114    { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
  26.115 @@ -272,6 +328,270 @@
  26.116  }
  26.117  
  26.118  
  26.119 +#define SAFE_RELEASE(p)                             \
  26.120 +{                                                   \
  26.121 +	if (p) {                                        \
  26.122 +	(p)->lpVtbl->Release((p));                  \
  26.123 +	(p) = 0;                                    \
  26.124 +	}                                               \
  26.125 +}
  26.126 +
  26.127 +
  26.128 +DEFINE_GUID(CLSID_WbemLocator,   0x4590f811,0x1d3a,0x11d0,0x89,0x1F,0x00,0xaa,0x00,0x4b,0x2e,0x24);
  26.129 +DEFINE_GUID(IID_IWbemLocator,    0xdc12a687,0x737f,0x11cf,0x88,0x4d,0x00,0xaa,0x00,0x4b,0x2e,0x24);
  26.130 +
  26.131 +//-----------------------------------------------------------------------------
  26.132 +//
  26.133 +// code from MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014(v=vs.85).aspx
  26.134 +//
  26.135 +// Enum each PNP device using WMI and check each device ID to see if it contains 
  26.136 +// "IG_" (ex. "VID_045E&PID_028E&IG_00").  If it does, then it's an XInput device
  26.137 +// Unfortunately this information can not be found by just using DirectInput 
  26.138 +//-----------------------------------------------------------------------------
  26.139 +BOOL IsXInputDevice( const GUID* pGuidProductFromDirectInput )
  26.140 +{
  26.141 +	IWbemLocator*           pIWbemLocator  = NULL;
  26.142 +	IEnumWbemClassObject*   pEnumDevices   = NULL;
  26.143 +	IWbemClassObject*       pDevices[20];
  26.144 +	IWbemServices*          pIWbemServices = NULL;
  26.145 +	DWORD                   uReturned      = 0;
  26.146 +	BSTR                    bstrNamespace  = NULL;
  26.147 +	BSTR                    bstrDeviceID   = NULL;
  26.148 +	BSTR                    bstrClassName  = NULL;
  26.149 +	SDL_bool                bIsXinputDevice= SDL_FALSE;
  26.150 +	UINT                    iDevice        = 0;
  26.151 +	VARIANT                 var;
  26.152 +	HRESULT                 hr;
  26.153 +	DWORD bCleanupCOM;
  26.154 +
  26.155 +	SDL_memset( pDevices, 0x0, sizeof(pDevices) );
  26.156 +
  26.157 +	// CoInit if needed
  26.158 +	hr = CoInitialize(NULL);
  26.159 +	bCleanupCOM = SUCCEEDED(hr);
  26.160 +
  26.161 +	// Create WMI
  26.162 +	hr = CoCreateInstance( &CLSID_WbemLocator,
  26.163 +		NULL,
  26.164 +		CLSCTX_INPROC_SERVER,
  26.165 +		&IID_IWbemLocator,
  26.166 +		(LPVOID*) &pIWbemLocator);
  26.167 +	if( FAILED(hr) || pIWbemLocator == NULL )
  26.168 +		goto LCleanup;
  26.169 +
  26.170 +	bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );if( bstrNamespace == NULL ) goto LCleanup;        
  26.171 +	bstrClassName = SysAllocString( L"Win32_PNPEntity" );   if( bstrClassName == NULL ) goto LCleanup;        
  26.172 +	bstrDeviceID  = SysAllocString( L"DeviceID" );          if( bstrDeviceID == NULL )  goto LCleanup;        
  26.173 +	
  26.174 +	// Connect to WMI 
  26.175 +	hr = IWbemLocator_ConnectServer( pIWbemLocator, bstrNamespace, NULL, NULL, 0L, 
  26.176 +		0L, NULL, NULL, &pIWbemServices );
  26.177 +	if( FAILED(hr) || pIWbemServices == NULL )
  26.178 +		goto LCleanup;
  26.179 +
  26.180 +	// Switch security level to IMPERSONATE. 
  26.181 +	CoSetProxyBlanket( (IUnknown *)pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, 
  26.182 +		RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );                    
  26.183 +
  26.184 +	hr = IWbemServices_CreateInstanceEnum( pIWbemServices, bstrClassName, 0, NULL, &pEnumDevices ); 
  26.185 +	if( FAILED(hr) || pEnumDevices == NULL )
  26.186 +		goto LCleanup;
  26.187 +
  26.188 +	// Loop over all devices
  26.189 +	for( ;; )
  26.190 +	{
  26.191 +		// Get 20 at a time
  26.192 +		hr = IEnumWbemClassObject_Next( pEnumDevices, 10000, 20, pDevices, &uReturned );
  26.193 +		if( FAILED(hr) )
  26.194 +			goto LCleanup;
  26.195 +		if( uReturned == 0 )
  26.196 +			break;
  26.197 +
  26.198 +		for( iDevice=0; iDevice<uReturned; iDevice++ )
  26.199 +		{
  26.200 +			// For each device, get its device ID
  26.201 +			hr = IWbemClassObject_Get( pDevices[iDevice], bstrDeviceID, 0L, &var, NULL, NULL );
  26.202 +			if(  SUCCEEDED( hr ) && var.vt == VT_BSTR && var.bstrVal != NULL )
  26.203 +			{
  26.204 +				// Check if the device ID contains "IG_".  If it does, then it's an XInput device
  26.205 +				// This information can not be found from DirectInput 
  26.206 +				char *pDeviceString = WIN_StringToUTF8( var.bstrVal );
  26.207 +				if( SDL_strstr( pDeviceString, "IG_" ) )
  26.208 +				{
  26.209 +					// If it does, then get the VID/PID from var.bstrVal
  26.210 +					long dwPid = 0, dwVid = 0;
  26.211 +					char * strPid = NULL;
  26.212 +					DWORD dwVidPid = 0;
  26.213 +					char * strVid = SDL_strstr( pDeviceString, "VID_" );
  26.214 +					if( strVid )
  26.215 +					{
  26.216 +						dwVid = SDL_strtol( strVid + 4, NULL, 16 );
  26.217 +					}
  26.218 +					strPid = SDL_strstr( pDeviceString, "PID_" );
  26.219 +					if( strPid  )
  26.220 +					{
  26.221 +						dwPid = SDL_strtol( strPid + 4, NULL, 16 );
  26.222 +					}
  26.223 +
  26.224 +					// Compare the VID/PID to the DInput device
  26.225 +					dwVidPid = MAKELONG( dwVid, dwPid );
  26.226 +					if( dwVidPid == pGuidProductFromDirectInput->Data1 )
  26.227 +					{
  26.228 +						bIsXinputDevice = SDL_TRUE;
  26.229 +					}
  26.230 +				}
  26.231 +				if ( pDeviceString )
  26.232 +					SDL_free( pDeviceString );
  26.233 +
  26.234 +				if ( bIsXinputDevice )
  26.235 +					break;
  26.236 +			}   
  26.237 +			SAFE_RELEASE( pDevices[iDevice] );
  26.238 +		}
  26.239 +	}
  26.240 +	
  26.241 +LCleanup:
  26.242 +
  26.243 +	for( iDevice=0; iDevice<20; iDevice++ )
  26.244 +		SAFE_RELEASE( pDevices[iDevice] );
  26.245 +	SAFE_RELEASE( pEnumDevices );
  26.246 +	SAFE_RELEASE( pIWbemLocator );
  26.247 +	SAFE_RELEASE( pIWbemServices );
  26.248 +
  26.249 +	if ( bstrNamespace )
  26.250 +		SysFreeString( bstrNamespace );
  26.251 +	if ( bstrClassName )
  26.252 +		SysFreeString( bstrClassName );
  26.253 +	if ( bstrDeviceID )
  26.254 +		SysFreeString( bstrDeviceID );
  26.255 +
  26.256 +	if( bCleanupCOM )
  26.257 +		CoUninitialize();
  26.258 +		
  26.259 +	return bIsXinputDevice;
  26.260 +}
  26.261 +
  26.262 +
  26.263 +static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
  26.264 +
  26.265 +/* windowproc for our joystick detect thread message only window, to detect any usb device addition/removal
  26.266 + */
  26.267 +LRESULT CALLBACK SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)    {
  26.268 +	switch (message)    {
  26.269 +	case WM_DEVICECHANGE:
  26.270 +		switch (wParam) {
  26.271 +		case DBT_DEVICEARRIVAL:
  26.272 +			if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)    {
  26.273 +				s_bWindowsDeviceChanged = SDL_TRUE;
  26.274 +			}
  26.275 +			break;
  26.276 +		case DBT_DEVICEREMOVECOMPLETE:
  26.277 +			if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)    {
  26.278 +				s_bWindowsDeviceChanged = SDL_TRUE;
  26.279 +			}
  26.280 +			break;
  26.281 +		}
  26.282 +		return 0;
  26.283 +	}
  26.284 +
  26.285 +	return DefWindowProc (hwnd, message, wParam, lParam);
  26.286 +}
  26.287 +
  26.288 +
  26.289 +/*  helper func to create a hidden, message only window for the joystick detect thread
  26.290 + */
  26.291 +HWND CreateHiddenJoystickDetectWindow() {
  26.292 +	WNDCLASSEX wincl;
  26.293 +	HWND hMessageWindow = 0;
  26.294 +	SDL_memset( &wincl, 0x0, sizeof(wincl) );
  26.295 +	wincl.hInstance = GetModuleHandle( NULL );
  26.296 +	wincl.lpszClassName = L"Message";
  26.297 +	wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc;      // This function is called by windows
  26.298 +	wincl.cbSize = sizeof (WNDCLASSEX);
  26.299 +
  26.300 +	if (!RegisterClassEx (&wincl))
  26.301 +		return 0;
  26.302 +
  26.303 +	hMessageWindow = (HWND)CreateWindowEx( 0,  L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
  26.304 +	return hMessageWindow;
  26.305 +}
  26.306 +
  26.307 +DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \
  26.308 +	0xC0, 0x4F, 0xB9, 0x51, 0xED);
  26.309 +
  26.310 +/* Function/thread to scan the system for joysticks.
  26.311 + */
  26.312 +static int
  26.313 +SDL_JoystickThread(void *_data)
  26.314 +{
  26.315 +	int nDevicesLast = 0;
  26.316 +	HRESULT result = S_OK;	
  26.317 +	HWND messageWindow = 0;
  26.318 +	HDEVNOTIFY hNotify = 0;
  26.319 +	DEV_BROADCAST_DEVICEINTERFACE dbh;
  26.320 +
  26.321 +	result = WIN_CoInitialize();
  26.322 +
  26.323 +	messageWindow = CreateHiddenJoystickDetectWindow();
  26.324 +	if ( !messageWindow )
  26.325 +	{
  26.326 +		SDL_SetError("Failed to create message window for joystick autodetect.",
  26.327 +			GetLastError());
  26.328 +		return -1;
  26.329 +	}
  26.330 +
  26.331 +	SDL_memset(&dbh, 0x0, sizeof(dbh));
  26.332 +
  26.333 +	dbh.dbcc_size = sizeof(dbh);
  26.334 +	dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  26.335 +	dbh.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
  26.336 +
  26.337 +	hNotify = RegisterDeviceNotification( messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE );
  26.338 +	if ( !hNotify )
  26.339 +	{
  26.340 +		SDL_SetError("Failed to create notify device for joystick autodetect.",
  26.341 +			GetLastError());
  26.342 +		return -1;
  26.343 +	}
  26.344 +
  26.345 +	SDL_LockMutex( s_mutexJoyStickEnum );
  26.346 +	while ( s_bJoystickThreadQuit == SDL_FALSE )
  26.347 +	{
  26.348 +		MSG messages;
  26.349 +		SDL_CondWaitTimeout( s_condJoystickThread, s_mutexJoyStickEnum, 300 );
  26.350 +
  26.351 +		while ( s_bJoystickThreadQuit == SDL_FALSE && PeekMessage(&messages, messageWindow, 0, 0, PM_NOREMOVE) )
  26.352 +		{
  26.353 +			if ( GetMessage(&messages, messageWindow, 0, 0) != 0 )  {
  26.354 +				TranslateMessage(&messages);
  26.355 +				DispatchMessage(&messages);
  26.356 +			}
  26.357 +		}
  26.358 +
  26.359 +		if ( s_pKnownJoystickGUIDs && s_bWindowsDeviceChanged )
  26.360 +		{
  26.361 +			int nDevices = 0;
  26.362 +
  26.363 +			SDL_Delay( 300 ); // wait for direct input to find out about this device
  26.364 +
  26.365 +			s_bDeviceRemoved = SDL_TRUE;
  26.366 +			s_bDeviceAdded = SDL_TRUE;
  26.367 +			s_bWindowsDeviceChanged = SDL_FALSE;
  26.368 +		}
  26.369 +	}
  26.370 +	SDL_UnlockMutex( s_mutexJoyStickEnum );
  26.371 +
  26.372 +	if ( hNotify )
  26.373 +		UnregisterDeviceNotification( hNotify );
  26.374 +
  26.375 +	if ( messageWindow )
  26.376 +		DestroyWindow( messageWindow );
  26.377 +	messageWindow = 0;
  26.378 +	WIN_CoUninitialize();
  26.379 +	return 1;
  26.380 +}
  26.381 +
  26.382 +
  26.383  /* Function to scan the system for joysticks.
  26.384   * This function should set SDL_numjoysticks to the number of available
  26.385   * joysticks.  Joystick 0 should be the system default joystick.
  26.386 @@ -283,8 +603,6 @@
  26.387      HRESULT result;
  26.388      HINSTANCE instance;
  26.389  
  26.390 -    SYS_NumJoysticks = 0;
  26.391 -
  26.392      result = WIN_CoInitialize();
  26.393      if (FAILED(result)) {
  26.394          SetDIerror("CoInitialize", result);
  26.395 @@ -293,8 +611,8 @@
  26.396  
  26.397      coinitialized = SDL_TRUE;
  26.398  
  26.399 -    result = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
  26.400 -                              &IID_IDirectInput, (LPVOID)&dinput);
  26.401 +    result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
  26.402 +                              &IID_IDirectInput8, (LPVOID)&dinput);
  26.403  
  26.404      if (FAILED(result)) {
  26.405          SDL_SYS_JoystickQuit();
  26.406 @@ -310,7 +628,7 @@
  26.407                       GetLastError());
  26.408          return (-1);
  26.409      }
  26.410 -    result = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION);
  26.411 +    result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
  26.412  
  26.413      if (FAILED(result)) {
  26.414          SDL_SYS_JoystickQuit();
  26.415 @@ -318,34 +636,54 @@
  26.416          return (-1);
  26.417      }
  26.418  
  26.419 -    /* Look for joysticks, wheels, head trackers, gamepads, etc.. */
  26.420 -    result = IDirectInput_EnumDevices(dinput,
  26.421 -                                      DIDEVTYPE_JOYSTICK,
  26.422 -                                      EnumJoysticksCallback,
  26.423 -                                      NULL, DIEDFL_ATTACHEDONLY);
  26.424 -
  26.425 -    return SYS_NumJoysticks;
  26.426 -}
  26.427 +	s_mutexJoyStickEnum = SDL_CreateMutex();
  26.428 +	s_condJoystickThread = SDL_CreateCond();
  26.429 +	s_bDeviceAdded = SDL_TRUE; // force a scan of the system for joysticks this first time
  26.430 +	SDL_SYS_JoystickDetect();
  26.431  
  26.432 -static BOOL CALLBACK
  26.433 -EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
  26.434 -{
  26.435 -    SDL_memcpy(&SYS_Joystick[SYS_NumJoysticks], pdidInstance,
  26.436 -               sizeof(DIDEVICEINSTANCE));
  26.437 -    SYS_JoystickNames[SYS_NumJoysticks] = WIN_StringToUTF8(pdidInstance->tszProductName);
  26.438 -    SYS_NumJoysticks++;
  26.439 +	// try to load XInput support if available
  26.440 +	s_pXInputDLL = LoadLibrary( L"XInput1_3.dll" );
  26.441 +	if ( !s_pXInputDLL )
  26.442 +		s_pXInputDLL = LoadLibrary( L"bin\\XInput1_3.dll" );
  26.443 +	if ( s_pXInputDLL )
  26.444 +	{
  26.445 +		// 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...
  26.446 +		PC_XInputGetState = (XInputGetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, (LPCSTR)100 );
  26.447 +		PC_XInputSetState = (XInputSetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputSetState" );
  26.448 +		PC_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputGetCapabilities" );
  26.449 +		if ( !PC_XInputGetState || !PC_XInputSetState || !PC_XInputGetCapabilities )
  26.450 +		{
  26.451 +			SDL_SYS_JoystickQuit();
  26.452 +			SDL_SetError("GetProcAddress() failed when loading XInput.", GetLastError());
  26.453 +			return (-1);
  26.454 +		}
  26.455 +	}
  26.456  
  26.457 -    if (SYS_NumJoysticks >= MAX_JOYSTICKS)
  26.458 -        return DIENUM_STOP;
  26.459  
  26.460 -    return DIENUM_CONTINUE;
  26.461 +	if ( !s_threadJoystick )
  26.462 +	{
  26.463 +		s_bJoystickThreadQuit = SDL_FALSE;
  26.464 +		/* spin up the thread to detect hotplug of devices */
  26.465 +#if defined(__WIN32__) && !defined(HAVE_LIBC)
  26.466 +#undef SDL_CreateThread
  26.467 +		s_threadJoystick= SDL_CreateThread( SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL );
  26.468 +#else
  26.469 +		s_threadJoystick = SDL_CreateThread( SDL_JoystickThread, "SDL_joystick", NULL );
  26.470 +#endif
  26.471 +	}
  26.472 +	    return SDL_SYS_NumJoysticks();
  26.473  }
  26.474  
  26.475  /* Function to get the device-dependent name of a joystick */
  26.476  const char *
  26.477 -SDL_SYS_JoystickName(int index)
  26.478 +SDL_SYS_JoystickNameForIndex(int index)
  26.479  {
  26.480 -    return SYS_JoystickNames[index];
  26.481 +	JoyStick_DeviceData *device = SYS_Joystick;
  26.482 +
  26.483 +	for (; index > 0; index--)
  26.484 +		device = device->pNext;
  26.485 +
  26.486 +	return device->joystickname;
  26.487  }
  26.488  
  26.489  /* Function to open a joystick for use.
  26.490 @@ -354,17 +692,20 @@
  26.491     It returns 0, or -1 if there is an error.
  26.492   */
  26.493  int
  26.494 -SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
  26.495 +SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
  26.496  {
  26.497      HRESULT result;
  26.498      LPDIRECTINPUTDEVICE device;
  26.499      DIPROPDWORD dipdw;
  26.500 +	JoyStick_DeviceData *joystickdevice = SYS_Joystick;
  26.501 +
  26.502 +	for (; device_index > 0; device_index--)
  26.503 +		joystickdevice = joystickdevice->pNext;
  26.504  
  26.505      SDL_memset(&dipdw, 0, sizeof(DIPROPDWORD));
  26.506      dipdw.diph.dwSize = sizeof(DIPROPDWORD);
  26.507      dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  26.508  
  26.509 -
  26.510      /* allocate memory for system specific hardware data */
  26.511      joystick->hwdata =
  26.512          (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
  26.513 @@ -374,137 +715,195 @@
  26.514      }
  26.515      SDL_memset(joystick->hwdata, 0, sizeof(struct joystick_hwdata));
  26.516      joystick->hwdata->buffered = 1;
  26.517 +	joystick->hwdata->removed = 0;
  26.518 +	joystick->instance_id = joystickdevice->nInstanceID;
  26.519      joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
  26.520 -
  26.521 -    result =
  26.522 -        IDirectInput_CreateDevice(dinput,
  26.523 -                                  &SYS_Joystick[joystick->index].
  26.524 -                                  guidInstance, &device, NULL);
  26.525 -    if (FAILED(result)) {
  26.526 -        SetDIerror("IDirectInput::CreateDevice", result);
  26.527 -        return (-1);
  26.528 -    }
  26.529 +	joystick->hwdata->guid = joystickdevice->guid;
  26.530  
  26.531 -    /* Now get the IDirectInputDevice2 interface, instead. */
  26.532 -    result = IDirectInputDevice_QueryInterface(device,
  26.533 -                                               &IID_IDirectInputDevice2,
  26.534 -                                               (LPVOID *) & joystick->
  26.535 -                                               hwdata->InputDevice);
  26.536 -    /* We are done with this object.  Use the stored one from now on. */
  26.537 -    IDirectInputDevice_Release(device);
  26.538 +	if ( joystickdevice->bXInputDevice )
  26.539 +	{
  26.540 +		XINPUT_CAPABILITIES	capabilities;
  26.541 +		Uint8 userId = 0;
  26.542 +		DWORD result;
  26.543 +		JoyStick_DeviceData *joysticklist = SYS_Joystick;
  26.544 +		// scan the opened joysticks and pick the next free xinput userid for this one
  26.545 +		for( ; joysticklist; joysticklist = joysticklist->pNext)
  26.546 +		{
  26.547 +			if ( joysticklist->bXInputDevice && joysticklist->XInputUserId == userId )
  26.548 +				userId++;
  26.549 +		}
  26.550  
  26.551 -    if (FAILED(result)) {
  26.552 -        SetDIerror("IDirectInputDevice::QueryInterface", result);
  26.553 -        return (-1);
  26.554 -    }
  26.555 +		if ( XINPUTGETCAPABILITIES )
  26.556 +		{
  26.557 +			result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
  26.558 +			if ( result == ERROR_SUCCESS )
  26.559 +			{
  26.560 +				SDL_bool bIsSupported = SDL_FALSE;
  26.561 +				// Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad.
  26.562 +				bIsSupported = ( capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD );
  26.563  
  26.564 -    /* Aquire shared access. Exclusive access is required for forces,
  26.565 -     * though. */
  26.566 -    result =
  26.567 -        IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata->
  26.568 -                                                InputDevice, SDL_HelperWindow,
  26.569 -                                                DISCL_EXCLUSIVE |
  26.570 -                                                DISCL_BACKGROUND);
  26.571 -    if (FAILED(result)) {
  26.572 -        SetDIerror("IDirectInputDevice2::SetCooperativeLevel", result);
  26.573 -        return (-1);
  26.574 -    }
  26.575 +				if ( !bIsSupported )
  26.576 +				{
  26.577 +					joystickdevice->bXInputDevice = SDL_FALSE;
  26.578 +				}
  26.579 +				else
  26.580 +				{
  26.581 +					// valid
  26.582 +					joystick->hwdata->bXInputDevice = SDL_TRUE;
  26.583 +					SDL_memset( joystick->hwdata->XInputState, 0x0, sizeof(joystick->hwdata->XInputState) );
  26.584 +					joystickdevice->XInputUserId = userId;
  26.585 +					joystick->hwdata->userid = userId;
  26.586 +					joystick->hwdata->currentXInputSlot = 0;
  26.587 +					// The XInput API has a hard coded button/axis mapping, so we just match it
  26.588 +					joystick->naxes = 6;
  26.589 +					joystick->nbuttons = 15;
  26.590 +					joystick->nballs = 0;
  26.591 +					joystick->nhats = 0;
  26.592 +				}
  26.593 +			}
  26.594 +			else
  26.595 +			{
  26.596 +				joystickdevice->bXInputDevice = SDL_FALSE;
  26.597 +			}
  26.598 +		}
  26.599 +		else
  26.600 +		{
  26.601 +			joystickdevice->bXInputDevice = SDL_FALSE;
  26.602 +		}
  26.603 +	}
  26.604  
  26.605 -    /* Use the extended data structure: DIJOYSTATE2. */
  26.606 -    result =
  26.607 -        IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice,
  26.608 -                                          &c_dfDIJoystick2);
  26.609 -    if (FAILED(result)) {
  26.610 -        SetDIerror("IDirectInputDevice2::SetDataFormat", result);
  26.611 -        return (-1);
  26.612 -    }
  26.613 +	if ( joystickdevice->bXInputDevice == SDL_FALSE )
  26.614 +	{
  26.615 +		joystick->hwdata->bXInputDevice = SDL_FALSE;
  26.616  
  26.617 -    /* Get device capabilities */
  26.618 -    result =
  26.619 -        IDirectInputDevice2_GetCapabilities(joystick->hwdata->InputDevice,
  26.620 -                                            &joystick->hwdata->Capabilities);
  26.621 +		result =
  26.622 +			IDirectInput8_CreateDevice(dinput,
  26.623 +									  &(joystickdevice->dxdevice.guidInstance), &device, NULL);
  26.624 +		if (FAILED(result)) {
  26.625 +			SetDIerror("IDirectInput::CreateDevice", result);
  26.626 +			return (-1);
  26.627 +		}
  26.628  
  26.629 -    if (FAILED(result)) {
  26.630 -        SetDIerror("IDirectInputDevice2::GetCapabilities", result);
  26.631 -        return (-1);
  26.632 -    }
  26.633 +		/* Now get the IDirectInputDevice2 interface, instead. */
  26.634 +		result = IDirectInputDevice8_QueryInterface(device,
  26.635 +												   &IID_IDirectInputDevice8,
  26.636 +												   (LPVOID *) & joystick->
  26.637 +												   hwdata->InputDevice);
  26.638 +		/* We are done with this object.  Use the stored one from now on. */
  26.639 +		IDirectInputDevice8_Release(device);
  26.640  
  26.641 -    /* Force capable? */
  26.642 -    if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
  26.643 -
  26.644 -        result = IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
  26.645 +		if (FAILED(result)) {
  26.646 +			SetDIerror("IDirectInputDevice::QueryInterface", result);
  26.647 +			return (-1);
  26.648 +		}
  26.649  
  26.650 -        if (FAILED(result)) {
  26.651 -            SetDIerror("IDirectInputDevice2::Acquire", result);
  26.652 -            return (-1);
  26.653 -        }
  26.654 +		/* Aquire shared access. Exclusive access is required for forces,
  26.655 +		 * though. */
  26.656 +		result =
  26.657 +			IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
  26.658 +													InputDevice, SDL_HelperWindow,
  26.659 +													DISCL_NONEXCLUSIVE |
  26.660 +													DISCL_BACKGROUND);
  26.661 +		if (FAILED(result)) {
  26.662 +			SetDIerror("IDirectInputDevice2::SetCooperativeLevel", result);
  26.663 +			return (-1);
  26.664 +		}
  26.665  
  26.666 -        /* reset all accuators. */
  26.667 -        result =
  26.668 -            IDirectInputDevice2_SendForceFeedbackCommand(joystick->hwdata->
  26.669 -                                                         InputDevice,
  26.670 -                                                         DISFFC_RESET);
  26.671 +		/* Use the extended data structure: DIJOYSTATE2. */
  26.672 +		result =
  26.673 +			IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
  26.674 +											  &c_dfDIJoystick2);
  26.675 +		if (FAILED(result)) {
  26.676 +			SetDIerror("IDirectInputDevice2::SetDataFormat", result);
  26.677 +			return (-1);
  26.678 +		}
  26.679  
  26.680 -        /* Not necessarily supported, ignore if not supported.
  26.681 -        if (FAILED(result)) {
  26.682 -            SetDIerror("IDirectInputDevice2::SendForceFeedbackCommand",
  26.683 -                       result);
  26.684 -            return (-1);
  26.685 -        }
  26.686 -        */
  26.687 +		/* Get device capabilities */
  26.688 +		result =
  26.689 +			IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
  26.690 +												&joystick->hwdata->Capabilities);
  26.691 +
  26.692 +		if (FAILED(result)) {
  26.693 +			SetDIerror("IDirectInputDevice2::GetCapabilities", result);
  26.694 +			return (-1);
  26.695 +		}
  26.696 +
  26.697 +		/* Force capable? */
  26.698 +		if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
  26.699  
  26.700 -        result = IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice);
  26.701 +			result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
  26.702  
  26.703 -        if (FAILED(result)) {
  26.704 -            SetDIerror("IDirectInputDevice2::Unacquire", result);
  26.705 -            return (-1);
  26.706 -        }
  26.707 +			if (FAILED(result)) {
  26.708 +				SetDIerror("IDirectInputDevice2::Acquire", result);
  26.709 +				return (-1);
  26.710 +			}
  26.711  
  26.712 -        /* Turn on auto-centering for a ForceFeedback device (until told
  26.713 -         * otherwise). */
  26.714 -        dipdw.diph.dwObj = 0;
  26.715 -        dipdw.diph.dwHow = DIPH_DEVICE;
  26.716 -        dipdw.dwData = DIPROPAUTOCENTER_ON;
  26.717 +			/* reset all accuators. */
  26.718 +			result =
  26.719 +				IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
  26.720 +															 InputDevice,
  26.721 +															 DISFFC_RESET);
  26.722  
  26.723 -        result =
  26.724 -            IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
  26.725 -                                            DIPROP_AUTOCENTER, &dipdw.diph);
  26.726 +			/* Not necessarily supported, ignore if not supported.
  26.727 +			if (FAILED(result)) {
  26.728 +				SetDIerror("IDirectInputDevice2::SendForceFeedbackCommand",
  26.729 +						   result);
  26.730 +				return (-1);
  26.731 +			}
  26.732 +			*/
  26.733 +
  26.734 +			result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
  26.735  
  26.736 -        /* Not necessarily supported, ignore if not supported.
  26.737 -        if (FAILED(result)) {
  26.738 -            SetDIerror("IDirectInputDevice2::SetProperty", result);
  26.739 -            return (-1);
  26.740 -        }
  26.741 -        */
  26.742 -    }
  26.743 +			if (FAILED(result)) {
  26.744 +				SetDIerror("IDirectInputDevice2::Unacquire", result);
  26.745 +				return (-1);
  26.746 +			}
  26.747 +
  26.748 +			/* Turn on auto-centering for a ForceFeedback device (until told
  26.749 +			 * otherwise). */
  26.750 +			dipdw.diph.dwObj = 0;
  26.751 +			dipdw.diph.dwHow = DIPH_DEVICE;
  26.752 +			dipdw.dwData = DIPROPAUTOCENTER_ON;
  26.753  
  26.754 -    /* What buttons and axes does it have? */
  26.755 -    IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice,
  26.756 -                                    EnumDevObjectsCallback, joystick,
  26.757 -                                    DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
  26.758 +			result =
  26.759 +				IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
  26.760 +												DIPROP_AUTOCENTER, &dipdw.diph);
  26.761  
  26.762 -	/* Reorder the input objects. Some devices do not report the X axis as
  26.763 -	 * the first axis, for example. */
  26.764 -	SortDevObjects(joystick);
  26.765 +			/* Not necessarily supported, ignore if not supported.
  26.766 +			if (FAILED(result)) {
  26.767 +				SetDIerror("IDirectInputDevice2::SetProperty", result);
  26.768 +				return (-1);
  26.769 +			}
  26.770 +			*/
  26.771 +		}
  26.772  
  26.773 -    dipdw.diph.dwObj = 0;
  26.774 -    dipdw.diph.dwHow = DIPH_DEVICE;
  26.775 -    dipdw.dwData = INPUT_QSIZE;
  26.776 +		/* What buttons and axes does it have? */
  26.777 +		IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
  26.778 +										EnumDevObjectsCallback, joystick,
  26.779 +										DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
  26.780  
  26.781 -    /* Set the buffer size */
  26.782 -    result =
  26.783 -        IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
  26.784 -                                        DIPROP_BUFFERSIZE, &dipdw.diph);
  26.785 +		/* Reorder the input objects. Some devices do not report the X axis as
  26.786 +		 * the first axis, for example. */
  26.787 +		SortDevObjects(joystick);
  26.788 +
  26.789 +		dipdw.diph.dwObj = 0;
  26.790 +		dipdw.diph.dwHow = DIPH_DEVICE;
  26.791 +		dipdw.dwData = INPUT_QSIZE;
  26.792  
  26.793 -    if (result == DI_POLLEDDEVICE) {
  26.794 -        /* This device doesn't support buffering, so we're forced
  26.795 -         * to use less reliable polling. */
  26.796 -        joystick->hwdata->buffered = 0;
  26.797 -    } else if (FAILED(result)) {
  26.798 -        SetDIerror("IDirectInputDevice2::SetProperty", result);
  26.799 -        return (-1);
  26.800 -    }
  26.801 +		/* Set the buffer size */
  26.802 +		result =
  26.803 +			IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
  26.804 +											DIPROP_BUFFERSIZE, &dipdw.diph);
  26.805  
  26.806 +		if (result == DI_POLLEDDEVICE) {
  26.807 +			/* This device doesn't support buffering, so we're forced
  26.808 +			 * to use less reliable polling. */
  26.809 +			joystick->hwdata->buffered = 0;
  26.810 +		} else if (FAILED(result)) {
  26.811 +			SetDIerror("IDirectInputDevice2::SetProperty", result);
  26.812 +			return (-1);
  26.813 +		}
  26.814 +	}
  26.815      return (0);
  26.816  }
  26.817  
  26.818 @@ -564,15 +963,15 @@
  26.819      HRESULT result;
  26.820      input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
  26.821  
  26.822 -    in->ofs = dev->dwOfs;
  26.823 -
  26.824      if (dev->dwType & DIDFT_BUTTON) {
  26.825          in->type = BUTTON;
  26.826          in->num = joystick->nbuttons;
  26.827 +		in->ofs = DIJOFS_BUTTON( in->num );
  26.828          joystick->nbuttons++;
  26.829      } else if (dev->dwType & DIDFT_POV) {
  26.830          in->type = HAT;
  26.831          in->num = joystick->nhats;
  26.832 +		in->ofs = DIJOFS_POV( in->num );
  26.833          joystick->nhats++;
  26.834      } else if (dev->dwType & DIDFT_AXIS) {
  26.835          DIPROPRANGE diprg;
  26.836 @@ -580,16 +979,38 @@
  26.837  
  26.838          in->type = AXIS;
  26.839          in->num = joystick->naxes;
  26.840 +		// work our the axis this guy maps too, thanks for the code icculus!
  26.841 +		if ( !SDL_memcmp( &dev->guidType, &GUID_XAxis, sizeof(dev->guidType) ) )
  26.842 +			in->ofs = DIJOFS_X;
  26.843 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_YAxis, sizeof(dev->guidType) ) )
  26.844 +			in->ofs = DIJOFS_Y;
  26.845 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_ZAxis, sizeof(dev->guidType) ) )
  26.846 +			in->ofs = DIJOFS_Z;
  26.847 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_RxAxis, sizeof(dev->guidType) ) )
  26.848 +			in->ofs = DIJOFS_RX;
  26.849 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_RyAxis, sizeof(dev->guidType) ) )
  26.850 +			in->ofs = DIJOFS_RY;
  26.851 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_RzAxis, sizeof(dev->guidType) ) )
  26.852 +			in->ofs = DIJOFS_RZ;
  26.853 +		else if ( !SDL_memcmp( &dev->guidType, &GUID_Slider, sizeof(dev->guidType) ) )
  26.854 +		{
  26.855 +			in->ofs = DIJOFS_SLIDER( joystick->hwdata->NumSliders );
  26.856 +			++joystick->hwdata->NumSliders;
  26.857 +		}
  26.858 +		else 
  26.859 +		{
  26.860 +			 return DIENUM_CONTINUE; // not an axis we can grok
  26.861 +		}
  26.862  
  26.863          diprg.diph.dwSize = sizeof(diprg);
  26.864          diprg.diph.dwHeaderSize = sizeof(diprg.diph);
  26.865 -        diprg.diph.dwObj = dev->dwOfs;
  26.866 -        diprg.diph.dwHow = DIPH_BYOFFSET;
  26.867 +        diprg.diph.dwObj = dev->dwType;
  26.868 +        diprg.diph.dwHow = DIPH_BYID;
  26.869          diprg.lMin = AXIS_MIN;
  26.870          diprg.lMax = AXIS_MAX;
  26.871  
  26.872          result =
  26.873 -            IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
  26.874 +            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
  26.875                                              DIPROP_RANGE, &diprg.diph);
  26.876          if (FAILED(result)) {
  26.877              return DIENUM_CONTINUE;     /* don't use this axis */
  26.878 @@ -598,11 +1019,11 @@
  26.879          /* Set dead zone to 0. */
  26.880          dilong.diph.dwSize = sizeof(dilong);
  26.881          dilong.diph.dwHeaderSize = sizeof(dilong.diph);
  26.882 -        dilong.diph.dwObj = dev->dwOfs;
  26.883 -        dilong.diph.dwHow = DIPH_BYOFFSET;
  26.884 +        dilong.diph.dwObj = dev->dwType;
  26.885 +        dilong.diph.dwHow = DIPH_BYID;
  26.886          dilong.dwData = 0;
  26.887          result =
  26.888 -            IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
  26.889 +            IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
  26.890                                              DIPROP_DEADZONE, &dilong.diph);
  26.891          if (FAILED(result)) {
  26.892              return DIENUM_CONTINUE;     /* don't use this axis */
  26.893 @@ -636,15 +1057,22 @@
  26.894      int i;
  26.895  
  26.896      result =
  26.897 -        IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
  26.898 +        IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
  26.899                                             sizeof(DIJOYSTATE2), &state);
  26.900      if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
  26.901 -        IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
  26.902 +        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
  26.903          result =
  26.904 -            IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
  26.905 +            IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
  26.906                                                 sizeof(DIJOYSTATE2), &state);
  26.907      }
  26.908  
  26.909 +	if ( result != DI_OK )
  26.910 +	{
  26.911 +		joystick->hwdata->send_remove_event = 1;
  26.912 +		joystick->hwdata->removed = 1;
  26.913 +		return;
  26.914 +	}
  26.915 +
  26.916      /* Set each known axis, button and POV. */
  26.917      for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
  26.918          const input_t *in = &joystick->hwdata->Inputs[i];
  26.919 @@ -717,20 +1145,24 @@
  26.920  
  26.921      numevents = INPUT_QSIZE;
  26.922      result =
  26.923 -        IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
  26.924 +        IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
  26.925                                            sizeof(DIDEVICEOBJECTDATA), evtbuf,
  26.926                                            &numevents, 0);
  26.927      if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
  26.928 -        IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
  26.929 +        IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
  26.930          result =
  26.931 -            IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
  26.932 +            IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
  26.933                                                sizeof(DIDEVICEOBJECTDATA),
  26.934                                                evtbuf, &numevents, 0);
  26.935      }
  26.936  
  26.937      /* Handle the events or punt */
  26.938      if (FAILED(result))
  26.939 +	{
  26.940 +		joystick->hwdata->send_remove_event = 1;
  26.941 +		joystick->hwdata->removed = 1;
  26.942          return;
  26.943 +	}
  26.944  
  26.945      for (i = 0; i < (int) numevents; ++i) {
  26.946          int j;
  26.947 @@ -763,6 +1195,82 @@
  26.948  }
  26.949  
  26.950  
  26.951 +/* Function to return > 0 if a bit array of buttons differs after applying a mask
  26.952 +*/
  26.953 +int ButtonChanged( int ButtonsNow, int ButtonsPrev, int ButtonMask )
  26.954 +{
  26.955 +	return ( ButtonsNow & ButtonMask ) != ( ButtonsPrev & ButtonMask );
  26.956 +}
  26.957 +
  26.958 +/* Function to update the state of a XInput style joystick.
  26.959 +*/
  26.960 +void
  26.961 +SDL_SYS_JoystickUpdate_XInput(SDL_Joystick * joystick)
  26.962 +{
  26.963 +	HRESULT result;
  26.964 +
  26.965 +	if ( !XINPUTGETSTATE )
  26.966 +		return;
  26.967 +
  26.968 +	result = XINPUTGETSTATE( joystick->hwdata->userid, &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot] );
  26.969 +	if ( result == ERROR_DEVICE_NOT_CONNECTED )
  26.970 +	{
  26.971 +		joystick->hwdata->send_remove_event = 1;
  26.972 +		joystick->hwdata->removed = 1;
  26.973 +		return;
  26.974 +	}
  26.975 +
  26.976 +	// only fire events if the data changed from last time
  26.977 +	if ( joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot].dwPacketNumber != 0 
  26.978 +		&& joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot].dwPacketNumber != joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot^1].dwPacketNumber )
  26.979 +	{
  26.980 +		XINPUT_STATE_EX *pXInputState = &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot];
  26.981 +		XINPUT_STATE_EX *pXInputStatePrev = &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot ^ 1];
  26.982 +
  26.983 +		SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX );
  26.984 +		SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-1*pXInputState->Gamepad.sThumbLY-1) );
  26.985 +		SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX );
  26.986 +		SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-1*pXInputState->Gamepad.sThumbRY-1) );
  26.987 +		SDL_PrivateJoystickAxis(joystick, 4, (Sint16)((int)pXInputState->Gamepad.bLeftTrigger*32767/255) );
  26.988 +		SDL_PrivateJoystickAxis(joystick, 5, (Sint16)((int)pXInputState->Gamepad.bRightTrigger*32767/255) );
  26.989 +
  26.990 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_UP ) )
  26.991 +			SDL_PrivateJoystickButton(joystick, 0, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ? SDL_PRESSED :	SDL_RELEASED );
  26.992 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_DOWN ) )
  26.993 +			SDL_PrivateJoystickButton(joystick, 1, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ? SDL_PRESSED :	SDL_RELEASED );
  26.994 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_LEFT ) )
  26.995 +			SDL_PrivateJoystickButton(joystick, 2, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ? SDL_PRESSED :	SDL_RELEASED );
  26.996 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_RIGHT ) )
  26.997 +			SDL_PrivateJoystickButton(joystick, 3, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ? SDL_PRESSED :	SDL_RELEASED );
  26.998 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_START ) )
  26.999 +			SDL_PrivateJoystickButton(joystick, 4, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_START ? SDL_PRESSED :	SDL_RELEASED );
 26.1000 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_BACK ) )
 26.1001 +			SDL_PrivateJoystickButton(joystick, 5, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_BACK ? SDL_PRESSED :	SDL_RELEASED );
 26.1002 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_THUMB ) )
 26.1003 +			SDL_PrivateJoystickButton(joystick, 6, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ? SDL_PRESSED :	SDL_RELEASED );
 26.1004 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_THUMB ) )
 26.1005 +			SDL_PrivateJoystickButton(joystick, 7, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ? SDL_PRESSED :	SDL_RELEASED );
 26.1006 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_SHOULDER ) )
 26.1007 +			SDL_PrivateJoystickButton(joystick, 8, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER ? SDL_PRESSED :	SDL_RELEASED );
 26.1008 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_SHOULDER ) )
 26.1009 +			SDL_PrivateJoystickButton(joystick, 9, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER ? SDL_PRESSED :	SDL_RELEASED );
 26.1010 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_A ) )
 26.1011 +			SDL_PrivateJoystickButton(joystick, 10, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_A ? SDL_PRESSED :	SDL_RELEASED );
 26.1012 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_B ) )
 26.1013 +			SDL_PrivateJoystickButton(joystick, 11, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_B ? SDL_PRESSED :	SDL_RELEASED );
 26.1014 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_X ) )
 26.1015 +			SDL_PrivateJoystickButton(joystick, 12, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_X ? SDL_PRESSED :	SDL_RELEASED );
 26.1016 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_Y ) )
 26.1017 +			SDL_PrivateJoystickButton(joystick, 13, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_Y ? SDL_PRESSED :	SDL_RELEASED );
 26.1018 +		if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons,  0x400 ) )
 26.1019 +			SDL_PrivateJoystickButton(joystick, 14, pXInputState->Gamepad.wButtons & 0x400 ? SDL_PRESSED :	SDL_RELEASED ); // 0x400 is the undocumented code for the guide button
 26.1020 +
 26.1021 +		joystick->hwdata->currentXInputSlot ^= 1;
 26.1022 +
 26.1023 +	}
 26.1024 +}
 26.1025 +
 26.1026 +
 26.1027  static Uint8
 26.1028  TranslatePOV(DWORD value)
 26.1029  {
 26.1030 @@ -823,46 +1331,97 @@
 26.1031  {
 26.1032      HRESULT result;
 26.1033  
 26.1034 -    result = IDirectInputDevice2_Poll(joystick->hwdata->InputDevice);
 26.1035 -    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
 26.1036 -        IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
 26.1037 -        IDirectInputDevice2_Poll(joystick->hwdata->InputDevice);
 26.1038 -    }
 26.1039 +	if ( joystick->closed || !joystick->hwdata )
 26.1040 +		return;
 26.1041  
 26.1042 -    if (joystick->hwdata->buffered)
 26.1043 -        SDL_SYS_JoystickUpdate_Buffered(joystick);
 26.1044 -    else
 26.1045 -        SDL_SYS_JoystickUpdate_Polled(joystick);
 26.1046 +	if (joystick->hwdata->bXInputDevice)
 26.1047 +	{
 26.1048 +		SDL_SYS_JoystickUpdate_XInput(joystick);
 26.1049 +	}
 26.1050 +	else
 26.1051 +	{
 26.1052 +		result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
 26.1053 +		if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
 26.1054 +			IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
 26.1055 +			IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
 26.1056 +		}
 26.1057 +
 26.1058 +		if (joystick->hwdata->buffered)
 26.1059 +			SDL_SYS_JoystickUpdate_Buffered(joystick);
 26.1060 +		else
 26.1061 +			SDL_SYS_JoystickUpdate_Polled(joystick);
 26.1062 +	}
 26.1063 +
 26.1064 +	if ( joystick->hwdata->removed )
 26.1065 +	{
 26.1066 +		joystick->closed = 1;
 26.1067 +		joystick->uncentered = 1;
 26.1068 +	}
 26.1069  }
 26.1070  
 26.1071  /* Function to close a joystick after use */
 26.1072  void
 26.1073  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
 26.1074  {
 26.1075 -    IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice);
 26.1076 -    IDirectInputDevice2_Release(joystick->hwdata->InputDevice);
 26.1077 +	if ( joystick->hwdata->bXInputDevice )
 26.1078 +	{
 26.1079 +		JoyStick_DeviceData *joysticklist = SYS_Joystick;
 26.1080 +		// scan the opened joysticks and clear the userid for this instance
 26.1081 +		for( ; joysticklist; joysticklist = joysticklist->pNext)
 26.1082 +		{
 26.1083 +			if ( joysticklist->bXInputDevice && joysticklist->nInstanceID == joystick->instance_id )
 26.1084 +			{
 26.1085 +				joysticklist->XInputUserId = INVALID_XINPUT_USERID;
 26.1086 +			}
 26.1087 +		}
 26.1088 +
 26.1089 +	}
 26.1090 +	else
 26.1091 +	{
 26.1092 +	    IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
 26.1093 +	    IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
 26.1094 +	}
 26.1095  
 26.1096      if (joystick->hwdata != NULL) {
 26.1097          /* free system specific hardware data */
 26.1098          SDL_free(joystick->hwdata);
 26.1099      }
 26.1100 +
 26.1101 +	joystick->closed = 1;
 26.1102  }
 26.1103  
 26.1104  /* Function to perform any system-specific joystick related cleanup */
 26.1105  void
 26.1106  SDL_SYS_JoystickQuit(void)
 26.1107  {
 26.1108 -    int i;
 26.1109 +	JoyStick_DeviceData *device = SYS_Joystick;
 26.1110 +
 26.1111 +	while ( device )
 26.1112 +	{
 26.1113 +		JoyStick_DeviceData *device_next = device->pNext;
 26.1114 +		SDL_free(device->joystickname);
 26.1115 +		SDL_free(device);
 26.1116 +		device = device_next;
 26.1117 +	}
 26.1118 +	SYS_Joystick = NULL;
 26.1119  
 26.1120 -    for (i = 0; i < SDL_arraysize(SYS_JoystickNames); ++i) {
 26.1121 -        if (SYS_JoystickNames[i]) {
 26.1122 -            SDL_free(SYS_JoystickNames[i]);
 26.1123 -            SYS_JoystickNames[i] = NULL;
 26.1124 -        }
 26.1125 -    }
 26.1126 +	if ( s_threadJoystick )
 26.1127 +	{
 26.1128 +		SDL_LockMutex( s_mutexJoyStickEnum );
 26.1129 +		s_bJoystickThreadQuit = SDL_TRUE;
 26.1130 +		SDL_CondBroadcast( s_condJoystickThread ); // signal the joystick thread to quit
 26.1131 +		SDL_UnlockMutex( s_mutexJoyStickEnum );
 26.1132 +		SDL_WaitThread( s_threadJoystick, NULL ); // wait for it to bugger off
 26.1133 +
 26.1134 +		SDL_DestroyMutex( s_mutexJoyStickEnum );
 26.1135 +		SDL_DestroyCond( s_condJoystickThread );
 26.1136 +		s_condJoystickThread= NULL;
 26.1137 +		s_mutexJoyStickEnum = NULL;
 26.1138 +		s_threadJoystick = NULL;
 26.1139 +	}
 26.1140  
 26.1141      if (dinput != NULL) {
 26.1142 -        IDirectInput_Release(dinput);
 26.1143 +        IDirectInput8_Release(dinput);
 26.1144          dinput = NULL;
 26.1145      }
 26.1146  
 26.1147 @@ -870,6 +1429,254 @@
 26.1148          WIN_CoUninitialize();
 26.1149          coinitialized = SDL_FALSE;
 26.1150      }
 26.1151 +
 26.1152 +	if ( s_pKnownJoystickGUIDs )
 26.1153 +	{
 26.1154 +		SDL_free( s_pKnownJoystickGUIDs );
 26.1155 +		s_pKnownJoystickGUIDs = NULL;
 26.1156 +	}
 26.1157 +
 26.1158 +	if ( s_pXInputDLL )
 26.1159 +	{
 26.1160 +		FreeLibrary( s_pXInputDLL );
 26.1161 +		s_pXInputDLL = NULL;
 26.1162 +	}
 26.1163 +}
 26.1164 +
 26.1165 +
 26.1166 +/* Function to perform the mapping between current device instance and this joysticks instance id */
 26.1167 +SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
 26.1168 +{
 26.1169 +	JoyStick_DeviceData *device = SYS_Joystick;
 26.1170 +	int index;
 26.1171 +
 26.1172 +	for (index = device_index; index > 0; index--)
 26.1173 +		device = device->pNext;
 26.1174 +
 26.1175 +	return device->nInstanceID;
 26.1176 +}
 26.1177 +
 26.1178 +/* return true if this joystick is plugged in right now */
 26.1179 +int SDL_SYS_JoystickAttached( SDL_Joystick * joystick )
 26.1180 +{
 26.1181 +	return joystick->closed == 0 && joystick->hwdata->removed == 0;
 26.1182 +}
 26.1183 +
 26.1184 +
 26.1185 +/* return the number of joysticks that are connected right now */
 26.1186 +int SDL_SYS_NumJoysticks()
 26.1187 +{
 26.1188 +	int nJoysticks = 0;
 26.1189 +	JoyStick_DeviceData *device = SYS_Joystick;
 26.1190 +	while ( device )
 26.1191 +	{
 26.1192 +		nJoysticks++;
 26.1193 +		device = device->pNext;
 26.1194 +	}
 26.1195 +
 26.1196 +	return nJoysticks;
 26.1197 +}
 26.1198 +
 26.1199 +static int s_iNewGUID = 0;
 26.1200 +
 26.1201 +/* helper function for direct input, gets called for each connected joystick */
 26.1202 +static BOOL CALLBACK
 26.1203 +	EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
 26.1204 +{
 26.1205 +	JoyStick_DeviceData *pNewJoystick;
 26.1206 +	SDL_bool bXInputDevice;
 26.1207 +	pNewJoystick = *(JoyStick_DeviceData **)pContext;
 26.1208 +	while ( pNewJoystick )
 26.1209 +	{
 26.1210 +		if ( !SDL_memcmp( &pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance) ) )
 26.1211 +		{
 26.1212 +			if ( SYS_Joystick )
 26.1213 +			{
 26.1214 +				pNewJoystick->pNext = SYS_Joystick;
 26.1215 +			}
 26.1216 +			SYS_Joystick = pNewJoystick;
 26.1217 +			/* if we are replacing the front of the list then update it */
 26.1218 +			if ( pNewJoystick == *(JoyStick_DeviceData **)pContext ) 
 26.1219 +			{
 26.1220 +				*(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
 26.1221 +			}
 26.1222 +
 26.1223 +			s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
 26.1224 +			s_iNewGUID++;
 26.1225 +			if ( s_iNewGUID < MAX_JOYSTICKS )
 26.1226 +				return DIENUM_CONTINUE; // already have this joystick loaded, just keep going
 26.1227 +			else
 26.1228 +				return DIENUM_STOP; 
 26.1229 +		}
 26.1230 +
 26.1231 +		pNewJoystick = pNewJoystick->pNext;
 26.1232 +	}
 26.1233 +
 26.1234 +	s_bDeviceAdded = SDL_TRUE;
 26.1235 +
 26.1236 +	bXInputDevice = IsXInputDevice( &pdidInstance->guidProduct );
 26.1237 +
 26.1238 +	pNewJoystick = (JoyStick_DeviceData *)SDL_malloc( sizeof(JoyStick_DeviceData) );
 26.1239 +
 26.1240 +	if ( bXInputDevice )
 26.1241 +	{
 26.1242 +		SDL_memset(&(pNewJoystick->dxdevice), 0x0,
 26.1243 +			sizeof(DIDEVICEINSTANCE));
 26.1244 +		pNewJoystick->bXInputDevice = 1;
 26.1245 +		pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
 26.1246 +	}
 26.1247 +	else
 26.1248 +	{
 26.1249 +		pNewJoystick->bXInputDevice = 0;
 26.1250 +		SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
 26.1251 +			sizeof(DIDEVICEINSTANCE));
 26.1252 +	}
 26.1253 +	pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
 26.1254 +	pNewJoystick->send_add_event = 1;
 26.1255 +	pNewJoystick->nInstanceID = ++s_nInstanceID;
 26.1256 +	SDL_memcpy( &pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid) );
 26.1257 +	pNewJoystick->pNext = NULL;
 26.1258 +
 26.1259 +	if ( SYS_Joystick )
 26.1260 +	{
 26.1261 +		pNewJoystick->pNext = SYS_Joystick;
 26.1262 +	}
 26.1263 +	SYS_Joystick = pNewJoystick;
 26.1264 +
 26.1265 +	s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
 26.1266 +	s_iNewGUID++;
 26.1267 +
 26.1268 +	if ( s_iNewGUID < MAX_JOYSTICKS )
 26.1269 +		return DIENUM_CONTINUE; // already have this joystick loaded, just keep going
 26.1270 +	else
 26.1271 +		return DIENUM_STOP; 
 26.1272 +}
 26.1273 +
 26.1274 +
 26.1275 +/* detect any new joysticks being inserted into the system */
 26.1276 +void SDL_SYS_JoystickDetect()
 26.1277 +{
 26.1278 +	HRESULT result;
 26.1279 +	JoyStick_DeviceData *pCurList = NULL;
 26.1280 +	/* only enum the devices if the joystick thread told us something changed */
 26.1281 +	if ( s_bDeviceAdded || s_bDeviceRemoved )
 26.1282 +	{
 26.1283 +		s_bDeviceAdded = SDL_FALSE;
 26.1284 +		s_bDeviceRemoved = SDL_FALSE;
 26.1285 +
 26.1286 +		pCurList = SYS_Joystick;
 26.1287 +		SYS_Joystick = NULL;
 26.1288 +		s_iNewGUID = 0;
 26.1289 +		SDL_mutexP( s_mutexJoyStickEnum );
 26.1290 +
 26.1291 +		if ( !s_pKnownJoystickGUIDs )
 26.1292 +			s_pKnownJoystickGUIDs = SDL_malloc( sizeof(GUID)*MAX_JOYSTICKS );
 26.1293 +				
 26.1294 +		SDL_memset( s_pKnownJoystickGUIDs, 0x0, sizeof(GUID)*MAX_JOYSTICKS );
 26.1295 +
 26.1296 +		/* Look for joysticks, wheels, head trackers, gamepads, etc.. */
 26.1297 +		result = IDirectInput8_EnumDevices(dinput,
 26.1298 +			DI8DEVCLASS_GAMECTRL,
 26.1299 +			EnumJoysticksCallback,
 26.1300 +			&pCurList, DIEDFL_ATTACHEDONLY);
 26.1301 +
 26.1302 +		SDL_mutexV( s_mutexJoyStickEnum );
 26.1303 +	}
 26.1304 +
 26.1305 +	if ( pCurList )
 26.1306 +	{
 26.1307 +		while ( pCurList )
 26.1308 +		{
 26.1309 +			JoyStick_DeviceData *pListNext = NULL;
 26.1310 +#if !SDL_EVENTS_DISABLED
 26.1311 +			SDL_Event event;
 26.1312 +			event.type = SDL_JOYDEVICEREMOVED;
 26.1313 +
 26.1314 +			if (SDL_GetEventState(event.type) == SDL_ENABLE) {
 26.1315 +				event.jdevice.which = pCurList->nInstanceID;
 26.1316 +				if ((SDL_EventOK == NULL)
 26.1317 +					|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
 26.1318 +						SDL_PushEvent(&event);
 26.1319 +				}
 26.1320 +			}
 26.1321 +#endif // !SDL_EVENTS_DISABLED 
 26.1322 +
 26.1323 +			pListNext = pCurList->pNext;
 26.1324 +			SDL_free(pCurList->joystickname);
 26.1325 +			SDL_free( pCurList );
 26.1326 +			pCurList = pListNext;
 26.1327 +		}
 26.1328 +
 26.1329 +	}
 26.1330 +
 26.1331 +	if ( s_bDeviceAdded )
 26.1332 +	{
 26.1333 +		JoyStick_DeviceData *pNewJoystick;
 26.1334 +		int device_index = 0;
 26.1335 +		s_bDeviceAdded = SDL_FALSE;
 26.1336 +		pNewJoystick = SYS_Joystick;
 26.1337 +		while ( pNewJoystick )
 26.1338 +		{
 26.1339 +			if ( pNewJoystick->send_add_event )
 26.1340 +			{
 26.1341 +#if !SDL_EVENTS_DISABLED
 26.1342 +				SDL_Event event;
 26.1343 +				event.type = SDL_JOYDEVICEADDED;
 26.1344 +
 26.1345 +				if (SDL_GetEventState(event.type) == SDL_ENABLE) {
 26.1346 +					event.jdevice.which = device_index;
 26.1347 +					if ((SDL_EventOK == NULL)
 26.1348 +						|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
 26.1349 +							SDL_PushEvent(&event);
 26.1350 +					}
 26.1351 +				}
 26.1352 +#endif /* !SDL_EVENTS_DISABLED */
 26.1353 +				pNewJoystick->send_add_event = 0;
 26.1354 +			}
 26.1355 +			device_index++;
 26.1356 +			pNewJoystick = pNewJoystick->pNext;
 26.1357 +		}
 26.1358 +	}
 26.1359 +}
 26.1360 +
 26.1361 +
 26.1362 +/* we need to poll if we have pending hotplug device changes or connected devices */
 26.1363 +int SDL_SYS_JoystickNeedsPolling()
 26.1364 +{
 26.1365 +	/* we have a new device or one was pulled, we need to think this frame please */
 26.1366 +	if ( s_bDeviceAdded || s_bDeviceRemoved )
 26.1367 +		return 1;
 26.1368 +
 26.1369 +	return 0;
 26.1370 +}
 26.1371 +
 26.1372 +/* return the stable device guid for this device index */
 26.1373 +JoystickGUID SDL_SYS_PrivateJoystickGetDeviceID( int device_index )
 26.1374 +{
 26.1375 +	JoyStick_DeviceData *device = SYS_Joystick;
 26.1376 +	int index;
 26.1377 +
 26.1378 +	for (index = device_index; index > 0; index--)
 26.1379 +		device = device->pNext;
 26.1380 +
 26.1381 +	return device->guid;
 26.1382 +}
 26.1383 +
 26.1384 +/* return 1 if this device is using XInput */
 26.1385 +int SDL_SYS_IsXInputDeviceIndex( int device_index )
 26.1386 +{
 26.1387 +	JoyStick_DeviceData *device = SYS_Joystick;
 26.1388 +	int index;
 26.1389 +
 26.1390 +	for (index = device_index; index > 0; index--)
 26.1391 +		device = device->pNext;
 26.1392 +
 26.1393 +	return device->bXInputDevice;
 26.1394 +}
 26.1395 +
 26.1396 +JoystickGUID SDL_SYS_PrivateJoystickGetGUID(SDL_Joystick * joystick)
 26.1397 +{
 26.1398 +	return joystick->hwdata->guid;
 26.1399  }
 26.1400  
 26.1401  #endif /* SDL_JOYSTICK_DINPUT */
    27.1 --- a/src/joystick/windows/SDL_dxjoystick_c.h	Mon Nov 26 14:59:07 2012 -0800
    27.2 +++ b/src/joystick/windows/SDL_dxjoystick_c.h	Mon Nov 26 16:37:54 2012 -0800
    27.3 @@ -34,9 +34,14 @@
    27.4  
    27.5  #include "../../core/windows/SDL_windows.h"
    27.6  
    27.7 -#define DIRECTINPUT_VERSION 0x0700      /* Need version 7 for force feedback. */
    27.8 +#define DIRECTINPUT_VERSION 0x0800      /* Need version 7 for force feedback. Need verison 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */
    27.9  #include <dinput.h>
   27.10 -
   27.11 +#define COBJMACROS
   27.12 +#include <wbemcli.h>
   27.13 +#include <oleauto.h>
   27.14 +#include <xinput.h>
   27.15 +#include <devguid.h>
   27.16 +#include <dbt.h>
   27.17  
   27.18  #define MAX_INPUTS	256     /* each joystick can have up to 256 inputs */
   27.19  
   27.20 @@ -57,15 +62,42 @@
   27.21      Uint8 num;
   27.22  } input_t;
   27.23  
   27.24 +/* typedef's for XInput structs we use */
   27.25 +typedef struct
   27.26 +{
   27.27 +	WORD                                wButtons;
   27.28 +	BYTE                                bLeftTrigger;
   27.29 +	BYTE                                bRightTrigger;
   27.30 +	SHORT                               sThumbLX;
   27.31 +	SHORT                               sThumbLY;
   27.32 +	SHORT                               sThumbRX;
   27.33 +	SHORT                               sThumbRY;
   27.34 +	DWORD								dwPaddingReserved;
   27.35 +} XINPUT_GAMEPAD_EX;
   27.36 +
   27.37 +typedef struct 
   27.38 +{
   27.39 +	DWORD                               dwPacketNumber;
   27.40 +	XINPUT_GAMEPAD_EX                   Gamepad;
   27.41 +} XINPUT_STATE_EX;
   27.42 +
   27.43  /* The private structure used to keep track of a joystick */
   27.44  struct joystick_hwdata
   27.45  {
   27.46      LPDIRECTINPUTDEVICE2 InputDevice;
   27.47      DIDEVCAPS Capabilities;
   27.48      int buffered;
   27.49 +	JoystickGUID guid;
   27.50  
   27.51      input_t Inputs[MAX_INPUTS];
   27.52      int NumInputs;
   27.53 +	int NumSliders;
   27.54 +	Uint8 removed;
   27.55 +	Uint8 send_remove_event;
   27.56 +	Uint8 bXInputDevice; // 1 if this device supports using the xinput API rather than DirectInput
   27.57 +	Uint8 userid; // XInput userid index for this joystick
   27.58 +	Uint8 currentXInputSlot; // the current position to write to in XInputState below, used so we can compare old and new values
   27.59 +	XINPUT_STATE_EX	XInputState[2];
   27.60  };
   27.61  
   27.62  #endif /* SDL_JOYSTICK_DINPUT_H */
    28.1 --- a/test/Makefile.in	Mon Nov 26 14:59:07 2012 -0800
    28.2 +++ b/test/Makefile.in	Mon Nov 26 16:37:54 2012 -0800
    28.3 @@ -14,6 +14,7 @@
    28.4  	testdraw2$(EXE) \
    28.5  	testerror$(EXE) \
    28.6  	testfile$(EXE) \
    28.7 +	testgamecontroller$(EXE) \
    28.8  	testgesture$(EXE) \
    28.9  	testgl2$(EXE) \
   28.10  	testgles$(EXE) \
   28.11 @@ -87,6 +88,9 @@
   28.12  testfile$(EXE): $(srcdir)/testfile.c
   28.13  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
   28.14  
   28.15 +testgamecontroller$(EXE): $(srcdir)/testgamecontroller.c
   28.16 +	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
   28.17 + 
   28.18  testgesture$(EXE): $(srcdir)/testgesture.c
   28.19  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@
   28.20   
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/test/testgamecontroller.c	Mon Nov 26 16:37:54 2012 -0800
    29.3 @@ -0,0 +1,205 @@
    29.4 +/*
    29.5 +  Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
    29.6 +
    29.7 +  This software is provided 'as-is', without any express or implied
    29.8 +  warranty.  In no event will the authors be held liable for any damages
    29.9 +  arising from the use of this software.
   29.10 +
   29.11 +  Permission is granted to anyone to use this software for any purpose,
   29.12 +  including commercial applications, and to alter it and redistribute it
   29.13 +  freely.
   29.14 +*/
   29.15 +
   29.16 +/* Simple program to test the SDL game controller routines */
   29.17 +
   29.18 +#include <stdio.h>
   29.19 +#include <stdlib.h>
   29.20 +#include <string.h>
   29.21 +
   29.22 +#include "SDL.h"
   29.23 +
   29.24 +#ifdef __IPHONEOS__
   29.25 +#define SCREEN_WIDTH	320
   29.26 +#define SCREEN_HEIGHT	480
   29.27 +#else
   29.28 +#define SCREEN_WIDTH	640
   29.29 +#define SCREEN_HEIGHT	480
   29.30 +#endif
   29.31 +
   29.32 +#define MAX_NUM_AXES 6
   29.33 +#define MAX_NUM_HATS 2
   29.34 +
   29.35 +static SDL_bool s_ForceQuit = SDL_FALSE;
   29.36 +
   29.37 +static void
   29.38 +DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h)
   29.39 +{
   29.40 +    const SDL_Rect area = { x, y, w, h };
   29.41 +    SDL_RenderFillRect(r, &area);
   29.42 +}
   29.43 +
   29.44 +void
   29.45 +WatchGameController(SDL_GameController * gamecontroller)
   29.46 +{
   29.47 +    SDL_Window *window = NULL;
   29.48 +    SDL_Renderer *screen = NULL;
   29.49 +    const char *name = NULL;
   29.50 +    int done = 0;
   29.51 +    SDL_Event event;
   29.52 +    int i;
   29.53 +
   29.54 +    /* Create a window to display controller axis position */
   29.55 +    window = SDL_CreateWindow("Game Controller Test", SDL_WINDOWPOS_CENTERED,
   29.56 +                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
   29.57 +                              SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
   29.58 +    if (window == NULL) {
   29.59 +        fprintf(stderr, "Couldn't create window: %s\n", SDL_GetError());
   29.60 +        return;
   29.61 +    }
   29.62 +
   29.63 +    screen = SDL_CreateRenderer(window, -1, 0);
   29.64 +    if (screen == NULL) {
   29.65 +        fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError());
   29.66 +        SDL_DestroyWindow(window);
   29.67 +        return;
   29.68 +    }
   29.69 +
   29.70 +    SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   29.71 +    SDL_RenderClear(screen);
   29.72 +    SDL_RenderPresent(screen);
   29.73 +	SDL_RaiseWindow(window);
   29.74 +
   29.75 +    /* Print info about the controller we are watching */
   29.76 +    name = SDL_GameControllerName(gamecontroller);
   29.77 +    printf("Watching controller %s\n",  name ? name : "Unknown Controller");
   29.78 +    
   29.79 +    /* Loop, getting controller events! */
   29.80 +    while (!done) {
   29.81 +        /* blank screen, set up for drawing this frame. */
   29.82 +        SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   29.83 +        SDL_RenderClear(screen);
   29.84 +
   29.85 +        while (SDL_PollEvent(&event)) {
   29.86 +            switch (event.type) {
   29.87 +            case SDL_CONTROLLERAXISMOTION:
   29.88 +                printf("Controller %d axis %d value: %d\n",
   29.89 +                       event.caxis.which,
   29.90 +                       event.caxis.axis, event.caxis.value);
   29.91 +                break;
   29.92 +            case SDL_CONTROLLERBUTTONDOWN:
   29.93 +                printf("Controller %d button %d down\n",
   29.94 +                       event.cbutton.which, event.cbutton.button);
   29.95 +                break;
   29.96 +            case SDL_CONTROLLERBUTTONUP:
   29.97 +                printf("Controller %d button %d up\n",
   29.98 +                       event.cbutton.which, event.cbutton.button);
   29.99 +                break;
  29.100 +            case SDL_KEYDOWN:
  29.101 +                if (event.key.keysym.sym != SDLK_ESCAPE) {
  29.102 +                    break;
  29.103 +                }
  29.104 +                /* Fall through to signal quit */
  29.105 +            case SDL_QUIT:
  29.106 +                done = 1;
  29.107 +				s_ForceQuit = SDL_TRUE;
  29.108 +                break;
  29.109 +            default:
  29.110 +                break;
  29.111 +            }
  29.112 +        }
  29.113 +        /* Update visual controller state */
  29.114 +        SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE);
  29.115 +        for (i = 0; i <SDL_CONTROLLER_BUTTON_MAX; ++i) {
  29.116 +            if (SDL_GameControllerGetButton(gamecontroller, i) == SDL_PRESSED) {
  29.117 +                DrawRect(screen, i * 34, SCREEN_HEIGHT - 34, 32, 32);
  29.118 +            }
  29.119 +        }
  29.120 +
  29.121 +        SDL_SetRenderDrawColor(screen, 0xFF, 0x00, 0x00, SDL_ALPHA_OPAQUE);
  29.122 +        for (i = 0; i < SDL_CONTROLLER_AXIS_MAX / 2; ++i) {
  29.123 +            /* Draw the X/Y axis */
  29.124 +            int x, y;
  29.125 +            x = (((int) SDL_GameControllerGetAxis(gamecontroller, i * 2 + 0)) + 32768);
  29.126 +            x *= SCREEN_WIDTH;
  29.127 +            x /= 65535;
  29.128 +            if (x < 0) {
  29.129 +                x = 0;
  29.130 +            } else if (x > (SCREEN_WIDTH - 16)) {
  29.131 +                x = SCREEN_WIDTH - 16;
  29.132 +            }
  29.133 +            y = (((int) SDL_GameControllerGetAxis(gamecontroller, i * 2 + 1)) + 32768);
  29.134 +            y *= SCREEN_HEIGHT;
  29.135 +            y /= 65535;
  29.136 +            if (y < 0) {
  29.137 +                y = 0;
  29.138 +            } else if (y > (SCREEN_HEIGHT - 16)) {
  29.139 +                y = SCREEN_HEIGHT - 16;
  29.140 +            }
  29.141 +
  29.142 +            DrawRect(screen, x, y, 16, 16);
  29.143 +        }
  29.144 +
  29.145 +        SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0xFF, SDL_ALPHA_OPAQUE);
  29.146 +
  29.147 +        SDL_RenderPresent(screen);
  29.148 +		
  29.149 +		if ( !done )
  29.150 +			done = SDL_GameControllerGetAttached( gamecontroller ) == 0;
  29.151 +    }
  29.152 +
  29.153 +    SDL_DestroyRenderer(screen);
  29.154 +    SDL_DestroyWindow(window);
  29.155 +}
  29.156 +
  29.157 +int
  29.158 +main(int argc, char *argv[])
  29.159 +{
  29.160 +    const char *name;
  29.161 +    int i;
  29.162 +	int nController = 0;
  29.163 +    SDL_GameController *gamecontroller;
  29.164 +
  29.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" );
  29.166 +    /* Initialize SDL (Note: video is required to start event loop) */
  29.167 +    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER ) < 0) {
  29.168 +        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
  29.169 +        exit(1);
  29.170 +    }
  29.171 +
  29.172 +    /* Print information about the controller */
  29.173 +    for (i = 0; i < SDL_NumJoysticks(); ++i) {
  29.174 +		if ( SDL_IsGameController(i) )
  29.175 +		{
  29.176 +			nController++;
  29.177 +			name = SDL_GameControllerNameForIndex(i);
  29.178 +			printf("Game Controller %d: %s\n", i, name ? name : "Unknown Controller");
  29.179 +		}
  29.180 +    }
  29.181 +	printf("There are %d game controllers attached\n", nController);
  29.182 +
  29.183 +    if (argv[1]) {
  29.184 +		int nreportederror = 0;
  29.185 +		SDL_Event event;
  29.186 +		gamecontroller = SDL_GameControllerOpen(atoi(argv[1]));
  29.187 +		while ( s_ForceQuit == SDL_FALSE ) {
  29.188 +			if (gamecontroller == NULL) {
  29.189 +				if ( nreportederror == 0 ) {
  29.190 +					printf("Couldn't open joystick %d: %s\n", atoi(argv[1]), SDL_GetError());
  29.191 +					nreportederror = 1;
  29.192 +				}
  29.193 +			} else {
  29.194 +				nreportederror = 0;
  29.195 +				WatchGameController(gamecontroller);
  29.196 +				SDL_GameControllerClose(gamecontroller);
  29.197 +			}
  29.198 +			
  29.199 +			gamecontroller = NULL;
  29.200 +			SDL_WaitEvent( &event );
  29.201 +			if ( event.type == SDL_JOYDEVICEADDED )
  29.202 +				gamecontroller = SDL_GameControllerOpen(atoi(argv[1]));
  29.203 +		}
  29.204 +	}
  29.205 +    SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER );
  29.206 +
  29.207 +    return (0);
  29.208 +}
    30.1 --- a/test/testjoystick.c	Mon Nov 26 14:59:07 2012 -0800
    30.2 +++ b/test/testjoystick.c	Mon Nov 26 16:37:54 2012 -0800
    30.3 @@ -17,10 +17,14 @@
    30.4  #include <string.h>
    30.5  
    30.6  #include "SDL.h"
    30.7 -#include "common.h"
    30.8  
    30.9 -static CommonState *state;
   30.10 -static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE;
   30.11 +#ifdef __IPHONEOS__
   30.12 +#define SCREEN_WIDTH	320
   30.13 +#define SCREEN_HEIGHT	480
   30.14 +#else
   30.15 +#define SCREEN_WIDTH	640
   30.16 +#define SCREEN_HEIGHT	480
   30.17 +#endif
   30.18  
   30.19  #define MAX_NUM_AXES 6
   30.20  #define MAX_NUM_HATS 2
   30.21 @@ -37,16 +41,35 @@
   30.22  {
   30.23      SDL_Window *window = NULL;
   30.24      SDL_Renderer *screen = NULL;
   30.25 -    SDL_Rect viewport;
   30.26 -    SDL_Event event;
   30.27 -
   30.28      const char *name = NULL;
   30.29      int done = 0;
   30.30 +    SDL_Event event;
   30.31      int i;
   30.32  
   30.33 +    /* Create a window to display joystick axis position */
   30.34 +    window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
   30.35 +                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
   30.36 +                              SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
   30.37 +    if (window == NULL) {
   30.38 +        fprintf(stderr, "Couldn't create window: %s\n", SDL_GetError());
   30.39 +        return;
   30.40 +    }
   30.41 +
   30.42 +    screen = SDL_CreateRenderer(window, -1, 0);
   30.43 +    if (screen == NULL) {
   30.44 +        fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError());
   30.45 +        SDL_DestroyWindow(window);
   30.46 +        return;
   30.47 +    }
   30.48 +
   30.49 +    SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   30.50 +    SDL_RenderClear(screen);
   30.51 +    SDL_RenderPresent(screen);
   30.52 +	SDL_RaiseWindow(window);
   30.53 +
   30.54      /* Print info about the joystick we are watching */
   30.55 -    name = SDL_JoystickName(SDL_JoystickIndex(joystick));
   30.56 -    printf("Watching joystick %d: (%s)\n", SDL_JoystickIndex(joystick),
   30.57 +    name = SDL_JoystickName(joystick);
   30.58 +    printf("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
   30.59             name ? name : "Unknown Joystick");
   30.60      printf("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
   30.61             SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
   30.62 @@ -54,6 +77,10 @@
   30.63  
   30.64      /* Loop, getting joystick events! */
   30.65      while (!done) {
   30.66 +        /* blank screen, set up for drawing this frame. */
   30.67 +        SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   30.68 +        SDL_RenderClear(screen);
   30.69 +
   30.70          while (SDL_PollEvent(&event)) {
   30.71              switch (event.type) {
   30.72              case SDL_JOYAXISMOTION:
   30.73 @@ -101,100 +128,86 @@
   30.74                  break;
   30.75              }
   30.76          }
   30.77 -
   30.78          /* Update visual joystick state */
   30.79 -        for (i = 0; i < state->num_windows; ++i) {
   30.80 -            screen = state->renderers[i];
   30.81 -
   30.82 -            /* Erase previous axes */
   30.83 -            SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   30.84 -            SDL_RenderClear(screen);
   30.85 +        SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE);
   30.86 +        for (i = 0; i < SDL_JoystickNumButtons(joystick); ++i) {
   30.87 +            if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) {
   30.88 +                DrawRect(screen, i * 34, SCREEN_HEIGHT - 34, 32, 32);
   30.89 +            }
   30.90 +        }
   30.91  
   30.92 -            /* Query the sizes */
   30.93 -            SDL_RenderGetViewport(screen, &viewport);
   30.94 -
   30.95 -            SDL_SetRenderDrawColor(screen, 0x00, 0xFF, 0x00, SDL_ALPHA_OPAQUE);
   30.96 -            for (i = 0; i < SDL_JoystickNumButtons(joystick); ++i) {
   30.97 -                if (SDL_JoystickGetButton(joystick, i) == SDL_PRESSED) {
   30.98 -                    DrawRect(screen, i * 34, viewport.h - 34, 32, 32);
   30.99 -                }
  30.100 +        SDL_SetRenderDrawColor(screen, 0xFF, 0x00, 0x00, SDL_ALPHA_OPAQUE);
  30.101 +        for (i = 0; i < SDL_JoystickNumAxes(joystick) / 2; ++i) {
  30.102 +            /* Draw the X/Y axis */
  30.103 +            int x, y;
  30.104 +            x = (((int) SDL_JoystickGetAxis(joystick, i * 2 + 0)) + 32768);
  30.105 +            x *= SCREEN_WIDTH;
  30.106 +            x /= 65535;
  30.107 +            if (x < 0) {
  30.108 +                x = 0;
  30.109 +            } else if (x > (SCREEN_WIDTH - 16)) {
  30.110 +                x = SCREEN_WIDTH - 16;
  30.111 +            }
  30.112 +            y = (((int) SDL_JoystickGetAxis(joystick, i * 2 + 1)) + 32768);
  30.113 +            y *= SCREEN_HEIGHT;
  30.114 +            y /= 65535;
  30.115 +            if (y < 0) {
  30.116 +                y = 0;
  30.117 +            } else if (y > (SCREEN_HEIGHT - 16)) {
  30.118 +                y = SCREEN_HEIGHT - 16;
  30.119              }
  30.120  
  30.121 -            SDL_SetRenderDrawColor(screen, 0xFF, 0x00, 0x00, SDL_ALPHA_OPAQUE);
  30.122 -            for (i = 0; i < SDL_JoystickNumAxes(joystick) / 2; ++i) {
  30.123 -                /* Draw the X/Y axis */
  30.124 -                int x, y;
  30.125 -                x = (((int) SDL_JoystickGetAxis(joystick, i * 2 + 0)) + 32768);
  30.126 -                x *= viewport.w ;
  30.127 -                x /= 65535;
  30.128 -                if (x < 0) {
  30.129 -                    x = 0;
  30.130 -                } else if (x > (viewport.w - 16)) {
  30.131 -                    x = viewport.w - 16;
  30.132 -                }
  30.133 -                y = (((int) SDL_JoystickGetAxis(joystick, i * 2 + 1)) + 32768);
  30.134 -                y *= viewport.h;
  30.135 -                y /= 65535;
  30.136 -                if (y < 0) {
  30.137 -                    y = 0;
  30.138 -                } else if (y > (viewport.h - 16)) {
  30.139 -                    y = viewport.h - 16;
  30.140 -                }
  30.141 +            DrawRect(screen, x, y, 16, 16);
  30.142 +        }
  30.143  
  30.144 -                DrawRect(screen, x, y, 16, 16);
  30.145 +        SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0xFF, SDL_ALPHA_OPAQUE);
  30.146 +        for (i = 0; i < SDL_JoystickNumHats(joystick); ++i) {
  30.147 +            /* Derive the new position */
  30.148 +            int x = SCREEN_WIDTH/2;
  30.149 +            int y = SCREEN_HEIGHT/2;
  30.150 +            const Uint8 hat_pos = SDL_JoystickGetHat(joystick, i);
  30.151 +
  30.152 +            if (hat_pos & SDL_HAT_UP) {
  30.153 +                y = 0;
  30.154 +            } else if (hat_pos & SDL_HAT_DOWN) {
  30.155 +                y = SCREEN_HEIGHT-8;
  30.156              }
  30.157  
  30.158 -            SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0xFF, SDL_ALPHA_OPAQUE);
  30.159 -            for (i = 0; i < SDL_JoystickNumHats(joystick); ++i) {
  30.160 -                /* Derive the new position */
  30.161 -                int x = viewport.w/2;
  30.162 -                int y = viewport.h/2;
  30.163 -                const Uint8 hat_pos = SDL_JoystickGetHat(joystick, i);
  30.164 -
  30.165 -                if (hat_pos & SDL_HAT_UP) {
  30.166 -                    y = 0;
  30.167 -                } else if (hat_pos & SDL_HAT_DOWN) {
  30.168 -                    y = viewport.h-8;
  30.169 -                }
  30.170 -
  30.171 -                if (hat_pos & SDL_HAT_LEFT) {
  30.172 -                    x = 0;
  30.173 -                } else if (hat_pos & SDL_HAT_RIGHT) {
  30.174 -                    x = viewport.w-8;
  30.175 -                }
  30.176 -
  30.177 -                DrawRect(screen, x, y, 8, 8);
  30.178 +            if (hat_pos & SDL_HAT_LEFT) {
  30.179 +                x = 0;
  30.180 +            } else if (hat_pos & SDL_HAT_RIGHT) {
  30.181 +                x = SCREEN_WIDTH-8;
  30.182              }
  30.183  
  30.184 -            SDL_RenderPresent(screen);
  30.185 +            DrawRect(screen, x, y, 8, 8);
  30.186          }
  30.187 +
  30.188 +        SDL_RenderPresent(screen);
  30.189 +		
  30.190 +		done = SDL_JoystickGetAttached( joystick ) == 0;
  30.191      }
  30.192 +
  30.193 +    SDL_DestroyRenderer(screen);
  30.194 +    SDL_DestroyWindow(window);
  30.195  }
  30.196  
  30.197  int
  30.198  main(int argc, char *argv[])
  30.199  {
  30.200      const char *name;
  30.201 -    int i, joy=-1;
  30.202 +    int i;
  30.203      SDL_Joystick *joystick;
  30.204  
  30.205      /* Initialize SDL (Note: video is required to start event loop) */
  30.206 -    if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
  30.207 +    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
  30.208          fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
  30.209          exit(1);
  30.210      }
  30.211  
  30.212 -    /* Initialize test framework */
  30.213 -    state = CommonCreateState(argv, SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
  30.214 -    if (!state) {
  30.215 -        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
  30.216 -        return 1;
  30.217 -    }
  30.218 -
  30.219      /* Print information about the joysticks */
  30.220      printf("There are %d joysticks attached\n", SDL_NumJoysticks());
  30.221      for (i = 0; i < SDL_NumJoysticks(); ++i) {
  30.222 -        name = SDL_JoystickName(i);
  30.223 +        name = SDL_JoystickNameForIndex(i);
  30.224          printf("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
  30.225          joystick = SDL_JoystickOpen(i);
  30.226          if (joystick == NULL) {
  30.227 @@ -205,42 +218,34 @@
  30.228              printf("      balls: %d\n", SDL_JoystickNumBalls(joystick));
  30.229              printf("       hats: %d\n", SDL_JoystickNumHats(joystick));
  30.230              printf("    buttons: %d\n", SDL_JoystickNumButtons(joystick));
  30.231 +            printf("instance id: %d\n", SDL_JoystickInstanceID(joystick));
  30.232              SDL_JoystickClose(joystick);
  30.233          }
  30.234      }
  30.235  
  30.236 -    for (i = 1; i < argc;) {
  30.237 -        int consumed;
  30.238 -
  30.239 -        consumed = CommonArg(state, i);
  30.240 -        if (consumed == 0) {
  30.241 -            consumed = -1;
  30.242 -            if (SDL_isdigit(*argv[i])) {
  30.243 -                joy = SDL_atoi(argv[i]);
  30.244 -                consumed = 1;
  30.245 -            }
  30.246 -        }
  30.247 -        if (consumed < 0) {
  30.248 -            return 1;
  30.249 -        }
  30.250 -        i += consumed;
  30.251 -    }
  30.252 -    if (!CommonInit(state)) {
  30.253 -        return 2;
  30.254 -    }
  30.255 -
  30.256 -    if (joy > -1) {
  30.257 -        joystick = SDL_JoystickOpen(joy);
  30.258 -        if (joystick == NULL) {
  30.259 -            printf("Couldn't open joystick %d: %s\n", joy,
  30.260 -                   SDL_GetError());
  30.261 -        } else {
  30.262 -            WatchJoystick(joystick);
  30.263 -            SDL_JoystickClose(joystick);
  30.264 -        }
  30.265 -    }
  30.266 -    SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
  30.267 -    CommonQuit(state);
  30.268 +    if (argv[1]) {
  30.269 +		int nreportederror = 0;
  30.270 +		SDL_Event event;
  30.271 +		joystick = SDL_JoystickOpen(atoi(argv[1]));
  30.272 +		while ( 1 ) {
  30.273 +			if (joystick == NULL) {
  30.274 +				if ( nreportederror == 0 ) {
  30.275 +					printf("Couldn't open joystick %d: %s\n", atoi(argv[1]), SDL_GetError());
  30.276 +					nreportederror = 1;
  30.277 +				}
  30.278 +			} else {
  30.279 +				nreportederror = 0;
  30.280 +				WatchJoystick(joystick);
  30.281 +				SDL_JoystickClose(joystick);
  30.282 +			}
  30.283 +			
  30.284 +			joystick = NULL;
  30.285 +			SDL_WaitEvent( &event );
  30.286 +			if ( event.type == SDL_JOYDEVICEADDED )
  30.287 +				joystick = SDL_JoystickOpen(atoi(argv[1]));
  30.288 +		}
  30.289 +	}
  30.290 +    SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
  30.291  
  30.292      return (0);
  30.293  }