Moved WiimoteNew into Dolphin and eliminated the old wiimote plugin. Removed wiimote plugin support. Moved input dialog related InputUICommon stuff into DolphinWX. Removed now unused InputCommon files. UDPWiimote stuff is temporarily disabled until it is reorganized so Core won't depend on wx. Real wiimotes are now initialized on first need(wiimote diag open or game start) and left initialized until Dolphin exit.(maybe this will work better for Linux/OS X) (scons probably needs some fixes)
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6270 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@@ -1,672 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="Plugin_Wiimote"
|
||||
ProjectGUID="{8D612734-FAA5-4B8A-804F-4DEA2367D495}"
|
||||
RootNamespace="Plugin_Wiimote"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_WIIMOTE_TEST_EXPORTS;_SECURE_SCL=0"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
AssemblerListingLocation="$(IntDir)\"
|
||||
ProgramDataBaseFileName="$(IntDir)\"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wiiuse.lib rpcrt4.lib wxbase28ud.lib wxmsw28ud_core.lib"
|
||||
OutputFile="..\..\..\Binary\Win32/Plugins\Plugin_WiimoteD.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\WiiUse\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="0"
|
||||
EnableCOMDATFolding="0"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_WIIMOTE_TEST_EXPORTS;_SECURE_SCL=0"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
AssemblerListingLocation="$(IntDir)\"
|
||||
ProgramDataBaseFileName="$(IntDir)\"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wiiuse.lib rpcrt4.lib wxbase28ud.lib wxmsw28ud_core.lib"
|
||||
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_WiimoteD.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\WiiUse\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="0"
|
||||
EnableCOMDATFolding="0"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_WIIMOTE_TEST_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS"
|
||||
RuntimeLibrary="0"
|
||||
AssemblerListingLocation="$(IntDir)\"
|
||||
ProgramDataBaseFileName="$(IntDir)\"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/NODEFAULTLIB:msvcrt.lib"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wiiuse.lib wxbase28u.lib wxmsw28u_core.lib"
|
||||
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_Wiimote.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\WiiUse\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="0"
|
||||
EnableCOMDATFolding="0"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_WIIMOTE_TEST_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS"
|
||||
RuntimeLibrary="0"
|
||||
AssemblerListingLocation="$(IntDir)\"
|
||||
ProgramDataBaseFileName="$(IntDir)\"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wiiuse.lib wxbase28u.lib wxmsw28u_core.lib"
|
||||
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_Wiimote.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\WiiUse\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="0"
|
||||
EnableCOMDATFolding="0"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="DebugFast|Win32"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="DEBUGFAST;WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_WIIMOTE_TEST_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
RuntimeLibrary="0"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/NODEFAULTLIB:msvcrt.lib"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wiiuse.lib wxbase28u.lib wxmsw28u_core.lib wiiuse.lib"
|
||||
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_WiimoteDF.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\win32;..\..\..\Externals\WiiUse\win32;..\..\..\Externals\wxWidgets\lib\vc_lib\Win32"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="DebugFast|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_WIIMOTE_TEST_EXPORTS;DEBUGFAST;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
RuntimeLibrary="0"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wiiuse.lib wxbase28u.lib wxmsw28u_core.lib wiiuse.lib"
|
||||
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_WiimoteDF.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\..\Externals\SDL\x64;..\..\..\Externals\WiiUse\x64;..\..\..\Externals\wxWidgets\lib\vc_lib\x64"
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Emulated Wiimote"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\DataReports.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\EmuDefinitions.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\EmuDefinitions.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\EmuDynamics.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\EmuMain.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\EmuMain.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\EmuPad.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\EmuSubroutines.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\EmuSubroutines.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Encryption.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Encryption.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\FillReport.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Rumble.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\UDPWiimote.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\UDPWiimote.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\wiimote_hid.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Real Wiimote"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\wiimote_real.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\wiimote_real.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Config"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\Config.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Config.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ConfigBasicDlg.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ConfigBasicDlg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ConfigGamepad.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ConfigPadDlg.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\ConfigPadDlg.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="UDP Wiimote"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\UDPWiimote.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\UDPWiimote.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\Src\main.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\main.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\PluginSpecs\pluginspecs_wiimote.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\SConscript"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -1,530 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "Common.h"
|
||||
#include "IniFile.h"
|
||||
#include "StringUtil.h"
|
||||
#include "wiimote_hid.h"
|
||||
#include "Config.h"
|
||||
#include "EmuDefinitions.h" // for PadMapping
|
||||
#include "main.h"
|
||||
#include "FileUtil.h"
|
||||
#include "WXInputBase.h"
|
||||
|
||||
// Configuration file control names
|
||||
// Do not change the order unless you change the related arrays
|
||||
// Directionals are ordered as L, R, U, D
|
||||
|
||||
static const char* wmControlNames[] =
|
||||
{
|
||||
"WmA",
|
||||
"WmB",
|
||||
"Wm1",
|
||||
"Wm2",
|
||||
"WmP",
|
||||
"WmM",
|
||||
"WmH",
|
||||
"WmL",
|
||||
"WmR",
|
||||
"WmU",
|
||||
"WmD",
|
||||
"WmRollL",
|
||||
"WmRollR",
|
||||
"WmPitchU",
|
||||
"WmPitchD",
|
||||
"WmShake",
|
||||
|
||||
"NcZ",
|
||||
"NcC",
|
||||
"NcL",
|
||||
"NcR",
|
||||
"NcU",
|
||||
"NcD",
|
||||
"NcRollL",
|
||||
"NcRollR",
|
||||
"NcPitchU",
|
||||
"NcPitchD",
|
||||
"NcShake",
|
||||
|
||||
"CcA",
|
||||
"CcB",
|
||||
"CcX",
|
||||
"CcY",
|
||||
"CcP",
|
||||
"CcM",
|
||||
"CcH",
|
||||
"CcTl",
|
||||
"CcTr",
|
||||
"CcZl",
|
||||
"CcZr",
|
||||
"CcDl",
|
||||
"CcDr",
|
||||
"CcDu",
|
||||
"CcDd",
|
||||
"CcLl",
|
||||
"CcLr",
|
||||
"CcLu",
|
||||
"CcLd",
|
||||
"CcRl",
|
||||
"CcRr",
|
||||
"CcRu",
|
||||
"CcRd",
|
||||
|
||||
"GH3Green",
|
||||
"GH3Red",
|
||||
"GH3Yellow",
|
||||
"GH3Blue",
|
||||
"GH3Orange",
|
||||
"GH3Plus",
|
||||
"GH3Minus",
|
||||
"GH3Whammy",
|
||||
"GH3Al",
|
||||
"GH3Ar",
|
||||
"GH3Au",
|
||||
"GH3Ad",
|
||||
"GH3StrumUp",
|
||||
"GH3StrumDown",
|
||||
};
|
||||
|
||||
static int wmDefaultControls[] =
|
||||
{
|
||||
// Wiimote
|
||||
#ifdef _WIN32
|
||||
'Z',
|
||||
'X',
|
||||
'C',
|
||||
'V',
|
||||
VK_OEM_PLUS,
|
||||
VK_OEM_MINUS,
|
||||
VK_BACK,
|
||||
VK_LEFT,
|
||||
VK_RIGHT,
|
||||
VK_UP,
|
||||
VK_DOWN,
|
||||
'N',
|
||||
'M',
|
||||
VK_OEM_COMMA,
|
||||
VK_OEM_PERIOD,
|
||||
VK_OEM_2, // /
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
XK_z,
|
||||
XK_x,
|
||||
XK_c,
|
||||
XK_v,
|
||||
XK_equal,
|
||||
XK_minus,
|
||||
XK_BackSpace,
|
||||
XK_Left,
|
||||
XK_Right,
|
||||
XK_Up,
|
||||
XK_Down,
|
||||
XK_n,
|
||||
XK_m,
|
||||
XK_comma,
|
||||
XK_period,
|
||||
XK_slash,
|
||||
#elif defined(USE_WX) && USE_WX
|
||||
'Z',
|
||||
'X',
|
||||
'C',
|
||||
'V',
|
||||
'P',
|
||||
'O',
|
||||
WXK_BACK,
|
||||
WXK_LEFT,
|
||||
WXK_RIGHT,
|
||||
WXK_UP,
|
||||
WXK_DOWN,
|
||||
'N',
|
||||
'M',
|
||||
WXK_SEPARATOR,
|
||||
WXK_DECIMAL,
|
||||
WXK_DIVIDE,
|
||||
#else
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
#endif
|
||||
|
||||
// Nunchuck
|
||||
#ifdef _WIN32
|
||||
VK_NUMPAD0,
|
||||
VK_DECIMAL,
|
||||
VK_NUMPAD4,
|
||||
VK_NUMPAD6,
|
||||
VK_NUMPAD8,
|
||||
VK_NUMPAD5,
|
||||
VK_NUMPAD7,
|
||||
VK_NUMPAD9,
|
||||
VK_NUMPAD1,
|
||||
VK_NUMPAD3,
|
||||
VK_NUMPAD2,
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
XK_KP_0,
|
||||
XK_KP_Decimal,
|
||||
XK_KP_4,
|
||||
XK_KP_6,
|
||||
XK_KP_8,
|
||||
XK_KP_5,
|
||||
XK_KP_7,
|
||||
XK_KP_9,
|
||||
XK_KP_1,
|
||||
XK_KP_3,
|
||||
XK_KP_2,
|
||||
#elif defined(USE_WX) && USE_WX
|
||||
WXK_NUMPAD0,
|
||||
WXK_NUMPAD_DECIMAL,
|
||||
WXK_NUMPAD4,
|
||||
WXK_NUMPAD6,
|
||||
WXK_NUMPAD8,
|
||||
WXK_NUMPAD5,
|
||||
WXK_NUMPAD7,
|
||||
WXK_NUMPAD9,
|
||||
WXK_NUMPAD1,
|
||||
WXK_NUMPAD3,
|
||||
WXK_NUMPAD2,
|
||||
#else
|
||||
0,0,0,0,0,0,0,0,0,0,0,
|
||||
#endif
|
||||
|
||||
// Classic Controller
|
||||
// A, B, X, Y
|
||||
#ifdef _WIN32
|
||||
VK_OEM_4, // [
|
||||
VK_OEM_6, // ]
|
||||
VK_OEM_1, // ;
|
||||
VK_OEM_7, // '
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
XK_bracketleft,
|
||||
XK_bracketright,
|
||||
XK_semicolon,
|
||||
XK_quoteright,
|
||||
#elif defined(USE_WX) && USE_WX
|
||||
'O',
|
||||
'P',
|
||||
'K',
|
||||
'L',
|
||||
#else
|
||||
0,0,0,0,
|
||||
#endif
|
||||
// +, -, Home
|
||||
'H',
|
||||
'F',
|
||||
'G',
|
||||
// Triggers, Zs
|
||||
'E',
|
||||
'Y',
|
||||
'R',
|
||||
'T',
|
||||
// Digital pad
|
||||
#ifdef _WIN32
|
||||
VK_NUMPAD4,
|
||||
VK_NUMPAD6,
|
||||
VK_NUMPAD8,
|
||||
VK_NUMPAD5,
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
XK_KP_4,
|
||||
XK_KP_6,
|
||||
XK_KP_8,
|
||||
XK_KP_5,
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
WXK_NUMPAD4,
|
||||
WXK_NUMPAD6,
|
||||
WXK_NUMPAD8,
|
||||
WXK_NUMPAD5,
|
||||
#else
|
||||
0,0,0,0,
|
||||
#endif
|
||||
// Left analog
|
||||
'A',
|
||||
'D',
|
||||
'W',
|
||||
'S',
|
||||
// Right analog
|
||||
'J',
|
||||
'L',
|
||||
'I',
|
||||
'K',
|
||||
|
||||
// Guttar Hero
|
||||
'A',
|
||||
'S',
|
||||
'D',
|
||||
'F',
|
||||
'G',
|
||||
'L',
|
||||
'J',
|
||||
'H',
|
||||
#ifdef _WIN32
|
||||
VK_NUMPAD4,
|
||||
VK_NUMPAD6,
|
||||
VK_NUMPAD8,
|
||||
VK_NUMPAD5,
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
XK_KP_4,
|
||||
XK_KP_6,
|
||||
XK_KP_8,
|
||||
XK_KP_5,
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
WXK_NUMPAD4,
|
||||
WXK_NUMPAD6,
|
||||
WXK_NUMPAD8,
|
||||
WXK_NUMPAD5,
|
||||
#else
|
||||
0,0,0,0,
|
||||
#endif
|
||||
'I',
|
||||
'K',
|
||||
};
|
||||
|
||||
|
||||
Config g_Config;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
// Set all default values to zero
|
||||
memset(this, 0, sizeof(Config));
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
std::string temp;
|
||||
IniFile iniFile;
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Wiimote.ini").c_str());
|
||||
|
||||
// Real Wiimote
|
||||
iniFile.Get("Real", "UpdateStatus", &bUpdateRealWiimote, true);
|
||||
iniFile.Get("Real", "Unpair", &bUnpairRealWiimote, false);
|
||||
iniFile.Get("Real", "Autopair", &bPairRealWiimote, false);
|
||||
iniFile.Get("Real", "Timeout", &bWiiReadTimeout, 30);
|
||||
iniFile.Get("Real", "AccNeutralX", &iAccNeutralX, 0);
|
||||
iniFile.Get("Real", "AccNeutralY", &iAccNeutralY, 0);
|
||||
iniFile.Get("Real", "AccNeutralZ", &iAccNeutralZ, 0);
|
||||
iniFile.Get("Real", "AccNunNeutralX", &iAccNunNeutralX, 0);
|
||||
iniFile.Get("Real", "AccNunNeutralY", &iAccNunNeutralY, 0);
|
||||
iniFile.Get("Real", "AccNunNeutralZ", &iAccNunNeutralZ, 0);
|
||||
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
// Slot specific settings
|
||||
char SectionName[32];
|
||||
sprintf(SectionName, "Wiimote%i", i + 1);
|
||||
|
||||
// General
|
||||
iniFile.Get(SectionName, "Source", &WiiMoteEmu::WiiMapping[i].Source, (i == 0) ? 1 : 0);
|
||||
|
||||
iniFile.Get(SectionName, "Sideways", &WiiMoteEmu::WiiMapping[i].bSideways, false);
|
||||
iniFile.Get(SectionName, "Upright", &WiiMoteEmu::WiiMapping[i].bUpright, false);
|
||||
iniFile.Get(SectionName, "ExtensionConnected", &WiiMoteEmu::WiiMapping[i].iExtensionConnected, WiiMoteEmu::EXT_NONE);
|
||||
iniFile.Get(SectionName, "MotionPlusConnected", &WiiMoteEmu::WiiMapping[i].bMotionPlusConnected, false);
|
||||
|
||||
iniFile.Get(SectionName, "TiltInputWM", &WiiMoteEmu::WiiMapping[i].Tilt.InputWM, WiiMoteEmu::FROM_KEYBOARD);
|
||||
iniFile.Get(SectionName, "TiltInputNC", &WiiMoteEmu::WiiMapping[i].Tilt.InputNC, WiiMoteEmu::FROM_KEYBOARD);
|
||||
iniFile.Get(SectionName, "TiltRollDegree", &WiiMoteEmu::WiiMapping[i].Tilt.RollDegree, 60);
|
||||
iniFile.Get(SectionName, "TiltRollSwing", &WiiMoteEmu::WiiMapping[i].Tilt.RollSwing, false);
|
||||
iniFile.Get(SectionName, "TiltRollInvert", &WiiMoteEmu::WiiMapping[i].Tilt.RollInvert, false);
|
||||
WiiMoteEmu::WiiMapping[i].Tilt.RollRange = (WiiMoteEmu::WiiMapping[i].Tilt.RollSwing) ? 0 : WiiMoteEmu::WiiMapping[i].Tilt.RollDegree;
|
||||
iniFile.Get(SectionName, "TiltPitchDegree", &WiiMoteEmu::WiiMapping[i].Tilt.PitchDegree, 60);
|
||||
iniFile.Get(SectionName, "TiltPitchSwing", &WiiMoteEmu::WiiMapping[i].Tilt.PitchSwing, false);
|
||||
iniFile.Get(SectionName, "TiltPitchInvert", &WiiMoteEmu::WiiMapping[i].Tilt.PitchInvert, false);
|
||||
WiiMoteEmu::WiiMapping[i].Tilt.PitchRange = (WiiMoteEmu::WiiMapping[i].Tilt.PitchSwing) ? 0 : WiiMoteEmu::WiiMapping[i].Tilt.PitchDegree;
|
||||
|
||||
// StickMapping
|
||||
iniFile.Get(SectionName, "NCStick", &WiiMoteEmu::WiiMapping[i].Stick.NC, WiiMoteEmu::FROM_KEYBOARD);
|
||||
iniFile.Get(SectionName, "CCStickLeft", &WiiMoteEmu::WiiMapping[i].Stick.CCL, WiiMoteEmu::FROM_KEYBOARD);
|
||||
iniFile.Get(SectionName, "CCStickRight", &WiiMoteEmu::WiiMapping[i].Stick.CCR, WiiMoteEmu::FROM_KEYBOARD);
|
||||
iniFile.Get(SectionName, "CCTriggers", &WiiMoteEmu::WiiMapping[i].Stick.CCT, WiiMoteEmu::FROM_KEYBOARD);
|
||||
iniFile.Get(SectionName, "GHStick", &WiiMoteEmu::WiiMapping[i].Stick.GH, WiiMoteEmu::FROM_KEYBOARD);
|
||||
|
||||
// ButtonMapping
|
||||
for (int x = 0; x < WiiMoteEmu::LAST_CONSTANT; x++)
|
||||
iniFile.Get(SectionName, wmControlNames[x], &WiiMoteEmu::WiiMapping[i].Button[x], wmDefaultControls[x]);
|
||||
|
||||
// This pad Id could possibly be higher than the number of pads that are connected,
|
||||
// but we check later, when needed, that that is not the case
|
||||
iniFile.Get(SectionName, "DeviceID", &WiiMoteEmu::WiiMapping[i].ID, 0);
|
||||
|
||||
iniFile.Get(SectionName, "Axis_Lx", &WiiMoteEmu::WiiMapping[i].AxisMapping.Lx, 0);
|
||||
iniFile.Get(SectionName, "Axis_Ly", &WiiMoteEmu::WiiMapping[i].AxisMapping.Ly, 1);
|
||||
iniFile.Get(SectionName, "Axis_Rx", &WiiMoteEmu::WiiMapping[i].AxisMapping.Rx, 2);
|
||||
iniFile.Get(SectionName, "Axis_Ry", &WiiMoteEmu::WiiMapping[i].AxisMapping.Ry, 3);
|
||||
iniFile.Get(SectionName, "Trigger_L", &WiiMoteEmu::WiiMapping[i].AxisMapping.Tl, 1004);
|
||||
iniFile.Get(SectionName, "Trigger_R", &WiiMoteEmu::WiiMapping[i].AxisMapping.Tr, 1005);
|
||||
iniFile.Get(SectionName, "DeadZoneL", &WiiMoteEmu::WiiMapping[i].DeadZoneL, 0);
|
||||
iniFile.Get(SectionName, "DeadZoneR", &WiiMoteEmu::WiiMapping[i].DeadZoneR, 0);
|
||||
iniFile.Get(SectionName, "Diagonal", &WiiMoteEmu::WiiMapping[i].Diagonal, 100);
|
||||
iniFile.Get(SectionName, "Circle2Square", &WiiMoteEmu::WiiMapping[i].bCircle2Square, false);
|
||||
iniFile.Get(SectionName, "Rumble", &WiiMoteEmu::WiiMapping[i].Rumble, false);
|
||||
iniFile.Get(SectionName, "RumbleStrength", &WiiMoteEmu::WiiMapping[i].RumbleStrength, 80);
|
||||
iniFile.Get(SectionName, "TriggerType", &WiiMoteEmu::WiiMapping[i].TriggerType, 0);
|
||||
|
||||
//UDPWii
|
||||
iniFile.Get(SectionName, "UDPWii_Enable", &WiiMoteEmu::WiiMapping[i].UDPWM.enable, false);
|
||||
std::string port;
|
||||
char default_port[15];
|
||||
sprintf(default_port,"%d",4432+i);
|
||||
iniFile.Get(SectionName, "UDPWii_Port", &port, default_port);
|
||||
strncpy(WiiMoteEmu::WiiMapping[i].UDPWM.port,port.c_str(),10);
|
||||
iniFile.Get(SectionName, "UDPWii_EnableAccel", &WiiMoteEmu::WiiMapping[i].UDPWM.enableAccel, true);
|
||||
iniFile.Get(SectionName, "UDPWii_EnableButtons", &WiiMoteEmu::WiiMapping[i].UDPWM.enableButtons, true);
|
||||
iniFile.Get(SectionName, "UDPWii_EnableIR", &WiiMoteEmu::WiiMapping[i].UDPWM.enableIR, true);
|
||||
iniFile.Get(SectionName, "UDPWii_EnableNunchuck", &WiiMoteEmu::WiiMapping[i].UDPWM.enableNunchuck, true);
|
||||
}
|
||||
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Dolphin.ini").c_str());
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
char SectionName[32];
|
||||
sprintf(SectionName, "Wiimote%i", i + 1);
|
||||
iniFile.Get(SectionName, "AutoReconnectRealWiimote", &WiiMoteEmu::WiiMapping[i].bWiiAutoReconnect, false);
|
||||
}
|
||||
|
||||
Config::LoadIR();
|
||||
|
||||
// Load a few screen settings to. If these are added to the DirectX plugin it's probably
|
||||
// better to place them in the main Dolphin.ini file
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_opengl.ini").c_str());
|
||||
iniFile.Get("Settings", "KeepAR_4_3", &bKeepAR43, false);
|
||||
iniFile.Get("Settings", "KeepAR_16_9", &bKeepAR169, false);
|
||||
iniFile.Get("Settings", "Crop", &bCrop, false);
|
||||
|
||||
//DEBUG_LOG(WIIMOTE, "Load()");
|
||||
}
|
||||
|
||||
void Config::LoadIR()
|
||||
{
|
||||
// Load the IR cursor settings if it's avaliable for the GameId, if not load the default settings
|
||||
IniFile iniFile;
|
||||
char TmpSection[32];
|
||||
int defaultLeft, defaultTop, defaultWidth, defaultHeight;
|
||||
|
||||
sprintf(TmpSection, "%s", g_ISOId ? Hex2Ascii(g_ISOId).c_str() : "Default");
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "IrPointer.ini").c_str());
|
||||
//Load defaults first...
|
||||
iniFile.Get("Default", "IRLeft", &defaultLeft, LEFT);
|
||||
iniFile.Get("Default", "IRTop", &defaultTop, TOP);
|
||||
iniFile.Get("Default", "IRWidth", &defaultWidth, RIGHT - LEFT);
|
||||
iniFile.Get("Default", "IRHeight", &defaultHeight, BOTTOM - TOP);
|
||||
iniFile.Get("Default", "IRLevel", &iIRLevel, 3);
|
||||
|
||||
//...and fall back to them if the GameId is not found.
|
||||
//It shouldn't matter if we read Default twice, its in memory anyways.
|
||||
iniFile.Get(TmpSection, "IRLeft", &iIRLeft, defaultLeft);
|
||||
iniFile.Get(TmpSection, "IRTop", &iIRTop, defaultTop);
|
||||
iniFile.Get(TmpSection, "IRWidth", &iIRWidth, defaultWidth);
|
||||
iniFile.Get(TmpSection, "IRHeight", &iIRHeight, defaultHeight);
|
||||
}
|
||||
|
||||
void Config::Save()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Wiimote.ini").c_str());
|
||||
|
||||
iniFile.Set("Real", "UpdateStatus", bUpdateRealWiimote);
|
||||
iniFile.Set("Real", "Unpair", bUnpairRealWiimote);
|
||||
iniFile.Set("Real", "Autopair", bPairRealWiimote);
|
||||
iniFile.Set("Real", "Timeout", bWiiReadTimeout);
|
||||
iniFile.Set("Real", "AccNeutralX", iAccNeutralX);
|
||||
iniFile.Set("Real", "AccNeutralY", iAccNeutralY);
|
||||
iniFile.Set("Real", "AccNeutralZ", iAccNeutralZ);
|
||||
iniFile.Set("Real", "AccNunNeutralX", iAccNunNeutralX);
|
||||
iniFile.Set("Real", "AccNunNeutralY", iAccNunNeutralY);
|
||||
iniFile.Set("Real", "AccNunNeutralZ", iAccNunNeutralZ);
|
||||
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
// Slot specific settings
|
||||
char SectionName[32];
|
||||
sprintf(SectionName, "Wiimote%i", i + 1);
|
||||
|
||||
iniFile.Set(SectionName, "Source", WiiMoteEmu::WiiMapping[i].Source);
|
||||
iniFile.Set(SectionName, "Sideways", WiiMoteEmu::WiiMapping[i].bSideways);
|
||||
iniFile.Set(SectionName, "Upright", WiiMoteEmu::WiiMapping[i].bUpright);
|
||||
iniFile.Set(SectionName, "ExtensionConnected", WiiMoteEmu::WiiMapping[i].iExtensionConnected);
|
||||
iniFile.Set(SectionName, "MotionPlusConnected", WiiMoteEmu::WiiMapping[i].bMotionPlusConnected);
|
||||
iniFile.Set(SectionName, "TiltInputWM", WiiMoteEmu::WiiMapping[i].Tilt.InputWM);
|
||||
iniFile.Set(SectionName, "TiltInputNC", WiiMoteEmu::WiiMapping[i].Tilt.InputNC);
|
||||
iniFile.Set(SectionName, "TiltRollDegree", WiiMoteEmu::WiiMapping[i].Tilt.RollDegree);
|
||||
iniFile.Set(SectionName, "TiltRollSwing", WiiMoteEmu::WiiMapping[i].Tilt.RollSwing);
|
||||
iniFile.Set(SectionName, "TiltRollInvert", WiiMoteEmu::WiiMapping[i].Tilt.RollInvert);
|
||||
iniFile.Set(SectionName, "TiltPitchDegree", WiiMoteEmu::WiiMapping[i].Tilt.PitchDegree);
|
||||
iniFile.Set(SectionName, "TiltPitchSwing", WiiMoteEmu::WiiMapping[i].Tilt.PitchSwing);
|
||||
iniFile.Set(SectionName, "TiltPitchInvert", WiiMoteEmu::WiiMapping[i].Tilt.PitchInvert);
|
||||
|
||||
// StickMapping
|
||||
iniFile.Set(SectionName, "NCStick", WiiMoteEmu::WiiMapping[i].Stick.NC);
|
||||
iniFile.Set(SectionName, "CCStickLeft", WiiMoteEmu::WiiMapping[i].Stick.CCL);
|
||||
iniFile.Set(SectionName, "CCStickRight", WiiMoteEmu::WiiMapping[i].Stick.CCR);
|
||||
iniFile.Set(SectionName, "CCTriggers", WiiMoteEmu::WiiMapping[i].Stick.CCT);
|
||||
iniFile.Set(SectionName, "GHStick", WiiMoteEmu::WiiMapping[i].Stick.GH);
|
||||
|
||||
// ButtonMapping
|
||||
for (int x = 0; x < WiiMoteEmu::LAST_CONSTANT; x++)
|
||||
iniFile.Set(SectionName, wmControlNames[x], WiiMoteEmu::WiiMapping[i].Button[x]);
|
||||
|
||||
// Save the physical device ID number
|
||||
iniFile.Set(SectionName, "DeviceID", WiiMoteEmu::WiiMapping[i].ID);
|
||||
|
||||
iniFile.Set(SectionName, "Axis_Lx", WiiMoteEmu::WiiMapping[i].AxisMapping.Lx);
|
||||
iniFile.Set(SectionName, "Axis_Ly", WiiMoteEmu::WiiMapping[i].AxisMapping.Ly);
|
||||
iniFile.Set(SectionName, "Axis_Rx", WiiMoteEmu::WiiMapping[i].AxisMapping.Rx);
|
||||
iniFile.Set(SectionName, "Axis_Ry", WiiMoteEmu::WiiMapping[i].AxisMapping.Ry);
|
||||
iniFile.Set(SectionName, "Trigger_L", WiiMoteEmu::WiiMapping[i].AxisMapping.Tl);
|
||||
iniFile.Set(SectionName, "Trigger_R", WiiMoteEmu::WiiMapping[i].AxisMapping.Tr);
|
||||
iniFile.Set(SectionName, "DeadZoneL", WiiMoteEmu::WiiMapping[i].DeadZoneL);
|
||||
iniFile.Set(SectionName, "DeadZoneR", WiiMoteEmu::WiiMapping[i].DeadZoneR);
|
||||
iniFile.Set(SectionName, "Diagonal", WiiMoteEmu::WiiMapping[i].Diagonal);
|
||||
iniFile.Set(SectionName, "Circle2Square", WiiMoteEmu::WiiMapping[i].bCircle2Square);
|
||||
iniFile.Set(SectionName, "Rumble", WiiMoteEmu::WiiMapping[i].Rumble);
|
||||
iniFile.Set(SectionName, "RumbleStrength", WiiMoteEmu::WiiMapping[i].RumbleStrength);
|
||||
iniFile.Set(SectionName, "TriggerType", WiiMoteEmu::WiiMapping[i].TriggerType);
|
||||
|
||||
// UDPWii
|
||||
iniFile.Set(SectionName, "UDPWii_Enable", WiiMoteEmu::WiiMapping[i].UDPWM.enable);
|
||||
iniFile.Set(SectionName, "UDPWii_Port", WiiMoteEmu::WiiMapping[i].UDPWM.port);
|
||||
iniFile.Set(SectionName, "UDPWii_EnableAccel", WiiMoteEmu::WiiMapping[i].UDPWM.enableAccel);
|
||||
iniFile.Set(SectionName, "UDPWii_EnableButtons", WiiMoteEmu::WiiMapping[i].UDPWM.enableButtons);
|
||||
iniFile.Set(SectionName, "UDPWii_EnableIR", WiiMoteEmu::WiiMapping[i].UDPWM.enableIR);
|
||||
iniFile.Set(SectionName, "UDPWii_EnableNunchuck", WiiMoteEmu::WiiMapping[i].UDPWM.enableNunchuck);
|
||||
}
|
||||
|
||||
iniFile.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Wiimote.ini").c_str());
|
||||
|
||||
// Save the IR cursor settings if it's avaliable for the GameId, if not save the default settings
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "IrPointer.ini").c_str());
|
||||
char TmpSection[32];
|
||||
sprintf(TmpSection, "%s", g_ISOId ? Hex2Ascii(g_ISOId).c_str() : "Default");
|
||||
iniFile.Set(TmpSection, "IRLeft", iIRLeft);
|
||||
iniFile.Set(TmpSection, "IRTop", iIRTop);
|
||||
iniFile.Set(TmpSection, "IRWidth", iIRWidth);
|
||||
iniFile.Set(TmpSection, "IRHeight", iIRHeight);
|
||||
iniFile.Set(TmpSection, "IRLevel", iIRLevel);
|
||||
iniFile.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "IrPointer.ini").c_str());
|
||||
|
||||
//Save any options that need to be accessed in Dolphin
|
||||
iniFile.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Dolphin.ini").c_str());
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
char SectionName[32];
|
||||
sprintf(SectionName, "Wiimote%i", i + 1);
|
||||
iniFile.Set(SectionName, "AutoReconnectRealWiimote", WiiMoteEmu::WiiMapping[i].bWiiAutoReconnect);
|
||||
}
|
||||
iniFile.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "Dolphin.ini").c_str());
|
||||
|
||||
//DEBUG_LOG(WIIMOTE, "Save()");
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _PLUGIN_WIIMOTE_CONFIG_H
|
||||
#define _PLUGIN_WIIMOTE_CONFIG_H
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#include <X11/keysym.h>
|
||||
#endif
|
||||
|
||||
struct Config
|
||||
{
|
||||
Config();
|
||||
void Load();
|
||||
void LoadIR();
|
||||
void Save();
|
||||
|
||||
// For dialog sync
|
||||
int CurrentPage;
|
||||
|
||||
// Real Wiimote
|
||||
bool bUpdateRealWiimote, bUnpairRealWiimote, bPairRealWiimote;
|
||||
volatile int bNumberRealWiimotes;
|
||||
int bNumberEmuWiimotes, bWiiReadTimeout;
|
||||
int iIRLeft, iIRTop, iIRWidth, iIRHeight, iIRLevel;
|
||||
int iAccNeutralX, iAccNeutralY, iAccNeutralZ;
|
||||
int iAccNunNeutralX, iAccNunNeutralY, iAccNunNeutralZ;
|
||||
|
||||
// Screen size settings
|
||||
bool bKeepAR43, bKeepAR169, bCrop;
|
||||
};
|
||||
|
||||
extern Config g_Config;
|
||||
#endif // _PLUGIN_WIIMOTE_CONFIG_H
|
||||
@@ -1,659 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "wiimote_real.h" // Local
|
||||
#include "wiimote_hid.h"
|
||||
#include "main.h"
|
||||
#include "ConfigBasicDlg.h"
|
||||
#include "ConfigPadDlg.h"
|
||||
#include "Config.h"
|
||||
#include "EmuMain.h" // for SetDefaultExtensionRegistry
|
||||
#include "EmuSubroutines.h" // for WmRequestStatus
|
||||
|
||||
BEGIN_EVENT_TABLE(WiimoteBasicConfigDialog,wxDialog)
|
||||
EVT_CLOSE(WiimoteBasicConfigDialog::OnClose)
|
||||
EVT_BUTTON(wxID_OK, WiimoteBasicConfigDialog::ButtonClick)
|
||||
EVT_BUTTON(wxID_CANCEL, WiimoteBasicConfigDialog::ButtonClick)
|
||||
EVT_BUTTON(ID_BUTTONMAPPING, WiimoteBasicConfigDialog::ButtonClick)
|
||||
EVT_BUTTON(ID_BUTTONRECORDING, WiimoteBasicConfigDialog::ButtonClick)
|
||||
EVT_NOTEBOOK_PAGE_CHANGED(ID_NOTEBOOK, WiimoteBasicConfigDialog::NotebookPageChanged)
|
||||
|
||||
EVT_BUTTON(IDB_PAIRUP_REAL, WiimoteBasicConfigDialog::ButtonClick)
|
||||
EVT_BUTTON(IDB_REFRESH_REAL, WiimoteBasicConfigDialog::ButtonClick)
|
||||
|
||||
EVT_CHOICE(IDC_INPUT_SOURCE, WiimoteBasicConfigDialog::GeneralSettingsChanged)
|
||||
EVT_CHECKBOX(IDC_SIDEWAYSWIIMOTE, WiimoteBasicConfigDialog::GeneralSettingsChanged)
|
||||
EVT_CHECKBOX(IDC_UPRIGHTWIIMOTE, WiimoteBasicConfigDialog::GeneralSettingsChanged)
|
||||
EVT_CHECKBOX(IDC_MOTIONPLUSCONNECTED, WiimoteBasicConfigDialog::GeneralSettingsChanged)
|
||||
EVT_CHECKBOX(IDC_WIIAUTORECONNECT, WiimoteBasicConfigDialog::GeneralSettingsChanged)
|
||||
EVT_CHECKBOX(IDC_WIIAUTOUNPAIR, WiimoteBasicConfigDialog::GeneralSettingsChanged)
|
||||
EVT_CHECKBOX(IDC_WIIAUTOPAIR, WiimoteBasicConfigDialog::GeneralSettingsChanged)
|
||||
EVT_CHOICE(IDC_EXTCONNECTED, WiimoteBasicConfigDialog::GeneralSettingsChanged)
|
||||
|
||||
//UDPWii
|
||||
EVT_CHECKBOX(IDC_UDPWIIENABLE, WiimoteBasicConfigDialog::UDPWiiSettingsChanged)
|
||||
EVT_CHECKBOX(IDC_UDPWIIACCEL, WiimoteBasicConfigDialog::UDPWiiSettingsChanged)
|
||||
EVT_CHECKBOX(IDC_UDPWIIBUTT, WiimoteBasicConfigDialog::UDPWiiSettingsChanged)
|
||||
EVT_CHECKBOX(IDC_UDPWIIIR, WiimoteBasicConfigDialog::UDPWiiSettingsChanged)
|
||||
EVT_CHECKBOX(IDC_UDPWIINUN, WiimoteBasicConfigDialog::UDPWiiSettingsChanged)
|
||||
EVT_TEXT(IDT_UDPWIIPORT, WiimoteBasicConfigDialog::UDPWiiSettingsChanged)
|
||||
|
||||
// IR cursor
|
||||
EVT_COMMAND_SCROLL(IDS_WIDTH, WiimoteBasicConfigDialog::IRCursorChanged)
|
||||
EVT_COMMAND_SCROLL(IDS_HEIGHT, WiimoteBasicConfigDialog::IRCursorChanged)
|
||||
EVT_COMMAND_SCROLL(IDS_LEFT, WiimoteBasicConfigDialog::IRCursorChanged)
|
||||
EVT_COMMAND_SCROLL(IDS_TOP, WiimoteBasicConfigDialog::IRCursorChanged)
|
||||
EVT_COMMAND_SCROLL(IDS_LEVEL, WiimoteBasicConfigDialog::IRCursorChanged)
|
||||
EVT_COMMAND_SCROLL(IDS_TIMEOUT, WiimoteBasicConfigDialog::IRCursorChanged)//scrollevent
|
||||
|
||||
EVT_TIMER(IDTM_UPDATE_ONCE, WiimoteBasicConfigDialog::UpdateOnce)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
WiimoteBasicConfigDialog::WiimoteBasicConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title,
|
||||
const wxPoint &position, const wxSize& size, long style)
|
||||
: wxDialog(parent, id, title, position, size, style)
|
||||
{
|
||||
#if wxUSE_TIMER
|
||||
m_TimeoutOnce = new wxTimer(this, IDTM_UPDATE_ONCE);
|
||||
m_ShutDownTimer = new wxTimer(this, IDTM_SHUTDOWN);
|
||||
#endif
|
||||
|
||||
ControlsCreated = false;
|
||||
m_Page = 0;
|
||||
|
||||
#if defined HAVE_WIIUSE && HAVE_WIIUSE
|
||||
// Initialize the Real WiiMotes here, so we get a count of how many were found and set everything properly
|
||||
WiiMoteReal::Initialize();
|
||||
#endif
|
||||
|
||||
CreateGUIControls();
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void WiimoteBasicConfigDialog::OnClose(wxCloseEvent& event)
|
||||
{
|
||||
EndModal(wxID_CLOSE);
|
||||
}
|
||||
|
||||
void WiimoteBasicConfigDialog::ButtonClick(wxCommandEvent& event)
|
||||
{
|
||||
switch(event.GetId())
|
||||
{
|
||||
case wxID_OK:
|
||||
#if defined HAVE_WIIUSE && HAVE_WIIUSE
|
||||
WiiMoteReal::Allocate();
|
||||
#endif
|
||||
g_Config.Save();
|
||||
Close();
|
||||
break;
|
||||
case wxID_CANCEL:
|
||||
g_Config.Load();
|
||||
Close();
|
||||
break;
|
||||
case ID_BUTTONMAPPING:
|
||||
g_Config.CurrentPage = m_Page;
|
||||
m_PadConfigFrame = new WiimotePadConfigDialog(this);
|
||||
m_PadConfigFrame->ShowModal();
|
||||
m_PadConfigFrame->Destroy();
|
||||
m_PadConfigFrame = NULL;
|
||||
m_Page = g_Config.CurrentPage;
|
||||
m_Notebook->ChangeSelection(g_Config.CurrentPage);
|
||||
UpdateGUI();
|
||||
break;
|
||||
#ifdef _WIN32
|
||||
case IDB_PAIRUP_REAL:
|
||||
if (g_EmulatorState != PLUGIN_EMUSTATE_PLAY)
|
||||
{
|
||||
WiiMoteReal::g_StartAutopairThread.Set();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case IDB_REFRESH_REAL:
|
||||
// If the config dialog was open when the user click on Play/Pause, the GUI was not updated, so this could crash everything!
|
||||
if (g_EmulatorState != PLUGIN_EMUSTATE_PLAY)
|
||||
{
|
||||
DoRefreshReal();
|
||||
}
|
||||
UpdateGUI();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WiimoteBasicConfigDialog::CreateGUIControls()
|
||||
{
|
||||
wxArrayString arrayStringFor_source;
|
||||
arrayStringFor_source.Add(wxT("Inactive"));
|
||||
arrayStringFor_source.Add(wxT("Emulated Wiimote"));
|
||||
arrayStringFor_source.Add(wxT("Real Wiimote"));
|
||||
|
||||
wxArrayString arrayStringFor_extension;
|
||||
arrayStringFor_extension.Add(wxT("None"));
|
||||
arrayStringFor_extension.Add(wxT("Nunchuck"));
|
||||
arrayStringFor_extension.Add(wxT("Classic Controller"));
|
||||
arrayStringFor_extension.Add(wxT("Guitar Hero 3 Guitar"));
|
||||
|
||||
m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
|
||||
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
m_Controller[i] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1 + i, wxDefaultPosition, wxDefaultSize);
|
||||
m_Notebook->AddPage(m_Controller[i], wxString::Format(wxT("Wiimote %d"), i+1));
|
||||
|
||||
// Basic Settings
|
||||
m_InputSource[i] = new wxChoice(m_Controller[i], IDC_INPUT_SOURCE, wxDefaultPosition, wxDefaultSize, arrayStringFor_source, 0, wxDefaultValidator);
|
||||
m_InputSource[i]->SetToolTip(wxT("This can only be changed when the emulator is paused or stopped."));
|
||||
|
||||
// Emulated Wiimote
|
||||
m_SidewaysWiimote[i] = new wxCheckBox(m_Controller[i], IDC_SIDEWAYSWIIMOTE, wxT("Sideways Wiimote"));
|
||||
m_SidewaysWiimote[i]->SetToolTip(wxT("Treat the sideways position as neutral"));
|
||||
m_UprightWiimote[i] = new wxCheckBox(m_Controller[i], IDC_UPRIGHTWIIMOTE, wxT("Upright Wiimote"));
|
||||
m_UprightWiimote[i]->SetToolTip(wxT("Treat the upright position as neutral"));
|
||||
|
||||
m_WiiMotionPlusConnected[i] = new wxCheckBox(m_Controller[i], IDC_MOTIONPLUSCONNECTED, wxT("Wii Motion Plus Connected"));
|
||||
|
||||
m_Extension[i] = new wxChoice(m_Controller[i], IDC_EXTCONNECTED, wxDefaultPosition, wxDefaultSize, arrayStringFor_extension, 0, wxDefaultValidator);
|
||||
|
||||
// UDPWii
|
||||
m_UDPWiiEnable[i] = new wxCheckBox(m_Controller[i], IDC_UDPWIIENABLE, wxT("Enable UDPWii"));
|
||||
m_UDPWiiEnable[i]->SetToolTip(wxT("Enable listening for wiimote data on the network. Requires emulation restart"));
|
||||
m_UDPWiiAccel[i] = new wxCheckBox(m_Controller[i], IDC_UDPWIIACCEL, wxT("Update acceleration from UDPWii"));
|
||||
m_UDPWiiAccel[i]->SetToolTip(wxT("Retrieve acceleration data from a device on the network"));
|
||||
m_UDPWiiButt[i] = new wxCheckBox(m_Controller[i], IDC_UDPWIIBUTT, wxT("Update buttons from UDPWii"));
|
||||
m_UDPWiiButt[i]->SetToolTip(wxT("Retrieve button data from a device on the network. This doesn't affect keyboard mappings"));
|
||||
m_UDPWiiIR[i] = new wxCheckBox(m_Controller[i], IDC_UDPWIIIR, wxT("Update IR pointer from UDPWii"));
|
||||
m_UDPWiiIR[i]->SetToolTip(wxT("Retrieve IR pointer from a device on the network. Disables using mouse as pointer"));
|
||||
m_UDPWiiNun[i] = new wxCheckBox(m_Controller[i], IDC_UDPWIINUN, wxT("Update nunchuck from UDPWii"));
|
||||
m_UDPWiiNun[i]->SetToolTip(wxT("Retrieve nunchuck data from a device on the network."));
|
||||
m_UDPWiiPort[i] = new wxTextCtrl(m_Controller[i], IDT_UDPWIIPORT);
|
||||
m_UDPWiiPort[i]->SetMaxLength(9);
|
||||
m_TextUDPWiiPort[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("UDP Port:"));
|
||||
m_TextUDPWiiPort[i]->SetToolTip(wxT("The UDP port on witch UDPWii listens for this remote."));
|
||||
|
||||
#ifdef _WIN32
|
||||
m_PairUpRealWiimote[i] = new wxButton(m_Controller[i], IDB_PAIRUP_REAL, wxT("Pair Up"));
|
||||
m_PairUpRealWiimote[i]->SetToolTip(wxT("Press the Buttons 1 and 2 on your Wiimote.\nThis might take a few seconds.\nIt only works if you are using Microsoft Bluetooth stack.")); // Only working with MS BT Stack.
|
||||
#endif
|
||||
|
||||
m_TextFoundRealWiimote[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Connected to 0 Real Wiimotes"));
|
||||
m_ConnectRealWiimote[i] = new wxButton(m_Controller[i], IDB_REFRESH_REAL, wxT("Refresh"));
|
||||
m_ConnectRealWiimote[i]->SetToolTip(wxT("This can only be done when the emulator is paused or stopped."));
|
||||
|
||||
m_TextWiimoteTimeout[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Timeout: 000 ms"));
|
||||
m_WiimoteTimeout[i] = new wxSlider(m_Controller[i], IDS_TIMEOUT, 0, 10, 200, wxDefaultPosition, wxSize(75, -1));
|
||||
m_WiimoteTimeout[i]->SetToolTip(wxT("General Real Wiimote Read Timeout, Default: 30 (ms). Higher values eliminate frequent disconnects and packet loss."));
|
||||
|
||||
#ifdef _WIN32
|
||||
//Real Wiimote / automatic settings
|
||||
m_WiiAutoReconnect[i] = new wxCheckBox(m_Controller[i], IDC_WIIAUTORECONNECT, wxT("Reconnect Wiimote on disconnect"));
|
||||
m_WiiAutoReconnect[i]->SetToolTip(wxT("This makes dolphin automatically reconnect a wiimote when it has being disconnected.\nThis will cause problems when 2 controllers are connected for a 1 player game."));
|
||||
m_WiiAutoUnpair[i] = new wxCheckBox(m_Controller[i], IDC_WIIAUTOUNPAIR, wxT("Unpair Wiimote on close"));
|
||||
m_WiiAutoUnpair[i]->SetToolTip(wxT("This makes dolphin automatically unpair a wiimote when dolphin is about to be closed."));
|
||||
m_WiiExtendedPairUp[i] = new wxCheckBox(m_Controller[i], IDC_WIIAUTOPAIR, wxT("Extended PairUp/Connect"));
|
||||
m_WiiExtendedPairUp[i]->SetToolTip(wxT("This makes dolphin automatically pair up and connect Wiimotes on pressing 1+2 on your Wiimote."));
|
||||
#endif
|
||||
|
||||
//IR Pointer
|
||||
m_TextScreenWidth[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Width: 000"));
|
||||
m_TextScreenHeight[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Height: 000"));
|
||||
m_TextScreenLeft[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Left: 000"));
|
||||
m_TextScreenTop[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Top: 000"));
|
||||
m_TextScreenIrLevel[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Sensivity: 000"));
|
||||
|
||||
m_SliderWidth[i] = new wxSlider(m_Controller[i], IDS_WIDTH, 0, 100, 923, wxDefaultPosition, wxSize(75, -1));
|
||||
m_SliderHeight[i] = new wxSlider(m_Controller[i], IDS_HEIGHT, 0, 0, 727, wxDefaultPosition, wxSize(75, -1));
|
||||
m_SliderLeft[i] = new wxSlider(m_Controller[i], IDS_LEFT, 0, 100, 500, wxDefaultPosition, wxSize(75, -1));
|
||||
m_SliderTop[i] = new wxSlider(m_Controller[i], IDS_TOP, 0, 0, 500, wxDefaultPosition, wxSize(75, -1));
|
||||
m_SliderIrLevel[i] = new wxSlider(m_Controller[i], IDS_LEVEL, 0, 1, 5, wxDefaultPosition, wxSize(75, -1));
|
||||
|
||||
// These are changed from the graphics plugin settings, so they are just here to show the loaded status
|
||||
m_TextAR[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Aspect Ratio"));
|
||||
m_CheckAR43[i] = new wxCheckBox(m_Controller[i], wxID_ANY, wxT("4:3"), wxDefaultPosition, wxSize(-1, -1), 0, wxDefaultValidator);
|
||||
m_CheckAR43[i]->Enable(false);
|
||||
m_CheckAR169[i] = new wxCheckBox(m_Controller[i], wxID_ANY, wxT("16:9"), wxDefaultPosition, wxSize(-1, -1), 0, wxDefaultValidator);
|
||||
m_CheckAR169[i]->Enable(false);
|
||||
m_Crop[i] = new wxCheckBox(m_Controller[i], wxID_ANY, wxT("Crop"), wxDefaultPosition, wxSize(-1, -1), 0, wxDefaultValidator);
|
||||
m_Crop[i]->Enable(false);
|
||||
|
||||
// Sizers
|
||||
m_SizeBasic[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Input Source"));
|
||||
m_SizeBasic[i]->Add(m_InputSource[i], 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_SizeEmu[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Emulated Position"));
|
||||
m_SizeEmu[i]->Add(m_SidewaysWiimote[i], 0, wxEXPAND | wxALL, 5);
|
||||
m_SizeEmu[i]->Add(m_UprightWiimote[i], 0, wxEXPAND | (wxLEFT | wxDOWN | wxRIGHT), 5);
|
||||
|
||||
m_SizeExtensions[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Emulated Extension"));
|
||||
m_SizeExtensions[i]->Add(m_WiiMotionPlusConnected[i], 0, wxEXPAND | wxALL, 5);
|
||||
m_SizeExtensions[i]->Add(m_Extension[i], 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_SizeUDPWii[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Emulated UDPWii"));
|
||||
m_SizeUDPWii[i]->Add(m_UDPWiiEnable[i], 0, wxEXPAND | wxALL,1);
|
||||
m_SizeUDPWiiPort[i]= new wxBoxSizer(wxHORIZONTAL);
|
||||
m_SizeUDPWiiPort[i]->Add(m_TextUDPWiiPort[i], 0, wxEXPAND | wxALL,1);
|
||||
m_SizeUDPWiiPort[i]->Add(m_UDPWiiPort[i], 0, wxEXPAND | wxALL,1);
|
||||
m_SizeUDPWii[i]->Add(m_SizeUDPWiiPort[i], 0, wxEXPAND | wxALL,1);
|
||||
m_SizeUDPWii[i]->Add(m_UDPWiiAccel[i], 0, wxEXPAND | wxALL,1);
|
||||
m_SizeUDPWii[i]->Add(m_UDPWiiButt[i], 0, wxEXPAND | wxALL,1);
|
||||
m_SizeUDPWii[i]->Add(m_UDPWiiIR[i], 0, wxEXPAND | wxALL,1);
|
||||
m_SizeUDPWii[i]->Add(m_UDPWiiNun[i], 0, wxEXPAND | wxALL,1);
|
||||
|
||||
#ifdef _WIN32
|
||||
m_SizeRealAuto[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Automatic"));
|
||||
m_SizeRealAuto[i]->Add(m_WiiAutoReconnect[i], 0, wxEXPAND | (wxDOWN | wxTOP), 5);
|
||||
m_SizeRealAuto[i]->Add(m_WiiAutoUnpair[i], 0, wxEXPAND | (wxDOWN | wxTOP), 5);
|
||||
m_SizeRealAuto[i]->Add(m_WiiExtendedPairUp[i], 0, wxEXPAND | (wxDOWN | wxTOP), 5);
|
||||
#endif
|
||||
|
||||
m_SizeRealTimeout[i] = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_SizeRealTimeout[i]->Add(m_TextWiimoteTimeout[i], 0, wxEXPAND | (wxTOP), 3);
|
||||
m_SizeRealTimeout[i]->Add(m_WiimoteTimeout[i], 0, wxEXPAND | (wxRIGHT), 0);
|
||||
|
||||
m_SizeRealRefreshPair[i] = new wxBoxSizer(wxHORIZONTAL);
|
||||
#ifdef _WIN32
|
||||
m_SizeRealRefreshPair[i]->Add(m_PairUpRealWiimote[i], 0, wxEXPAND | wxALL, 5);
|
||||
#endif
|
||||
m_SizeRealRefreshPair[i]->Add(m_ConnectRealWiimote[i], 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_SizeReal[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Real Wiimote"));
|
||||
m_SizeReal[i]->Add(m_TextFoundRealWiimote[i], 0, wxALIGN_CENTER | wxALL, 5);
|
||||
m_SizeReal[i]->Add(m_SizeRealRefreshPair[i], 0, wxALIGN_CENTER | (wxLEFT | wxDOWN | wxRIGHT), 5);
|
||||
#ifdef _WIN32
|
||||
m_SizeReal[i]->Add(m_SizeRealAuto[i], 0, wxEXPAND | wxALL, 5);
|
||||
#endif
|
||||
m_SizeReal[i]->Add(m_SizeRealTimeout[i], 0, wxEXPAND | (wxLEFT | wxDOWN | wxRIGHT), 5);
|
||||
|
||||
m_SizerIRPointerWidth[i] = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_SizerIRPointerWidth[i]->Add(m_TextScreenLeft[i], 0, wxEXPAND | (wxTOP), 3);
|
||||
m_SizerIRPointerWidth[i]->Add(m_SliderLeft[i], 0, wxEXPAND | (wxRIGHT), 0);
|
||||
m_SizerIRPointerWidth[i]->Add(m_TextScreenWidth[i], 0, wxEXPAND | (wxTOP), 3);
|
||||
m_SizerIRPointerWidth[i]->Add(m_SliderWidth[i], 0, wxEXPAND | (wxLEFT), 0);
|
||||
|
||||
m_SizerIRPointerHeight[i] = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_SizerIRPointerHeight[i]->Add(m_TextScreenTop[i], 0, wxEXPAND | (wxTOP), 3);
|
||||
m_SizerIRPointerHeight[i]->Add(m_SliderTop[i], 0, wxEXPAND | (wxRIGHT), 0);
|
||||
m_SizerIRPointerHeight[i]->Add(m_TextScreenHeight[i], 0, wxEXPAND | (wxTOP), 3);
|
||||
m_SizerIRPointerHeight[i]->Add(m_SliderHeight[i], 0, wxEXPAND | (wxLEFT), 0);
|
||||
|
||||
m_SizerIRPointerScreen[i] = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_SizerIRPointerScreen[i]->Add(m_TextAR[i], 0, wxEXPAND | (wxTOP), 0);
|
||||
m_SizerIRPointerScreen[i]->Add(m_CheckAR43[i], 0, wxEXPAND | (wxLEFT), 5);
|
||||
m_SizerIRPointerScreen[i]->Add(m_CheckAR169[i], 0, wxEXPAND | (wxLEFT), 5);
|
||||
m_SizerIRPointerScreen[i]->Add(m_Crop[i], 0, wxEXPAND | (wxLEFT), 5);
|
||||
|
||||
m_SizerIRPointerSensitivity[i] = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_SizerIRPointerSensitivity[i]->Add(m_TextScreenIrLevel[i], 0, wxEXPAND | (wxTOP), 3);
|
||||
m_SizerIRPointerSensitivity[i]->Add(m_SliderIrLevel[i], 0, wxEXPAND | (wxRIGHT), 0);
|
||||
|
||||
m_SizerIRPointer[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("IR Pointer"));
|
||||
m_SizerIRPointer[i]->Add(m_SizerIRPointerWidth[i], 0, wxEXPAND | (wxLEFT | wxDOWN | wxRIGHT), 5);
|
||||
m_SizerIRPointer[i]->Add(m_SizerIRPointerHeight[i], 0, wxEXPAND | (wxLEFT | wxDOWN | wxRIGHT), 5);
|
||||
m_SizerIRPointer[i]->Add(m_SizerIRPointerSensitivity[i], 0, wxEXPAND | (wxLEFT | wxDOWN | wxRIGHT), 5);
|
||||
m_SizerIRPointer[i]->Add(m_SizerIRPointerScreen[i], 0, wxALIGN_CENTER | (wxUP | wxDOWN), 10);
|
||||
|
||||
m_SizeBasicGeneralLeft[i] = new wxBoxSizer(wxVERTICAL);
|
||||
m_SizeBasicGeneralLeft[i]->Add(m_SizeBasic[i], 0, wxEXPAND | (wxUP), 5);
|
||||
m_SizeBasicGeneralLeft[i]->Add(m_SizeEmu[i], 0, wxEXPAND | (wxUP), 5);
|
||||
m_SizeBasicGeneralLeft[i]->Add(m_SizeExtensions[i], 0, wxEXPAND | (wxUP), 5);
|
||||
m_SizeBasicGeneralLeft[i]->Add(m_SizeUDPWii[i], 0, wxEXPAND | (wxUP), 5);
|
||||
|
||||
m_SizeBasicGeneralRight[i] = new wxBoxSizer(wxVERTICAL);
|
||||
m_SizeBasicGeneralRight[i]->Add(m_SizeReal[i], 0, wxEXPAND | (wxUP), 5);
|
||||
m_SizeBasicGeneralRight[i]->Add(m_SizerIRPointer[i], 0, wxEXPAND | (wxUP), 5);
|
||||
|
||||
m_SizeBasicGeneral[i] = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_SizeBasicGeneral[i]->Add(m_SizeBasicGeneralLeft[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
|
||||
m_SizeBasicGeneral[i]->Add(m_SizeBasicGeneralRight[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
|
||||
|
||||
// Set the main sizer
|
||||
m_Controller[i]->SetSizer(m_SizeBasicGeneral[i]);
|
||||
}
|
||||
|
||||
m_ButtonMapping = new wxButton(this, ID_BUTTONMAPPING, wxT("Button Mapping"));
|
||||
|
||||
m_OK = new wxButton(this, wxID_OK, wxT("OK"));
|
||||
m_OK->SetToolTip(wxT("Save changes and close"));
|
||||
m_Cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel"));
|
||||
m_Cancel->SetToolTip(wxT("Discard changes and close"));
|
||||
|
||||
wxBoxSizer* sButtons = new wxBoxSizer(wxHORIZONTAL);
|
||||
sButtons->Add(m_ButtonMapping, 0, (wxALL), 0);
|
||||
sButtons->AddStretchSpacer();
|
||||
sButtons->Add(m_OK, 0, (wxALL), 0);
|
||||
sButtons->Add(m_Cancel, 0, (wxLEFT), 5);
|
||||
|
||||
m_MainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
m_MainSizer->Add(m_Notebook, 1, wxEXPAND | wxALL, 5);
|
||||
m_MainSizer->Add(sButtons, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
|
||||
|
||||
SetSizer(m_MainSizer);
|
||||
Layout();
|
||||
Fit();
|
||||
// Center the window if there is room for it
|
||||
#ifdef _WIN32
|
||||
if (GetSystemMetrics(SM_CYFULLSCREEN) > 600)
|
||||
Center();
|
||||
#endif
|
||||
|
||||
ControlsCreated = true;
|
||||
}
|
||||
|
||||
// Execute a delayed function
|
||||
void WiimoteBasicConfigDialog::UpdateOnce(wxTimerEvent& event)
|
||||
{
|
||||
switch(event.GetId())
|
||||
{
|
||||
case IDTM_UPDATE_ONCE:
|
||||
// Reenable the checkbox
|
||||
SetCursor(wxCursor(wxCURSOR_ARROW));
|
||||
UpdateGUI();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_WIIUSE
|
||||
void WiimoteBasicConfigDialog::DoRefreshReal()
|
||||
{
|
||||
WiiMoteReal::Shutdown();
|
||||
WiiMoteReal::Initialize();
|
||||
}
|
||||
|
||||
|
||||
void WiimoteBasicConfigDialog::UpdateBasicConfigDialog(bool state) {
|
||||
#ifdef _WIN32
|
||||
if (m_BasicConfigFrame != NULL) {
|
||||
if (state) {
|
||||
m_PairUpRealWiimote[m_Page]->Enable(true);
|
||||
m_BasicConfigFrame->UpdateGUI();
|
||||
}
|
||||
else
|
||||
m_PairUpRealWiimote[m_Page]->Enable(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void WiimoteBasicConfigDialog::DoUseReal()
|
||||
{
|
||||
if (!g_RealWiiMotePresent)
|
||||
return;
|
||||
|
||||
// Clear any eventual events in the Wiimote queue
|
||||
WiiMoteReal::ClearEvents();
|
||||
|
||||
// Are we using an extension now? The report that it's removed, then reconnected.
|
||||
bool UsingExtension = false;
|
||||
if ((WiiMoteEmu::WiiMapping[m_Page].iExtensionConnected != WiiMoteEmu::EXT_NONE) || ( WiiMoteEmu::WiiMapping[m_Page].bMotionPlusConnected))
|
||||
UsingExtension = true;
|
||||
|
||||
DEBUG_LOG(WIIMOTE, "DoUseReal() Connect extension: %i", !UsingExtension);
|
||||
DoExtensionConnectedDisconnected(UsingExtension ? 0 : 1);
|
||||
|
||||
UsingExtension = !UsingExtension;
|
||||
DEBUG_LOG(WIIMOTE, "DoUseReal() Connect extension: %i", !UsingExtension);
|
||||
DoExtensionConnectedDisconnected(UsingExtension ? 1 : 0);
|
||||
|
||||
if (g_EmulatorState == PLUGIN_EMUSTATE_PLAY)
|
||||
{
|
||||
// Disable the checkbox for a moment
|
||||
SetCursor(wxCursor(wxCURSOR_WAIT));
|
||||
// We may not need this if there is already a message queue that allows the nessesary timeout
|
||||
//sleep(100);
|
||||
|
||||
/* Start the timer to allow the approximate time it takes for the Wiimote to come online
|
||||
it would simpler to use sleep(1000) but that doesn't work because we need the functions in main.cpp
|
||||
to work */
|
||||
m_TimeoutOnce->Start(1000, true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Generate connect/disconnect status event
|
||||
void WiimoteBasicConfigDialog::DoExtensionConnectedDisconnected(int Extension)
|
||||
{
|
||||
// There is no need for this if no game is running
|
||||
if (!g_EmulatorRunning || WiiMoteEmu::WiiMapping[m_Page].Source != 1)
|
||||
return;
|
||||
|
||||
u8 DataFrame[8] = {0}; // make a blank report for it
|
||||
wm_request_status *rs = (wm_request_status*)DataFrame;
|
||||
|
||||
// Check if a game is running, in that case change the status
|
||||
if (WiiMoteEmu::g_ReportingChannel[m_Page] > 0)
|
||||
{
|
||||
WiiMoteEmu::g_ID = m_Page;
|
||||
WiiMoteEmu::WmRequestStatus(WiiMoteEmu::g_ReportingChannel[m_Page], rs, Extension);
|
||||
}
|
||||
}
|
||||
|
||||
// Notebook page changed
|
||||
void WiimoteBasicConfigDialog::NotebookPageChanged(wxNotebookEvent& event)
|
||||
{
|
||||
// Update the global variable
|
||||
m_Page = event.GetSelection();
|
||||
|
||||
// Update GUI
|
||||
if (ControlsCreated)
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void WiimoteBasicConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
|
||||
{
|
||||
switch (event.GetId())
|
||||
{
|
||||
case IDC_INPUT_SOURCE:
|
||||
// If the config dialog was open when the user click on Play/Pause, the GUI was not updated, so this could crash everything!
|
||||
if (g_EmulatorState == PLUGIN_EMUSTATE_PLAY)
|
||||
{
|
||||
PanicAlert("This can only be changed when the emulator is paused or stopped!");
|
||||
WiiMoteEmu::WiiMapping[m_Page].Source = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_InputSource[m_Page]->GetSelection() == 2)
|
||||
{
|
||||
WiiMoteEmu::WiiMapping[m_Page].Source = 2;
|
||||
DoUseReal();
|
||||
}
|
||||
else
|
||||
WiiMoteEmu::WiiMapping[m_Page].Source = m_InputSource[m_Page]->GetSelection();
|
||||
}
|
||||
break;
|
||||
case IDC_SIDEWAYSWIIMOTE:
|
||||
WiiMoteEmu::WiiMapping[m_Page].bSideways = m_SidewaysWiimote[m_Page]->IsChecked();
|
||||
break;
|
||||
case IDC_UPRIGHTWIIMOTE:
|
||||
WiiMoteEmu::WiiMapping[m_Page].bUpright = m_UprightWiimote[m_Page]->IsChecked();
|
||||
break;
|
||||
case IDC_MOTIONPLUSCONNECTED:
|
||||
WiiMoteEmu::WiiMapping[m_Page].bMotionPlusConnected = m_WiiMotionPlusConnected[m_Page]->IsChecked();
|
||||
DoExtensionConnectedDisconnected(WiiMoteEmu::EXT_NONE);
|
||||
if (g_EmulatorRunning)
|
||||
SLEEP(25);
|
||||
WiiMoteEmu::UpdateExtRegisterBlocks(m_Page);
|
||||
DoExtensionConnectedDisconnected();
|
||||
break;
|
||||
case IDC_WIIAUTORECONNECT:
|
||||
WiiMoteEmu::WiiMapping[m_Page].bWiiAutoReconnect = m_WiiAutoReconnect[m_Page]->IsChecked();
|
||||
break;
|
||||
case IDC_WIIAUTOUNPAIR:
|
||||
g_Config.bUnpairRealWiimote = m_WiiAutoUnpair[m_Page]->IsChecked();
|
||||
break;
|
||||
#ifdef _WIN32
|
||||
case IDC_WIIAUTOPAIR:
|
||||
if (m_WiiExtendedPairUp[m_Page]->IsChecked())
|
||||
WiiMoteReal::g_StartAutopairThread.Set();
|
||||
g_Config.bPairRealWiimote = m_WiiExtendedPairUp[m_Page]->IsChecked();
|
||||
break;
|
||||
#endif
|
||||
case IDC_EXTCONNECTED:
|
||||
// Disconnect the extension so that the game recognize the change
|
||||
DoExtensionConnectedDisconnected(WiiMoteEmu::EXT_NONE);
|
||||
// It doesn't seem to be needed but shouldn't it at least take 25 ms to
|
||||
// reconnect an extension after we disconnected another?
|
||||
if (g_EmulatorRunning)
|
||||
SLEEP(25);
|
||||
// Update status
|
||||
WiiMoteEmu::WiiMapping[m_Page].iExtensionConnected = m_Extension[m_Page]->GetSelection();
|
||||
// Copy the calibration data
|
||||
WiiMoteEmu::UpdateExtRegisterBlocks(m_Page);
|
||||
// Generate connect/disconnect status event
|
||||
DoExtensionConnectedDisconnected();
|
||||
break;
|
||||
}
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void WiimoteBasicConfigDialog::IRCursorChanged(wxScrollEvent& event)
|
||||
{
|
||||
switch (event.GetId())
|
||||
{
|
||||
case IDS_WIDTH:
|
||||
g_Config.iIRWidth = m_SliderWidth[m_Page]->GetValue();
|
||||
break;
|
||||
case IDS_HEIGHT:
|
||||
g_Config.iIRHeight = m_SliderHeight[m_Page]->GetValue();
|
||||
break;
|
||||
case IDS_LEFT:
|
||||
g_Config.iIRLeft = m_SliderLeft[m_Page]->GetValue();
|
||||
break;
|
||||
case IDS_TOP:
|
||||
g_Config.iIRTop = m_SliderTop[m_Page]->GetValue();
|
||||
break;
|
||||
case IDS_LEVEL:
|
||||
g_Config.iIRLevel = m_SliderIrLevel[m_Page]->GetValue();
|
||||
if (g_RealWiiMotePresent) {
|
||||
for (int i = 0; i < WiiMoteReal::g_NumberOfWiiMotes; i++)
|
||||
wiiuse_set_ir_sensitivity(WiiMoteReal::g_WiiMotesFromWiiUse[i], g_Config.iIRLevel);
|
||||
}
|
||||
break;
|
||||
case IDS_TIMEOUT:
|
||||
g_Config.bWiiReadTimeout = m_WiimoteTimeout[m_Page]->GetValue();
|
||||
if (g_RealWiiMotePresent) {
|
||||
wiiuse_set_timeout(WiiMoteReal::g_WiiMotesFromWiiUse, WiiMoteReal::g_NumberOfWiiMotes, g_Config.bWiiReadTimeout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void WiimoteBasicConfigDialog::UDPWiiSettingsChanged(wxCommandEvent &event)
|
||||
{
|
||||
switch(event.GetId())
|
||||
{
|
||||
case IDC_UDPWIIENABLE:
|
||||
WiiMoteEmu::WiiMapping[m_Page].UDPWM.enable=m_UDPWiiEnable[m_Page]->GetValue();
|
||||
break;
|
||||
case IDC_UDPWIIACCEL:
|
||||
WiiMoteEmu::WiiMapping[m_Page].UDPWM.enableAccel=m_UDPWiiAccel[m_Page]->GetValue();
|
||||
break;
|
||||
case IDC_UDPWIIIR:
|
||||
WiiMoteEmu::WiiMapping[m_Page].UDPWM.enableIR=m_UDPWiiIR[m_Page]->GetValue();
|
||||
break;
|
||||
case IDC_UDPWIIBUTT:
|
||||
WiiMoteEmu::WiiMapping[m_Page].UDPWM.enableButtons=m_UDPWiiButt[m_Page]->GetValue();
|
||||
break;
|
||||
case IDC_UDPWIINUN:
|
||||
WiiMoteEmu::WiiMapping[m_Page].UDPWM.enableNunchuck=m_UDPWiiNun[m_Page]->GetValue();
|
||||
break;
|
||||
case IDT_UDPWIIPORT:
|
||||
strncpy(WiiMoteEmu::WiiMapping[m_Page].UDPWM.port,(const char*)(m_UDPWiiPort[m_Page]->GetValue().mb_str(wxConvUTF8)),10);
|
||||
break;
|
||||
}
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void WiimoteBasicConfigDialog::UpdateGUI()
|
||||
{
|
||||
/* I have disabled this option during a running game because it's enough to be able to switch
|
||||
between using and not using then. To also use the connect option during a running game would
|
||||
mean that the wiimote must be sent the current reporting mode and the channel ID after it
|
||||
has been initialized. Functions for that are basically already in place so these two options
|
||||
could possibly be simplified to one option. */
|
||||
#ifdef _WIN32
|
||||
m_PairUpRealWiimote[m_Page]->Enable(g_EmulatorState != PLUGIN_EMUSTATE_PLAY);
|
||||
#endif
|
||||
m_TextFoundRealWiimote[m_Page]->SetLabel(wxString::Format(wxT("Connected to %i Real Wiimotes"), WiiMoteReal::g_NumberOfWiiMotes));
|
||||
m_ConnectRealWiimote[m_Page]->Enable(g_EmulatorState != PLUGIN_EMUSTATE_PLAY);
|
||||
|
||||
m_InputSource[m_Page]->SetSelection(WiiMoteEmu::WiiMapping[m_Page].Source);
|
||||
m_InputSource[m_Page]->Enable(g_EmulatorState != PLUGIN_EMUSTATE_PLAY);
|
||||
|
||||
if (WiiMoteEmu::WiiMapping[m_Page].Source == 2)
|
||||
{
|
||||
m_Extension[m_Page]->Enable(false);
|
||||
m_WiiMotionPlusConnected[m_Page]->Enable(false);
|
||||
m_SidewaysWiimote[m_Page]->Enable(false);
|
||||
m_UprightWiimote[m_Page]->Enable(false);
|
||||
m_WiimoteTimeout[m_Page]->Enable(true);
|
||||
m_SliderIrLevel[m_Page]->Enable(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Extension[m_Page]->Enable(true);
|
||||
m_WiiMotionPlusConnected[m_Page]->Enable(true);
|
||||
m_SidewaysWiimote[m_Page]->Enable(true);
|
||||
m_UprightWiimote[m_Page]->Enable(true);
|
||||
m_WiimoteTimeout[m_Page]->Enable(false);
|
||||
m_SliderIrLevel[m_Page]->Enable(false);
|
||||
}
|
||||
|
||||
//General settings
|
||||
m_Extension[m_Page]->SetSelection(WiiMoteEmu::WiiMapping[m_Page].iExtensionConnected);
|
||||
m_SidewaysWiimote[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].bSideways);
|
||||
m_UprightWiimote[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].bUpright);
|
||||
m_WiiMotionPlusConnected[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].bMotionPlusConnected);
|
||||
|
||||
//Real Wiimote related settings
|
||||
#ifdef _WIN32
|
||||
//Automatic settings
|
||||
m_WiiAutoReconnect[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].bWiiAutoReconnect);
|
||||
m_WiiAutoUnpair[m_Page]->SetValue(g_Config.bUnpairRealWiimote);
|
||||
m_WiiExtendedPairUp[m_Page]->SetValue(g_Config.bPairRealWiimote);
|
||||
#endif
|
||||
m_TextWiimoteTimeout[m_Page]->SetLabel(wxString::Format(wxT("Timeout: %i ms"), g_Config.bWiiReadTimeout));
|
||||
m_WiimoteTimeout[m_Page]->SetValue(g_Config.bWiiReadTimeout);
|
||||
|
||||
// Update the Wiimote IR pointer calibration
|
||||
m_TextScreenWidth[m_Page]->SetLabel(wxString::Format(wxT("Width: %i"), g_Config.iIRWidth));
|
||||
m_TextScreenHeight[m_Page]->SetLabel(wxString::Format(wxT("Height: %i"), g_Config.iIRHeight));
|
||||
m_TextScreenLeft[m_Page]->SetLabel(wxString::Format(wxT("Left: %i"), g_Config.iIRLeft));
|
||||
m_TextScreenTop[m_Page]->SetLabel(wxString::Format(wxT("Top: %i"), g_Config.iIRTop));
|
||||
m_TextScreenIrLevel[m_Page]->SetLabel(wxString::Format(wxT("Sensitivity: %i"), g_Config.iIRLevel));
|
||||
|
||||
// Update the slider position if a configuration has been loaded
|
||||
m_SliderWidth[m_Page]->SetValue(g_Config.iIRWidth);
|
||||
m_SliderHeight[m_Page]->SetValue(g_Config.iIRHeight);
|
||||
m_SliderLeft[m_Page]->SetValue(g_Config.iIRLeft);
|
||||
m_SliderTop[m_Page]->SetValue(g_Config.iIRTop);
|
||||
m_SliderIrLevel[m_Page]->SetValue(g_Config.iIRLevel);
|
||||
|
||||
m_CheckAR43[m_Page]->SetValue(g_Config.bKeepAR43);
|
||||
m_CheckAR169[m_Page]->SetValue(g_Config.bKeepAR169);
|
||||
m_Crop[m_Page]->SetValue(g_Config.bCrop);
|
||||
|
||||
//Update UDPWii
|
||||
m_UDPWiiEnable[m_Page]->Enable(g_EmulatorState != PLUGIN_EMUSTATE_PLAY);
|
||||
m_UDPWiiPort[m_Page]->Enable(g_EmulatorState != PLUGIN_EMUSTATE_PLAY);
|
||||
m_UDPWiiEnable[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].UDPWM.enable);
|
||||
m_UDPWiiAccel[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].UDPWM.enableAccel);
|
||||
m_UDPWiiButt[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].UDPWM.enableButtons);
|
||||
m_UDPWiiIR[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].UDPWM.enableIR);
|
||||
m_UDPWiiNun[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].UDPWM.enableNunchuck);
|
||||
m_UDPWiiPort[m_Page]->ChangeValue(wxString::FromAscii(WiiMoteEmu::WiiMapping[m_Page].UDPWM.port));
|
||||
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef __BASICCONFIGDIALOG_h__
|
||||
#define __BASICCONFIGDIALOG_h__
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/combobox.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include "wiimote_hid.h"
|
||||
|
||||
class WiimoteBasicConfigDialog : public wxDialog
|
||||
{
|
||||
public:
|
||||
WiimoteBasicConfigDialog(wxWindow *parent,
|
||||
wxWindowID id = wxID_ANY,
|
||||
const wxString &title = wxT("Wii Remote Plugin Configuration"),
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxDEFAULT_DIALOG_STYLE | wxWANTS_CHARS);
|
||||
virtual ~WiimoteBasicConfigDialog(){;}
|
||||
|
||||
// General open, close and event functions
|
||||
void UpdateGUI();
|
||||
void UpdateBasicConfigDialog(bool state);
|
||||
void ButtonClick(wxCommandEvent& event);
|
||||
void ShutDown(wxTimerEvent& WXUNUSED(event));
|
||||
void UpdateOnce(wxTimerEvent& event);
|
||||
|
||||
// Timers
|
||||
wxTimer *m_TimeoutOnce,
|
||||
*m_ShutDownTimer;
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE();
|
||||
|
||||
bool ControlsCreated;
|
||||
int m_Page;
|
||||
|
||||
wxNotebook *m_Notebook;
|
||||
wxPanel *m_Controller[MAX_WIIMOTES];
|
||||
|
||||
wxButton *m_OK,
|
||||
*m_Cancel,
|
||||
*m_ButtonMapping,
|
||||
*m_Recording,
|
||||
*m_PairUpRealWiimote[MAX_WIIMOTES],
|
||||
*m_ConnectRealWiimote[MAX_WIIMOTES];
|
||||
|
||||
wxChoice *m_InputSource[MAX_WIIMOTES],
|
||||
*m_Extension[MAX_WIIMOTES];
|
||||
|
||||
wxSlider *m_SliderWidth[MAX_WIIMOTES],
|
||||
*m_SliderHeight[MAX_WIIMOTES],
|
||||
*m_SliderLeft[MAX_WIIMOTES],
|
||||
*m_SliderTop[MAX_WIIMOTES],
|
||||
*m_WiimoteTimeout[MAX_WIIMOTES],
|
||||
*m_SliderIrLevel[MAX_WIIMOTES];
|
||||
|
||||
wxCheckBox *m_SidewaysWiimote[MAX_WIIMOTES],
|
||||
*m_UprightWiimote[MAX_WIIMOTES],
|
||||
*m_WiiMotionPlusConnected[MAX_WIIMOTES],
|
||||
*m_CheckAR43[MAX_WIIMOTES],
|
||||
*m_CheckAR169[MAX_WIIMOTES],
|
||||
*m_Crop[MAX_WIIMOTES],
|
||||
*m_WiiAutoReconnect[MAX_WIIMOTES],
|
||||
*m_WiiAutoUnpair[MAX_WIIMOTES],
|
||||
*m_WiiExtendedPairUp[MAX_WIIMOTES],
|
||||
*m_UDPWiiEnable[MAX_WIIMOTES],
|
||||
*m_UDPWiiAccel[MAX_WIIMOTES],
|
||||
*m_UDPWiiButt[MAX_WIIMOTES],
|
||||
*m_UDPWiiIR[MAX_WIIMOTES],
|
||||
*m_UDPWiiNun[MAX_WIIMOTES];
|
||||
|
||||
wxStaticText *m_TextWiimoteTimeout[MAX_WIIMOTES],
|
||||
*m_TextScreenWidth[MAX_WIIMOTES],
|
||||
*m_TextScreenHeight[MAX_WIIMOTES],
|
||||
*m_TextScreenLeft[MAX_WIIMOTES],
|
||||
*m_TextScreenTop[MAX_WIIMOTES],
|
||||
*m_TextScreenIrLevel[MAX_WIIMOTES],
|
||||
*m_TextAR[MAX_WIIMOTES],
|
||||
*m_TextFoundRealWiimote[MAX_WIIMOTES],
|
||||
*m_TextUDPWiiPort[MAX_WIIMOTES];
|
||||
|
||||
wxBoxSizer *m_MainSizer,
|
||||
*m_SizeBasicGeneral[MAX_WIIMOTES],
|
||||
*m_SizeBasicGeneralLeft[MAX_WIIMOTES],
|
||||
*m_SizeBasicGeneralRight[MAX_WIIMOTES],
|
||||
*m_SizeRealTimeout[MAX_WIIMOTES],
|
||||
*m_SizeRealRefreshPair[MAX_WIIMOTES],
|
||||
*m_SizerIRPointerWidth[MAX_WIIMOTES],
|
||||
*m_SizerIRPointerHeight[MAX_WIIMOTES],
|
||||
*m_SizerIRPointerScreen[MAX_WIIMOTES],
|
||||
*m_SizerIRPointerSensitivity[MAX_WIIMOTES],
|
||||
*m_SizeUDPWiiPort[MAX_WIIMOTES];
|
||||
|
||||
wxStaticBoxSizer *m_SizeBasic[MAX_WIIMOTES],
|
||||
*m_SizeEmu[MAX_WIIMOTES],
|
||||
*m_SizeReal[MAX_WIIMOTES],
|
||||
*m_SizeRealAuto[MAX_WIIMOTES],
|
||||
*m_SizeExtensions[MAX_WIIMOTES],
|
||||
*m_SizerIRPointer[MAX_WIIMOTES],
|
||||
*m_SizeUDPWii[MAX_WIIMOTES];
|
||||
|
||||
wxTextCtrl *m_UDPWiiPort[MAX_WIIMOTES];
|
||||
|
||||
enum
|
||||
{
|
||||
ID_BUTTONMAPPING,
|
||||
ID_BUTTONRECORDING,
|
||||
IDTM_SHUTDOWN,
|
||||
IDTM_UPDATE,
|
||||
IDTM_UPDATE_ONCE,
|
||||
|
||||
ID_NOTEBOOK,
|
||||
ID_CONTROLLERPAGE1,
|
||||
ID_CONTROLLERPAGE2,
|
||||
ID_CONTROLLERPAGE3,
|
||||
ID_CONTROLLERPAGE4,
|
||||
|
||||
// Emulated/Real Wiimote
|
||||
IDC_INPUT_SOURCE,
|
||||
IDC_SIDEWAYSWIIMOTE,
|
||||
IDC_UPRIGHTWIIMOTE,
|
||||
IDC_MOTIONPLUSCONNECTED,
|
||||
IDC_WIIAUTORECONNECT,
|
||||
IDC_WIIAUTOUNPAIR,
|
||||
IDC_WIIAUTOPAIR,
|
||||
IDC_EXTCONNECTED,
|
||||
|
||||
//UDPWii
|
||||
IDC_UDPWIIENABLE,
|
||||
IDC_UDPWIIACCEL,
|
||||
IDC_UDPWIIBUTT,
|
||||
IDC_UDPWIIIR,
|
||||
IDC_UDPWIINUN,
|
||||
IDT_UDPWIIPORT,
|
||||
|
||||
// Real
|
||||
IDB_PAIRUP_REAL,
|
||||
IDB_REFRESH_REAL,
|
||||
|
||||
IDS_WIDTH,
|
||||
IDS_HEIGHT,
|
||||
IDS_LEFT,
|
||||
IDS_TOP,
|
||||
IDS_LEVEL,
|
||||
IDS_TIMEOUT,
|
||||
};
|
||||
|
||||
void CreateGUIControls();
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void NotebookPageChanged(wxNotebookEvent& event);
|
||||
void GeneralSettingsChanged(wxCommandEvent& event);
|
||||
void IRCursorChanged(wxScrollEvent& event);
|
||||
void UDPWiiSettingsChanged(wxCommandEvent& event);
|
||||
|
||||
void DoRefreshReal(); // Real
|
||||
void DoUseReal();
|
||||
|
||||
void DoExtensionConnectedDisconnected(int Extension = -1); // Emulated
|
||||
};
|
||||
|
||||
extern WiimoteBasicConfigDialog *m_BasicConfigFrame;
|
||||
#endif
|
||||
@@ -1,347 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "wiimote_hid.h"
|
||||
#include "main.h"
|
||||
#include "ConfigPadDlg.h"
|
||||
#include "Config.h"
|
||||
#include "EmuMain.h" // for WiiMoteEmu class
|
||||
#include "EmuDefinitions.h"
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#include "X11InputBase.h"
|
||||
#endif
|
||||
|
||||
// Replace the harder to understand -1 with "" for the sake of user friendliness
|
||||
void WiimotePadConfigDialog::ToBlank(bool toBlank, int Id)
|
||||
{
|
||||
if (!m_ControlsCreated)
|
||||
return;
|
||||
|
||||
if(toBlank)
|
||||
{
|
||||
if (GetButtonText(Id) == wxString(wxT("-1")))
|
||||
SetButtonText(Id, wxString());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetButtonText(Id).IsEmpty())
|
||||
SetButtonText(Id, wxString(wxT("-1")));
|
||||
}
|
||||
}
|
||||
|
||||
void WiimotePadConfigDialog::DoChangeDeadZone()
|
||||
{
|
||||
float Rad;
|
||||
|
||||
Rad = (float)WiiMoteEmu::WiiMapping[m_Page].DeadZoneL * ((float)BoxW / 100.0) * 0.5;
|
||||
m_bmpDeadZoneLeftIn[m_Page]->SetBitmap(CreateBitmapClear());
|
||||
m_bmpDeadZoneLeftIn[m_Page]->SetSize(0, 0);
|
||||
m_bmpDeadZoneLeftIn[m_Page]->SetBitmap(CreateBitmapDeadZone((int)Rad));
|
||||
m_bmpDeadZoneLeftIn[m_Page]->SetPosition(wxPoint(BoxW / 2 - (int)Rad, BoxH / 2 - (int)Rad));
|
||||
m_bmpDeadZoneLeftIn[m_Page]->Refresh();
|
||||
|
||||
Rad = (float)WiiMoteEmu::WiiMapping[m_Page].DeadZoneR * ((float)BoxW / 100.0) * 0.5;
|
||||
m_bmpDeadZoneRightIn[m_Page]->SetBitmap(CreateBitmapClear());
|
||||
m_bmpDeadZoneRightIn[m_Page]->SetSize(0, 0);
|
||||
m_bmpDeadZoneRightIn[m_Page]->SetBitmap(CreateBitmapDeadZone((int)Rad));
|
||||
m_bmpDeadZoneRightIn[m_Page]->SetPosition(wxPoint(BoxW / 2 - (int)Rad, BoxH / 2 - (int)Rad));
|
||||
m_bmpDeadZoneRightIn[m_Page]->Refresh();
|
||||
}
|
||||
|
||||
// Set dialog items from saved values
|
||||
|
||||
|
||||
// Update the textbox for the buttons
|
||||
void WiimotePadConfigDialog::SetButtonText(int id, const wxString &str)
|
||||
{
|
||||
if (IDB_ANALOG_LEFT_X <= id && id <= IDB_TRIGGER_R)
|
||||
m_Button_Analog[id - IDB_ANALOG_LEFT_X][m_Page]->SetLabel(str);
|
||||
else if (IDB_WM_A <= id && id <= IDB_WM_SHAKE)
|
||||
m_Button_Wiimote[id - IDB_WM_A][m_Page]->SetLabel(str);
|
||||
else if (IDB_NC_Z <= id && id <= IDB_NC_SHAKE)
|
||||
m_Button_NunChuck[id - IDB_NC_Z][m_Page]->SetLabel(str);
|
||||
else if (IDB_CC_A <= id && id <= IDB_CC_RD)
|
||||
m_Button_Classic[id - IDB_CC_A][m_Page]->SetLabel(str);
|
||||
else if (IDB_GH3_GREEN <= id && id <= IDB_GH3_STRUM_DOWN)
|
||||
m_Button_GH3[id - IDB_GH3_GREEN][m_Page]->SetLabel(str);
|
||||
}
|
||||
|
||||
// Get the text in the textbox for the buttons
|
||||
wxString WiimotePadConfigDialog::GetButtonText(int id)
|
||||
{
|
||||
if (IDB_ANALOG_LEFT_X <= id && id <= IDB_TRIGGER_R)
|
||||
return m_Button_Analog[id - IDB_ANALOG_LEFT_X][m_Page]->GetLabel();
|
||||
else if (IDB_WM_A <= id && id <= IDB_WM_SHAKE)
|
||||
return m_Button_Wiimote[id - IDB_WM_A][m_Page]->GetLabel();
|
||||
else if (IDB_NC_Z <= id && id <= IDB_NC_SHAKE)
|
||||
return m_Button_NunChuck[id - IDB_NC_Z][m_Page]->GetLabel();
|
||||
else if (IDB_CC_A <= id && id <= IDB_CC_RD)
|
||||
return m_Button_Classic[id - IDB_CC_A][m_Page]->GetLabel();
|
||||
else if (IDB_GH3_GREEN <= id && id <= IDB_GH3_STRUM_DOWN)
|
||||
return m_Button_GH3[id - IDB_GH3_GREEN][m_Page]->GetLabel();
|
||||
|
||||
return wxString();
|
||||
}
|
||||
|
||||
void WiimotePadConfigDialog::DoGetButtons(int _GetId)
|
||||
{
|
||||
// Collect the starting values
|
||||
// Get the current controller
|
||||
int PadID = WiiMoteEmu::WiiMapping[m_Page].ID;
|
||||
|
||||
// Get the controller and trigger type
|
||||
int TriggerType = WiiMoteEmu::WiiMapping[m_Page].TriggerType;
|
||||
|
||||
// Collect the accepted buttons for this slot
|
||||
bool LeftRight = (_GetId == IDB_TRIGGER_L || _GetId == IDB_TRIGGER_R);
|
||||
|
||||
bool Axis = (_GetId >= IDB_ANALOG_LEFT_X && _GetId <= IDB_TRIGGER_R)
|
||||
// Don't allow SDL axis input for the shoulder buttons if XInput is selected
|
||||
&& !(TriggerType == InputCommon::CTL_TRIGGER_XINPUT && (_GetId == IDB_TRIGGER_L || _GetId == IDB_TRIGGER_R) );
|
||||
|
||||
bool XInput = (TriggerType == InputCommon::CTL_TRIGGER_XINPUT);
|
||||
|
||||
bool Button = (_GetId >= IDB_WM_A && _GetId <= IDB_GH3_STRUM_DOWN);
|
||||
|
||||
bool Hat = (_GetId >= IDB_WM_A && _GetId <= IDB_GH3_STRUM_DOWN);
|
||||
|
||||
bool NoTriggerFilter = false;
|
||||
|
||||
// Values used in this function
|
||||
int Seconds = 4; // Seconds to wait for
|
||||
int TimesPerSecond = 40; // How often to run the check
|
||||
|
||||
// Values returned from InputCommon::GetButton()
|
||||
int value; // Axis value or Hat value
|
||||
int type; // Button type
|
||||
|
||||
int KeyPressed = 0;
|
||||
int pressed = 0;
|
||||
bool Succeed = false;
|
||||
bool Stop = false; // Stop the timer
|
||||
|
||||
//DEBUG_LOG(WIIMOTE, "Before (%i) Id:%i %i IsRunning:%i",
|
||||
// GetButtonWaitingTimer, GetButtonWaitingID, _GetId, m_ButtonMappingTimer->IsRunning());
|
||||
|
||||
// If the Id has changed or the timer is not running we should start one
|
||||
if( GetButtonWaitingID != _GetId || !m_ButtonMappingTimer->IsRunning() )
|
||||
{
|
||||
if(m_ButtonMappingTimer->IsRunning())
|
||||
m_ButtonMappingTimer->Stop();
|
||||
|
||||
// Save the button Id
|
||||
GetButtonWaitingID = _GetId;
|
||||
GetButtonWaitingTimer = 0;
|
||||
|
||||
// Start the timer
|
||||
#if wxUSE_TIMER
|
||||
m_ButtonMappingTimer->Start(1000 / TimesPerSecond);
|
||||
#endif
|
||||
DEBUG_LOG(WIIMOTE, "Timer Started: Pad:%i _GetId:%i "
|
||||
"Allowed input is Axis:%i LeftRight:%i XInput:%i Button:%i Hat:%i",
|
||||
WiiMoteEmu::WiiMapping[m_Page].ID, _GetId,
|
||||
Axis, LeftRight, XInput, Button, Hat);
|
||||
}
|
||||
|
||||
// Check for buttons
|
||||
// If there is a timer we should not create a new one
|
||||
else if (WiiMoteEmu::NumGoodPads > 0)
|
||||
{
|
||||
InputCommon::GetButton(
|
||||
WiiMoteEmu::WiiMapping[m_Page].joy, PadID, WiiMoteEmu::joyinfo[PadID].NumButtons, WiiMoteEmu::joyinfo[PadID].NumAxes, WiiMoteEmu::joyinfo[PadID].NumHats,
|
||||
KeyPressed, value, type, pressed, Succeed, Stop,
|
||||
LeftRight, Axis, XInput, Button, Hat, NoTriggerFilter);
|
||||
}
|
||||
|
||||
// Process results
|
||||
// Count each time
|
||||
GetButtonWaitingTimer++;
|
||||
|
||||
// This is run every second
|
||||
if (GetButtonWaitingTimer % TimesPerSecond == 0)
|
||||
{
|
||||
// Current time
|
||||
int TmpTime = Seconds - (GetButtonWaitingTimer / TimesPerSecond);
|
||||
// Update text
|
||||
SetButtonText(_GetId, wxString::Format(wxT("[ %d ]"), TmpTime));
|
||||
}
|
||||
|
||||
// Time's up
|
||||
if (GetButtonWaitingTimer / TimesPerSecond >= Seconds)
|
||||
{
|
||||
Stop = true;
|
||||
// Revert back to old label
|
||||
SetButtonText(_GetId, OldLabel);
|
||||
}
|
||||
|
||||
// If we got a button
|
||||
if(Succeed)
|
||||
{
|
||||
Stop = true;
|
||||
// We need to assign hat special code
|
||||
if (type == InputCommon::CTL_HAT)
|
||||
{
|
||||
// Index of pressed starts from 0
|
||||
if (value & SDL_HAT_UP) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_UP;
|
||||
else if (value & SDL_HAT_DOWN) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_DOWN;
|
||||
else if (value & SDL_HAT_LEFT) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_LEFT;
|
||||
else if (value & SDL_HAT_RIGHT) pressed = 0x0100 + 0x0010 * pressed + SDL_HAT_RIGHT;
|
||||
else pressed = -1;
|
||||
}
|
||||
if (IDB_WM_A <= _GetId && _GetId <= IDB_GH3_STRUM_DOWN)
|
||||
{
|
||||
// Better make the pad button code far from virtual key code
|
||||
SaveButtonMapping(_GetId, 0x1000 + pressed);
|
||||
SetButtonText(_GetId, wxString::Format(wxT("PAD: %d"), pressed));
|
||||
}
|
||||
else if (IDB_ANALOG_LEFT_X <= _GetId && _GetId <= IDB_TRIGGER_R)
|
||||
{
|
||||
SaveButtonMapping(_GetId, pressed);
|
||||
SetButtonText(_GetId, wxString::Format(wxT("%d"), pressed));
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the timer
|
||||
if(Stop)
|
||||
{
|
||||
DEBUG_LOG(WIIMOTE, "Timer Stopped for Pad:%i _GetId:%i",
|
||||
WiiMoteEmu::WiiMapping[m_Page].ID, _GetId);
|
||||
|
||||
EndGetButtons();
|
||||
}
|
||||
|
||||
// If we got a bad button
|
||||
if(KeyPressed == -1)
|
||||
{
|
||||
// Update text
|
||||
SetButtonText(_GetId, wxString(wxT("PAD: -1")));
|
||||
// Notify the user
|
||||
wxMessageBox(wxString::Format(
|
||||
wxT("You selected a key with a to low key code (%i), please")
|
||||
wxT(" select another key with a higher key code."), pressed)
|
||||
, wxT("Notice"), wxICON_INFORMATION);
|
||||
}
|
||||
}
|
||||
|
||||
void WiimotePadConfigDialog::EndGetButtons(void)
|
||||
{
|
||||
wxTheApp->Disconnect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
|
||||
wxKeyEventHandler(WiimotePadConfigDialog::OnKeyDown),
|
||||
(wxObject*)0, this);
|
||||
m_ButtonMappingTimer->Stop();
|
||||
GetButtonWaitingTimer = 0;
|
||||
GetButtonWaitingID = 0;
|
||||
ClickedButton = NULL;
|
||||
}
|
||||
|
||||
// Convert the 0x8000 range values to BoxW and BoxH for the plot
|
||||
void WiimotePadConfigDialog::Convert2Box(int &x)
|
||||
{
|
||||
// Border adjustment
|
||||
int BoxW_ = BoxW - 2;
|
||||
// Convert values
|
||||
x = (BoxW_ / 2) + (x * BoxW_ / (32767 * 2));
|
||||
}
|
||||
|
||||
// Update the input status boxes
|
||||
void WiimotePadConfigDialog::UpdatePadInfo(wxTimerEvent& WXUNUSED(event))
|
||||
{
|
||||
//DEBUG_LOG(WIIMOTE, "SDL_WasInit: %i", SDL_WasInit(0));
|
||||
|
||||
/* Return if it's not enabled or not detected. The ID should never be less than zero here,
|
||||
it can only be that because of a manual ini file change, but we make that check anway. */
|
||||
if (WiiMoteEmu::WiiMapping[m_Page].ID < 0 || WiiMoteEmu::WiiMapping[m_Page].ID >= WiiMoteEmu::NumGoodPads)
|
||||
{
|
||||
m_tStatusLeftIn[m_Page]->SetLabel(wxT("Not connected"));
|
||||
m_tStatusLeftOut[m_Page]->SetLabel(wxT("Not connected"));
|
||||
m_tStatusRightIn[m_Page]->SetLabel(wxT("Not connected"));
|
||||
m_tStatusRightOut[m_Page]->SetLabel(wxT("Not connected"));
|
||||
m_TriggerStatusL[m_Page]->SetLabel(wxT("000"));
|
||||
m_TriggerStatusR[m_Page]->SetLabel(wxT("000"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that Dolphin is in focus, otherwise don't update the pad status
|
||||
//if (IsFocus())
|
||||
WiiMoteEmu::GetAxisState(WiiMoteEmu::WiiMapping[m_Page]);
|
||||
|
||||
// Analog stick
|
||||
// Get original values
|
||||
int main_x = WiiMoteEmu::WiiMapping[m_Page].AxisState.Lx;
|
||||
int main_y = WiiMoteEmu::WiiMapping[m_Page].AxisState.Ly;
|
||||
int right_x = WiiMoteEmu::WiiMapping[m_Page].AxisState.Rx;
|
||||
int right_y = WiiMoteEmu::WiiMapping[m_Page].AxisState.Ry;
|
||||
|
||||
// Get adjusted values
|
||||
int main_x_after = main_x, main_y_after = main_y;
|
||||
int right_x_after = right_x, right_y_after = right_y;
|
||||
|
||||
// Produce square
|
||||
if(WiiMoteEmu::WiiMapping[m_Page].bCircle2Square)
|
||||
InputCommon::Square2Circle(main_x_after, main_y_after, WiiMoteEmu::WiiMapping[m_Page].Diagonal, true);
|
||||
|
||||
// Check dead zone
|
||||
float DeadZoneLeft = (float)WiiMoteEmu::WiiMapping[m_Page].DeadZoneL / 100.0;
|
||||
float DeadZoneRight = (float)WiiMoteEmu::WiiMapping[m_Page].DeadZoneR / 100.0;
|
||||
if (InputCommon::IsDeadZone(DeadZoneLeft, main_x_after, main_y_after))
|
||||
{
|
||||
main_x_after = 0;
|
||||
main_y_after = 0;
|
||||
}
|
||||
if (InputCommon::IsDeadZone(DeadZoneRight, right_x_after, right_y_after))
|
||||
{
|
||||
right_x_after = 0;
|
||||
right_y_after = 0;
|
||||
}
|
||||
|
||||
int Lx = InputCommon::Pad_Convert(main_x); int Ly = InputCommon::Pad_Convert(main_y);
|
||||
int Rx = InputCommon::Pad_Convert(right_x); int Ry = InputCommon::Pad_Convert(right_y);
|
||||
int Lx_after = InputCommon::Pad_Convert(main_x_after); int Ly_after = InputCommon::Pad_Convert(main_y_after);
|
||||
int Rx_after = InputCommon::Pad_Convert(right_x_after); int Ry_after = InputCommon::Pad_Convert(right_y_after);
|
||||
|
||||
m_tStatusLeftIn[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Lx, Ly));
|
||||
m_tStatusLeftOut[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Lx_after, Ly_after));
|
||||
m_tStatusRightIn[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Rx, Ry));
|
||||
m_tStatusRightOut[m_Page]->SetLabel(wxString::Format(wxT("X:%03i Y:%03i"), Rx_after, Ry_after));
|
||||
|
||||
// Adjust the values for the plot
|
||||
Convert2Box(main_x); Convert2Box(main_y);
|
||||
Convert2Box(right_x); Convert2Box(right_y);
|
||||
Convert2Box(main_x_after); Convert2Box(main_y_after);
|
||||
Convert2Box(right_x_after); Convert2Box(right_y_after);
|
||||
|
||||
// Adjust the dot
|
||||
m_bmpDotLeftIn[m_Page]->SetPosition(wxPoint(main_x, main_y));
|
||||
m_bmpDotLeftOut[m_Page]->SetPosition(wxPoint(main_x_after, main_y_after));
|
||||
m_bmpDotRightIn[m_Page]->SetPosition(wxPoint(right_x, right_y));
|
||||
m_bmpDotRightOut[m_Page]->SetPosition(wxPoint(right_x_after, right_y_after));
|
||||
|
||||
// Get the trigger values
|
||||
int TriggerLeft = WiiMoteEmu::WiiMapping[m_Page].AxisState.Tl;
|
||||
int TriggerRight = WiiMoteEmu::WiiMapping[m_Page].AxisState.Tr;
|
||||
|
||||
// Convert the triggers values
|
||||
if (WiiMoteEmu::WiiMapping[m_Page].TriggerType == InputCommon::CTL_TRIGGER_SDL)
|
||||
{
|
||||
TriggerLeft = InputCommon::Pad_Convert(TriggerLeft);
|
||||
TriggerRight = InputCommon::Pad_Convert(TriggerRight);
|
||||
}
|
||||
|
||||
m_TriggerStatusL[m_Page]->SetLabel(wxString::Format(wxT("%03i"), TriggerLeft));
|
||||
m_TriggerStatusR[m_Page]->SetLabel(wxString::Format(wxT("%03i"), TriggerRight));
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,227 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef __PADCONFIGDIALOG_h__
|
||||
#define __PADCONFIGDIALOG_h__
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/combobox.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include "Config.h"
|
||||
#include "wiimote_hid.h"
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include "X11InputBase.h"
|
||||
#endif
|
||||
|
||||
class WiimotePadConfigDialog : public wxDialog
|
||||
{
|
||||
public:
|
||||
WiimotePadConfigDialog(wxWindow *parent,
|
||||
wxWindowID id = wxID_ANY,
|
||||
const wxString &title = wxT("Wii Remote Plugin Configuration"),
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxDEFAULT_DIALOG_STYLE | wxWANTS_CHARS);
|
||||
virtual ~WiimotePadConfigDialog();
|
||||
|
||||
void Convert2Box(int &x);
|
||||
|
||||
wxTimer *m_UpdatePadTimer,
|
||||
*m_ButtonMappingTimer;
|
||||
|
||||
wxStaticBitmap *m_bmpDotLeftIn[MAX_WIIMOTES],
|
||||
*m_bmpDotLeftOut[MAX_WIIMOTES],
|
||||
*m_bmpDotRightIn[MAX_WIIMOTES],
|
||||
*m_bmpDotRightOut[MAX_WIIMOTES],
|
||||
*m_bmpDeadZoneLeftIn[MAX_WIIMOTES],
|
||||
*m_bmpDeadZoneRightIn[MAX_WIIMOTES];
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE();
|
||||
|
||||
enum
|
||||
{
|
||||
// <It's important that the internal ordering of these are unchanged>
|
||||
// Wiimote
|
||||
IDB_WM_A, IDB_WM_B,
|
||||
IDB_WM_1, IDB_WM_2,
|
||||
IDB_WM_P, IDB_WM_M, IDB_WM_H,
|
||||
IDB_WM_L, IDB_WM_R, IDB_WM_U, IDB_WM_D,
|
||||
IDB_WM_ROLL_L, IDB_WM_ROLL_R,
|
||||
IDB_WM_PITCH_U, IDB_WM_PITCH_D,
|
||||
IDB_WM_SHAKE,
|
||||
|
||||
// Nunchuck
|
||||
IDB_NC_Z,
|
||||
IDB_NC_C,
|
||||
IDB_NC_L,
|
||||
IDB_NC_R,
|
||||
IDB_NC_U,
|
||||
IDB_NC_D,
|
||||
IDB_NC_ROLL_L, IDB_NC_ROLL_R,
|
||||
IDB_NC_PITCH_U, IDB_NC_PITCH_D,
|
||||
IDB_NC_SHAKE,
|
||||
|
||||
// Classic Controller
|
||||
IDB_CC_A, IDB_CC_B,
|
||||
IDB_CC_X, IDB_CC_Y,
|
||||
IDB_CC_P, IDB_CC_M, IDB_CC_H,
|
||||
IDB_CC_TL, IDB_CC_TR, IDB_CC_ZL, IDB_CC_ZR, // Shoulder triggers and Zs
|
||||
IDB_CC_DL, IDB_CC_DR, IDB_CC_DU, IDB_CC_DD, // Digital pad
|
||||
IDB_CC_LL, IDB_CC_LR, IDB_CC_LU, IDB_CC_LD, // Left analog stick
|
||||
IDB_CC_RL, IDB_CC_RR, IDB_CC_RU, IDB_CC_RD, // Right analog stick
|
||||
|
||||
// Guitar Hero 3 Controller
|
||||
IDB_GH3_GREEN,
|
||||
IDB_GH3_RED,
|
||||
IDB_GH3_YELLOW,
|
||||
IDB_GH3_BLUE,
|
||||
IDB_GH3_ORANGE,
|
||||
IDB_GH3_PLUS,
|
||||
IDB_GH3_MINUS,
|
||||
IDB_GH3_WHAMMY,
|
||||
IDB_GH3_ANALOG_LEFT,
|
||||
IDB_GH3_ANALOG_RIGHT,
|
||||
IDB_GH3_ANALOG_UP,
|
||||
IDB_GH3_ANALOG_DOWN,
|
||||
IDB_GH3_STRUM_UP,
|
||||
IDB_GH3_STRUM_DOWN,
|
||||
|
||||
// Gamepad
|
||||
IDB_ANALOG_LEFT_X, IDB_ANALOG_LEFT_Y,
|
||||
IDB_ANALOG_RIGHT_X, IDB_ANALOG_RIGHT_Y,
|
||||
IDB_TRIGGER_L, IDB_TRIGGER_R,
|
||||
|
||||
IDTM_BUTTON = 1000, // Timer
|
||||
IDTM_UPDATE_PAD, // Timer
|
||||
|
||||
ID_NOTEBOOK,
|
||||
ID_CONTROLLERPAGE1,
|
||||
ID_CONTROLLERPAGE2,
|
||||
ID_CONTROLLERPAGE3,
|
||||
ID_CONTROLLERPAGE4,
|
||||
|
||||
// Gamepad settings
|
||||
IDC_JOYNAME,
|
||||
IDC_RUMBLE, IDC_RUMBLE_STRENGTH,
|
||||
IDC_DEAD_ZONE_LEFT, IDC_DEAD_ZONE_RIGHT,
|
||||
IDC_STICK_DIAGONAL, IDC_STICK_C2S,
|
||||
IDC_TILT_TYPE_WM, IDC_TILT_TYPE_NC,
|
||||
IDC_TILT_ROLL, IDC_TILT_ROLL_SWING,
|
||||
IDC_TILT_PITCH, IDC_TILT_PITCH_SWING,
|
||||
IDC_TILT_ROLL_INVERT, IDC_TILT_PITCH_INVERT,
|
||||
IDC_TRIGGER_TYPE,
|
||||
IDC_NUNCHUCK_STICK,
|
||||
IDC_CC_LEFT_STICK, IDC_CC_RIGHT_STICK, IDC_CC_TRIGGERS,
|
||||
IDC_GH3_ANALOG,
|
||||
};
|
||||
|
||||
bool m_ControlsCreated;
|
||||
int m_Page, BoxW, BoxH;
|
||||
|
||||
wxString OldLabel;
|
||||
|
||||
wxNotebook *m_Notebook;
|
||||
|
||||
wxStaticBitmap *m_bmpSquareLeftIn[MAX_WIIMOTES],
|
||||
*m_bmpSquareLeftOut[MAX_WIIMOTES],
|
||||
*m_bmpSquareRightIn[MAX_WIIMOTES],
|
||||
*m_bmpSquareRightOut[MAX_WIIMOTES];
|
||||
|
||||
wxCheckBox *m_CheckC2S[MAX_WIIMOTES],
|
||||
*m_CheckRumble[MAX_WIIMOTES],
|
||||
*m_TiltRollSwing[MAX_WIIMOTES],
|
||||
*m_TiltPitchSwing[MAX_WIIMOTES],
|
||||
*m_TiltRollInvert[MAX_WIIMOTES],
|
||||
*m_TiltPitchInvert[MAX_WIIMOTES];
|
||||
|
||||
wxButton *ClickedButton,
|
||||
*m_Button_Analog[IDB_TRIGGER_R - IDB_ANALOG_LEFT_X + 1][MAX_WIIMOTES],
|
||||
*m_Button_Wiimote[IDB_WM_SHAKE - IDB_WM_A + 1][MAX_WIIMOTES],
|
||||
*m_Button_NunChuck[IDB_NC_SHAKE - IDB_NC_Z + 1][MAX_WIIMOTES],
|
||||
*m_Button_Classic[IDB_CC_RD - IDB_CC_A + 1][MAX_WIIMOTES],
|
||||
*m_Button_GH3[IDB_GH3_STRUM_DOWN - IDB_GH3_GREEN + 1][MAX_WIIMOTES];
|
||||
|
||||
wxChoice *m_Joyname[MAX_WIIMOTES],
|
||||
*m_ComboDeadZoneLeft[MAX_WIIMOTES],
|
||||
*m_ComboDeadZoneRight[MAX_WIIMOTES],
|
||||
*m_ComboDiagonal[MAX_WIIMOTES],
|
||||
*m_RumbleStrength[MAX_WIIMOTES],
|
||||
*m_TiltTypeWM[MAX_WIIMOTES],
|
||||
*m_TiltTypeNC[MAX_WIIMOTES],
|
||||
*m_TiltComboRangeRoll[MAX_WIIMOTES],
|
||||
*m_TiltComboRangePitch[MAX_WIIMOTES],
|
||||
*m_TriggerType[MAX_WIIMOTES],
|
||||
*m_NunchuckComboStick[MAX_WIIMOTES],
|
||||
*m_CcComboLeftStick[MAX_WIIMOTES],
|
||||
*m_CcComboRightStick[MAX_WIIMOTES],
|
||||
*m_CcComboTriggers[MAX_WIIMOTES],
|
||||
*m_GH3ComboAnalog[MAX_WIIMOTES];
|
||||
|
||||
wxBoxSizer *m_Sizer_Classic[IDB_CC_RD - IDB_CC_A + 1][MAX_WIIMOTES];
|
||||
|
||||
wxStaticText
|
||||
*m_tStatusLeftIn[MAX_WIIMOTES], *m_tStatusLeftOut[MAX_WIIMOTES],
|
||||
*m_tStatusRightIn[MAX_WIIMOTES], *m_tStatusRightOut[MAX_WIIMOTES],
|
||||
*m_TriggerStatusL[MAX_WIIMOTES], *m_TriggerStatusR[MAX_WIIMOTES];
|
||||
|
||||
wxBitmap CreateBitmap();
|
||||
wxBitmap CreateBitmapDot();
|
||||
wxBitmap CreateBitmapDeadZone(int Radius);
|
||||
wxBitmap CreateBitmapClear();
|
||||
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void CloseClick(wxCommandEvent& event);
|
||||
void CreatePadGUIControls();
|
||||
void UpdateGUI();
|
||||
void NotebookPageChanged(wxNotebookEvent& event);
|
||||
void OnButtonTimer(wxTimerEvent& WXUNUSED(event)) { DoGetButtons(GetButtonWaitingID); }
|
||||
void OnKeyDown(wxKeyEvent& event);
|
||||
void OnButtonClick(wxCommandEvent& event);
|
||||
void OnAxisClick(wxCommandEvent& event);
|
||||
void GeneralSettingsChanged(wxCommandEvent& event);
|
||||
void SaveButtonMapping(int Id, int Key);
|
||||
|
||||
// Gamepad configuration
|
||||
void SetButtonText(int id,const wxString &str);
|
||||
wxString GetButtonText(int id);
|
||||
|
||||
void DoGetButtons(int id);
|
||||
void EndGetButtons();
|
||||
void UpdatePadInfo(wxTimerEvent& WXUNUSED(event));
|
||||
void ToBlank(bool ToBlank, int Id);
|
||||
void DoChangeDeadZone();
|
||||
|
||||
// Configure buttons
|
||||
int GetButtonWaitingID, GetButtonWaitingTimer, g_Pressed;
|
||||
};
|
||||
extern WiimotePadConfigDialog *m_PadConfigFrame;
|
||||
#endif
|
||||
@@ -1,286 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
|
||||
/* Data reports guide. The different structures location in the Input
|
||||
reports. The ? in the IR coordinates is the High coordinates that are four
|
||||
in one byte.
|
||||
|
||||
0x37: For the data reportingmode 0x37 there are five unused IR bytes in the
|
||||
end (represented) by "..." below, it seems like they can be set to either
|
||||
0xff or 0x00 without affecting the IR emulation. */
|
||||
|
||||
/* 0x33 [c.left etc] [c.a etc] acc.x y z ir0.x y ? ir1.x y ? ir2.x y ? ir3.x y
|
||||
?
|
||||
|
||||
0x37 [c.left etc] [c.a etc] acc.x y z ir0.x1 y1 ? x2 y2 ir1.x1 y1 ? x2 y2
|
||||
... ext.jx jy ax ay az bt
|
||||
|
||||
|
||||
The Data Report's path from here is
|
||||
WII_IPC_HLE_WiiMote.cpp:
|
||||
Callback_WiimoteInterruptChannel()
|
||||
CWII_IPC_HLE_WiiMote::SendL2capData()
|
||||
WII_IPC_HLE_Device_usb.cpp:
|
||||
CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket()
|
||||
at that point the message is queued and will be sent by the next
|
||||
CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "pluginspecs_wiimote.h"
|
||||
#include "StringUtil.h" // for ArrayToString
|
||||
|
||||
#include "wiimote_hid.h" // Local
|
||||
#include "main.h"
|
||||
#include "EmuMain.h"
|
||||
#include "EmuSubroutines.h"
|
||||
#include "EmuDefinitions.h"
|
||||
#include "Encryption.h" // for extension encryption
|
||||
#include "Config.h" // for g_Config
|
||||
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
// Subroutines
|
||||
|
||||
// Update the data reporting mode
|
||||
|
||||
void WmReportMode(u16 _channelID, wm_report_mode* dr)
|
||||
{
|
||||
INFO_LOG(WIIMOTE, "Set data report mode");
|
||||
DEBUG_LOG(WIIMOTE, " Rumble: %x", dr->rumble);
|
||||
DEBUG_LOG(WIIMOTE, " Continuous: %x", dr->continuous);
|
||||
DEBUG_LOG(WIIMOTE, " All The Time: %x", dr->all_the_time);
|
||||
DEBUG_LOG(WIIMOTE, " Mode: 0x%02x", dr->mode);
|
||||
|
||||
g_ReportingAuto[g_ID] = dr->all_the_time;
|
||||
g_ReportingMode[g_ID] = dr->mode;
|
||||
g_ReportingChannel[g_ID] = _channelID;
|
||||
|
||||
if (dr->all_the_time == 0)
|
||||
{
|
||||
PanicAlert("Wiimote: Reporting Always is set to OFF!");
|
||||
}
|
||||
|
||||
// Validation check
|
||||
switch(dr->mode)
|
||||
{
|
||||
case WM_REPORT_CORE:
|
||||
case WM_REPORT_CORE_ACCEL:
|
||||
case WM_REPORT_CORE_ACCEL_IR12:
|
||||
case WM_REPORT_CORE_ACCEL_EXT16:
|
||||
case WM_REPORT_CORE_ACCEL_IR10_EXT6:
|
||||
break;
|
||||
default:
|
||||
PanicAlert("Wiimote: Unsupported reporting mode 0x%x", dr->mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Case 0x30: Core Buttons */
|
||||
void SendReportCore(u16 _channelID)
|
||||
{
|
||||
u8 DataFrame[1024];
|
||||
u32 Offset = WriteWmReportHdr(DataFrame, WM_REPORT_CORE);
|
||||
|
||||
wm_report_core* pReport = (wm_report_core*)(DataFrame + Offset);
|
||||
Offset += sizeof(wm_report_core);
|
||||
memset(pReport, 0, sizeof(wm_report_core));
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
FillReportInfo(pReport->c);
|
||||
#endif
|
||||
|
||||
INFO_LOG(WIIMOTE, " SendReportCore(0x30)");
|
||||
DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID);
|
||||
DEBUG_LOG(WIIMOTE, " Size: %08x", Offset);
|
||||
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(g_ID, _channelID, DataFrame, Offset);
|
||||
}
|
||||
|
||||
|
||||
/* 0x31: Core Buttons and Accelerometer */
|
||||
void SendReportCoreAccel(u16 _channelID)
|
||||
{
|
||||
u8 DataFrame[1024];
|
||||
u32 Offset = WriteWmReportHdr(DataFrame, WM_REPORT_CORE_ACCEL);
|
||||
|
||||
wm_report_core_accel* pReport = (wm_report_core_accel*)(DataFrame + Offset);
|
||||
Offset += sizeof(wm_report_core_accel);
|
||||
memset(pReport, 0, sizeof(wm_report_core_accel));
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
FillReportInfo(pReport->c);
|
||||
FillReportAcc(pReport->a);
|
||||
#endif
|
||||
|
||||
INFO_LOG(WIIMOTE, " SendReportCoreAccel (0x31)");
|
||||
DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID);
|
||||
DEBUG_LOG(WIIMOTE, " Size: %08x", Offset);
|
||||
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(g_ID, _channelID, DataFrame, Offset);
|
||||
}
|
||||
|
||||
|
||||
/* Case 0x33: Core Buttons and Accelerometer with 12 IR bytes */
|
||||
void SendReportCoreAccelIr12(u16 _channelID) {
|
||||
u8 DataFrame[1024];
|
||||
u32 Offset = WriteWmReportHdr(DataFrame, WM_REPORT_CORE_ACCEL_IR12);
|
||||
|
||||
wm_report_core_accel_ir12* pReport = (wm_report_core_accel_ir12*)(DataFrame + Offset);
|
||||
Offset += sizeof(wm_report_core_accel_ir12);
|
||||
memset(pReport, 0, sizeof(wm_report_core_accel_ir12));
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
FillReportInfo(pReport->c);
|
||||
FillReportAcc(pReport->a);
|
||||
// We settle with emulating two objects, not all four. We leave object 2 and 3 with 0xff.
|
||||
FillReportIR(pReport->ir[0], pReport->ir[1]);
|
||||
#endif
|
||||
memset(&pReport->ir[2], 0xff, sizeof(wm_ir_extended));
|
||||
memset(&pReport->ir[3], 0xff, sizeof(wm_ir_extended));
|
||||
|
||||
INFO_LOG(WIIMOTE, " SendReportCoreAccelIr12(0x33)");
|
||||
DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID);
|
||||
DEBUG_LOG(WIIMOTE, " Size: %08x", Offset);
|
||||
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(g_ID, _channelID, DataFrame, Offset);
|
||||
}
|
||||
|
||||
|
||||
/* Case 0x35: Core Buttons and Accelerometer with 16 Extension Bytes */
|
||||
void SendReportCoreAccelExt16(u16 _channelID)
|
||||
{
|
||||
u8 DataFrame[1024];
|
||||
u32 Offset = WriteWmReportHdr(DataFrame, WM_REPORT_CORE_ACCEL_EXT16);
|
||||
|
||||
wm_report_core_accel_ext16* pReport = (wm_report_core_accel_ext16*)(DataFrame + Offset);
|
||||
Offset += sizeof(wm_report_core_accel_ext16);
|
||||
memset(pReport, 0, sizeof(wm_report_core_accel_ext16));
|
||||
|
||||
// Make a classic extension struct
|
||||
wm_classic_extension _ext;
|
||||
memset(&_ext, 0, sizeof(wm_classic_extension));
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
FillReportInfo(pReport->c);
|
||||
FillReportAcc(pReport->a);
|
||||
#endif
|
||||
|
||||
if(WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUK)
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
FillReportExtension(pReport->ext);
|
||||
#endif
|
||||
}
|
||||
else if(WiiMapping[g_ID].iExtensionConnected == EXT_CLASSIC_CONTROLLER)
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
FillReportClassicExtension(_ext);
|
||||
#endif
|
||||
// Copy _ext to pReport->ext
|
||||
memcpy(&pReport->ext, &_ext, sizeof(_ext));
|
||||
}
|
||||
|
||||
INFO_LOG(WIIMOTE, " SendReportCoreAccelExt16 (0x35)");
|
||||
DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID);
|
||||
DEBUG_LOG(WIIMOTE, " Size: %08x", Offset);
|
||||
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(g_ID, _channelID, DataFrame, Offset);
|
||||
}
|
||||
|
||||
|
||||
/* Case 0x37: Core Buttons and Accelerometer with 10 IR bytes and 6 Extension Bytes */
|
||||
void SendReportCoreAccelIr10Ext(u16 _channelID)
|
||||
{
|
||||
u8 DataFrame[1024];
|
||||
u32 Offset = WriteWmReportHdr(DataFrame, WM_REPORT_CORE_ACCEL_IR10_EXT6);
|
||||
|
||||
wm_report_core_accel_ir10_ext6* pReport = (wm_report_core_accel_ir10_ext6*)(DataFrame + Offset);
|
||||
Offset += sizeof(wm_report_core_accel_ir10_ext6);
|
||||
memset(pReport, 0, sizeof(wm_report_core_accel_ir10_ext6));
|
||||
|
||||
// Make a classic extension struct
|
||||
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
FillReportInfo(pReport->c);
|
||||
FillReportAcc(pReport->a);
|
||||
FillReportIRBasic(pReport->ir[0], pReport->ir[1]);
|
||||
if ((WiiMapping[g_ID].bMotionPlusConnected) )
|
||||
{
|
||||
if(WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUK)
|
||||
{
|
||||
if (g_RegExt[g_ID][0xFF] == 0x05) {
|
||||
FillReportMotionPlus(pReport->ext, true);
|
||||
}
|
||||
else {
|
||||
FillReportExtension(pReport->ext);
|
||||
}
|
||||
DEBUG_LOG(WIIMOTE, "Motionplus:Nunchuk data -> ext:%01x mp:%01x [ff:0x%02x]", (pReport->ext.az &0x01), (pReport->ext.bt &0x02),g_RegExt[g_ID][0xFF]);
|
||||
|
||||
}
|
||||
else if (WiiMapping[g_ID].iExtensionConnected == EXT_NONE)
|
||||
{
|
||||
FillReportMotionPlus(pReport->ext, false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
if(WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUK)
|
||||
{
|
||||
FillReportExtension(pReport->ext);
|
||||
}
|
||||
else if(WiiMapping[g_ID].iExtensionConnected == EXT_CLASSIC_CONTROLLER)
|
||||
{
|
||||
wm_classic_extension _ext;
|
||||
memset(&_ext, 0, sizeof(wm_classic_extension));
|
||||
|
||||
FillReportClassicExtension(_ext);
|
||||
|
||||
// Copy _ext to pReport->ext
|
||||
memcpy(&pReport->ext, &_ext, sizeof(_ext));
|
||||
}
|
||||
else if(WiiMapping[g_ID].iExtensionConnected == EXT_GUITARHERO)
|
||||
{
|
||||
|
||||
wm_GH3_extension _GH3_ext;
|
||||
memset(&_GH3_ext, 0, sizeof(wm_GH3_extension));
|
||||
FillReportGuitarHero3Extension(_GH3_ext);
|
||||
|
||||
memcpy(&pReport->ext, &_GH3_ext, sizeof(_GH3_ext));
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
INFO_LOG(WIIMOTE, " SendReportCoreAccelIr10Ext(0x37)");
|
||||
DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID);
|
||||
DEBUG_LOG(WIIMOTE, " Size: %08x", Offset);
|
||||
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(g_ID, _channelID, DataFrame, Offset);
|
||||
}
|
||||
|
||||
|
||||
} // end of namespace
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _EMU_DEFINITIONS_
|
||||
#define _EMU_DEFINITIONS_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
#include "wiimote_hid.h"
|
||||
#include "EmuDefinitions.h"
|
||||
#include "Encryption.h"
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
//******************************************************************************
|
||||
// Definitions and variable declarations
|
||||
//******************************************************************************
|
||||
u8 g_Eeprom[MAX_WIIMOTES][WIIMOTE_EEPROM_SIZE];
|
||||
u8 g_RegExt[MAX_WIIMOTES][WIIMOTE_REG_EXT_SIZE];
|
||||
u8 g_RegMotionPlus[MAX_WIIMOTES][WIIMOTE_REG_EXT_SIZE];
|
||||
u8 g_RegSpeaker[MAX_WIIMOTES][WIIMOTE_REG_SPEAKER_SIZE];
|
||||
u8 g_RegIr[MAX_WIIMOTES][WIIMOTE_REG_IR_SIZE];
|
||||
u8 g_IRClock[MAX_WIIMOTES];
|
||||
u8 g_IR[MAX_WIIMOTES];
|
||||
u8 g_Leds[MAX_WIIMOTES];
|
||||
u8 g_Speaker[MAX_WIIMOTES];
|
||||
u8 g_MotionPlus[MAX_WIIMOTES];
|
||||
u8 g_SpeakerMute[MAX_WIIMOTES];
|
||||
|
||||
u8 g_MotionPlusLastWriteReg[MAX_WIIMOTES];
|
||||
u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE];
|
||||
|
||||
int g_ID; // Current refreshing Wiimote
|
||||
bool g_ReportingAuto[MAX_WIIMOTES]; // Auto report or passive report
|
||||
bool g_InterleavedData[MAX_WIIMOTES]; //sending alternated data packets from the nunchuk/motionplus
|
||||
u8 g_ReportingMode[MAX_WIIMOTES]; // The reporting mode and channel id
|
||||
u16 g_ReportingChannel[MAX_WIIMOTES];
|
||||
|
||||
wiimote_key g_ExtKey[MAX_WIIMOTES]; // The extension encryption key
|
||||
bool g_Encryption; // Encryption on or off
|
||||
|
||||
// Gamepad input
|
||||
int NumPads = 0, NumGoodPads = 0; // Number of goods pads
|
||||
std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
|
||||
CONTROLLER_MAPPING_WII WiiMapping[MAX_WIIMOTES];
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //_EMU_DECLARATIONS_
|
||||
|
||||
@@ -1,363 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _EMU_DECLARATIONS_
|
||||
#define _EMU_DECLARATIONS_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "../../../Core/InputCommon/Src/InputCommon.h" // Core
|
||||
#include "../../../Core/InputCommon/Src/SDL_Util.h"
|
||||
#ifdef _WIN32
|
||||
#include "../../../Core/InputCommon/Src/XInput_Util.h"
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include "wiimote_hid.h" // Local
|
||||
#include "Encryption.h"
|
||||
|
||||
#include "UDPWiimote.h"
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#include <X11/X.h>
|
||||
#endif
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
//******************************************************************************
|
||||
// Definitions and variable declarations
|
||||
//******************************************************************************
|
||||
|
||||
/* The Libogc bounding box in smoothed IR coordinates is 232,284 792,704. However, there is no
|
||||
universal standard that works with all games. They all use their own calibration. Also,
|
||||
there is no widescreen mode for the calibration, at least not in the games I tried, the
|
||||
game decides for example that a horizontal value of 500 is 50% from the left of the screen,
|
||||
and then that's the same regardless if we use the widescreen mode or not.*/
|
||||
#define LEFT 266
|
||||
#define TOP 215
|
||||
#define RIGHT 752
|
||||
#define BOTTOM 705
|
||||
/* Since the width of the entire virtual screen is 1024 a reasonable sensor bar width is perhaps 200,
|
||||
given how small most sensor bars are compared to the total TV width. When I tried the distance with
|
||||
my Wiimote from around three meters distance from the sensor bar (that has around 15 cm beteen the
|
||||
IR lights) I got a dot distance of around 110 (and a dot size of between 1 and 2). */
|
||||
#define SENSOR_BAR_WIDTH 200
|
||||
|
||||
// Movement recording
|
||||
extern int g_RecordingPlaying[3];
|
||||
extern int g_RecordingCounter[3];
|
||||
extern int g_RecordingPoint[3];
|
||||
extern double g_RecordingStart[3];
|
||||
extern double g_RecordingCurrentTime[3];
|
||||
|
||||
// Registry sizes
|
||||
#define WIIMOTE_EEPROM_SIZE (16*1024)
|
||||
#define WIIMOTE_EEPROM_FREE_SIZE 0x16ff
|
||||
#define WIIMOTE_REG_SPEAKER_SIZE 10
|
||||
#define WIIMOTE_REG_EXT_SIZE 0x100
|
||||
#define WIIMOTE_REG_IR_SIZE 0x34
|
||||
|
||||
extern u8 g_Eeprom[MAX_WIIMOTES][WIIMOTE_EEPROM_SIZE];
|
||||
extern u8 g_RegExt[MAX_WIIMOTES][WIIMOTE_REG_EXT_SIZE];
|
||||
extern u8 g_RegMotionPlus[MAX_WIIMOTES][WIIMOTE_REG_EXT_SIZE];
|
||||
extern u8 g_RegSpeaker[MAX_WIIMOTES][WIIMOTE_REG_SPEAKER_SIZE];
|
||||
extern u8 g_RegIr[MAX_WIIMOTES][WIIMOTE_REG_IR_SIZE];
|
||||
extern u8 g_IRClock[MAX_WIIMOTES];
|
||||
extern u8 g_IR[MAX_WIIMOTES];
|
||||
extern u8 g_Leds[MAX_WIIMOTES];
|
||||
extern u8 g_Speaker[MAX_WIIMOTES];
|
||||
extern u8 g_MotionPlus[MAX_WIIMOTES];
|
||||
extern u8 g_MotionPlusLastWriteReg[MAX_WIIMOTES];
|
||||
extern u8 g_SpeakerMute[MAX_WIIMOTES];
|
||||
|
||||
extern u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE];
|
||||
|
||||
extern int g_ID;
|
||||
extern bool g_ReportingAuto[MAX_WIIMOTES];
|
||||
extern u8 g_ReportingMode[MAX_WIIMOTES];
|
||||
extern u16 g_ReportingChannel[MAX_WIIMOTES];
|
||||
extern bool g_InterleavedData[MAX_WIIMOTES];
|
||||
|
||||
extern wiimote_key g_ExtKey[MAX_WIIMOTES]; // extension encryption key
|
||||
extern bool g_Encryption;
|
||||
|
||||
/* An example of a factory default first bytes of the Eeprom memory. There are differences between
|
||||
different Wiimotes, my Wiimote had different neutral values for the accelerometer. */
|
||||
static const u8 EepromData_0[] = {
|
||||
0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3,
|
||||
0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3,
|
||||
// Accelerometer neutral values
|
||||
0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E,
|
||||
0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E
|
||||
};
|
||||
|
||||
static const u8 EepromData_16D0[] = {
|
||||
0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00, 0x00,
|
||||
0x33, 0xCC, 0x44, 0xBB, 0x00, 0x00, 0x66, 0x99,
|
||||
0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13
|
||||
};
|
||||
|
||||
/* Default calibration for the nunchuck. It should be written to 0x20 - 0x3f of the
|
||||
extension register. 0x80 is the neutral x and y accelerators and 0xb3 is the
|
||||
neutral z accelerometer that is adjusted for gravity. */
|
||||
static const u8 nunchuck_calibration[] =
|
||||
{
|
||||
0x80,0x80,0x80,0x00, // accelerometer x, y, z neutral
|
||||
0xb3,0xb3,0xb3,0x00, // x, y, z g-force values
|
||||
|
||||
0xff, 0x00, 0x80, 0xff, // 0xff max, 0x00 min, 0x80 = analog stick x and y axis center
|
||||
0x00, 0x80, 0xec, 0x41 // checksum on the last two bytes
|
||||
};
|
||||
|
||||
|
||||
static const u8 wireless_nunchuck_calibration[] =
|
||||
{
|
||||
128, 128, 128, 0x00,
|
||||
181, 181, 181, 0x00,
|
||||
255, 0, 125, 255,
|
||||
0, 126, 0xed, 0x43
|
||||
};
|
||||
|
||||
/* Classic Controller calibration */
|
||||
static const u8 classic_calibration[] =
|
||||
{
|
||||
0xff,0x00,0x80, 0xff,0x00,0x80, 0xff,0x00,0x80, 0xff,0x00,0x80,
|
||||
0x00,0x00, 0x51,0xa6
|
||||
};
|
||||
|
||||
|
||||
/* Default calibration for the motion plus, 0xA60020 */
|
||||
static const u8 motion_plus_calibration[] =
|
||||
{
|
||||
0x79, 0xbe, 0x77, 0x5a, 0x77, 0x38, // gyroscope neutral values (each 14 bit, last 2bits unknown) fast motion
|
||||
0x2f, 0x90, 0xcd, 0x3b, // "" min/max
|
||||
0x2f, 0xfd, 0xc8, 0x29, // "" min/max
|
||||
0x9c, 0x75,
|
||||
|
||||
0x7d, 0xd4, 0x78, 0xef, 0x78, 0x8a, // gyroscope neutral values (each 14 bit, last 2bits unknown) slow motion
|
||||
0x35, 0xa6, 0xc9, 0x9b, // "" min/max
|
||||
0x33, 0x50, // "" min
|
||||
0x2d, 0x00, 0xbd, 0x23
|
||||
}; // TODO: figure out remaining parts;
|
||||
|
||||
static const u8 motionplus_accel_gyro_syncing[] = { //resulting calibration data at 0xA60050 by syncing accels and gyros
|
||||
0x1e, 0x54, 0x74, 0xa2, 0x96, 0xec, 0x2b, 0xd6, 0xe1, 0xef, 0xc3, 0xf7, 0x84, 0x9e, 0x06, 0xbb,
|
||||
0x39, 0x33, 0x3d, 0x20, 0x97, 0xed, 0x75, 0x52, 0xfd, 0x98, 0xaf, 0xd8, 0xc9, 0x5a, 0x17, 0x23,
|
||||
0x74, 0x3a, 0x49, 0xd3, 0xb9, 0xf6, 0xff, 0x4f, 0x34, 0xa8, 0x6d, 0xc4, 0x96, 0x5c, 0xcd, 0xb2,
|
||||
0x33, 0x78, 0x98, 0xe9, 0xa9, 0x7f, 0xf7, 0x5e, 0x07, 0x87, 0xbb, 0x29, 0x01, 0x2b, 0x70, 0x3f
|
||||
};
|
||||
|
||||
static const u8 motionplus_activeflags[] = { //0xA600F0
|
||||
0x55, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0xff, 0xff, //Different flags, e.g. activation, calibration, initiaton, extensionstate.
|
||||
0x00, 0x00, 0xa6, 0x20, 0x00, 0x05 //Extension ID
|
||||
};
|
||||
|
||||
// Extension device IDs to be written to the last bytes of the extension reg
|
||||
static const u8 nunchuck_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x00, 0x00 };
|
||||
static const u8 classic_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x01, 0x01 };
|
||||
static const u8 gh3glp_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x01, 0x03 };
|
||||
static const u8 ghwtdrums_id[] = { 0x01, 0x00, 0xa4, 0x20, 0x01, 0x03 };
|
||||
static const u8 wbb_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x4, 0x02 };
|
||||
static const u8 motionplus_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x04, 0x05 };
|
||||
static const u8 motionplusnunchuk_id[] = { 0x00, 0x00, 0xa6, 0x20, 0x05, 0x05 };
|
||||
// The id for nothing inserted
|
||||
static const u8 nothing_id[] = { 0x00, 0x00, 0x00, 0x00, 0x2e, 0x2e };
|
||||
// The id for a partially inserted extension
|
||||
static const u8 partially_id[] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
|
||||
|
||||
|
||||
enum EExtensionType
|
||||
{
|
||||
EXT_NONE = 0,
|
||||
EXT_NUNCHUK,
|
||||
EXT_CLASSIC_CONTROLLER,
|
||||
EXT_GUITARHERO,
|
||||
EXT_WBB,
|
||||
};
|
||||
|
||||
enum EInputType
|
||||
{
|
||||
FROM_KEYBOARD,
|
||||
FROM_ANALOG1,
|
||||
FROM_ANALOG2,
|
||||
FROM_TRIGGER,
|
||||
};
|
||||
|
||||
enum EButtonCode
|
||||
{
|
||||
EWM_A = 0, // Keyboard A and Mouse A
|
||||
EWM_B,
|
||||
EWM_ONE, EWM_TWO,
|
||||
EWM_P, EWM_M, EWM_H,
|
||||
EWM_L, EWM_R, EWM_U, EWM_D,
|
||||
EWM_ROLL_L, EWM_ROLL_R,
|
||||
EWM_PITCH_U, EWM_PITCH_D,
|
||||
EWM_SHAKE,
|
||||
|
||||
ENC_Z, ENC_C,
|
||||
ENC_L, ENC_R, ENC_U, ENC_D,
|
||||
ENC_ROLL_L, ENC_ROLL_R,
|
||||
ENC_PITCH_U, ENC_PITCH_D,
|
||||
ENC_SHAKE,
|
||||
|
||||
ECC_A, ECC_B, ECC_X, ECC_Y,
|
||||
ECC_P, ECC_M, ECC_H,
|
||||
ECC_Tl, ECC_Tr, ECC_Zl, ECC_Zr,
|
||||
ECC_Dl, ECC_Dr, ECC_Du, ECC_Dd,
|
||||
ECC_Ll, ECC_Lr, ECC_Lu, ECC_Ld,
|
||||
ECC_Rl, ECC_Rr, ECC_Ru, ECC_Rd,
|
||||
|
||||
EGH_Green, EGH_Red, EGH_Yellow, EGH_Blue, EGH_Orange,
|
||||
EGH_Plus, EGH_Minus, EGH_Whammy,
|
||||
EGH_Al, EGH_Ar, EGH_Au, EGH_Ad,
|
||||
EGH_StrumUp, EGH_StrumDown,
|
||||
|
||||
LAST_CONSTANT,
|
||||
};
|
||||
|
||||
|
||||
union UAxis
|
||||
{
|
||||
int Code[6];
|
||||
struct
|
||||
{
|
||||
int Lx;
|
||||
int Ly;
|
||||
int Rx;
|
||||
int Ry;
|
||||
int Tl; // Trigger
|
||||
int Tr; // Trigger
|
||||
};
|
||||
};
|
||||
|
||||
struct SStickMapping
|
||||
{
|
||||
int NC;
|
||||
int CCL;
|
||||
int CCR;
|
||||
int CCT; //Trigger
|
||||
int GH; // Analog Stick
|
||||
int GHB; // Whammy bar
|
||||
};
|
||||
|
||||
struct STiltMapping
|
||||
{
|
||||
int InputWM;
|
||||
int InputNC;
|
||||
bool RollInvert;
|
||||
bool PitchInvert;
|
||||
int RollDegree;
|
||||
bool RollSwing;
|
||||
int RollRange;
|
||||
int PitchDegree;
|
||||
bool PitchSwing;
|
||||
int PitchRange;
|
||||
};
|
||||
|
||||
|
||||
struct SDot
|
||||
{
|
||||
int Rx, Ry, X, Y;
|
||||
bool Visible;
|
||||
int Size; // Size of the IR dot (0-15)
|
||||
int Order; // Increasing order from low to higher x-axis values
|
||||
};
|
||||
|
||||
struct SIR
|
||||
{
|
||||
SDot Dot[4];
|
||||
int Distance;
|
||||
};
|
||||
|
||||
struct STiltData
|
||||
{
|
||||
// FakeNoise is used to prevent disconnection
|
||||
// when there is no input for a long time
|
||||
int FakeNoise;
|
||||
int Shake;
|
||||
int Roll, Pitch;
|
||||
STiltData()
|
||||
{
|
||||
FakeNoise = 1;
|
||||
Shake = 0;
|
||||
Roll = 0;
|
||||
Pitch = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct SMotion
|
||||
{
|
||||
// Raw X and Y coordinate and processed X and Y coordinates
|
||||
SIR IR;
|
||||
STiltData TiltWM;
|
||||
STiltData TiltNC;
|
||||
};
|
||||
|
||||
struct UDPWiiSettings
|
||||
{
|
||||
bool enable;
|
||||
bool enableAccel;
|
||||
bool enableButtons;
|
||||
bool enableIR;
|
||||
bool enableNunchuck;
|
||||
char port[10];
|
||||
UDPWiimote *instance;
|
||||
};
|
||||
|
||||
struct CONTROLLER_MAPPING_WII // WII PAD MAPPING
|
||||
{
|
||||
SDL_Joystick *joy; // SDL joystick device
|
||||
UAxis AxisState;
|
||||
UAxis AxisMapping; // 6 Axes (Main, Sub, Triggers)
|
||||
int TriggerType; // SDL or XInput trigger
|
||||
int ID; // SDL joystick device ID
|
||||
bool Rumble;
|
||||
int RumbleStrength;
|
||||
int DeadZoneL; // Analog 1 Deadzone
|
||||
int DeadZoneR; // Analog 2 Deadzone
|
||||
bool bCircle2Square;
|
||||
int Diagonal;
|
||||
|
||||
int Source; // 0: inactive, 1: emu, 2: real
|
||||
bool bSideways;
|
||||
bool bUpright;
|
||||
bool bMotionPlusConnected;
|
||||
bool bWiiAutoReconnect;
|
||||
int iExtensionConnected;
|
||||
|
||||
STiltMapping Tilt;
|
||||
SStickMapping Stick;
|
||||
int Button[LAST_CONSTANT];
|
||||
SMotion Motion;
|
||||
|
||||
UDPWiiSettings UDPWM;
|
||||
};
|
||||
|
||||
// Gamepad input
|
||||
extern int NumPads, NumGoodPads; // Number of goods pads
|
||||
extern std::vector<InputCommon::CONTROLLER_INFO> joyinfo;
|
||||
extern CONTROLLER_MAPPING_WII WiiMapping[4];
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //_EMU_DEFINITIONS_
|
||||
@@ -1,433 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "MathUtil.h"
|
||||
#include "StringUtil.h" // for ArrayToString()
|
||||
#include "IniFile.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include "EmuDefinitions.h" // Local
|
||||
#include "main.h"
|
||||
#include "wiimote_hid.h"
|
||||
#include "EmuSubroutines.h"
|
||||
#include "EmuMain.h"
|
||||
#include "Encryption.h" // for extension encryption
|
||||
#include "Config.h" // for g_Config
|
||||
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
//******************************************************************************
|
||||
// Accelerometer functions
|
||||
//******************************************************************************
|
||||
|
||||
// Wiimote accelerometer
|
||||
/* The accelerometer x, y and z values range from 0x00 to 0xff with the default
|
||||
netural values being [y = 0x84, x = 0x84, z = 0x9f] according to a
|
||||
source. The extremes are 0x00 for (-) and 0xff for (+). It's important that
|
||||
all values are not 0x80, the mouse pointer can disappear from the screen
|
||||
permanently then, until z is adjusted back. This is because the game detects
|
||||
a steep pitch of the Wiimote then.
|
||||
|
||||
Wiimote Accelerometer Axes
|
||||
|
||||
+ (- -- X -- +)
|
||||
| ___
|
||||
| | |\ -
|
||||
| | + || \
|
||||
| . || \
|
||||
Y |. .|| Z
|
||||
| . || \
|
||||
| | . || \
|
||||
| |___|| +
|
||||
- ---
|
||||
|
||||
*/
|
||||
|
||||
// Single shake step of all three directions
|
||||
void ShakeToAccelerometer(int &_x, int &_y, int &_z, STiltData &_TiltData)
|
||||
{
|
||||
switch(_TiltData.Shake)
|
||||
{
|
||||
case 0:
|
||||
_TiltData.Shake = -1;
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
_x = g_wm.cal_zero.x / 2;
|
||||
_y = g_wm.cal_zero.y / 2;
|
||||
_z = g_wm.cal_zero.z / 2;
|
||||
break;
|
||||
case 5:
|
||||
case 7:
|
||||
_x = (0xFF - g_wm.cal_zero.x ) / 2;
|
||||
_y = (0xFF - g_wm.cal_zero.y ) / 2;
|
||||
_z = (0xFF - g_wm.cal_zero.z ) / 2;
|
||||
break;
|
||||
case 2:
|
||||
_x = 0x00;
|
||||
_y = 0x00;
|
||||
_z = 0x00;
|
||||
break;
|
||||
case 6:
|
||||
_x = 0xFF;
|
||||
_y = 0xFF;
|
||||
_z = 0xFF;
|
||||
break;
|
||||
case 4:
|
||||
_x = 0x80;
|
||||
_y = 0x80;
|
||||
_z = 0x80;
|
||||
break;
|
||||
default:
|
||||
_TiltData.Shake = -1;
|
||||
break;
|
||||
}
|
||||
_TiltData.Shake++;
|
||||
|
||||
if (_TiltData.Shake != 0)
|
||||
{
|
||||
DEBUG_LOG(WIIMOTE, "Shake: %i - 0x%02x, 0x%02x, 0x%02x", _TiltData.Shake, _x, _y, _z);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tilting by gamepad. We can guess that the game will calculate
|
||||
roll and pitch and use them as measures of the tilting. We are
|
||||
interested in this tilting range 90 to -90*/
|
||||
void TiltByGamepad(STiltData &_TiltData, int Type)
|
||||
{
|
||||
// Return if we have no pads
|
||||
if (NumGoodPads == 0) return;
|
||||
|
||||
/* Adjust the pad state values, including a downscaling from the original
|
||||
0x8000 size values to 0x80. The only reason we do this is that the code
|
||||
below crrently assume that the range is 0 to 255 for all axes. If we
|
||||
lose any precision by doing this we could consider not doing this
|
||||
adjustment. And instead for example upsize the XInput trigger from 0x80
|
||||
to 0x8000. */
|
||||
int Lx = WiiMapping[g_ID].AxisState.Lx;
|
||||
int Ly = WiiMapping[g_ID].AxisState.Ly;
|
||||
int Rx = WiiMapping[g_ID].AxisState.Rx;
|
||||
int Ry = WiiMapping[g_ID].AxisState.Ry;
|
||||
int Tl = WiiMapping[g_ID].AxisState.Tl;
|
||||
int Tr = WiiMapping[g_ID].AxisState.Tr;
|
||||
|
||||
// Save the Range in degrees, 45 and 90 are good values in some games
|
||||
int RollRange = WiiMapping[g_ID].Tilt.RollRange;
|
||||
int PitchRange = WiiMapping[g_ID].Tilt.PitchRange;
|
||||
|
||||
// The trigger currently only controls pitch, no roll, no free swing
|
||||
if (Type == FROM_TRIGGER)
|
||||
{
|
||||
// Make the range the same dimension as the analog stick
|
||||
Tl = Tl / 2;
|
||||
Tr = Tr / 2;
|
||||
// Invert
|
||||
if (WiiMapping[g_ID].Tilt.PitchInvert) { Tl = -Tl; Tr = -Tr; }
|
||||
// The final value
|
||||
_TiltData.Pitch = (int)((float)PitchRange * ((float)(Tl - Tr) / 128.0f));
|
||||
}
|
||||
|
||||
/* For the analog stick roll is by default set to the X-axis, pitch is by
|
||||
default set to the Y-axis. By changing the axis mapping and the invert
|
||||
options this can be altered in any way */
|
||||
else if (Type == FROM_ANALOG1)
|
||||
{
|
||||
// Adjust the trigger to go between negative and positive values
|
||||
Lx = Lx - 0x80;
|
||||
Ly = Ly - 0x80;
|
||||
// Invert
|
||||
if (WiiMapping[g_ID].Tilt.RollInvert) Lx = -Lx; // else Tr = -Tr;
|
||||
if (WiiMapping[g_ID].Tilt.PitchInvert) Ly = -Ly; // else Tr = -Tr;
|
||||
// Produce the final value
|
||||
_TiltData.Roll = (int)((RollRange) ? (float)RollRange * ((float)Lx / 128.0f) : Lx);
|
||||
_TiltData.Pitch = (int)((PitchRange) ? (float)PitchRange * ((float)Ly / 128.0f) : Ly);
|
||||
}
|
||||
// Otherwise we are using ANALOG2
|
||||
else
|
||||
{
|
||||
// Adjust the trigger to go between negative and positive values
|
||||
Rx = Rx - 0x80;
|
||||
Ry = Ry - 0x80;
|
||||
// Invert
|
||||
if (WiiMapping[g_ID].Tilt.RollInvert) Rx = -Rx; // else Tr = -Tr;
|
||||
if (WiiMapping[g_ID].Tilt.PitchInvert) Ry = -Ry; // else Tr = -Tr;
|
||||
// Produce the final value
|
||||
_TiltData.Roll = (int)((RollRange) ? (float)RollRange * ((float)Rx / 128.0f) : Rx);
|
||||
_TiltData.Pitch = (int)((PitchRange) ? (float)PitchRange * ((float)Ry / 128.0f) : Ry);
|
||||
}
|
||||
}
|
||||
|
||||
// Tilting by keyboard
|
||||
void TiltByKeyboard(STiltData &_TiltData, int Type)
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
int _ROLL_LEFT_ = (Type) ? ENC_ROLL_L : EWM_ROLL_L;
|
||||
int _ROLL_RIGHT_ = (Type) ? ENC_ROLL_R : EWM_ROLL_R;
|
||||
int _PITCH_UP_ = (Type) ? ENC_PITCH_U : EWM_PITCH_U;
|
||||
int _PITCH_DOWN_ = (Type) ? ENC_PITCH_D : EWM_PITCH_D;
|
||||
|
||||
// Do roll/pitch or free swing
|
||||
|
||||
if (IsKey(_ROLL_LEFT_))
|
||||
{
|
||||
if (WiiMapping[g_ID].Tilt.RollRange)
|
||||
{
|
||||
// Stop at the lower end of the range
|
||||
if (_TiltData.Roll > -WiiMapping[g_ID].Tilt.RollRange)
|
||||
_TiltData.Roll -= 3; // aim left
|
||||
}
|
||||
else // Free swing
|
||||
{
|
||||
_TiltData.Roll = -0x80 / 2;
|
||||
}
|
||||
}
|
||||
else if (IsKey(_ROLL_RIGHT_))
|
||||
{
|
||||
if (WiiMapping[g_ID].Tilt.RollRange)
|
||||
{
|
||||
// Stop at the upper end of the range
|
||||
if (_TiltData.Roll < WiiMapping[g_ID].Tilt.RollRange)
|
||||
_TiltData.Roll += 3; // aim right
|
||||
}
|
||||
else // Free swing
|
||||
{
|
||||
_TiltData.Roll = 0x80 / 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_TiltData.Roll = 0;
|
||||
}
|
||||
if (IsKey(_PITCH_UP_))
|
||||
{
|
||||
if (WiiMapping[g_ID].Tilt.PitchRange)
|
||||
{
|
||||
// Stop at the lower end of the range
|
||||
if (_TiltData.Pitch > -WiiMapping[g_ID].Tilt.PitchRange)
|
||||
_TiltData.Pitch -= 3; // aim down
|
||||
}
|
||||
else // Free swing
|
||||
{
|
||||
_TiltData.Pitch = -0x80 / 2;
|
||||
}
|
||||
}
|
||||
else if (IsKey(_PITCH_DOWN_))
|
||||
{
|
||||
if (WiiMapping[g_ID].Tilt.PitchRange)
|
||||
{
|
||||
// Stop at the upper end of the range
|
||||
if (_TiltData.Pitch < WiiMapping[g_ID].Tilt.PitchRange)
|
||||
_TiltData.Pitch += 3; // aim up
|
||||
}
|
||||
else // Free swing
|
||||
{
|
||||
_TiltData.Pitch = 0x80 / 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_TiltData.Pitch = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Tilting Wiimote (Wario Land aiming, Mario Kart steering and other things)
|
||||
void TiltWiimote(int &_x, int &_y, int &_z)
|
||||
{
|
||||
// Select input method and return the x, y, x values
|
||||
if ((WiiMapping[g_ID].UDPWM.instance)&&(WiiMapping[g_ID].UDPWM.enableAccel))
|
||||
{
|
||||
float x,y,z;
|
||||
WiiMapping[g_ID].UDPWM.instance->getAccel(x,y,z);
|
||||
float xg = WiiMoteEmu::g_wm.cal_g.x;
|
||||
float yg = WiiMoteEmu::g_wm.cal_g.y;
|
||||
float zg = WiiMoteEmu::g_wm.cal_g.z;
|
||||
_x = WiiMoteEmu::g_wm.cal_zero.x + (int)(xg * x);
|
||||
_y = WiiMoteEmu::g_wm.cal_zero.y + (int)(yg * y);
|
||||
_z = WiiMoteEmu::g_wm.cal_zero.z + (int)(zg * z);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (WiiMapping[g_ID].Tilt.InputWM == FROM_KEYBOARD)
|
||||
TiltByKeyboard(WiiMapping[g_ID].Motion.TiltWM, 0);
|
||||
else
|
||||
TiltByGamepad(WiiMapping[g_ID].Motion.TiltWM, WiiMapping[g_ID].Tilt.InputWM);
|
||||
|
||||
// Adjust angles, it's only needed if both roll and pitch is used together
|
||||
if (WiiMapping[g_ID].Tilt.RollRange && WiiMapping[g_ID].Tilt.PitchRange)
|
||||
AdjustAngles(WiiMapping[g_ID].Motion.TiltWM.Roll, WiiMapping[g_ID].Motion.TiltWM.Pitch);
|
||||
|
||||
// Calculate the accelerometer value from this tilt angle
|
||||
TiltToAccelerometer(_x, _y, _z,WiiMapping[g_ID].Motion.TiltWM);
|
||||
}
|
||||
//DEBUG_LOG(WIIMOTE, "Roll:%i, Pitch:%i, _x:%u, _y:%u, _z:%u", g_Wiimote_kbd.TiltData.Roll, g_Wiimote_kbd.TiltData.Pitch, _x, _y, _z);
|
||||
}
|
||||
|
||||
// Tilting Nunchuck (Mad World, Dead Space and other things)
|
||||
void TiltNunchuck(int &_x, int &_y, int &_z)
|
||||
{
|
||||
// Select input method and return the x, y, x values
|
||||
if (WiiMapping[g_ID].Tilt.InputNC == FROM_KEYBOARD)
|
||||
TiltByKeyboard(WiiMapping[g_ID].Motion.TiltNC, 1);
|
||||
else
|
||||
TiltByGamepad(WiiMapping[g_ID].Motion.TiltNC, WiiMapping[g_ID].Tilt.InputNC);
|
||||
|
||||
// Adjust angles, it's only needed if both roll and pitch is used together
|
||||
if (WiiMapping[g_ID].Tilt.RollRange && WiiMapping[g_ID].Tilt.PitchRange)
|
||||
AdjustAngles(WiiMapping[g_ID].Motion.TiltNC.Roll, WiiMapping[g_ID].Motion.TiltNC.Pitch);
|
||||
|
||||
// Calculate the accelerometer value from this tilt angle
|
||||
TiltToAccelerometer(_x, _y, _z, WiiMapping[g_ID].Motion.TiltNC);
|
||||
|
||||
//DEBUG_LOG(WIIMOTE, "Roll:%i, Pitch:%i, _x:%u, _y:%u, _z:%u", g_NunchuckExt.TiltData.Roll, g_NunchuckExt.TiltData.Pitch, _x, _y, _z);
|
||||
}
|
||||
|
||||
/* Angles adjustment for the upside down state when both roll and pitch is
|
||||
used. When the absolute values of the angles go over 90 the Wiimote is
|
||||
upside down and these adjustments are needed. */
|
||||
void AdjustAngles(int &Roll, int &Pitch)
|
||||
{
|
||||
int OldPitch = Pitch;
|
||||
|
||||
if (abs(Roll) > 90)
|
||||
{
|
||||
if (Pitch >= 0)
|
||||
Pitch = 180 - Pitch; // 15 to 165
|
||||
else
|
||||
Pitch = -180 - Pitch; // -15 to -165
|
||||
}
|
||||
|
||||
if (abs(OldPitch) > 90)
|
||||
{
|
||||
if (Roll >= 0)
|
||||
Roll = 180 - Roll; // 15 to 165
|
||||
else
|
||||
Roll = -180 - Roll; // -15 to -165
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Angles to accelerometer values
|
||||
void TiltToAccelerometer(int &_x, int &_y, int &_z, STiltData &_TiltData)
|
||||
{
|
||||
if (_TiltData.Roll == 0 && _TiltData.Pitch == 0)
|
||||
return;
|
||||
|
||||
// We need radiands for the math functions
|
||||
float Roll = InputCommon::Deg2Rad((float)_TiltData.Roll);
|
||||
float Pitch = InputCommon::Deg2Rad((float)_TiltData.Pitch);
|
||||
// We need float values
|
||||
float x = 0.0f, y = 0.0f, z = 1.0f; // Gravity
|
||||
|
||||
// In these cases we can use the simple and accurate formula
|
||||
if(WiiMapping[g_ID].Tilt.RollRange && !WiiMapping[g_ID].Tilt.PitchRange)
|
||||
{
|
||||
x = sin(Roll);
|
||||
z = cos(Roll);
|
||||
}
|
||||
else if (WiiMapping[g_ID].Tilt.PitchRange && !WiiMapping[g_ID].Tilt.RollRange)
|
||||
{
|
||||
y = sin(Pitch);
|
||||
z = cos(Pitch);
|
||||
}
|
||||
else if(WiiMapping[g_ID].Tilt.RollRange && WiiMapping[g_ID].Tilt.PitchRange)
|
||||
{
|
||||
// ====================================================
|
||||
/* This seems to always produce the exact same combination of x, y, z
|
||||
and Roll and Pitch that the real Wiimote produce. There is an
|
||||
unlimited amount of x, y, z combinations for any combination of Roll
|
||||
and Pitch. But if we select a Z from the smallest of the absolute
|
||||
value of cos(Roll) and cos (Pitch) we get the right values. */
|
||||
// ---------
|
||||
if (fabsf(cos(Roll)) < fabsf(cos(Pitch)))
|
||||
z = cos(Roll);
|
||||
else
|
||||
z = cos(Pitch);
|
||||
/* I got these from reversing the calculation in
|
||||
PitchAccelerometerToDegree() in a math program. */
|
||||
float x_num = 2 * tanf(0.5f * Roll) * z;
|
||||
float x_den = pow2f(tanf(0.5f * Roll)) - 1;
|
||||
x = - (x_num / x_den);
|
||||
float y_num = 2 * tanf(0.5f * Pitch) * z;
|
||||
float y_den = pow2f(tanf(0.5f * Pitch)) - 1;
|
||||
y = - (y_num / y_den);
|
||||
}
|
||||
|
||||
// Multiply with neutral value and its g
|
||||
float xg = g_wm.cal_g.x;
|
||||
float yg = g_wm.cal_g.y;
|
||||
float zg = g_wm.cal_g.z;
|
||||
int ix = g_wm.cal_zero.x + (int)(xg * x);
|
||||
int iy = g_wm.cal_zero.y + (int)(yg * y);
|
||||
int iz = g_wm.cal_zero.z + (int)(zg * z);
|
||||
|
||||
if (!WiiMapping[g_ID].bUpright)
|
||||
{
|
||||
if(WiiMapping[g_ID].Tilt.RollRange) _x = ix;
|
||||
if(WiiMapping[g_ID].Tilt.PitchRange) _y = iy;
|
||||
_z = iz;
|
||||
}
|
||||
else // Upright wiimote
|
||||
{
|
||||
if(WiiMapping[g_ID].Tilt.RollRange) _x = ix;
|
||||
if(WiiMapping[g_ID].Tilt.PitchRange) _z = iy;
|
||||
_y = 0xFF - iz;
|
||||
}
|
||||
|
||||
// Direct mapping for swing, from analog stick to accelerometer
|
||||
if (!WiiMapping[g_ID].Tilt.RollRange)
|
||||
{
|
||||
_x -= _TiltData.Roll;
|
||||
}
|
||||
if (!WiiMapping[g_ID].Tilt.PitchRange)
|
||||
{
|
||||
if (!WiiMapping[g_ID].bUpright)
|
||||
_z -= _TiltData.Pitch;
|
||||
else // Upright wiimote
|
||||
_y += _TiltData.Pitch;
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate IR dot when rolling Wiimote
|
||||
void RotateIRDot(int &_x, int &_y, STiltData &_TiltData)
|
||||
{
|
||||
if (!WiiMapping[g_ID].Tilt.RollRange || !_TiltData.Roll)
|
||||
return;
|
||||
|
||||
// The IR camera resolution is 1023x767
|
||||
float dot_x = _x - 1023.0f / 2;
|
||||
float dot_y = _y - 767.0f / 2;
|
||||
|
||||
float radius = sqrt(pow(dot_x, 2) + pow(dot_y, 2));
|
||||
float radian = atan2(dot_y, dot_x);
|
||||
|
||||
_x = (int)(radius * cos(radian + InputCommon::Deg2Rad((float)_TiltData.Roll)) + 1023.0f / 2);
|
||||
_y = (int)(radius * sin(radian + InputCommon::Deg2Rad((float)_TiltData.Roll)) + 767.0f / 2);
|
||||
|
||||
// Out of sight check
|
||||
if (_x < 0 || _x > 1023) _x = 0xFFFF;
|
||||
if (_y < 0 || _y > 767) _y = 0xFFFF;
|
||||
}
|
||||
|
||||
} // WiiMoteEmu
|
||||
@@ -1,731 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "StringUtil.h" // for ArrayToString()
|
||||
#include "IniFile.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include "EmuDefinitions.h" // Local
|
||||
#include "main.h"
|
||||
#include "wiimote_hid.h"
|
||||
#include "EmuSubroutines.h"
|
||||
#include "EmuMain.h"
|
||||
#include "Encryption.h" // for extension encryption
|
||||
#include "Config.h" // for g_Config
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
// Settings
|
||||
accel_cal g_wm;
|
||||
nu_cal g_nu;
|
||||
mp_cal g_mp[2]; //fast[0] and slow[01]-motion
|
||||
cc_cal g_ClassicContCalibration;
|
||||
gh3_cal g_GH3Calibration;
|
||||
|
||||
bool g_EmulatedWiiMoteInitialized = false;
|
||||
|
||||
/* Homebrew encryption for 16 byte zero keys. */
|
||||
void CryptBuffer(u8* _buffer, u8 _size)
|
||||
{
|
||||
for (int i=0; i<_size; i++)
|
||||
{
|
||||
_buffer[i] = ((_buffer[i] - 0x17) ^ 0x17) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteCrypted16(u8* _baseBlock, u16 _address, u16 _value)
|
||||
{
|
||||
u16 cryptedValue = _value;
|
||||
CryptBuffer((u8*)&cryptedValue, sizeof(u16));
|
||||
|
||||
*(u16*)(_baseBlock + _address) = cryptedValue;
|
||||
}
|
||||
|
||||
/* Calculate Extenstion Regisister Calibration Checksum */
|
||||
// This function is not currently used, it's just here to show how the values
|
||||
// in EmuDefinitions.h are calculated.
|
||||
void GetCalibrationChecksum()
|
||||
{
|
||||
u8 sum = 0;
|
||||
for (u32 i = 0; i < sizeof(nunchuck_calibration) - 2; i++)
|
||||
sum += nunchuck_calibration[i];
|
||||
|
||||
INFO_LOG(WIIMOTE, "0x%02x 0x%02x", (sum + 0x55), (sum + 0xaa));
|
||||
}
|
||||
|
||||
// Calculate checksum for the nunchuck calibration. The last two bytes.
|
||||
void ExtensionChecksum(u8 * Calibration)
|
||||
{
|
||||
u8 sum = 0; //u8 Byte15, Byte16;
|
||||
for (u32 i = 0; i < sizeof(Calibration) - 2; i++)
|
||||
{
|
||||
sum += Calibration[i];
|
||||
//INFO_LOG(WIIMOTE, "Plus 0x%02x", Calibration[i]);
|
||||
}
|
||||
// Byte15 = sum + 0x55; // Byte 15
|
||||
// Byte16 = sum + 0xaa; // Byte 16
|
||||
}
|
||||
|
||||
/* Bit shift conversions */
|
||||
u32 convert24bit(const u8* src) {
|
||||
return (src[0] << 16) | (src[1] << 8) | src[2];
|
||||
}
|
||||
|
||||
u16 convert16bit(const u8* src) {
|
||||
return (src[0] << 8) | src[1];
|
||||
}
|
||||
|
||||
/* Load pre-recorded movements */
|
||||
void LoadRecordedMovements()
|
||||
{
|
||||
INFO_LOG(WIIMOTE, "LoadRecordedMovements()");
|
||||
|
||||
IniFile file;
|
||||
file.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "WiimoteMovement.ini").c_str());
|
||||
|
||||
for(int i = 0; i < RECORDING_ROWS; i++)
|
||||
{
|
||||
//INFO_LOG(WIIMOTE, "Recording%i ", i + 1);
|
||||
|
||||
// Temporary storage
|
||||
int iTmp;
|
||||
std::string STmp;
|
||||
|
||||
// First clear the list
|
||||
VRecording.at(i).Recording.clear();
|
||||
|
||||
// Get row name
|
||||
std::string SaveName = StringFromFormat("Recording%i", i + 1);
|
||||
|
||||
// Get movement
|
||||
std::string TmpMovement; file.Get(SaveName.c_str(), "Movement", &TmpMovement, "");
|
||||
|
||||
// Get IR
|
||||
std::string TmpIR; file.Get(SaveName.c_str(), "IR", &TmpIR, "");
|
||||
|
||||
// Get time
|
||||
std::string TmpTime; file.Get(SaveName.c_str(), "Time", &TmpTime, "");
|
||||
|
||||
// Get IR bytes
|
||||
int TmpIRBytes; file.Get(SaveName.c_str(), "IRBytes", &TmpIRBytes, 0);
|
||||
VRecording.at(i).IRBytes = TmpIRBytes;
|
||||
|
||||
SRecording Tmp;
|
||||
for (int j = 0, k = 0, l = 0; (u32)j < TmpMovement.length(); j+=13)
|
||||
{
|
||||
// Skip blank savings
|
||||
if (TmpMovement.length() < 3) continue;
|
||||
|
||||
// Avoid going to far, this can only happen with modified ini files, but we check for it anyway
|
||||
if (TmpMovement.length() < (u32)j + 12) continue;
|
||||
|
||||
// Skip old style recordings
|
||||
if (TmpMovement.substr(j, 1) != "-" && TmpMovement.substr(j, 1) != "+") continue;
|
||||
|
||||
std::string StrX = TmpMovement.substr(j, 4);
|
||||
std::string StrY = TmpMovement.substr(j + 4, 4);
|
||||
std::string StrZ = TmpMovement.substr(j + 8, 4);
|
||||
Tmp.x = atoi(StrX.c_str());
|
||||
Tmp.y = atoi(StrY.c_str());
|
||||
Tmp.z = atoi(StrZ.c_str());
|
||||
|
||||
// Go to next set of IR values
|
||||
|
||||
// If there is no IR data saving we fill the array with
|
||||
// zeroes. This should only be able to occur from manual ini
|
||||
// editing but we check for it anyway
|
||||
for(int ii = 0; ii < TmpIRBytes; ii++)
|
||||
{
|
||||
if(TmpIR.length() < (u32)(k + i + TmpIRBytes)) continue; // Safety check
|
||||
std::string TmpStr = TmpIR.substr(k + ii*2, 2);
|
||||
u32 TmpU32;
|
||||
AsciiToHex(TmpStr.c_str(), TmpU32);
|
||||
Tmp.IR[ii] = (u8)TmpU32;
|
||||
}
|
||||
if (TmpIRBytes == 10) k += (10*2 + 1); else k += (12*2 + 1);
|
||||
|
||||
// Go to next set of time values
|
||||
double Time = (double)atoi(TmpTime.substr(l, 5).c_str());
|
||||
Tmp.Time = (double)(Time/1000);
|
||||
l += 6;
|
||||
|
||||
// Save the values
|
||||
VRecording.at(i).Recording.push_back(Tmp);
|
||||
|
||||
// Log results
|
||||
/*INFO_LOG(WIIMOTE, "Time:%f", Tmp.Time);
|
||||
std::string TmpIRLog = ArrayToString(Tmp.IR, TmpIRBytes, 0, 30);
|
||||
INFO_LOG(WIIMOTE, "IR: %s", TmpIRLog.c_str());
|
||||
INFO_LOG(WIIMOTE, "");*/
|
||||
}
|
||||
|
||||
// Get HotKey
|
||||
file.Get(SaveName.c_str(), "HotKeySwitch", &iTmp, 3); VRecording.at(i).HotKeySwitch = iTmp;
|
||||
file.Get(SaveName.c_str(), "HotKeyWiimote", &iTmp, 10); VRecording.at(i).HotKeyWiimote = iTmp;
|
||||
file.Get(SaveName.c_str(), "HotKeyNunchuck", &iTmp, 10); VRecording.at(i).HotKeyNunchuck = iTmp;
|
||||
file.Get(SaveName.c_str(), "HotKeyIR", &iTmp, 10); VRecording.at(i).HotKeyIR = iTmp;
|
||||
|
||||
// Get Recording speed
|
||||
int TmpPlaybackSpeed; file.Get(SaveName.c_str(), "PlaybackSpeed", &TmpPlaybackSpeed, -1);
|
||||
VRecording.at(i).PlaybackSpeed = TmpPlaybackSpeed;
|
||||
|
||||
// Logging
|
||||
/*std::string TmpIRLog;
|
||||
if(TmpIRBytes > 0 && VRecording.size() > i)
|
||||
TmpIRLog = ArrayToString(VRecording.at(i).Recording.at(0).IR, TmpIRBytes, 0, 30);
|
||||
else
|
||||
TmpIRLog = "";
|
||||
|
||||
INFO_LOG(WIIMOTE, "Size:%i HotKey:%i PlSpeed:%i IR:%s X:%i Y:%i Z:%i",
|
||||
VRecording.at(i).Recording.size(), VRecording.at(i).HotKeyWiimote, VRecording.at(i).PlaybackSpeed,
|
||||
TmpIRLog.c_str(),
|
||||
VRecording.at(i).Recording.at(0).x, VRecording.at(i).Recording.at(0).y, VRecording.at(i).Recording.at(0).z
|
||||
);*/
|
||||
}
|
||||
}
|
||||
|
||||
/* Calibrate the mouse position to the emulation window. g_WiimoteInitialize.hWnd is the rendering window handle. */
|
||||
void GetMousePos(float& x, float& y)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
POINT point;
|
||||
// Get the cursor position for the entire screen
|
||||
GetCursorPos(&point);
|
||||
// Get the cursor position relative to the upper left corner of the rendering window
|
||||
ScreenToClient((HWND)g_WiimoteInitialize.hWnd, &point);
|
||||
|
||||
// Get the size of the rendering window. (In my case Rect.top and Rect.left was zero.)
|
||||
RECT Rect;
|
||||
GetClientRect((HWND)g_WiimoteInitialize.hWnd, &Rect);
|
||||
// Width and height is the size of the rendering window
|
||||
float WinWidth = (float)(Rect.right - Rect.left);
|
||||
float WinHeight = (float)(Rect.bottom - Rect.top);
|
||||
float XOffset = 0, YOffset = 0;
|
||||
float PictureWidth = WinWidth, PictureHeight = WinHeight;
|
||||
#else
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
float WinWidth = 0, WinHeight = 0;
|
||||
float XOffset = 0, YOffset = 0;
|
||||
int root_x, root_y, win_x, win_y;
|
||||
if (IsFocus())
|
||||
{
|
||||
Window GLWin = (Window)g_WiimoteInitialize.hWnd;
|
||||
XWindowAttributes WinAttribs;
|
||||
XGetWindowAttributes (WMdisplay, GLWin, &WinAttribs);
|
||||
WinWidth = (float)WinAttribs.width;
|
||||
WinHeight = (float)WinAttribs.height;
|
||||
Window rootDummy, childWin;
|
||||
unsigned int mask;
|
||||
XQueryPointer(WMdisplay, GLWin, &rootDummy, &childWin, &root_x, &root_y, &win_x, &win_y, &mask);
|
||||
}
|
||||
float PictureWidth = WinWidth, PictureHeight = WinHeight;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || (defined(HAVE_X11) && HAVE_X11)
|
||||
/* Calculate the actual picture size and location */
|
||||
// Output: PictureWidth, PictureHeight, XOffset, YOffset
|
||||
if (g_Config.bKeepAR43 || g_Config.bKeepAR169)
|
||||
{
|
||||
// The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio
|
||||
float Ratio = WinWidth / WinHeight / (g_Config.bKeepAR43 ? (4.0f / 3.0f) : (16.0f / 9.0f));
|
||||
|
||||
// Check if height or width is the limiting factor. If ratio > 1 the picture is to wide and have to limit the width.
|
||||
if (Ratio > 1)
|
||||
{
|
||||
// Calculate the new width and height for glViewport, this is not the actual size of either the picture or the screen
|
||||
PictureWidth = WinWidth / Ratio;
|
||||
|
||||
// Calculate the new X offset
|
||||
|
||||
// Move the left of the picture to the middle of the screen
|
||||
XOffset = XOffset + WinWidth / 2.0f;
|
||||
// Then remove half the picture height to move it to the horizontal center
|
||||
XOffset = XOffset - PictureWidth / 2.0f;
|
||||
}
|
||||
// The window is to high, we have to limit the height
|
||||
else
|
||||
{
|
||||
// Calculate the new width and height for glViewport, this is not the actual size of either the picture or the screen
|
||||
// Invert the ratio to make it > 1
|
||||
Ratio = 1.0f / Ratio;
|
||||
PictureHeight = WinHeight / Ratio;
|
||||
|
||||
// Calculate the new Y offset
|
||||
// Move the top of the picture to the middle of the screen
|
||||
YOffset = YOffset + WinHeight / 2.0f;
|
||||
// Then remove half the picture height to move it to the vertical center
|
||||
YOffset = YOffset - PictureHeight / 2.0f;
|
||||
}
|
||||
/*
|
||||
INFO_LOG(WIIMOTE, "Screen Width:%4.0f Height:%4.0f Ratio:%1.2f", WinWidth, WinHeight, Ratio);
|
||||
INFO_LOG(WIIMOTE, "Picture Width:%4.1f Height:%4.1f YOffset:%4.0f XOffset:%4.0f", PictureWidth, PictureHeight, YOffset, XOffset);
|
||||
*/
|
||||
}
|
||||
|
||||
// Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10.
|
||||
// Output: PictureWidth, PictureHeight, XOffset, YOffset
|
||||
if ((g_Config.bKeepAR43 || g_Config.bKeepAR169) && g_Config.bCrop)
|
||||
{
|
||||
float Ratio = g_Config.bKeepAR43 ? ((4.0f / 3.0f) / (5.0f / 4.0f)) : (((16.0f / 9.0f) / (16.0f / 10.0f)));
|
||||
|
||||
// The width and height we will add (calculate this before PictureWidth and PictureHeight is adjusted)
|
||||
float IncreasedWidth = (Ratio - 1.0f) * PictureWidth;
|
||||
float IncreasedHeight = (Ratio - 1.0f) * PictureHeight;
|
||||
|
||||
// The new width and height
|
||||
PictureWidth = PictureWidth * Ratio;
|
||||
PictureHeight = PictureHeight * Ratio;
|
||||
|
||||
// Adjust the X and Y offset
|
||||
XOffset = float(XOffset - (IncreasedWidth / 2.0));
|
||||
YOffset = float(YOffset - (IncreasedHeight / 2.0));
|
||||
|
||||
/*
|
||||
INFO_LOG(WIIMOTE, "Crop Ratio:%1.2f IncrWidth:%3.0f IncrHeight:%3.0f", Ratio, IncreasedWidth, IncreasedHeight);
|
||||
INFO_LOG(WIIMOTE, "Picture Width:%4.1f Height:%4.1f YOffset:%4.0f XOffset:%4.0f", PictureWidth, PictureHeight, YOffset, XOffset);
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return the mouse position as a fraction of one, inside the picture, with (0.0, 0.0) being the upper left corner of the picture
|
||||
#ifdef _WIN32
|
||||
x = ((float)point.x - XOffset) / PictureWidth;
|
||||
y = ((float)point.y - YOffset) / PictureHeight;
|
||||
|
||||
/*
|
||||
INFO_LOG(WIIMOTE, "GetCursorPos: %i %i", point.x, point.y);
|
||||
INFO_LOG(WIIMOTE, "GetClientRect: %i %i %i %i", Rect.left, Rect.right, Rect.top, Rect.bottom);
|
||||
INFO_LOG(WIIMOTE, "Position X:%1.2f Y:%1.2f", x, y);
|
||||
*/
|
||||
#else
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
x = ((float)win_x - XOffset) / PictureWidth;
|
||||
y = ((float)win_y - YOffset) / PictureHeight;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This is not needed if we call FreeLibrary() when we stop a game, but if it's
|
||||
not called we need to reset these variables. */
|
||||
void Shutdown()
|
||||
{
|
||||
INFO_LOG(WIIMOTE, "ShutDown");
|
||||
|
||||
ResetVariables();
|
||||
// We can't close it here or it might crash
|
||||
// because the joystick could have been closed already in GCPad
|
||||
// But there is no easy way to know the situation of another DLL
|
||||
// So we just skip the close procedure here
|
||||
/*
|
||||
// Close joypads
|
||||
Close_Devices();
|
||||
// Finally close SDL
|
||||
if (SDL_WasInit(0))
|
||||
SDL_Quit();
|
||||
*/
|
||||
|
||||
for (int i=0; i<MAX_WIIMOTES; i++)
|
||||
{
|
||||
if (WiiMapping[i].UDPWM.instance)
|
||||
delete WiiMapping[i].UDPWM.instance;
|
||||
}
|
||||
|
||||
g_SearchDeviceDone = false;
|
||||
}
|
||||
|
||||
// Start emulation
|
||||
void Initialize()
|
||||
{
|
||||
INFO_LOG(WIIMOTE, "Initialize");
|
||||
|
||||
// Reset variables
|
||||
ResetVariables();
|
||||
|
||||
/* Populate joyinfo for all attached devices and do g_Config.Load() if the
|
||||
configuration window is not already open, if it's already open we
|
||||
continue with the settings we have */
|
||||
if(!g_SearchDeviceDone)
|
||||
{
|
||||
g_Config.Load();
|
||||
Search_Devices(joyinfo, NumPads, NumGoodPads);
|
||||
g_SearchDeviceDone = true;
|
||||
}
|
||||
|
||||
InitCalibration();
|
||||
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
// Write default Eeprom data to g_Eeprom[], this may be overwritten by
|
||||
// WiiMoteReal::Initialize() after this function.
|
||||
memset(g_Eeprom[i], 0, WIIMOTE_EEPROM_SIZE);
|
||||
memcpy(g_Eeprom[i], EepromData_0, sizeof(EepromData_0));
|
||||
memcpy(g_Eeprom[i] + 0x16D0, EepromData_16D0, sizeof(EepromData_16D0));
|
||||
// Copy extension id and calibration to its register, g_Config.Load() is needed before this
|
||||
UpdateExtRegisterBlocks(i);
|
||||
if (WiiMapping[i].UDPWM.enable)
|
||||
WiiMapping[i].UDPWM.instance=new UDPWiimote(WiiMapping[i].UDPWM.port);
|
||||
else
|
||||
WiiMapping[i].UDPWM.instance=NULL;
|
||||
}
|
||||
|
||||
// The emulated Wiimote is initialized
|
||||
g_EmulatedWiiMoteInitialized = true;
|
||||
|
||||
// Load pre-recorded movements
|
||||
LoadRecordedMovements();
|
||||
|
||||
/* The Nuncheck extension ID for homebrew applications that use the zero
|
||||
key. This writes 0x0000 in encrypted form (0xfefe) to 0xfe in the
|
||||
extension register. */
|
||||
//WriteCrypted16(g_RegExt, 0xfe, 0x0000); // Fully inserted Nunchuk
|
||||
|
||||
// I forgot what these were for? Is this the zero key encrypted 0xa420?
|
||||
// g_RegExt[0xfd] = 0x1e;
|
||||
// g_RegExt[0xfc] = 0x9a;
|
||||
}
|
||||
|
||||
// Set initial valuesm this done both in Init and Shutdown
|
||||
void ResetVariables()
|
||||
{
|
||||
g_EmulatedWiiMoteInitialized = false;
|
||||
|
||||
g_ID = 0;
|
||||
g_Encryption = false;
|
||||
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
g_ReportingAuto[i] = false;
|
||||
g_MotionPlusLastWriteReg[i] = 0;
|
||||
g_InterleavedData[i] = false;
|
||||
g_ReportingMode[i] = 0;
|
||||
g_ReportingChannel[i] = 0;
|
||||
WiiMapping[i].Motion.TiltWM.Shake = 0;
|
||||
WiiMapping[i].Motion.TiltWM.Roll = 0;
|
||||
WiiMapping[i].Motion.TiltWM.Pitch = 0;
|
||||
WiiMapping[i].Motion.TiltNC.Shake = 0;
|
||||
WiiMapping[i].Motion.TiltNC.Roll = 0;
|
||||
WiiMapping[i].Motion.TiltNC.Pitch = 0;
|
||||
}
|
||||
|
||||
// Set default recording values
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
g_RecordingPlaying[i] = -1;
|
||||
g_RecordingCounter[i] = 0;
|
||||
g_RecordingPoint[i] = 0;
|
||||
g_RecordingStart[i] = 0;
|
||||
g_RecordingCurrentTime[i] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Initiate the accelerometer neutral values
|
||||
void InitCalibration()
|
||||
{
|
||||
g_wm.cal_zero.x = EepromData_0[22];
|
||||
g_wm.cal_zero.y = EepromData_0[23];
|
||||
g_wm.cal_zero.z = EepromData_0[24];
|
||||
g_wm.cal_g.x = EepromData_0[26] - EepromData_0[22];
|
||||
g_wm.cal_g.y = EepromData_0[27] - EepromData_0[23];
|
||||
g_wm.cal_g.z = EepromData_0[28] - EepromData_0[24];
|
||||
|
||||
g_nu.cal_zero.x = nunchuck_calibration[0x00];
|
||||
g_nu.cal_zero.y = nunchuck_calibration[0x01];
|
||||
g_nu.cal_zero.z = nunchuck_calibration[0x02];
|
||||
g_nu.cal_g.x = nunchuck_calibration[0x04] - nunchuck_calibration[0x00];
|
||||
g_nu.cal_g.y = nunchuck_calibration[0x05] - nunchuck_calibration[0x01];
|
||||
g_nu.cal_g.z = nunchuck_calibration[0x06] - nunchuck_calibration[0x02];
|
||||
|
||||
g_mp[0].cal_zero.x = ((motion_plus_calibration[0x00]<<6) + (motion_plus_calibration[0x01]>>2));
|
||||
g_mp[0].cal_zero.y = ((motion_plus_calibration[0x02]<<6) + (motion_plus_calibration[0x03]>>2));
|
||||
g_mp[0].cal_zero.z = ((motion_plus_calibration[0x04]<<6) + (motion_plus_calibration[0x05]>>2));
|
||||
g_mp[1].cal_zero.x = ((motion_plus_calibration[0x10]<<6) + (motion_plus_calibration[0x11]>>2));
|
||||
g_mp[1].cal_zero.y = ((motion_plus_calibration[0x12]<<6) + (motion_plus_calibration[0x13]>>2));
|
||||
g_mp[1].cal_zero.z = ((motion_plus_calibration[0x14]<<6) + (motion_plus_calibration[0x15]>>2));
|
||||
|
||||
g_nu.jx.max = nunchuck_calibration[0x08];
|
||||
g_nu.jx.min = nunchuck_calibration[0x09];
|
||||
g_nu.jx.center = nunchuck_calibration[0x0a];
|
||||
g_nu.jy.max = nunchuck_calibration[0x0b];
|
||||
g_nu.jy.min = nunchuck_calibration[0x0c];
|
||||
g_nu.jy.center = nunchuck_calibration[0x0d];
|
||||
|
||||
g_ClassicContCalibration.Lx.max = classic_calibration[0x00];
|
||||
g_ClassicContCalibration.Lx.min = classic_calibration[0x01];
|
||||
g_ClassicContCalibration.Lx.center = classic_calibration[0x02];
|
||||
g_ClassicContCalibration.Ly.max = classic_calibration[0x03];
|
||||
g_ClassicContCalibration.Ly.min = classic_calibration[0x04];
|
||||
g_ClassicContCalibration.Ly.center = classic_calibration[0x05];
|
||||
|
||||
g_ClassicContCalibration.Rx.max = classic_calibration[0x06];
|
||||
g_ClassicContCalibration.Rx.min = classic_calibration[0x07];
|
||||
g_ClassicContCalibration.Rx.center = classic_calibration[0x08];
|
||||
g_ClassicContCalibration.Ry.max = classic_calibration[0x09];
|
||||
g_ClassicContCalibration.Ry.min = classic_calibration[0x0a];
|
||||
g_ClassicContCalibration.Ry.center = classic_calibration[0x0b];
|
||||
|
||||
g_ClassicContCalibration.Tl.neutral = classic_calibration[0x0c];
|
||||
g_ClassicContCalibration.Tr.neutral = classic_calibration[0x0d];
|
||||
|
||||
// TODO get the correct values here
|
||||
g_GH3Calibration.Lx.max = classic_calibration[0x00];
|
||||
g_GH3Calibration.Lx.min = classic_calibration[0x01];
|
||||
g_GH3Calibration.Lx.center = classic_calibration[0x02];
|
||||
g_GH3Calibration.Ly.max = classic_calibration[0x03];
|
||||
g_GH3Calibration.Ly.min = classic_calibration[0x04];
|
||||
g_GH3Calibration.Ly.center = classic_calibration[0x05];
|
||||
}
|
||||
|
||||
// Update the extension calibration values with our default values
|
||||
void UpdateExtRegisterBlocks(int Slot)
|
||||
{
|
||||
if (WiiMapping[Slot].bMotionPlusConnected)
|
||||
{
|
||||
// Copy extension id and calibration to its register
|
||||
if (WiiMapping[Slot].iExtensionConnected == EXT_NONE)
|
||||
{
|
||||
memset(g_RegExt[Slot],0,sizeof(g_RegExt[0]));
|
||||
memcpy(g_RegExt[Slot] + 0x20, motion_plus_calibration, sizeof(motion_plus_calibration));
|
||||
memset(g_RegExt[Slot] + 0x40, 0xFF, sizeof(nunchuck_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0x50, motionplus_accel_gyro_syncing, sizeof(motionplus_accel_gyro_syncing));
|
||||
memcpy(g_RegExt[Slot] + 0xf0, motionplus_activeflags, sizeof(motionplus_activeflags));
|
||||
memcpy(g_RegExt[Slot] + 0xfa, motionplus_id, sizeof(motionplus_id));
|
||||
|
||||
}
|
||||
else if(WiiMapping[Slot].iExtensionConnected == EXT_NUNCHUK)
|
||||
{
|
||||
|
||||
memset(g_RegExt[Slot],0,sizeof(g_RegExt[0]));
|
||||
memset(g_RegMotionPlus[Slot],0,sizeof(g_RegMotionPlus[0]));
|
||||
memcpy(g_RegExt[Slot] + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0x30, nunchuck_calibration, sizeof(nunchuck_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0xfa, nunchuck_id, sizeof(nunchuck_id));
|
||||
memcpy(g_RegMotionPlus[Slot] + 0x20, motion_plus_calibration, sizeof(motion_plus_calibration));
|
||||
memcpy(g_RegMotionPlus[Slot] + 0x40, nunchuck_calibration, sizeof(nunchuck_calibration));
|
||||
memcpy(g_RegMotionPlus[Slot] + 0x50, motionplus_accel_gyro_syncing, sizeof(motionplus_accel_gyro_syncing));
|
||||
memcpy(g_RegMotionPlus[Slot] + 0xf0, motionplus_activeflags, sizeof(motionplus_activeflags));
|
||||
memcpy(g_RegMotionPlus[Slot] + 0xfa, motionplusnunchuk_id, sizeof(motionplusnunchuk_id));
|
||||
|
||||
}
|
||||
g_MotionPlus[Slot] = (WiiMapping[Slot].iExtensionConnected) ? 0 : 1;
|
||||
|
||||
} else
|
||||
{
|
||||
|
||||
// Copy extension id and calibration to its register
|
||||
if(WiiMapping[Slot].iExtensionConnected == EXT_NUNCHUK)
|
||||
{
|
||||
memcpy(g_RegExt[Slot] + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0x30, nunchuck_calibration, sizeof(nunchuck_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0xfa, nunchuck_id, sizeof(nunchuck_id));
|
||||
}
|
||||
else if(WiiMapping[Slot].iExtensionConnected == EXT_CLASSIC_CONTROLLER)
|
||||
{
|
||||
memcpy(g_RegExt[Slot] + 0x20, classic_calibration, sizeof(classic_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0x30, classic_calibration, sizeof(classic_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0xfa, classic_id, sizeof(classic_id));
|
||||
}
|
||||
else if(WiiMapping[Slot].iExtensionConnected == EXT_GUITARHERO)
|
||||
{
|
||||
// TODO get the correct values here
|
||||
memcpy(g_RegExt[Slot] + 0x20, classic_calibration, sizeof(classic_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0x30, classic_calibration, sizeof(classic_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0xfa, gh3glp_id, sizeof(gh3glp_id));
|
||||
}
|
||||
else if(WiiMapping[Slot].iExtensionConnected == EXT_WBB)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG(WIIMOTE, "UpdateExtRegisterBlocks()");
|
||||
}
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
// TODO: Shorten the list
|
||||
p.DoArray(&g_Eeprom[0][0], WIIMOTE_EEPROM_SIZE * MAX_WIIMOTES);
|
||||
p.DoArray(&g_RegExt[0][0], WIIMOTE_REG_EXT_SIZE * MAX_WIIMOTES);
|
||||
p.DoArray(&g_RegMotionPlus[0][0], WIIMOTE_REG_EXT_SIZE * MAX_WIIMOTES);
|
||||
p.DoArray(&g_RegSpeaker[0][0], WIIMOTE_REG_SPEAKER_SIZE * MAX_WIIMOTES);
|
||||
p.DoArray(&g_RegIr[0][0], WIIMOTE_REG_IR_SIZE * MAX_WIIMOTES);
|
||||
//p.DoArray(g_RegExtTmp, WIIMOTE_REG_EXT_SIZE);
|
||||
|
||||
p.Do(g_Encryption);
|
||||
|
||||
//p.Do(NumPads);
|
||||
//p.Do(NumGoodPads);
|
||||
//p.Do(joyinfo);
|
||||
//p.DoArray(PadState, 4);
|
||||
//p.DoArray(PadMapping, 4);
|
||||
//p.Do(g_Wiimote_kbd);
|
||||
//p.Do(g_NunchuckExt);
|
||||
//p.Do(g_ClassicContExt);
|
||||
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
p.Do(g_ReportingAuto[i]);
|
||||
p.Do(g_ReportingMode[i]);
|
||||
p.Do(g_ReportingChannel[i]);
|
||||
//p.Do(g_IRClock[i]);
|
||||
p.Do(g_IR[i]);
|
||||
p.Do(g_Leds[i]);
|
||||
p.Do(g_Speaker[i]);
|
||||
//p.Do(g_MotionPlus[i]);
|
||||
//p.Do(g_SpeakerMute[i]);
|
||||
p.Do(g_ExtKey[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* This function produce Wiimote Input, i.e. reports from the Wiimote in
|
||||
response to Output from the Wii. */
|
||||
void InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
g_ID = _number;
|
||||
|
||||
hid_packet* hidp = (hid_packet*)_pData;
|
||||
|
||||
INFO_LOG(WIIMOTE, "Emu InterruptChannel (page: %i, type: 0x%02x, param: 0x%02x)", _number, hidp->type, hidp->param);
|
||||
|
||||
switch(hidp->type)
|
||||
{
|
||||
case HID_TYPE_DATA:
|
||||
{
|
||||
switch(hidp->param)
|
||||
{
|
||||
case HID_PARAM_OUTPUT:
|
||||
{
|
||||
wm_report* sr = (wm_report*)hidp->data;
|
||||
HidOutputReport(_channelID, sr);
|
||||
|
||||
/* This is the 0x22 answer to all Inputs.*/
|
||||
|
||||
// There are no 0x22 replys to these report from the real
|
||||
// wiimote from what I could see Report 0x10 that seems to
|
||||
// be only used for rumble, and we don't need to answer
|
||||
// that
|
||||
|
||||
// The rumble report still needs more investigation
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PanicAlert("HidInput: HID_TYPE_DATA - param 0x%02x", hidp->type, hidp->param);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PanicAlert("HidInput: Unknown type 0x%02x and param 0x%02x", hidp->type, hidp->param);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
g_ID = _number;
|
||||
|
||||
hid_packet* hidp = (hid_packet*)_pData;
|
||||
|
||||
INFO_LOG(WIIMOTE, "Emu ControlChannel (page: %i, type: 0x%02x, param: 0x%02x)", _number, hidp->type, hidp->param);
|
||||
|
||||
switch(hidp->type)
|
||||
{
|
||||
case HID_TYPE_HANDSHAKE:
|
||||
PanicAlert("HID_TYPE_HANDSHAKE - %s", (hidp->param == HID_PARAM_INPUT) ? "INPUT" : "OUPUT");
|
||||
break;
|
||||
|
||||
case HID_TYPE_SET_REPORT:
|
||||
if (hidp->param == HID_PARAM_INPUT)
|
||||
{
|
||||
PanicAlert("HID_TYPE_SET_REPORT - INPUT");
|
||||
}
|
||||
else
|
||||
{
|
||||
// AyuanX: My experiment shows Control Channel is never used
|
||||
// shuffle2: but lwbt uses this, so we'll do what we must :)
|
||||
HidOutputReport(_channelID, (wm_report*)hidp->data);
|
||||
|
||||
u8 handshake = HID_HANDSHAKE_SUCCESS;
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(g_ID, _channelID, &handshake, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_TYPE_DATA:
|
||||
PanicAlert("HID_TYPE_DATA - %s", (hidp->param == HID_PARAM_INPUT) ? "INPUT" : "OUTPUT");
|
||||
break;
|
||||
|
||||
default:
|
||||
PanicAlert("HidControlChannel: Unknown type %x and param %x", hidp->type, hidp->param);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* This is called from Wiimote_Update(). See SystemTimers.cpp for a
|
||||
documentation. I'm not sure exactly how often this function is called but I
|
||||
think it's tied to the frame rate of the game rather than a certain amount
|
||||
of times per second. */
|
||||
void Update(int _number)
|
||||
{
|
||||
if (g_ReportingAuto[_number] == false)
|
||||
return;
|
||||
|
||||
g_ID = _number;
|
||||
|
||||
// Read input or not
|
||||
if (WiiMapping[g_ID].Source == 1)
|
||||
{
|
||||
// Check if the pad state should be updated
|
||||
if (NumGoodPads > 0 && joyinfo.size() > (u32)WiiMapping[g_ID].ID)
|
||||
UpdatePadState(WiiMapping[g_ID]);
|
||||
}
|
||||
|
||||
switch(g_ReportingMode[g_ID])
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case WM_REPORT_CORE:
|
||||
SendReportCore(g_ReportingChannel[g_ID]);
|
||||
break;
|
||||
case WM_REPORT_CORE_ACCEL:
|
||||
SendReportCoreAccel(g_ReportingChannel[g_ID]);
|
||||
break;
|
||||
case WM_REPORT_CORE_ACCEL_IR12:
|
||||
SendReportCoreAccelIr12(g_ReportingChannel[g_ID]);
|
||||
break;
|
||||
case WM_REPORT_CORE_ACCEL_EXT16:
|
||||
SendReportCoreAccelExt16(g_ReportingChannel[g_ID]);
|
||||
break;
|
||||
case WM_REPORT_CORE_ACCEL_IR10_EXT6:
|
||||
SendReportCoreAccelIr10Ext(g_ReportingChannel[g_ID]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // end of namespace
|
||||
@@ -1,89 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef WIIMOTE_EMU_H
|
||||
#define WIIMOTE_EMU_H
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "wiimote_hid.h"
|
||||
#include "EmuDefinitions.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
// TODO: those are only used with Emulated wiimote.
|
||||
// if it were a class, we didn't need the extern here.
|
||||
// Settings
|
||||
extern accel_cal g_wm;
|
||||
extern nu_cal g_nu;
|
||||
extern mp_cal g_mp[2];
|
||||
extern cc_cal g_ClassicContCalibration;
|
||||
extern gh3_cal g_GH3Calibration;
|
||||
|
||||
u32 convert24bit(const u8* src);
|
||||
u16 convert16bit(const u8* src);
|
||||
|
||||
// General functions
|
||||
void ResetVariables();
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
void InitCalibration();
|
||||
void UpdateExtRegisterBlocks(int Slot);
|
||||
|
||||
void InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size);
|
||||
void ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size) ;
|
||||
void Update(int _number);
|
||||
void DoState(PointerWrap &p);
|
||||
bool IsKey(int Key);
|
||||
|
||||
// Recordings
|
||||
void LoadRecordedMovements();
|
||||
void GetMousePos(float& x, float& y);
|
||||
|
||||
// Gamepad
|
||||
void Close_Devices();
|
||||
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads);
|
||||
void GetAxisState(CONTROLLER_MAPPING_WII &_WiiMapping);
|
||||
void UpdatePadState(CONTROLLER_MAPPING_WII &_WiiMapping);
|
||||
|
||||
void TiltWiimote(int &_x, int &_y, int &_z);
|
||||
void TiltNunchuck(int &_x, int &_y, int &_z);
|
||||
void ShakeToAccelerometer(int &_x, int &_y, int &_z, STiltData &_TiltData);
|
||||
void TiltToAccelerometer(int &_x, int &_y, int &_z, STiltData &_TiltData);
|
||||
void AdjustAngles(int &Roll, int &Pitch);
|
||||
void RotateIRDot(int &_x, int &_y, STiltData &_TiltData);
|
||||
|
||||
// Accelerometer
|
||||
//void PitchAccelerometerToDegree(u8 _x, u8 _y, u8 _z, int &_Roll, int &_Pitch, int&, int&);
|
||||
//float AccelerometerToG(float Current, float Neutral, float G);
|
||||
|
||||
// IR data
|
||||
//void IRData2Dots(u8 *Data);
|
||||
//void IRData2DotsBasic(u8 *Data);
|
||||
//void ReorderIRDots();
|
||||
//void IRData2Distance();
|
||||
|
||||
// Classic Controller data
|
||||
//std::string CCData2Values(u8 *Data);
|
||||
|
||||
}; // WiiMoteEmu
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,209 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "StringUtil.h" // for ArrayToString()
|
||||
#include "IniFile.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include "EmuDefinitions.h" // Local
|
||||
#include "main.h"
|
||||
#include "wiimote_hid.h"
|
||||
#include "EmuSubroutines.h"
|
||||
#include "EmuMain.h"
|
||||
#include "Encryption.h" // for extension encryption
|
||||
#include "Config.h" // for g_Config
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "XInput.h"
|
||||
#endif
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
extern void PAD_RumbleClose();
|
||||
|
||||
// Close joypads
|
||||
void Close_Devices()
|
||||
{
|
||||
PAD_RumbleClose();
|
||||
// Close all devices carefully. We must check that we are not accessing any
|
||||
// undefined vector elements or any bad devices
|
||||
if (SDL_WasInit(0))
|
||||
{
|
||||
for (int i = 0; i < NumPads; i++)
|
||||
{
|
||||
if (joyinfo.at(i).joy)
|
||||
{
|
||||
if(SDL_JoystickOpened(i))
|
||||
{
|
||||
INFO_LOG(WIIMOTE, "Shut down Joypad: %i", i);
|
||||
SDL_JoystickClose(joyinfo.at(i).joy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
WiiMapping[i].joy = NULL;
|
||||
|
||||
// Clear the physical device info
|
||||
joyinfo.clear();
|
||||
NumPads = 0;
|
||||
NumGoodPads = 0;
|
||||
}
|
||||
|
||||
// Fill joyinfo with the current connected devices
|
||||
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads)
|
||||
{
|
||||
// Close opened pad first
|
||||
Close_Devices();
|
||||
|
||||
bool WasGotten = InputCommon::SearchDevices(_joyinfo, _NumPads, _NumGoodPads);
|
||||
|
||||
if (_NumGoodPads == 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
if (_NumPads > WiiMapping[i].ID)
|
||||
if(_joyinfo.at(WiiMapping[i].ID).Good)
|
||||
{
|
||||
WiiMapping[i].joy = _joyinfo.at(WiiMapping[i].ID).joy;
|
||||
#ifdef _WIN32
|
||||
XINPUT_STATE xstate;
|
||||
DWORD xresult = XInputGetState(WiiMapping[i].ID, &xstate);
|
||||
if (xresult == ERROR_SUCCESS)
|
||||
WiiMapping[i].TriggerType = InputCommon::CTL_TRIGGER_XINPUT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return WasGotten;
|
||||
}
|
||||
|
||||
|
||||
// Request joystick state
|
||||
/* Called from: PAD_GetStatus() Input: The virtual device 0, 1, 2 or 3
|
||||
Function: Updates the PadState struct with the current pad status. The input
|
||||
value "controller" is for a virtual controller 0 to 3. */
|
||||
void GetAxisState(CONTROLLER_MAPPING_WII &_WiiMapping)
|
||||
{
|
||||
// Update the gamepad status
|
||||
SDL_JoystickUpdate();
|
||||
|
||||
// Update axis states. It doesn't hurt much if we happen to ask for nonexisting axises here.
|
||||
_WiiMapping.AxisState.Lx = SDL_JoystickGetAxis(_WiiMapping.joy, _WiiMapping.AxisMapping.Lx);
|
||||
_WiiMapping.AxisState.Ly = SDL_JoystickGetAxis(_WiiMapping.joy, _WiiMapping.AxisMapping.Ly);
|
||||
_WiiMapping.AxisState.Rx = SDL_JoystickGetAxis(_WiiMapping.joy, _WiiMapping.AxisMapping.Rx);
|
||||
_WiiMapping.AxisState.Ry = SDL_JoystickGetAxis(_WiiMapping.joy, _WiiMapping.AxisMapping.Ry);
|
||||
|
||||
// Update the analog trigger axis values
|
||||
#ifdef _WIN32
|
||||
if (_WiiMapping.TriggerType == InputCommon::CTL_TRIGGER_SDL)
|
||||
{
|
||||
#endif
|
||||
// If we are using SDL analog triggers the buttons have to be mapped as 1000 or up, otherwise they are not used
|
||||
// We must also check that we are not asking for a negative axis number because SDL_JoystickGetAxis() has
|
||||
// no good way of handling that
|
||||
if ((_WiiMapping.AxisMapping.Tl - 1000) >= 0)
|
||||
_WiiMapping.AxisState.Tl = SDL_JoystickGetAxis(_WiiMapping.joy, _WiiMapping.AxisMapping.Tl - 1000);
|
||||
if ((_WiiMapping.AxisMapping.Tr - 1000) >= 0)
|
||||
_WiiMapping.AxisState.Tr = SDL_JoystickGetAxis(_WiiMapping.joy, _WiiMapping.AxisMapping.Tr - 1000);
|
||||
#ifdef _WIN32
|
||||
}
|
||||
else
|
||||
{
|
||||
_WiiMapping.AxisState.Tl = XInput::GetXI(_WiiMapping.ID, _WiiMapping.AxisMapping.Tl - 1000);
|
||||
_WiiMapping.AxisState.Tr = XInput::GetXI(_WiiMapping.ID, _WiiMapping.AxisMapping.Tr - 1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Debugging
|
||||
// Console::ClearScreen();
|
||||
DEBUG_LOG(CONSOLE,
|
||||
"Controller and handle: %i %i\n"
|
||||
|
||||
"Triggers:%i %i %i %i %i\n"
|
||||
|
||||
"Analog:%06i %06i \n",
|
||||
|
||||
controller, (int)_PadState.joy,
|
||||
|
||||
_PadMapping.triggertype,
|
||||
_PadMapping.Axis.Tl, _PadMapping.Axis.Tr,
|
||||
_PadState.Axis.Tl, _PadState.Axis.Tr,
|
||||
|
||||
_PadState.Axis.Lx, _PadState.Axis.Ly
|
||||
);*/
|
||||
}
|
||||
|
||||
void UpdatePadState(CONTROLLER_MAPPING_WII &_WiiMapping)
|
||||
{
|
||||
// Return if we have no pads
|
||||
if (NumGoodPads == 0) return;
|
||||
|
||||
GetAxisState(_WiiMapping);
|
||||
|
||||
int &Lx = _WiiMapping.AxisState.Lx;
|
||||
int &Ly = _WiiMapping.AxisState.Ly;
|
||||
int &Rx = _WiiMapping.AxisState.Rx;
|
||||
int &Ry = _WiiMapping.AxisState.Ry;
|
||||
int &Tl = _WiiMapping.AxisState.Tl;
|
||||
int &Tr = _WiiMapping.AxisState.Tr;
|
||||
|
||||
// Check the circle to square option
|
||||
if(_WiiMapping.bCircle2Square)
|
||||
{
|
||||
InputCommon::Square2Circle(Lx, Ly, _WiiMapping.Diagonal, true);
|
||||
InputCommon::Square2Circle(Rx, Ry, _WiiMapping.Diagonal, true);
|
||||
}
|
||||
|
||||
// Dead zone adjustment
|
||||
float DeadZoneLeft = (float)_WiiMapping.DeadZoneL / 100.0f;
|
||||
float DeadZoneRight = (float)_WiiMapping.DeadZoneR / 100.0f;
|
||||
if (InputCommon::IsDeadZone(DeadZoneLeft, Lx, Ly))
|
||||
{
|
||||
Lx = 0;
|
||||
Ly = 0;
|
||||
}
|
||||
if (InputCommon::IsDeadZone(DeadZoneRight, Rx, Ry))
|
||||
{
|
||||
Rx = 0;
|
||||
Ry = 0;
|
||||
}
|
||||
|
||||
// Downsize the values from 0x8000 to 0x80
|
||||
Lx = InputCommon::Pad_Convert(Lx);
|
||||
Ly = InputCommon::Pad_Convert(Ly);
|
||||
Rx = InputCommon::Pad_Convert(Rx);
|
||||
Ry = InputCommon::Pad_Convert(Ry);
|
||||
// The XInput range is already 0 to 0x80
|
||||
if (_WiiMapping.TriggerType == InputCommon::CTL_TRIGGER_SDL)
|
||||
{
|
||||
Tl = InputCommon::Pad_Convert(Tl);
|
||||
Tr = InputCommon::Pad_Convert(Tr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end of namespace WiiMoteEmu
|
||||
@@ -1,717 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
/* HID reports access guide. */
|
||||
|
||||
/* 0x10 - 0x1a Output EmuMain.cpp: HidOutputReport()
|
||||
0x10 - 0x14: General
|
||||
0x15: Status report request from the Wii
|
||||
0x16 and 0x17: Write and read memory or registers
|
||||
0x19 and 0x1a: General
|
||||
0x20 - 0x22 Input EmuMain.cpp: HidOutputReport() to the destination
|
||||
0x15 leads to a 0x20 Input report
|
||||
0x17 leads to a 0x21 Input report
|
||||
0x10 - 0x1a leads to a 0x22 Input report
|
||||
0x30 - 0x3f Input This file: Update() */
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "StringUtil.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include "EmuMain.h" // Local
|
||||
#include "EmuSubroutines.h"
|
||||
#include "Config.h" // for g_Config
|
||||
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
extern void PAD_Rumble(u8 _numPAD, unsigned int _uType);
|
||||
|
||||
/* Here we process the Output Reports that the Wii sends. Our response will be
|
||||
an Input Report back to the Wii. Input and Output is from the Wii's
|
||||
perspective, Output means data to the Wiimote (from the Wii), Input means
|
||||
data from the Wiimote.
|
||||
|
||||
The call browser:
|
||||
|
||||
1. Wiimote_InterruptChannel > InterruptChannel > HidOutputReport
|
||||
2. Wiimote_ControlChannel > ControlChannel > HidOutputReport
|
||||
|
||||
The IR enable/disable and speaker enable/disable and mute/unmute values are
|
||||
bit2: 0 = Disable (0x02), 1 = Enable (0x06)
|
||||
*/
|
||||
void HidOutputReport(u16 _channelID, wm_report* sr)
|
||||
{
|
||||
INFO_LOG(WIIMOTE, "HidOutputReport (page: %i, cid: 0x%02x, wm: 0x%02x)", g_ID, _channelID, sr->wm);
|
||||
|
||||
switch(sr->wm)
|
||||
{
|
||||
case WM_RUMBLE: // 0x10
|
||||
PAD_Rumble(g_ID, sr->data[0]);
|
||||
break;
|
||||
|
||||
case WM_LEDS: // 0x11
|
||||
INFO_LOG(WIIMOTE, "Set LEDs: 0x%02x", sr->data[0]);
|
||||
g_Leds[g_ID] = sr->data[0] >> 4;
|
||||
break;
|
||||
|
||||
case WM_REPORT_MODE: // 0x12
|
||||
WmReportMode(_channelID, (wm_report_mode*)sr->data);
|
||||
break;
|
||||
|
||||
case WM_IR_PIXEL_CLOCK: // 0x13
|
||||
INFO_LOG(WIIMOTE, "WM IR Clock: 0x%02x", sr->data[0]);
|
||||
//g_IRClock[g_ID] = (sr->data[0] & 0x04) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case WM_SPEAKER_ENABLE: // 0x14
|
||||
INFO_LOG(WIIMOTE, "WM Speaker Enable: 0x%02x", sr->data[0]);
|
||||
g_Speaker[g_ID] = (sr->data[0] & 0x04) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case WM_REQUEST_STATUS: // 0x15
|
||||
WmRequestStatus(_channelID, (wm_request_status*)sr->data);
|
||||
break;
|
||||
|
||||
case WM_WRITE_DATA: // 0x16
|
||||
WmWriteData(_channelID, (wm_write_data*)sr->data);
|
||||
break;
|
||||
|
||||
case WM_READ_DATA: // 0x17
|
||||
WmReadData(_channelID, (wm_read_data*)sr->data);
|
||||
break;
|
||||
|
||||
case WM_WRITE_SPEAKER_DATA: // 0x18
|
||||
// TODO: Does this need an ack?
|
||||
break;
|
||||
|
||||
case WM_SPEAKER_MUTE: // 0x19
|
||||
INFO_LOG(WIIMOTE, "WM Speaker Mute: 0x%02x", sr->data[0]);
|
||||
//g_SpeakerMute[g_ID] = (sr->data[0] & 0x04) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case WM_IR_LOGIC: // 0x1a
|
||||
// This enables or disables the IR lights, we update the global variable g_IR
|
||||
// so that WmRequestStatus() knows about it
|
||||
INFO_LOG(WIIMOTE, "WM IR Enable: 0x%02x", sr->data[0]);
|
||||
g_IR[g_ID] = (sr->data[0] & 0x04) ? 1 : 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->wm);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send general feedback except the following types
|
||||
// as these ones generate their own feedbacks
|
||||
// or don't send feedbacks
|
||||
if ((sr->wm != WM_RUMBLE)
|
||||
&& (sr->wm != WM_READ_DATA)
|
||||
&& (sr->wm != WM_REQUEST_STATUS)
|
||||
&& (sr->wm != WM_WRITE_SPEAKER_DATA)
|
||||
)
|
||||
{
|
||||
WmSendAck(_channelID, sr->wm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Generate the right header for wm reports. The returned values is the length
|
||||
of the header before the data begins. It's always two for all reports 0x20 -
|
||||
0x22, 0x30 - 0x37 */
|
||||
int WriteWmReportHdr(u8* dst, u8 wm)
|
||||
{
|
||||
// Update the first byte to 0xa1
|
||||
u32 Offset = 0;
|
||||
hid_packet* pHidHeader = (hid_packet*)dst;
|
||||
Offset += sizeof(hid_packet);
|
||||
pHidHeader->type = HID_TYPE_DATA;
|
||||
pHidHeader->param = HID_PARAM_INPUT;
|
||||
|
||||
// Update the second byte to the current report type 0x20 - 0x22, 0x30 - 0x37
|
||||
wm_report* pReport = (wm_report*)(dst + Offset);
|
||||
Offset += sizeof(wm_report);
|
||||
pReport->wm = wm;
|
||||
return Offset;
|
||||
}
|
||||
|
||||
/* This will generate the 0x22 acknowledgement for most Input reports.
|
||||
It has the form of "a1 22 00 00 _reportID 00".
|
||||
The first two bytes are the core buttons data,
|
||||
00 00 means nothing is pressed.
|
||||
The last byte is the success code 00. */
|
||||
void WmSendAck(u16 _channelID, u8 _reportID)
|
||||
{
|
||||
u8 DataFrame[1024];
|
||||
// Write DataFrame header
|
||||
u32 Offset = WriteWmReportHdr(DataFrame, WM_ACK_DATA);
|
||||
wm_acknowledge* pData = (wm_acknowledge*)(DataFrame + Offset);
|
||||
memset(pData, 0, sizeof(wm_acknowledge));
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
FillReportInfo(pData->buttons);
|
||||
#endif
|
||||
pData->reportID = _reportID;
|
||||
pData->errorID = 0;
|
||||
Offset += sizeof(wm_acknowledge);
|
||||
|
||||
DEBUG_LOG(WIIMOTE, "WMSendAck");
|
||||
DEBUG_LOG(WIIMOTE, " Report ID: %02x", _reportID);
|
||||
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(g_ID, _channelID, DataFrame, Offset);
|
||||
}
|
||||
|
||||
|
||||
/* Read data from Wiimote and Extensions registers. */
|
||||
void WmReadData(u16 _channelID, wm_read_data* rd)
|
||||
{
|
||||
u32 address = convert24bit(rd->address);
|
||||
u16 size = convert16bit(rd->size);
|
||||
u8 addressHI = (address >> 16) & 0xFE;
|
||||
INFO_LOG(WIIMOTE, "Read data");
|
||||
DEBUG_LOG(WIIMOTE, " Read data Space: %x", rd->space);
|
||||
DEBUG_LOG(WIIMOTE, " Read data Address: 0x%06x", address);
|
||||
DEBUG_LOG(WIIMOTE, " Read data Size: 0x%04x", size);
|
||||
|
||||
/* Now we determine what address space we are reading from. Space 0 is
|
||||
Eeprom and space 1 and 2 are the registers. */
|
||||
if(rd->space == WM_SPACE_EEPROM)
|
||||
{
|
||||
if (address + size > WIIMOTE_EEPROM_SIZE)
|
||||
{
|
||||
PanicAlert("WmReadData: address + size out of bounds");
|
||||
return;
|
||||
}
|
||||
SendReadDataReply(_channelID, g_Eeprom[g_ID] + address, address, addressHI, (int)size);
|
||||
/*DEBUG_LOG(WIIMOTE, "Read RegEeprom: Size: %i, Address: %08x, Offset: %08x",
|
||||
size, address, (address & 0xffff));*/
|
||||
}
|
||||
else if(rd->space == WM_SPACE_REGS1 || rd->space == WM_SPACE_REGS2)
|
||||
{
|
||||
u8* block;
|
||||
u32 blockSize;
|
||||
switch(addressHI)
|
||||
{
|
||||
case 0xA2:
|
||||
block = g_RegSpeaker[g_ID];
|
||||
blockSize = WIIMOTE_REG_SPEAKER_SIZE;
|
||||
DEBUG_LOG(WIIMOTE, " Case 0xa2: g_RegSpeaker");
|
||||
break;
|
||||
|
||||
case 0xA4:
|
||||
block = g_RegExt[g_ID];
|
||||
blockSize = WIIMOTE_REG_EXT_SIZE;
|
||||
DEBUG_LOG(WIIMOTE, " Case 0xa4: ExtReg");
|
||||
break;
|
||||
|
||||
case 0xA6:
|
||||
block = g_RegMotionPlus[g_ID];
|
||||
blockSize = WIIMOTE_REG_EXT_SIZE;
|
||||
DEBUG_LOG(WIIMOTE, " Case 0xa6: MotionPlusReg [%x]", address);
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
block = g_RegIr[g_ID];
|
||||
blockSize = WIIMOTE_REG_IR_SIZE;
|
||||
DEBUG_LOG(WIIMOTE, " Case 0xb0: g_RegIr");
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(WIIMOTE, "WmReadData: bad register block!");
|
||||
PanicAlert("WmReadData: bad register block!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Encrypt data that is read from the Wiimote Extension Register
|
||||
if(addressHI == 0xa4)
|
||||
{
|
||||
// Check if encrypted reads is on
|
||||
if(g_RegExt[g_ID][0xf0] == 0xaa)
|
||||
{
|
||||
/* Copy the registry to a temporary space. We don't want to change the unencrypted
|
||||
data in the registry */
|
||||
memcpy(g_RegExtTmp, g_RegExt[g_ID], sizeof(g_RegExt[0]));
|
||||
|
||||
// Encrypt g_RegExtTmp at that location
|
||||
wiimote_encrypt(&g_ExtKey[g_ID], &g_RegExtTmp[address & 0xffff], (address & 0xffff), (u8)size);
|
||||
|
||||
// Update the block that SendReadDataReply will eventually send to the Wii
|
||||
block = g_RegExtTmp;
|
||||
}
|
||||
}
|
||||
|
||||
address &= 0xFFFF;
|
||||
if(address + size > blockSize)
|
||||
{
|
||||
PanicAlert("WmReadData: address + size out of bounds! [%d %d %d]", address, size, blockSize);
|
||||
return;
|
||||
}
|
||||
|
||||
// Let this function process the message and send it to the Wii
|
||||
SendReadDataReply(_channelID, block + address, address, addressHI, (u8)size);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x)!", size, rd->space);
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we produce the actual 0x21 Input report that we send to the Wii. The
|
||||
message is divided into 16 bytes pieces and sent piece by piece. There will
|
||||
be five formatting bytes at the begging of all reports. A common format is
|
||||
00 00 f0 00 20, the 00 00 means that no buttons are pressed, the f means 16
|
||||
bytes in the message, the 0 means no error, the 00 20 means that the message
|
||||
is at the 00 20 offest in the registry that was read.
|
||||
|
||||
_Base: The data beginning at _Base[0]
|
||||
_Address: The starting address inside the registry, this is used to check for out of bounds reading
|
||||
_Size: The total size to send
|
||||
*/
|
||||
void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _AddressHI, int _Size)
|
||||
{
|
||||
int dataOffset = 0;
|
||||
const u8* data = (const u8*)_Base;
|
||||
|
||||
while (_Size > 0)
|
||||
{
|
||||
u8 DataFrame[1024];
|
||||
// Write the first two bytes to DataFrame
|
||||
u32 Offset = WriteWmReportHdr(DataFrame, WM_READ_DATA_REPLY);
|
||||
|
||||
// Limit the size to 16 bytes
|
||||
int copySize = (_Size > 16) ? 16 : _Size;
|
||||
// AyuanX: the MTU is 640B though... what a waste!
|
||||
|
||||
wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset);
|
||||
memset(pReply,0,sizeof(wm_read_data_reply));
|
||||
Offset += sizeof(wm_read_data_reply);
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
FillReportInfo(pReply->buttons);
|
||||
#endif
|
||||
pReply->error = 0;
|
||||
// 0x1 means two bytes, 0xf means 16 bytes
|
||||
pReply->size = copySize - 1;
|
||||
pReply->address = Common::swap16(_Address + dataOffset);
|
||||
|
||||
// Clear the mem first
|
||||
memset(pReply->data, 0, 16);
|
||||
|
||||
// Write a pice of _Base to DataFrame
|
||||
memcpy(pReply->data, data + dataOffset, copySize);
|
||||
|
||||
// Update DataOffset for the next loop
|
||||
dataOffset += copySize;
|
||||
|
||||
/* Out of bounds. The real Wiimote generate an error for the first
|
||||
request to 0x1770 if we dont't replicate that the game will never
|
||||
read the capibration data at the beginning of Eeprom. I think this
|
||||
error is supposed to occur when we try to read above the freely
|
||||
usable space that ends at 0x16ff. */
|
||||
if (Common::swap16(pReply->address + pReply->size) > WIIMOTE_EEPROM_FREE_SIZE)
|
||||
{
|
||||
pReply->size = 0x0f;
|
||||
pReply->error = 0x08;
|
||||
}
|
||||
|
||||
if (WiiMapping[g_ID].bMotionPlusConnected)
|
||||
{
|
||||
//MP+ will try to read from this Registeraddress, expecting an error if a previous WM+ activation has been succesful
|
||||
//It will also return an error if there was no WM+ present at all
|
||||
if (((_Address == 0x00FE ) || (_Address == 0x00FF )) && (_AddressHI == 0xA6) && (g_RegExt[g_ID][0xFF] == 0x05))
|
||||
{
|
||||
pReply->size = 0x0f;
|
||||
pReply->error = 0x07; //error: write-only area when activated/or not present
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Logging
|
||||
DEBUG_LOG(WIIMOTE, "SendReadDataReply");
|
||||
DEBUG_LOG(WIIMOTE, " Buttons: 0x%04x", pReply->buttons);
|
||||
DEBUG_LOG(WIIMOTE, " Error: 0x%x", pReply->error);
|
||||
DEBUG_LOG(WIIMOTE, " Size: 0x%x", pReply->size);
|
||||
DEBUG_LOG(WIIMOTE, " Address: 0x%04x", pReply->address);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string Temp = ArrayToString(DataFrame, Offset);
|
||||
DEBUG_LOG(WIIMOTE, "Data: %s", Temp.c_str());
|
||||
#endif
|
||||
|
||||
// Send a piece
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(g_ID, _channelID, DataFrame, Offset);
|
||||
|
||||
// Update the size that is left
|
||||
_Size -= copySize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Write data to Wiimote and Extensions registers. */
|
||||
void WmWriteData(u16 _channelID, wm_write_data* wd)
|
||||
{
|
||||
u32 address = convert24bit(wd->address);
|
||||
u8 addressHI = (address >> 16) & 0xFE;
|
||||
INFO_LOG(WIIMOTE, "Write data");
|
||||
DEBUG_LOG(WIIMOTE, " Space: %x", wd->space);
|
||||
DEBUG_LOG(WIIMOTE, " Address: 0x%06x", address);
|
||||
DEBUG_LOG(WIIMOTE, " Size: 0x%02x", wd->size);
|
||||
// Write to EEPROM
|
||||
if(wd->size <= 16 && wd->space == WM_SPACE_EEPROM)
|
||||
{
|
||||
if(address + wd->size > WIIMOTE_EEPROM_SIZE) {
|
||||
ERROR_LOG(WIIMOTE, "WmWriteData: address + size out of bounds!");
|
||||
PanicAlert("WmWriteData: address + size out of bounds!");
|
||||
return;
|
||||
}
|
||||
memcpy(g_Eeprom[g_ID] + address, wd->data, wd->size);
|
||||
}
|
||||
// Write to registers
|
||||
else if(wd->size <= 16 && (wd->space == WM_SPACE_REGS1 || wd->space == WM_SPACE_REGS2))
|
||||
{
|
||||
u8* block;
|
||||
u32 blockSize;
|
||||
switch(addressHI)
|
||||
{
|
||||
case 0xA2:
|
||||
block = g_RegSpeaker[g_ID];
|
||||
blockSize = WIIMOTE_REG_SPEAKER_SIZE;
|
||||
DEBUG_LOG(WIIMOTE, " Case 0xa2: RegSpeaker");
|
||||
break;
|
||||
|
||||
case 0xA4:
|
||||
block = g_RegExt[g_ID]; // Extension Controller register
|
||||
blockSize = WIIMOTE_REG_EXT_SIZE;
|
||||
DEBUG_LOG(WIIMOTE, " Case 0xa4: ExtReg");
|
||||
break;
|
||||
|
||||
case 0xA6:
|
||||
block = g_RegMotionPlus[g_ID];
|
||||
blockSize = WIIMOTE_REG_EXT_SIZE;
|
||||
DEBUG_LOG(WIIMOTE, " Case 0xa6: MotionPlusReg [%x]", address);
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
block = g_RegIr[g_ID];
|
||||
blockSize = WIIMOTE_REG_IR_SIZE;
|
||||
INFO_LOG(WIIMOTE, " Case 0xb0: RegIr");
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(WIIMOTE, "WmWriteData: bad register block!");
|
||||
PanicAlert("WmWriteData: bad register block!");
|
||||
return;
|
||||
}
|
||||
|
||||
address &= 0xFFFF;
|
||||
|
||||
// Check if the address is within bounds
|
||||
if(address + wd->size > blockSize) {
|
||||
PanicAlert("WmWriteData: address + size out of bounds!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally write the registers to the right structure
|
||||
memcpy(block + address, wd->data, wd->size);
|
||||
|
||||
// Generate key for the Wiimote Extension
|
||||
if(blockSize == WIIMOTE_REG_EXT_SIZE)
|
||||
{
|
||||
// Run the key generation on all writes in the key area, it doesn't matter
|
||||
// that we send it parts of a key, only the last full key will have an effect
|
||||
if(address >= 0x40 && address <= 0x4c)
|
||||
wiimote_gen_key(&g_ExtKey[g_ID], &g_RegExt[g_ID][0x40]);
|
||||
|
||||
}
|
||||
if (WiiMapping[g_ID].bMotionPlusConnected) {
|
||||
//If the MP+ gets activated, it's important to send one or two status reports depending on the presence of a pass-through extension
|
||||
int sendreport = HandlingMotionPlusWrites(wd->data, addressHI, address);
|
||||
g_MotionPlusLastWriteReg[g_ID] = address;
|
||||
|
||||
switch (sendreport)
|
||||
{
|
||||
//pass-through extension disconnected and wm+ connected
|
||||
case 1:
|
||||
WmRequestStatus(_channelID, (wm_request_status*) wd, 0);
|
||||
WmRequestStatus(_channelID, (wm_request_status*) wd, 1);
|
||||
break;
|
||||
|
||||
//wm+ unplugged(on deactivation)
|
||||
case 2:
|
||||
WmRequestStatus(_channelID, (wm_request_status*) wd, 0);
|
||||
break;
|
||||
|
||||
//wm+ plugged in(on activation)
|
||||
case 3:
|
||||
WmRequestStatus(_channelID, (wm_request_status*) wd, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("WmWriteData: unimplemented parameters!");
|
||||
}
|
||||
|
||||
/* Just added for home brew... Isn't it enough that we call this from
|
||||
InterruptChannel()? Or is there a separate route here that don't pass
|
||||
though InterruptChannel()? */
|
||||
}
|
||||
|
||||
|
||||
/* Here we produce a 0x20 status report to send to the Wii. We currently ignore
|
||||
the status request rs and all its eventual instructions it may include (for
|
||||
example turn off rumble or something else) and just send the status
|
||||
report. */
|
||||
void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension)
|
||||
{
|
||||
u8 DataFrame[1024];
|
||||
u32 Offset = WriteWmReportHdr(DataFrame, WM_STATUS_REPORT);
|
||||
|
||||
wm_status_report* pStatus = (wm_status_report*)(DataFrame + Offset);
|
||||
Offset += sizeof(wm_status_report);
|
||||
memset(pStatus, 0, sizeof(wm_status_report)); // fill the status report with zeros
|
||||
|
||||
// Status values
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
FillReportInfo(pStatus->buttons);
|
||||
#endif
|
||||
pStatus->leds = g_Leds[g_ID]; // leds are 4 bit
|
||||
pStatus->ir = g_IR[g_ID]; // 1 bit
|
||||
pStatus->speaker = g_Speaker[g_ID]; // 1 bit
|
||||
pStatus->battery_low = 0; // battery is okay
|
||||
pStatus->battery = 0x5f; // fully charged
|
||||
/* Battery levels in voltage
|
||||
0x00 - 0x32: level 1
|
||||
0x33 - 0x43: level 2
|
||||
0x33 - 0x54: level 3
|
||||
0x55 - 0xff: level 4 */
|
||||
|
||||
// Check if we have a specific order about the extension status
|
||||
if (Extension == -1)
|
||||
{
|
||||
if (WiiMapping[g_ID].bMotionPlusConnected)
|
||||
pStatus->extension = ((g_MotionPlus[g_ID]) || (WiiMapping[g_ID].iExtensionConnected != EXT_NONE)) ? 1 : 0;
|
||||
else
|
||||
pStatus->extension = (WiiMapping[g_ID].iExtensionConnected == EXT_NONE) ? 0 : 1;
|
||||
// Read config value for the first time
|
||||
}
|
||||
else
|
||||
{
|
||||
pStatus->extension = (Extension) ? 1 : 0;
|
||||
}
|
||||
|
||||
INFO_LOG(WIIMOTE, "Request Status");
|
||||
DEBUG_LOG(WIIMOTE, " Buttons: 0x%04x", pStatus->buttons);
|
||||
DEBUG_LOG(WIIMOTE, " Extension: %x", pStatus->extension);
|
||||
DEBUG_LOG(WIIMOTE, " Speaker: %x", pStatus->speaker);
|
||||
DEBUG_LOG(WIIMOTE, " IR: %x", pStatus->ir);
|
||||
DEBUG_LOG(WIIMOTE, " LEDs: %x", pStatus->leds);
|
||||
|
||||
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(g_ID, _channelID, DataFrame, Offset);
|
||||
}
|
||||
|
||||
//http://snzgoo.blogspot.com for more details on what this is doing
|
||||
int HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address)
|
||||
{
|
||||
bool MPlusActiveExt = (g_RegExt[g_ID][0xFF] == 0x05) ? 1 : 0;
|
||||
|
||||
switch (addressHI)
|
||||
{
|
||||
case 0xA4:
|
||||
switch (address)
|
||||
{
|
||||
case 0x00FE:
|
||||
if (data[0] == 0x00)
|
||||
{
|
||||
if (MPlusActiveExt)
|
||||
{
|
||||
if (WiiMapping[g_ID].iExtensionConnected)
|
||||
{
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Disabling WM+ and swapping registers back", data[0], addressHI, address);
|
||||
g_RegExt[g_ID][0xFE] = 0x00;
|
||||
SwapExtRegisters();
|
||||
return 1; // we need to issue a 0x20 report, if there's an extension connected to the MP+!
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: WM+ already inactive", data[0], addressHI, address);
|
||||
}
|
||||
g_MotionPlus[g_ID] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
//1. Disables an active wiimote; 0x20 report sent when iExtensionConnected != NONE : ext disconnect.
|
||||
//2. Initializing the pass-through extension: writing 0x55 ->0xA400F0 and then 0x00 to 0xA400FB.
|
||||
//3. Single write 0x00 to 0x00FB when MP got activated, part of the MP activation.
|
||||
case 0x00FB:
|
||||
if ((data[0] == 0x00) && (g_MotionPlusLastWriteReg[g_ID] == 0xF0))
|
||||
{
|
||||
switch (g_MotionPlusLastWriteReg[g_ID])
|
||||
{
|
||||
case 0xF0:
|
||||
//1. disabling wiimote,
|
||||
if (MPlusActiveExt) //mp already deactivated, no register swap needed
|
||||
{
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Disabling WM+ and swapping registers back", data[0], addressHI, address)
|
||||
g_MotionPlus[g_ID] = WiiMapping[g_ID].iExtensionConnected ? 1 : 0;
|
||||
g_RegExt[g_ID][0xFE] = 0x05;
|
||||
SwapExtRegisters();
|
||||
|
||||
if (!WiiMapping[g_ID].iExtensionConnected)
|
||||
return 2;
|
||||
} //2. Default extension init, disable mp if actitaved, else do nothing
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: WM+ already disabled [ext:%i] - no swapping", data[0], addressHI, address, WiiMapping[g_ID].iExtensionConnected);
|
||||
g_RegMotionPlus[g_ID][0xFE] = 0x05;
|
||||
g_RegMotionPlus[g_ID][0xF7] = 0x08;
|
||||
}
|
||||
break;
|
||||
//3. part of wm activation.
|
||||
default:
|
||||
if (MPlusActiveExt)
|
||||
{
|
||||
g_RegExt[g_ID][0xF1] = 0x01;
|
||||
g_RegExt[g_ID][0xF7] = 0x08; //init/calibration state flag
|
||||
|
||||
if (WiiMapping[g_ID].iExtensionConnected)
|
||||
{
|
||||
//I don't know what these are for: F6h,F8h, F9h. They seem necessary to be set to 0x00 instead of 0xFF(default),
|
||||
//when there's an extension connected to the MP
|
||||
g_RegExt[g_ID][0xF6] = 0x00;
|
||||
g_RegExt[g_ID][0xF8] = 0x00;
|
||||
g_RegExt[g_ID][0xF9] = 0x00;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//switch for invalid/valid data calibration (0x00/0x01)
|
||||
case 0x00F1:
|
||||
if (MPlusActiveExt)
|
||||
{
|
||||
g_RegExt[g_ID][0xF7] = 0x1A; //syncing finished
|
||||
}
|
||||
break;
|
||||
|
||||
//switch for triggering the calibration/syncing between wiimote and MP (corresponding data will be at 50h)
|
||||
case 0x00F2:
|
||||
if(MPlusActiveExt && (g_RegExt[g_ID][0xF7] < 0x0E))
|
||||
{
|
||||
g_RegExt[g_ID][0xF7] = 0x0E;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
//MotionPlus Register
|
||||
case 0xA6:
|
||||
switch (address)
|
||||
{
|
||||
//Enabling WM+: swapping extension registers
|
||||
case 0x00FE:
|
||||
if ((data[0] == 0x04) || (data[0] == 0x05))
|
||||
{
|
||||
if (!MPlusActiveExt)
|
||||
{
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Enabling WM+ and swapping registers", data[0], addressHI, address);
|
||||
|
||||
//The WII will try to read from the A6 WM+ register directly after activation,
|
||||
//and we need to reply with an error each time as long the mp is still activate.
|
||||
//In addition, we need to sent 1-2 0x20 statusreports depending on if theres an extension connected to the MP or not.
|
||||
g_MotionPlus[g_ID] = 1;
|
||||
SwapExtRegisters();
|
||||
|
||||
g_RegExt[g_ID][0xF7] = 0x08; //Reset flag
|
||||
g_RegExt[g_ID][0xFE] = data[0];
|
||||
|
||||
if (WiiMapping[g_ID].iExtensionConnected != EXT_NONE)
|
||||
{
|
||||
g_RegExt[g_ID][0xF1] = 0x01;
|
||||
g_RegExt[g_ID][0xF6] = 0x00;
|
||||
g_RegExt[g_ID][0xF8] = 0x00;
|
||||
g_RegExt[g_ID][0xF9] = 0x00;
|
||||
return 1; // we need to issue 2 0x20 reports, if there's an extension connected to the MP
|
||||
}
|
||||
return 3; // we need to issue 1 0x20 report, if there's no extension connected to the MP
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: WM already enabled no register swapping", data[0], addressHI, address);
|
||||
}
|
||||
}
|
||||
break;
|
||||
//Part of the WM+ init()
|
||||
case 0x00F0:
|
||||
if (data[0] == 0x55) {
|
||||
//If the wiimote is already active, we will init() the WM+ directly in the ExtReg, shouldn't happen usually
|
||||
if (MPlusActiveExt)
|
||||
{
|
||||
g_RegExt[g_ID][0xFE] = 0x05;
|
||||
g_RegExt[g_ID][0xF7] = 0x08;
|
||||
}
|
||||
if (WiiMapping[g_ID].iExtensionConnected == EXT_NONE)
|
||||
g_MotionPlus[g_ID] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: unknown reason", data[0], addressHI, address);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//Swapping Ext/WM+-registers
|
||||
void SwapExtRegisters()
|
||||
{
|
||||
memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp));
|
||||
memcpy(g_RegExtTmp, g_RegExt[g_ID], sizeof(g_RegExt[0]));
|
||||
memset(g_RegExt[0], 0, sizeof(g_RegExt[0]));
|
||||
memcpy(g_RegExt[g_ID], g_RegMotionPlus[g_ID], sizeof(g_RegMotionPlus[0]));
|
||||
memset(g_RegMotionPlus[0], 0, sizeof(g_RegMotionPlus[0]));
|
||||
memcpy(g_RegMotionPlus[g_ID], g_RegExtTmp, sizeof(g_RegExtTmp));
|
||||
|
||||
if (g_RegMotionPlus[g_ID][0xFC]) {
|
||||
g_RegMotionPlus[g_ID][0xFC] = 0xa6;
|
||||
}
|
||||
if (g_RegExt[g_ID][0xFC]) {
|
||||
g_RegExt[g_ID][0xFC] = 0xa4;
|
||||
}
|
||||
}
|
||||
|
||||
} // WiiMoteEmu
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _EMU_SUBFUNCTIONS_
|
||||
#define _EMU_SUBFUNCTIONS_
|
||||
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "main.h"
|
||||
#include "wiimote_hid.h" // Local
|
||||
#include "EmuDefinitions.h"
|
||||
#include "Encryption.h"
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
void HidOutputReport(u16 _channelID, wm_report* sr);
|
||||
|
||||
void WmReadData(u16 _channelID, wm_read_data* rd);
|
||||
void WmWriteData(u16 _channelID, wm_write_data* wd);
|
||||
void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension = -1);
|
||||
void WmRequestStatus_(u16 _channelID, int a);
|
||||
void WmReportMode(u16 _channelID, wm_report_mode* dr);
|
||||
|
||||
void SendReportCoreAccel(u16 _channelID);
|
||||
void SendReportCoreAccelIr12(u16 _channelID);
|
||||
void SendReportCore(u16 _channelID);
|
||||
void SendReportCoreAccelExt16(u16 _channelID);
|
||||
void SendReportCoreAccelIr10Ext(u16 _channelID);
|
||||
|
||||
int WriteWmReportHdr(u8* dst, u8 wm);
|
||||
void WmSendAck(u16 _channelID, u8 _reportID);
|
||||
void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _AddressHI, int _Size);
|
||||
void SwapExtRegisters();
|
||||
int HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address);
|
||||
|
||||
void FillReportAcc(wm_accel& _acc);
|
||||
void FillReportInfo(wm_core& _core);
|
||||
void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1);
|
||||
void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1);
|
||||
void FillReportExtension(wm_extension& _ext);
|
||||
void FillReportClassicExtension(wm_classic_extension& _ext);
|
||||
void FillReportGuitarHero3Extension(wm_GH3_extension& _ext);
|
||||
void FillReportMotionPlusNunchukExtension(wm_extension& _ext);
|
||||
void FillReportMotionPlusNoExtension(wm_extension& _ext);
|
||||
void FillReportMotionPlus(wm_extension& ext, bool extension);
|
||||
} // namespace
|
||||
|
||||
#endif //_EMU_DECLARATIONS_
|
||||
@@ -1,296 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
// Copyright (C) Hector Martin "marcan" ([email protected])
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
#include "Encryption.h"
|
||||
|
||||
|
||||
u8 ans_tbl[7][6] = {
|
||||
{0xA8,0x77,0xA6,0xE0,0xF7,0x43},
|
||||
{0x5A,0x35,0x85,0xE2,0x72,0x97},
|
||||
{0x8F,0xB7,0x1A,0x62,0x87,0x38},
|
||||
{ 0xD,0x67,0xC7,0xBE,0x4F,0x3E},
|
||||
{0x20,0x76,0x37,0x8F,0x68,0xB7},
|
||||
{0xA9,0x26,0x3F,0x2B,0x10,0xE3},
|
||||
{0x30,0x7E,0x90, 0xE,0x85, 0xA},
|
||||
};
|
||||
|
||||
u8 tsbox[256] = {
|
||||
0x70,0x51, 3,0x86,0x40, 0xD,0x4F,0xEB,0x3E,0xCC,0xD1,0x87,0x35,0xBD,0xF5, 0xB,
|
||||
0x5E,0xD0,0xF8,0xF2,0xD5,0xE2,0x6C,0x31, 0xC,0xAD,0xFC,0x21,0xC3,0x78,0xC1, 6,
|
||||
0xC2,0x4C,0x55,0xE6,0x4A,0x34,0x48,0x11,0x1E,0xDA,0xE7,0x1A,0x84,0xA0,0x96,0xA7,
|
||||
0xE3,0x7F,0xAF,0x63,0x9C,0xFA,0x23,0x5B,0x79,0xC8,0x9E,0xBA,0xB2,0xC9,0x22,0x12,
|
||||
0x4B,0xB3,0xA1,0xB6,0x32,0x49,0xA2,0xE1,0x89,0x39,0x10,0x66,0xC5, 7,0x8F,0x54,
|
||||
0xEA,0x91,0xCA,0x3F,0xF9,0x19,0xF0,0xD7,0x46,0xBC,0x28,0x1B,0x61,0xE8,0x2F,0x6A,
|
||||
0xAE,0x9D,0xF6,0x4E, 9,0x14,0x77,0x4D,0xDB,0x1F,0x2E,0x7B,0x7C,0xF1,0x43,0xA3,
|
||||
0,0xB8,0x13,0x8C,0x85,0xB9,0x29,0x75,0x88,0xFD,0xD2,0x56,0x1C,0x50,0x97,0x41,
|
||||
0xE5,0x3B,0x60,0xB5,0xC0,0x64,0xEE,0x98,0xD6,0x2D,0x25,0xA4,0xAA,0xCD,0x7D,0xA8,
|
||||
0x83,0xC6,0xAB,0xBE,0x44,0x99,0x26,0x3C,0xCE,0x9F,0xBF,0xD3,0xCB,0x76,0x7A,0x7E,
|
||||
0x82, 1,0x8A,0x9A,0x80,0x1D, 0xE,0xB0,0x5C,0xD4,0x38,0x62,0xF4,0x30,0xE0,0x8E,
|
||||
0x53,0xB7, 2,0x57,0xAC,0xA6,0x52, 0xA,0x6D,0x92,0x65,0x17,0x24,0x33,0x45,0x72,
|
||||
0x74,0xB1,0xB4,0xF7,0x5D,0xED,0x2C,0xFF,0x47,0x37,0x5A,0x90,0xBB,0xDF,0x2A,0x16,
|
||||
0x59,0x95,0xD9,0xC4,0x27,0x67,0x73,0xC7,0x68,0xFE,0xA5,0xDD,0x6B,0x5F,0x93,0xD8,
|
||||
0xEC, 5,0x3A,0x8D,0x6E,0xFB,0x3D,0xA9,0x69,0x36,0xF3,0x94,0xDE,0xEF,0x15,0x6F,
|
||||
0x8B,0x9B, 8, 0xF,0xDC,0x81,0x18,0x20, 4,0xE4,0x71,0xCF,0xE9,0x2B,0x42,0x58,
|
||||
};
|
||||
|
||||
u8 sboxes[8][256] = {
|
||||
{
|
||||
1,0xA0,0xA9,0x62,0xD6,0x3F,0x85,0xA7,0xB6,0xD4,0xFA,0x15,0x66,0x17, 9,0xBD,
|
||||
0x5D,0x14,0x34,0x26,0x59,0x72,0x91,0x54, 6,0x4F,0xF8,0xB0,0x5B,0x74,0x93,0x99,
|
||||
0x8C,0xF2,0x45,0xCD,0xEA,0x4E,0xAD,0x10,0x4A,0xE5,0xCA,0xEE,0xDF,0xC6,0x6F,0x9F,
|
||||
0x88,0x8E, 2,0xCC, 8,0xA8,0x77,0x94,0x6D,0x21,0xB1,0x28,0xE4,0x39,0x79,0x96,
|
||||
0x60,0x71,0x81,0x16,0x2E,0xE6,0x78,0xB9,0xC4,0x46,0x9A,0x42,0xAE,0xB7,0x7C,0x43,
|
||||
0xB3,0x22,0x1A,0x86,0xC2,0x32,0x3D,0x2D,0x9C,0xD2,0x29,0xE9,0x63,0x9B,0xD1,0x31,
|
||||
0x38,0x5E,0x1E,0x36,0x41,0xBB, 3,0x18,0x2B,0x3E,0xBF,0x68,0x61,0xFC,0x52,0xC0,
|
||||
0xDE,0xE0, 0xA,0x58,0x13,0x5A, 0,0xBE,0x1C,0x90, 0xE,0x53,0x12,0xFD,0xE2,0x6E,
|
||||
0xBA,0xCE,0x24,0x27,0x44,0x7F,0x87,0xA3,0xA1,0xD5,0x50,0x40,0xE3,0xF9,0x83,0xF7,
|
||||
0xC7,0xA2,0x35,0xC8,0xDB,0x19,0xAB,0x2F,0x11,0x25,0xED,0x33,0x9E,0x55,0xE1,0x48,
|
||||
0xAF,0x73,0x84,0xDA,0x2A,0xAA,0x51,0xEB,0x9D,0x95,0xB2,0xCB,0xE7,0x70,0x80,0xFE,
|
||||
0x4C,0x65, 4,0xEF,0xC5,0xF1,0xC3,0x3A,0xB4,0xF5,0x5F,0x23,0x89,0xDD,0x30,0xA5,
|
||||
0x8B,0xD3,0xF6,0xDC,0x4D,0x64,0xD7,0xF0,0x8F,0xEC,0x56,0x37,0x5C,0xA4, 0xD, 7,
|
||||
0x76,0x8A,0x2C, 0xB,0xB5,0xD8,0xC1,0x1F,0xE8,0x3B,0xF4,0x4B,0x1B,0x47,0x6C,0x49,
|
||||
0x67,0x7B,0x92,0xCF,0x75,0x7E,0x20,0xD9,0x7D,0x3C,0x97,0x7A,0xD0, 5,0x6B, 0xF,
|
||||
0x1D,0xFB,0x82,0x98,0x57,0x8D,0xF3,0x6A,0xBC,0xAC,0xC9,0xA6,0xFF,0xB8,0x69, 0xC,
|
||||
},
|
||||
{
|
||||
0x4C,0x4D,0x72, 7,0x5A,0x49,0x33,0x8D,0xA2,0xAB,0x46,0x3D,0x63, 0xD,0xA0,0x97,
|
||||
0xFF,0xF0,0xF5,0xFA,0xC0,0xE9,0xDB,0x62,0xE4,0xE1,0x74,0x43,0xDC,0x86,0x18,0x29,
|
||||
0x37,0xF4, 6,0xE2,0xED,0x6F,0x90,0x48,0x1E,0x2D,0x1D,0xEA,0x73,0x94,0x54,0xDF,
|
||||
0x25,0xF6,0x47,0x27,0xD9,0x11,0x77,0xC9,0x84,0x1C,0x5B,0x5C,0x51,0x81,0xA6,0x22,
|
||||
0x3E,0x24,0x96,0xC8,0x8A,0xEC,0x82,0x7C, 9,0xB8,0x45,0x4A,0x57,0xBB,0x2F,0x50,
|
||||
0x75,0x8E,0x61,0x70,0x8C,0x6C,0xAF,0xD0,0xFD,0xB4,0x1B,0xAE,0xDE,0xFE,0x3B,0xB5,
|
||||
0x36,0xBD,0x55, 1, 0xE,0x9C,0x41,0x56,0x5F,0xB3,0x26, 3,0x83,0xBA,0x13,0x4B,
|
||||
0xCA,0xC5, 0xA,0xF8,0x60,0xA5,0xB9,0xC7,0xC3,0x98,0x32,0xFB,0x12,0xF9,0xA7,0x92,
|
||||
0xAA,0x68,0xF3,0x78,0x7E, 5,0x20,0x21, 2,0xE8,0xBF,0xF2,0xB0,0x59,0x8F,0xD2,
|
||||
0xCB,0x87,0x65,0x15,0xF1,0x1A,0xB2,0x30,0xAD,0xEE,0x58,0xA3,0x8B,0x66,0x1F,0x2C,
|
||||
0xD7,0x5D,0x19,0x85,0xA8,0xE6,0xD3,0x6B,0xA1, 0xC,0x91,0x93,0x6A,0x5E, 0xB,0x79,
|
||||
0xE3,0xDD, 0,0x4F,0x3C,0x89,0x6E,0x71,0x69,0xA9,0xAC,0x40,0xE5,0x99,0x28,0xC6,
|
||||
0x31,0x4E,0x7A,0xCD, 8,0x9E,0x7D,0xEF,0x17,0xFC,0x88,0xD8,0xA4,0x6D,0x44,0x95,
|
||||
0xD1,0xB7,0xD4,0x9B,0xBE,0x2A,0x34,0x64,0x2B,0xCF,0x2E,0xEB,0x38,0xCE,0x23,0xE0,
|
||||
0x3A,0x3F,0xF7,0x7B,0x9F,0x10,0x53,0xBC,0x52,0x67,0x16,0xE7,0x80,0x76, 4,0xC4,
|
||||
0xB6,0xC1,0xC2,0x7F,0x9A,0xDA,0xD5,0x39,0x42,0x14,0x9D,0xB1, 0xF,0x35,0xD6,0xCC,
|
||||
},
|
||||
{
|
||||
0xB9,0xDA,0x38, 0xC,0xA2,0x9C, 9,0x1F, 6,0xB1,0xB6,0xFD,0x1A,0x69,0x23,0x30,
|
||||
0xC4,0xDE, 1,0xD1,0xF4,0x58,0x29,0x37,0x1C,0x7D,0xD5,0xBF,0xFF,0xBD,0xC8,0xC9,
|
||||
0xCF,0x65,0xBE,0x7B,0x78,0x97,0x98,0x67, 8,0xB3,0x26,0x57,0xF7,0xFA,0x40,0xAD,
|
||||
0x8E,0x75,0xA6,0x7C,0xDB,0x91,0x8B,0x51,0x99,0xD4,0x17,0x7A,0x90,0x8D,0xCE,0x63,
|
||||
0xCB,0x4E,0xA0,0xAB,0x18,0x3A,0x5B,0x50,0x7F,0x21,0x74,0xC1,0xBB,0xB8,0xB7,0xBA,
|
||||
0xB,0x35,0x95,0x31,0x59,0x9A,0x4D, 4, 7,0x1E,0x5A,0x76,0x13,0xF3,0x71,0x83,
|
||||
0xD0,0x86, 3,0xA8,0x39,0x42,0xAA,0x28,0xE6,0xE4,0xD8,0x5D,0xD3,0xD0,0x6E,0x6F,
|
||||
0x96,0xFB,0x5E,0xBC,0x56,0xC2,0x5F,0x85,0x9B,0xE7,0xAF,0xD2,0x3B,0x84,0x6A,0xA7,
|
||||
0x53,0xC5,0x44,0x49,0xA5,0xF9,0x36,0x72,0x3D,0x2C,0xD9,0x1B,0xA1,0xF5,0x4F,0x93,
|
||||
0x9D,0x68,0x47,0x41,0x16,0xCA,0x2A,0x4C,0xA3,0x87,0xD6,0xE5,0x19,0x2E,0x77,0x15,
|
||||
0x6D,0x70,0xC0,0xDF,0xB2, 0,0x46,0xED,0xC6,0x6C,0x43,0x60,0x92,0x2D,0xA9,0x22,
|
||||
0x45,0x8F,0x34,0x55,0xAE,0xA4, 0xA,0x66,0x32,0xE0,0xDC, 2,0xAC,0xE8,0x20,0x8C,
|
||||
0x89,0x62,0x4A,0xFE,0xEE,0xC3,0xE3,0x3C,0xF1,0x79, 5,0xE9,0xF6,0x27,0x33,0xCC,
|
||||
0xF2,0x9E,0x11,0x81,0x7E,0x80,0x10,0x8A,0x82,0x9F,0x48, 0xD,0xD7,0xB4,0xFC,0x2F,
|
||||
0xB5,0xC7,0xDD,0x88,0x14,0x6B,0x2B,0x54,0xEA,0x1D,0x94,0x5C,0xB0,0xEF,0x12,0x24,
|
||||
0xCD,0xEB,0xE1,0xE2,0x64,0x73,0x3F, 0xE,0x52,0x61,0x25,0x3E,0xF8, 0xF,0x4B,0xEC,
|
||||
},
|
||||
{
|
||||
0xC0, 0,0x30,0xF6, 2,0x49,0x3D,0x10,0x6E,0x20,0xC9,0xA6,0x2F,0xFE,0x2C,0x2B,
|
||||
0x75,0x2E,0x45,0x26,0xAB,0x48,0xA9,0x80,0xFC, 4,0xCC,0xD3,0xB5,0xBA,0xA3,0x38,
|
||||
0x31,0x7D, 1,0xD9,0xA7,0x7B,0x96,0xB6,0x63,0x69,0x4E,0xF7,0xDE,0xE0,0x78,0xCA,
|
||||
0x50,0xAA,0x41,0x91,0x65,0x88,0xE4,0x21,0x85,0xDA,0x3A,0x27,0xBE,0x1C,0x3E,0x42,
|
||||
0x5E,0x17,0x52,0x7F,0x1F,0x89,0x24,0x6F,0x8F,0x5C,0x67,0x74, 0xE,0x12,0x87,0x8D,
|
||||
0xE9,0x34,0xED,0x73,0xC4,0xF8,0x61,0x5B, 5,0xDF,0x59,0x4C,0x97,0x79,0x83,0x18,
|
||||
0xA4,0x55,0x95,0xEB,0xBD,0x53,0xF5,0xF1,0x57,0x66,0x46,0x9F,0xB2,0x81, 9,0x51,
|
||||
0x86,0x22,0x16,0xDD,0x23,0x93,0x76,0x29,0xC2,0xD7,0x1D,0xD4,0xBF,0x36,0x3F,0xEA,
|
||||
0x4B,0x11,0x32,0xB9,0x62,0x54,0x60,0xD6,0x6D,0x43,0x9A, 0xD,0x92,0x9C,0xB0,0xEF,
|
||||
0x58,0x6C,0x9D,0x77,0x2D,0x70,0xFA,0xF3,0xB3, 0xB,0xE2,0x40,0x7E,0xF4,0x8A,0xE5,
|
||||
0x8C,0x3C,0x56,0x71,0xD1,0x64,0xE1,0x82, 0xA,0xCB,0x13,0x15,0x90,0xEC, 3,0x99,
|
||||
0xAF,0x14,0x5D, 0xF,0x33,0x4A,0x94,0xA5,0xA8,0x35,0x1B,0xE3,0x6A,0xC6,0x28,0xFF,
|
||||
0x4D,0xE7,0x25,0x84,0xAC, 8,0xAE,0xC5,0xA2,0x2A,0xB8,0x37, 0xC,0x7A,0xA0,0xC3,
|
||||
0xCE,0xAD, 6,0x1A,0x9E,0x8B,0xFB,0xD5,0xD0,0xC1,0x1E,0xD0,0xB4,0x9B,0xB1,0x44,
|
||||
0xF2,0x47,0xC7,0x68,0xCF,0x72,0xBB,0x4F,0x5A,0xF9,0xDC,0x6B,0xDB,0xD2,0xE8,0x7C,
|
||||
0xC8,0xEE,0x98,0xA1,0xE6,0xD8,0x39, 7,0x5F,0xFD,0x8E,0x19,0xB7,0x3B,0xBC,0xCD,
|
||||
},
|
||||
{
|
||||
0x7C,0xE3,0x81,0x73,0xB2,0x11,0xBF,0x6F,0x20,0x98,0xFE,0x75,0x96,0xEF,0x6C,0xDA,
|
||||
0x50,0xE1, 9,0x72,0x54,0x45,0xBA,0x34,0x80,0x5B,0xED,0x3E,0x53,0x2C,0x87,0xA4,
|
||||
0x57,0xF3,0x33,0x3F,0x3C,0xB7,0x67,0xB4,0xA3,0x25,0x60,0x4F, 7,0x6B,0x1B,0x47,
|
||||
0x15, 0xF,0xE4, 0xA,0xEA,0xD1,0x32,0x78,0x36,0x49,0x8D,0x4B,0xD2,0xBC,0xA5,0xDC,
|
||||
0x1D, 0xD,0x4D,0xCD,0x9A,0x82,0x5F,0xFC,0x94,0x65,0xBE,0xE2,0xF4,0xC9,0x1E,0x44,
|
||||
0xCB,0x9E, 0xC,0x64,0x71,0x26,0x63,0xB3,0x14,0xE8,0x40,0x70,0x8A, 0xE,0x19,0x42,
|
||||
0x6D,0xAC,0x88,0x10,0x5C,0xDF,0x41,0xA9,0xAD,0xE5,0xFB,0x74,0xCC,0xD5, 6,0x8E,
|
||||
0x59,0x86,0xCE,0x1F,0x3D,0x76,0xE0,0x8F,0xB9,0x77,0x27,0x7B,0xA6,0xD8,0x29,0xD3,
|
||||
0xEC,0xB8,0x13,0xF7,0xFA,0xC3,0x51,0x6A,0xDE,0x4A,0x5A,0xEB,0xC2,0x8B,0x23,0x48,
|
||||
0x92,0xCF,0x62,0xA8,0x99,0xF8,0xD0,0x2E,0x85,0x61,0x43,0xC8,0xBD,0xF0, 5,0x93,
|
||||
0xCA,0x4E,0xF1,0x7D,0x30,0xFD,0xC4,0x69,0x66,0x2F, 8,0xB1,0x52,0xF9,0x21,0xE6,
|
||||
0x7A,0x2B,0xDD,0x39,0x84,0xFF,0xC0,0x91,0xD6,0x37,0xD4,0x7F,0x2D,0x9B,0x5D,0xA1,
|
||||
0x3B,0x6E,0xB5,0xC5,0x46, 4,0xF5,0x90,0xEE,0x7E,0x83,0x1C, 3,0x56,0xB6,0xAA,
|
||||
0,0x17, 1,0x35,0x55,0x79, 0xB,0x12,0xBB,0x1A,0x31,0xE7, 2,0x28,0x16,0xC1,
|
||||
0xF6,0xA2,0xDB,0x18,0x9C,0x89,0x68,0x38,0x97,0xAB,0xC7,0x2A,0xD7,0x3A,0xF2,0xC6,
|
||||
0x24,0x4C,0xB0,0x58,0xA0,0x22,0x5E,0x9D,0xD9,0xA7,0xE9,0xAE,0xAF,0x8C,0x95,0x9F,
|
||||
},
|
||||
{
|
||||
0x28,0xB7,0x20,0xD7,0xB0,0x30,0xC3, 9,0x19,0xC0,0x67,0xD6, 0,0x3C,0x7E,0xE7,
|
||||
0xE9,0xF4, 8,0x5A,0xF8,0xB8,0x2E, 5,0xA6,0x25,0x9E,0x5C,0xD8,0x15, 0xD,0xE1,
|
||||
0xF6,0x11,0x54,0x6B,0xCD,0x21,0x46,0x66,0x5E,0x84,0xAD, 6,0x38,0x29,0x44,0xC5,
|
||||
0xA2,0xCE,0xF1,0xAA,0xC1,0x40,0x71,0x86,0xB5,0xEF,0xFC,0x36,0xA8,0xCB, 0xA,0x48,
|
||||
0x27,0x45,0x64,0xA3,0xAF,0x8C,0xB2,0xC6,0x9F, 7,0x89,0xDC,0x17,0xD3,0x49,0x79,
|
||||
0xFB,0xFE,0x1D,0xD0,0xB9,0x88,0x43,0x52,0xBC, 1,0x78,0x2B,0x7D,0x94,0xC7, 0xE,
|
||||
0xDE,0xA5,0xD5,0x9B,0xCC,0xF7,0x61,0x7A,0xC2,0x74,0x81,0x39, 3,0xAB,0x96,0xA0,
|
||||
0x37,0xBD,0x2D,0x72,0x75,0x3F,0xC9,0xD4,0x8E,0x6F,0xF9,0x8D,0xED,0x62,0xDB,0x1C,
|
||||
0xDF, 4,0xAC,0x1B,0x6C,0x14,0x4B,0x63,0xD0,0xBF,0xB4,0x82,0xEC,0x7B,0x1A,0x59,
|
||||
0x92,0xD2,0x10,0x60,0xB6,0x3D,0x5F,0xE6,0x80,0x6E,0x70,0xC4,0xF2,0x35,0xD9,0x7C,
|
||||
0xEE,0xE5,0x41,0xA4,0x5B,0x50,0xDD,0xBB,0x4C,0xF3,0x1F,0x9D,0x5D,0x57,0x55,0x51,
|
||||
0x97,0xE3,0x58,0x42,0x4D,0x9C,0x73,0xBA,0xC8,0x77,0x31,0x69,0x26,0xAE,0xEA,0x8A,
|
||||
0xDA,0x22,0xB3,0x87,0x56,0xFA,0x93, 0xB,0x34,0x16,0x33,0xE8,0xE4,0x53,0xBE,0xA9,
|
||||
0xB1,0x3A,0x3E,0xF5,0x90,0x6A,0xCF,0x3B,0x12,0xFD,0x8F,0x9A,0xA7,0x47,0x91,0x99,
|
||||
0xEB, 0xF,0x24,0xFF,0x23,0x18,0x85,0x4E,0x7F, 0xC,0xE0,0xA1,0xD2,0xD1,0x2C,0x2A,
|
||||
0x4A, 2,0x4F,0x1E,0x95,0x68,0x8B,0x98,0x83,0x6D,0x76,0xCA,0x65,0x32,0x13,0x2F,
|
||||
},
|
||||
{
|
||||
0xC3,0x82,0x9A,0xA4,0xBA,0x81,0x60,0x37,0x34,0x35,0xFC,0x80,0xA8,0x51,0x65,0x67,
|
||||
0xED,0x30,0x5F,0x10,0xD3,0x4A,0x27,0x2F,0x13,0xB9,0x2A,0xD2,0xCC,0xE1,0xEF,0xAE,
|
||||
0xEB,0xBE,0xF4,0xBD,0xCF,0x43,0xB3,0xC5,0x88,0x84,0xB7,0xDD,0x39,0x40,0xCE,0x48,
|
||||
0x6D,0x9B,0x72,0x61,0x7E,0xE7,0xA1,0x4E,0x53,0x2E,0x77,0x3B,0xE2,0xC9,0x36,0x22,
|
||||
0x1B,0x6E,0x73,0xB1, 3,0xB2,0x4C,0x87,0xA9,0xD4,0x4D, 0xF,0xD8,0x15,0x6C,0xAA,
|
||||
0x18,0xF6,0x49,0x57,0x5D,0xFB,0x7A,0x14,0x94,0x63,0xA0,0x11,0xB0,0x9E,0xDE, 5,
|
||||
0x46,0xC8,0xEE,0x47,0xDB,0xDC,0x24,0x89,0x9C,0x91,0x97,0x29,0xE9,0x7B,0xC1, 7,
|
||||
0x1E,0xB8,0xFD,0xFE,0xAC,0xC6,0x62,0x98,0x4F,0xF1,0x79,0xE0,0xE8,0x6B,0x78,0x56,
|
||||
0xB6,0x8D, 4,0x50,0x86,0xCA,0x6F,0x20,0xE6,0xEA,0xE5,0x76,0x17,0x1C,0x74,0x7F,
|
||||
0xBC, 0xD,0x2C,0x85,0xF7,0x66,0x96,0xE4,0x8B,0x75,0x3F,0x4B,0xD9,0x38,0xAF,0x7C,
|
||||
0xDA, 0xB,0x83,0x2D,0x31,0x32,0xA2,0xF5,0x1D,0x59,0x41,0x45,0xBF,0x3C,0x1F,0xF8,
|
||||
0xF9,0x8A,0xD0,0x16,0x25,0x69,0x12,0x99,0x9D,0x21,0x95,0xAB, 1,0xA6,0xD7,0xB5,
|
||||
0xC0,0x7D,0xFF,0x58, 0xE,0x3A,0x92,0xD1,0x55,0xE3, 8,0x9F,0xD6,0x3E,0x52,0x8E,
|
||||
0xFA,0xA3,0xC7, 2,0xCD,0xDF,0x8F,0x64,0x19,0x8C,0xF3,0xA7, 0xC,0x5E, 0xA,0x6A,
|
||||
9,0xF0,0x93,0x5B,0x42,0xC2, 6,0x23,0xEC,0x71,0xAD,0xB4,0xCB,0xBB,0x70,0x28,
|
||||
0xD5,0x1A,0x5C,0x33,0x68,0x5A, 0,0x44,0x90,0xA5,0xC4,0x26,0x3D,0x2B,0xF2,0x54,
|
||||
},
|
||||
{
|
||||
0x96,0xAD,0xDA,0x1F,0xED,0x33,0xE1,0x81,0x69, 8, 0xD, 0xA,0xDB,0x35,0x77,0x9A,
|
||||
0x64,0xD1,0xFC,0x78,0xAA,0x1B,0xD0,0x67,0xA0,0xDD,0xFA,0x6C,0x63,0x71, 5,0x84,
|
||||
0x17,0x6A,0x89,0x4F,0x66,0x7F,0xC6,0x50,0x55,0x92,0x6F,0xBD,0xE7,0xD2,0x40,0x72,
|
||||
0x8D,0xBB,0xEC, 6,0x42,0x8A,0xE4,0x88,0x9D,0x7E,0x7A,0x82,0x27,0x13,0x41,0x1A,
|
||||
0xAF,0xC8,0xA4,0x76,0xB4,0xC2,0xFE,0x6D,0x1C,0xD9,0x61,0x30,0xB3,0x7C,0xEA,0xF7,
|
||||
0x29, 0xF,0xF2,0x3B,0x51,0xC1,0xDE,0x5F,0xE5,0x2A,0x2F,0x99, 0xB,0x5D,0xA3,0x2B,
|
||||
0x4A,0xAB,0x95,0xA5,0xD3,0x58,0x56,0xEE,0x28,0x31, 0,0xCC,0x15,0x46,0xCA,0xE6,
|
||||
0x86,0x38,0x3C,0x65,0xF5,0xE3,0x9F,0xD6,0x5B, 9,0x49,0x83,0x70,0x2D,0x53,0xA9,
|
||||
0x7D,0xE2,0xC4,0xAC,0x8E,0x5E,0xB8,0x25,0xF4,0xB9,0x57,0xF3,0xF1,0x68,0x47,0xB2,
|
||||
0xA2,0x59,0x20,0xCE,0x34,0x79,0x5C,0x90, 0xE,0x1E,0xBE,0xD5,0x22,0x23,0xB1,0xC9,
|
||||
0x18,0x62,0x16,0x2E,0x91,0x3E, 7,0x8F,0xD8,0x3F,0x93,0x3D,0xD4,0x9B,0xDF,0x85,
|
||||
0x21,0xFB,0x11,0x74,0x97,0xC7,0xD7,0xDC,0x4C,0x19,0x45,0x98,0xE9,0x43, 2,0x4B,
|
||||
0xBC,0xC3, 4,0x9C,0x6B,0xF0,0x75,0x52,0xA7,0x26,0xF6,0xC5,0xBA,0xCF,0xB0,0xB7,
|
||||
0xAE,0x5A,0xA1,0xBF, 3,0x8B,0x80,0x12,0x6E, 0xC,0xEB,0xF9,0xC0,0x44,0x24,0xEF,
|
||||
0x10,0xF8,0xA8,0x8C,0xE8,0x7B,0xFF,0x9E,0x2C,0xCD,0x60,0x36,0x87,0xB5,0x94,0xA6,
|
||||
0x54,0x73,0x3A,0x14,0x4E, 1,0x1D,0xB6,0xFD,0x37,0x48,0x4D,0x39,0xCB,0xE0,0x32,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static inline u8 ror8(u8 a, u8 b) {
|
||||
return (a>>b) | ((a<<(8-b))&0xff);
|
||||
}
|
||||
|
||||
|
||||
void genkey(u8 *rand, u8 idx, u8 *key)
|
||||
{
|
||||
u8 *ans = ans_tbl[idx];
|
||||
u8 t0[10];
|
||||
int i;
|
||||
|
||||
for(i=0;i<10;i++)
|
||||
t0[i] = tsbox[rand[i]];
|
||||
|
||||
key[0] = ((ror8((ans[0]^t0[5]),(t0[2]%8)) - t0[9]) ^ t0[4]);
|
||||
key[1] = ((ror8((ans[1]^t0[1]),(t0[0]%8)) - t0[5]) ^ t0[7]);
|
||||
key[2] = ((ror8((ans[2]^t0[6]),(t0[8]%8)) - t0[2]) ^ t0[0]);
|
||||
key[3] = ((ror8((ans[3]^t0[4]),(t0[7]%8)) - t0[3]) ^ t0[2]);
|
||||
key[4] = ((ror8((ans[4]^t0[1]),(t0[6]%8)) - t0[3]) ^ t0[4]);
|
||||
key[5] = ((ror8((ans[5]^t0[7]),(t0[8]%8)) - t0[5]) ^ t0[9]);
|
||||
}
|
||||
|
||||
|
||||
void gentabs(u8 *rand, u8 *key, u8 idx, u8 *ft, u8 *sb)
|
||||
{
|
||||
ft[0] = sboxes[idx][key[4]] ^ sboxes[(idx+1)%8][rand[3]];
|
||||
ft[1] = sboxes[idx][key[2]] ^ sboxes[(idx+1)%8][rand[5]];
|
||||
ft[2] = sboxes[idx][key[5]] ^ sboxes[(idx+1)%8][rand[7]];
|
||||
ft[3] = sboxes[idx][key[0]] ^ sboxes[(idx+1)%8][rand[2]];
|
||||
ft[4] = sboxes[idx][key[1]] ^ sboxes[(idx+1)%8][rand[4]];
|
||||
ft[5] = sboxes[idx][key[3]] ^ sboxes[(idx+1)%8][rand[9]];
|
||||
ft[6] = sboxes[idx][rand[0]] ^ sboxes[(idx+1)%8][rand[6]];
|
||||
ft[7] = sboxes[idx][rand[1]] ^ sboxes[(idx+1)%8][rand[8]];
|
||||
|
||||
sb[0] = sboxes[idx][key[0]] ^ sboxes[(idx+1)%8][rand[1]];
|
||||
sb[1] = sboxes[idx][key[5]] ^ sboxes[(idx+1)%8][rand[4]];
|
||||
sb[2] = sboxes[idx][key[3]] ^ sboxes[(idx+1)%8][rand[0]];
|
||||
sb[3] = sboxes[idx][key[2]] ^ sboxes[(idx+1)%8][rand[9]];
|
||||
sb[4] = sboxes[idx][key[4]] ^ sboxes[(idx+1)%8][rand[7]];
|
||||
sb[5] = sboxes[idx][key[1]] ^ sboxes[(idx+1)%8][rand[8]];
|
||||
sb[6] = sboxes[idx][rand[3]] ^ sboxes[(idx+1)%8][rand[5]];
|
||||
sb[7] = sboxes[idx][rand[2]] ^ sboxes[(idx+1)%8][rand[6]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Generate key from the 0x40-0x4c data in g_RegExt */
|
||||
void wiimote_gen_key(wiimote_key *key, u8 *keydata)
|
||||
{
|
||||
u8 rand[10];
|
||||
u8 skey[6];
|
||||
u8 testkey[6];
|
||||
int idx;
|
||||
|
||||
for(int i=0;i<10;i++)
|
||||
rand[9-i] = keydata[i];
|
||||
for(int i=0;i<6;i++)
|
||||
skey[5-i] = keydata[i+10];
|
||||
|
||||
DEBUG_LOG(WIIMOTE, "rand: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", rand[0], rand[1], rand[2], rand[3], rand[4], rand[5], rand[6], rand[7], rand[8], rand[9]);
|
||||
DEBUG_LOG(WIIMOTE, "key: %02x %02x %02x %02x %02x %02x", skey[0], skey[1], skey[2], skey[3], skey[4], skey[5]);
|
||||
|
||||
for(idx = 0; idx < 7; idx++)
|
||||
{
|
||||
genkey(rand, idx, testkey);
|
||||
if(!memcmp(testkey, skey, 6))
|
||||
break;
|
||||
}
|
||||
// default case is idx = 7 which is valid (homebrew uses it for the 0x17 case)
|
||||
DEBUG_LOG(WIIMOTE, "idx: %d", idx);
|
||||
|
||||
gentabs(rand, skey, idx, key->ft, key->sb);
|
||||
|
||||
DEBUG_LOG(WIIMOTE, "ft: %02x %02x %02x %02x %02x %02x %02x %02x", key->ft[0], key->ft[1], key->ft[2], key->ft[3], key->ft[4], key->ft[5], key->ft[6], key->ft[7]);
|
||||
DEBUG_LOG(WIIMOTE, "sb: %02x %02x %02x %02x %02x %02x %02x %02x", key->sb[0], key->sb[1], key->sb[2], key->sb[3], key->sb[4], key->sb[5], key->sb[6], key->sb[7]);
|
||||
|
||||
// for homebrew, ft and sb are all 0x97 which is equivalent to 0x17
|
||||
}
|
||||
|
||||
|
||||
/* Encrypt data */
|
||||
void wiimote_encrypt(wiimote_key *key, u8 *data, int addr, u8 len)
|
||||
{
|
||||
for(int i = 0; i < len; i++, addr++)
|
||||
data[i] = (data[i] - key->ft[addr%8]) ^ key->sb[addr%8];
|
||||
}
|
||||
|
||||
|
||||
/* Decrypt data */
|
||||
void wiimote_decrypt(wiimote_key *key, u8 *data, int addr, u8 len)
|
||||
{
|
||||
for(int i = 0; i < len; i++, addr++)
|
||||
data[i] = (data[i] ^ key->sb[addr%8]) + key->ft[addr%8];
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
// Copyright (C) Hector Martin "marcan" ([email protected])
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#ifndef WIIMOTE_EXTENSION_ENCRYPTION_H
|
||||
#define WIIMOTE_EXTENSION_ENCRYPTION_H
|
||||
|
||||
|
||||
// ===================================================
|
||||
/* They key structure to use with wiimote_gen_key() */
|
||||
// ----------------
|
||||
typedef struct {
|
||||
u8 ft[8];
|
||||
u8 sb[8];
|
||||
} wiimote_key;
|
||||
|
||||
|
||||
void wiimote_encrypt(wiimote_key *key, u8 *data, int addr, u8 len);
|
||||
void wiimote_decrypt(wiimote_key *key, u8 *data, int addr, u8 len);
|
||||
|
||||
void wiimote_gen_key(wiimote_key *key, u8 *keydata);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,397 +0,0 @@
|
||||
// Copyright (C) 2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// !! !!
|
||||
// !! THIS CODE IS UNUSED !!
|
||||
// !! !!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
#include "FakeAccelerometer.h"
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
// Wiimote accelerometer
|
||||
/* The accelerometer x, y and z values range from 0x00 to 0xff with the default
|
||||
netural values being [y = 0x84, x = 0x84, z = 0x9f] according to a
|
||||
source. The extremes are 0x00 for (-) and 0xff for (+). It's important that
|
||||
all values are not 0x80, the mouse pointer can disappear from the screen
|
||||
permanently then, until z is adjusted back. This is because the game detects
|
||||
a steep pitch of the Wiimote then.
|
||||
|
||||
Wiimote Accelerometer Axes
|
||||
|
||||
+ (- -- X -- +)
|
||||
| ___
|
||||
| | |\ -
|
||||
| | + || \
|
||||
| . || \
|
||||
Y |. .|| Z
|
||||
| . || \
|
||||
| | . || \
|
||||
| |___|| +
|
||||
- ---
|
||||
|
||||
*/
|
||||
|
||||
void FakeAccelerometer::StartShake() {
|
||||
StartShake(*this);
|
||||
}
|
||||
|
||||
void FakeAccelerometer::StartShake(ShakeData &shakeData) {
|
||||
if (shakeData.Shake <= 0) shakeData.Shake = 1;
|
||||
}
|
||||
|
||||
// Single shake step of all three directions
|
||||
void FakeAccelerometer::SingleShake() {
|
||||
SingleShake(this->x, this->y, this->z, *((ShakeData*)this));
|
||||
}
|
||||
|
||||
void FakeAccelerometer::SingleShake(int &_x, int &_y, int &_z, ShakeData &shakeData)
|
||||
{
|
||||
// if (shakeData.Shake == 0)
|
||||
// {
|
||||
// if((wm == 0 && IsKey(g_Wiimote_kbd.SHAKE)) || (wm == 1 && IsKey(g_NunchuckExt.SHAKE)))
|
||||
// Shake[wm] = 1;
|
||||
// }
|
||||
switch(shakeData.Shake)
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
_x = g_wm.cal_zero.x / 2;
|
||||
_y = g_wm.cal_zero.y / 2;
|
||||
_z = g_wm.cal_zero.z / 2;
|
||||
break;
|
||||
case 5:
|
||||
case 7:
|
||||
_x = (0xFF - g_wm.cal_zero.x ) / 2;
|
||||
_y = (0xFF - g_wm.cal_zero.y ) / 2;
|
||||
_z = (0xFF - g_wm.cal_zero.z ) / 2;
|
||||
break;
|
||||
case 2:
|
||||
_x = 0x00;
|
||||
_y = 0x00;
|
||||
_z = 0x00;
|
||||
break;
|
||||
case 6:
|
||||
_x = 0xFF;
|
||||
_y = 0xFF;
|
||||
_z = 0xFF;
|
||||
break;
|
||||
case 4:
|
||||
_x = 0x80;
|
||||
_y = 0x80;
|
||||
_z = 0x80;
|
||||
break;
|
||||
default:
|
||||
shakeData.Shake = -1;
|
||||
break;
|
||||
}
|
||||
shakeData.Shake++;
|
||||
//if (Shake[wm] != 0) DEBUG_LOG(WIIMOTE, "Shake: %i - 0x%02x, 0x%02x, 0x%02x", Shake[wm], _x, _y, _z);
|
||||
}
|
||||
|
||||
|
||||
/* Tilting Wiimote with gamepad. We can guess that the game will calculate a
|
||||
Wiimote pitch and use it as a measure of the tilting of the Wiimote. We are
|
||||
interested in this tilting range 90 to -90*/
|
||||
void FakeAccelerometer::TiltWiimoteGamepad() {
|
||||
TiltWiimoteGamepad(this->Roll, this->Pitch);
|
||||
}
|
||||
|
||||
void FakeAccelerometer::TiltWiimoteGamepad(int &Roll, int &Pitch)
|
||||
{
|
||||
// Return if we have no pads
|
||||
if (NumGoodPads == 0) return;
|
||||
|
||||
// This has to be changed if multiple Wiimotes are to be supported later
|
||||
const int Page = 0;
|
||||
|
||||
/* Adjust the pad state values, including a downscaling from the original
|
||||
0x8000 size values to 0x80. The only reason we do this is that the code
|
||||
below crrently assume that the range is 0 to 255 for all axes. If we
|
||||
lose any precision by doing this we could consider not doing this
|
||||
adjustment. And instead for example upsize the XInput trigger from 0x80
|
||||
to 0x8000. */
|
||||
int Lx, Ly, Rx, Ry, Tl, Tr;
|
||||
PadStateAdjustments(Lx, Ly, Rx, Ry, Tl, Tr);
|
||||
|
||||
// Save the Range in degrees, 45 and 90 are good values in some games
|
||||
int &RollRange = g_Config.Tilt.Range.Roll;
|
||||
int &PitchRange = g_Config.Tilt.Range.Pitch;
|
||||
|
||||
// The trigger currently only controls pitch
|
||||
if (g_Config.Tilt.Type == g_Config.Tilt.TRIGGER)
|
||||
{
|
||||
// Make the range the same dimension as the analog stick
|
||||
Tl = Tl / 2;
|
||||
Tr = Tr / 2;
|
||||
// Invert
|
||||
if (PadMapping[Page].bPitchInvert) { Tl = -Tl; Tr = -Tr; }
|
||||
// The final value
|
||||
Pitch = (float)PitchRange * ((float)(Tl - Tr) / 128.0f);
|
||||
}
|
||||
|
||||
/* For the analog stick roll is by default set to the X-axis, pitch is by
|
||||
default set to the Y-axis. By changing the axis mapping and the invert
|
||||
options this can be altered in any way */
|
||||
else if (g_Config.Tilt.Type == g_Config.Tilt.ANALOG1)
|
||||
{
|
||||
// Adjust the trigger to go between negative and positive values
|
||||
Lx = Lx - 0x80;
|
||||
Ly = Ly - 0x80;
|
||||
// Invert
|
||||
if (PadMapping[Page].bRollInvert) Lx = -Lx; // else Tr = -Tr;
|
||||
if (PadMapping[Page].bPitchInvert) Ly = -Ly; // else Tr = -Tr;
|
||||
// Produce the final value
|
||||
Roll = (RollRange) ? (float)RollRange * ((float)Lx / 128.0f) : Lx;
|
||||
Pitch = (PitchRange) ? (float)PitchRange * ((float)Ly / 128.0f) : Ly;
|
||||
}
|
||||
// Otherwise we are using ANALOG2
|
||||
else
|
||||
{
|
||||
// Adjust the trigger to go between negative and positive values
|
||||
Rx = Rx - 0x80;
|
||||
Ry = Ry - 0x80;
|
||||
// Invert
|
||||
if (PadMapping[Page].bRollInvert) Rx = -Rx; // else Tr = -Tr;
|
||||
if (PadMapping[Page].bPitchInvert) Ry = -Ry; // else Tr = -Tr;
|
||||
// Produce the final value
|
||||
Roll = (RollRange) ? (float)RollRange * ((float)Rx / 128.0f) : Rx;
|
||||
Pitch = (PitchRange) ? (float)PitchRange * ((float)Ry / 128.0f) : Ry;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Tilting Wiimote with keyboard
|
||||
void FakeAccelerometer::TiltWiimoteKeyboard() {
|
||||
TiltWiimoteKeyboard(this->Roll, this->Pitch);
|
||||
}
|
||||
|
||||
void FakeAccelerometer::TiltWiimoteKeyboard(int &Roll, int &Pitch)
|
||||
{
|
||||
// Direct map roll/pitch to swing
|
||||
if (g_Config.Tilt.Range.Roll == 0 && g_Config.Tilt.Range.Pitch == 0)
|
||||
{
|
||||
if (IsKey(g_Wiimote_kbd.ROLL_L))
|
||||
Roll = -0x80 / 2;
|
||||
else if (IsKey(g_Wiimote_kbd.ROLL_R))
|
||||
Roll = 0x80 / 2;
|
||||
else
|
||||
Roll = 0;
|
||||
if (IsKey(g_Wiimote_kbd.PITCH_U))
|
||||
Pitch = -0x80 / 2;
|
||||
else if (IsKey(g_Wiimote_kbd.PITCH_D))
|
||||
Pitch = 0x80 / 2;
|
||||
else
|
||||
Pitch = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise do roll/pitch
|
||||
if (IsKey(g_Wiimote_kbd.ROLL_L))
|
||||
{
|
||||
// Stop at the upper end of the range
|
||||
if (Roll < g_Config.Tilt.Range.Roll)
|
||||
Roll += 3; // aim left
|
||||
}
|
||||
else if (IsKey(g_Wiimote_kbd.ROLL_R))
|
||||
{
|
||||
// Stop at the lower end of the range
|
||||
if (Roll > -g_Config.Tilt.Range.Roll)
|
||||
Roll -= 3; // aim right
|
||||
}
|
||||
else
|
||||
{
|
||||
Roll = 0;
|
||||
}
|
||||
if (IsKey(g_Wiimote_kbd.PITCH_U))
|
||||
{
|
||||
// Stop at the upper end of the range
|
||||
if (Pitch < g_Config.Tilt.Range.Pitch)
|
||||
Pitch += 3; // aim up
|
||||
}
|
||||
else if (IsKey(g_Wiimote_kbd.PITCH_D))
|
||||
{
|
||||
// Stop at the lower end of the range
|
||||
if (Pitch > -g_Config.Tilt.Range.Pitch)
|
||||
Pitch -= 3; // aim down
|
||||
}
|
||||
else
|
||||
{
|
||||
Pitch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Tilting Wiimote (Wario Land aiming, Mario Kart steering and other things)
|
||||
void FakeAccelerometer::Tilt() {
|
||||
Tilt(this->x, this->y, this->z);
|
||||
}
|
||||
|
||||
void FakeAccelerometer::Tilt(int &_x, int &_y, int &_z)
|
||||
{
|
||||
// Check if it's on
|
||||
if (g_Config.Tilt.Type == g_Config.Tilt.OFF) return;
|
||||
|
||||
// Select input method and return the x, y, x values
|
||||
if (g_Config.Tilt.Type == g_Config.Tilt.KEYBOARD)
|
||||
TiltWiimoteKeyboard();
|
||||
else if (g_Config.Tilt.Type == g_Config.Tilt.TRIGGER || g_Config.Tilt.Type == g_Config.Tilt.ANALOG1 || g_Config.Tilt.Type == g_Config.Tilt.ANALOG2)
|
||||
TiltWiimoteGamepad();
|
||||
|
||||
// Adjust angles, it's only needed if both roll and pitch is used together
|
||||
if (g_Config.Tilt.Range.Roll != 0 && g_Config.Tilt.Range.Pitch != 0)
|
||||
AdjustAngles(Roll, Pitch);
|
||||
|
||||
// Calculate the accelerometer value from this tilt angle
|
||||
PitchDegreeToAccelerometer(Roll, Pitch, _x, _y, _z);
|
||||
|
||||
//DEBUG_LOG(WIIMOTE, "Roll:%i, Pitch:%i, _x:%u, _y:%u, _z:%u", Roll, Pitch, _x, _y, _z);
|
||||
}
|
||||
|
||||
void FakeAccelerometer::FillReportAcc(wm_accel& _acc)
|
||||
{
|
||||
// Recorded movements
|
||||
// Check for a playback command
|
||||
if(g_RecordingPlaying[0] < 0)
|
||||
{
|
||||
g_RecordingPlaying[0] = RecordingCheckKeys(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the recording reached the end or failed somehow we will not return
|
||||
if (RecordingPlay(_acc.x, _acc.y, _acc.z, 0))
|
||||
return;
|
||||
//DEBUG_LOG(WIIMOTE, "X, Y, Z: %u %u %u", _acc.x, _acc.y, _acc.z);
|
||||
}
|
||||
|
||||
// Initial value
|
||||
x = g_wm.cal_zero.x;
|
||||
y = g_wm.cal_zero.y;
|
||||
z = g_wm.cal_zero.z;
|
||||
|
||||
if (!g_Config.bUpright)
|
||||
z += g_wm.cal_g.z;
|
||||
else // Upright wiimote
|
||||
y -= g_wm.cal_g.y;
|
||||
|
||||
// Check that Dolphin is in focus
|
||||
if (IsFocus())
|
||||
{
|
||||
// Check for shake button
|
||||
if(IsKey(g_Wiimote_kbd.SHAKE)) StartShake();
|
||||
// Step the shake simulation one step
|
||||
SingleShake();
|
||||
|
||||
// Tilt Wiimote, allow the shake function to interrupt it
|
||||
if (g_Wiimote_kbd.shakeData.Shake == 0) Tilt();
|
||||
|
||||
// Boundary check
|
||||
if (x > 0xFF) x = 0xFF;
|
||||
else if (x < 0x00) x = 0x00;
|
||||
if (y > 0xFF) y = 0xFF;
|
||||
else if (y < 0x00) y = 0x00;
|
||||
if (z > 0xFF) z = 0xFF;
|
||||
else if (z < 0x00) z = 0x00;
|
||||
}
|
||||
|
||||
_acc.x = x;
|
||||
_acc.y = y;
|
||||
_acc.z = z;
|
||||
|
||||
// Debugging for translating Wiimote to Keyboard (or Gamepad)
|
||||
/*
|
||||
|
||||
// Toogle console display
|
||||
if(GetAsyncKeyState('U'))
|
||||
{
|
||||
if(consoleDisplay < 2)
|
||||
consoleDisplay ++;
|
||||
else
|
||||
consoleDisplay = 0;
|
||||
}
|
||||
|
||||
if(GetAsyncKeyState('5'))
|
||||
A-=1;
|
||||
else if(GetAsyncKeyState('6'))
|
||||
A+=1;
|
||||
if(GetAsyncKeyState('7'))
|
||||
B-=1;
|
||||
else if(GetAsyncKeyState('8'))
|
||||
B+=1;
|
||||
if(GetAsyncKeyState('9'))
|
||||
C-=1;
|
||||
else if(GetAsyncKeyState('0'))
|
||||
C+=1;
|
||||
|
||||
else if(GetAsyncKeyState(VK_NUMPAD3))
|
||||
d-=1;
|
||||
else if(GetAsyncKeyState(VK_NUMPAD6))
|
||||
d+=1;
|
||||
else if(GetAsyncKeyState(VK_ADD))
|
||||
yhistsize-=1;
|
||||
else if(GetAsyncKeyState(VK_SUBTRACT))
|
||||
yhistsize+=1;
|
||||
|
||||
|
||||
if(GetAsyncKeyState(VK_INSERT))
|
||||
AX-=1;
|
||||
else if(GetAsyncKeyState(VK_DELETE))
|
||||
AX+=1;
|
||||
else if(GetAsyncKeyState(VK_HOME))
|
||||
AY-=1;
|
||||
else if(GetAsyncKeyState(VK_END))
|
||||
AY+=1;
|
||||
else if(GetAsyncKeyState(VK_SHIFT))
|
||||
AZ-=1;
|
||||
else if(GetAsyncKeyState(VK_CONTROL))
|
||||
AZ+=1;
|
||||
|
||||
if(GetAsyncKeyState(VK_NUMPAD1))
|
||||
X+=1;
|
||||
else if(GetAsyncKeyState(VK_NUMPAD2))
|
||||
X-=1;
|
||||
if(GetAsyncKeyState(VK_NUMPAD4))
|
||||
Y+=1;
|
||||
else if(GetAsyncKeyState(VK_NUMPAD5))
|
||||
Y-=1;
|
||||
if(GetAsyncKeyState(VK_NUMPAD7))
|
||||
Z+=1;
|
||||
else if(GetAsyncKeyState(VK_NUMPAD8))
|
||||
Z-=1;
|
||||
|
||||
//if(consoleDisplay == 0)
|
||||
DEBUG_LOG(WIIMOTE, "x: %03i | y: %03i | z: %03i | A:%i B:%i C:%i a:%i b:%i c:%i d:%i X:%i Y:%i Z:%i",
|
||||
_acc.x, _acc.y, _acc.z,
|
||||
A, B, C,
|
||||
a, b, c, d,
|
||||
X, Y, Z
|
||||
);
|
||||
DEBUG_LOG(WIIMOTE, "x: %03i | y: %03i | z: %03i | X:%i Y:%i Z:%i | AX:%i AY:%i AZ:%i ",
|
||||
_acc.x, _acc.y, _acc.z,
|
||||
X, Y, Z,
|
||||
AX, AY, AZ
|
||||
);*/
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright (C) 2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// !! !!
|
||||
// !! THIS CODE IS UNUSED !!
|
||||
// !! !!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
#ifndef FAKEACCELEROMETER_H
|
||||
#define FAKEACCELEROMETER_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "Timer.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
#include "StringUtil.h" // For ArrayToString
|
||||
|
||||
#include "wiimote_hid.h"
|
||||
#include "main.h"
|
||||
#include "EmuMain.h"
|
||||
#include "EmuSubroutines.h"
|
||||
#include "EmuDefinitions.h"
|
||||
#include "Config.h" // For g_Config
|
||||
|
||||
namespace WiiMoteEmu {
|
||||
|
||||
extern int IsKey(int Key);
|
||||
extern bool RecordingCheckKeys(int WmNuIr);
|
||||
extern bool RecordingPlay(u8 &_x, u8 &_y, u8 &_z, int Wm);
|
||||
|
||||
class FakeAccelerometer : ShakeData {
|
||||
private:
|
||||
int x, y, z;
|
||||
public:
|
||||
void StartShake();
|
||||
void StartShake(ShakeData &shakeData);
|
||||
void SingleShake();
|
||||
void SingleShake(int &_x, int &_y, int &_z, ShakeData &shakeData);
|
||||
void TiltWiimoteGamepad();
|
||||
void TiltWiimoteGamepad(int &Roll, int &Pitch);
|
||||
void TiltWiimoteKeyboard();
|
||||
void TiltWiimoteKeyboard(int &Roll, int &Pitch);
|
||||
void Tilt();
|
||||
void Tilt(int &_x, int &_y, int &_z);
|
||||
void FillReportAcc(wm_accel& _acc);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,405 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
//
|
||||
|
||||
#include "EmuDefinitions.h"
|
||||
#ifdef _WIN32
|
||||
#include "XInput.h"
|
||||
#endif
|
||||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
// SDL Haptic fails on windows, it just doesn't work (even the sample doesn't work)
|
||||
// So until i can make it work, this is all disabled >:(
|
||||
#if SDL_VERSION_ATLEAST(1, 3, 0) && !defined(_WIN32) && !defined(__APPLE__)
|
||||
#define SDL_RUMBLE
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
#define RUMBLE_HACK
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#pragma comment(lib, "dxguid.lib")
|
||||
#pragma comment(lib, "dinput8.lib")
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
#include <dinput.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef RUMBLE_HACK
|
||||
|
||||
struct RUMBLE // GC Pad rumble DIDevice
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 g_pDevice; // 4 pads objects
|
||||
LPDIRECTINPUTEFFECT g_pEffect;
|
||||
DWORD g_dwNumForceFeedbackAxis;
|
||||
DIEFFECT eff;
|
||||
};
|
||||
|
||||
#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
|
||||
|
||||
BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext);
|
||||
BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext);
|
||||
void SetDeviceForcesXY(int pad, int nXYForce);
|
||||
HRESULT InitRumble(HWND hWnd);
|
||||
void Rumble_DInput(int _ID, unsigned int _Strength);
|
||||
void Rumble_XInput(int _ID, unsigned int _Strength);
|
||||
|
||||
|
||||
LPDIRECTINPUT8 g_Rumble; // DInput Rumble object
|
||||
RUMBLE pRumble[MAX_WIIMOTES];
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Set PAD rumble. Explanation: Stop = 0, Rumble = 1
|
||||
void PAD_Rumble(u8 _numPAD, unsigned int _uType)
|
||||
{
|
||||
if (WiiMapping[_numPAD].ID >= NumPads || !WiiMapping[_numPAD].Rumble)
|
||||
return;
|
||||
|
||||
unsigned int Strength = 0;
|
||||
if (_uType == 1)
|
||||
{
|
||||
Strength = WiiMapping[_numPAD].RumbleStrength;
|
||||
Strength = Strength > 100 ? 100 : Strength;
|
||||
}
|
||||
|
||||
if (WiiMapping[_numPAD].TriggerType == InputCommon::CTL_TRIGGER_XINPUT)
|
||||
Rumble_XInput(WiiMapping[_numPAD].ID, Strength);
|
||||
else
|
||||
Rumble_DInput(WiiMapping[_numPAD].ID, Strength);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Set rumble with XInput.
|
||||
void Rumble_XInput(int _ID, unsigned int _Strength)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
XINPUT_VIBRATION vib;
|
||||
vib.wLeftMotorSpeed = 0xFFFF / 100 * _Strength;
|
||||
vib.wRightMotorSpeed = 0xFFFF / 100 * _Strength;
|
||||
XInputSetState(_ID, &vib);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Set rumble with DInput.¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
void Rumble_DInput(int _ID, unsigned int _Strength)
|
||||
{
|
||||
if (!g_Rumble)
|
||||
{
|
||||
// GetForegroundWindow() always sends the good HWND
|
||||
if (FAILED(InitRumble(GetForegroundWindow())))
|
||||
PanicAlert("Could not initialize Rumble!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Acquire gamepad
|
||||
if (pRumble[_ID].g_pDevice != NULL)
|
||||
pRumble[_ID].g_pDevice->Acquire();
|
||||
}
|
||||
|
||||
SetDeviceForcesXY(_ID, _Strength * 100);
|
||||
}
|
||||
|
||||
HRESULT InitRumble(HWND hWnd)
|
||||
{
|
||||
DIPROPDWORD dipdw;
|
||||
HRESULT hr;
|
||||
|
||||
// Register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use.
|
||||
if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_Rumble, NULL)))
|
||||
return hr;
|
||||
|
||||
// Look for a device we can use
|
||||
if (FAILED(hr = g_Rumble->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, NULL, DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK)))
|
||||
return hr;
|
||||
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
if (NULL == pRumble[i].g_pDevice)
|
||||
WiiMapping[i].Rumble = false; // Disable Rumble for this pad only.
|
||||
else
|
||||
{
|
||||
pRumble[i].g_pDevice->SetDataFormat(&c_dfDIJoystick);
|
||||
pRumble[i].g_pDevice->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND);
|
||||
// Request exclusive acces for both background and foreground.
|
||||
|
||||
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.dwData = FALSE;
|
||||
|
||||
// if Force Feedback doesn't seem to work...
|
||||
if (FAILED(pRumble[i].g_pDevice->EnumObjects(EnumAxesCallback,
|
||||
(void*)&pRumble[i].g_dwNumForceFeedbackAxis, DIDFT_AXIS))
|
||||
|| FAILED(pRumble[i].g_pDevice->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph)))
|
||||
{
|
||||
PanicAlert("Device %d doesn't seem to work ! \nRumble for device %d is now Disabled !", i+1);
|
||||
|
||||
WiiMapping[i].Rumble = false; // Disable Rumble for this pad
|
||||
|
||||
continue; // Next pad
|
||||
}
|
||||
|
||||
if (pRumble[i].g_dwNumForceFeedbackAxis > 2)
|
||||
pRumble[i].g_dwNumForceFeedbackAxis = 2;
|
||||
|
||||
DWORD _rgdwAxes[2] = {DIJOFS_X, DIJOFS_Y};
|
||||
long rglDirection[2] = {0, 0};
|
||||
DICONSTANTFORCE cf = {0};
|
||||
|
||||
ZeroMemory(&pRumble[i].eff, sizeof(pRumble[i].eff));
|
||||
pRumble[i].eff.dwSize = sizeof(DIEFFECT);
|
||||
pRumble[i].eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||
pRumble[i].eff.dwDuration = INFINITE; // fixed time may be safer (X * DI_SECONDS)
|
||||
pRumble[i].eff.dwSamplePeriod = 0;
|
||||
pRumble[i].eff.dwGain = DI_FFNOMINALMAX;
|
||||
pRumble[i].eff.dwTriggerButton = DIEB_NOTRIGGER;
|
||||
pRumble[i].eff.dwTriggerRepeatInterval = 0;
|
||||
pRumble[i].eff.cAxes = pRumble[i].g_dwNumForceFeedbackAxis;
|
||||
pRumble[i].eff.rgdwAxes = _rgdwAxes;
|
||||
pRumble[i].eff.rglDirection = rglDirection;
|
||||
pRumble[i].eff.lpEnvelope = 0;
|
||||
pRumble[i].eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE );
|
||||
pRumble[i].eff.lpvTypeSpecificParams = &cf;
|
||||
pRumble[i].eff.dwStartDelay = 0;
|
||||
|
||||
// Create the prepared effect
|
||||
if (FAILED(hr = pRumble[i].g_pDevice->CreateEffect(GUID_ConstantForce, &pRumble[i].eff, &pRumble[i].g_pEffect, NULL)))
|
||||
continue;
|
||||
|
||||
if (pRumble[i].g_pEffect == NULL)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void SetDeviceForcesXY(int npad, int nXYForce)
|
||||
{
|
||||
// Security check
|
||||
if (pRumble[npad].g_pDevice == NULL)
|
||||
return;
|
||||
|
||||
// If nXYForce is null, there's no point to create the effect
|
||||
// Just stop the force feedback
|
||||
if (nXYForce == 0) {
|
||||
pRumble[npad].g_pEffect->Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
long rglDirection[2] = {0};
|
||||
DICONSTANTFORCE cf;
|
||||
|
||||
// If only one force feedback axis, then apply only one direction and keep the direction at zero
|
||||
if (pRumble[npad].g_dwNumForceFeedbackAxis == 1)
|
||||
{
|
||||
rglDirection[0] = 0;
|
||||
cf.lMagnitude = nXYForce; // max should be 10000
|
||||
}
|
||||
// If two force feedback axis, then apply magnitude from both directions
|
||||
else
|
||||
{
|
||||
rglDirection[0] = nXYForce;
|
||||
rglDirection[1] = nXYForce;
|
||||
cf.lMagnitude = static_cast<LONG>(1.4142f*nXYForce);
|
||||
}
|
||||
|
||||
ZeroMemory(&pRumble[npad].eff, sizeof(pRumble[npad].eff));
|
||||
pRumble[npad].eff.dwSize = sizeof(DIEFFECT);
|
||||
pRumble[npad].eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||
pRumble[npad].eff.cAxes = pRumble[npad].g_dwNumForceFeedbackAxis;
|
||||
pRumble[npad].eff.rglDirection = rglDirection;
|
||||
pRumble[npad].eff.lpEnvelope = 0;
|
||||
pRumble[npad].eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
|
||||
pRumble[npad].eff.lpvTypeSpecificParams = &cf;
|
||||
pRumble[npad].eff.dwStartDelay = 0;
|
||||
|
||||
// Now set the new parameters..
|
||||
pRumble[npad].g_pEffect->SetParameters(&pRumble[npad].eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START);
|
||||
// ..And start the effect immediately.
|
||||
if (pRumble[npad].g_pEffect != NULL)
|
||||
pRumble[npad].g_pEffect->Start(1, 0);
|
||||
}
|
||||
|
||||
BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContext)
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 pDevice;
|
||||
DIPROPDWORD dipdw;
|
||||
HRESULT hr;
|
||||
|
||||
int JoystickID;
|
||||
|
||||
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
|
||||
g_Rumble->CreateDevice(pInst->guidInstance, &pDevice, NULL); // Create a DInput pad device
|
||||
|
||||
if (SUCCEEDED(hr = pDevice->GetProperty(DIPROP_JOYSTICKID, &dipdw.diph))) // Get DInput Device ID
|
||||
JoystickID = dipdw.dwData;
|
||||
else
|
||||
return DIENUM_CONTINUE;
|
||||
|
||||
//PanicAlert("DInput ID : %d \nSDL ID (1-4) : %d / %d / %d / %d\n", JoystickID, WiiMapping[0].ID, WiiMapping[1].ID, WiiMapping[2].ID, WiiMapping[3].ID);
|
||||
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
if (WiiMapping[i].ID == JoystickID) // if SDL ID = DInput ID -> we're dealing with the same device
|
||||
{
|
||||
// a DInput device is created even if rumble is disabled on startup
|
||||
// this way, you can toggle the rumble setting while in game
|
||||
pRumble[i].g_pDevice = pDevice; // everything looks good, save the DInput device
|
||||
}
|
||||
}
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext)
|
||||
{
|
||||
DWORD* pdwNumForceFeedbackAxis = (DWORD*)pContext; // Enum Rumble Axis
|
||||
if ((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0)
|
||||
(*pdwNumForceFeedbackAxis)++;
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
void PAD_RumbleClose()
|
||||
{
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
if (WiiMapping[i].ID < NumPads)
|
||||
if (WiiMapping[i].TriggerType == InputCommon::CTL_TRIGGER_XINPUT)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Kill Xpad rumble
|
||||
XINPUT_VIBRATION vib;
|
||||
vib.wLeftMotorSpeed = 0;
|
||||
vib.wRightMotorSpeed = 0;
|
||||
XInputSetState(WiiMapping[i].ID, &vib);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// It may look weird, but we don't free anything here, it was the cause of crashes
|
||||
// on stop, and the DLL isn't unloaded anyway, so the pointers stay
|
||||
// We just stop the rumble in case it's still playing an effect.
|
||||
if (pRumble[WiiMapping[i].ID].g_pDevice && pRumble[WiiMapping[i].ID].g_pEffect)
|
||||
pRumble[WiiMapping[i].ID].g_pEffect->Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // Multiplatform SDL Rumble code
|
||||
|
||||
#ifdef SDL_RUMBLE
|
||||
|
||||
struct RUMBLE // GC Pad rumble DIDevice
|
||||
{
|
||||
SDL_Haptic* g_pDevice;
|
||||
SDL_HapticEffect g_pEffect;
|
||||
int effect_id;
|
||||
};
|
||||
|
||||
RUMBLE pRumble[4] = {0}; // 4 GC Rumble Pads
|
||||
#endif
|
||||
|
||||
|
||||
// Use PAD rumble
|
||||
// --------------
|
||||
bool PAD_Init_Rumble(u8 _numPAD, SDL_Joystick *SDL_Device)
|
||||
{
|
||||
#ifdef SDL_RUMBLE
|
||||
if (SDL_Device == NULL)
|
||||
return false;
|
||||
|
||||
pRumble[_numPAD].g_pDevice = SDL_HapticOpenFromJoystick(SDL_Device);
|
||||
|
||||
if (pRumble[_numPAD].g_pDevice == NULL)
|
||||
return false; // Most likely joystick isn't haptic
|
||||
|
||||
if (!(SDL_HapticQuery(pRumble[_numPAD].g_pDevice) & SDL_HAPTIC_CONSTANT))
|
||||
{
|
||||
SDL_HapticClose(pRumble[_numPAD].g_pDevice); // No effect
|
||||
pRumble[_numPAD].g_pDevice = 0;
|
||||
WiiMapping[_numPAD].Rumble = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the strength of the rumble effect
|
||||
int Strenght = 3276 * (pRumble[_numPAD].RumbleStrength);
|
||||
Strenght = Strenght > 32767 ? 32767 : Strenght;
|
||||
|
||||
// Create the effect
|
||||
memset(&pRumble[_numPAD].g_pEffect, 0, sizeof(SDL_HapticEffect)); // 0 is safe default
|
||||
pRumble[_numPAD].g_pEffect.type = SDL_HAPTIC_CONSTANT;
|
||||
pRumble[_numPAD].g_pEffect.constant.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates
|
||||
pRumble[_numPAD].g_pEffect.constant.direction.dir[0] = 18000; // Force comes from south
|
||||
pRumble[_numPAD].g_pEffect.constant.level = Strenght;
|
||||
pRumble[_numPAD].g_pEffect.constant.length = 10000; // 10s long (should be INFINITE, but 10s is safer)
|
||||
pRumble[_numPAD].g_pEffect.constant.attack_length = 0; // disable Fade in...
|
||||
pRumble[_numPAD].g_pEffect.constant.fade_length = 0; // ...and out
|
||||
|
||||
// Upload the effect
|
||||
pRumble[_numPAD].effect_id = SDL_HapticNewEffect( pRumble[_numPAD].g_pDevice, &pRumble[_numPAD].g_pEffect );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Set PAD rumble. Explanation: Stop = 0, Rumble = 1
|
||||
// --------------
|
||||
void PAD_Rumble(u8 _numPAD, unsigned int _uType)
|
||||
{
|
||||
#ifdef SDL_RUMBLE
|
||||
if (WiiMapping[_numPAD].Rumble) // rumble activated
|
||||
{
|
||||
if (!pRumble[_numPAD].g_pDevice)
|
||||
return;
|
||||
|
||||
if (_uType == 1)
|
||||
SDL_HapticRunEffect( pRumble[_numPAD].g_pDevice, pRumble[_numPAD].effect_id, 1 );
|
||||
else
|
||||
SDL_HapticStopAll(pRumble[_numPAD].g_pDevice);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PAD_RumbleClose()
|
||||
{
|
||||
#ifdef SDL_RUMBLE
|
||||
for (int i=0; i<4; i++) // Free all pads
|
||||
{
|
||||
if (pRumble[i].g_pDevice) {
|
||||
SDL_HapticClose( pRumble[i].g_pDevice );
|
||||
pRumble[i].g_pDevice = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // RUMBLE_HACK
|
||||
|
||||
} // end of namespace
|
||||
@@ -1,37 +0,0 @@
|
||||
# -*- python -*-
|
||||
|
||||
Import('env')
|
||||
import os
|
||||
|
||||
name = os.sep + "Plugin_Wiimote"
|
||||
|
||||
files = [
|
||||
"Config.cpp",
|
||||
"DataReports.cpp",
|
||||
"EmuDefinitions.cpp",
|
||||
"EmuDynamics.cpp",
|
||||
"EmuMain.cpp",
|
||||
"EmuPad.cpp",
|
||||
"EmuSubroutines.cpp",
|
||||
"Encryption.cpp",
|
||||
"main.cpp",
|
||||
"Rumble.cpp",
|
||||
"UDPWiimote.cpp"
|
||||
]
|
||||
|
||||
libs = [ 'inputcommon', 'common', 'SDL' ]
|
||||
|
||||
if env['HAVE_WX']:
|
||||
libs = [ 'inputuicommon' ] + libs
|
||||
files += [
|
||||
"ConfigBasicDlg.cpp",
|
||||
"ConfigPadDlg.cpp",
|
||||
"ConfigGamepad.cpp",
|
||||
"FillReport.cpp",
|
||||
]
|
||||
|
||||
if env['HAVE_WIIUSE']:
|
||||
libs += [ 'wiiuse' ]
|
||||
files += [ 'wiimote_real.cpp' ]
|
||||
|
||||
env.SharedLibrary(env['plugin_dir'] + name, files, LIBS = libs + env['LIBS'])
|
||||
@@ -1,297 +0,0 @@
|
||||
#include "UDPWiimote.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#define sock_t SOCKET
|
||||
#define ERRNO WSAGetLastError()
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define BAD_SOCK INVALID_SOCKET
|
||||
#define close(x) closesocket(x)
|
||||
#define cleanup do {noinst--; if (noinst==0) WSACleanup();} while (0)
|
||||
#define blockingoff(sock) ioctlsocket(sock, FIONBIO, &iMode)
|
||||
#define dataz char*
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "Ws2_32.lib")
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#define BAD_SOCK -1
|
||||
#define ERRNO errno
|
||||
#define cleanup noinst--
|
||||
#define blockingoff(sock) fcntl(sock, F_SETFL, O_NONBLOCK)
|
||||
#define dataz void*
|
||||
#define sock_t int
|
||||
|
||||
#endif
|
||||
|
||||
#include "Thread.h"
|
||||
#include "EmuMain.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <list>
|
||||
|
||||
struct UDPWiimote::_d
|
||||
{
|
||||
Common::Thread * thread;
|
||||
std::list<sock_t> sockfds;
|
||||
Common::CriticalSection termLock,mutex;
|
||||
volatile bool exit;
|
||||
};
|
||||
|
||||
int UDPWiimote::noinst=0;
|
||||
|
||||
void _UDPWiiThread(void* arg)
|
||||
{
|
||||
((UDPWiimote*)arg)->mainThread();
|
||||
//NOTICE_LOG(WIIMOTE,"UDPWii thread stopped");
|
||||
}
|
||||
|
||||
THREAD_RETURN UDPWiiThread(void* arg)
|
||||
{
|
||||
_UDPWiiThread(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UDPWiimote::UDPWiimote(const char *port) :
|
||||
d(new _d) ,x(0),y(0),z(0),nunX(0),nunY(0),
|
||||
pointerX(-0.1),pointerY(-0.1),nunMask(0),mask(0),time(0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
u_long iMode = 1;
|
||||
#endif
|
||||
struct addrinfo hints, *servinfo, *p;
|
||||
int rv;
|
||||
d->thread=NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (noinst==0)
|
||||
{
|
||||
WORD sockVersion;
|
||||
WSADATA wsaData;
|
||||
sockVersion = MAKEWORD(2, 2);
|
||||
WSAStartup(sockVersion, &wsaData);
|
||||
}
|
||||
#endif
|
||||
|
||||
noinst++;
|
||||
// NOTICE_LOG(WIIMOTE,"UDPWii instantiated");
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_flags = AI_PASSIVE; // use my IP
|
||||
|
||||
if ((rv = getaddrinfo(NULL, port, &hints, &servinfo)) != 0) {
|
||||
cleanup;
|
||||
err=-1;
|
||||
return;
|
||||
}
|
||||
|
||||
// loop through all the results and bind to everything we can
|
||||
for(p = servinfo; p != NULL; p = p->ai_next) {
|
||||
sock_t sock;
|
||||
if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == BAD_SOCK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bind(sock, p->ai_addr, p->ai_addrlen) == -1) {
|
||||
close(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//NOTICE_LOG(WIIMOTE,"UDPWii new listening sock");
|
||||
d->sockfds.push_back(sock);
|
||||
}
|
||||
|
||||
if (d->sockfds.empty()) {
|
||||
cleanup;
|
||||
err=-2;
|
||||
return;
|
||||
}
|
||||
|
||||
freeaddrinfo(servinfo);
|
||||
err=0;
|
||||
d->exit=false;
|
||||
// NOTICE_LOG(WIIMOTE,"UDPWii thread starting");
|
||||
d->termLock.Enter();
|
||||
d->thread = new Common::Thread(UDPWiiThread,this);
|
||||
d->termLock.Leave();
|
||||
return;
|
||||
}
|
||||
|
||||
void UDPWiimote::mainThread()
|
||||
{
|
||||
d->termLock.Enter();
|
||||
// NOTICE_LOG(WIIMOTE,"UDPWii thread started");
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec=1;
|
||||
timeout.tv_usec=500000;
|
||||
//Common::Thread * thisthr= d->thread;
|
||||
do
|
||||
{
|
||||
int maxfd=0;
|
||||
FD_ZERO(&fds);
|
||||
for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++)
|
||||
{
|
||||
FD_SET(*i,&fds);
|
||||
#ifndef _WIN32
|
||||
if (*i>=maxfd)
|
||||
maxfd=(*i)+1;
|
||||
#endif
|
||||
}
|
||||
d->termLock.Leave();
|
||||
if (d->exit) return;
|
||||
int rt=select(maxfd,&fds,NULL,NULL,&timeout);
|
||||
if (d->exit) return;
|
||||
d->termLock.Enter();
|
||||
if (d->exit) return;
|
||||
if (rt)
|
||||
{
|
||||
for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++)
|
||||
if (FD_ISSET(*i,&fds))
|
||||
{
|
||||
sock_t fd=*i;
|
||||
u8 bf[64];
|
||||
int size=60;
|
||||
size_t addr_len;
|
||||
struct sockaddr_storage their_addr;
|
||||
addr_len = sizeof their_addr;
|
||||
if ((size = recvfrom(fd, (dataz)bf, size , 0,(struct sockaddr *)&their_addr, (socklen_t*)&addr_len)) == -1)
|
||||
{
|
||||
ERROR_LOG(WIIMOTE,"UDPWii Packet error");
|
||||
}
|
||||
else
|
||||
{
|
||||
d->mutex.Enter();
|
||||
if (pharsePacket(bf,size)==0)
|
||||
{
|
||||
//NOTICE_LOG(WIIMOTE,"UDPWII New pack");
|
||||
} else {
|
||||
//NOTICE_LOG(WIIMOTE,"UDPWII Wrong pack format... ignoring");
|
||||
}
|
||||
d->mutex.Leave();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
broadcastPresence();
|
||||
}
|
||||
} while (!(d->exit));
|
||||
d->termLock.Leave();
|
||||
//delete thisthr;
|
||||
}
|
||||
|
||||
UDPWiimote::~UDPWiimote()
|
||||
{
|
||||
d->exit=true;
|
||||
d->termLock.Enter();
|
||||
d->termLock.Leave();
|
||||
for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++)
|
||||
close(*i);
|
||||
cleanup;
|
||||
delete d;
|
||||
}
|
||||
|
||||
#define ACCEL_FLAG (1<<0)
|
||||
#define BUTT_FLAG (1<<1)
|
||||
#define IR_FLAG (1<<2)
|
||||
#define NUN_FLAG (1<<3)
|
||||
|
||||
int UDPWiimote::pharsePacket(u8 * bf, size_t size)
|
||||
{
|
||||
if (size<3) return -1;
|
||||
if (bf[0]!=0xde)
|
||||
return -1;
|
||||
if (bf[1]==0)
|
||||
time=0;
|
||||
if (bf[1]<time)
|
||||
return -1;
|
||||
time=bf[1];
|
||||
u32 *p=(u32*)(&bf[3]);
|
||||
if (bf[2]&ACCEL_FLAG)
|
||||
{
|
||||
if ((size-(((u8*)p)-bf))<12) return -1;
|
||||
double ux,uy,uz;
|
||||
ux=(double)((s32)ntohl(*p)); p++;
|
||||
uy=(double)((s32)ntohl(*p)); p++;
|
||||
uz=(double)((s32)ntohl(*p)); p++;
|
||||
x=ux/1048576; //packet accel data
|
||||
y=uy/1048576;
|
||||
z=uz/1048576;
|
||||
}
|
||||
if (bf[2]&BUTT_FLAG)
|
||||
{
|
||||
if ((size-(((u8*)p)-bf))<4) return -1;
|
||||
mask=ntohl(*p); p++;
|
||||
}
|
||||
if (bf[2]&IR_FLAG)
|
||||
{
|
||||
if ((size-(((u8*)p)-bf))<8) return -1;
|
||||
pointerX=((double)((s32)ntohl(*p)))/1048576; p++;
|
||||
pointerY=((double)((s32)ntohl(*p)))/1048576; p++;
|
||||
}
|
||||
if (bf[2]&NUN_FLAG)
|
||||
{
|
||||
if ((size-(((u8*)p)-bf))<9) return -1;
|
||||
nunMask=*((u8*)p); p=(u32*)(((u8*)p)+1);
|
||||
nunX=((double)((s32)ntohl(*p)))/1048576; p++;
|
||||
nunY=((double)((s32)ntohl(*p)))/1048576; p++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void UDPWiimote::broadcastPresence()
|
||||
{
|
||||
// NOTICE_LOG(WIIMOTE,"UDPWii broadcasting presence");
|
||||
}
|
||||
|
||||
void UDPWiimote::getAccel(float &_x, float &_y, float &_z)
|
||||
{
|
||||
d->mutex.Enter();
|
||||
_x=x;
|
||||
_y=y;
|
||||
_z=z;
|
||||
d->mutex.Leave();
|
||||
//NOTICE_LOG(WIIMOTE,"%lf %lf %lf",_x, _y, _z);
|
||||
}
|
||||
|
||||
u32 UDPWiimote::getButtons()
|
||||
{
|
||||
u32 msk;
|
||||
d->mutex.Enter();
|
||||
msk=mask;
|
||||
d->mutex.Leave();
|
||||
return msk;
|
||||
}
|
||||
|
||||
void UDPWiimote::getIR(float &_x, float &_y)
|
||||
{
|
||||
d->mutex.Enter();
|
||||
_x=(float)pointerX;
|
||||
_y=(float)pointerY;
|
||||
d->mutex.Leave();
|
||||
}
|
||||
|
||||
void UDPWiimote::getNunchuck(float &_x, float &_y, u8 &_mask)
|
||||
{
|
||||
d->mutex.Enter();
|
||||
_x=(float)nunX;
|
||||
_y=(float)nunY;
|
||||
_mask=nunMask;
|
||||
d->mutex.Leave();
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#ifndef UDPWIIMOTE_H
|
||||
#define UDPWIIMOTE_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#define UDPWM_B1 (1<<0)
|
||||
#define UDPWM_B2 (1<<1)
|
||||
#define UDPWM_BA (1<<2)
|
||||
#define UDPWM_BB (1<<3)
|
||||
#define UDPWM_BP (1<<4)
|
||||
#define UDPWM_BM (1<<5)
|
||||
#define UDPWM_BH (1<<6)
|
||||
#define UDPWM_BU (1<<7)
|
||||
#define UDPWM_BD (1<<8)
|
||||
#define UDPWM_BL (1<<9)
|
||||
#define UDPWM_BR (1<<10)
|
||||
#define UDPWM_SK (1<<11)
|
||||
#define UDPWM_NC (1<<0)
|
||||
#define UDPWM_NZ (1<<1)
|
||||
|
||||
class UDPWiimote
|
||||
{
|
||||
public:
|
||||
UDPWiimote(const char * port);
|
||||
virtual ~UDPWiimote();
|
||||
void getAccel(float &x, float &y, float &z);
|
||||
u32 getButtons();
|
||||
void getNunchuck(float &x, float &y, u8 &mask);
|
||||
void getIR(float &x, float &y);
|
||||
int getErrNo() {return err;};
|
||||
private:
|
||||
int pharsePacket(u8 * data, size_t size);
|
||||
void mainThread();
|
||||
struct _d; //using pimpl because Winsock2.h doesen't have include guards -_-
|
||||
_d *d;
|
||||
double x,y,z;
|
||||
double nunX,nunY;
|
||||
double pointerX,pointerY;
|
||||
u8 nunMask;
|
||||
u32 mask;
|
||||
int err;
|
||||
static int noinst;
|
||||
friend void _UDPWiiThread(void* arg);
|
||||
void broadcastPresence();
|
||||
u8 time;
|
||||
};
|
||||
#endif
|
||||
@@ -1,398 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "LogManager.h"
|
||||
#include "StringUtil.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#define EXCLUDEMAIN_H // Avoid certain declarations in main.h
|
||||
#include "EmuDefinitions.h" // Local
|
||||
#include "wiimote_hid.h"
|
||||
#include "main.h"
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
#include "ConfigPadDlg.h"
|
||||
#include "ConfigBasicDlg.h"
|
||||
|
||||
WiimotePadConfigDialog *m_PadConfigFrame = NULL;
|
||||
WiimoteBasicConfigDialog *m_BasicConfigFrame = NULL;
|
||||
#endif
|
||||
#include "Config.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
#include "EmuMain.h"
|
||||
#if HAVE_WIIUSE
|
||||
#include "wiimote_real.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
Display* WMdisplay = NULL;
|
||||
#endif
|
||||
SWiimoteInitialize g_WiimoteInitialize;
|
||||
PLUGIN_GLOBALS* globals = NULL;
|
||||
|
||||
// General
|
||||
bool g_EmulatorRunning = false;
|
||||
u32 g_ISOId = 0;
|
||||
bool g_SearchDeviceDone = false;
|
||||
bool g_RealWiiMotePresent = false;
|
||||
|
||||
// Debugging
|
||||
bool g_DebugAccelerometer = false;
|
||||
bool g_DebugData = false;
|
||||
bool g_DebugComm = false;
|
||||
bool g_DebugSoundData = false;
|
||||
bool g_DebugCustom = false;
|
||||
|
||||
// Update speed
|
||||
int g_UpdateCounter = 0;
|
||||
double g_UpdateTime = 0;
|
||||
int g_UpdateRate = 0;
|
||||
int g_UpdateWriteScreen = 0;
|
||||
std::vector<int> g_UpdateTimeList (5, 0);
|
||||
|
||||
// Movement recording
|
||||
std::vector<SRecordingAll> VRecording(RECORDING_ROWS);
|
||||
|
||||
PLUGIN_EMUSTATE g_EmulatorState = PLUGIN_EMUSTATE_STOP;
|
||||
|
||||
// Standard crap to make wxWidgets happy
|
||||
#ifdef _WIN32
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
class wxDLLApp : public wxApp
|
||||
{
|
||||
bool OnInit()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
|
||||
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
||||
#endif
|
||||
|
||||
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
|
||||
DWORD dwReason, // reason called
|
||||
LPVOID lpvReserved) // reserved
|
||||
{
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxSetInstance((HINSTANCE)hinstDLL);
|
||||
wxInitialize();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxUninitialize();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
g_hInstance = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Exports
|
||||
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
|
||||
{
|
||||
_PluginInfo->Version = 0x0100;
|
||||
_PluginInfo->Type = PLUGIN_TYPE_WIIMOTE;
|
||||
#ifdef DEBUGFAST
|
||||
sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin (DebugFast)");
|
||||
#else
|
||||
#ifndef _DEBUG
|
||||
sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin");
|
||||
#else
|
||||
sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin (Debug)");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
|
||||
{
|
||||
globals = _pPluginGlobals;
|
||||
LogManager::SetInstance((LogManager *)globals->logManager);
|
||||
}
|
||||
|
||||
void *DllDebugger(void *_hParent, bool Show)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DllConfig(void *_hParent)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (WiiMoteReal::g_AutoPairUpInvisibleWindow == NULL)
|
||||
{
|
||||
WiiMoteReal::g_AutoPairUpInvisibleWindow = new Common::Thread(WiiMoteReal::RunInvisibleMessageWindow_ThreadFunc, NULL);
|
||||
WiiMoteReal::g_AutoPairUpMonitoring = new Common::Thread(WiiMoteReal::PairUp_ThreadFunc, NULL);
|
||||
}
|
||||
#endif
|
||||
if (!g_SearchDeviceDone)
|
||||
{
|
||||
// Load settings
|
||||
g_Config.Load();
|
||||
// We do a pad search before creating the dialog
|
||||
WiiMoteEmu::Search_Devices(WiiMoteEmu::joyinfo, WiiMoteEmu::NumPads, WiiMoteEmu::NumGoodPads);
|
||||
g_SearchDeviceDone = true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
m_BasicConfigFrame = new WiimoteBasicConfigDialog((wxWindow *)_hParent);
|
||||
m_BasicConfigFrame->ShowModal();
|
||||
m_BasicConfigFrame->Destroy();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Start emulation
|
||||
void Initialize(void *init)
|
||||
{
|
||||
g_EmulatorRunning = true;
|
||||
g_WiimoteInitialize = *(SWiimoteInitialize *)init;
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
// Load the ISO Id
|
||||
g_ISOId = g_WiimoteInitialize.ISOId;
|
||||
// Load the settings
|
||||
g_Config.Load();
|
||||
#endif
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
WMdisplay = XOpenDisplay(NULL);
|
||||
#endif
|
||||
|
||||
g_ISOId = g_WiimoteInitialize.ISOId;
|
||||
DEBUG_LOG(WIIMOTE, "ISOId: %08x %s", g_WiimoteInitialize.ISOId, Hex2Ascii(g_WiimoteInitialize.ISOId).c_str());
|
||||
|
||||
// Load IR settings, as this is a per-game setting and the user might have loaded a different game
|
||||
g_Config.LoadIR();
|
||||
|
||||
// Run this first so that WiiMoteReal::Initialize() overwrites g_Eeprom
|
||||
WiiMoteEmu::Initialize();
|
||||
|
||||
/* We will run WiiMoteReal::Initialize() even if we are not using a real
|
||||
wiimote, to check if there is a real wiimote connected. We will initiate
|
||||
wiiuse.dll, but we will return before creating a new thread for it if we
|
||||
find no real Wiimotes. Then g_RealWiiMotePresent will also be
|
||||
false. This function call will be done instantly whether there is a real
|
||||
Wiimote connected or not. It takes no time for Wiiuse to check for
|
||||
connected Wiimotes. */
|
||||
#if HAVE_WIIUSE
|
||||
|
||||
WiiMoteReal::Initialize();
|
||||
WiiMoteReal::Allocate();
|
||||
#ifdef _WIN32
|
||||
if (WiiMoteReal::g_AutoPairUpInvisibleWindow == NULL)
|
||||
{
|
||||
WiiMoteReal::g_AutoPairUpInvisibleWindow = new Common::Thread(WiiMoteReal::RunInvisibleMessageWindow_ThreadFunc, NULL);
|
||||
WiiMoteReal::g_AutoPairUpMonitoring = new Common::Thread(WiiMoteReal::PairUp_ThreadFunc, NULL);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// If a game is not running this is called by the Configuration window when it's closed
|
||||
void Shutdown(void)
|
||||
{
|
||||
// Not running
|
||||
g_EmulatorRunning = false;
|
||||
|
||||
// Reset the game ID in all cases
|
||||
g_ISOId = 0;
|
||||
|
||||
#if HAVE_WIIUSE
|
||||
WiiMoteReal::Shutdown();
|
||||
#endif
|
||||
WiiMoteEmu::Shutdown();
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
if (WMdisplay)
|
||||
XCloseDisplay(WMdisplay);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void DoState(unsigned char **ptr, int mode)
|
||||
{
|
||||
PointerWrap p(ptr, mode);
|
||||
|
||||
// TODO: Shorten the list
|
||||
|
||||
//p.Do(g_EmulatorRunning);
|
||||
//p.Do(g_ISOId);
|
||||
//p.Do(g_RealWiiMotePresent);
|
||||
//p.Do(g_RealWiiMoteInitialized);
|
||||
//p.Do(g_EmulatedWiiMoteInitialized);
|
||||
//p.Do(g_UpdateCounter);
|
||||
//p.Do(g_UpdateTime);
|
||||
//p.Do(g_UpdateRate);
|
||||
//p.Do(g_UpdateWriteScreen);
|
||||
//p.Do(g_UpdateTimeList);
|
||||
|
||||
#if HAVE_WIIUSE
|
||||
WiiMoteReal::DoState(p);
|
||||
#endif
|
||||
WiiMoteEmu::DoState(p);
|
||||
|
||||
return;
|
||||
}
|
||||
void EmuStateChange(PLUGIN_EMUSTATE newState)
|
||||
{
|
||||
g_EmulatorState = newState;
|
||||
}
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
// Hack to use wx key events
|
||||
volatile bool wxkeystate[WXK_SPECIAL20];
|
||||
#endif
|
||||
|
||||
// Set buttons status from keyboard input. Currently this is done from
|
||||
// wxWidgets in the main application.
|
||||
// --------------
|
||||
void Wiimote_Input(u16 _Key, u8 _UpDown)
|
||||
{
|
||||
#if defined(__APPLE__) && defined(USE_WX) && USE_WX
|
||||
if (_Key < WXK_SPECIAL20)
|
||||
{
|
||||
wxkeystate[_Key] = _UpDown;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This function produce Wiimote Input (reports from the Wiimote) in response
|
||||
to Output from the Wii. It's called from WII_IPC_HLE_WiiMote.cpp.
|
||||
|
||||
Switch between real and emulated wiimote: We send all this Input to WiiMoteEmu::InterruptChannel()
|
||||
so that it knows the channel ID and the data reporting mode at all times.
|
||||
*/
|
||||
void Wiimote_InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
// Decide where to send the message
|
||||
if (WiiMoteEmu::WiiMapping[_number].Source <= 1)
|
||||
WiiMoteEmu::InterruptChannel(_number, _channelID, _pData, _Size);
|
||||
#if HAVE_WIIUSE
|
||||
else if (g_RealWiiMotePresent)
|
||||
WiiMoteReal::InterruptChannel(_number, _channelID, _pData, _Size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Function: Used for the initial Bluetooth HID handshake.
|
||||
void Wiimote_ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
// Debugging
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
DEBUG_LOG(WIIMOTE, "Wiimote_ControlChannel");
|
||||
DEBUG_LOG(WIIMOTE, " Channel ID: %04x", _channelID);
|
||||
std::string Temp = ArrayToString((const u8*)_pData, _Size);
|
||||
DEBUG_LOG(WIIMOTE, " Data: %s", Temp.c_str());
|
||||
#endif
|
||||
|
||||
// Check for custom communication
|
||||
if(_channelID == 99 && *(const u8*)_pData == WIIMOTE_DISCONNECT)
|
||||
{
|
||||
WiiMoteEmu::g_ReportingAuto[_number] = false;
|
||||
WARN_LOG(WIIMOTE, "Wiimote: #%i Disconnected", _number);
|
||||
#ifdef _WIN32
|
||||
PostMessage((HWND)g_WiimoteInitialize.hWnd, WM_USER, WIIMOTE_DISCONNECT, _number);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (WiiMoteEmu::WiiMapping[_number].Source <= 1)
|
||||
WiiMoteEmu::ControlChannel(_number, _channelID, _pData, _Size);
|
||||
#if HAVE_WIIUSE
|
||||
else if (g_RealWiiMotePresent)
|
||||
WiiMoteReal::ControlChannel(_number, _channelID, _pData, _Size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// This sends a Data Report from the Wiimote. See SystemTimers.cpp for the documentation of this update.
|
||||
void Wiimote_Update(int _number)
|
||||
{
|
||||
// This functions will send:
|
||||
// Emulated Wiimote: Only data reports 0x30-0x37
|
||||
// Real Wiimote: Both data reports 0x30-0x37 and all other read reports
|
||||
if (WiiMoteEmu::WiiMapping[_number].Source <= 1)
|
||||
WiiMoteEmu::Update(_number);
|
||||
#if HAVE_WIIUSE
|
||||
else if (g_RealWiiMotePresent)
|
||||
WiiMoteReal::Update(_number);
|
||||
#endif
|
||||
|
||||
/*
|
||||
// Debugging
|
||||
#ifdef _WIN32
|
||||
if( GetAsyncKeyState(VK_HOME) && g_DebugComm ) g_DebugComm = false; // Page Down
|
||||
else if (GetAsyncKeyState(VK_HOME) && !g_DebugComm ) g_DebugComm = true;
|
||||
|
||||
if( GetAsyncKeyState(VK_PRIOR) && g_DebugData ) g_DebugData = false; // Page Up
|
||||
else if (GetAsyncKeyState(VK_PRIOR) && !g_DebugData ) g_DebugData = true;
|
||||
|
||||
if( GetAsyncKeyState(VK_NEXT) && g_DebugAccelerometer ) g_DebugAccelerometer = false; // Home
|
||||
else if (GetAsyncKeyState(VK_NEXT) && !g_DebugAccelerometer ) g_DebugAccelerometer = true;
|
||||
|
||||
if( GetAsyncKeyState(VK_END) && g_DebugCustom ) { g_DebugCustom = false; DEBUG_LOG(WIIMOTE, "Custom Debug: Off");} // End
|
||||
else if (GetAsyncKeyState(VK_END) && !g_DebugCustom ) {g_DebugCustom = true; DEBUG_LOG(WIIMOTE, "Custom Debug: Off");}
|
||||
#endif
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
unsigned int Wiimote_GetAttachedControllers()
|
||||
{
|
||||
unsigned int attached = 0;
|
||||
for (unsigned int i=0; i<4; ++i)
|
||||
if (WiiMoteEmu::WiiMapping[i].Source)
|
||||
attached |= (1 << i);
|
||||
return attached;
|
||||
}
|
||||
|
||||
|
||||
// Unpair Wiimotes, TODO: Add linux/osx un-pair function
|
||||
unsigned int Wiimote_UnPairWiimotes()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (g_Config.bUnpairRealWiimote)
|
||||
return WiiMoteReal::WiimotePairUp(true);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Supporting functions
|
||||
|
||||
// Check if the render window is in focus
|
||||
|
||||
bool IsFocus()
|
||||
{
|
||||
return g_WiimoteInitialize.pRendererHasFocus();
|
||||
}
|
||||
|
||||
/* Returns a timestamp with three decimals for precise time comparisons. The return format is
|
||||
of the form seconds.milleseconds for example 1234.123. The leding seconds have no particular meaning
|
||||
but are just there to enable use to tell if we have entered a new second or now. */
|
||||
// -----------------
|
||||
@@ -1,89 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "CommonTypes.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/XKBlib.h>
|
||||
extern Display* WMdisplay;
|
||||
#endif
|
||||
|
||||
bool IsFocus();
|
||||
|
||||
// Movement recording
|
||||
#define RECORDING_ROWS 15
|
||||
#define WM_RECORDING_WIIMOTE 0
|
||||
#define WM_RECORDING_NUNCHUCK 1
|
||||
#define WM_RECORDING_IR 2
|
||||
struct SRecording
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
double Time;
|
||||
u8 IR[12];
|
||||
};
|
||||
struct SRecordingAll
|
||||
{
|
||||
std::vector<SRecording> Recording;
|
||||
int HotKeySwitch, HotKeyWiimote, HotKeyNunchuck, HotKeyIR;
|
||||
int PlaybackSpeed;
|
||||
int IRBytes;
|
||||
};
|
||||
|
||||
#ifndef EXCLUDEMAIN_H
|
||||
// General
|
||||
extern bool g_EmulatorRunning;
|
||||
extern u32 g_ISOId;
|
||||
extern bool g_SearchDeviceDone;
|
||||
extern bool g_RealWiiMotePresent;
|
||||
#ifdef _WIN32
|
||||
extern HINSTANCE g_hInstance;
|
||||
#endif
|
||||
|
||||
// Debugging
|
||||
extern bool g_DebugAccelerometer;
|
||||
extern bool g_DebugData;
|
||||
extern bool g_DebugComm;
|
||||
extern bool g_DebugSoundData;
|
||||
extern bool g_DebugCustom;
|
||||
|
||||
// Update speed
|
||||
extern int g_UpdateCounter;
|
||||
extern double g_UpdateTime;
|
||||
extern int g_UpdateWriteScreen;
|
||||
extern int g_UpdateRate;
|
||||
extern std::vector<int> g_UpdateTimeList;
|
||||
|
||||
// Movement recording
|
||||
extern std::vector<SRecordingAll> VRecording;
|
||||
|
||||
extern PLUGIN_EMUSTATE g_EmulatorState;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // MAIN_H
|
||||
@@ -1,409 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef WIIMOTE_HID_H
|
||||
#define WIIMOTE_HID_H
|
||||
|
||||
#include "CommonTypes.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4200)
|
||||
#endif
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#define MAX_WIIMOTES 4
|
||||
|
||||
// Source: HID_010_SPC_PFL/1.0 (official HID specification)
|
||||
|
||||
struct hid_packet {
|
||||
u8 param : 4;
|
||||
u8 type : 4;
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
#define HID_TYPE_HANDSHAKE 0
|
||||
#define HID_TYPE_SET_REPORT 5
|
||||
#define HID_TYPE_DATA 0xA
|
||||
|
||||
#define HID_HANDSHAKE_SUCCESS 0
|
||||
|
||||
#define HID_PARAM_INPUT 1
|
||||
#define HID_PARAM_OUTPUT 2
|
||||
|
||||
//source: http://wiibrew.org/wiki/Wiimote
|
||||
|
||||
struct wm_core {
|
||||
u8 left : 1;
|
||||
u8 right : 1;
|
||||
u8 down : 1;
|
||||
u8 up : 1;
|
||||
u8 plus : 1;
|
||||
u8 : 3;
|
||||
u8 two : 1;
|
||||
u8 one : 1;
|
||||
u8 b : 1;
|
||||
u8 a : 1;
|
||||
u8 minus : 1;
|
||||
u8 : 2;
|
||||
u8 home : 1;
|
||||
};
|
||||
|
||||
struct wm_accel {
|
||||
u8 x, y, z;
|
||||
};
|
||||
|
||||
struct mp_gyro {
|
||||
u16 x:14, y:14, z:14;
|
||||
};
|
||||
// Four bytes for two objects. Filled with 0xFF if empty
|
||||
struct wm_ir_basic
|
||||
{
|
||||
u8 x1;
|
||||
u8 y1;
|
||||
u8 x2Hi : 2;
|
||||
u8 y2Hi : 2;
|
||||
u8 x1Hi : 2;
|
||||
u8 y1Hi : 2;
|
||||
u8 x2;
|
||||
u8 y2;
|
||||
};
|
||||
|
||||
// Three bytes for one object
|
||||
struct wm_ir_extended
|
||||
{
|
||||
u8 x;
|
||||
u8 y;
|
||||
u8 size : 4;
|
||||
u8 xHi : 2;
|
||||
u8 yHi : 2;
|
||||
};
|
||||
|
||||
struct wm_extension
|
||||
{
|
||||
u8 jx; // joystick x, y
|
||||
u8 jy;
|
||||
u8 ax; // accelerometer
|
||||
u8 ay;
|
||||
u8 az;
|
||||
u8 bt; // buttons
|
||||
};
|
||||
|
||||
struct wm_cc_4
|
||||
{
|
||||
u8 padding : 1;
|
||||
u8 bRT : 1;
|
||||
u8 bP : 1;
|
||||
u8 bH : 1;
|
||||
u8 bM : 1;
|
||||
u8 bLT : 1;
|
||||
u8 bdD : 1;
|
||||
u8 bdR : 1;
|
||||
};
|
||||
|
||||
struct wm_cc_5
|
||||
{
|
||||
u8 bdU : 1;
|
||||
u8 bdL : 1;
|
||||
u8 bZR : 1;
|
||||
u8 bX : 1;
|
||||
u8 bA : 1;
|
||||
u8 bY : 1;
|
||||
u8 bB : 1;
|
||||
u8 bZL : 1;
|
||||
};
|
||||
|
||||
struct wm_classic_extension
|
||||
{
|
||||
u8 Lx : 6; // byte 0
|
||||
u8 Rx3 : 2;
|
||||
u8 Ly : 6; // byte 1
|
||||
u8 Rx2 : 2;
|
||||
u8 Ry : 5; // byte 2
|
||||
u8 lT2 : 2;
|
||||
u8 Rx : 1;
|
||||
u8 rT : 5; // byte 3
|
||||
u8 lT : 3;
|
||||
wm_cc_4 b1; // byte 4
|
||||
wm_cc_5 b2; // byte 5
|
||||
};
|
||||
|
||||
struct wm_mp_nc_0 //motionplus data
|
||||
{
|
||||
u8 YawLeftLS; //7e
|
||||
u8 RollLeftLS; //82
|
||||
u8 PitchDownLS; //83
|
||||
u8 pitchslow : 1; //1
|
||||
u8 yawslow : 1; //0
|
||||
u8 YawLeftHI : 6; //01 1010 /1a
|
||||
u8 ExtCon : 1; // 1 usually
|
||||
u8 rollslow : 1; //0
|
||||
u8 RollLeftHI : 6; //00 1010
|
||||
u8 dummy : 1; // 0 usually. 1 in dem fall mhh
|
||||
u8 mpdata : 1; //1 in this case, interleaved motion+ data
|
||||
u8 PitchDownHI : 6;//01 1100
|
||||
}; // default for yaw/roll/pitch around 0x1F7F
|
||||
|
||||
struct wm_mp_nc_1 //nunchuk data on motion-plus pass-through
|
||||
{
|
||||
u8 jx;
|
||||
u8 jy;
|
||||
u8 ax;
|
||||
u8 ay;
|
||||
u8 ExtCon : 1; // 1 usually
|
||||
u8 az : 7;
|
||||
u8 dummy : 1; //0 always
|
||||
u8 mpdata : 1; //0 when nunchuk interleaved data
|
||||
u8 bz : 1;
|
||||
u8 bc : 1;
|
||||
u8 axLS : 1; // ls 1, ls0 = 0 by default,
|
||||
u8 ayLS : 1;
|
||||
u8 azLS : 2;
|
||||
};
|
||||
|
||||
struct wm_GH3_extension
|
||||
{
|
||||
u8 SX : 6;
|
||||
u8 pad1 : 2; // 1 on GH3, 0 on GHWT
|
||||
|
||||
u8 SY : 6;
|
||||
u8 pad2 : 2; // 1 on GH3, 0 on GHWT
|
||||
|
||||
u8 TB : 5; // not used in GH3
|
||||
u8 pad3 : 3; // Always 0
|
||||
|
||||
u8 Whammy : 5;
|
||||
u8 pad4 : 3; // Always 0
|
||||
|
||||
u8 pad5 : 2; // Always 1
|
||||
u8 Plus : 1;
|
||||
u8 pad6 : 1; // Always 1
|
||||
u8 Minus : 1;
|
||||
u8 pad7 : 1; // Always 1
|
||||
u8 StrumDown : 1;
|
||||
u8 pad8 : 1; // Always 1
|
||||
|
||||
u8 StrumUp : 1;
|
||||
u8 pad9 : 2; // Always 1
|
||||
u8 Yellow : 1;
|
||||
u8 Green : 1;
|
||||
u8 Blue : 1;
|
||||
u8 Red : 1;
|
||||
u8 Orange : 1;
|
||||
};
|
||||
|
||||
|
||||
struct wm_report {
|
||||
u8 wm;
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
#define WM_RUMBLE 0x10
|
||||
|
||||
#define WM_LEDS 0x11
|
||||
struct wm_leds {
|
||||
u8 rumble : 1;
|
||||
u8 : 3;
|
||||
u8 leds : 4;
|
||||
};
|
||||
|
||||
#define WM_REPORT_MODE 0x12
|
||||
struct wm_report_mode {
|
||||
u8 rumble : 1;
|
||||
u8 continuous : 1;
|
||||
u8 all_the_time : 1;
|
||||
u8 : 5;
|
||||
u8 mode;
|
||||
};
|
||||
|
||||
#define WM_IR_PIXEL_CLOCK 0x13
|
||||
#define WM_IR_LOGIC 0x1A
|
||||
|
||||
#define WM_REQUEST_STATUS 0x15
|
||||
struct wm_request_status {
|
||||
u8 rumble : 1;
|
||||
u8 : 7;
|
||||
};
|
||||
|
||||
#define WM_STATUS_REPORT 0x20
|
||||
struct wm_status_report {
|
||||
wm_core buttons;
|
||||
u8 battery_low : 1;
|
||||
u8 extension : 1;
|
||||
u8 speaker : 1;
|
||||
u8 ir : 1;
|
||||
u8 leds : 4;
|
||||
u8 padding2[2]; // two 00, TODO: this needs more investigation
|
||||
u8 battery;
|
||||
};
|
||||
|
||||
#define WM_WRITE_DATA 0x16
|
||||
struct wm_write_data
|
||||
{
|
||||
u8 rumble : 1;
|
||||
u8 space : 2; //see WM_SPACE_*
|
||||
u8 : 5;
|
||||
u8 address[3];
|
||||
u8 size;
|
||||
u8 data[16];
|
||||
};
|
||||
|
||||
#define WM_ACK_DATA 0x22
|
||||
struct wm_acknowledge
|
||||
{
|
||||
wm_core buttons;
|
||||
u8 reportID;
|
||||
u8 errorID;
|
||||
};
|
||||
|
||||
#define WM_READ_DATA 0x17
|
||||
struct wm_read_data {
|
||||
u8 rumble : 1;
|
||||
u8 space : 2; //see WM_SPACE_*
|
||||
u8 : 5;
|
||||
u8 address[3];
|
||||
u8 size[2];
|
||||
};
|
||||
|
||||
#define WM_SPACE_EEPROM 0
|
||||
#define WM_SPACE_REGS1 1
|
||||
#define WM_SPACE_REGS2 2
|
||||
#define WM_SPACE_INVALID 3
|
||||
|
||||
#define WM_READ_DATA_REPLY 0x21
|
||||
struct wm_read_data_reply {
|
||||
wm_core buttons;
|
||||
u8 error : 4; //see WM_RDERR_*
|
||||
u8 size : 4;
|
||||
u16 address;
|
||||
u8 data[16];
|
||||
};
|
||||
|
||||
#define WM_RDERR_WOREG 7
|
||||
#define WM_RDERR_NOMEM 8
|
||||
|
||||
|
||||
// Data reports
|
||||
|
||||
#define WM_REPORT_CORE 0x30
|
||||
struct wm_report_core {
|
||||
wm_core c;
|
||||
};
|
||||
|
||||
#define WM_REPORT_CORE_ACCEL 0x31
|
||||
struct wm_report_core_accel {
|
||||
wm_core c;
|
||||
wm_accel a;
|
||||
};
|
||||
|
||||
#define WM_REPORT_CORE_EXT8 0x32
|
||||
|
||||
#define WM_REPORT_CORE_ACCEL_IR12 0x33
|
||||
struct wm_report_core_accel_ir12 {
|
||||
wm_core c;
|
||||
wm_accel a;
|
||||
wm_ir_extended ir[4];
|
||||
};
|
||||
|
||||
#define WM_REPORT_CORE_EXT19 0x34
|
||||
#define WM_REPORT_CORE_ACCEL_EXT16 0x35
|
||||
struct wm_report_core_accel_ext16
|
||||
{
|
||||
wm_core c;
|
||||
wm_accel a;
|
||||
wm_extension ext;
|
||||
//wm_ir_basic ir[2];
|
||||
u8 pad[10];
|
||||
|
||||
};
|
||||
|
||||
#define WM_REPORT_CORE_IR10_EXT9 0x36
|
||||
|
||||
#define WM_REPORT_CORE_ACCEL_IR10_EXT6 0x37
|
||||
struct wm_report_core_accel_ir10_ext6
|
||||
{
|
||||
wm_core c;
|
||||
wm_accel a;
|
||||
wm_ir_basic ir[2];
|
||||
//u8 ext[6];
|
||||
wm_extension ext;
|
||||
};
|
||||
|
||||
#define WM_REPORT_EXT21 0x3d // never used?
|
||||
struct wm_report_ext21
|
||||
{
|
||||
u8 ext[21];
|
||||
};
|
||||
|
||||
#define WM_REPORT_INTERLEAVE1 0x3e
|
||||
#define WM_REPORT_INTERLEAVE2 0x3f
|
||||
|
||||
#define WM_SPEAKER_ENABLE 0x14
|
||||
#define WM_SPEAKER_MUTE 0x19
|
||||
#define WM_WRITE_SPEAKER_DATA 0x18
|
||||
|
||||
|
||||
// Custom structs
|
||||
|
||||
/**
|
||||
* @struct accel_t
|
||||
* @brief Accelerometer struct. For any device with an accelerometer.
|
||||
*/
|
||||
struct accel_cal
|
||||
{
|
||||
wm_accel cal_zero; /**< zero calibration */
|
||||
wm_accel cal_g; /**< 1g difference around 0cal */
|
||||
};
|
||||
|
||||
struct nu_js {
|
||||
u8 max, min, center;
|
||||
};
|
||||
struct cc_trigger {
|
||||
u8 neutral;
|
||||
};
|
||||
struct nu_cal
|
||||
{
|
||||
wm_accel cal_zero; // zero calibratio
|
||||
wm_accel cal_g; // g size
|
||||
nu_js jx; //
|
||||
nu_js jy; //
|
||||
};
|
||||
|
||||
struct mp_cal
|
||||
{
|
||||
mp_gyro cal_zero;
|
||||
mp_gyro cal_min;
|
||||
mp_gyro cal_max;
|
||||
};
|
||||
|
||||
struct cc_cal
|
||||
{
|
||||
nu_js Lx; //
|
||||
nu_js Ly; //
|
||||
nu_js Rx; //
|
||||
nu_js Ry; //
|
||||
cc_trigger Tl; //
|
||||
cc_trigger Tr; //
|
||||
};
|
||||
struct gh3_cal
|
||||
{
|
||||
nu_js Lx;
|
||||
nu_js Ly;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif //WIIMOTE_HID_H
|
||||
@@ -1,896 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include <iostream> // System
|
||||
#include <queue>
|
||||
|
||||
#include "wiiuse.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Thread.h"
|
||||
#include "StringUtil.h"
|
||||
#include "Timer.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include "wiimote_hid.h"
|
||||
#include "main.h"
|
||||
#include "Config.h"
|
||||
#include "EmuMain.h"
|
||||
#include "EmuDefinitions.h"
|
||||
#define EXCLUDE_H // Avoid certain declarations in wiimote_real.h
|
||||
#include "wiimote_real.h"
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
#include "ConfigBasicDlg.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <bthdef.h>
|
||||
#include <BluetoothAPIs.h>
|
||||
|
||||
#pragma comment(lib, "Bthprops.lib")
|
||||
#endif
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
namespace WiiMoteReal
|
||||
{
|
||||
|
||||
bool g_RealWiiMoteInitialized = false;
|
||||
bool g_RealWiiMoteAllocated = false;
|
||||
|
||||
// Forwarding
|
||||
|
||||
class CWiiMote;
|
||||
|
||||
// Variable declarations
|
||||
|
||||
wiimote_t** g_WiiMotesFromWiiUse = NULL;
|
||||
Common::Thread* g_pReadThread = NULL;
|
||||
int g_NumberOfWiiMotes;
|
||||
volatile int LastNumberOfWiimotes = 0;
|
||||
CWiiMote* g_WiiMotes[MAX_WIIMOTES];
|
||||
volatile bool g_Shutdown = false;
|
||||
bool g_WiimoteInUse[MAX_WIIMOTES];
|
||||
Common::Event NeedsConnect;
|
||||
Common::Event Connected;
|
||||
|
||||
#if defined(_WIN32) && defined(HAVE_WIIUSE)
|
||||
//Autopairup
|
||||
Common::Thread* g_AutoPairUpInvisibleWindow = NULL;
|
||||
Common::Thread* g_AutoPairUpMonitoring = NULL;
|
||||
Common::Event g_StartAutopairThread;
|
||||
|
||||
int stoprefresh = 0;
|
||||
unsigned int PairUpTimer = 2000;
|
||||
|
||||
int PairUpRefreshWiimote(bool addwiimote);
|
||||
int PairUpFindNewSlot(void);
|
||||
void ToggleEmulatorState(bool stop);
|
||||
THREAD_RETURN PairUp_ThreadFunc(void* arg);
|
||||
THREAD_RETURN RunInvisibleMessageWindow_ThreadFunc(void* arg);
|
||||
#endif
|
||||
|
||||
THREAD_RETURN ReadWiimote_ThreadFunc(void* arg);
|
||||
|
||||
// Probably this class should be in its own file
|
||||
|
||||
class CWiiMote
|
||||
{
|
||||
public:
|
||||
|
||||
CWiiMote(u8 _WiimoteNumber, wiimote_t* _pWiimote)
|
||||
: m_WiimoteNumber(_WiimoteNumber)
|
||||
, m_channelID(0)
|
||||
, m_pWiiMote(_pWiimote)
|
||||
, m_pCriticalSection(NULL)
|
||||
, m_LastReportValid(false)
|
||||
{
|
||||
m_pCriticalSection = new Common::CriticalSection();
|
||||
|
||||
//wiiuse_set_leds(m_pWiiMote, WIIMOTE_LED_4);
|
||||
|
||||
#ifdef _WIN32
|
||||
// F|RES: i dunno if we really need this
|
||||
CancelIo(m_pWiiMote->dev_handle);
|
||||
//CancelIoEx(m_pWiiMote->dev_handle,NULL); //causing problems under older win systems
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual ~CWiiMote()
|
||||
{
|
||||
delete m_pCriticalSection;
|
||||
};
|
||||
|
||||
|
||||
// Queue raw HID data from the core to the wiimote
|
||||
void SendData(u16 _channelID, const u8* _pData, u32 _Size)
|
||||
{
|
||||
m_channelID = _channelID;
|
||||
|
||||
m_pCriticalSection->Enter();
|
||||
{
|
||||
SEvent WriteEvent;
|
||||
memcpy(WriteEvent.m_PayLoad, _pData, _Size);
|
||||
WriteEvent._Size = _Size;
|
||||
m_EventWriteQueue.push(WriteEvent);
|
||||
}
|
||||
m_pCriticalSection->Leave();
|
||||
}
|
||||
|
||||
|
||||
/* Read and write data to the Wiimote */
|
||||
void ReadData()
|
||||
{
|
||||
if (!m_channelID)
|
||||
return;
|
||||
|
||||
m_pCriticalSection->Enter();
|
||||
|
||||
// Send data to the Wiimote
|
||||
if (!m_EventWriteQueue.empty())
|
||||
{
|
||||
const SEvent& rEvent = m_EventWriteQueue.front();
|
||||
wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, rEvent._Size);
|
||||
//std::string Temp = ArrayToString(rEvent.m_PayLoad, rEvent._Size);
|
||||
//DEBUG_LOG(WIIMOTE, "Wiimote Write:\n%s:%d", Temp.c_str(), ret);
|
||||
#ifdef _WIN32
|
||||
if (m_pWiiMote->event == WIIUSE_UNEXPECTED_DISCONNECT)
|
||||
{
|
||||
NOTICE_LOG(WIIMOTE, "wiiuse_io_write: unexpected disconnect. handle: %08x", m_pWiiMote->dev_handle);
|
||||
}
|
||||
#endif
|
||||
m_EventWriteQueue.pop();
|
||||
}
|
||||
|
||||
m_pCriticalSection->Leave();
|
||||
|
||||
|
||||
// Read data from wiimote (but don't send it to the core, just filter and queue)
|
||||
if (wiiuse_io_read(m_pWiiMote))
|
||||
{
|
||||
const byte* pBuffer = m_pWiiMote->event_buf;
|
||||
//std::string Temp = ArrayToString(pBuffer, 20);
|
||||
//DEBUG_LOG(WIIMOTE, "Wiimote Read:\n%s", Temp.c_str());
|
||||
// Check if we have a channel (connection) if so save the data...
|
||||
if (m_channelID > 0)
|
||||
{
|
||||
m_pCriticalSection->Enter();
|
||||
|
||||
// Filter out data reports
|
||||
if (pBuffer[1] >= 0x30)
|
||||
{
|
||||
// Copy Buffer to LastReport
|
||||
memcpy(m_LastReport.m_PayLoad, pBuffer + 1, MAX_PAYLOAD - 1);
|
||||
m_LastReportValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy Buffer to ImportantEvent
|
||||
SEvent ImportantEvent;
|
||||
memcpy(ImportantEvent.m_PayLoad, pBuffer + 1, MAX_PAYLOAD - 1);
|
||||
|
||||
// Put it in the read queue right away
|
||||
m_EventReadQueue.push(ImportantEvent);
|
||||
}
|
||||
m_pCriticalSection->Leave();
|
||||
}
|
||||
|
||||
memset((void*)&m_pWiiMote->event_buf,0,sizeof(m_pWiiMote->event_buf));
|
||||
}
|
||||
#ifdef _WIN32
|
||||
else if (m_pWiiMote->event == WIIUSE_UNEXPECTED_DISCONNECT)
|
||||
{
|
||||
NOTICE_LOG(WIIMOTE, "wiiuse_io_read: unexpected disconnect. handle: %08x", m_pWiiMote->dev_handle);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
// Send queued data to the core
|
||||
void Update()
|
||||
{
|
||||
// Thread function
|
||||
m_pCriticalSection->Enter();
|
||||
|
||||
if (m_EventReadQueue.empty())
|
||||
{
|
||||
// Send the data report
|
||||
if (m_LastReportValid)
|
||||
SendEvent(m_LastReport);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send a 0x20, 0x21 or 0x22 report
|
||||
SendEvent(m_EventReadQueue.front());
|
||||
m_EventReadQueue.pop();
|
||||
}
|
||||
|
||||
m_pCriticalSection->Leave();
|
||||
};
|
||||
|
||||
|
||||
// Clear events
|
||||
void ClearEvents()
|
||||
{
|
||||
while (!m_EventReadQueue.empty())
|
||||
m_EventReadQueue.pop();
|
||||
while (!m_EventWriteQueue.empty())
|
||||
m_EventWriteQueue.pop();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct SEvent
|
||||
{
|
||||
SEvent()
|
||||
{
|
||||
memset(m_PayLoad, 0, MAX_PAYLOAD);
|
||||
}
|
||||
byte m_PayLoad[MAX_PAYLOAD];
|
||||
u32 _Size;
|
||||
};
|
||||
typedef std::queue<SEvent> CEventQueue;
|
||||
|
||||
u8 m_WiimoteNumber; // Just for debugging
|
||||
u16 m_channelID;
|
||||
CEventQueue m_EventReadQueue; // Read from Wiimote
|
||||
CEventQueue m_EventWriteQueue; // Write to Wiimote
|
||||
SEvent m_LastReport;
|
||||
wiimote_t* m_pWiiMote; // This is g_WiiMotesFromWiiUse[]
|
||||
Common::CriticalSection* m_pCriticalSection;
|
||||
bool m_LastReportValid;
|
||||
|
||||
// Send queued data to the core
|
||||
void SendEvent(SEvent& _rEvent)
|
||||
{
|
||||
// We don't have an answer channel
|
||||
if (m_channelID == 0)
|
||||
return;
|
||||
|
||||
// Check event buffer
|
||||
u8 Buffer[1024];
|
||||
u32 Offset = 0;
|
||||
hid_packet* pHidHeader = (hid_packet*)(Buffer + Offset);
|
||||
pHidHeader->type = HID_TYPE_DATA;
|
||||
pHidHeader->param = HID_PARAM_INPUT;
|
||||
|
||||
// Create the buffer
|
||||
memcpy(&Buffer[Offset], pHidHeader, sizeof(hid_packet));
|
||||
Offset += sizeof(hid_packet);
|
||||
memcpy(&Buffer[Offset], _rEvent.m_PayLoad, sizeof(_rEvent.m_PayLoad));
|
||||
Offset += sizeof(_rEvent.m_PayLoad);
|
||||
|
||||
// Send it
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(m_WiimoteNumber, m_channelID, Buffer, Offset);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Function Definitions
|
||||
|
||||
void SendAcc(u8 _ReportID)
|
||||
{
|
||||
byte DataAcc[MAX_PAYLOAD];
|
||||
|
||||
DataAcc[0] = 0x22; // Report 0x12
|
||||
DataAcc[1] = 0x00; // Core buttons
|
||||
DataAcc[2] = 0x00;
|
||||
DataAcc[3] = _ReportID; // Reporting mode
|
||||
|
||||
for (int i = 0; i < g_NumberOfWiiMotes; i++)
|
||||
wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[i], (byte*)DataAcc, MAX_PAYLOAD);
|
||||
|
||||
std::string Temp = ArrayToString(DataAcc, 28, 0, 30);
|
||||
DEBUG_LOG(WIIMOTE, "SendAcc: %s", Temp.c_str());
|
||||
|
||||
//22 00 00 _reportID 00
|
||||
}
|
||||
|
||||
// Clear any potential queued events
|
||||
void ClearEvents()
|
||||
{
|
||||
for (int i = 0; i < g_NumberOfWiiMotes; i++)
|
||||
if (g_WiimoteInUse[i])
|
||||
g_WiiMotes[i]->ClearEvents();
|
||||
}
|
||||
|
||||
// Flash lights, and if connecting, also rumble
|
||||
void FlashLights(bool Connect)
|
||||
{
|
||||
|
||||
for (int i = 0; i < g_NumberOfWiiMotes; i++)
|
||||
{
|
||||
if (Connect)
|
||||
wiiuse_rumble(WiiMoteReal::g_WiiMotesFromWiiUse[i], 1);
|
||||
}
|
||||
SLEEP(200);
|
||||
for (int i = 0; i < g_NumberOfWiiMotes; i++)
|
||||
{
|
||||
if (Connect) {
|
||||
wiiuse_rumble(WiiMoteReal::g_WiiMotesFromWiiUse[i], 0);
|
||||
wiiuse_set_leds(WiiMoteReal::g_WiiMotesFromWiiUse[i], WIIMOTE_LED_1 | WIIMOTE_LED_2 | WIIMOTE_LED_3 | WIIMOTE_LED_4);
|
||||
}
|
||||
else
|
||||
wiiuse_set_leds(WiiMoteReal::g_WiiMotesFromWiiUse[i], WIIMOTE_LED_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
int Initialize()
|
||||
{
|
||||
int i, wiimote_slots = 0;
|
||||
|
||||
// Return if already initialized
|
||||
if (g_RealWiiMoteInitialized)
|
||||
return g_NumberOfWiiMotes;
|
||||
|
||||
|
||||
NeedsConnect.Init();
|
||||
Connected.Init();
|
||||
|
||||
// Clear the wiimote classes
|
||||
memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES);
|
||||
for (i = 0; i < MAX_WIIMOTES; i++)
|
||||
g_WiimoteInUse[i] = false;
|
||||
|
||||
g_RealWiiMotePresent = false;
|
||||
g_RealWiiMoteAllocated = false;
|
||||
|
||||
// Only call wiiuse_find with the number of slots configured for real wiimotes
|
||||
for (i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
// Found a WiiMote (slot) that wants to be real :P
|
||||
if (WiiMoteEmu::WiiMapping[i].Source == 2) {
|
||||
wiimote_slots++;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't bother initializing wiiuse if we don't want any real wiimotes
|
||||
if (wiimote_slots < 1)
|
||||
return 0;
|
||||
|
||||
// Call Wiiuse.dll
|
||||
if(!g_WiiMotesFromWiiUse)
|
||||
g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES);
|
||||
|
||||
#ifdef _WIN32
|
||||
g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, wiimote_slots, LastNumberOfWiimotes);
|
||||
#else
|
||||
g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, wiimote_slots, 5); //move the timeout var into wiimote_t structure to avoid confusion
|
||||
#endif
|
||||
LastNumberOfWiimotes = g_NumberOfWiiMotes;
|
||||
DEBUG_LOG(WIIMOTE, "Found No of Wiimotes: %i", g_NumberOfWiiMotes);
|
||||
if (g_NumberOfWiiMotes > 0)
|
||||
{
|
||||
|
||||
g_RealWiiMotePresent = true;
|
||||
// Create a new thread for listening for Wiimote data
|
||||
// and also connecting in Linux/OSX.
|
||||
// Windows connects to Wiimote in the wiiuse_find function
|
||||
g_pReadThread = new Common::Thread(ReadWiimote_ThreadFunc, NULL);
|
||||
// Don't run the Wiimote thread if no wiimotes were found
|
||||
g_Shutdown = false;
|
||||
|
||||
//Hack for OSX
|
||||
NeedsConnect.Set();
|
||||
Connected.Wait();
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < g_NumberOfWiiMotes; i++)
|
||||
{
|
||||
// Set the ir sensor sensitivity.
|
||||
if (g_Config.iIRLevel) {
|
||||
wiiuse_set_ir_sensitivity(g_WiiMotesFromWiiUse[i], g_Config.iIRLevel);
|
||||
}
|
||||
}
|
||||
if (g_Config.bWiiReadTimeout != 30)
|
||||
wiiuse_set_timeout(g_WiiMotesFromWiiUse, g_NumberOfWiiMotes, g_Config.bWiiReadTimeout);
|
||||
|
||||
// If we are connecting from the config window without a game running we set the LEDs
|
||||
if (g_EmulatorState == PLUGIN_EMUSTATE_STOP && g_RealWiiMotePresent)
|
||||
FlashLights(true);
|
||||
|
||||
// Initialized, even if we didn't find a Wiimote
|
||||
g_RealWiiMoteInitialized = true;
|
||||
|
||||
return g_NumberOfWiiMotes;
|
||||
}
|
||||
|
||||
// Allocate each Real WiiMote found to a WiiMote slot with Source set to "WiiMote Real"
|
||||
void Allocate()
|
||||
{
|
||||
if (g_RealWiiMoteAllocated)// && (g_NumberOfWiiMotes == LastNumberOfWiimotes))
|
||||
return;
|
||||
if (!g_RealWiiMoteInitialized)
|
||||
Initialize();
|
||||
|
||||
// Clear the wiimote classes
|
||||
memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES);
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
g_WiimoteInUse[i] = false;
|
||||
|
||||
g_Config.bNumberEmuWiimotes = g_Config.bNumberRealWiimotes = 0;
|
||||
|
||||
// Create Wiimote classes, one for each Real WiiMote found
|
||||
int current_number = 0;
|
||||
for (int i = 0; i < g_NumberOfWiiMotes; i++)
|
||||
{
|
||||
|
||||
// Let's find out the slot this Real WiiMote will be using... We need this because the user can set any of the 4 WiiMotes as Real, Emulated or Inactive...
|
||||
for (; current_number < MAX_WIIMOTES; current_number++)
|
||||
{
|
||||
// Just to be sure we won't be overlapping any WiiMote...
|
||||
if (g_WiimoteInUse[current_number] == true)
|
||||
continue;
|
||||
if (WiiMoteEmu::WiiMapping[current_number].Source == 1)
|
||||
g_Config.bNumberEmuWiimotes++;
|
||||
// Found a WiiMote (slot) that wants to be real :P
|
||||
else if (WiiMoteEmu::WiiMapping[current_number].Source == 2) {
|
||||
g_Config.bNumberRealWiimotes++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we found a valid slot for this WiiMote...
|
||||
if (current_number < MAX_WIIMOTES)
|
||||
{
|
||||
g_WiiMotes[current_number] = new CWiiMote(current_number, g_WiiMotesFromWiiUse[i]);
|
||||
g_WiimoteInUse[current_number] = true;
|
||||
switch (current_number)
|
||||
{
|
||||
case 0:
|
||||
wiiuse_set_leds(g_WiiMotesFromWiiUse[i], WIIMOTE_LED_1);
|
||||
break;
|
||||
case 1:
|
||||
wiiuse_set_leds(g_WiiMotesFromWiiUse[i], WIIMOTE_LED_2);
|
||||
break;
|
||||
case 2:
|
||||
wiiuse_set_leds(g_WiiMotesFromWiiUse[i], WIIMOTE_LED_3);
|
||||
break;
|
||||
case 3:
|
||||
wiiuse_set_leds(g_WiiMotesFromWiiUse[i], WIIMOTE_LED_4);
|
||||
break;
|
||||
default:
|
||||
PanicAlert("Trying to create real wiimote %i WTF", current_number);
|
||||
break;
|
||||
}
|
||||
DEBUG_LOG(WIIMOTE, "Real WiiMote allocated as WiiMote #%i", current_number);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are more slots marked as "Real WiiMote" than the number of Real WiiMotes connected, disable them!
|
||||
for(current_number++; current_number < MAX_WIIMOTES; current_number++)
|
||||
{
|
||||
if (WiiMoteEmu::WiiMapping[current_number].Source == 1)
|
||||
g_Config.bNumberEmuWiimotes++;
|
||||
else if (WiiMoteEmu::WiiMapping[current_number].Source == 2)
|
||||
WiiMoteEmu::WiiMapping[current_number].Source = 0;
|
||||
}
|
||||
|
||||
DEBUG_LOG(WIIMOTE, "Using %i Real Wiimote(s) and %i Emu Wiimote(s)", g_Config.bNumberRealWiimotes, g_Config.bNumberEmuWiimotes);
|
||||
|
||||
g_RealWiiMoteAllocated = true;
|
||||
|
||||
}
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
//TODO: Implement
|
||||
}
|
||||
|
||||
void Shutdown(void)
|
||||
{
|
||||
if (!g_RealWiiMoteInitialized)
|
||||
return;
|
||||
// Stop the loop in the thread
|
||||
g_Shutdown = true; // not safe .. might crash when still @ReadWiimote
|
||||
|
||||
// Stop the thread
|
||||
if (g_pReadThread != NULL)
|
||||
{
|
||||
delete g_pReadThread;
|
||||
g_pReadThread = NULL;
|
||||
}
|
||||
|
||||
// Delete the wiimotes
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
{
|
||||
delete g_WiiMotes[i];
|
||||
g_WiiMotes[i] = NULL;
|
||||
}
|
||||
|
||||
// Flash flights
|
||||
if (g_EmulatorState != PLUGIN_EMUSTATE_PLAY && g_RealWiiMotePresent)
|
||||
FlashLights(false);
|
||||
|
||||
// Clean up wiiuse
|
||||
#ifndef WIN32
|
||||
wiiuse_cleanup(g_WiiMotesFromWiiUse, g_NumberOfWiiMotes);
|
||||
g_WiiMotesFromWiiUse = NULL;
|
||||
#endif
|
||||
// Uninitialized
|
||||
g_RealWiiMoteInitialized = false;
|
||||
g_RealWiiMotePresent = false;
|
||||
g_RealWiiMoteAllocated = false;
|
||||
}
|
||||
|
||||
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
//DEBUG_LOG(WIIMOTE, "Real InterruptChannel on WiiMote #%i", _WiimoteNumber);
|
||||
g_WiiMotes[_WiimoteNumber]->SendData(_channelID, (const u8*)_pData, _Size);
|
||||
}
|
||||
|
||||
void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
g_WiiMotes[_WiimoteNumber]->SendData(_channelID, (const u8*)_pData, _Size);
|
||||
|
||||
const hid_packet* const hidp = (hid_packet*)_pData;
|
||||
if (hidp->type == HID_TYPE_SET_REPORT)
|
||||
{
|
||||
u8 handshake_ok = HID_HANDSHAKE_SUCCESS;
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(_WiimoteNumber, _channelID, &handshake_ok, sizeof(handshake_ok));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Read the Wiimote once
|
||||
void Update(int _WiimoteNumber)
|
||||
{
|
||||
//DEBUG_LOG(WIIMOTE, "Real Update on WiiMote #%i", _WiimoteNumber);
|
||||
g_WiiMotes[_WiimoteNumber]->Update();
|
||||
}
|
||||
|
||||
/* Continuously read the Wiimote status. However, the actual sending of data
|
||||
occurs in Update(). If we are not currently using the real Wiimote we allow
|
||||
the separate ReadWiimote() function to run. Wo don't use them at the same
|
||||
time to avoid a potential collision. */
|
||||
THREAD_RETURN ReadWiimote_ThreadFunc(void* arg)
|
||||
{
|
||||
NeedsConnect.Wait();
|
||||
#ifndef _WIN32
|
||||
int Connect;
|
||||
// WiiUse initializes the Wiimotes in Windows right from the wiiuse_find function
|
||||
// The Functionality should REALLY be changed
|
||||
Connect = wiiuse_connect(g_WiiMotesFromWiiUse, MAX_WIIMOTES);
|
||||
DEBUG_LOG(WIIMOTE, "Connected: %i", Connect);
|
||||
#endif
|
||||
Connected.Set();
|
||||
|
||||
while (!g_Shutdown)
|
||||
{
|
||||
// Usually, there is at least one Real Wiimote in use,
|
||||
// except a wiimote gets disconnected unexpectly ingame or wiimote input type gets changed from real to none
|
||||
|
||||
if (g_Config.bNumberRealWiimotes > 0)
|
||||
{
|
||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
||||
if (g_WiimoteInUse[i])
|
||||
g_WiiMotes[i]->ReadData();
|
||||
}
|
||||
//else { idle }
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
// WiiMote Pair-Up, function will return amount of either new paired or unpaired devices
|
||||
int WiimotePairUp(bool unpair)
|
||||
{
|
||||
HANDLE hRadios[256];
|
||||
int nRadios;
|
||||
int nPaired = 0;
|
||||
|
||||
// Enumerate BT radios
|
||||
HBLUETOOTH_RADIO_FIND hFindRadio;
|
||||
BLUETOOTH_FIND_RADIO_PARAMS radioParam;
|
||||
|
||||
radioParam.dwSize = sizeof(BLUETOOTH_FIND_RADIO_PARAMS);
|
||||
nRadios = 0;
|
||||
|
||||
hFindRadio = BluetoothFindFirstRadio(&radioParam, &hRadios[nRadios++]);
|
||||
if (hFindRadio)
|
||||
{
|
||||
while (BluetoothFindNextRadio(&radioParam, &hRadios[nRadios++]));
|
||||
BluetoothFindRadioClose(hFindRadio);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(WIIMOTE, "Pair-Up: Error enumerating radios", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
nRadios--;
|
||||
DEBUG_LOG(WIIMOTE, "Pair-Up: Found %d radios\n", nRadios);
|
||||
|
||||
// Pair with Wii device(s)
|
||||
int radio = 0;
|
||||
|
||||
for (radio = 0; radio < nRadios; radio++)
|
||||
{
|
||||
BLUETOOTH_RADIO_INFO radioInfo;
|
||||
HBLUETOOTH_DEVICE_FIND hFind;
|
||||
|
||||
BLUETOOTH_DEVICE_INFO btdi;
|
||||
BLUETOOTH_DEVICE_SEARCH_PARAMS srch;
|
||||
|
||||
radioInfo.dwSize = sizeof(radioInfo);
|
||||
btdi.dwSize = sizeof(btdi);
|
||||
srch.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS);
|
||||
|
||||
BluetoothGetRadioInfo(hRadios[radio], &radioInfo);
|
||||
|
||||
srch.fReturnAuthenticated = TRUE;
|
||||
srch.fReturnRemembered = TRUE;
|
||||
srch.fReturnConnected = TRUE; // does not filter properly somehow, so we 've to do an additional check on fConnected BT Devices
|
||||
srch.fReturnUnknown = TRUE;
|
||||
srch.fIssueInquiry = TRUE;
|
||||
srch.cTimeoutMultiplier = 2;
|
||||
srch.hRadio = hRadios[radio];
|
||||
|
||||
//DEBUG_LOG(WIIMOTE, "Pair-Up: Scanning for BT Device(s)");
|
||||
|
||||
hFind = BluetoothFindFirstDevice(&srch, &btdi);
|
||||
|
||||
if (hFind == NULL)
|
||||
{
|
||||
ERROR_LOG(WIIMOTE, "Pair-Up: Error enumerating devices: %08x", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
//btdi.szName is sometimes missings it's content - it's a bt feature..
|
||||
|
||||
DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ", btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered);
|
||||
|
||||
if ((!wcscmp(btdi.szName, L"Nintendo RVL-WBC-01") || !wcscmp(btdi.szName, L"Nintendo RVL-CNT-01")) && !btdi.fConnected && !unpair)
|
||||
{
|
||||
//TODO: improve the read of the BT driver, esp. when batteries of the wiimote are removed while being fConnected
|
||||
if (btdi.fRemembered)
|
||||
{
|
||||
// Make Windows forget old expired pairing
|
||||
// we can pretty much ignore the return value here.
|
||||
// it either worked (ERROR_SUCCESS), or the device did not exist (ERROR_NOT_FOUND)
|
||||
// in both cases, there is nothing left.
|
||||
BluetoothRemoveDevice(&btdi.Address);
|
||||
}
|
||||
|
||||
// Activate service
|
||||
DWORD hr = BluetoothSetServiceState(hRadios[radio], &btdi, &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE);
|
||||
if (!hr == ERROR_SUCCESS)
|
||||
{
|
||||
nPaired++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr);
|
||||
}
|
||||
}
|
||||
else if ((!wcscmp(btdi.szName, L"Nintendo RVL-WBC-01") || !wcscmp(btdi.szName, L"Nintendo RVL-CNT-01")) && unpair)
|
||||
{
|
||||
|
||||
BluetoothRemoveDevice(&btdi.Address);
|
||||
NOTICE_LOG(WIIMOTE, "Pair-Up: Automatically removed BT Device on shutdown: %08x", GetLastError());
|
||||
nPaired++;
|
||||
|
||||
}
|
||||
} while (BluetoothFindNextDevice(hFind, &btdi));
|
||||
BluetoothFindRadioClose(hFind);
|
||||
}
|
||||
|
||||
SLEEP(10);
|
||||
|
||||
|
||||
// Clean up
|
||||
for (radio = 0; radio < nRadios; radio++)
|
||||
{
|
||||
CloseHandle(hRadios[radio]);
|
||||
}
|
||||
|
||||
return nPaired;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WIIUSE
|
||||
// Listening for new installed wiimotes, and calling PaiUpRefreshWiimote() when found
|
||||
LRESULT CALLBACK CallBackDeviceChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
|
||||
case WM_DEVICECHANGE:
|
||||
// DBT_DEVNODES_CHANGED 0x007 (devnodes are atm not received); DBT_DEVICEARRIVAL 0x8000 DBT_DEVICEREMOVECOMPLETE 0x8004 // avoiding header file^^
|
||||
if ( ( wParam == 0x8000 || wParam == 0x8004 || wParam == 0x0007 ) )
|
||||
{
|
||||
if (wiiuse_check_system_notification(uMsg, wParam, lParam)) //extern wiiuse function: returns 1 if the event came from a wiimote
|
||||
{
|
||||
switch (wParam)
|
||||
{
|
||||
case 0x8000:
|
||||
if (stoprefresh) // arrival will pop up twice //need to rewrite the stoprefresh thing, to support multiple pair ups in one go
|
||||
{
|
||||
stoprefresh = 0;
|
||||
|
||||
PairUpRefreshWiimote(true);
|
||||
break;
|
||||
}
|
||||
else stoprefresh = 1; //fake arrival wait for second go
|
||||
break;
|
||||
|
||||
case 0x8004:
|
||||
if (!stoprefresh) // removal event will pop up only once (it will also pop up if we add a device: fake arrival, fake removal, real arrival.
|
||||
{
|
||||
PairUpRefreshWiimote(false);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
// Generating a new invisible message window and listening for new messages
|
||||
THREAD_RETURN RunInvisibleMessageWindow_ThreadFunc(void* arg)
|
||||
{
|
||||
MSG Msg;
|
||||
HWND hwnd;
|
||||
BOOL ret;
|
||||
|
||||
WNDCLASSEX WCEx;
|
||||
ZeroMemory(&WCEx, sizeof(WCEx));
|
||||
WCEx.cbSize = sizeof(WCEx);
|
||||
WCEx.lpfnWndProc = CallBackDeviceChange;
|
||||
WCEx.hInstance = g_hInstance;
|
||||
WCEx.lpszClassName = L"MSGWND";
|
||||
|
||||
if (RegisterClassEx(&WCEx) != 0)
|
||||
{
|
||||
hwnd = CreateWindowEx(0, WCEx.lpszClassName, NULL,0,
|
||||
0, 0, 0, 0, HWND_MESSAGE, NULL, g_hInstance, NULL);
|
||||
|
||||
if (!hwnd) {
|
||||
UnregisterClass(WCEx.lpszClassName, g_hInstance);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
wiiuse_register_system_notification(hwnd); //function moved into wiiuse to avoid ddk/wdk dependicies
|
||||
|
||||
while((ret = GetMessage(&Msg, 0, 0, 0)) != 0)
|
||||
{
|
||||
if ( ret == -1) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
TranslateMessage(&Msg);
|
||||
DispatchMessage(&Msg);
|
||||
}
|
||||
}
|
||||
|
||||
UnregisterClass(WCEx.lpszClassName, g_hInstance);
|
||||
|
||||
return (int)Msg.wParam;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ToggleEmulatorState(bool stop) {
|
||||
PostMessage(GetParent((HWND)g_WiimoteInitialize.hWnd), WM_USER, WM_USER_PAUSE, 0);
|
||||
if (stop) {
|
||||
while (g_EmulatorState != PLUGIN_EMUSTATE_PLAY) Sleep(50);
|
||||
}
|
||||
else {
|
||||
while (g_EmulatorState == PLUGIN_EMUSTATE_PLAY) Sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// function gets called by windows callbacks if a wiimote was either installed or removed
|
||||
int PairUpRefreshWiimote(bool addwiimote)
|
||||
{
|
||||
int connectslot = -1;
|
||||
|
||||
if (g_EmulatorState != PLUGIN_EMUSTATE_PLAY)
|
||||
{
|
||||
Shutdown();
|
||||
if (addwiimote)
|
||||
{
|
||||
connectslot = PairUpFindNewSlot();
|
||||
}
|
||||
Initialize();
|
||||
if (m_BasicConfigFrame != NULL)
|
||||
m_BasicConfigFrame->UpdateGUI();
|
||||
}
|
||||
else {
|
||||
|
||||
ToggleEmulatorState(true);
|
||||
Shutdown();
|
||||
if (addwiimote)
|
||||
{
|
||||
connectslot = PairUpFindNewSlot();
|
||||
}
|
||||
Initialize();
|
||||
Allocate();
|
||||
ToggleEmulatorState(false);
|
||||
if (addwiimote)
|
||||
PostMessage(GetParent((HWND)g_WiimoteInitialize.hWnd), WM_USER, WM_USER_KEYDOWN, (3 + connectslot));
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// returns first inactive wiimote slot to place new wiimote and set type to real wiimote
|
||||
int PairUpFindNewSlot() {
|
||||
int realWM = 0;
|
||||
for(int x=0; x<MAX_WIIMOTES; x++)
|
||||
{
|
||||
if (WiiMoteEmu::WiiMapping[x].Source == 0)
|
||||
{
|
||||
WiiMoteEmu::WiiMapping[x].Source = 2;
|
||||
return x;
|
||||
} else if (WiiMoteEmu::WiiMapping[x].Source == 2) {
|
||||
realWM++;
|
||||
if (realWM>g_NumberOfWiiMotes)
|
||||
return x;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
// loop to poll and install new bluetooth devices; windows callback will take care of the rest on successful installation
|
||||
THREAD_RETURN PairUp_ThreadFunc(void* arg)
|
||||
{
|
||||
Sleep(100); //small pause till the callback is registered on first start
|
||||
DEBUG_LOG(WIIMOTE, "PairUp_ThreadFunc started.");
|
||||
g_StartAutopairThread.Init();
|
||||
int result;
|
||||
|
||||
while(1) {
|
||||
if (g_Config.bPairRealWiimote) {
|
||||
PairUpTimer = 2000;
|
||||
result = g_StartAutopairThread.Wait(PairUpTimer);
|
||||
}
|
||||
else {
|
||||
result = g_StartAutopairThread.Wait();
|
||||
}
|
||||
|
||||
if (result)
|
||||
WiimotePairUp(false);
|
||||
else {
|
||||
if (m_BasicConfigFrame != NULL)
|
||||
m_BasicConfigFrame->UpdateBasicConfigDialog(false);
|
||||
WiimotePairUp(false);
|
||||
if (m_BasicConfigFrame != NULL)
|
||||
m_BasicConfigFrame->UpdateBasicConfigDialog(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
DEBUG_LOG(WIIMOTE, "PairUp_ThreadFunc terminated.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}; // end of namespace
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#ifndef WIIMOTE_REAL_H
|
||||
#define WIIMOTE_REAL_H
|
||||
|
||||
|
||||
#include "wiiuse.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
#ifndef EXCLUDE_H
|
||||
//this one is required for Common::Event
|
||||
#include "Thread.h"
|
||||
#endif
|
||||
|
||||
namespace WiiMoteReal
|
||||
{
|
||||
|
||||
int Initialize();
|
||||
#ifdef _WIN32
|
||||
int WiimotePairUp(bool unpair);
|
||||
#endif
|
||||
|
||||
void Allocate();
|
||||
void DoState(PointerWrap &p);
|
||||
void Shutdown(void);
|
||||
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
|
||||
void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
|
||||
void Update(int _WiimoteNumber);
|
||||
|
||||
void SendAcc(u8 _ReportID);
|
||||
void ClearEvents();
|
||||
|
||||
|
||||
#ifndef EXCLUDE_H
|
||||
extern wiimote_t** g_WiiMotesFromWiiUse;
|
||||
extern bool g_Shutdown;
|
||||
extern int g_NumberOfWiiMotes;
|
||||
extern int LastNumberOfWiimotes;
|
||||
#ifdef _WIN32
|
||||
extern Common::Thread* g_AutoPairUpInvisibleWindow;
|
||||
extern Common::Thread* g_AutoPairUpMonitoring;
|
||||
extern Common::Event g_StartAutopairThread;
|
||||
THREAD_RETURN PairUp_ThreadFunc(void* arg);
|
||||
THREAD_RETURN RunInvisibleMessageWindow_ThreadFunc(void* arg);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}; // WiiMoteReal
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,648 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="Plugin_WiimoteNew"
|
||||
ProjectGUID="{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}"
|
||||
RootNamespace="Plugin_WiimoteNew"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;_SECURE_SCL=0"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
AssemblerListingLocation="$(IntDir)\"
|
||||
ProgramDataBaseFileName="$(IntDir)\"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib rpcrt4.lib winmm.lib wxbase28ud.lib wxmsw28ud_core.lib openal32.lib wiiuse.lib"
|
||||
OutputFile="..\..\..\Binary\Win32/Plugins\Plugin_WiimoteNewD.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""..\..\..\Externals\SDL\$(PlatformName)";"..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)";../../../Externals/OpenAL/Win32/;"..\..\..\Externals\WiiUse\$(PlatformName)""
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="0"
|
||||
EnableCOMDATFolding="0"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;_SECURE_SCL=0"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
AssemblerListingLocation="$(IntDir)\"
|
||||
ProgramDataBaseFileName="$(IntDir)\"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib rpcrt4.lib winmm.lib wxbase28ud.lib wxmsw28ud_core.lib openal32.lib wiiuse.lib"
|
||||
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_WiimoteNewD.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""..\..\..\Externals\SDL\$(PlatformName)";"..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)";../../../Externals/OpenAL/Win64/;"..\..\..\Externals\WiiUse\$(PlatformName)""
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="0"
|
||||
EnableCOMDATFolding="0"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS"
|
||||
RuntimeLibrary="0"
|
||||
AssemblerListingLocation="$(IntDir)\"
|
||||
ProgramDataBaseFileName="$(IntDir)\"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/NODEFAULTLIB:msvcrt.lib"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib openal32.lib wiiuse.lib"
|
||||
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_WiimoteNew.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""..\..\..\Externals\SDL\$(PlatformName)";"..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)";../../../Externals/OpenAL/Win32/;"..\..\..\Externals\WiiUse\$(PlatformName)""
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="0"
|
||||
EnableCOMDATFolding="0"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
CommandLine=""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS"
|
||||
RuntimeLibrary="0"
|
||||
AssemblerListingLocation="$(IntDir)\"
|
||||
ProgramDataBaseFileName="$(IntDir)\"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib openal32.lib wiiuse.lib"
|
||||
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_WiimoteNew.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""..\..\..\Externals\SDL\$(PlatformName)";"..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)";../../../Externals/OpenAL/Win64/;"..\..\..\Externals\WiiUse\$(PlatformName)""
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="0"
|
||||
EnableCOMDATFolding="0"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="DebugFast|Win32"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="DEBUGFAST;WIN32;NDEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
RuntimeLibrary="0"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/NODEFAULTLIB:msvcrt.lib"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib openal32.lib wiiuse.lib"
|
||||
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_WiimoteNewDF.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""..\..\..\Externals\SDL\$(PlatformName)";"..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)";../../../Externals/OpenAL/Win32/;"..\..\..\Externals\WiiUse\$(PlatformName)""
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="DebugFast|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include_1.3;..\..\..\Externals\WiiUse\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc;..\..\Core\Common\Src;..\..\Core\InputCommon\Src;..\..\Core\InputUICommon\Src"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;Plugin_WiimoteNew_TEST_EXPORTS;DEBUGFAST;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
|
||||
RuntimeLibrary="0"
|
||||
WarningLevel="3"
|
||||
WarnAsError="false"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="SDL.lib xinput.lib comctl32.lib winmm.lib wxbase28u.lib wxmsw28u_core.lib openal32.lib wiiuse.lib"
|
||||
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_WiimoteNewDF.dll"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories=""..\..\..\Externals\SDL\$(PlatformName)";"..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)";../../../Externals/OpenAL/Win64/;"..\..\..\Externals\WiiUse\$(PlatformName)""
|
||||
GenerateManifest="false"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="WiimoteEmu"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\EmuSubroutines.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Encryption.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Encryption.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\MatrixMath.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Speaker.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\UDPTLayer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\WiimoteEmu.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\WiimoteEmu.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\WiimoteHid.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Attachment"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Attachment.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Attachment.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Classic.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Classic.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Drums.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Drums.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Guitar.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Guitar.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Nunchuk.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Nunchuk.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Turntable.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteEmu\Attachment\Turntable.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="WiimoteReal"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteReal\WiimoteReal.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteReal\WiimoteReal.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteConfigDiag.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteConfigDiag.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\WiimoteNew.cpp"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -1,36 +0,0 @@
|
||||
# -*- python -*-
|
||||
|
||||
Import('env')
|
||||
import os
|
||||
import sys
|
||||
|
||||
name = os.sep + "Plugin_WiimoteNew"
|
||||
|
||||
files = [
|
||||
'WiimoteEmu/WiimoteEmu.cpp',
|
||||
'WiimoteEmu/Attachment/Classic.cpp',
|
||||
'WiimoteEmu/Attachment/Attachment.cpp',
|
||||
'WiimoteEmu/Attachment/Nunchuk.cpp',
|
||||
'WiimoteEmu/Attachment/Drums.cpp',
|
||||
'WiimoteEmu/Attachment/Guitar.cpp',
|
||||
'WiimoteEmu/Attachment/Turntable.cpp',
|
||||
'WiimoteEmu/EmuSubroutines.cpp',
|
||||
'WiimoteEmu/Encryption.cpp',
|
||||
'WiimoteEmu/Speaker.cpp',
|
||||
'WiimoteNew.cpp'
|
||||
]
|
||||
|
||||
libs = [ 'inputcommon', 'common' ]
|
||||
|
||||
if not sys.platform == 'darwin':
|
||||
libs += [ 'SDL' ]
|
||||
|
||||
if env['HAVE_WX']:
|
||||
libs = [ 'inputuicommon' ] + libs
|
||||
files += [ 'WiimoteConfigDiag.cpp' ]
|
||||
|
||||
if env['HAVE_WIIUSE']:
|
||||
files += [ 'WiimoteReal/WiimoteReal.cpp' ]
|
||||
libs += [ 'wiiuse' ]
|
||||
|
||||
env.SharedLibrary(env['plugin_dir'] + name, files, LIBS = libs + env['LIBS'])
|
||||
@@ -1,153 +0,0 @@
|
||||
|
||||
#include "WiimoteConfigDiag.h"
|
||||
#include "WiimoteReal/WiimoteReal.h"
|
||||
|
||||
#define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s)
|
||||
|
||||
const wxString& ConnectedWiimotesString()
|
||||
{
|
||||
static wxString str = wxT("Connected to . Wiimotes");
|
||||
str[13] = wxChar(wxT('0') + WiimoteReal::Initialize());
|
||||
return str;
|
||||
}
|
||||
|
||||
WiimoteConfigPage::WiimoteConfigPage(wxWindow* const parent, const int index)
|
||||
: wxNotebookPage(parent, -1, wxDefaultPosition, wxDefaultSize)
|
||||
, m_index(index)
|
||||
{
|
||||
// input source
|
||||
const wxString src_choices[] = { wxT("None"),
|
||||
wxT("Emulated Wiimote"), wxT("Real Wiimote"), wxT("Hybrid Wiimote") };
|
||||
|
||||
wxChoice* const input_src_choice = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize,
|
||||
sizeof(src_choices)/sizeof(*src_choices), src_choices);
|
||||
input_src_choice->Select(g_wiimote_sources[m_index]);
|
||||
_connect_macro_(input_src_choice, WiimoteConfigPage::SelectSource, wxEVT_COMMAND_CHOICE_SELECTED, this);
|
||||
|
||||
wxStaticBoxSizer* const input_src_sizer = new wxStaticBoxSizer(wxHORIZONTAL, this, wxT("Input Source"));
|
||||
input_src_sizer->Add(input_src_choice, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
// emulated wiimote
|
||||
wxButton* const configure_wiimote_emu_btn = new wxButton(this, -1, wxT("Configure"));
|
||||
wxStaticBoxSizer* const wiimote_emu_sizer = new wxStaticBoxSizer(wxHORIZONTAL, this, wxT("Emulated Wiimote"));
|
||||
wiimote_emu_sizer->Add(configure_wiimote_emu_btn, 1, wxEXPAND | wxALL, 5);
|
||||
_connect_macro_(configure_wiimote_emu_btn, WiimoteConfigDiag::ConfigEmulatedWiimote, wxEVT_COMMAND_BUTTON_CLICKED, parent->GetParent());
|
||||
|
||||
// real wiimote
|
||||
connected_wiimotes_txt = new wxStaticText(this, -1, ConnectedWiimotesString());
|
||||
|
||||
wxButton* const refresh_btn = new wxButton(this, -1, wxT("Refresh"), wxDefaultPosition);
|
||||
_connect_macro_(refresh_btn, WiimoteConfigDiag::RefreshRealWiimotes, wxEVT_COMMAND_BUTTON_CLICKED, parent->GetParent());
|
||||
|
||||
wxStaticBoxSizer* const wiimote_real_sizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Real Wiimote"));
|
||||
wiimote_real_sizer->AddStretchSpacer(1);
|
||||
wiimote_real_sizer->Add(connected_wiimotes_txt, 0, wxALIGN_CENTER | wxBOTTOM | wxLEFT | wxRIGHT, 5);
|
||||
#ifdef _WIN32
|
||||
wxButton* const pairup_btn = new wxButton(this, -1, wxT("Pair Up"), wxDefaultPosition);
|
||||
_connect_macro_(pairup_btn, WiimoteConfigDiag::PairUpRealWiimotes, wxEVT_COMMAND_BUTTON_CLICKED, parent->GetParent());
|
||||
wiimote_real_sizer->Add(pairup_btn, 0, wxALIGN_CENTER | wxBOTTOM, 5);
|
||||
#endif
|
||||
wiimote_real_sizer->Add(refresh_btn, 0, wxALIGN_CENTER, 5);
|
||||
wiimote_real_sizer->AddStretchSpacer(1);
|
||||
|
||||
// sizers
|
||||
wxBoxSizer* const left_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
left_sizer->Add(input_src_sizer, 0, wxEXPAND | wxBOTTOM, 5);
|
||||
left_sizer->Add(wiimote_emu_sizer, 0, wxEXPAND, 0);
|
||||
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
main_sizer->Add(left_sizer, 1, wxLEFT | wxTOP | wxBOTTOM | wxEXPAND, 5);
|
||||
main_sizer->Add(wiimote_real_sizer, 1, wxALL | wxEXPAND, 5);
|
||||
|
||||
SetSizerAndFit(main_sizer);
|
||||
Layout();
|
||||
}
|
||||
|
||||
WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin)
|
||||
: wxDialog(parent, -1, wxT("Dolphin Wiimote Configuration"), wxDefaultPosition, wxDefaultSize)
|
||||
, m_plugin(plugin)
|
||||
{
|
||||
m_pad_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT);
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
WiimoteConfigPage* const wpage = new WiimoteConfigPage(m_pad_notebook, i);
|
||||
//m_padpages.push_back(wpage);
|
||||
m_pad_notebook->AddPage(wpage, wxString(wxT("Wiimote ")) + wxChar('1'+i));
|
||||
}
|
||||
|
||||
wxButton* const ok_button = new wxButton(this, -1, wxT("OK"), wxDefaultPosition);
|
||||
_connect_macro_(ok_button, WiimoteConfigDiag::Save, wxEVT_COMMAND_BUTTON_CLICKED, this);
|
||||
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(m_pad_notebook, 1, wxEXPAND | wxALL, 5);
|
||||
main_sizer->Add(ok_button, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
SetSizerAndFit(main_sizer);
|
||||
|
||||
Center();
|
||||
}
|
||||
|
||||
void WiimoteConfigDiag::ConfigEmulatedWiimote(wxCommandEvent& event)
|
||||
{
|
||||
InputConfigDialog* const m_emu_config_diag = new InputConfigDialog(this, m_plugin, "Dolphin Emulated Wiimote Configuration", m_pad_notebook->GetSelection());
|
||||
m_emu_config_diag->ShowModal();
|
||||
m_emu_config_diag->Destroy();
|
||||
}
|
||||
|
||||
void WiimoteConfigDiag::UpdateGUI()
|
||||
{
|
||||
for (size_t p = 0; p < m_pad_notebook->GetPageCount(); ++p)
|
||||
((WiimoteConfigPage*)m_pad_notebook->GetPage(p))->
|
||||
connected_wiimotes_txt->SetLabel(ConnectedWiimotesString());
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void WiimoteConfigDiag::PairUpRealWiimotes(wxCommandEvent& event)
|
||||
{
|
||||
const int paired = WiimoteReal::PairUp();
|
||||
|
||||
if (paired > 0)
|
||||
{
|
||||
// Will this message be anoying?
|
||||
//PanicAlert("Paired %d wiimotes.", paired);
|
||||
WiimoteReal::Refresh();
|
||||
UpdateGUI();
|
||||
}
|
||||
else if (paired < 0)
|
||||
PanicAlert("A supported bluetooth device was not found!\n"
|
||||
"(Only the Microsoft bluetooth stack is supported.)");
|
||||
}
|
||||
#endif
|
||||
|
||||
void WiimoteConfigDiag::RefreshRealWiimotes(wxCommandEvent& event)
|
||||
{
|
||||
WiimoteReal::Refresh();
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void WiimoteConfigPage::SelectSource(wxCommandEvent& event)
|
||||
{
|
||||
// should be kinda fine, maybe should just set when user clicks OK, w/e change it later
|
||||
g_wiimote_sources[m_index] = event.GetInt();
|
||||
}
|
||||
|
||||
void WiimoteConfigDiag::Save(wxCommandEvent& event)
|
||||
{
|
||||
std::string ini_filename = (std::string(File::GetUserPath(D_CONFIG_IDX)) + g_plugin.ini_name + ".ini" );
|
||||
|
||||
IniFile inifile;
|
||||
inifile.Load(ini_filename);
|
||||
|
||||
for (unsigned int i=0; i<MAX_WIIMOTES; ++i)
|
||||
{
|
||||
std::string secname("Wiimote");
|
||||
secname += (char)('1' + i);
|
||||
IniFile::Section& sec = *inifile.GetOrCreateSection(secname.c_str());
|
||||
|
||||
sec.Set("Source", (int)g_wiimote_sources[i]);
|
||||
}
|
||||
|
||||
inifile.Save(ini_filename);
|
||||
|
||||
Close();
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
|
||||
#ifndef WIIMOTE_CONFIG_DIAG_H
|
||||
#define WIIMOTE_CONFIG_DIAG_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/listbox.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/combobox.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/spinctrl.h>
|
||||
|
||||
#include "ConfigDiag.h"
|
||||
|
||||
class WiimoteConfigPage : public wxNotebookPage
|
||||
{
|
||||
public:
|
||||
WiimoteConfigPage(wxWindow* const parent, const int index);
|
||||
|
||||
void SelectSource(wxCommandEvent& event);
|
||||
|
||||
wxStaticText* connected_wiimotes_txt;
|
||||
|
||||
private:
|
||||
const int m_index;
|
||||
};
|
||||
|
||||
class WiimoteConfigDiag : public wxDialog
|
||||
{
|
||||
public:
|
||||
WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin);
|
||||
|
||||
#ifdef _WIN32
|
||||
void PairUpRealWiimotes(wxCommandEvent& event);
|
||||
#endif
|
||||
void RefreshRealWiimotes(wxCommandEvent& event);
|
||||
|
||||
void ConfigEmulatedWiimote(wxCommandEvent& event);
|
||||
void Save(wxCommandEvent& event);
|
||||
void UpdateGUI();
|
||||
|
||||
private:
|
||||
InputPlugin& m_plugin;
|
||||
|
||||
wxNotebook* m_pad_notebook;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
#include "Attachment.h"
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
// Extension device IDs to be written to the last bytes of the extension reg
|
||||
// The id for nothing inserted
|
||||
static const u8 nothing_id[] = { 0x00, 0x00, 0x00, 0x00, 0x2e, 0x2e };
|
||||
// The id for a partially inserted extension
|
||||
static const u8 partially_id[] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
|
||||
|
||||
Attachment::Attachment( const char* const _name ) : name( _name )
|
||||
{
|
||||
reg.resize( WIIMOTE_REG_EXT_SIZE, 0);
|
||||
}
|
||||
|
||||
None::None() : Attachment( "None" )
|
||||
{
|
||||
// set up register
|
||||
memcpy( ®[0xfa], nothing_id, sizeof(nothing_id) );
|
||||
}
|
||||
|
||||
std::string Attachment::GetName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ControllerEmu::Extension::GetState( u8* const data, const bool focus )
|
||||
{
|
||||
((WiimoteEmu::Attachment*)attachments[ active_extension ])->GetState( data, focus );
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#ifndef _ATTACHMENT_EMU_H_
|
||||
#define _ATTACHMENT_EMU_H_
|
||||
|
||||
#include "ControllerEmu.h"
|
||||
#include "../WiimoteEmu.h"
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
class Attachment : public ControllerEmu
|
||||
{
|
||||
public:
|
||||
Attachment( const char* const _name );
|
||||
|
||||
virtual void GetState( u8* const data, const bool focus = true ) {}
|
||||
std::string GetName() const;
|
||||
|
||||
const char* const name;
|
||||
std::vector<u8> reg;
|
||||
};
|
||||
|
||||
class None : public Attachment
|
||||
{
|
||||
public:
|
||||
None();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,130 +0,0 @@
|
||||
#include "Classic.h"
|
||||
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
static const u8 classic_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x01, 0x01 };
|
||||
/* Classic Controller calibration */
|
||||
static const u8 classic_calibration[] =
|
||||
{
|
||||
0xff, 0x00, 0x80, 0xff, 0x00, 0x80,
|
||||
0xff, 0x00, 0x80, 0xff, 0x00, 0x80,
|
||||
0x00, 0x00, 0x51, 0xa6
|
||||
};
|
||||
|
||||
static const u16 classic_button_bitmasks[] =
|
||||
{
|
||||
Classic::BUTTON_A,
|
||||
Classic::BUTTON_B,
|
||||
Classic::BUTTON_X,
|
||||
Classic::BUTTON_Y,
|
||||
|
||||
Classic::BUTTON_ZL,
|
||||
Classic::BUTTON_ZR,
|
||||
|
||||
Classic::BUTTON_MINUS,
|
||||
Classic::BUTTON_PLUS,
|
||||
|
||||
Classic::BUTTON_HOME,
|
||||
};
|
||||
|
||||
static const char* const classic_button_names[] =
|
||||
{
|
||||
"A","B","X","Y","ZL","ZR","-","+","Home",
|
||||
};
|
||||
|
||||
static const u16 classic_trigger_bitmasks[] =
|
||||
{
|
||||
Classic::TRIGGER_L, Classic::TRIGGER_R,
|
||||
};
|
||||
|
||||
static const char* const classic_trigger_names[] =
|
||||
{
|
||||
"L", "R", "L-Analog", "R-Analog"
|
||||
};
|
||||
|
||||
static const u16 classic_dpad_bitmasks[] =
|
||||
{
|
||||
Classic::PAD_UP, Classic::PAD_DOWN, Classic::PAD_LEFT, Classic::PAD_RIGHT
|
||||
};
|
||||
|
||||
Classic::Classic() : Attachment( "Classic" )
|
||||
{
|
||||
// buttons
|
||||
groups.push_back( m_buttons = new Buttons( "Buttons" ) );
|
||||
for ( unsigned int i = 0; i < sizeof(classic_button_names)/sizeof(*classic_button_names); ++i )
|
||||
m_buttons->controls.push_back( new ControlGroup::Input( classic_button_names[i] ) );
|
||||
|
||||
// sticks
|
||||
groups.push_back( m_left_stick = new AnalogStick( "Left Stick" ) );
|
||||
groups.push_back( m_right_stick = new AnalogStick( "Right Stick" ) );
|
||||
|
||||
// triggers
|
||||
groups.push_back( m_triggers = new MixedTriggers( "Triggers" ) );
|
||||
for ( unsigned int i=0; i < sizeof(classic_trigger_names)/sizeof(*classic_trigger_names); ++i )
|
||||
m_triggers->controls.push_back( new ControlGroup::Input( classic_trigger_names[i] ) );
|
||||
|
||||
// dpad
|
||||
groups.push_back( m_dpad = new Buttons( "D-Pad" ) );
|
||||
for ( unsigned int i=0; i < 4; ++i )
|
||||
m_dpad->controls.push_back( new ControlGroup::Input( named_directions[i] ) );
|
||||
|
||||
// set up register
|
||||
// calibration
|
||||
memcpy( ®[0x20], classic_calibration, sizeof(classic_calibration) );
|
||||
// id
|
||||
memcpy( ®[0xfa], classic_id, sizeof(classic_id) );
|
||||
}
|
||||
|
||||
void Classic::GetState( u8* const data, const bool focus )
|
||||
{
|
||||
wm_classic_extension* const ccdata = (wm_classic_extension*)data;
|
||||
ccdata->bt = 0;
|
||||
|
||||
// not using calibration data, o well
|
||||
|
||||
// left stick
|
||||
{
|
||||
u8 x, y;
|
||||
m_left_stick->GetState( &x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0 );
|
||||
|
||||
ccdata->lx = x;
|
||||
ccdata->ly = y;
|
||||
}
|
||||
|
||||
// right stick
|
||||
{
|
||||
u8 x, y;
|
||||
m_right_stick->GetState( &x, &y, 0x10, focus ? 0x0F /*0x0C*/ : 0 );
|
||||
|
||||
ccdata->rx1 = x;
|
||||
ccdata->rx2 = x >> 1;
|
||||
ccdata->rx3 = x >> 3;
|
||||
ccdata->ry = y;
|
||||
}
|
||||
|
||||
//triggers
|
||||
{
|
||||
u8 trigs[2];
|
||||
m_triggers->GetState( &ccdata->bt, classic_trigger_bitmasks, trigs, focus ? 0x1F : 0 );
|
||||
|
||||
ccdata->lt1 = trigs[0];
|
||||
ccdata->lt2 = trigs[0] >> 3;
|
||||
ccdata->rt = trigs[1];
|
||||
}
|
||||
|
||||
if (focus)
|
||||
{
|
||||
// buttons
|
||||
m_buttons->GetState( &ccdata->bt, classic_button_bitmasks );
|
||||
// dpad
|
||||
m_dpad->GetState( &ccdata->bt, classic_dpad_bitmasks );
|
||||
}
|
||||
|
||||
// flip button bits
|
||||
ccdata->bt ^= 0xFFFF;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#include "Attachment.h"
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
class Classic : public Attachment
|
||||
{
|
||||
public:
|
||||
Classic();
|
||||
void GetState( u8* const data, const bool focus );
|
||||
|
||||
enum
|
||||
{
|
||||
PAD_RIGHT = 0x80,
|
||||
PAD_DOWN = 0x40,
|
||||
TRIGGER_L = 0x20,
|
||||
BUTTON_MINUS = 0x10,
|
||||
BUTTON_HOME = 0x08,
|
||||
BUTTON_PLUS = 0x04,
|
||||
TRIGGER_R = 0x02,
|
||||
NOTHING = 0x01,
|
||||
BUTTON_ZL = 0x8000,
|
||||
BUTTON_B = 0x4000,
|
||||
BUTTON_Y = 0x2000,
|
||||
BUTTON_A = 0x1000,
|
||||
BUTTON_X = 0x0800,
|
||||
BUTTON_ZR = 0x0400,
|
||||
PAD_LEFT = 0x0200,
|
||||
PAD_UP = 0x0100,
|
||||
};
|
||||
|
||||
private:
|
||||
Buttons* m_buttons;
|
||||
MixedTriggers* m_triggers;
|
||||
Buttons* m_dpad;
|
||||
AnalogStick* m_left_stick;
|
||||
AnalogStick* m_right_stick;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
#include "Drums.h"
|
||||
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
static const u8 drums_id[] = { 0x01, 0x00, 0xa4, 0x20, 0x01, 0x03 };
|
||||
|
||||
static const u16 drum_pad_bitmasks[] =
|
||||
{
|
||||
Drums::PAD_RED,
|
||||
Drums::PAD_YELLOW,
|
||||
Drums::PAD_BLUE,
|
||||
Drums::PAD_GREEN,
|
||||
Drums::PAD_ORANGE,
|
||||
Drums::PAD_BASS,
|
||||
};
|
||||
|
||||
static const char* const drum_pad_names[] =
|
||||
{
|
||||
"Red","Yellow","Blue","Green","Orange","Bass"
|
||||
};
|
||||
|
||||
static const u16 drum_button_bitmasks[] =
|
||||
{
|
||||
Drums::BUTTON_MINUS,
|
||||
Drums::BUTTON_PLUS,
|
||||
};
|
||||
|
||||
Drums::Drums() : Attachment( "Drums" )
|
||||
{
|
||||
// pads
|
||||
groups.push_back( m_pads = new Buttons( "Pads" ) );
|
||||
for ( unsigned int i = 0; i < sizeof(drum_pad_names)/sizeof(*drum_pad_names); ++i )
|
||||
m_pads->controls.push_back( new ControlGroup::Input( drum_pad_names[i] ) );
|
||||
|
||||
// stick
|
||||
groups.push_back( m_stick = new AnalogStick( "Stick" ) );
|
||||
|
||||
// buttons
|
||||
groups.push_back( m_buttons = new Buttons( "Buttons" ) );
|
||||
m_buttons->controls.push_back( new ControlGroup::Input("-") );
|
||||
m_buttons->controls.push_back( new ControlGroup::Input("+") );
|
||||
|
||||
// set up register
|
||||
// id
|
||||
memcpy( ®[0xfa], drums_id, sizeof(drums_id) );
|
||||
}
|
||||
|
||||
void Drums::GetState(u8* const data, const bool focus)
|
||||
{
|
||||
wm_drums_extension* const ddata = (wm_drums_extension*)data;
|
||||
ddata->bt = 0;
|
||||
|
||||
// calibration data not figured out yet?
|
||||
|
||||
// stick
|
||||
{
|
||||
u8 x, y;
|
||||
m_stick->GetState( &x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0 );
|
||||
|
||||
ddata->sx = x;
|
||||
ddata->sy = y;
|
||||
}
|
||||
|
||||
// TODO: softness maybe
|
||||
data[2] = 0xFF;
|
||||
data[3] = 0xFF;
|
||||
|
||||
if (focus)
|
||||
{
|
||||
// buttons
|
||||
m_buttons->GetState( &ddata->bt, drum_button_bitmasks );
|
||||
// pads
|
||||
m_pads->GetState( &ddata->bt, drum_pad_bitmasks );
|
||||
}
|
||||
|
||||
// flip button bits
|
||||
ddata->bt ^= 0xFFFF;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#include "Attachment.h"
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
class Drums : public Attachment
|
||||
{
|
||||
public:
|
||||
Drums();
|
||||
void GetState( u8* const data, const bool focus );
|
||||
|
||||
enum
|
||||
{
|
||||
BUTTON_PLUS = 0x04,
|
||||
BUTTON_MINUS = 0x10,
|
||||
|
||||
PAD_BASS = 0x0400,
|
||||
PAD_BLUE = 0x0800,
|
||||
PAD_GREEN = 0x1000,
|
||||
PAD_YELLOW = 0x2000,
|
||||
PAD_RED = 0x4000,
|
||||
PAD_ORANGE = 0x8000,
|
||||
};
|
||||
|
||||
private:
|
||||
Buttons* m_buttons;
|
||||
Buttons* m_pads;
|
||||
AnalogStick* m_stick;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
#include "Guitar.h"
|
||||
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
static const u8 guitar_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x01, 0x03 };
|
||||
|
||||
static const u16 guitar_fret_bitmasks[] =
|
||||
{
|
||||
Guitar::FRET_GREEN,
|
||||
Guitar::FRET_RED,
|
||||
Guitar::FRET_YELLOW,
|
||||
Guitar::FRET_BLUE,
|
||||
Guitar::FRET_ORANGE,
|
||||
};
|
||||
|
||||
static const char* const guitar_fret_names[] =
|
||||
{
|
||||
"Green","Red","Yellow","Blue","Orange",
|
||||
};
|
||||
|
||||
static const u16 guitar_button_bitmasks[] =
|
||||
{
|
||||
Guitar::BUTTON_MINUS,
|
||||
Guitar::BUTTON_PLUS,
|
||||
};
|
||||
|
||||
static const u16 guitar_strum_bitmasks[] =
|
||||
{
|
||||
Guitar::BAR_UP,
|
||||
Guitar::BAR_DOWN,
|
||||
};
|
||||
|
||||
Guitar::Guitar() : Attachment( "Guitar" )
|
||||
{
|
||||
// frets
|
||||
groups.push_back( m_frets = new Buttons( "Frets" ) );
|
||||
for ( unsigned int i = 0; i < sizeof(guitar_fret_names)/sizeof(*guitar_fret_names); ++i )
|
||||
m_frets->controls.push_back( new ControlGroup::Input( guitar_fret_names[i] ) );
|
||||
|
||||
// strum
|
||||
groups.push_back( m_strum = new Buttons( "Strum" ) );
|
||||
m_strum->controls.push_back( new ControlGroup::Input("Up") );
|
||||
m_strum->controls.push_back( new ControlGroup::Input("Down") );
|
||||
|
||||
// buttons
|
||||
groups.push_back( m_buttons = new Buttons( "Buttons" ) );
|
||||
m_buttons->controls.push_back( new ControlGroup::Input("-") );
|
||||
m_buttons->controls.push_back( new ControlGroup::Input("+") );
|
||||
|
||||
// stick
|
||||
groups.push_back( m_stick = new AnalogStick( "Stick" ) );
|
||||
|
||||
// whammy
|
||||
groups.push_back( m_whammy = new Triggers( "Whammy" ) );
|
||||
m_whammy->controls.push_back( new ControlGroup::Input("Bar") );
|
||||
|
||||
// set up register
|
||||
// id
|
||||
memcpy( ®[0xfa], guitar_id, sizeof(guitar_id) );
|
||||
}
|
||||
|
||||
void Guitar::GetState(u8* const data, const bool focus)
|
||||
{
|
||||
wm_guitar_extension* const gdata = (wm_guitar_extension*)data;
|
||||
gdata->bt = 0;
|
||||
|
||||
// calibration data not figured out yet?
|
||||
|
||||
// stick
|
||||
{
|
||||
u8 x, y;
|
||||
m_stick->GetState( &x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0 );
|
||||
|
||||
gdata->sx = x;
|
||||
gdata->sy = y;
|
||||
}
|
||||
|
||||
// TODO: touch bar, probably not
|
||||
gdata->tb = 0x0F; // not touched
|
||||
|
||||
// whammy bar
|
||||
u8 whammy;
|
||||
m_whammy->GetState( &whammy, 0x1F );
|
||||
gdata->whammy = whammy;
|
||||
|
||||
if (focus)
|
||||
{
|
||||
// buttons
|
||||
m_buttons->GetState( &gdata->bt, guitar_button_bitmasks );
|
||||
// frets
|
||||
m_frets->GetState( &gdata->bt, guitar_fret_bitmasks );
|
||||
// strum
|
||||
m_strum->GetState( &gdata->bt, guitar_strum_bitmasks );
|
||||
}
|
||||
|
||||
// flip button bits
|
||||
gdata->bt ^= 0xFFFF;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#include "Attachment.h"
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
class Guitar : public Attachment
|
||||
{
|
||||
public:
|
||||
Guitar();
|
||||
void GetState( u8* const data, const bool focus );
|
||||
|
||||
enum
|
||||
{
|
||||
BUTTON_PLUS = 0x04,
|
||||
BUTTON_MINUS = 0x10,
|
||||
BAR_DOWN = 0x40,
|
||||
|
||||
BAR_UP = 0x0100,
|
||||
FRET_YELLOW = 0x0800,
|
||||
FRET_GREEN = 0x1000,
|
||||
FRET_BLUE = 0x2000,
|
||||
FRET_RED = 0x4000,
|
||||
FRET_ORANGE = 0x8000,
|
||||
};
|
||||
|
||||
private:
|
||||
Buttons* m_buttons;
|
||||
Buttons* m_frets;
|
||||
Buttons* m_strum;
|
||||
Triggers* m_whammy;
|
||||
AnalogStick* m_stick;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
#include "Nunchuk.h"
|
||||
|
||||
#include "UDPWrapper.h"
|
||||
#include "UDPWiimote.h"
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
static const u8 nunchuck_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x00, 0x00 };
|
||||
/* Default calibration for the nunchuck. It should be written to 0x20 - 0x3f of the
|
||||
extension register. 0x80 is the neutral x and y accelerators and 0xb3 is the
|
||||
neutral z accelerometer that is adjusted for gravity. */
|
||||
static const u8 nunchuck_calibration[] =
|
||||
{
|
||||
0x80, 0x80, 0x80, 0x00, // accelerometer x, y, z neutral
|
||||
0xb3, 0xb3, 0xb3, 0x00, // x, y, z g-force values
|
||||
|
||||
// 0x80 = analog stick x and y axis center
|
||||
0xff, 0x00, 0x80,
|
||||
0xff, 0x00, 0x80,
|
||||
0xec, 0x41 // checksum on the last two bytes
|
||||
};
|
||||
|
||||
static const u8 nunchuk_button_bitmasks[] =
|
||||
{
|
||||
Nunchuk::BUTTON_C,
|
||||
Nunchuk::BUTTON_Z,
|
||||
};
|
||||
|
||||
Nunchuk::Nunchuk(UDPWrapper *wrp) : Attachment("Nunchuk") , m_udpWrap(wrp)
|
||||
{
|
||||
// buttons
|
||||
groups.push_back(m_buttons = new Buttons("Buttons"));
|
||||
m_buttons->controls.push_back(new ControlGroup::Input("C"));
|
||||
m_buttons->controls.push_back(new ControlGroup::Input("Z"));
|
||||
|
||||
// stick
|
||||
groups.push_back(m_stick = new AnalogStick("Stick"));
|
||||
|
||||
// swing
|
||||
groups.push_back(m_swing = new Force("Swing"));
|
||||
|
||||
// tilt
|
||||
groups.push_back(m_tilt = new Tilt("Tilt"));
|
||||
|
||||
// shake
|
||||
groups.push_back(m_shake = new Buttons("Shake"));
|
||||
m_shake->controls.push_back(new ControlGroup::Input("X"));
|
||||
m_shake->controls.push_back(new ControlGroup::Input("Y"));
|
||||
m_shake->controls.push_back(new ControlGroup::Input("Z"));
|
||||
|
||||
// set up register
|
||||
// calibration
|
||||
memcpy(®[0x20], nunchuck_calibration, sizeof(nunchuck_calibration));
|
||||
// id
|
||||
memcpy(®[0xfa], nunchuck_id, sizeof(nunchuck_id));
|
||||
|
||||
// this should get set to 0 on disconnect, but it isn't, o well
|
||||
memset(m_shake_step, 0, sizeof(m_shake_step));
|
||||
}
|
||||
|
||||
void Nunchuk::GetState(u8* const data, const bool focus)
|
||||
{
|
||||
wm_extension* const ncdata = (wm_extension*)data;
|
||||
ncdata->bt = 0;
|
||||
|
||||
// stick / not using calibration data for stick, o well
|
||||
m_stick->GetState(&ncdata->jx, &ncdata->jy, 0x80, focus ? 127 : 0);
|
||||
|
||||
AccelData accel;
|
||||
|
||||
// tilt
|
||||
EmulateTilt(&accel, m_tilt, focus);
|
||||
|
||||
if (focus)
|
||||
{
|
||||
// swing
|
||||
EmulateSwing(&accel, m_swing);
|
||||
// shake
|
||||
EmulateShake(&accel, m_shake, m_shake_step);
|
||||
// buttons
|
||||
m_buttons->GetState(&ncdata->bt, nunchuk_button_bitmasks);
|
||||
}
|
||||
|
||||
// flip the button bits :/
|
||||
ncdata->bt ^= 0x03;
|
||||
|
||||
//UDPNunchuk stuff
|
||||
if (m_udpWrap->inst)
|
||||
{
|
||||
if (m_udpWrap->updNun)
|
||||
{
|
||||
u8 mask;
|
||||
float x, y;
|
||||
m_udpWrap->inst->getNunchuck(x, y, mask);
|
||||
// buttons
|
||||
if (mask & UDPWM_NC)
|
||||
ncdata->bt &= ~WiimoteEmu::Nunchuk::BUTTON_C;
|
||||
if (mask & UDPWM_NZ)
|
||||
ncdata->bt &= ~WiimoteEmu::Nunchuk::BUTTON_Z;
|
||||
// stick
|
||||
if (ncdata->jx == 0x80 && ncdata->jy == 0x80)
|
||||
{
|
||||
ncdata->jx = u8(0x80 + x*127);
|
||||
ncdata->jy = u8(0x80 + y*127);
|
||||
}
|
||||
}
|
||||
if (m_udpWrap->updNunAccel)
|
||||
{
|
||||
float x,y,z;
|
||||
m_udpWrap->inst->getNunchuckAccel(x,y,z);
|
||||
accel.x=x;
|
||||
accel.y=y;
|
||||
accel.z=z;
|
||||
}
|
||||
}
|
||||
//End UDPNunchuck
|
||||
|
||||
wm_accel* dt = (wm_accel*)&ncdata->ax;
|
||||
accel_cal* calib = (accel_cal*)®[0x20];
|
||||
dt->x=u8(trim(accel.x*(calib->one_g.x-calib->zero_g.x)+calib->zero_g.x));
|
||||
dt->y=u8(trim(accel.y*(calib->one_g.y-calib->zero_g.y)+calib->zero_g.y));
|
||||
dt->z=u8(trim(accel.z*(calib->one_g.z-calib->zero_g.z)+calib->zero_g.z));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
#ifndef NUNCHUCK_H
|
||||
#define NUNCHUCK_H
|
||||
|
||||
#include "Attachment.h"
|
||||
|
||||
class UDPWrapper;
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
class Nunchuk : public Attachment
|
||||
{
|
||||
public:
|
||||
Nunchuk(UDPWrapper * wrp);
|
||||
virtual void GetState( u8* const data, const bool focus );
|
||||
|
||||
enum
|
||||
{
|
||||
BUTTON_C = 0x02,
|
||||
BUTTON_Z = 0x01,
|
||||
};
|
||||
|
||||
private:
|
||||
Tilt* m_tilt;
|
||||
Force* m_swing;
|
||||
|
||||
Buttons* m_shake;
|
||||
|
||||
Buttons* m_buttons;
|
||||
AnalogStick* m_stick;
|
||||
|
||||
unsigned int m_shake_step[3];
|
||||
|
||||
UDPWrapper* const m_udpWrap;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,121 +0,0 @@
|
||||
#include "Turntable.h"
|
||||
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
static const u8 turntable_id[] = {0x03, 0x00, 0xa4, 0x20, 0x01, 0x03};
|
||||
|
||||
static const u16 turntable_button_bitmasks[] =
|
||||
{
|
||||
Turntable::BUTTON_L_GREEN,
|
||||
Turntable::BUTTON_L_RED,
|
||||
Turntable::BUTTON_L_BLUE,
|
||||
Turntable::BUTTON_R_GREEN,
|
||||
Turntable::BUTTON_R_RED,
|
||||
Turntable::BUTTON_R_BLUE,
|
||||
Turntable::BUTTON_MINUS,
|
||||
Turntable::BUTTON_PLUS,
|
||||
Turntable::BUTTON_EUPHORIA,
|
||||
};
|
||||
|
||||
static const char* const turntable_button_names[] =
|
||||
{
|
||||
"Green Left", "Red Left", "Blue Left",
|
||||
"Green Right", "Red Right", "Blue Right",
|
||||
"-", "+", "Euphoria",
|
||||
};
|
||||
|
||||
Turntable::Turntable() : Attachment("Turntable")
|
||||
{
|
||||
// buttons
|
||||
groups.push_back(m_buttons = new Buttons("Buttons"));
|
||||
for (unsigned int i = 0; i < sizeof(turntable_button_names)/sizeof(*turntable_button_names); ++i)
|
||||
m_buttons->controls.push_back(new ControlGroup::Input( turntable_button_names[i]));
|
||||
|
||||
// turntables
|
||||
groups.push_back(m_left_table = new Slider("Table Left"));
|
||||
groups.push_back(m_right_table = new Slider("Table Right"));
|
||||
|
||||
// stick
|
||||
groups.push_back(m_stick = new AnalogStick("Stick"));
|
||||
|
||||
// effect dial
|
||||
groups.push_back(m_effect_dial = new Triggers("Effect"));
|
||||
m_effect_dial->controls.push_back(new ControlGroup::Input("Dial"));
|
||||
|
||||
// crossfade
|
||||
groups.push_back(m_crossfade = new Slider("Crossfade"));
|
||||
|
||||
// set up register
|
||||
// id
|
||||
memcpy(®[0xfa], turntable_id, sizeof(turntable_id));
|
||||
}
|
||||
|
||||
void Turntable::GetState(u8* const data, const bool focus)
|
||||
{
|
||||
wm_turntable_extension* const ttdata = (wm_turntable_extension*)data;
|
||||
ttdata->bt = 0;
|
||||
|
||||
// stick
|
||||
{
|
||||
u8 x, y;
|
||||
m_stick->GetState(&x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0);
|
||||
|
||||
ttdata->sx = x;
|
||||
ttdata->sy = y;
|
||||
}
|
||||
|
||||
// left table
|
||||
{
|
||||
s8 tt = 0;
|
||||
m_left_table->GetState(&tt, focus ? 0x1F : 0);
|
||||
|
||||
ttdata->ltable1 = tt;
|
||||
ttdata->ltable2 = tt << 5;
|
||||
}
|
||||
|
||||
// right table
|
||||
{
|
||||
s8 tt = 0;
|
||||
m_right_table->GetState(&tt, focus ? 0x1F : 0);
|
||||
|
||||
ttdata->rtable1 = tt;
|
||||
ttdata->rtable2 = tt << 1;
|
||||
ttdata->rtable3 = tt << 3;
|
||||
ttdata->rtable4 = tt << 5;
|
||||
}
|
||||
|
||||
// effect dial
|
||||
{
|
||||
u8 dial = 0;
|
||||
m_effect_dial->GetState(&dial, focus ? 0xF : 0);
|
||||
|
||||
ttdata->dial1 = dial;
|
||||
ttdata->dial2 = dial << 3;
|
||||
}
|
||||
|
||||
// crossfade slider
|
||||
{
|
||||
u8 cfs = 0;
|
||||
m_crossfade->GetState(&cfs, 8, 7);
|
||||
|
||||
ttdata->slider = cfs;
|
||||
}
|
||||
|
||||
if (focus)
|
||||
{
|
||||
// buttons
|
||||
m_buttons->GetState(&ttdata->bt, turntable_button_bitmasks);
|
||||
}
|
||||
|
||||
// flip button bits :/
|
||||
ttdata->bt ^= (
|
||||
BUTTON_L_GREEN | BUTTON_L_RED | BUTTON_L_BLUE |
|
||||
BUTTON_R_GREEN | BUTTON_R_RED | BUTTON_R_BLUE |
|
||||
BUTTON_MINUS | BUTTON_PLUS | BUTTON_EUPHORIA
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#include "Attachment.h"
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
class Turntable : public Attachment
|
||||
{
|
||||
public:
|
||||
Turntable();
|
||||
void GetState(u8* const data, const bool focus);
|
||||
|
||||
enum
|
||||
{
|
||||
BUTTON_EUPHORIA = 0x1000,
|
||||
|
||||
BUTTON_L_GREEN = 0x0800,
|
||||
BUTTON_L_RED = 0x20,
|
||||
BUTTON_L_BLUE = 0x8000,
|
||||
|
||||
BUTTON_R_GREEN = 0x2000,
|
||||
BUTTON_R_RED = 0x02,
|
||||
BUTTON_R_BLUE = 0x0400,
|
||||
|
||||
BUTTON_MINUS = 0x10,
|
||||
BUTTON_PLUS = 0x04,
|
||||
};
|
||||
|
||||
private:
|
||||
Buttons* m_buttons;
|
||||
MixedTriggers* m_triggers;
|
||||
AnalogStick* m_stick;
|
||||
Triggers *m_effect_dial;
|
||||
Slider *m_left_table, *m_right_table, *m_crossfade;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,543 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
/* HID reports access guide. */
|
||||
|
||||
/* 0x10 - 0x1a Output EmuMain.cpp: HidOutputReport()
|
||||
0x10 - 0x14: General
|
||||
0x15: Status report request from the Wii
|
||||
0x16 and 0x17: Write and read memory or registers
|
||||
0x19 and 0x1a: General
|
||||
0x20 - 0x22 Input EmuMain.cpp: HidOutputReport() to the destination
|
||||
0x15 leads to a 0x20 Input report
|
||||
0x17 leads to a 0x21 Input report
|
||||
0x10 - 0x1a leads to a 0x22 Input report
|
||||
0x30 - 0x3f Input This file: Update() */
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "FileUtil.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include "WiimoteEmu.h"
|
||||
#include "WiimoteHid.h"
|
||||
#include "../WiimoteReal/WiimoteReal.h"
|
||||
|
||||
#include "Attachment/Attachment.h"
|
||||
|
||||
/* Bit shift conversions */
|
||||
u32 swap24(const u8* src)
|
||||
{
|
||||
return (src[0] << 16) | (src[1] << 8) | src[2];
|
||||
}
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
void Wiimote::ReportMode(const wm_report_mode* const dr)
|
||||
{
|
||||
//INFO_LOG(WIIMOTE, "Set data report mode");
|
||||
//DEBUG_LOG(WIIMOTE, " Rumble: %x", dr->rumble);
|
||||
//DEBUG_LOG(WIIMOTE, " Continuous: %x", dr->continuous);
|
||||
//DEBUG_LOG(WIIMOTE, " All The Time: %x", dr->all_the_time);
|
||||
//DEBUG_LOG(WIIMOTE, " Mode: 0x%02x", dr->mode);
|
||||
|
||||
//m_reporting_auto = dr->all_the_time;
|
||||
m_reporting_auto = dr->continuous; // this right?
|
||||
m_reporting_mode = dr->mode;
|
||||
//m_reporting_channel = _channelID; // this is set in every Interrupt/Control Channel now
|
||||
|
||||
// reset IR camera
|
||||
//memset(m_reg_ir, 0, sizeof(*m_reg_ir)); //ugly hack
|
||||
|
||||
if (dr->mode > 0x37)
|
||||
PanicAlert("Wiimote: Unsupported Reporting mode.");
|
||||
else if (dr->mode < WM_REPORT_CORE)
|
||||
PanicAlert("Wiimote: Reporting mode < 0x30.");
|
||||
}
|
||||
|
||||
/* Here we process the Output Reports that the Wii sends. Our response will be
|
||||
an Input Report back to the Wii. Input and Output is from the Wii's
|
||||
perspective, Output means data to the Wiimote (from the Wii), Input means
|
||||
data from the Wiimote.
|
||||
|
||||
The call browser:
|
||||
|
||||
1. Wiimote_InterruptChannel > InterruptChannel > HidOutputReport
|
||||
2. Wiimote_ControlChannel > ControlChannel > HidOutputReport
|
||||
|
||||
The IR enable/disable and speaker enable/disable and mute/unmute values are
|
||||
bit2: 0 = Disable (0x02), 1 = Enable (0x06)
|
||||
*/
|
||||
void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack)
|
||||
{
|
||||
INFO_LOG(WIIMOTE, "HidOutputReport (page: %i, cid: 0x%02x, wm: 0x%02x)", m_index, m_reporting_channel, sr->wm);
|
||||
|
||||
// wiibrew:
|
||||
// In every single Output Report, bit 0 (0x01) of the first byte controls the Rumble feature.
|
||||
m_rumble_on = sr->rumble;
|
||||
|
||||
switch (sr->wm)
|
||||
{
|
||||
case WM_RUMBLE : // 0x10
|
||||
// this is handled above
|
||||
return; // no ack
|
||||
break;
|
||||
|
||||
case WM_LEDS : // 0x11
|
||||
//INFO_LOG(WIIMOTE, "Set LEDs: 0x%02x", sr->data[0]);
|
||||
m_status.leds = sr->data[0] >> 4;
|
||||
break;
|
||||
|
||||
case WM_REPORT_MODE : // 0x12
|
||||
ReportMode((wm_report_mode*)sr->data);
|
||||
break;
|
||||
|
||||
case WM_IR_PIXEL_CLOCK : // 0x13
|
||||
//INFO_LOG(WIIMOTE, "WM IR Clock: 0x%02x", sr->data[0]);
|
||||
//m_ir_clock = sr->enable;
|
||||
if (false == sr->ack)
|
||||
return;
|
||||
break;
|
||||
|
||||
case WM_SPEAKER_ENABLE : // 0x14
|
||||
//INFO_LOG(WIIMOTE, "WM Speaker Enable: 0x%02x", sr->data[0]);
|
||||
//PanicAlert( "WM Speaker Enable: %d", sr->data[0] );
|
||||
m_status.speaker = sr->enable;
|
||||
if (false == sr->ack)
|
||||
return;
|
||||
break;
|
||||
|
||||
case WM_REQUEST_STATUS : // 0x15
|
||||
RequestStatus((wm_request_status*)sr->data);
|
||||
return; // sends its own ack
|
||||
break;
|
||||
|
||||
case WM_WRITE_DATA : // 0x16
|
||||
WriteData((wm_write_data*)sr->data);
|
||||
break;
|
||||
|
||||
case WM_READ_DATA : // 0x17
|
||||
ReadData((wm_read_data*)sr->data);
|
||||
return; // sends its own ack
|
||||
break;
|
||||
|
||||
case WM_WRITE_SPEAKER_DATA : // 0x18
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
SpeakerData((wm_speaker_data*)sr->data);
|
||||
#endif
|
||||
// TODO: Does this need an ack?
|
||||
return; // no ack
|
||||
break;
|
||||
|
||||
case WM_SPEAKER_MUTE : // 0x19
|
||||
//INFO_LOG(WIIMOTE, "WM Speaker Mute: 0x%02x", sr->data[0]);
|
||||
//PanicAlert( "WM Speaker Mute: %d", sr->data[0] & 0x04 );
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
// testing
|
||||
if (sr->data[0] & 0x04)
|
||||
memset(&m_channel_status, 0, sizeof(m_channel_status));
|
||||
#endif
|
||||
m_speaker_mute = sr->enable;
|
||||
if (false == sr->ack)
|
||||
return;
|
||||
break;
|
||||
|
||||
case WM_IR_LOGIC: // 0x1a
|
||||
// comment from old plugin:
|
||||
// This enables or disables the IR lights, we update the global variable g_IR
|
||||
// so that WmRequestStatus() knows about it
|
||||
//INFO_LOG(WIIMOTE, "WM IR Enable: 0x%02x", sr->data[0]);
|
||||
m_status.ir = sr->enable;
|
||||
if (false == sr->ack)
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->wm);
|
||||
return; // no ack
|
||||
break;
|
||||
}
|
||||
|
||||
// send ack
|
||||
if (send_ack)
|
||||
SendAck(sr->wm);
|
||||
}
|
||||
|
||||
/* This will generate the 0x22 acknowledgement for most Input reports.
|
||||
It has the form of "a1 22 00 00 _reportID 00".
|
||||
The first two bytes are the core buttons data,
|
||||
00 00 means nothing is pressed.
|
||||
The last byte is the success code 00. */
|
||||
void Wiimote::SendAck(u8 _reportID)
|
||||
{
|
||||
u8 data[6];
|
||||
|
||||
data[0] = 0xA1;
|
||||
data[1] = WM_ACK_DATA;
|
||||
|
||||
wm_acknowledge* const ack = (wm_acknowledge*)(data + 2);
|
||||
|
||||
ack->buttons = m_status.buttons;
|
||||
ack->reportID = _reportID;
|
||||
ack->errorID = 0;
|
||||
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel( m_index, m_reporting_channel, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Wiimote::HandleExtensionSwap()
|
||||
{
|
||||
// handle switch extension
|
||||
if (m_extension->active_extension != m_extension->switch_extension)
|
||||
{
|
||||
// if an extension is currently connected and we want to switch to a different extension
|
||||
if ((m_extension->active_extension > 0) && m_extension->switch_extension)
|
||||
// detach extension first, wait til next Update() or RequestStatus() call to change to the new extension
|
||||
m_extension->active_extension = 0;
|
||||
else
|
||||
// set the wanted extension
|
||||
m_extension->active_extension = m_extension->switch_extension;
|
||||
|
||||
// update status struct
|
||||
m_status.extension = m_extension->active_extension ? 1 : 0;
|
||||
|
||||
// set register, I hate this line
|
||||
m_register[0xa40000] = ((WiimoteEmu::Attachment*)m_extension->attachments[m_extension->active_extension])->reg;
|
||||
}
|
||||
}
|
||||
|
||||
// old comment
|
||||
/* Here we produce a 0x20 status report to send to the Wii. We currently ignore
|
||||
the status request rs and all its eventual instructions it may include (for
|
||||
example turn off rumble or something else) and just send the status
|
||||
report. */
|
||||
void Wiimote::RequestStatus(const wm_request_status* const rs)
|
||||
{
|
||||
HandleExtensionSwap();
|
||||
|
||||
// set up report
|
||||
u8 data[8];
|
||||
data[0] = 0xA1;
|
||||
data[1] = WM_STATUS_REPORT;
|
||||
|
||||
// status values
|
||||
*(wm_status_report*)(data + 2) = m_status;
|
||||
|
||||
// hybrid wiimote stuff
|
||||
if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index] && (m_extension->switch_extension <= 0))
|
||||
{
|
||||
using namespace WiimoteReal;
|
||||
|
||||
g_refresh_critsec.Enter();
|
||||
if (g_wiimotes[m_index])
|
||||
{
|
||||
wm_request_status rpt;
|
||||
rpt.rumble = 0;
|
||||
g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt));
|
||||
}
|
||||
g_refresh_critsec.Leave();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// send report
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_reporting_channel, data, sizeof(data));
|
||||
}
|
||||
|
||||
/* Write data to Wiimote and Extensions registers. */
|
||||
void Wiimote::WriteData(const wm_write_data* const wd)
|
||||
{
|
||||
u32 address = swap24(wd->address);
|
||||
|
||||
// ignore the 0x010000 bit
|
||||
address &= 0xFEFFFF;
|
||||
|
||||
if (wd->size > 16)
|
||||
{
|
||||
PanicAlert("WriteData: size is > 16 bytes");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (wd->space)
|
||||
{
|
||||
case WM_SPACE_EEPROM :
|
||||
{
|
||||
// Write to EEPROM
|
||||
|
||||
if (address + wd->size > WIIMOTE_EEPROM_SIZE)
|
||||
{
|
||||
ERROR_LOG(WIIMOTE, "WriteData: address + size out of bounds!");
|
||||
PanicAlert("WriteData: address + size out of bounds!");
|
||||
return;
|
||||
}
|
||||
memcpy(m_eeprom + address, wd->data, wd->size);
|
||||
|
||||
// write mii data to file
|
||||
// i need to improve this greatly
|
||||
if (address >= 0x0FCA && address < 0x12C0)
|
||||
{
|
||||
// writing the whole mii block each write :/
|
||||
std::ofstream file;
|
||||
file.open( (std::string(File::GetUserPath(D_WIIUSER_IDX)) + "mii.bin").c_str(), std::ios::binary | std::ios::out);
|
||||
file.write((char*)m_eeprom + 0x0FCA, 0x02f0);
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_SPACE_REGS1 :
|
||||
case WM_SPACE_REGS2 :
|
||||
{
|
||||
// Write to Control Register
|
||||
|
||||
// ignore second byte for extension area
|
||||
if (0xA4 == (address >> 16))
|
||||
address &= 0xFF00FF;
|
||||
|
||||
// write to the register
|
||||
m_register.Write(address, wd->data, wd->size);
|
||||
|
||||
switch (address >> 16)
|
||||
{
|
||||
// speaker
|
||||
case 0xa2 :
|
||||
//PanicAlert("Write to speaker!!");
|
||||
break;
|
||||
// extension register
|
||||
case 0xa4 :
|
||||
{
|
||||
// Run the key generation on all writes in the key area, it doesn't matter
|
||||
// that we send it parts of a key, only the last full key will have an effect
|
||||
// I might have f'ed this up
|
||||
if ( address >= 0xa40040 && address <= 0xa4004c )
|
||||
wiimote_gen_key(&m_ext_key, m_reg_ext->encryption_key);
|
||||
//else if ( address >= 0xa40020 && address < 0xa40040 )
|
||||
// PanicAlert("Writing to extension calibration data! Extension may misbehave");
|
||||
}
|
||||
break;
|
||||
// ir
|
||||
case 0xB0 :
|
||||
if (5 == m_reg_ir->mode)
|
||||
PanicAlert("IR Full Mode is Unsupported!");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PanicAlert("WriteData: unimplemented parameters!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read data from Wiimote and Extensions registers. */
|
||||
void Wiimote::ReadData(const wm_read_data* const rd)
|
||||
{
|
||||
u32 address = swap24(rd->address);
|
||||
u16 size = Common::swap16(rd->size);
|
||||
|
||||
// ignore the 0x010000 bit
|
||||
address &= 0xFEFFFF;
|
||||
|
||||
// hybrid wiimote stuff
|
||||
// relay the read data request to real-wiimote
|
||||
if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index] && ((0xA4 != (address >> 16)) || (m_extension->switch_extension <= 0)))
|
||||
{
|
||||
WiimoteReal::InterruptChannel(m_index, m_reporting_channel, ((u8*)rd) - 2, sizeof(wm_read_data) + 2); // hacky
|
||||
|
||||
// don't want emu-wiimote to send reply
|
||||
return;
|
||||
}
|
||||
|
||||
ReadRequest rr;
|
||||
u8* block = new u8[size];
|
||||
|
||||
switch (rd->space)
|
||||
{
|
||||
case WM_SPACE_EEPROM :
|
||||
{
|
||||
//PanicAlert("ReadData: reading from EEPROM: address: 0x%x size: 0x%x", address, size);
|
||||
// Read from EEPROM
|
||||
if (address + size >= WIIMOTE_EEPROM_FREE_SIZE)
|
||||
{
|
||||
if (address + size > WIIMOTE_EEPROM_SIZE)
|
||||
{
|
||||
PanicAlert("ReadData: address + size out of bounds");
|
||||
return;
|
||||
}
|
||||
// generate a read error
|
||||
size = 0;
|
||||
}
|
||||
|
||||
// read mii data from file
|
||||
// i need to improve this greatly
|
||||
if (address >= 0x0FCA && address < 0x12C0)
|
||||
{
|
||||
// reading the whole mii block :/
|
||||
std::ifstream file;
|
||||
file.open( (std::string(File::GetUserPath(D_WIIUSER_IDX)) + "mii.bin").c_str(), std::ios::binary | std::ios::in);
|
||||
file.read((char*)m_eeprom + 0x0FCA, 0x02f0);
|
||||
file.close();
|
||||
}
|
||||
|
||||
// read mem to be sent to wii
|
||||
memcpy( block, m_eeprom + address, size);
|
||||
}
|
||||
break;
|
||||
case WM_SPACE_REGS1 :
|
||||
case WM_SPACE_REGS2 :
|
||||
{
|
||||
// Read from Control Register
|
||||
|
||||
// ignore second byte for extension area
|
||||
if (0xA4 == (address >> 16))
|
||||
address &= 0xFF00FF;
|
||||
|
||||
// read block to send to wii
|
||||
m_register.Read( address, block, size );
|
||||
|
||||
switch (address >> 16)
|
||||
{
|
||||
// speaker
|
||||
case 0xa2 :
|
||||
//PanicAlert("read from speaker!!");
|
||||
break;
|
||||
// extension
|
||||
case 0xa4 :
|
||||
{
|
||||
// Encrypt data read from extension register
|
||||
// Check if encrypted reads is on
|
||||
if (0xaa == m_reg_ext->encryption)
|
||||
wiimote_encrypt(&m_ext_key, block, address & 0xffff, (u8)size);
|
||||
|
||||
//if ( address >= 0xa40008 && address < 0xa40020 )
|
||||
// PanicAlert("Reading extension data from register");
|
||||
}
|
||||
break;
|
||||
// motion plus
|
||||
case 0xa6 :
|
||||
{
|
||||
// emulated motion plus is not yet supported
|
||||
// return read error
|
||||
size = 0;
|
||||
|
||||
// motion plus crap copied from old wiimote plugin
|
||||
//block[0xFC] = 0xA6;
|
||||
//block[0xFD] = 0x20;
|
||||
//block[0xFE] = 0x00;
|
||||
//block[0xFF] = 0x05;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default :
|
||||
PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x)!", size, rd->space);
|
||||
break;
|
||||
}
|
||||
|
||||
// want the requested address, not the above modified one
|
||||
rr.address = swap24(rd->address);
|
||||
rr.size = size;
|
||||
//rr.channel = _channelID;
|
||||
rr.position = 0;
|
||||
rr.data = block;
|
||||
|
||||
// send up to 16 bytes
|
||||
SendReadDataReply(rr);
|
||||
|
||||
// if there is more data to be sent, add it to the queue
|
||||
if (rr.size)
|
||||
m_read_requests.push( rr );
|
||||
else
|
||||
delete[] rr.data;
|
||||
}
|
||||
|
||||
// old comment
|
||||
/* Here we produce the actual 0x21 Input report that we send to the Wii. The
|
||||
message is divided into 16 bytes pieces and sent piece by piece. There will
|
||||
be five formatting bytes at the begging of all reports. A common format is
|
||||
00 00 f0 00 20, the 00 00 means that no buttons are pressed, the f means 16
|
||||
bytes in the message, the 0 means no error, the 00 20 means that the message
|
||||
is at the 00 20 offest in the registry that was read.
|
||||
*/
|
||||
void Wiimote::SendReadDataReply(ReadRequest& _request)
|
||||
{
|
||||
u8 data[23];
|
||||
data[0] = 0xA1;
|
||||
data[1] = WM_READ_DATA_REPLY;
|
||||
|
||||
wm_read_data_reply* const reply = (wm_read_data_reply*)(data + 2);
|
||||
reply->buttons = m_status.buttons;
|
||||
reply->address = Common::swap16(_request.address);
|
||||
|
||||
// generate a read error
|
||||
// Out of bounds. The real Wiimote generate an error for the first
|
||||
// request to 0x1770 if we dont't replicate that the game will never
|
||||
// read the calibration data at the beginning of Eeprom. I think this
|
||||
// error is supposed to occur when we try to read above the freely
|
||||
// usable space that ends at 0x16ff.
|
||||
if (0 == _request.size)
|
||||
{
|
||||
reply->size = 0x0f;
|
||||
reply->error = 0x08;
|
||||
|
||||
memset(reply->data, 0, sizeof(reply->data));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Limit the amt to 16 bytes
|
||||
// AyuanX: the MTU is 640B though... what a waste!
|
||||
const int amt = std::min( (unsigned int)16, _request.size );
|
||||
|
||||
// no error
|
||||
reply->error = 0;
|
||||
|
||||
// 0x1 means two bytes, 0xf means 16 bytes
|
||||
reply->size = amt - 1;
|
||||
|
||||
// Clear the mem first
|
||||
memset(reply->data, 0, sizeof(reply->data));
|
||||
|
||||
// copy piece of mem
|
||||
memcpy(reply->data, _request.data + _request.position, amt);
|
||||
|
||||
// update request struct
|
||||
_request.size -= amt;
|
||||
_request.position += amt;
|
||||
_request.address += amt;
|
||||
}
|
||||
|
||||
// Send a piece
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_reporting_channel, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Wiimote::DoState(PointerWrap& p)
|
||||
{
|
||||
// not working :(
|
||||
//if (p.MODE_READ == p.GetMode())
|
||||
//{
|
||||
// // LOAD
|
||||
// Reset(); // should cause a status report to be sent, then wii should re-setup wiimote
|
||||
//}
|
||||
//p.Do(m_reporting_channel);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
// Copyright (C) Hector Martin "marcan" ([email protected])
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
#include "Encryption.h"
|
||||
|
||||
|
||||
static const u8 ans_tbl[7][6] = {
|
||||
{0xA8,0x77,0xA6,0xE0,0xF7,0x43},
|
||||
{0x5A,0x35,0x85,0xE2,0x72,0x97},
|
||||
{0x8F,0xB7,0x1A,0x62,0x87,0x38},
|
||||
{ 0xD,0x67,0xC7,0xBE,0x4F,0x3E},
|
||||
{0x20,0x76,0x37,0x8F,0x68,0xB7},
|
||||
{0xA9,0x26,0x3F,0x2B,0x10,0xE3},
|
||||
{0x30,0x7E,0x90, 0xE,0x85, 0xA},
|
||||
};
|
||||
|
||||
static const u8 tsbox[256] = {
|
||||
0x70,0x51, 3,0x86,0x40, 0xD,0x4F,0xEB,0x3E,0xCC,0xD1,0x87,0x35,0xBD,0xF5, 0xB,
|
||||
0x5E,0xD0,0xF8,0xF2,0xD5,0xE2,0x6C,0x31, 0xC,0xAD,0xFC,0x21,0xC3,0x78,0xC1, 6,
|
||||
0xC2,0x4C,0x55,0xE6,0x4A,0x34,0x48,0x11,0x1E,0xDA,0xE7,0x1A,0x84,0xA0,0x96,0xA7,
|
||||
0xE3,0x7F,0xAF,0x63,0x9C,0xFA,0x23,0x5B,0x79,0xC8,0x9E,0xBA,0xB2,0xC9,0x22,0x12,
|
||||
0x4B,0xB3,0xA1,0xB6,0x32,0x49,0xA2,0xE1,0x89,0x39,0x10,0x66,0xC5, 7,0x8F,0x54,
|
||||
0xEA,0x91,0xCA,0x3F,0xF9,0x19,0xF0,0xD7,0x46,0xBC,0x28,0x1B,0x61,0xE8,0x2F,0x6A,
|
||||
0xAE,0x9D,0xF6,0x4E, 9,0x14,0x77,0x4D,0xDB,0x1F,0x2E,0x7B,0x7C,0xF1,0x43,0xA3,
|
||||
0,0xB8,0x13,0x8C,0x85,0xB9,0x29,0x75,0x88,0xFD,0xD2,0x56,0x1C,0x50,0x97,0x41,
|
||||
0xE5,0x3B,0x60,0xB5,0xC0,0x64,0xEE,0x98,0xD6,0x2D,0x25,0xA4,0xAA,0xCD,0x7D,0xA8,
|
||||
0x83,0xC6,0xAB,0xBE,0x44,0x99,0x26,0x3C,0xCE,0x9F,0xBF,0xD3,0xCB,0x76,0x7A,0x7E,
|
||||
0x82, 1,0x8A,0x9A,0x80,0x1D, 0xE,0xB0,0x5C,0xD4,0x38,0x62,0xF4,0x30,0xE0,0x8E,
|
||||
0x53,0xB7, 2,0x57,0xAC,0xA6,0x52, 0xA,0x6D,0x92,0x65,0x17,0x24,0x33,0x45,0x72,
|
||||
0x74,0xB1,0xB4,0xF7,0x5D,0xED,0x2C,0xFF,0x47,0x37,0x5A,0x90,0xBB,0xDF,0x2A,0x16,
|
||||
0x59,0x95,0xD9,0xC4,0x27,0x67,0x73,0xC7,0x68,0xFE,0xA5,0xDD,0x6B,0x5F,0x93,0xD8,
|
||||
0xEC, 5,0x3A,0x8D,0x6E,0xFB,0x3D,0xA9,0x69,0x36,0xF3,0x94,0xDE,0xEF,0x15,0x6F,
|
||||
0x8B,0x9B, 8, 0xF,0xDC,0x81,0x18,0x20, 4,0xE4,0x71,0xCF,0xE9,0x2B,0x42,0x58,
|
||||
};
|
||||
|
||||
static const u8 sboxes[8][256] = {
|
||||
{
|
||||
1,0xA0,0xA9,0x62,0xD6,0x3F,0x85,0xA7,0xB6,0xD4,0xFA,0x15,0x66,0x17, 9,0xBD,
|
||||
0x5D,0x14,0x34,0x26,0x59,0x72,0x91,0x54, 6,0x4F,0xF8,0xB0,0x5B,0x74,0x93,0x99,
|
||||
0x8C,0xF2,0x45,0xCD,0xEA,0x4E,0xAD,0x10,0x4A,0xE5,0xCA,0xEE,0xDF,0xC6,0x6F,0x9F,
|
||||
0x88,0x8E, 2,0xCC, 8,0xA8,0x77,0x94,0x6D,0x21,0xB1,0x28,0xE4,0x39,0x79,0x96,
|
||||
0x60,0x71,0x81,0x16,0x2E,0xE6,0x78,0xB9,0xC4,0x46,0x9A,0x42,0xAE,0xB7,0x7C,0x43,
|
||||
0xB3,0x22,0x1A,0x86,0xC2,0x32,0x3D,0x2D,0x9C,0xD2,0x29,0xE9,0x63,0x9B,0xD1,0x31,
|
||||
0x38,0x5E,0x1E,0x36,0x41,0xBB, 3,0x18,0x2B,0x3E,0xBF,0x68,0x61,0xFC,0x52,0xC0,
|
||||
0xDE,0xE0, 0xA,0x58,0x13,0x5A, 0,0xBE,0x1C,0x90, 0xE,0x53,0x12,0xFD,0xE2,0x6E,
|
||||
0xBA,0xCE,0x24,0x27,0x44,0x7F,0x87,0xA3,0xA1,0xD5,0x50,0x40,0xE3,0xF9,0x83,0xF7,
|
||||
0xC7,0xA2,0x35,0xC8,0xDB,0x19,0xAB,0x2F,0x11,0x25,0xED,0x33,0x9E,0x55,0xE1,0x48,
|
||||
0xAF,0x73,0x84,0xDA,0x2A,0xAA,0x51,0xEB,0x9D,0x95,0xB2,0xCB,0xE7,0x70,0x80,0xFE,
|
||||
0x4C,0x65, 4,0xEF,0xC5,0xF1,0xC3,0x3A,0xB4,0xF5,0x5F,0x23,0x89,0xDD,0x30,0xA5,
|
||||
0x8B,0xD3,0xF6,0xDC,0x4D,0x64,0xD7,0xF0,0x8F,0xEC,0x56,0x37,0x5C,0xA4, 0xD, 7,
|
||||
0x76,0x8A,0x2C, 0xB,0xB5,0xD8,0xC1,0x1F,0xE8,0x3B,0xF4,0x4B,0x1B,0x47,0x6C,0x49,
|
||||
0x67,0x7B,0x92,0xCF,0x75,0x7E,0x20,0xD9,0x7D,0x3C,0x97,0x7A,0xD0, 5,0x6B, 0xF,
|
||||
0x1D,0xFB,0x82,0x98,0x57,0x8D,0xF3,0x6A,0xBC,0xAC,0xC9,0xA6,0xFF,0xB8,0x69, 0xC,
|
||||
},
|
||||
{
|
||||
0x4C,0x4D,0x72, 7,0x5A,0x49,0x33,0x8D,0xA2,0xAB,0x46,0x3D,0x63, 0xD,0xA0,0x97,
|
||||
0xFF,0xF0,0xF5,0xFA,0xC0,0xE9,0xDB,0x62,0xE4,0xE1,0x74,0x43,0xDC,0x86,0x18,0x29,
|
||||
0x37,0xF4, 6,0xE2,0xED,0x6F,0x90,0x48,0x1E,0x2D,0x1D,0xEA,0x73,0x94,0x54,0xDF,
|
||||
0x25,0xF6,0x47,0x27,0xD9,0x11,0x77,0xC9,0x84,0x1C,0x5B,0x5C,0x51,0x81,0xA6,0x22,
|
||||
0x3E,0x24,0x96,0xC8,0x8A,0xEC,0x82,0x7C, 9,0xB8,0x45,0x4A,0x57,0xBB,0x2F,0x50,
|
||||
0x75,0x8E,0x61,0x70,0x8C,0x6C,0xAF,0xD0,0xFD,0xB4,0x1B,0xAE,0xDE,0xFE,0x3B,0xB5,
|
||||
0x36,0xBD,0x55, 1, 0xE,0x9C,0x41,0x56,0x5F,0xB3,0x26, 3,0x83,0xBA,0x13,0x4B,
|
||||
0xCA,0xC5, 0xA,0xF8,0x60,0xA5,0xB9,0xC7,0xC3,0x98,0x32,0xFB,0x12,0xF9,0xA7,0x92,
|
||||
0xAA,0x68,0xF3,0x78,0x7E, 5,0x20,0x21, 2,0xE8,0xBF,0xF2,0xB0,0x59,0x8F,0xD2,
|
||||
0xCB,0x87,0x65,0x15,0xF1,0x1A,0xB2,0x30,0xAD,0xEE,0x58,0xA3,0x8B,0x66,0x1F,0x2C,
|
||||
0xD7,0x5D,0x19,0x85,0xA8,0xE6,0xD3,0x6B,0xA1, 0xC,0x91,0x93,0x6A,0x5E, 0xB,0x79,
|
||||
0xE3,0xDD, 0,0x4F,0x3C,0x89,0x6E,0x71,0x69,0xA9,0xAC,0x40,0xE5,0x99,0x28,0xC6,
|
||||
0x31,0x4E,0x7A,0xCD, 8,0x9E,0x7D,0xEF,0x17,0xFC,0x88,0xD8,0xA4,0x6D,0x44,0x95,
|
||||
0xD1,0xB7,0xD4,0x9B,0xBE,0x2A,0x34,0x64,0x2B,0xCF,0x2E,0xEB,0x38,0xCE,0x23,0xE0,
|
||||
0x3A,0x3F,0xF7,0x7B,0x9F,0x10,0x53,0xBC,0x52,0x67,0x16,0xE7,0x80,0x76, 4,0xC4,
|
||||
0xB6,0xC1,0xC2,0x7F,0x9A,0xDA,0xD5,0x39,0x42,0x14,0x9D,0xB1, 0xF,0x35,0xD6,0xCC,
|
||||
},
|
||||
{
|
||||
0xB9,0xDA,0x38, 0xC,0xA2,0x9C, 9,0x1F, 6,0xB1,0xB6,0xFD,0x1A,0x69,0x23,0x30,
|
||||
0xC4,0xDE, 1,0xD1,0xF4,0x58,0x29,0x37,0x1C,0x7D,0xD5,0xBF,0xFF,0xBD,0xC8,0xC9,
|
||||
0xCF,0x65,0xBE,0x7B,0x78,0x97,0x98,0x67, 8,0xB3,0x26,0x57,0xF7,0xFA,0x40,0xAD,
|
||||
0x8E,0x75,0xA6,0x7C,0xDB,0x91,0x8B,0x51,0x99,0xD4,0x17,0x7A,0x90,0x8D,0xCE,0x63,
|
||||
0xCB,0x4E,0xA0,0xAB,0x18,0x3A,0x5B,0x50,0x7F,0x21,0x74,0xC1,0xBB,0xB8,0xB7,0xBA,
|
||||
0xB,0x35,0x95,0x31,0x59,0x9A,0x4D, 4, 7,0x1E,0x5A,0x76,0x13,0xF3,0x71,0x83,
|
||||
0xD0,0x86, 3,0xA8,0x39,0x42,0xAA,0x28,0xE6,0xE4,0xD8,0x5D,0xD3,0xD0,0x6E,0x6F,
|
||||
0x96,0xFB,0x5E,0xBC,0x56,0xC2,0x5F,0x85,0x9B,0xE7,0xAF,0xD2,0x3B,0x84,0x6A,0xA7,
|
||||
0x53,0xC5,0x44,0x49,0xA5,0xF9,0x36,0x72,0x3D,0x2C,0xD9,0x1B,0xA1,0xF5,0x4F,0x93,
|
||||
0x9D,0x68,0x47,0x41,0x16,0xCA,0x2A,0x4C,0xA3,0x87,0xD6,0xE5,0x19,0x2E,0x77,0x15,
|
||||
0x6D,0x70,0xC0,0xDF,0xB2, 0,0x46,0xED,0xC6,0x6C,0x43,0x60,0x92,0x2D,0xA9,0x22,
|
||||
0x45,0x8F,0x34,0x55,0xAE,0xA4, 0xA,0x66,0x32,0xE0,0xDC, 2,0xAC,0xE8,0x20,0x8C,
|
||||
0x89,0x62,0x4A,0xFE,0xEE,0xC3,0xE3,0x3C,0xF1,0x79, 5,0xE9,0xF6,0x27,0x33,0xCC,
|
||||
0xF2,0x9E,0x11,0x81,0x7E,0x80,0x10,0x8A,0x82,0x9F,0x48, 0xD,0xD7,0xB4,0xFC,0x2F,
|
||||
0xB5,0xC7,0xDD,0x88,0x14,0x6B,0x2B,0x54,0xEA,0x1D,0x94,0x5C,0xB0,0xEF,0x12,0x24,
|
||||
0xCD,0xEB,0xE1,0xE2,0x64,0x73,0x3F, 0xE,0x52,0x61,0x25,0x3E,0xF8, 0xF,0x4B,0xEC,
|
||||
},
|
||||
{
|
||||
0xC0, 0,0x30,0xF6, 2,0x49,0x3D,0x10,0x6E,0x20,0xC9,0xA6,0x2F,0xFE,0x2C,0x2B,
|
||||
0x75,0x2E,0x45,0x26,0xAB,0x48,0xA9,0x80,0xFC, 4,0xCC,0xD3,0xB5,0xBA,0xA3,0x38,
|
||||
0x31,0x7D, 1,0xD9,0xA7,0x7B,0x96,0xB6,0x63,0x69,0x4E,0xF7,0xDE,0xE0,0x78,0xCA,
|
||||
0x50,0xAA,0x41,0x91,0x65,0x88,0xE4,0x21,0x85,0xDA,0x3A,0x27,0xBE,0x1C,0x3E,0x42,
|
||||
0x5E,0x17,0x52,0x7F,0x1F,0x89,0x24,0x6F,0x8F,0x5C,0x67,0x74, 0xE,0x12,0x87,0x8D,
|
||||
0xE9,0x34,0xED,0x73,0xC4,0xF8,0x61,0x5B, 5,0xDF,0x59,0x4C,0x97,0x79,0x83,0x18,
|
||||
0xA4,0x55,0x95,0xEB,0xBD,0x53,0xF5,0xF1,0x57,0x66,0x46,0x9F,0xB2,0x81, 9,0x51,
|
||||
0x86,0x22,0x16,0xDD,0x23,0x93,0x76,0x29,0xC2,0xD7,0x1D,0xD4,0xBF,0x36,0x3F,0xEA,
|
||||
0x4B,0x11,0x32,0xB9,0x62,0x54,0x60,0xD6,0x6D,0x43,0x9A, 0xD,0x92,0x9C,0xB0,0xEF,
|
||||
0x58,0x6C,0x9D,0x77,0x2D,0x70,0xFA,0xF3,0xB3, 0xB,0xE2,0x40,0x7E,0xF4,0x8A,0xE5,
|
||||
0x8C,0x3C,0x56,0x71,0xD1,0x64,0xE1,0x82, 0xA,0xCB,0x13,0x15,0x90,0xEC, 3,0x99,
|
||||
0xAF,0x14,0x5D, 0xF,0x33,0x4A,0x94,0xA5,0xA8,0x35,0x1B,0xE3,0x6A,0xC6,0x28,0xFF,
|
||||
0x4D,0xE7,0x25,0x84,0xAC, 8,0xAE,0xC5,0xA2,0x2A,0xB8,0x37, 0xC,0x7A,0xA0,0xC3,
|
||||
0xCE,0xAD, 6,0x1A,0x9E,0x8B,0xFB,0xD5,0xD0,0xC1,0x1E,0xD0,0xB4,0x9B,0xB1,0x44,
|
||||
0xF2,0x47,0xC7,0x68,0xCF,0x72,0xBB,0x4F,0x5A,0xF9,0xDC,0x6B,0xDB,0xD2,0xE8,0x7C,
|
||||
0xC8,0xEE,0x98,0xA1,0xE6,0xD8,0x39, 7,0x5F,0xFD,0x8E,0x19,0xB7,0x3B,0xBC,0xCD,
|
||||
},
|
||||
{
|
||||
0x7C,0xE3,0x81,0x73,0xB2,0x11,0xBF,0x6F,0x20,0x98,0xFE,0x75,0x96,0xEF,0x6C,0xDA,
|
||||
0x50,0xE1, 9,0x72,0x54,0x45,0xBA,0x34,0x80,0x5B,0xED,0x3E,0x53,0x2C,0x87,0xA4,
|
||||
0x57,0xF3,0x33,0x3F,0x3C,0xB7,0x67,0xB4,0xA3,0x25,0x60,0x4F, 7,0x6B,0x1B,0x47,
|
||||
0x15, 0xF,0xE4, 0xA,0xEA,0xD1,0x32,0x78,0x36,0x49,0x8D,0x4B,0xD2,0xBC,0xA5,0xDC,
|
||||
0x1D, 0xD,0x4D,0xCD,0x9A,0x82,0x5F,0xFC,0x94,0x65,0xBE,0xE2,0xF4,0xC9,0x1E,0x44,
|
||||
0xCB,0x9E, 0xC,0x64,0x71,0x26,0x63,0xB3,0x14,0xE8,0x40,0x70,0x8A, 0xE,0x19,0x42,
|
||||
0x6D,0xAC,0x88,0x10,0x5C,0xDF,0x41,0xA9,0xAD,0xE5,0xFB,0x74,0xCC,0xD5, 6,0x8E,
|
||||
0x59,0x86,0xCE,0x1F,0x3D,0x76,0xE0,0x8F,0xB9,0x77,0x27,0x7B,0xA6,0xD8,0x29,0xD3,
|
||||
0xEC,0xB8,0x13,0xF7,0xFA,0xC3,0x51,0x6A,0xDE,0x4A,0x5A,0xEB,0xC2,0x8B,0x23,0x48,
|
||||
0x92,0xCF,0x62,0xA8,0x99,0xF8,0xD0,0x2E,0x85,0x61,0x43,0xC8,0xBD,0xF0, 5,0x93,
|
||||
0xCA,0x4E,0xF1,0x7D,0x30,0xFD,0xC4,0x69,0x66,0x2F, 8,0xB1,0x52,0xF9,0x21,0xE6,
|
||||
0x7A,0x2B,0xDD,0x39,0x84,0xFF,0xC0,0x91,0xD6,0x37,0xD4,0x7F,0x2D,0x9B,0x5D,0xA1,
|
||||
0x3B,0x6E,0xB5,0xC5,0x46, 4,0xF5,0x90,0xEE,0x7E,0x83,0x1C, 3,0x56,0xB6,0xAA,
|
||||
0,0x17, 1,0x35,0x55,0x79, 0xB,0x12,0xBB,0x1A,0x31,0xE7, 2,0x28,0x16,0xC1,
|
||||
0xF6,0xA2,0xDB,0x18,0x9C,0x89,0x68,0x38,0x97,0xAB,0xC7,0x2A,0xD7,0x3A,0xF2,0xC6,
|
||||
0x24,0x4C,0xB0,0x58,0xA0,0x22,0x5E,0x9D,0xD9,0xA7,0xE9,0xAE,0xAF,0x8C,0x95,0x9F,
|
||||
},
|
||||
{
|
||||
0x28,0xB7,0x20,0xD7,0xB0,0x30,0xC3, 9,0x19,0xC0,0x67,0xD6, 0,0x3C,0x7E,0xE7,
|
||||
0xE9,0xF4, 8,0x5A,0xF8,0xB8,0x2E, 5,0xA6,0x25,0x9E,0x5C,0xD8,0x15, 0xD,0xE1,
|
||||
0xF6,0x11,0x54,0x6B,0xCD,0x21,0x46,0x66,0x5E,0x84,0xAD, 6,0x38,0x29,0x44,0xC5,
|
||||
0xA2,0xCE,0xF1,0xAA,0xC1,0x40,0x71,0x86,0xB5,0xEF,0xFC,0x36,0xA8,0xCB, 0xA,0x48,
|
||||
0x27,0x45,0x64,0xA3,0xAF,0x8C,0xB2,0xC6,0x9F, 7,0x89,0xDC,0x17,0xD3,0x49,0x79,
|
||||
0xFB,0xFE,0x1D,0xD0,0xB9,0x88,0x43,0x52,0xBC, 1,0x78,0x2B,0x7D,0x94,0xC7, 0xE,
|
||||
0xDE,0xA5,0xD5,0x9B,0xCC,0xF7,0x61,0x7A,0xC2,0x74,0x81,0x39, 3,0xAB,0x96,0xA0,
|
||||
0x37,0xBD,0x2D,0x72,0x75,0x3F,0xC9,0xD4,0x8E,0x6F,0xF9,0x8D,0xED,0x62,0xDB,0x1C,
|
||||
0xDF, 4,0xAC,0x1B,0x6C,0x14,0x4B,0x63,0xD0,0xBF,0xB4,0x82,0xEC,0x7B,0x1A,0x59,
|
||||
0x92,0xD2,0x10,0x60,0xB6,0x3D,0x5F,0xE6,0x80,0x6E,0x70,0xC4,0xF2,0x35,0xD9,0x7C,
|
||||
0xEE,0xE5,0x41,0xA4,0x5B,0x50,0xDD,0xBB,0x4C,0xF3,0x1F,0x9D,0x5D,0x57,0x55,0x51,
|
||||
0x97,0xE3,0x58,0x42,0x4D,0x9C,0x73,0xBA,0xC8,0x77,0x31,0x69,0x26,0xAE,0xEA,0x8A,
|
||||
0xDA,0x22,0xB3,0x87,0x56,0xFA,0x93, 0xB,0x34,0x16,0x33,0xE8,0xE4,0x53,0xBE,0xA9,
|
||||
0xB1,0x3A,0x3E,0xF5,0x90,0x6A,0xCF,0x3B,0x12,0xFD,0x8F,0x9A,0xA7,0x47,0x91,0x99,
|
||||
0xEB, 0xF,0x24,0xFF,0x23,0x18,0x85,0x4E,0x7F, 0xC,0xE0,0xA1,0xD2,0xD1,0x2C,0x2A,
|
||||
0x4A, 2,0x4F,0x1E,0x95,0x68,0x8B,0x98,0x83,0x6D,0x76,0xCA,0x65,0x32,0x13,0x2F,
|
||||
},
|
||||
{
|
||||
0xC3,0x82,0x9A,0xA4,0xBA,0x81,0x60,0x37,0x34,0x35,0xFC,0x80,0xA8,0x51,0x65,0x67,
|
||||
0xED,0x30,0x5F,0x10,0xD3,0x4A,0x27,0x2F,0x13,0xB9,0x2A,0xD2,0xCC,0xE1,0xEF,0xAE,
|
||||
0xEB,0xBE,0xF4,0xBD,0xCF,0x43,0xB3,0xC5,0x88,0x84,0xB7,0xDD,0x39,0x40,0xCE,0x48,
|
||||
0x6D,0x9B,0x72,0x61,0x7E,0xE7,0xA1,0x4E,0x53,0x2E,0x77,0x3B,0xE2,0xC9,0x36,0x22,
|
||||
0x1B,0x6E,0x73,0xB1, 3,0xB2,0x4C,0x87,0xA9,0xD4,0x4D, 0xF,0xD8,0x15,0x6C,0xAA,
|
||||
0x18,0xF6,0x49,0x57,0x5D,0xFB,0x7A,0x14,0x94,0x63,0xA0,0x11,0xB0,0x9E,0xDE, 5,
|
||||
0x46,0xC8,0xEE,0x47,0xDB,0xDC,0x24,0x89,0x9C,0x91,0x97,0x29,0xE9,0x7B,0xC1, 7,
|
||||
0x1E,0xB8,0xFD,0xFE,0xAC,0xC6,0x62,0x98,0x4F,0xF1,0x79,0xE0,0xE8,0x6B,0x78,0x56,
|
||||
0xB6,0x8D, 4,0x50,0x86,0xCA,0x6F,0x20,0xE6,0xEA,0xE5,0x76,0x17,0x1C,0x74,0x7F,
|
||||
0xBC, 0xD,0x2C,0x85,0xF7,0x66,0x96,0xE4,0x8B,0x75,0x3F,0x4B,0xD9,0x38,0xAF,0x7C,
|
||||
0xDA, 0xB,0x83,0x2D,0x31,0x32,0xA2,0xF5,0x1D,0x59,0x41,0x45,0xBF,0x3C,0x1F,0xF8,
|
||||
0xF9,0x8A,0xD0,0x16,0x25,0x69,0x12,0x99,0x9D,0x21,0x95,0xAB, 1,0xA6,0xD7,0xB5,
|
||||
0xC0,0x7D,0xFF,0x58, 0xE,0x3A,0x92,0xD1,0x55,0xE3, 8,0x9F,0xD6,0x3E,0x52,0x8E,
|
||||
0xFA,0xA3,0xC7, 2,0xCD,0xDF,0x8F,0x64,0x19,0x8C,0xF3,0xA7, 0xC,0x5E, 0xA,0x6A,
|
||||
9,0xF0,0x93,0x5B,0x42,0xC2, 6,0x23,0xEC,0x71,0xAD,0xB4,0xCB,0xBB,0x70,0x28,
|
||||
0xD5,0x1A,0x5C,0x33,0x68,0x5A, 0,0x44,0x90,0xA5,0xC4,0x26,0x3D,0x2B,0xF2,0x54,
|
||||
},
|
||||
{
|
||||
0x96,0xAD,0xDA,0x1F,0xED,0x33,0xE1,0x81,0x69, 8, 0xD, 0xA,0xDB,0x35,0x77,0x9A,
|
||||
0x64,0xD1,0xFC,0x78,0xAA,0x1B,0xD0,0x67,0xA0,0xDD,0xFA,0x6C,0x63,0x71, 5,0x84,
|
||||
0x17,0x6A,0x89,0x4F,0x66,0x7F,0xC6,0x50,0x55,0x92,0x6F,0xBD,0xE7,0xD2,0x40,0x72,
|
||||
0x8D,0xBB,0xEC, 6,0x42,0x8A,0xE4,0x88,0x9D,0x7E,0x7A,0x82,0x27,0x13,0x41,0x1A,
|
||||
0xAF,0xC8,0xA4,0x76,0xB4,0xC2,0xFE,0x6D,0x1C,0xD9,0x61,0x30,0xB3,0x7C,0xEA,0xF7,
|
||||
0x29, 0xF,0xF2,0x3B,0x51,0xC1,0xDE,0x5F,0xE5,0x2A,0x2F,0x99, 0xB,0x5D,0xA3,0x2B,
|
||||
0x4A,0xAB,0x95,0xA5,0xD3,0x58,0x56,0xEE,0x28,0x31, 0,0xCC,0x15,0x46,0xCA,0xE6,
|
||||
0x86,0x38,0x3C,0x65,0xF5,0xE3,0x9F,0xD6,0x5B, 9,0x49,0x83,0x70,0x2D,0x53,0xA9,
|
||||
0x7D,0xE2,0xC4,0xAC,0x8E,0x5E,0xB8,0x25,0xF4,0xB9,0x57,0xF3,0xF1,0x68,0x47,0xB2,
|
||||
0xA2,0x59,0x20,0xCE,0x34,0x79,0x5C,0x90, 0xE,0x1E,0xBE,0xD5,0x22,0x23,0xB1,0xC9,
|
||||
0x18,0x62,0x16,0x2E,0x91,0x3E, 7,0x8F,0xD8,0x3F,0x93,0x3D,0xD4,0x9B,0xDF,0x85,
|
||||
0x21,0xFB,0x11,0x74,0x97,0xC7,0xD7,0xDC,0x4C,0x19,0x45,0x98,0xE9,0x43, 2,0x4B,
|
||||
0xBC,0xC3, 4,0x9C,0x6B,0xF0,0x75,0x52,0xA7,0x26,0xF6,0xC5,0xBA,0xCF,0xB0,0xB7,
|
||||
0xAE,0x5A,0xA1,0xBF, 3,0x8B,0x80,0x12,0x6E, 0xC,0xEB,0xF9,0xC0,0x44,0x24,0xEF,
|
||||
0x10,0xF8,0xA8,0x8C,0xE8,0x7B,0xFF,0x9E,0x2C,0xCD,0x60,0x36,0x87,0xB5,0x94,0xA6,
|
||||
0x54,0x73,0x3A,0x14,0x4E, 1,0x1D,0xB6,0xFD,0x37,0x48,0x4D,0x39,0xCB,0xE0,0x32,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static inline u8 ror8(const u8 a, const u8 b)
|
||||
{
|
||||
return (a>>b) | ((a<<(8-b))&0xff);
|
||||
}
|
||||
|
||||
|
||||
void genkey(const u8* const rand, const u8 idx, u8* const key)
|
||||
{
|
||||
const u8* const ans = ans_tbl[idx];
|
||||
u8 t0[10];
|
||||
|
||||
for(int i=0; i<10; ++i)
|
||||
t0[i] = tsbox[rand[i]];
|
||||
|
||||
key[0] = ((ror8((ans[0]^t0[5]),(t0[2]%8)) - t0[9]) ^ t0[4]);
|
||||
key[1] = ((ror8((ans[1]^t0[1]),(t0[0]%8)) - t0[5]) ^ t0[7]);
|
||||
key[2] = ((ror8((ans[2]^t0[6]),(t0[8]%8)) - t0[2]) ^ t0[0]);
|
||||
key[3] = ((ror8((ans[3]^t0[4]),(t0[7]%8)) - t0[3]) ^ t0[2]);
|
||||
key[4] = ((ror8((ans[4]^t0[1]),(t0[6]%8)) - t0[3]) ^ t0[4]);
|
||||
key[5] = ((ror8((ans[5]^t0[7]),(t0[8]%8)) - t0[5]) ^ t0[9]);
|
||||
}
|
||||
|
||||
|
||||
void gentabs(const u8* const rand, const u8* const key, const u8 idx, u8* const ft, u8* const sb)
|
||||
{
|
||||
ft[0] = sboxes[idx][key[4]] ^ sboxes[(idx+1)%8][rand[3]];
|
||||
ft[1] = sboxes[idx][key[2]] ^ sboxes[(idx+1)%8][rand[5]];
|
||||
ft[2] = sboxes[idx][key[5]] ^ sboxes[(idx+1)%8][rand[7]];
|
||||
ft[3] = sboxes[idx][key[0]] ^ sboxes[(idx+1)%8][rand[2]];
|
||||
ft[4] = sboxes[idx][key[1]] ^ sboxes[(idx+1)%8][rand[4]];
|
||||
ft[5] = sboxes[idx][key[3]] ^ sboxes[(idx+1)%8][rand[9]];
|
||||
ft[6] = sboxes[idx][rand[0]] ^ sboxes[(idx+1)%8][rand[6]];
|
||||
ft[7] = sboxes[idx][rand[1]] ^ sboxes[(idx+1)%8][rand[8]];
|
||||
|
||||
sb[0] = sboxes[idx][key[0]] ^ sboxes[(idx+1)%8][rand[1]];
|
||||
sb[1] = sboxes[idx][key[5]] ^ sboxes[(idx+1)%8][rand[4]];
|
||||
sb[2] = sboxes[idx][key[3]] ^ sboxes[(idx+1)%8][rand[0]];
|
||||
sb[3] = sboxes[idx][key[2]] ^ sboxes[(idx+1)%8][rand[9]];
|
||||
sb[4] = sboxes[idx][key[4]] ^ sboxes[(idx+1)%8][rand[7]];
|
||||
sb[5] = sboxes[idx][key[1]] ^ sboxes[(idx+1)%8][rand[8]];
|
||||
sb[6] = sboxes[idx][rand[3]] ^ sboxes[(idx+1)%8][rand[5]];
|
||||
sb[7] = sboxes[idx][rand[2]] ^ sboxes[(idx+1)%8][rand[6]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Generate key from the 0x40-0x4c data in g_RegExt */
|
||||
void wiimote_gen_key(wiimote_key* const key, const u8* const keydata)
|
||||
{
|
||||
u8 rand[10];
|
||||
u8 skey[6];
|
||||
u8 testkey[6];
|
||||
int idx;
|
||||
|
||||
for (int i=0; i<10; ++i)
|
||||
rand[9-i] = keydata[i];
|
||||
for (int i=0; i<6; ++i)
|
||||
skey[5-i] = keydata[i+10];
|
||||
|
||||
//DEBUG_LOG(WIIMOTE, "rand: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", rand[0], rand[1], rand[2], rand[3], rand[4], rand[5], rand[6], rand[7], rand[8], rand[9]);
|
||||
//DEBUG_LOG(WIIMOTE, "key: %02x %02x %02x %02x %02x %02x", skey[0], skey[1], skey[2], skey[3], skey[4], skey[5]);
|
||||
|
||||
for(idx = 0; idx < 7; ++idx)
|
||||
{
|
||||
genkey(rand, idx, testkey);
|
||||
if (0 == memcmp(testkey, skey, 6))
|
||||
break;
|
||||
}
|
||||
// default case is idx = 7 which is valid (homebrew uses it for the 0x17 case)
|
||||
//DEBUG_LOG(WIIMOTE, "idx: %d", idx);
|
||||
|
||||
gentabs(rand, skey, idx, key->ft, key->sb);
|
||||
|
||||
//DEBUG_LOG(WIIMOTE, "ft: %02x %02x %02x %02x %02x %02x %02x %02x", key->ft[0], key->ft[1], key->ft[2], key->ft[3], key->ft[4], key->ft[5], key->ft[6], key->ft[7]);
|
||||
//DEBUG_LOG(WIIMOTE, "sb: %02x %02x %02x %02x %02x %02x %02x %02x", key->sb[0], key->sb[1], key->sb[2], key->sb[3], key->sb[4], key->sb[5], key->sb[6], key->sb[7]);
|
||||
|
||||
// for homebrew, ft and sb are all 0x97 which is equivalent to 0x17
|
||||
}
|
||||
|
||||
// TODO: is there a reason these can only handle a length of 255?
|
||||
/* Encrypt data */
|
||||
void wiimote_encrypt(const wiimote_key* const key, u8* const data, int addr, const u8 len)
|
||||
{
|
||||
for (int i = 0; i < len; ++i, ++addr)
|
||||
data[i] = (data[i] - key->ft[addr % 8]) ^ key->sb[addr % 8];
|
||||
}
|
||||
|
||||
|
||||
/* Decrypt data */
|
||||
void wiimote_decrypt(const wiimote_key* const key, u8* const data, int addr, const u8 len)
|
||||
{
|
||||
for (int i = 0; i < len; ++i, ++addr)
|
||||
data[i] = (data[i] ^ key->sb[addr % 8]) + key->ft[addr % 8];
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
// Copyright (C) Hector Martin "marcan" ([email protected])
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#ifndef WIIMOTE_EXTENSION_ENCRYPTION_H
|
||||
#define WIIMOTE_EXTENSION_ENCRYPTION_H
|
||||
|
||||
|
||||
// ===================================================
|
||||
/* They key structure to use with wiimote_gen_key() */
|
||||
// ----------------
|
||||
struct wiimote_key
|
||||
{
|
||||
u8 ft[8];
|
||||
u8 sb[8];
|
||||
};
|
||||
|
||||
|
||||
void wiimote_encrypt(const wiimote_key* const key, u8* const data, int addr, const u8 len);
|
||||
void wiimote_decrypt(const wiimote_key* const key, u8* const data, int addr, const u8 len);
|
||||
|
||||
void wiimote_gen_key(wiimote_key* const key, const u8* const keydata);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#ifndef MATRIXMATH_H
|
||||
#define MATRIXMATH_H
|
||||
|
||||
#include <math.h>
|
||||
|
||||
typedef double Matrix[4][4];
|
||||
typedef struct
|
||||
{
|
||||
double x,y,z;
|
||||
} Vertex;
|
||||
|
||||
inline void MatrixIdentity(Matrix & m)
|
||||
{
|
||||
m[0][0]=1; m[0][1]=0; m[0][2]=0; m[0][3]=0;
|
||||
m[1][0]=0; m[1][1]=1; m[1][2]=0; m[1][3]=0;
|
||||
m[2][0]=0; m[2][1]=0; m[2][2]=1; m[2][3]=0;
|
||||
m[3][0]=0; m[3][1]=0; m[3][2]=0; m[3][3]=1;
|
||||
}
|
||||
|
||||
inline void MatrixFrustum(Matrix &m, double l, double r, double b, double t, double n, double f)
|
||||
{
|
||||
m[0][0]=2*n/(r-l); m[0][1]=0; m[0][2]=0; m[0][3]=0;
|
||||
m[1][0]=0; m[1][1]=2*n/(t-b); m[1][2]=0; m[1][3]=0;
|
||||
m[2][0]=(r+l)/(r-l); m[2][1]=(t+b)/(t-b); m[2][2]=(f+n)/(f-n); m[2][3]=-1;
|
||||
m[3][0]=0; m[3][1]=0; m[3][2]=2*f*n/(f-n); m[3][3]=0;
|
||||
}
|
||||
inline void MatrixPerspective(Matrix & m, double fovy, double aspect, double nplane, double fplane)
|
||||
{
|
||||
double xmin,xmax,ymin,ymax;
|
||||
|
||||
ymax = nplane * tan(fovy * M_PI / 360.0);
|
||||
ymin = -ymax;
|
||||
xmin = ymin * aspect;
|
||||
xmax = ymax * aspect;
|
||||
|
||||
MatrixFrustum(m,xmin,xmax,ymin,ymax,nplane,fplane);
|
||||
}
|
||||
|
||||
inline void MatrixRotationByZ(Matrix &m, double sin, double cos)
|
||||
{
|
||||
m[0][0]=cos; m[0][1]=-sin; m[0][2]=0; m[0][3]=0;
|
||||
m[1][0]=sin; m[1][1]=cos; m[1][2]=0; m[1][3]=0;
|
||||
m[2][0]=0; m[2][1]=0; m[2][2]=1; m[2][3]=0;
|
||||
m[3][0]=0; m[3][1]=0; m[3][2]=0; m[3][3]=1;
|
||||
}
|
||||
|
||||
inline void MatrixScale(Matrix &m, double xfact, double yfact, double zfact)
|
||||
{
|
||||
m[0][0]=xfact; m[0][1]=0; m[0][2]=0; m[0][3]=0;
|
||||
m[1][0]=0; m[1][1]=yfact; m[1][2]=0; m[1][3]=0;
|
||||
m[2][0]=0; m[2][1]=0; m[2][2]=zfact; m[2][3]=0;
|
||||
m[3][0]=0; m[3][1]=0; m[3][2]=0; m[3][3]=1;
|
||||
}
|
||||
|
||||
inline void MatrixMultiply(Matrix &r, const Matrix &a, const Matrix &b)
|
||||
{
|
||||
for (int i=0; i<16; i++)
|
||||
r[i>>2][i&3]=0.0f;
|
||||
for (int i=0; i<4; i++)
|
||||
for (int j=0; j<4; j++)
|
||||
for (int k=0; k<4; k++)
|
||||
r[i][j]+=a[i][k]*b[k][j];
|
||||
}
|
||||
|
||||
inline void MatrixTransformVertex(Matrix const & m, Vertex & v)
|
||||
{
|
||||
Vertex ov;
|
||||
double w;
|
||||
ov.x=v.x;
|
||||
ov.y=v.y;
|
||||
ov.z=v.z;
|
||||
v.x = m[0][0] * ov.x + m[0][1] * ov.y + m[0][2] * ov.z + m[0][3];
|
||||
v.y = m[1][0] * ov.x + m[1][1] * ov.y + m[1][2] * ov.z + m[1][3];
|
||||
v.z = m[2][0] * ov.x + m[2][1] * ov.y + m[2][2] * ov.z + m[2][3];
|
||||
w = m[3][0] * ov.x + m[3][1] * ov.y + m[3][2] * ov.z + m[3][3];
|
||||
if (w!=0)
|
||||
{
|
||||
v.x/=w;
|
||||
v.y/=w;
|
||||
v.z/=w;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
#include "WiimoteEmu.h"
|
||||
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
void Wiimote::SpeakerData(wm_speaker_data* sd)
|
||||
{
|
||||
SoundBuffer sb;
|
||||
sb.samples = new s16[sd->length * 2];
|
||||
|
||||
s16* s = sb.samples;
|
||||
const u8* const e = sd->data + sd->length;
|
||||
for ( const u8* i = sd->data; i<e; ++i )
|
||||
{
|
||||
*s++ = NGCADPCM::ADPDecodeSample(*i & 0x0F, sd->data[0] & 0x0F, &m_channel_status.hist1p, &m_channel_status.hist2p);
|
||||
*s++ = NGCADPCM::ADPDecodeSample(*i >> 4, sd->data[0] >> 4, &m_channel_status.hist1p, &m_channel_status.hist2p);
|
||||
}
|
||||
|
||||
alGenBuffers(1, &sb.buffer);
|
||||
// TODO make this not always 3000
|
||||
alBufferData(sb.buffer, AL_FORMAT_MONO16, sb.samples, (sd->length * sizeof(short) * 2), 3360);
|
||||
// testing
|
||||
//alBufferData(sb.buffer, AL_FORMAT_MONO16, sb.samples, (sd->length * sizeof(short) * 2), 48000/m_reg_speaker->sample_rate);
|
||||
alSourceQueueBuffers(m_audio_source, 1, &sb.buffer);
|
||||
|
||||
ALint state;
|
||||
alGetSourcei(m_audio_source, AL_SOURCE_STATE, &state);
|
||||
if (AL_PLAYING != state)
|
||||
alSourcePlay(m_audio_source);
|
||||
|
||||
m_audio_buffers.push(sb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,56 +0,0 @@
|
||||
//UDP Wiimote Translation Layer
|
||||
|
||||
#ifndef UDPTLAYER_H
|
||||
#define UDPTLAYER_H
|
||||
|
||||
#include "UDPWiimote.h"
|
||||
#include "WiimoteEmu.h"
|
||||
|
||||
using WiimoteEmu::Wiimote;
|
||||
|
||||
namespace UDPTLayer
|
||||
{
|
||||
void GetButtons(UDPWrapper * m , wm_core * butt)
|
||||
{
|
||||
if (!(m->inst)) return;
|
||||
if (!(m->updButt)) return;
|
||||
u32 mask=m->inst->getButtons();
|
||||
*butt|=(mask&UDPWM_BA)?Wiimote::BUTTON_A:0;
|
||||
*butt|=(mask&UDPWM_BB)?Wiimote::BUTTON_B:0;
|
||||
*butt|=(mask&UDPWM_B1)?Wiimote::BUTTON_ONE:0;
|
||||
*butt|=(mask&UDPWM_B2)?Wiimote::BUTTON_TWO:0;
|
||||
*butt|=(mask&UDPWM_BP)?Wiimote::BUTTON_PLUS:0;
|
||||
*butt|=(mask&UDPWM_BM)?Wiimote::BUTTON_MINUS:0;
|
||||
*butt|=(mask&UDPWM_BH)?Wiimote::BUTTON_HOME:0;
|
||||
*butt|=(mask&UDPWM_BU)?Wiimote::PAD_UP:0;
|
||||
*butt|=(mask&UDPWM_BD)?Wiimote::PAD_DOWN:0;
|
||||
*butt|=(mask&UDPWM_BL)?Wiimote::PAD_LEFT:0;
|
||||
*butt|=(mask&UDPWM_BR)?Wiimote::PAD_RIGHT:0;
|
||||
}
|
||||
|
||||
void GetAcceleration(UDPWrapper * m , WiimoteEmu::AccelData * const data)
|
||||
{
|
||||
if (!(m->inst)) return;
|
||||
if (!(m->updAccel)) return;
|
||||
float x,y,z;
|
||||
m->inst->getAccel(x,y,z);
|
||||
data->x=x;
|
||||
data->y=y;
|
||||
data->z=z;
|
||||
}
|
||||
|
||||
void GetIR( UDPWrapper * m, float * x, float * y, float * z)
|
||||
{
|
||||
if (!(m->inst)) return;
|
||||
if (!(m->updIR)) return;
|
||||
if ((*x>=-0.999)&&(*x<=0.999)&&(*y>=-0.999)&&(*y<=0.999)) return; //the recieved values are used ONLY when the normal pointer is offscreen
|
||||
float _x,_y;
|
||||
m->inst->getIR(_x,_y);
|
||||
*x=_x*2-1;
|
||||
*y=-(_y*2-1);
|
||||
*z=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,242 +0,0 @@
|
||||
#ifndef _CONEMU_WIIMOTE_H_
|
||||
#define _CONEMU_WIIMOTE_H_
|
||||
|
||||
//#define USE_WIIMOTE_EMU_SPEAKER
|
||||
|
||||
//#include <Core.h>
|
||||
//#include <HW/StreamADPCM.h>
|
||||
// just used to get the OpenAL includes :p
|
||||
//#include <OpenALStream.h>
|
||||
|
||||
#include "ControllerEmu.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
#include "WiimoteHid.h"
|
||||
#include "Encryption.h"
|
||||
#include "UDPWrapper.h"
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#define PI 3.14159265358979323846
|
||||
|
||||
// Registry sizes
|
||||
#define WIIMOTE_EEPROM_SIZE (16*1024)
|
||||
#define WIIMOTE_EEPROM_FREE_SIZE 0x1700
|
||||
#define WIIMOTE_REG_SPEAKER_SIZE 10
|
||||
#define WIIMOTE_REG_EXT_SIZE 0x100
|
||||
#define WIIMOTE_REG_IR_SIZE 0x34
|
||||
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
namespace WiimoteEmu
|
||||
{
|
||||
|
||||
struct ReportFeatures
|
||||
{
|
||||
u8 core, accel, ir, ext, size;
|
||||
};
|
||||
|
||||
struct AccelData
|
||||
{
|
||||
double x,y,z;
|
||||
};
|
||||
|
||||
extern const ReportFeatures reporting_mode_features[];
|
||||
|
||||
void EmulateShake(AccelData* const accel_data
|
||||
, ControllerEmu::Buttons* const buttons_group
|
||||
, unsigned int* const shake_step);
|
||||
|
||||
void EmulateTilt(AccelData* const accel
|
||||
, ControllerEmu::Tilt* const tilt_group
|
||||
, const bool focus, const bool sideways = false, const bool upright = false);
|
||||
|
||||
void EmulateSwing(AccelData* const accel
|
||||
, ControllerEmu::Force* const tilt_group
|
||||
, const bool sideways = false, const bool upright = false);
|
||||
|
||||
inline double trim(double a)
|
||||
{
|
||||
if (a<=0) return 0;
|
||||
if (a>=255) return 255;
|
||||
return a;
|
||||
}
|
||||
|
||||
class Wiimote : public ControllerEmu
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
PAD_LEFT = 0x01,
|
||||
PAD_RIGHT = 0x02,
|
||||
PAD_DOWN = 0x04,
|
||||
PAD_UP = 0x08,
|
||||
BUTTON_PLUS = 0x10,
|
||||
|
||||
BUTTON_TWO = 0x0100,
|
||||
BUTTON_ONE = 0x0200,
|
||||
BUTTON_B = 0x0400,
|
||||
BUTTON_A = 0x0800,
|
||||
BUTTON_MINUS = 0x1000,
|
||||
BUTTON_HOME = 0x8000,
|
||||
};
|
||||
|
||||
Wiimote( const unsigned int index );
|
||||
std::string GetName() const;
|
||||
|
||||
void Update();
|
||||
void InterruptChannel(const u16 _channelID, const void* _pData, u32 _Size);
|
||||
void ControlChannel(const u16 _channelID, const void* _pData, u32 _Size);
|
||||
|
||||
void DoState(PointerWrap& p);
|
||||
|
||||
void LoadDefaults(const ControllerInterface& ciface);
|
||||
|
||||
protected:
|
||||
bool Step();
|
||||
void HidOutputReport(const wm_report* const sr, const bool send_ack = true);
|
||||
void HandleExtensionSwap();
|
||||
|
||||
void GetCoreData(u8* const data);
|
||||
void GetAccelData(u8* const data, u8* const buttons);
|
||||
void GetIRData(u8* const data, bool use_accel);
|
||||
void GetExtData(u8* const data);
|
||||
|
||||
bool HaveExtension() const { return m_extension->active_extension > 0; }
|
||||
bool WantExtension() const { return m_extension->switch_extension != 0; }
|
||||
|
||||
private:
|
||||
struct ReadRequest
|
||||
{
|
||||
//u16 channel;
|
||||
unsigned int address, size, position;
|
||||
u8* data;
|
||||
};
|
||||
|
||||
void Reset();
|
||||
|
||||
void ReportMode(const wm_report_mode* const dr);
|
||||
void SendAck(const u8 _reportID);
|
||||
void RequestStatus(const wm_request_status* const rs = NULL);
|
||||
void ReadData(const wm_read_data* const rd);
|
||||
void WriteData(const wm_write_data* const wd);
|
||||
void SendReadDataReply(ReadRequest& _request);
|
||||
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
void SpeakerData(wm_speaker_data* sd);
|
||||
#endif
|
||||
|
||||
// control groups
|
||||
Buttons* m_buttons;
|
||||
Buttons* m_dpad;
|
||||
Buttons* m_shake;
|
||||
Cursor* m_ir;
|
||||
Tilt* m_tilt;
|
||||
Force* m_swing;
|
||||
ControlGroup* m_rumble;
|
||||
Extension* m_extension;
|
||||
ControlGroup* m_options;
|
||||
// WiiMote accel data
|
||||
AccelData m_accel;
|
||||
|
||||
// wiimote index, 0-3
|
||||
const unsigned int m_index;
|
||||
|
||||
double ir_sin,ir_cos; //for the low pass filter
|
||||
|
||||
//UDPWiimote
|
||||
UDPWrapper* m_udp;
|
||||
|
||||
bool m_rumble_on;
|
||||
bool m_speaker_mute;
|
||||
|
||||
bool m_reporting_auto;
|
||||
u8 m_reporting_mode;
|
||||
u16 m_reporting_channel;
|
||||
|
||||
unsigned int m_shake_step[3];
|
||||
|
||||
wm_status_report m_status;
|
||||
|
||||
class Register : public std::map< size_t, std::vector<u8> >
|
||||
{
|
||||
public:
|
||||
void Write( size_t address, const void* src, size_t length );
|
||||
void Read( size_t address, void* dst, size_t length );
|
||||
|
||||
} m_register;
|
||||
|
||||
// read data request queue
|
||||
// maybe it isn't actualy a queue
|
||||
// maybe read requests cancel any current requests
|
||||
std::queue< ReadRequest > m_read_requests;
|
||||
|
||||
#ifdef USE_WIIMOTE_EMU_SPEAKER
|
||||
// speaker stuff
|
||||
struct SoundBuffer
|
||||
{
|
||||
s16* samples;
|
||||
ALuint buffer;
|
||||
};
|
||||
std::queue<SoundBuffer> m_audio_buffers;
|
||||
ALuint m_audio_source;
|
||||
struct
|
||||
{
|
||||
int hist1p, hist2p;
|
||||
} m_channel_status;
|
||||
#endif
|
||||
|
||||
u8 m_eeprom[WIIMOTE_EEPROM_SIZE];
|
||||
|
||||
u8* m_reg_motion_plus;
|
||||
|
||||
struct IrReg
|
||||
{
|
||||
u8 data[0x33];
|
||||
u8 mode;
|
||||
|
||||
} *m_reg_ir;
|
||||
|
||||
struct ExtensionReg
|
||||
{
|
||||
u8 unknown1[0x08];
|
||||
|
||||
// address 0x08
|
||||
u8 controller_data[0x06];
|
||||
u8 unknown2[0x12];
|
||||
|
||||
// address 0x20
|
||||
u8 calibration[0x10];
|
||||
u8 unknown3[0x10];
|
||||
|
||||
// address 0x40
|
||||
u8 encryption_key[0x10];
|
||||
u8 unknown4[0xA0];
|
||||
|
||||
// address 0xF0
|
||||
u8 encryption;
|
||||
u8 unknown5[0x9];
|
||||
|
||||
// address 0xFA
|
||||
u8 constant_id[6];
|
||||
|
||||
} *m_reg_ext;
|
||||
|
||||
struct SpeakerReg
|
||||
{
|
||||
u16 unknown;
|
||||
u8 format;
|
||||
u16 sample_rate;
|
||||
u8 volume;
|
||||
u8 unk[4];
|
||||
|
||||
} *m_reg_speaker;
|
||||
|
||||
wiimote_key m_ext_key;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,382 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef WIIMOTE_HID_H
|
||||
#define WIIMOTE_HID_H
|
||||
|
||||
#include "CommonTypes.h"
|
||||
|
||||
// what is this ?
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4200)
|
||||
#endif
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// Source: HID_010_SPC_PFL/1.0 (official HID specification)
|
||||
|
||||
struct hid_packet {
|
||||
u8 param : 4;
|
||||
u8 type : 4;
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
#define HID_TYPE_HANDSHAKE 0
|
||||
#define HID_TYPE_SET_REPORT 5
|
||||
#define HID_TYPE_DATA 0xA
|
||||
|
||||
#define HID_HANDSHAKE_SUCCESS 0
|
||||
|
||||
#define HID_PARAM_INPUT 1
|
||||
#define HID_PARAM_OUTPUT 2
|
||||
|
||||
//source: http://wiibrew.org/wiki/Wiimote
|
||||
|
||||
typedef u16 wm_core;
|
||||
|
||||
struct wm_accel
|
||||
{
|
||||
u8 x, y, z;
|
||||
};
|
||||
|
||||
// Four bytes for two objects. Filled with 0xFF if empty
|
||||
struct wm_ir_basic
|
||||
{
|
||||
u8 x1;
|
||||
u8 y1;
|
||||
u8 x2hi : 2;
|
||||
u8 y2hi : 2;
|
||||
u8 x1hi : 2;
|
||||
u8 y1hi : 2;
|
||||
u8 x2;
|
||||
u8 y2;
|
||||
};
|
||||
|
||||
// Three bytes for one object
|
||||
struct wm_ir_extended
|
||||
{
|
||||
u8 x;
|
||||
u8 y;
|
||||
u8 size : 4;
|
||||
u8 xhi : 2;
|
||||
u8 yhi : 2;
|
||||
};
|
||||
|
||||
struct wm_extension
|
||||
{
|
||||
u8 jx; // joystick x, y
|
||||
u8 jy;
|
||||
u8 ax; // accelerometer
|
||||
u8 ay;
|
||||
u8 az;
|
||||
u8 bt; // buttons
|
||||
};
|
||||
|
||||
struct wm_classic_extension
|
||||
{
|
||||
u8 lx : 6; // byte 0
|
||||
u8 rx3 : 2;
|
||||
u8 ly : 6; // byte 1
|
||||
u8 rx2 : 2;
|
||||
u8 ry : 5; // byte 2
|
||||
u8 lt2 : 2;
|
||||
u8 rx1 : 1;
|
||||
u8 rt : 5; // byte 3
|
||||
u8 lt1 : 3;
|
||||
u16 bt; // byte 4, 5
|
||||
};
|
||||
|
||||
struct wm_guitar_extension
|
||||
{
|
||||
u8 sx : 6;
|
||||
u8 pad1 : 2; // 1 on gh3, 0 on ghwt
|
||||
|
||||
u8 sy : 6;
|
||||
u8 pad2 : 2; // 1 on gh3, 0 on ghwt
|
||||
|
||||
u8 tb : 5; // not used in gh3
|
||||
u8 pad3 : 3; // always 0
|
||||
|
||||
u8 whammy : 5;
|
||||
u8 pad4 : 3; // always 0
|
||||
|
||||
u16 bt; // buttons
|
||||
};
|
||||
|
||||
struct wm_drums_extension
|
||||
{
|
||||
u8 sx : 6;
|
||||
u8 pad1 : 2; // always 0
|
||||
|
||||
u8 sy : 6;
|
||||
u8 pad2 : 2; // always 0
|
||||
|
||||
u8 pad3 : 1; // unknown
|
||||
u8 which : 5;
|
||||
u8 none : 1;
|
||||
u8 hhp : 1;
|
||||
|
||||
u8 pad4 : 1; // unknown
|
||||
u8 velocity : 4; // unknown
|
||||
u8 softness : 3;
|
||||
|
||||
u16 bt; // buttons
|
||||
};
|
||||
|
||||
struct wm_turntable_extension
|
||||
{
|
||||
u8 sx : 6;
|
||||
u8 rtable3 : 2;
|
||||
|
||||
u8 sy : 6;
|
||||
u8 rtable2 : 2;
|
||||
|
||||
u8 rtable4 : 1;
|
||||
u8 slider : 4;
|
||||
u8 dial2 : 2;
|
||||
u8 rtable1 : 1;
|
||||
|
||||
u8 ltable1 : 5;
|
||||
u8 dial1 : 3;
|
||||
|
||||
union
|
||||
{
|
||||
u16 ltable2 : 1;
|
||||
u16 bt; // buttons
|
||||
};
|
||||
};
|
||||
|
||||
struct wm_report
|
||||
{
|
||||
u8 wm;
|
||||
union
|
||||
{
|
||||
u8 data[0];
|
||||
struct
|
||||
{
|
||||
u8 rumble : 1; // enable/disable rumble
|
||||
// only valid for certain reports
|
||||
u8 ack : 1; // respond with an ack
|
||||
u8 enable : 1; // enable/disable certain features
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#define WM_RUMBLE 0x10
|
||||
|
||||
#define WM_LEDS 0x11
|
||||
struct wm_leds {
|
||||
u8 rumble : 1;
|
||||
u8 : 3;
|
||||
u8 leds : 4;
|
||||
};
|
||||
|
||||
#define WM_REPORT_MODE 0x12
|
||||
struct wm_report_mode {
|
||||
u8 rumble : 1;
|
||||
u8 continuous : 1; // these 2 seem to be named wrong
|
||||
u8 all_the_time : 1;
|
||||
u8 : 5;
|
||||
u8 mode;
|
||||
};
|
||||
|
||||
#define WM_IR_PIXEL_CLOCK 0x13
|
||||
#define WM_IR_LOGIC 0x1A
|
||||
|
||||
#define WM_REQUEST_STATUS 0x15
|
||||
struct wm_request_status {
|
||||
u8 rumble : 1;
|
||||
u8 : 7;
|
||||
};
|
||||
|
||||
#define WM_STATUS_REPORT 0x20
|
||||
struct wm_status_report {
|
||||
wm_core buttons;
|
||||
u8 battery_low : 1;
|
||||
u8 extension : 1;
|
||||
u8 speaker : 1;
|
||||
u8 ir : 1;
|
||||
u8 leds : 4;
|
||||
u8 padding2[2]; // two 00, TODO: this needs more investigation
|
||||
u8 battery;
|
||||
};
|
||||
|
||||
#define WM_WRITE_DATA 0x16
|
||||
struct wm_write_data
|
||||
{
|
||||
u8 rumble : 1;
|
||||
u8 space : 2; //see WM_SPACE_*
|
||||
u8 : 5;
|
||||
u8 address[3];
|
||||
u8 size;
|
||||
u8 data[16];
|
||||
};
|
||||
|
||||
#define WM_ACK_DATA 0x22
|
||||
struct wm_acknowledge
|
||||
{
|
||||
wm_core buttons;
|
||||
u8 reportID;
|
||||
u8 errorID;
|
||||
};
|
||||
|
||||
#define WM_READ_DATA 0x17
|
||||
struct wm_read_data {
|
||||
u8 rumble : 1;
|
||||
u8 space : 2; //see WM_SPACE_*
|
||||
u8 : 5;
|
||||
u8 address[3];
|
||||
u16 size;
|
||||
};
|
||||
|
||||
#define WM_SPACE_EEPROM 0
|
||||
#define WM_SPACE_REGS1 1
|
||||
#define WM_SPACE_REGS2 2
|
||||
#define WM_SPACE_INVALID 3
|
||||
|
||||
#define WM_READ_DATA_REPLY 0x21
|
||||
struct wm_read_data_reply {
|
||||
wm_core buttons;
|
||||
u8 error : 4; //see WM_RDERR_*
|
||||
u8 size : 4;
|
||||
u16 address;
|
||||
u8 data[16];
|
||||
};
|
||||
|
||||
#define WM_RDERR_WOREG 7
|
||||
#define WM_RDERR_NOMEM 8
|
||||
|
||||
|
||||
// Data reports
|
||||
|
||||
#define WM_REPORT_CORE 0x30
|
||||
struct wm_report_core {
|
||||
wm_core c;
|
||||
};
|
||||
|
||||
#define WM_REPORT_CORE_ACCEL 0x31
|
||||
struct wm_report_core_accel {
|
||||
wm_core c;
|
||||
wm_accel a;
|
||||
};
|
||||
|
||||
#define WM_REPORT_CORE_EXT8 0x32
|
||||
|
||||
#define WM_REPORT_CORE_ACCEL_IR12 0x33
|
||||
struct wm_report_core_accel_ir12 {
|
||||
wm_core c;
|
||||
wm_accel a;
|
||||
wm_ir_extended ir[4];
|
||||
};
|
||||
|
||||
#define WM_REPORT_CORE_EXT19 0x34
|
||||
#define WM_REPORT_CORE_ACCEL_EXT16 0x35
|
||||
struct wm_report_core_accel_ext16
|
||||
{
|
||||
wm_core c;
|
||||
wm_accel a;
|
||||
wm_extension ext;
|
||||
//wm_ir_basic ir[2];
|
||||
u8 pad[10];
|
||||
|
||||
};
|
||||
|
||||
#define WM_REPORT_CORE_IR10_EXT9 0x36
|
||||
|
||||
#define WM_REPORT_CORE_ACCEL_IR10_EXT6 0x37
|
||||
struct wm_report_core_accel_ir10_ext6
|
||||
{
|
||||
wm_core c;
|
||||
wm_accel a;
|
||||
wm_ir_basic ir[2];
|
||||
//u8 ext[6];
|
||||
wm_extension ext;
|
||||
};
|
||||
|
||||
#define WM_REPORT_EXT21 0x3d // never used?
|
||||
struct wm_report_ext21
|
||||
{
|
||||
u8 ext[21];
|
||||
};
|
||||
|
||||
#define WM_REPORT_INTERLEAVE1 0x3e
|
||||
#define WM_REPORT_INTERLEAVE2 0x3f
|
||||
|
||||
#define WM_SPEAKER_ENABLE 0x14
|
||||
#define WM_SPEAKER_MUTE 0x19
|
||||
#define WM_WRITE_SPEAKER_DATA 0x18
|
||||
struct wm_speaker_data {
|
||||
u8 unknown : 3;
|
||||
u8 length : 5;
|
||||
u8 data[20];
|
||||
};
|
||||
|
||||
// Custom structs
|
||||
|
||||
/**
|
||||
* @struct accel_t
|
||||
* @brief Accelerometer struct. For any device with an accelerometer.
|
||||
*/
|
||||
struct accel_cal
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 x, y, z;
|
||||
u8 xlo : 2;
|
||||
u8 ylo : 2;
|
||||
u8 zlo : 2;
|
||||
} zero_g;
|
||||
|
||||
struct
|
||||
{
|
||||
u8 x, y, z;
|
||||
u8 xlo : 2;
|
||||
u8 ylo : 2;
|
||||
u8 zlo : 2;
|
||||
} one_g;
|
||||
};
|
||||
|
||||
struct nu_js {
|
||||
u8 max, min, center;
|
||||
};
|
||||
struct cc_trigger {
|
||||
u8 neutral;
|
||||
};
|
||||
struct nu_cal
|
||||
{
|
||||
wm_accel cal_zero; // zero calibratio
|
||||
wm_accel cal_g; // g size
|
||||
nu_js jx; //
|
||||
nu_js jy; //
|
||||
};
|
||||
struct cc_cal
|
||||
{
|
||||
nu_js Lx; //
|
||||
nu_js Ly; //
|
||||
nu_js Rx; //
|
||||
nu_js Ry; //
|
||||
cc_trigger Tl; //
|
||||
cc_trigger Tr; //
|
||||
};
|
||||
struct gh3_cal
|
||||
{
|
||||
nu_js Lx;
|
||||
nu_js Ly;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif //WIIMOTE_HID_H
|
||||
@@ -1,337 +0,0 @@
|
||||
|
||||
#include "Common.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include "WiimoteReal/WiimoteReal.h"
|
||||
#include "WiimoteEmu/WiimoteEmu.h"
|
||||
|
||||
#include "ControllerInterface/ControllerInterface.h"
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
#include "WiimoteConfigDiag.h"
|
||||
#include "../../InputUICommon/Src/ConfigDiag.h"
|
||||
#endif
|
||||
#include "../../InputCommon/Src/InputConfig.h"
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#include <X11/Xlib.h>
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define PLUGIN_VERSION 0x0100
|
||||
|
||||
#define PLUGIN_NAME "Dolphin Wiimote New"
|
||||
#if defined(DEBUGFAST)
|
||||
#define PLUGIN_FULL_NAME PLUGIN_NAME" (DebugFast)"
|
||||
#elif defined(_DEBUG)
|
||||
#define PLUGIN_FULL_NAME PLUGIN_NAME" (Debug)"
|
||||
#else
|
||||
#define PLUGIN_FULL_NAME PLUGIN_NAME
|
||||
#endif
|
||||
|
||||
// plugin globals
|
||||
InputPlugin g_plugin( "WiimoteNew", "Wiimote", "Wiimote" );
|
||||
SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
#ifdef _WIN32
|
||||
class wxDLLApp : public wxApp
|
||||
{
|
||||
bool OnInit()
|
||||
{
|
||||
return true;
|
||||
};
|
||||
};
|
||||
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
|
||||
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
|
||||
{
|
||||
switch (fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
wxSetInstance(hinstDLL);
|
||||
wxInitialize();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
wxUninitialize();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_hInstance = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
void DeInitPlugin()
|
||||
{
|
||||
if (g_plugin.controller_interface.IsInit())
|
||||
{
|
||||
std::vector<ControllerEmu*>::const_iterator
|
||||
i = g_plugin.controllers.begin(),
|
||||
e = g_plugin.controllers.end();
|
||||
for ( ; i!=e; ++i )
|
||||
delete *i;
|
||||
g_plugin.controllers.clear();
|
||||
|
||||
// true parameter to make SDL not quit in the wiimote plugin,
|
||||
// the old wiimote plugin uses this hack as well, to prevent crash on stop
|
||||
g_plugin.controller_interface.DeInit(true);
|
||||
|
||||
// real wiimotes
|
||||
WiimoteReal::Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
// if plugin isn't initialized, init and load config
|
||||
void InitPlugin( void* const hwnd )
|
||||
{
|
||||
if (false == g_plugin.controller_interface.IsInit())
|
||||
{
|
||||
// add 4 wiimotes
|
||||
for ( unsigned int i = 0; i<4; ++i )
|
||||
g_plugin.controllers.push_back( new WiimoteEmu::Wiimote(i) );
|
||||
|
||||
// needed for Xlib and exclusive dinput
|
||||
g_plugin.controller_interface.SetHwnd(hwnd);
|
||||
g_plugin.controller_interface.Init();
|
||||
|
||||
// load the saved controller config
|
||||
g_plugin.LoadConfig();
|
||||
|
||||
// real wiimotes
|
||||
WiimoteReal::LoadSettings();
|
||||
WiimoteReal::Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
// I N T E R F A C E
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function: Wiimote_Output
|
||||
// Purpose: An L2CAP packet is passed from the Core to the Wiimote,
|
||||
// on the HID CONTROL channel.
|
||||
// input: Da pakket.
|
||||
// output: none
|
||||
//
|
||||
void Wiimote_ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number])
|
||||
((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->ControlChannel(_channelID, _pData, _Size);
|
||||
|
||||
if (WIIMOTE_SRC_REAL & g_wiimote_sources[_number])
|
||||
WiimoteReal::ControlChannel(_number, _channelID, _pData, _Size);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function: Send keyboard input to the plugin
|
||||
// Purpose:
|
||||
// input: The key and if it's pressed or released
|
||||
// output: None
|
||||
//
|
||||
void Wiimote_Input(u16 _Key, u8 _UpDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function: Unpair real Wiimotes (just a dummy to be compliant)
|
||||
// Purpose:
|
||||
// input: None
|
||||
// output: 0 Wiimotes disconnected
|
||||
//
|
||||
unsigned int Wiimote_UnPairWiimotes(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function: Wiimote_InterruptChannel
|
||||
// Purpose: An L2CAP packet is passed from the Core to the Wiimote,
|
||||
// on the HID INTERRUPT channel.
|
||||
// input: Da pakket.
|
||||
// output: none
|
||||
//
|
||||
void Wiimote_InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number])
|
||||
((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->InterruptChannel(_channelID, _pData, _Size);
|
||||
else
|
||||
WiimoteReal::InterruptChannel(_number, _channelID, _pData, _Size);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function: Wiimote_Update
|
||||
// Purpose: This function is called periodically by the Core.
|
||||
// input: none
|
||||
// output: none
|
||||
//
|
||||
void Wiimote_Update(int _number)
|
||||
{
|
||||
//PanicAlert( "Wiimote_Update" );
|
||||
|
||||
// TODO: change this to a TryEnter, and make it give empty input on failure
|
||||
g_plugin.controls_crit.Enter();
|
||||
|
||||
static int _last_number = 4;
|
||||
if (_number <= _last_number)
|
||||
{
|
||||
g_plugin.controller_interface.UpdateOutput();
|
||||
g_plugin.controller_interface.UpdateInput();
|
||||
}
|
||||
_last_number = _number;
|
||||
|
||||
if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number])
|
||||
((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->Update();
|
||||
else
|
||||
WiimoteReal::Update(_number);
|
||||
|
||||
g_plugin.controls_crit.Leave();
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function: PAD_GetAttachedPads
|
||||
// Purpose: Get mask of attached pads (eg: controller 1 & 4 -> 0x9)
|
||||
// input: none
|
||||
// output: number of pads
|
||||
//
|
||||
unsigned int Wiimote_GetAttachedControllers()
|
||||
{
|
||||
unsigned int attached = 0;
|
||||
for (unsigned int i=0; i<4; ++i)
|
||||
if (g_wiimote_sources[i])
|
||||
attached |= (1 << i);
|
||||
return attached;
|
||||
}
|
||||
|
||||
// GLOBAL I N T E R F A C E
|
||||
// Function: GetDllInfo
|
||||
// Purpose: This function allows the emulator to gather information
|
||||
// about the DLL by filling in the PluginInfo structure.
|
||||
// input: A pointer to a PLUGIN_INFO structure that needs to be
|
||||
// filled by the function. (see def above)
|
||||
// output: none
|
||||
//
|
||||
void GetDllInfo(PLUGIN_INFO* _pPluginInfo)
|
||||
{
|
||||
// don't feel like messing around with all those strcpy functions and warnings
|
||||
//char *s1 = CIFACE_PLUGIN_FULL_NAME, *s2 = _pPluginInfo->Name;
|
||||
//while ( *s2++ = *s1++ );
|
||||
memcpy( _pPluginInfo->Name, PLUGIN_FULL_NAME, sizeof(PLUGIN_FULL_NAME) );
|
||||
_pPluginInfo->Type = PLUGIN_TYPE_WIIMOTE;
|
||||
_pPluginInfo->Version = PLUGIN_VERSION;
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: DllConfig
|
||||
// Purpose: This function is optional function that is provided
|
||||
// to allow the user to configure the DLL
|
||||
// input: A handle to the window that calls this function
|
||||
// output: none
|
||||
//
|
||||
void DllConfig(void *_hParent)
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
const bool was_init = g_plugin.controller_interface.IsInit();
|
||||
|
||||
if (false == was_init)
|
||||
{
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
Window win = GDK_WINDOW_XID(GTK_WIDGET(((wxWindow *)_hParent)->GetHandle())->window);
|
||||
InitPlugin((void *)win);
|
||||
#else
|
||||
InitPlugin(((wxWindow *)_hParent)->GetHandle());
|
||||
#endif
|
||||
}
|
||||
|
||||
WiimoteConfigDiag* const m_ConfigFrame = new WiimoteConfigDiag((wxWindow *)_hParent, g_plugin);
|
||||
|
||||
m_ConfigFrame->ShowModal();
|
||||
|
||||
m_ConfigFrame->Destroy();
|
||||
|
||||
if (false == was_init)
|
||||
DeInitPlugin();
|
||||
#endif
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: DllDebugger
|
||||
// Purpose: Open the debugger
|
||||
// input: a handle to the window that calls this function
|
||||
// output: none
|
||||
//
|
||||
void *DllDebugger(void *_hParent, bool Show)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: DllSetGlobals
|
||||
// Purpose: Set the pointer for globals variables
|
||||
// input: a pointer to the global struct
|
||||
// output: none
|
||||
//
|
||||
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
|
||||
{
|
||||
// wut?
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: Initialize
|
||||
// Purpose: Initialize the plugin
|
||||
// input: Init
|
||||
// output: none
|
||||
//
|
||||
void Initialize(void *init)
|
||||
{
|
||||
g_WiimoteInitialize = *(SWiimoteInitialize*)init;
|
||||
if ( false == g_plugin.controller_interface.IsInit() )
|
||||
InitPlugin( g_WiimoteInitialize.hWnd );
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: Shutdown
|
||||
// Purpose: This function is called when the emulator is shutting down
|
||||
// a game allowing the dll to de-initialise.
|
||||
// input: none
|
||||
// output: none
|
||||
//
|
||||
void Shutdown(void)
|
||||
{
|
||||
if ( g_plugin.controller_interface.IsInit() )
|
||||
DeInitPlugin();
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: DoState
|
||||
// Purpose: Saves/load state
|
||||
// input/output: ptr
|
||||
// input: mode
|
||||
//
|
||||
void DoState(unsigned char **ptr, int mode)
|
||||
{
|
||||
// TODO: this
|
||||
|
||||
//PointerWrap p(ptr, mode);
|
||||
//for (unsigned int i=0; i<4; ++i)
|
||||
// ((WiimoteEmu::Wiimote*)g_plugin.controllers[i])->DoState(p);
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
// Function: EmuStateChange
|
||||
// Purpose: Notifies the plugin of a change in emulation state
|
||||
// input: newState
|
||||
// output: none
|
||||
//
|
||||
void EmuStateChange(PLUGIN_EMUSTATE newState)
|
||||
{
|
||||
// maybe use this later
|
||||
WiimoteReal::StateChange(newState);
|
||||
}
|
||||
@@ -1,597 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "Common.h"
|
||||
#include "IniFile.h"
|
||||
#include "StringUtil.h"
|
||||
#include "Timer.h"
|
||||
#include "pluginspecs_wiimote.h"
|
||||
|
||||
#include "wiiuse.h"
|
||||
#include "WiimoteReal.h"
|
||||
|
||||
#include "../WiimoteEmu/WiimoteHid.h"
|
||||
|
||||
// used for pair up
|
||||
#ifdef _WIN32
|
||||
#include <bthdef.h>
|
||||
#include <BluetoothAPIs.h>
|
||||
#pragma comment(lib, "Bthprops.lib")
|
||||
#endif
|
||||
|
||||
unsigned int g_wiimote_sources[MAX_WIIMOTES];
|
||||
|
||||
namespace WiimoteReal
|
||||
{
|
||||
|
||||
bool g_real_wiimotes_initialized = false;
|
||||
wiimote_t** g_wiimotes_from_wiiuse = NULL;
|
||||
unsigned int g_wiimotes_found = 0;
|
||||
// removed g_wiimotes_lastfound because Refresh() isn't taking advantage of it
|
||||
|
||||
volatile bool g_run_wiimote_thread = false;
|
||||
Common::Thread *g_wiimote_threads[MAX_WIIMOTES] = {};
|
||||
Common::CriticalSection g_refresh_critsec;
|
||||
|
||||
|
||||
THREAD_RETURN WiimoteThreadFunc(void* arg);
|
||||
void StartWiimoteThreads();
|
||||
void StopWiimoteThreads();
|
||||
|
||||
Wiimote *g_wiimotes[MAX_WIIMOTES];
|
||||
|
||||
Wiimote::Wiimote(wiimote_t* const _wiimote, const unsigned int _index)
|
||||
: index(_index)
|
||||
, wiimote(_wiimote)
|
||||
, m_last_data_report(NULL)
|
||||
, m_channel(0)
|
||||
{
|
||||
// disable reporting
|
||||
DisableDataReporting();
|
||||
|
||||
// set LEDs
|
||||
wiiuse_set_leds(wiimote, WIIMOTE_LED_1 << index);
|
||||
|
||||
// TODO: make Dolphin connect wiimote, maybe
|
||||
}
|
||||
|
||||
Wiimote::~Wiimote()
|
||||
{
|
||||
ClearReadQueue();
|
||||
|
||||
// clear write queue
|
||||
Report rpt;
|
||||
while (m_write_reports.Pop(rpt))
|
||||
delete[] rpt.first;
|
||||
|
||||
// disable reporting / wiiuse might do this on shutdown anyway, o well, don't know for sure
|
||||
DisableDataReporting();
|
||||
}
|
||||
|
||||
// silly, copying data n stuff, o well, don't use this too often
|
||||
void Wiimote::SendPacket(const u8 rpt_id, const void* const data, const unsigned int size)
|
||||
{
|
||||
Report rpt;
|
||||
rpt.second = size + 2;
|
||||
rpt.first = new u8[rpt.second];
|
||||
rpt.first[0] = 0xA1;
|
||||
rpt.first[1] = rpt_id;
|
||||
memcpy(rpt.first + 2, data, size);
|
||||
m_write_reports.Push(rpt);
|
||||
}
|
||||
|
||||
void Wiimote::DisableDataReporting()
|
||||
{
|
||||
wm_report_mode rpt;
|
||||
rpt.mode = WM_REPORT_CORE;
|
||||
rpt.all_the_time = 0;
|
||||
rpt.continuous = 0;
|
||||
rpt.rumble = 0;
|
||||
SendPacket(WM_REPORT_MODE, &rpt, sizeof(rpt));
|
||||
}
|
||||
|
||||
void Wiimote::ClearReadQueue()
|
||||
{
|
||||
if (m_last_data_report)
|
||||
{
|
||||
delete[] m_last_data_report;
|
||||
m_last_data_report = NULL;
|
||||
}
|
||||
|
||||
u8 *rpt;
|
||||
while (m_read_reports.Pop(rpt))
|
||||
delete[] rpt;
|
||||
}
|
||||
|
||||
void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size)
|
||||
{
|
||||
// Check for custom communication
|
||||
if (99 == channel)
|
||||
Disconnect();
|
||||
else
|
||||
{
|
||||
InterruptChannel(channel, data, size);
|
||||
const hid_packet* const hidp = (hid_packet*)data;
|
||||
if (hidp->type == HID_TYPE_SET_REPORT)
|
||||
{
|
||||
u8 handshake_ok = HID_HANDSHAKE_SUCCESS;
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(index, channel, &handshake_ok, sizeof(handshake_ok));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Wiimote::InterruptChannel(const u16 channel, const void* const data, const u32 size)
|
||||
{
|
||||
if (0 == m_channel) // first interrupt/control channel sent
|
||||
{
|
||||
ClearReadQueue();
|
||||
|
||||
// request status
|
||||
wm_request_status rpt;
|
||||
rpt.rumble = 0;
|
||||
SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt));
|
||||
}
|
||||
|
||||
m_channel = channel; // this right?
|
||||
|
||||
Wiimote::Report rpt;
|
||||
rpt.first = new u8[size];
|
||||
rpt.second = (u8)size;
|
||||
memcpy(rpt.first, (u8*)data, size);
|
||||
|
||||
// some hax, since we just send the last data report to Dolphin on each Update() call
|
||||
// , make the wiimote only send updated data reports when data changes
|
||||
// == less bt traffic, eliminates some unneeded packets
|
||||
if (WM_REPORT_MODE == ((u8*)data)[1])
|
||||
{
|
||||
// also delete the last data report
|
||||
if (m_last_data_report)
|
||||
{
|
||||
delete[] m_last_data_report;
|
||||
m_last_data_report = NULL;
|
||||
}
|
||||
|
||||
// nice var names :p, this seems to be this one
|
||||
((wm_report_mode*)(rpt.first + 2))->all_the_time = false;
|
||||
//((wm_report_mode*)(data + 2))->continuous = false;
|
||||
}
|
||||
|
||||
m_write_reports.Push(rpt);
|
||||
}
|
||||
|
||||
bool Wiimote::Read()
|
||||
{
|
||||
if (wiiuse_io_read(wiimote))
|
||||
{
|
||||
if (m_channel)
|
||||
{
|
||||
// add it to queue
|
||||
u8* const rpt = new u8[MAX_PAYLOAD];
|
||||
memcpy(rpt, wiimote->event_buf, MAX_PAYLOAD);
|
||||
m_read_reports.Push(rpt);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Wiimote::Write()
|
||||
{
|
||||
Report rpt;
|
||||
if (m_write_reports.Pop(rpt))
|
||||
{
|
||||
wiiuse_io_write(wiimote, rpt.first, rpt.second);
|
||||
delete[] rpt.first;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns the next report that should be sent
|
||||
u8* Wiimote::ProcessReadQueue()
|
||||
{
|
||||
// pop through the queued reports
|
||||
u8* rpt = m_last_data_report;
|
||||
while (m_read_reports.Pop(rpt))
|
||||
{
|
||||
// a data report
|
||||
if (rpt[1] >= WM_REPORT_CORE)
|
||||
m_last_data_report = rpt;
|
||||
// some other kind of report
|
||||
else
|
||||
return rpt;
|
||||
}
|
||||
|
||||
// the queue was empty, or there were only data reports
|
||||
return rpt;
|
||||
}
|
||||
|
||||
void Wiimote::Update()
|
||||
{
|
||||
// pop through the queued reports
|
||||
u8* const rpt = ProcessReadQueue();
|
||||
|
||||
// send the report
|
||||
if (rpt && m_channel)
|
||||
g_WiimoteInitialize.pWiimoteInterruptChannel(index, m_channel, rpt, MAX_PAYLOAD);
|
||||
|
||||
// delete the data if it isn't also the last data rpt
|
||||
if (rpt != m_last_data_report)
|
||||
delete[] rpt;
|
||||
}
|
||||
|
||||
void Wiimote::Disconnect()
|
||||
{
|
||||
m_channel = 0;
|
||||
|
||||
// disable reporting
|
||||
DisableDataReporting();
|
||||
}
|
||||
|
||||
void LoadSettings()
|
||||
{
|
||||
std::string ini_filename = (std::string(File::GetUserPath(D_CONFIG_IDX)) + g_plugin.ini_name + ".ini" );
|
||||
|
||||
IniFile inifile;
|
||||
inifile.Load(ini_filename);
|
||||
|
||||
for (unsigned int i=0; i<MAX_WIIMOTES; ++i)
|
||||
{
|
||||
std::string secname("Wiimote");
|
||||
secname += (char)('1' + i);
|
||||
IniFile::Section& sec = *inifile.GetOrCreateSection(secname.c_str());
|
||||
|
||||
sec.Get("Source", &g_wiimote_sources[i], WIIMOTE_SRC_EMU);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Initialize()
|
||||
{
|
||||
// return if already initialized
|
||||
if (g_real_wiimotes_initialized)
|
||||
return g_wiimotes_found;
|
||||
|
||||
memset(g_wiimotes, 0, sizeof(g_wiimotes));
|
||||
|
||||
// only call wiiuse_find with the number of slots configured for real wiimotes
|
||||
unsigned int wanted_wiimotes = 0;
|
||||
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
|
||||
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i])
|
||||
++wanted_wiimotes;
|
||||
|
||||
// don't bother initializing wiiuse if we don't want any real wiimotes
|
||||
if (0 == wanted_wiimotes)
|
||||
{
|
||||
g_wiimotes_found = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialized
|
||||
g_real_wiimotes_initialized = true;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Alloc memory for wiimote structure only if we're starting fresh
|
||||
if(!g_wiimotes_from_wiiuse)
|
||||
g_wiimotes_from_wiiuse = wiiuse_init(MAX_WIIMOTES);
|
||||
// on windows wiiuse_find() expects as a 3rd parameter the amount of last connected wiimotes instead of the timeout,
|
||||
// a timeout parameter is useless on win32 here, since at this points we already have the wiimotes discovered and paired up, just not connected.
|
||||
g_wiimotes_found = wiiuse_find(g_wiimotes_from_wiiuse, wanted_wiimotes, 0);
|
||||
#else
|
||||
g_wiimotes_from_wiiuse = wiiuse_init(MAX_WIIMOTES);
|
||||
g_wiimotes_found = wiiuse_find(g_wiimotes_from_wiiuse, wanted_wiimotes, 5);
|
||||
#endif
|
||||
DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted",
|
||||
g_wiimotes_found, wanted_wiimotes);
|
||||
|
||||
g_wiimotes_found =
|
||||
wiiuse_connect(g_wiimotes_from_wiiuse, g_wiimotes_found);
|
||||
|
||||
DEBUG_LOG(WIIMOTE, "Connected to %i Real Wiimotes", g_wiimotes_found);
|
||||
|
||||
// create real wiimote class instances, assign wiimotes
|
||||
for (unsigned int i = 0, w = 0; i<MAX_WIIMOTES && w<g_wiimotes_found; ++i)
|
||||
{
|
||||
// create/assign wiimote
|
||||
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i])
|
||||
g_wiimotes[i] = new Wiimote(g_wiimotes_from_wiiuse[w++], i);
|
||||
}
|
||||
|
||||
StartWiimoteThreads();
|
||||
|
||||
return g_wiimotes_found;
|
||||
}
|
||||
|
||||
void Shutdown(void)
|
||||
{
|
||||
if (false == g_real_wiimotes_initialized)
|
||||
return;
|
||||
|
||||
// Uninitialized
|
||||
g_real_wiimotes_initialized = false;
|
||||
|
||||
StopWiimoteThreads();
|
||||
|
||||
// delete wiimotes
|
||||
for (unsigned int i=0; i<MAX_WIIMOTES; ++i)
|
||||
if (g_wiimotes[i])
|
||||
{
|
||||
delete g_wiimotes[i];
|
||||
g_wiimotes[i] = NULL;
|
||||
}
|
||||
|
||||
// Clean up wiiuse, win32: we cant just delete the struct on win32, since wiiuse_find() maintains it and
|
||||
// adds/removes wimotes directly to/from it to prevent problems, which would occur when using more than 1 wiimote if we create it from scratch everytime
|
||||
#ifndef _WIN32
|
||||
wiiuse_cleanup(g_wiimotes_from_wiiuse, MAX_WIIMOTES);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Refresh() // this gets called from the GUI thread
|
||||
{
|
||||
#ifdef __linux__
|
||||
// make sure real wiimotes have been initialized
|
||||
if (!g_real_wiimotes_initialized)
|
||||
{
|
||||
Initialize();
|
||||
return;
|
||||
}
|
||||
|
||||
// find the number of slots configured for real wiimotes
|
||||
unsigned int wanted_wiimotes = 0;
|
||||
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
|
||||
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i])
|
||||
++wanted_wiimotes;
|
||||
|
||||
// don't scan for wiimotes if we don't want any more
|
||||
if (wanted_wiimotes <= g_wiimotes_found)
|
||||
return;
|
||||
|
||||
// scan for wiimotes
|
||||
unsigned int num_wiimotes = wiiuse_find(g_wiimotes_from_wiiuse, wanted_wiimotes, 5);
|
||||
|
||||
DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted", num_wiimotes, wanted_wiimotes);
|
||||
|
||||
int num_new_wiimotes = wiiuse_connect(g_wiimotes_from_wiiuse, num_wiimotes);
|
||||
|
||||
DEBUG_LOG(WIIMOTE, "Connected to %i additional Real Wiimotes", num_new_wiimotes);
|
||||
|
||||
StopWiimoteThreads();
|
||||
|
||||
g_refresh_critsec.Enter();
|
||||
|
||||
// create real wiimote class instances, and assign wiimotes for the new wiimotes
|
||||
for (unsigned int i = g_wiimotes_found, w = g_wiimotes_found;
|
||||
i < MAX_WIIMOTES && w < num_wiimotes; ++i)
|
||||
{
|
||||
// create/assign wiimote
|
||||
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] && NULL == g_wiimotes[i])
|
||||
g_wiimotes[i] = new Wiimote(g_wiimotes_from_wiiuse[w++], i);
|
||||
}
|
||||
g_wiimotes_found = num_wiimotes;
|
||||
|
||||
g_refresh_critsec.Leave();
|
||||
|
||||
StartWiimoteThreads();
|
||||
|
||||
#else // windows/ OSX
|
||||
g_refresh_critsec.Enter();
|
||||
|
||||
// should be fine i think
|
||||
Shutdown();
|
||||
Initialize();
|
||||
|
||||
g_refresh_critsec.Leave();
|
||||
#endif
|
||||
}
|
||||
|
||||
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
g_refresh_critsec.Enter();
|
||||
|
||||
if (g_wiimotes[_WiimoteNumber])
|
||||
g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size);
|
||||
|
||||
g_refresh_critsec.Leave();
|
||||
}
|
||||
|
||||
void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
|
||||
{
|
||||
g_refresh_critsec.Enter();
|
||||
|
||||
if (g_wiimotes[_WiimoteNumber])
|
||||
g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size);
|
||||
|
||||
g_refresh_critsec.Leave();
|
||||
}
|
||||
|
||||
|
||||
// Read the Wiimote once
|
||||
void Update(int _WiimoteNumber)
|
||||
{
|
||||
g_refresh_critsec.Enter();
|
||||
|
||||
if (g_wiimotes[_WiimoteNumber])
|
||||
g_wiimotes[_WiimoteNumber]->Update();
|
||||
|
||||
g_refresh_critsec.Leave();
|
||||
}
|
||||
|
||||
void StateChange(PLUGIN_EMUSTATE newState)
|
||||
{
|
||||
//g_refresh_critsec.Enter(); // enter
|
||||
|
||||
// TODO: disable/enable auto reporting, maybe
|
||||
|
||||
//g_refresh_critsec.Leave(); // leave
|
||||
}
|
||||
|
||||
void StartWiimoteThreads()
|
||||
{
|
||||
g_run_wiimote_thread = true;
|
||||
for (unsigned int i=0; i<MAX_WIIMOTES; ++i)
|
||||
if (g_wiimotes[i])
|
||||
g_wiimote_threads[i] = new Common::Thread(WiimoteThreadFunc, g_wiimotes[i]);
|
||||
}
|
||||
|
||||
void StopWiimoteThreads()
|
||||
{
|
||||
g_run_wiimote_thread = false;
|
||||
for (unsigned int i=0; i<MAX_WIIMOTES; ++i)
|
||||
if (g_wiimote_threads[i])
|
||||
{
|
||||
g_wiimote_threads[i]->WaitForDeath();
|
||||
delete g_wiimote_threads[i];
|
||||
g_wiimote_threads[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
THREAD_RETURN WiimoteThreadFunc(void* arg)
|
||||
{
|
||||
Wiimote* const wiimote = (Wiimote*)arg;
|
||||
|
||||
{
|
||||
char thname[] = "Wiimote # Thread";
|
||||
thname[8] = (char)('1' + wiimote->index);
|
||||
Common::SetCurrentThreadName(thname);
|
||||
}
|
||||
|
||||
// rumble briefly
|
||||
wiiuse_rumble(wiimote->wiimote, 1);
|
||||
SLEEP(200);
|
||||
wiiuse_rumble(wiimote->wiimote, 0);
|
||||
|
||||
// main loop
|
||||
while (g_run_wiimote_thread)
|
||||
{
|
||||
// hopefully this is alright
|
||||
while (wiimote->Write()) {}
|
||||
|
||||
// sleep if there was nothing to read
|
||||
if (false == wiimote->Read())
|
||||
Common::SleepCurrentThread(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// WiiMote Pair-Up, function will return amount of either new paired or unpaired devices
|
||||
// negative number on failure
|
||||
int PairUp(bool unpair)
|
||||
{
|
||||
int nPaired = 0;
|
||||
|
||||
BLUETOOTH_DEVICE_SEARCH_PARAMS srch;
|
||||
srch.dwSize = sizeof(srch);
|
||||
srch.fReturnAuthenticated = true;
|
||||
srch.fReturnRemembered = true;
|
||||
srch.fReturnConnected = true; // does not filter properly somehow, so we've to do an additional check on fConnected BT Devices
|
||||
srch.fReturnUnknown = true;
|
||||
srch.fIssueInquiry = true;
|
||||
srch.cTimeoutMultiplier = 2; // == (2 * 1.28) seconds
|
||||
|
||||
BLUETOOTH_FIND_RADIO_PARAMS radioParam;
|
||||
radioParam.dwSize = sizeof(radioParam);
|
||||
|
||||
HANDLE hRadio;
|
||||
|
||||
// Enumerate BT radios
|
||||
HBLUETOOTH_RADIO_FIND hFindRadio = BluetoothFindFirstRadio(&radioParam, &hRadio);
|
||||
|
||||
if (NULL == hFindRadio)
|
||||
return -1;
|
||||
|
||||
while (hFindRadio)
|
||||
{
|
||||
BLUETOOTH_RADIO_INFO radioInfo;
|
||||
radioInfo.dwSize = sizeof(radioInfo);
|
||||
|
||||
// TODO: check for SUCCEEDED()
|
||||
BluetoothGetRadioInfo(hRadio, &radioInfo);
|
||||
|
||||
srch.hRadio = hRadio;
|
||||
|
||||
BLUETOOTH_DEVICE_INFO btdi;
|
||||
btdi.dwSize = sizeof(btdi);
|
||||
|
||||
// Enumerate BT devices
|
||||
HBLUETOOTH_DEVICE_FIND hFindDevice = BluetoothFindFirstDevice(&srch, &btdi);
|
||||
while (hFindDevice)
|
||||
{
|
||||
//btdi.szName is sometimes missings it's content - it's a bt feature..
|
||||
DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ", btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered);
|
||||
|
||||
// TODO: Probably could just check for "Nintendo RVL"
|
||||
if (0 == wcscmp(btdi.szName, L"Nintendo RVL-WBC-01") || 0 == wcscmp(btdi.szName, L"Nintendo RVL-CNT-01"))
|
||||
{
|
||||
if (unpair)
|
||||
{
|
||||
if (SUCCEEDED(BluetoothRemoveDevice(&btdi.Address)))
|
||||
{
|
||||
NOTICE_LOG(WIIMOTE, "Pair-Up: Automatically removed BT Device on shutdown: %08x", GetLastError());
|
||||
++nPaired;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (false == btdi.fConnected)
|
||||
{
|
||||
//TODO: improve the read of the BT driver, esp. when batteries of the wiimote are removed while being fConnected
|
||||
if (btdi.fRemembered)
|
||||
{
|
||||
// Make Windows forget old expired pairing
|
||||
// we can pretty much ignore the return value here.
|
||||
// it either worked (ERROR_SUCCESS), or the device did not exist (ERROR_NOT_FOUND)
|
||||
// in both cases, there is nothing left.
|
||||
BluetoothRemoveDevice(&btdi.Address);
|
||||
}
|
||||
|
||||
// Activate service
|
||||
const DWORD hr = BluetoothSetServiceState(hRadio, &btdi, &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE);
|
||||
if (SUCCEEDED(hr))
|
||||
++nPaired;
|
||||
else
|
||||
ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (false == BluetoothFindNextDevice(hFindDevice, &btdi))
|
||||
{
|
||||
BluetoothFindDeviceClose(hFindDevice);
|
||||
hFindDevice = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (false == BluetoothFindNextRadio(hFindRadio, &hRadio))
|
||||
{
|
||||
BluetoothFindRadioClose(hFindRadio);
|
||||
hFindRadio = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return nPaired;
|
||||
}
|
||||
#endif
|
||||
|
||||
}; // end of namespace
|
||||
@@ -1,105 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#ifndef WIIMOTE_REAL_H
|
||||
#define WIIMOTE_REAL_H
|
||||
|
||||
#include "wiiuse.h"
|
||||
#include "ChunkFile.h"
|
||||
#include "Thread.h"
|
||||
#include "FifoQueue.h"
|
||||
#include "../WiimoteEmu/WiimoteEmu.h"
|
||||
|
||||
#include "../../InputCommon/Src/InputConfig.h"
|
||||
|
||||
#define MAX_WIIMOTES 4
|
||||
|
||||
extern unsigned int g_wiimote_sources[MAX_WIIMOTES];
|
||||
extern InputPlugin g_plugin;
|
||||
extern SWiimoteInitialize g_WiimoteInitialize;
|
||||
|
||||
enum
|
||||
{
|
||||
WIIMOTE_SRC_NONE = 0,
|
||||
WIIMOTE_SRC_EMU = 1,
|
||||
WIIMOTE_SRC_REAL = 2,
|
||||
WIIMOTE_SRC_HYBRID = 3, // emu + real
|
||||
};
|
||||
|
||||
namespace WiimoteReal
|
||||
{
|
||||
|
||||
class Wiimote
|
||||
{
|
||||
friend class WiimoteEmu::Wiimote;
|
||||
public:
|
||||
Wiimote(wiimote_t* const wm, const unsigned int index);
|
||||
~Wiimote();
|
||||
|
||||
void ControlChannel(const u16 channel, const void* const data, const u32 size);
|
||||
void InterruptChannel(const u16 channel, const void* const data, const u32 size);
|
||||
void Update();
|
||||
|
||||
u8* ProcessReadQueue();
|
||||
|
||||
bool Read();
|
||||
bool Write();
|
||||
void Disconnect();
|
||||
void DisableDataReporting();
|
||||
|
||||
void SendPacket(const u8 rpt_id, const void* const data, const unsigned int size);
|
||||
|
||||
// pointer to data, and size of data
|
||||
typedef std::pair<u8*,u8> Report;
|
||||
|
||||
const unsigned int index;
|
||||
wiimote_t* const wiimote;
|
||||
|
||||
protected:
|
||||
u8 *m_last_data_report;
|
||||
u16 m_channel;
|
||||
|
||||
private:
|
||||
void ClearReadQueue();
|
||||
|
||||
Common::FifoQueue<u8*> m_read_reports;
|
||||
Common::FifoQueue<Report> m_write_reports;
|
||||
};
|
||||
|
||||
extern Common::CriticalSection g_refresh_critsec;
|
||||
extern Wiimote *g_wiimotes[4];
|
||||
|
||||
unsigned int Initialize();
|
||||
void Shutdown();
|
||||
void Refresh();
|
||||
void LoadSettings();
|
||||
|
||||
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
|
||||
void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
|
||||
void Update(int _WiimoteNumber);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
void StateChange(PLUGIN_EMUSTATE newState);
|
||||
|
||||
#ifdef _WIN32
|
||||
int PairUp(bool unpair = false);
|
||||
#endif
|
||||
|
||||
}; // WiiMoteReal
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user