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:
Jordan Woyak 2010-10-12 19:42:29 +00:00
commit 7e08fc19fc
116 changed files with 661 additions and 14529 deletions

View file

@ -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>

View file

@ -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()");
}

View file

@ -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

View file

@ -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));
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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_

View file

@ -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_

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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_

View file

@ -1,296 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// Copyright (C) Hector Martin "marcan" (hector@marcansoft.com)
// 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];
}

View file

@ -1,40 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// Copyright (C) Hector Martin "marcan" (hector@marcansoft.com)
// 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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'])

View file

@ -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();
}

View file

@ -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

View file

@ -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. */
// -----------------

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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="&quot;..\..\..\Externals\SDL\$(PlatformName)&quot;;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;;../../../Externals/OpenAL/Win32/;&quot;..\..\..\Externals\WiiUse\$(PlatformName)&quot;"
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="&quot;..\..\..\Externals\SDL\$(PlatformName)&quot;;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;;../../../Externals/OpenAL/Win64/;&quot;..\..\..\Externals\WiiUse\$(PlatformName)&quot;"
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="&quot;..\..\..\Externals\SDL\$(PlatformName)&quot;;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;;../../../Externals/OpenAL/Win32/;&quot;..\..\..\Externals\WiiUse\$(PlatformName)&quot;"
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="&quot;..\..\..\Externals\SDL\$(PlatformName)&quot;;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;;../../../Externals/OpenAL/Win64/;&quot;..\..\..\Externals\WiiUse\$(PlatformName)&quot;"
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="&quot;..\..\..\Externals\SDL\$(PlatformName)&quot;;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;;../../../Externals/OpenAL/Win32/;&quot;..\..\..\Externals\WiiUse\$(PlatformName)&quot;"
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="&quot;..\..\..\Externals\SDL\$(PlatformName)&quot;;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;;../../../Externals/OpenAL/Win64/;&quot;..\..\..\Externals\WiiUse\$(PlatformName)&quot;"
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>

View file

@ -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'])

View file

@ -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();
}

View file

@ -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

View file

@ -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( &reg[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 );
}

View file

@ -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

View file

@ -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( &reg[0x20], classic_calibration, sizeof(classic_calibration) );
// id
memcpy( &reg[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;
}
}

View file

@ -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;
};
}

View file

@ -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( &reg[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;
}
}

View file

@ -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;
};
}

View file

@ -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( &reg[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;
}
}

View file

@ -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;
};
}

View file

@ -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(&reg[0x20], nunchuck_calibration, sizeof(nunchuck_calibration));
// id
memcpy(&reg[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*)&reg[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));
}
}

View file

@ -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

View file

@ -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(&reg[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
);
}
}

View file

@ -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;
};
}

View file

@ -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);
}
}

View file

@ -1,295 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// Copyright (C) Hector Martin "marcan" (hector@marcansoft.com)
// 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];
}

View file

@ -1,41 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// Copyright (C) Hector Martin "marcan" (hector@marcansoft.com)
// 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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