Commited my new wiimote plugin work so far. Some code was copied from the current wiimote plugin. I have cleaned up most of the functions, but there are still a bunch of unused structs and stuff that I need to clean up.

Moved ControllerInterface to InputCommon. Moved GCPadNew GUI/Config code to a new project, InputPluginCommon. It is used by both GCPadNew and WiimoteNew. I hope that I included everyone's fixes to GCPadNew and ControllerInterface.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5355 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Jordan Woyak 2010-04-13 05:15:38 +00:00
parent 9592da1a9b
commit d8906d2a0c
53 changed files with 4398 additions and 931 deletions

View File

@ -408,6 +408,74 @@
<References>
</References>
<Files>
<Filter
Name="ControllerInterface"
>
<File
RelativePath=".\Src\ControllerInterface\ControllerInterface.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\ControllerInterface.h"
>
</File>
<Filter
Name="DirectInput"
>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInput.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInput.h"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputJoystick.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputJoystick.h"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputKeyboardMouse.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputKeyboardMouse.h"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\NamedKeys.h"
>
</File>
</Filter>
<Filter
Name="SDL"
>
<File
RelativePath=".\Src\ControllerInterface\SDL\SDL.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\SDL\SDL.h"
>
</File>
</Filter>
<Filter
Name="XInput"
>
<File
RelativePath=".\Src\ControllerInterface\XInput\XInput.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\XInput\XInput.h"
>
</File>
</Filter>
</Filter>
<File
RelativePath=".\Src\Configuration.cpp"
>

View File

@ -40,7 +40,7 @@ void ControllerInterface::Init()
ciface::DirectInput::Init( m_devices/*, (HWND)m_hwnd*/ );
#endif
#ifdef CIFACE_USE_XLIB
ciface::Xlib::Init( m_devices, m_hwnd );
ciface::XLIB::Init( m_devices, m_hwnd );
#endif
#ifdef CIFACE_USE_OSX
ciface::OSX::Init( m_devices, m_hwnd );
@ -238,7 +238,7 @@ ControlState ControllerInterface::InputReference::State( const ControlState igno
if ( NULL == device )
return 0;
ControlState state = 0;
ControlState state;
// this mode thing will be turned into a switch statement
switch ( mode )
{
@ -360,7 +360,11 @@ void ControllerInterface::DeviceQualifier::FromDevice(const ControllerInterface:
//
bool ControllerInterface::DeviceQualifier::operator==(const ControllerInterface::Device* const dev) const
{
return (dev->GetName() == name) && (dev->GetId() == cid) && (dev->GetSource() == source);
if ( dev->GetName() == name )
if ( dev->GetId() == cid )
if ( dev->GetSource() == source )
return true;
return false;
}
//

View File

@ -377,12 +377,10 @@ std::string Joystick::GetSource() const
// update IO
bool Joystick::UpdateInput()
{
if ( m_must_poll )
m_device->Poll();
//return false;
HRESULT hr = m_device->GetDeviceState( sizeof(m_state_in), &m_state_in );

View File

@ -189,8 +189,8 @@ bool KeyboardMouse::UpdateOutput()
m_current_state_out[i] ^= 1;
}
}
if ( kbinputs.size() )
if (kbinputs.size())
return ( kbinputs.size() == SendInput( (UINT)kbinputs.size(), &kbinputs[0], sizeof( kbinputs[0] ) ) );
else
return true;

View File

@ -1,101 +1,101 @@
#include "../ControllerInterface.h"
#ifdef CIFACE_USE_OSX
#include "OSX.h"
#include "OSXPrivate.h"
namespace ciface
{
namespace OSX
{
void Init( std::vector<ControllerInterface::Device*>& devices, void* hwnd )
{
// mouse will be added to this, Keyboard class will be turned into KeyboardMouse
// single device for combined keyboard/mouse, this will allow combinations like shift+click more easily
//devices.push_back( new Keyboard( hwnd ) );
}
Keyboard::Keyboard( void *View )
{
memset( &m_state, 0, sizeof(m_state) );
OSX_Init(View);
// This is REALLY dumb right here
// Should REALLY cover the entire UTF-8 Range
for (int a = 0; a < 256; ++a)
inputs.push_back( new Key( (char)a ) );
}
Keyboard::~Keyboard()
{
// might not need this func
}
ControlState Keyboard::GetInputState( const ControllerInterface::Device::Input* const input )
{
return ((Input*)input)->GetState( &m_state );
}
void Keyboard::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state )
{
}
bool Keyboard::UpdateInput()
{
memset(m_state.keyboard, 0, 256);
OSX_UpdateKeys(256, m_state.keyboard );
// mouse stuff in here too
return true;
}
bool Keyboard::UpdateOutput()
{
return true;
}
std::string Keyboard::GetName() const
{
return "Keyboard";
//return "Keyboard Mouse"; // change to this later
}
std::string Keyboard::GetSource() const
{
return "OSX";
}
int Keyboard::GetId() const
{
return 0;
}
ControlState Keyboard::Key::GetState( State* const state )
{
for(unsigned int a = 0; a < 256; ++a)
if(state->keyboard[a] == m_index)
return true;
return false;
}
std::string Keyboard::Key::GetName() const
{
char temp[16];
sprintf(temp, "Key:%c", m_index);
return std::string(temp);
}
}
}
#endif
#include "../ControllerInterface.h"
#ifdef CIFACE_USE_OSX
#include "OSX.h"
#include "OSXPrivate.h"
namespace ciface
{
namespace OSX
{
void Init( std::vector<ControllerInterface::Device*>& devices, void* hwnd )
{
// mouse will be added to this, Keyboard class will be turned into KeyboardMouse
// single device for combined keyboard/mouse, this will allow combinations like shift+click more easily
//devices.push_back( new Keyboard( hwnd ) );
}
Keyboard::Keyboard( void *View )
{
memset( &m_state, 0, sizeof(m_state) );
OSX_Init(View);
// This is REALLY dumb right here
// Should REALLY cover the entire UTF-8 Range
for (int a = 0; a < 256; ++a)
inputs.push_back( new Key( (char)a ) );
}
Keyboard::~Keyboard()
{
// might not need this func
}
ControlState Keyboard::GetInputState( const ControllerInterface::Device::Input* const input )
{
return ((Input*)input)->GetState( &m_state );
}
void Keyboard::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state )
{
}
bool Keyboard::UpdateInput()
{
memset(m_state.keyboard, 0, 256);
OSX_UpdateKeys(256, m_state.keyboard );
// mouse stuff in here too
return true;
}
bool Keyboard::UpdateOutput()
{
return true;
}
std::string Keyboard::GetName() const
{
return "Keyboard";
//return "Keyboard Mouse"; // change to this later
}
std::string Keyboard::GetSource() const
{
return "OSX";
}
int Keyboard::GetId() const
{
return 0;
}
ControlState Keyboard::Key::GetState( State* const state )
{
for(unsigned int a = 0; a < 256; ++a)
if(state->keyboard[a] == m_index)
return true;
return false;
}
std::string Keyboard::Key::GetName() const
{
char temp[16];
sprintf(temp, "Key:%c", m_index);
return std::string(temp);
}
}
}
#endif

View File

@ -1,68 +1,68 @@
#ifndef _CIFACE_OSX_H_
#define _CIFACE_OSX_H_
#include "../ControllerInterface.h"
namespace ciface
{
namespace OSX
{
void Init( std::vector<ControllerInterface::Device*>& devices, void* hwnd );
class Keyboard : public ControllerInterface::Device
{
friend class ControllerInterface;
friend class ControllerInterface::ControlReference;
protected:
struct State
{
char keyboard[256]; // really dumb
// mouse crap will go here
};
class Input : public ControllerInterface::Device::Input
{
friend class Keyboard;
protected:
Input( const unsigned char index ) : m_index(index) {}
virtual ControlState GetState( State* const js ) = 0;
const unsigned char m_index;
};
class Key : public Input
{
friend class Keyboard;
public:
std::string GetName() const;
protected:
Key( const unsigned char key ) : Input(key) {}
ControlState GetState( State* const js );
};
bool UpdateInput();
bool UpdateOutput();
ControlState GetInputState( const ControllerInterface::Device::Input* const input );
void SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state );
public:
Keyboard( void* view );
~Keyboard();
std::string GetName() const;
std::string GetSource() const;
int GetId() const;
private:
State m_state;
};
}
}
#endif
#ifndef _CIFACE_OSX_H_
#define _CIFACE_OSX_H_
#include "../ControllerInterface.h"
namespace ciface
{
namespace OSX
{
void Init( std::vector<ControllerInterface::Device*>& devices, void* hwnd );
class Keyboard : public ControllerInterface::Device
{
friend class ControllerInterface;
friend class ControllerInterface::ControlReference;
protected:
struct State
{
char keyboard[256]; // really dumb
// mouse crap will go here
};
class Input : public ControllerInterface::Device::Input
{
friend class Keyboard;
protected:
Input( const unsigned char index ) : m_index(index) {}
virtual ControlState GetState( State* const js ) = 0;
const unsigned char m_index;
};
class Key : public Input
{
friend class Keyboard;
public:
std::string GetName() const;
protected:
Key( const unsigned char key ) : Input(key) {}
ControlState GetState( State* const js );
};
bool UpdateInput();
bool UpdateOutput();
ControlState GetInputState( const ControllerInterface::Device::Input* const input );
void SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state );
public:
Keyboard( void* view );
~Keyboard();
std::string GetName() const;
std::string GetSource() const;
int GetId() const;
private:
State m_state;
};
}
}
#endif

View File

@ -148,7 +148,15 @@ bool Device::UpdateInput()
bool Device::UpdateOutput()
{
return ( ERROR_SUCCESS == XInputSetState( m_index, &m_state_out ) );
// this if statement is to make rumble work better when multiple ControllerInterfaces are using the device
static XINPUT_VIBRATION current_state_out = {0,0};
if ( memcmp( &m_state_out, &current_state_out, sizeof(m_state_out) ) )
{
current_state_out = m_state_out;
return ( ERROR_SUCCESS == XInputSetState( m_index, &m_state_out ) );
}
else
return true;
}
// GET name/source/id

View File

@ -0,0 +1,450 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="InputPluginCommon"
ProjectGUID="{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}"
RootNamespace="VideoCommon"
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="4"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../Core/InputCommon/Src;../../Core/Common/Src;../../PluginSpecs;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\wxWidgets\lib\vc_lib\msw;..\..\..\Externals\wxWidgets\include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
BufferSecurityCheck="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../Core/InputCommon/Src;../../Core/Common/Src;../../PluginSpecs;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\wxWidgets\lib\vc_lib\msw;..\..\..\Externals\wxWidgets\include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_SECURE_SCL=0;_LIB;__WXMSW__;wxUSE_BASE=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
BufferSecurityCheck="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../../Core/InputCommon/Src;../../Core/Common/Src;../../PluginSpecs;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\wxWidgets\lib\vc_lib\msw;..\..\..\Externals\wxWidgets\include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
StringPooling="true"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2"
FloatingPointModel="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="false"
AdditionalIncludeDirectories="../../Core/InputCommon/Src;../../Core/Common/Src;../../PluginSpecs;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\wxWidgets\lib\vc_lib\msw;..\..\..\Externals\wxWidgets\include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
BufferSecurityCheck="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\$(ProjectName).lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="DebugFast|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../Core/InputCommon/Src;../../Core/Common/Src;../../PluginSpecs;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\wxWidgets\lib\vc_lib\msw;..\..\..\Externals\wxWidgets\include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
BufferSecurityCheck="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="DebugFast|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
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="../../Core/InputCommon/Src;../../Core/Common/Src;../../PluginSpecs;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\wxWidgets\lib\vc_lib\msw;..\..\..\Externals\wxWidgets\include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_SECURE_SCL=0;__WXMSW__;wxUSE_BASE=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
BufferSecurityCheck="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\Src\Config.cpp"
>
</File>
<File
RelativePath=".\Src\Config.h"
>
</File>
<File
RelativePath=".\Src\ConfigDiag.cpp"
>
</File>
<File
RelativePath=".\Src\ConfigDiag.h"
>
</File>
<File
RelativePath=".\Src\ConfigDiagBitmaps.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerEmu.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerEmu.h"
>
</File>
<File
RelativePath=".\Src\IniFile.cpp"
>
</File>
<File
RelativePath=".\Src\IniFile.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -1,11 +1,14 @@
#include "Config.h"
Plugin::Plugin()
Plugin::Plugin( const char* const _ini_name, const char* const _gui_name, const char* const _profile_name )
: ini_name(_ini_name)
, gui_name(_gui_name)
, profile_name(_profile_name)
{
// GCPads
for ( unsigned int i = 0; i<4; ++i )
controllers.push_back( new GCPad( i ) );
//for ( unsigned int i = 0; i<4; ++i )
//controllers.push_back( new GCPad( i ) );
// Wiimotes / disabled, cause it only the GUI half is done
//for ( unsigned int i = 0; i<4; ++i )
// controllers.push_back( new Wiimote( i ) );
@ -25,7 +28,7 @@ void Plugin::LoadConfig()
IniFile inifile;
std::ifstream file;
file.open( (std::string(File::GetUserPath(D_CONFIG_IDX)) + CONFIG_FILE_NAME ).c_str() );
file.open( (std::string(File::GetUserPath(D_CONFIG_IDX)) + ini_name + ".ini" ).c_str() );
inifile.Load( file );
file.close();
@ -48,7 +51,7 @@ void Plugin::SaveConfig()
inifile.Clean();
std::ofstream file;
file.open( (std::string(File::GetUserPath(D_CONFIG_IDX)) + CONFIG_FILE_NAME ).c_str() );
file.open( (std::string(File::GetUserPath(D_CONFIG_IDX)) + ini_name + ".ini" ).c_str() );
inifile.Save( file );
file.close();
}

View File

@ -1,16 +1,12 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define CONFIG_FILE_NAME "GCPadNew.ini"
#include "ControllerInterface/ControllerInterface.h"
#include <ControllerInterface/ControllerInterface.h>
#include "Thread.h"
#include "FileUtil.h"
#include "IniFile.h"
#include "ControllerEmu.h"
#include "ControllerEmu/GCPad/GCPad.h"
#include "ControllerEmu/Wiimote/Wiimote.h"
#include <string>
#include <vector>
@ -21,7 +17,7 @@ class Plugin
{
public:
Plugin();
Plugin( const char* const _ini_name, const char* const _gui_name, const char* const _profile_name );
~Plugin();
void LoadConfig();
@ -31,6 +27,10 @@ public:
Common::CriticalSection controls_crit, interface_crit; // lock controls first
ControllerInterface controller_interface;
const char * const ini_name;
const char * const gui_name;
const char * const profile_name;
};
#endif

View File

@ -1,9 +1,64 @@
#include "ConfigDiag.h"
#define _connect_macro_( b, f, c, s ) (b)->Connect( wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s );
void GamepadPage::ConfigExtension( wxCommandEvent& event )
{
ControllerEmu::Extension* const ex = ((ExtensionButton*)event.GetEventObject())->extension;
// show config diag, if "none" isn't selected
if ( ex->switch_extension )
{
wxDialog* const dlg = new wxDialog( this, -1, wxString::FromAscii(ex->attachments[ex->switch_extension]->GetName().c_str()), wxDefaultPosition );
wxPanel* const pnl = new wxPanel( dlg, -1, wxDefaultPosition );
wxBoxSizer* const pnl_szr = new wxBoxSizer( wxHORIZONTAL );
const std::size_t orig_size = control_groups.size();
ControlGroupsSizer* const szr = new ControlGroupsSizer( ex->attachments[ex->switch_extension], pnl, this, &control_groups );
pnl->SetSizerAndFit( szr );
pnl_szr->Add( pnl, 0, wxLEFT, 5 );
dlg->SetSizerAndFit( pnl_szr );
dlg->Center();
dlg->ShowModal();
dlg->Destroy();
// remove the new groups that were just added, now that the window closed
control_groups.resize( orig_size );
}
}
PadSettingExtension::PadSettingExtension( wxWindow* const parent, ControllerEmu::Extension* const ext )
: wxChoice( parent, -1 )
, extension(ext)
{
std::vector<ControllerEmu*>::const_iterator
i = extension->attachments.begin(),
e = extension->attachments.end();
for ( ; i!=e; ++i )
Append( wxString::FromAscii( (*i)->GetName().c_str() ) );
UpdateGUI();
}
void PadSettingExtension::UpdateGUI()
{
Select( extension->switch_extension );
}
void PadSettingExtension::UpdateValue()
{
extension->switch_extension = GetSelection();
}
PadSettingCheckBox::PadSettingCheckBox( wxWindow* const parent, ControlState& _value, const char* const label )
: PadSetting(_value)
, wxCheckBox( parent, -1, wxString::FromAscii( label ), wxDefaultPosition )
: wxCheckBox( parent, -1, wxString::FromAscii( label ), wxDefaultPosition )
, value(_value)
{
UpdateGUI();
}
@ -20,8 +75,8 @@ void PadSettingCheckBox::UpdateValue()
}
PadSettingChoice::PadSettingChoice( wxWindow* const parent, ControlState& _value, int min, int max )
: PadSetting(_value)
, wxChoice( parent, -1, wxDefaultPosition, wxSize( 54, -1 ) )
: wxChoice( parent, -1, wxDefaultPosition, wxSize( 54, -1 ) )
, value(_value)
{
Append( wxT("0") );
for ( ; min<=max; ++min )
@ -53,10 +108,10 @@ ControlDialog::ControlDialog( wxWindow* const parent, ControllerInterface::Contr
device_cbox = new wxComboBox( this, -1, wxString::FromAscii( ref->device_qualifier.ToString().c_str() ), wxDefaultPosition, wxSize(256,-1), wxArrayString(), wxTE_PROCESS_ENTER );
#define _connect_macro2_( b, f, c ) (b)->Connect( wxID_ANY, c, wxCommandEventHandler( GamepadPage::f ), (wxObject*)0, (wxEvtHandler*)parent );
//#define _connect_macro2_( b, f, c ) (b)->Connect( wxID_ANY, c, wxCommandEventHandler( GamepadPage::f ), (wxObject*)0, (wxEvtHandler*)parent );
_connect_macro2_( device_cbox, SetDevice, wxEVT_COMMAND_COMBOBOX_SELECTED );
_connect_macro2_( device_cbox, SetDevice, wxEVT_COMMAND_TEXT_ENTER );
_connect_macro_( device_cbox, GamepadPage::SetDevice, wxEVT_COMMAND_COMBOBOX_SELECTED, parent );
_connect_macro_( device_cbox, GamepadPage::SetDevice, wxEVT_COMMAND_TEXT_ENTER, parent );
std::vector< ControllerInterface::Device* >::const_iterator i = devs.begin(),
e = devs.end();
@ -93,7 +148,7 @@ ControlButton::ControlButton( wxWindow* const parent, ControllerInterface::Contr
void ConfigDialog::UpdateProfileComboBox()
{
std::string pname( File::GetUserPath(D_CONFIG_IDX) );
pname += PROFILES_PATH;
pname += PROFILES_PATH; pname += m_plugin.profile_name;
CFileSearch::XStringVector exts;
exts.push_back("*.ini");
@ -185,24 +240,21 @@ void ControlChooser::UpdateGUI()
void GamepadPage::UpdateGUI()
{
device_cbox->SetLabel( wxString::FromAscii( controller->default_device.ToString().c_str() ) );
device_cbox->SetValue( wxString::FromAscii( controller->default_device.ToString().c_str() ) );
std::vector< ControlGroupBox* >::const_iterator
g = control_groups.begin(),
std::vector< ControlGroupBox* >::const_iterator g = control_groups.begin(),
ge = control_groups.end();
for ( ; g!=ge; ++g )
{
// buttons
std::vector<ControlButton*>::const_iterator
i = (*g)->control_buttons.begin(),
e = (*g)->control_buttons.end();
std::vector<ControlButton*>::const_iterator i = (*g)->control_buttons.begin()
, e = (*g)->control_buttons.end();
for ( ; i!=e; ++i )
(*i)->SetLabel( wxString::FromAscii( (*i)->control_reference->control_qualifier.name.c_str() ) );
// settings
std::vector<PadSetting*>::const_iterator
si = (*g)->options.begin(),
se = (*g)->options.end();
// cboxes
std::vector<PadSetting*>::const_iterator si = (*g)->options.begin()
, se = (*g)->options.end();
for ( ; si!=se; ++si )
(*si)->UpdateGUI();
}
@ -213,12 +265,12 @@ void GamepadPage::ClearAll( wxCommandEvent& event )
m_plugin.controls_crit.Enter(); // enter
// just load an empty ini section to clear everything :P
IniSection Section = IniSection();
ControllerInterface Face = ControllerInterface();
controller->LoadConfig( Section );
IniSection section;
controller->LoadConfig( section );
// no point in using the real ControllerInterface i guess
controller->UpdateReferences( Face );
ControllerInterface face;
controller->UpdateReferences( face );
UpdateGUI();
@ -229,7 +281,8 @@ void GamepadPage::SetControl( wxCommandEvent& event )
{
m_plugin.controls_crit.Enter(); // enter
m_control_dialog->control_reference->control_qualifier.name = std::string( m_control_dialog->control_chooser->textctrl->GetValue().ToAscii() );
m_control_dialog->control_reference->control_qualifier.name =
std::string( m_control_dialog->control_chooser->textctrl->GetValue().ToAscii() );
m_control_dialog->control_reference->UpdateControls();
m_control_dialog->control_chooser->UpdateGUI();
@ -356,18 +409,15 @@ void ControlDialog::SelectControl( wxCommandEvent& event )
wxString final_label;
if (sels.GetCount() == 0)
return;
if ( sels.GetCount() == 1 )
if (sels.GetCount() == 1)
final_label = names[ sels[0] ];
//else if ( sels.GetCount() == lb->GetCount() )
//else if ( sels.size() == lb->GetCount() )
// final_label = "||";
else
{
final_label = wxT('|');
for ( unsigned int i=0; i<sels.GetCount(); ++i )
final_label += names[ sels[i] ] + wxT('|');
final_label = wxT('|');
for ( unsigned int i=0; i<sels.GetCount(); ++i )
final_label += names[ sels[i] ] + wxT('|');
}
control_chooser->textctrl->SetValue( final_label );
@ -375,14 +425,14 @@ void ControlDialog::SelectControl( wxCommandEvent& event )
// kinda dumb
wxCommandEvent nullevent;
((GamepadPage*)m_parent)->SetControl( nullevent );
}
ControlChooser::ControlChooser( wxWindow* const parent, ControllerInterface::ControlReference* const ref, wxWindow* const eventsink )
: wxStaticBoxSizer( wxVERTICAL, parent, ref->is_input ? wxT("Input") : wxT("Output") )
, control_reference(ref)
{
#define _connect_macro_( b, f, c ) (b)->Connect( wxID_ANY, (c), wxCommandEventHandler( GamepadPage::f ), (wxObject*)0, (wxEvtHandler*)eventsink );
//#define _connect_macro_( b, f, c ) (b)->Connect( wxID_ANY, (c), wxCommandEventHandler( GamepadPage::f ), (wxObject*)0, (wxEvtHandler*)eventsink );
textctrl = new wxTextCtrl( parent, -1 );
wxButton* detect_button = new wxButton( parent, -1, ref->is_input ? wxT("Detect 1") : wxT("Test") );
@ -399,7 +449,7 @@ ControlChooser::ControlChooser( wxWindow* const parent, ControllerInterface::Con
for ( unsigned int i = 2; i<5; ++i )
{
wxButton* d_btn = new wxButton( parent, -1, wxChar( '0'+i ), wxDefaultPosition, wxSize(20,-1) );
_connect_macro_( d_btn, ConfigDetectControl, wxEVT_COMMAND_BUTTON_CLICKED);
_connect_macro_( d_btn, GamepadPage::ConfigDetectControl, wxEVT_COMMAND_BUTTON_CLICKED, eventsink );
button_sizer->Add( d_btn );
}
button_sizer->Add( clear_button, 1, 0, 5 );
@ -409,11 +459,11 @@ ControlChooser::ControlChooser( wxWindow* const parent, ControllerInterface::Con
range_slider->SetValue( control_reference->range * SLIDER_TICK_COUNT );
_connect_macro_( detect_button, ConfigDetectControl, wxEVT_COMMAND_BUTTON_CLICKED);
_connect_macro_( clear_button, ClearControl, wxEVT_COMMAND_BUTTON_CLICKED);
_connect_macro_( set_button, SetControl, wxEVT_COMMAND_BUTTON_CLICKED);
_connect_macro_( detect_button, GamepadPage::ConfigDetectControl, wxEVT_COMMAND_BUTTON_CLICKED, eventsink);
_connect_macro_( clear_button, GamepadPage::ClearControl, wxEVT_COMMAND_BUTTON_CLICKED, eventsink);
_connect_macro_( set_button, GamepadPage::SetControl, wxEVT_COMMAND_BUTTON_CLICKED, eventsink);
_connect_macro_( range_slider, AdjustControlOption, wxEVT_SCROLL_CHANGED);
_connect_macro_( range_slider, GamepadPage::AdjustControlOption, wxEVT_SCROLL_CHANGED, eventsink);
wxStaticText* range_label = new wxStaticText( parent, -1, wxT("Range"));
m_bound_label = new wxStaticText( parent, -1, wxT("") );
@ -425,7 +475,7 @@ ControlChooser::ControlChooser( wxWindow* const parent, ControllerInterface::Con
txtbox_szr->Add( textctrl, 1, wxEXPAND, 0 );
wxBoxSizer* mode_szr = NULL;
wxBoxSizer* mode_szr;
if ( control_reference->is_input )
{
mode_cbox = new wxChoice( parent, -1 );
@ -434,7 +484,7 @@ ControlChooser::ControlChooser( wxWindow* const parent, ControllerInterface::Con
mode_cbox->Append( wxT("NOT") );
mode_cbox->Select( ((ControllerInterface::InputReference*)control_reference)->mode );
_connect_macro_( mode_cbox, AdjustControlOption, wxEVT_COMMAND_CHOICE_SELECTED );
_connect_macro_( mode_cbox, GamepadPage::AdjustControlOption, wxEVT_COMMAND_CHOICE_SELECTED, eventsink );
mode_szr = new wxBoxSizer( wxHORIZONTAL );
mode_szr->Add( new wxStaticText( parent, -1, wxT("Mode") ), 0, wxCENTER|wxLEFT|wxRIGHT, 5 );
@ -462,7 +512,8 @@ void GamepadPage::LoadProfile( wxCommandEvent& event )
std::ifstream file;
std::string fname( File::GetUserPath(D_CONFIG_IDX) );
fname += PROFILES_PATH; fname += profile_cbox->GetValue().ToAscii(); fname += ".ini";
fname += PROFILES_PATH; fname += m_plugin.profile_name; fname += '/';
fname += profile_cbox->GetValue().ToAscii(); fname += ".ini";
if ( false == File::Exists( fname.c_str() ) )
return;
@ -491,7 +542,7 @@ void GamepadPage::SaveProfile( wxCommandEvent& event )
controller->SaveConfig( inifile["Profile"] );
std::ofstream file;
std::string fname( File::GetUserPath(D_CONFIG_IDX) );
fname += PROFILES_PATH;
fname += PROFILES_PATH; fname += m_plugin.profile_name; fname += '/';
if ( false == File::Exists( fname.c_str() ) )
File::CreateFullPath( fname.c_str() );
@ -513,7 +564,8 @@ void GamepadPage::DeleteProfile( wxCommandEvent& event )
// don't need lock
std::string fname( File::GetUserPath(D_CONFIG_IDX) );
fname += PROFILES_PATH; fname += profile_cbox->GetValue().ToAscii(); fname += ".ini";
fname += PROFILES_PATH; fname += m_plugin.profile_name; fname += '/';
fname += profile_cbox->GetValue().ToAscii(); fname += ".ini";
if ( File::Exists( fname.c_str() ) )
File::Delete( fname.c_str() );
@ -556,7 +608,7 @@ void GamepadPage::RefreshDevices( wxCommandEvent& event )
m_plugin.controls_crit.Leave(); // leave
}
ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWindow* const parent )
ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWindow* const parent, wxWindow* const eventsink )
: wxStaticBoxSizer( wxVERTICAL, parent, wxString::FromAscii( group->name ) )
{
@ -568,19 +620,17 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi
{
wxStaticText* label = new wxStaticText( parent, -1, wxString::FromAscii( group->controls[c]->name )/*.append(wxT(" :"))*/ );
ControlButton* control_button = new ControlButton( parent, group->controls[c]->control_ref, 80 );
control_button->SetFont(m_SmallFont);
controls.push_back( control_button );
ControlButton* adv_button = new ControlButton( parent, group->controls[c]->control_ref, 18, "+" );
adv_button->SetFont(m_SmallFont);
controls.push_back( control_button );
control_buttons.push_back( control_button );
control_button->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GamepadPage::DetectControl ),
(wxObject*)0, (wxEvtHandler*)parent );
adv_button->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GamepadPage::ConfigControl ),
(wxObject*)0, (wxEvtHandler*)parent );
_connect_macro_( control_button, GamepadPage::DetectControl, wxEVT_COMMAND_BUTTON_CLICKED, eventsink );
_connect_macro_( adv_button, GamepadPage::ConfigControl, wxEVT_COMMAND_BUTTON_CLICKED, eventsink );
wxBoxSizer* control_sizer = new wxBoxSizer( wxHORIZONTAL );
control_sizer->AddStretchSpacer( 1 );
@ -595,6 +645,7 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi
switch ( group->type )
{
case GROUP_TYPE_STICK :
case GROUP_TYPE_TILT :
{
wxBitmap bitmap(64, 64);
wxMemoryDC dc;
@ -607,8 +658,8 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi
PadSettingChoice* deadzone_cbox = new PadSettingChoice( parent, group->settings[0]->value, 1, 50 );
PadSettingChoice* diagonal_cbox = new PadSettingChoice( parent, group->settings[1]->value, 1, 100 );
deadzone_cbox->Connect( wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( GamepadPage::AdjustSetting ), (wxObject*)0, (wxEvtHandler*)parent );
diagonal_cbox->Connect( wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( GamepadPage::AdjustSetting ), (wxObject*)0, (wxEvtHandler*)parent );
_connect_macro_( deadzone_cbox, GamepadPage::AdjustSetting, wxEVT_COMMAND_CHOICE_SELECTED, eventsink );
_connect_macro_( diagonal_cbox, GamepadPage::AdjustSetting, wxEVT_COMMAND_CHOICE_SELECTED, eventsink );
options.push_back( deadzone_cbox );
options.push_back( diagonal_cbox );
@ -636,8 +687,7 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi
static_bitmap = new wxStaticBitmap( parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP );
PadSettingChoice* threshold_cbox = new PadSettingChoice( parent, group->settings[0]->value, 1, 99 );
// threshold_cbox->SetFont(m_SmallFont);
threshold_cbox->Connect( wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( GamepadPage::AdjustSetting ), (wxObject*)0, (wxEvtHandler*)parent );
_connect_macro_( threshold_cbox, GamepadPage::AdjustSetting, wxEVT_COMMAND_CHOICE_SELECTED, eventsink );
options.push_back( threshold_cbox );
@ -659,7 +709,7 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi
static_bitmap = new wxStaticBitmap( parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP );
PadSettingChoice* threshold_cbox = new PadSettingChoice( parent, group->settings[0]->value, 1, 99 );
threshold_cbox->Connect( wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( GamepadPage::AdjustSetting ), (wxObject*)0, (wxEvtHandler*)parent );
_connect_macro_( threshold_cbox, GamepadPage::AdjustSetting, wxEVT_COMMAND_CHOICE_SELECTED, eventsink );
options.push_back( threshold_cbox );
@ -671,28 +721,72 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi
Add( static_bitmap, 0, wxALL|wxCENTER, 5 );
}
break;
case GROUP_TYPE_EXTENSION :
{
PadSettingExtension* const attachments = new PadSettingExtension( parent, (ControllerEmu::Extension*)group );
wxButton* const configure = new ExtensionButton( parent, (ControllerEmu::Extension*)group );
options.push_back( attachments );
_connect_macro_( attachments, GamepadPage::AdjustSetting, wxEVT_COMMAND_CHOICE_SELECTED, eventsink );
_connect_macro_( configure, GamepadPage::ConfigExtension, wxEVT_COMMAND_BUTTON_CLICKED, eventsink );
Add( attachments, 0, wxTOP|wxLEFT|wxRIGHT|wxEXPAND, 5 );
Add( configure, 0, wxALL|wxEXPAND, 5 );
}
break;
default :
{
//options
std::vector<ControllerEmu::ControlGroup::Setting*>::const_iterator
i = group->settings.begin(),
e = group->settings.end();
for ( ; i!=e; ++i )
{
PadSettingCheckBox* setting_cbox = new PadSettingCheckBox( parent, (*i)->value, (*i)->name );
setting_cbox->Connect( wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( GamepadPage::AdjustSetting ), (wxObject*)0, (wxEvtHandler*)parent );
_connect_macro_( setting_cbox, GamepadPage::AdjustSetting, wxEVT_COMMAND_CHECKBOX_CLICKED, eventsink );
options.push_back( setting_cbox );
Add( setting_cbox, 0, wxALL|wxCENTER, 5 );
Add( setting_cbox, 0, wxALL|wxLEFT, 5 );
}
}
break;
}
//AddStretchSpacer( 0 );
}
ControlGroupsSizer::ControlGroupsSizer( ControllerEmu* const controller, wxWindow* const parent, wxWindow* const eventsink, std::vector<ControlGroupBox*>* groups )
: wxBoxSizer( wxHORIZONTAL )
{
wxBoxSizer* stacked_groups = NULL;
for ( unsigned int i = 0; i < controller->groups.size(); ++i )
{
ControlGroupBox* control_group = new ControlGroupBox( controller->groups[i], parent, eventsink );
if ( control_group->control_buttons.size() > 1 )
{
if ( stacked_groups )
Add( stacked_groups, 0, /*wxEXPAND|*/wxBOTTOM|wxRIGHT, 5 );
stacked_groups = new wxBoxSizer( wxVERTICAL );
stacked_groups->Add( control_group, 0, wxEXPAND );
}
else
stacked_groups->Add( control_group, 0, wxEXPAND );
if ( groups )
groups->push_back( control_group );
}
if ( stacked_groups )
Add( stacked_groups, 0, /*wxEXPAND|*/wxBOTTOM|wxRIGHT, 5 );
}
GamepadPage::GamepadPage( wxWindow* parent, Plugin& plugin, const unsigned int pad_num, ConfigDialog* const config_dialog )
: wxNotebookPage( parent, -1 , wxDefaultPosition, wxDefaultSize )
,controller(plugin.controllers[pad_num])
@ -700,29 +794,7 @@ GamepadPage::GamepadPage( wxWindow* parent, Plugin& plugin, const unsigned int p
,m_config_dialog(config_dialog)
{
wxBoxSizer* control_group_sizer = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* stacked_groups = NULL;
for ( unsigned int i = 0; i < m_plugin.controllers[pad_num]->groups.size(); ++i )
{
ControlGroupBox* control_group = new ControlGroupBox( m_plugin.controllers[pad_num]->groups[i], this );
if ( control_group->control_buttons.size() > 2 )
{
if ( stacked_groups )
control_group_sizer->Add( stacked_groups, 0, /*wxEXPAND|*/wxBOTTOM|wxRIGHT, 5 );
stacked_groups = new wxBoxSizer( wxVERTICAL );
stacked_groups->Add( control_group, 0, wxEXPAND );
}
else
stacked_groups->Add( control_group, 0, wxEXPAND );
control_groups.push_back( control_group );
}
if ( stacked_groups )
control_group_sizer->Add( stacked_groups, 0, /*wxEXPAND|*/wxBOTTOM|wxRIGHT, 5 );
wxBoxSizer* control_group_sizer = new ControlGroupsSizer( m_plugin.controllers[pad_num], this, this, &control_groups );
wxStaticBoxSizer* profile_sbox = new wxStaticBoxSizer( wxHORIZONTAL, this, wxT("Profile") );
@ -734,11 +806,11 @@ GamepadPage::GamepadPage( wxWindow* parent, Plugin& plugin, const unsigned int p
wxButton* refresh_button = new wxButton( this, -1, wxT("Refresh"), wxDefaultPosition, wxSize(60,-1) );
#define _connect_macro3_( b, f, c ) (b)->Connect( wxID_ANY, c, wxCommandEventHandler( GamepadPage::f ), (wxObject*)0, (wxEvtHandler*)this );
//#define _connect_macro3_( b, f, c ) (b)->Connect( wxID_ANY, c, wxCommandEventHandler( GamepadPage::f ), (wxObject*)0, (wxEvtHandler*)this );
_connect_macro3_( device_cbox, SetDevice, wxEVT_COMMAND_COMBOBOX_SELECTED );
_connect_macro3_( device_cbox, SetDevice, wxEVT_COMMAND_TEXT_ENTER );
_connect_macro3_( refresh_button, RefreshDevices, wxEVT_COMMAND_BUTTON_CLICKED );
_connect_macro_( device_cbox, GamepadPage::SetDevice, wxEVT_COMMAND_COMBOBOX_SELECTED, this );
_connect_macro_( device_cbox, GamepadPage::SetDevice, wxEVT_COMMAND_TEXT_ENTER, this );
_connect_macro_( refresh_button, GamepadPage::RefreshDevices, wxEVT_COMMAND_BUTTON_CLICKED, this );
device_sbox->Add( device_cbox, 1, wxLEFT|wxRIGHT, 5 );
device_sbox->Add( refresh_button, 0, wxRIGHT|wxBOTTOM, 5 );
@ -799,7 +871,7 @@ ConfigDialog::ConfigDialog( wxWindow* const parent, Plugin& plugin, const std::s
{
GamepadPage* gp = new GamepadPage( m_pad_notebook, plugin, i, this );
m_padpages.push_back( gp );
m_pad_notebook->AddPage( gp, wxString::FromAscii((plugin.controllers[i]->GetName().c_str())) );
m_pad_notebook->AddPage( gp, wxString::FromAscii( m_plugin.gui_name ) + wxT(' ') + wxChar('1'+i) );
}
UpdateDeviceComboBox();

View File

@ -6,7 +6,7 @@
#define PREVIEW_UPDATE_TIME 25
// might have to change this setup for wiimote
#define PROFILES_PATH "Profiles/GCPad/"
#define PROFILES_PATH "Profiles/"
#include <wx/wx.h>
#include <wx/listbox.h>
@ -21,38 +21,49 @@
#include <sstream>
#include <vector>
#include "ControllerInterface/ControllerInterface.h"
#include <ControllerInterface/ControllerInterface.h>
#include "Config.h"
#include "FileSearch.h"
class PadSetting
{
protected:
PadSetting( ControlState& _value ) : value(_value) {}
PadSetting() {}
public:
virtual void UpdateGUI() = 0;
virtual void UpdateValue() = 0;
ControlState& value;
};
class PadSettingChoice : public PadSetting, public wxChoice
class PadSettingExtension : public wxChoice, public PadSetting
{
public:
PadSettingExtension( wxWindow* const parent, ControllerEmu::Extension* const ext );
void UpdateGUI();
void UpdateValue();
ControllerEmu::Extension* const extension;
};
class PadSettingChoice : public wxChoice, public PadSetting
{
public:
PadSettingChoice( wxWindow* const parent, ControlState& _value, int min, int max );
void UpdateGUI();
void UpdateValue();
ControlState& value;
};
class PadSettingCheckBox : public PadSetting, public wxCheckBox
class PadSettingCheckBox : public wxCheckBox, public PadSetting
{
public:
PadSettingCheckBox( wxWindow* const parent, ControlState& _value, const char* const label );
void UpdateGUI();
void UpdateValue();
};
ControlState& value;
};
class ControlChooser : public wxStaticBoxSizer
{
@ -93,6 +104,16 @@ public:
ControlChooser* control_chooser;
};
class ExtensionButton : public wxButton
{
public:
ExtensionButton( wxWindow* const parent, ControllerEmu::Extension* const ext )
: wxButton( parent, -1, wxT("Configure"), wxDefaultPosition )
, extension(ext) {}
ControllerEmu::Extension* const extension;
};
class ControlButton : public wxButton
{
public:
@ -104,7 +125,7 @@ public:
class ControlGroupBox : public wxStaticBoxSizer
{
public:
ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWindow* const parent );
ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWindow* const parent, wxWindow* const eventsink );
ControllerEmu::ControlGroup* control_group;
wxStaticBitmap* static_bitmap;
@ -113,6 +134,14 @@ public:
std::vector<ControlButton*> control_buttons;
};
class ControlGroupsSizer : public wxBoxSizer
{
public:
ControlGroupsSizer( ControllerEmu* const controller, wxWindow* const parent, wxWindow* const eventsink, std::vector<ControlGroupBox*>* const groups = NULL );
};
class ConfigDialog;
class GamepadPage : public wxNotebookPage
@ -135,6 +164,8 @@ public:
void DetectControl( wxCommandEvent& event );
void ClearControl( wxCommandEvent& event );
void ConfigExtension( wxCommandEvent& event );
void SetDevice( wxCommandEvent& event );
void SetControl( wxCommandEvent& event );

View File

@ -24,16 +24,20 @@ void ConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
switch ( (*g)->control_group->type )
{
case GROUP_TYPE_TILT :
case GROUP_TYPE_STICK :
{
float x, y;
float x = 0, y = 0;
float xx, yy;
((ControllerEmu::AnalogStick*)(*g)->control_group)->GetState( &x, &y, 32.0, 32-1.5 );
if ( GROUP_TYPE_STICK == (*g)->control_group->type )
((ControllerEmu::AnalogStick*)(*g)->control_group)->GetState( &x, &y, 32.0, 32-1.5 );
else
((ControllerEmu::Tilt*)(*g)->control_group)->GetState( &x, &y, 32.0, 32-1.5 );
xx = ((ControllerEmu::AnalogStick*)(*g)->control_group)->controls[3]->control_ref->State();
xx -= ((ControllerEmu::AnalogStick*)(*g)->control_group)->controls[2]->control_ref->State();
yy = ((ControllerEmu::AnalogStick*)(*g)->control_group)->controls[1]->control_ref->State();
yy -= ((ControllerEmu::AnalogStick*)(*g)->control_group)->controls[0]->control_ref->State();
xx = (*g)->control_group->controls[3]->control_ref->State();
xx -= (*g)->control_group->controls[2]->control_ref->State();
yy = (*g)->control_group->controls[1]->control_ref->State();
yy -= (*g)->control_group->controls[0]->control_ref->State();
xx *= 32 - 1; xx += 32;
yy *= 32 - 1; yy += 32;
@ -48,11 +52,14 @@ void ConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
// circle for visual aid for diagonal adjustment
dc.SetPen(*wxLIGHT_GREY_PEN);
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawCircle( 32, 32, 32);
if ( GROUP_TYPE_STICK == (*g)->control_group->type )
dc.DrawCircle( 32, 32, 32);
else
dc.DrawRectangle( 16, 16, 32, 32 );
// deadzone circle
dc.SetBrush(*wxLIGHT_GREY_BRUSH);
dc.DrawCircle( 32, 32, ((ControllerEmu::AnalogStick*)(*g)->control_group)->settings[0]->value * 32 );
dc.DrawCircle( 32, 32, ((*g)->control_group)->settings[0]->value * 32 );
// raw dot
dc.SetPen(*wxGREY_PEN);

View File

@ -0,0 +1,258 @@
#include "ControllerEmu.h"
const char modifier[] = "Modifier";
ControllerEmu::~ControllerEmu()
{
std::vector<ControlGroup*>::const_iterator
i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
delete *i;
}
ControllerEmu::ControlGroup::~ControlGroup()
{
std::vector<Control*>::const_iterator
ci = controls.begin(),
ce = controls.end();
for ( ; ci!=ce; ++ci )
delete *ci;
std::vector<Setting*>::const_iterator
si = settings.begin(),
se = settings.end();
for ( ; si!=se; ++si )
delete *si;
}
void ControllerEmu::UpdateReferences( ControllerInterface& devi )
{
std::vector<ControlGroup*>::const_iterator
i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
{
std::vector<ControlGroup::Control*>::const_iterator
ci = (*i)->controls.begin(),
ce = (*i)->controls.end();
for ( ; ci!=ce; ++ci )
devi.UpdateReference( (*ci)->control_ref );
// extension
if ( GROUP_TYPE_EXTENSION == (*i)->type )
{
std::vector<ControllerEmu*>::const_iterator
ai = ((Extension*)*i)->attachments.begin(),
ae = ((Extension*)*i)->attachments.end();
for ( ; ai!=ae; ++ai )
(*ai)->UpdateReferences( devi );
}
}
}
void ControllerEmu::UpdateDefaultDevice()
{
std::vector<ControlGroup*>::const_iterator
i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
{
std::vector<ControlGroup::Control*>::const_iterator
ci = (*i)->controls.begin(),
ce = (*i)->controls.end();
for ( ; ci!=ce; ++ci )
(*ci)->control_ref->device_qualifier = default_device;
// extension
if ( GROUP_TYPE_EXTENSION == (*i)->type )
{
std::vector<ControllerEmu*>::const_iterator
ai = ((Extension*)*i)->attachments.begin(),
ae = ((Extension*)*i)->attachments.end();
for ( ; ai!=ae; ++ai )
{
(*ai)->default_device = default_device;
(*ai)->UpdateDefaultDevice();
}
}
}
}
void ControllerEmu::ControlGroup::LoadConfig( IniFile::Section& sec, const std::string& defdev, const std::string& base )
{
std::string group( base + name ); group += "/";
// settings
std::vector<ControlGroup::Setting*>::const_iterator
si = settings.begin(),
se = settings.end();
for ( ; si!=se; ++si )
(*si)->value = sec.Get(group+(*si)->name, (*si)->default_value*100) / 100;
// controls
std::vector<ControlGroup::Control*>::const_iterator
ci = controls.begin(),
ce = controls.end();
for ( ; ci!=ce; ++ci )
{
// control and dev qualifier
(*ci)->control_ref->control_qualifier.name = sec[group + (*ci)->name];
(*ci)->control_ref->device_qualifier.FromString( sec.Get( group+(*ci)->name+"/Device", defdev ) );
// range
(*ci)->control_ref->range = sec.Get( group+(*ci)->name+"/Range", 100.0f ) / 100;
// input mode
if ( (*ci)->control_ref->is_input )
((ControllerInterface::InputReference*)((*ci)->control_ref))->mode
= sec.Get( group+(*ci)->name+"/Mode", 0 );
}
// extensions
if ( GROUP_TYPE_EXTENSION == type )
{
Extension* const ex = ((Extension*)this);
ex->switch_extension = 0;
unsigned int n = 0;
const std::string extname = sec[ base + name ];
std::vector<ControllerEmu*>::const_iterator
ai = ((Extension*)this)->attachments.begin(),
ae = ((Extension*)this)->attachments.end();
for ( ; ai!=ae; ++ai,++n )
{
(*ai)->default_device.FromString( defdev );
(*ai)->LoadConfig( sec, base + (*ai)->GetName() + "/" );
if ( (*ai)->GetName() == extname )
ex->switch_extension = n;
}
}
}
void ControllerEmu::LoadConfig( IniFile::Section& sec, const std::string& base )
{
std::string defdev = default_device.ToString();
if ( base.empty() )
{
defdev = sec[ base + "Device" ];
default_device.FromString( defdev );
}
std::vector<ControlGroup*>::const_iterator i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
(*i)->LoadConfig( sec, defdev, base );
}
void ControllerEmu::ControlGroup::SaveConfig( IniFile::Section& sec, const std::string& defdev, const std::string& base )
{
std::string group( base + name ); group += "/";
// settings
std::vector<ControlGroup::Setting*>::const_iterator
si = settings.begin(),
se = settings.end();
for ( ; si!=se; ++si )
sec.Set( group+(*si)->name, (*si)->value*100, (*si)->default_value*100 );
// controls
std::vector<ControlGroup::Control*>::const_iterator
ci = controls.begin(),
ce = controls.end();
for ( ; ci!=ce; ++ci )
{
// control and dev qualifier
sec[group + (*ci)->name] = (*ci)->control_ref->control_qualifier.name;
sec.Set( group+(*ci)->name+"/Device", (*ci)->control_ref->device_qualifier.ToString(), defdev );
// range
sec.Set( group+(*ci)->name+"/Range", (*ci)->control_ref->range*100, 100 );
// input mode
if ( (*ci)->control_ref->is_input )
sec.Set( group+(*ci)->name+"/Mode",
((ControllerInterface::InputReference*)((*ci)->control_ref))->mode, (unsigned int)0 );
}
// extensions
if ( GROUP_TYPE_EXTENSION == type )
{
Extension* const ext = ((Extension*)this);
sec.Set( base + name, ext->attachments[ext->switch_extension]->GetName(), std::string("None") );
std::vector<ControllerEmu*>::const_iterator
ai = ((Extension*)this)->attachments.begin(),
ae = ((Extension*)this)->attachments.end();
for ( ; ai!=ae; ++ai )
(*ai)->SaveConfig( sec, base + (*ai)->GetName() + "/" );
}
}
void ControllerEmu::SaveConfig( IniFile::Section& sec, const std::string& base )
{
const std::string defdev = default_device.ToString();
if ( base.empty() )
sec[ std::string(" ") + base + "Device" ] = defdev;
std::vector<ControlGroup*>::const_iterator i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
(*i)->SaveConfig( sec, defdev, base );
}
ControllerEmu::AnalogStick::AnalogStick( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_STICK )
{
for ( unsigned int i = 0; i < 4; ++i )
controls.push_back( new Input( named_directions[i] ) );
controls.push_back( new Input( modifier ) );
settings.push_back( new Setting("Dead Zone", 0 ) );
settings.push_back( new Setting("Square Stick", 0 ) );
}
ControllerEmu::Buttons::Buttons( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_BUTTONS )
{
settings.push_back( new Setting("Threshold", 0.5f ) );
}
ControllerEmu::MixedTriggers::MixedTriggers( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_MIXED_TRIGGERS )
{
settings.push_back( new Setting("Threshold", 0.9f ) );
}
ControllerEmu::Force::Force( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_FORCE )
{
controls.push_back( new Input( "X-" ) );
controls.push_back( new Input( "X+" ) );
controls.push_back( new Input( "Y-" ) );
controls.push_back( new Input( "Y+" ) );
controls.push_back( new Input( "Z-" ) );
controls.push_back( new Input( "Z+" ) );
}
void ControllerEmu::Force::GetState( u8* data, const u8 base, const u8 range )
{
for ( unsigned int i=0; i<3; ++i,++data )
*data = u8( ( controls[i*2+1]->control_ref->State() - controls[i*2]->control_ref->State() ) * range + base );
}
ControllerEmu::Tilt::Tilt( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_TILT )
{
//for ( unsigned int i = 0; i < 4; ++i )
//controls.push_back( new Input( named_directions[i] ) );
controls.push_back( new Input( "Forward" ) );
controls.push_back( new Input( "Backward" ) );
controls.push_back( new Input( "Left" ) );
controls.push_back( new Input( "Right" ) );
controls.push_back( new Input( modifier ) );
settings.push_back( new Setting("Dead Zone", 0 ) );
settings.push_back( new Setting("Circle Stick", 0 ) );
}

View File

@ -9,7 +9,7 @@
//#include <CommonTypes.h>
#include <math.h>
#include "ControllerInterface/ControllerInterface.h"
#include <ControllerInterface/ControllerInterface.h>
#include "IniFile.h"
#include <vector>
@ -20,10 +20,13 @@
enum
{
GROUP_TYPE_OTHER
,GROUP_TYPE_STICK
,GROUP_TYPE_MIXED_TRIGGERS
,GROUP_TYPE_BUTTONS
GROUP_TYPE_OTHER,
GROUP_TYPE_STICK,
GROUP_TYPE_MIXED_TRIGGERS,
GROUP_TYPE_BUTTONS,
GROUP_TYPE_FORCE,
GROUP_TYPE_EXTENSION,
GROUP_TYPE_TILT,
};
const char * const named_directions[] =
@ -89,7 +92,8 @@ public:
ControlGroup( const char* const _name, const unsigned int _type = GROUP_TYPE_OTHER ) : name(_name), type(_type) {}
virtual ~ControlGroup();
//ControlGroup( const ControlGroup& ctrl );
void LoadConfig( IniFile::Section& sec, const std::string& defdev = "", const std::string& base = "" );
void SaveConfig( IniFile::Section& sec, const std::string& defdev = "", const std::string& base = "" );
//const unsigned int type;
const char* const name;
@ -119,8 +123,8 @@ public:
// modifier code
if ( m )
{
yy = (abs(yy)>deadzone) * sign(yy) * m;
xx = (abs(xx)>deadzone) * sign(xx) * m;
yy = (abs(yy)>deadzone) * sign(yy) * (m + deadzone/2);
xx = (abs(xx)>deadzone) * sign(xx) * (m + deadzone/2);
}
// deadzone / square stick code
@ -146,7 +150,7 @@ public:
dist /= ( 1 - deadzone );
// square stick code
ControlState amt = ( dist ) / stick_full;
ControlState amt = dist / stick_full;
dist -= ((square_full - 1) * amt * square);
yy = std::max( -1.0f, std::min( 1.0f, ang_sin * dist ) );
@ -203,18 +207,102 @@ public:
};
class Force : public ControlGroup
{
public:
Force( const char* const _name );
void GetState( u8* data, const u8 base, const u8 range );
};
class Tilt : public ControlGroup
{
public:
Tilt( const char* const _name );
template <typename C, typename R>
void GetState( C* const x, C* const y, const unsigned int base, const R range )
{
// this is all a mess
ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State();
ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State();
ControlState deadzone = settings[0]->value;
ControlState circle = settings[1]->value;
ControlState m = controls[4]->control_ref->State();
// modifier code
if ( m )
{
yy = (abs(yy)>deadzone) * sign(yy) * (m + deadzone/2);
xx = (abs(xx)>deadzone) * sign(xx) * (m + deadzone/2);
}
// deadzone / circle stick code
if ( deadzone || circle )
{
// this section might be all wrong, but its working good enough, i think
ControlState ang = atan2( yy, xx );
ControlState ang_sin = sin(ang);
ControlState ang_cos = cos(ang);
// the amt a full square stick would have at current angle
ControlState square_full = std::min( 1/abs(ang_sin), 1/abs(ang_cos) );
// the amt a full stick would have that was ( user setting circular ) at current angle
// i think this is more like a pointed circle rather than a rounded square like it should be
ControlState stick_full = (square_full * (1 - circle)) + (circle);
ControlState dist = sqrt(xx*xx + yy*yy);
// dead zone code
dist = std::max( 0.0f, dist - deadzone * stick_full );
dist /= (1 - deadzone);
// circle stick code
ControlState amt = dist / stick_full;
dist += (square_full - 1) * amt * circle;
yy = std::max( -1.0f, std::min( 1.0f, ang_sin * dist ) );
xx = std::max( -1.0f, std::min( 1.0f, ang_cos * dist ) );
}
*y = C( yy * range + base );
*x = C( xx * range + base );
}
};
class Extension : public ControlGroup
{
public:
Extension( const char* const _name )
: ControlGroup( _name, GROUP_TYPE_EXTENSION )
, switch_extension(0)
, active_extension(0) {}
void GetState( u8* const data );
std::vector<ControllerEmu*> attachments;
unsigned int switch_extension;
unsigned int active_extension;
};
virtual ~ControllerEmu();
virtual std::string GetName() const = 0;
void LoadConfig( IniFile::Section& sec );
void SaveConfig( IniFile::Section& sec );
void LoadConfig( IniFile::Section& sec, const std::string& base = "" );
void SaveConfig( IniFile::Section& sec, const std::string& base = "" );
void UpdateDefaultDevice();
void UpdateReferences( ControllerInterface& devi );
std::vector< ControlGroup* > groups;
ControlGroup* options;
ControllerInterface::DeviceQualifier default_device;
@ -222,6 +310,4 @@ public:
};
#endif

View File

@ -196,6 +196,29 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_GCPad", "Plugins\Plu
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_GCPadNew", "Plugins\Plugin_GCPadNew\Plugin_GCPadNew.vcproj", "{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}"
ProjectSection(ProjectDependencies) = postProject
{C7E5D50A-2916-464B-86A7-E10B3CC88ADA} = {C7E5D50A-2916-464B-86A7-E10B3CC88ADA}
{05C75041-D67D-4903-A362-8395A7B35C75} = {05C75041-D67D-4903-A362-8395A7B35C75}
{11F55366-12EC-4C44-A8CB-1D4E315D61ED} = {11F55366-12EC-4C44-A8CB-1D4E315D61ED}
{0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E} = {0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E}
{1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE} = {1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE}
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE} = {660BB3F7-ED8F-4027-A460-8E4EDA8189BE}
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_WiimoteNew", "Plugins\Plugin_WiimoteNew\Plugin_WiimoteNew.vcproj", "{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}"
ProjectSection(ProjectDependencies) = postProject
{C7E5D50A-2916-464B-86A7-E10B3CC88ADA} = {C7E5D50A-2916-464B-86A7-E10B3CC88ADA}
{05C75041-D67D-4903-A362-8395A7B35C75} = {05C75041-D67D-4903-A362-8395A7B35C75}
{11F55366-12EC-4C44-A8CB-1D4E315D61ED} = {11F55366-12EC-4C44-A8CB-1D4E315D61ED}
{0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E} = {0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E}
{1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE} = {1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE}
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE} = {660BB3F7-ED8F-4027-A460-8E4EDA8189BE}
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InputPluginCommon", "Core\InputPluginCommon\InputPluginCommon.vcproj", "{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}"
ProjectSection(ProjectDependencies) = postProject
{C7E5D50A-2916-464B-86A7-E10B3CC88ADA} = {C7E5D50A-2916-464B-86A7-E10B3CC88ADA}
{05C75041-D67D-4903-A362-8395A7B35C75} = {05C75041-D67D-4903-A362-8395A7B35C75}
{11F55366-12EC-4C44-A8CB-1D4E315D61ED} = {11F55366-12EC-4C44-A8CB-1D4E315D61ED}
{0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E} = {0E231FB1-F3C9-4724-ACCB-DE8BCB3C089E}
@ -575,6 +598,30 @@ Global
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Release|Win32.Build.0 = Release|Win32
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Release|x64.ActiveCfg = Release|x64
{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}.Release|x64.Build.0 = Release|x64
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.Debug|Win32.ActiveCfg = Debug|Win32
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.Debug|Win32.Build.0 = Debug|Win32
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.Debug|x64.ActiveCfg = Debug|x64
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.Debug|x64.Build.0 = Debug|x64
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.DebugFast|Win32.Build.0 = DebugFast|Win32
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.DebugFast|x64.ActiveCfg = DebugFast|x64
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.DebugFast|x64.Build.0 = DebugFast|x64
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.Release|Win32.ActiveCfg = Release|Win32
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.Release|Win32.Build.0 = Release|Win32
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.Release|x64.ActiveCfg = Release|x64
{BB6CE47B-C676-44BB-AE93-2CF59B8C8BD4}.Release|x64.Build.0 = Release|x64
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.Debug|Win32.ActiveCfg = Debug|Win32
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.Debug|Win32.Build.0 = Debug|Win32
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.Debug|x64.ActiveCfg = Debug|x64
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.Debug|x64.Build.0 = Debug|x64
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.DebugFast|Win32.Build.0 = DebugFast|Win32
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.DebugFast|x64.ActiveCfg = DebugFast|x64
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.DebugFast|x64.Build.0 = DebugFast|x64
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.Release|Win32.ActiveCfg = Release|Win32
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.Release|Win32.Build.0 = Release|Win32
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.Release|x64.ActiveCfg = Release|x64
{660BB3F7-ED8F-4027-A460-8E4EDA8189BE}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Version="9.00"
Name="Plugin_GCPadNew"
ProjectGUID="{1C3A7A91-A97F-4C7C-B45D-26F2242904D7}"
RootNamespace="Plugin_GCPadNew"
@ -44,7 +44,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -126,7 +126,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -206,7 +206,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
@ -293,7 +293,7 @@
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
@ -373,7 +373,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;DEBUGFAST;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
@ -455,7 +455,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;DEBUGFAST;_WINDOWS;_USRDLL;PLUGIN_NJOY_SDL_EXPORTS;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
@ -514,150 +514,14 @@
<References>
</References>
<Files>
<Filter
Name="Config"
<File
RelativePath=".\Src\GCPadEmu.cpp"
>
<File
RelativePath=".\Src\Config.cpp"
>
</File>
<File
RelativePath=".\Src\Config.h"
>
</File>
<Filter
Name="GUI"
>
<File
RelativePath=".\Src\ConfigDiag.cpp"
>
</File>
<File
RelativePath=".\Src\ConfigDiag.h"
>
</File>
<File
RelativePath=".\Src\ConfigDiagBitmaps.cpp"
>
</File>
</Filter>
</Filter>
<Filter
Name="IniFile"
</File>
<File
RelativePath=".\Src\GCPadEmu.h"
>
<File
RelativePath=".\Src\IniFile.cpp"
>
</File>
<File
RelativePath=".\Src\IniFile.h"
>
</File>
</Filter>
<Filter
Name="ControllerInterface"
>
<File
RelativePath=".\Src\ControllerInterface\ControllerInterface.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\ControllerInterface.h"
>
</File>
<Filter
Name="XInput"
>
<File
RelativePath=".\Src\ControllerInterface\XInput\XInput.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\XInput\XInput.h"
>
</File>
</Filter>
<Filter
Name="SDL"
>
<File
RelativePath=".\Src\ControllerInterface\SDL\SDL.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\SDL\SDL.h"
>
</File>
</Filter>
<Filter
Name="DirectInput"
>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInput.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInput.h"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputJoystick.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputJoystick.h"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputKeyboardMouse.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\DirectInputKeyboardMouse.h"
>
</File>
<File
RelativePath=".\Src\ControllerInterface\DirectInput\NamedKeys.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="ControllerEmu"
>
<File
RelativePath=".\Src\ControllerEmu.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerEmu.h"
>
</File>
<Filter
Name="GCPad"
>
<File
RelativePath=".\Src\ControllerEmu\GCPad\GCPad.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerEmu\GCPad\GCPad.h"
>
</File>
</Filter>
<Filter
Name="Wiimote"
>
<File
RelativePath=".\Src\ControllerEmu\Wiimote\Wiimote.cpp"
>
</File>
<File
RelativePath=".\Src\ControllerEmu\Wiimote\Wiimote.h"
>
</File>
</Filter>
</Filter>
</File>
<File
RelativePath=".\Src\GCPadNew.cpp"
>

View File

@ -1,138 +0,0 @@
#include "ControllerEmu.h"
#include "ControllerEmu/GCPad/GCPad.h"
const char modifier[] = "Modifier";
// TODO: make this use iterators
ControllerEmu::~ControllerEmu()
{
for ( unsigned int g = 0; g<groups.size(); ++g )
delete groups[g];
}
// TODO: make this use iterators
ControllerEmu::ControlGroup::~ControlGroup()
{
for ( unsigned int i = 0; i < controls.size(); ++i )
delete controls[i];
for ( unsigned int i = 0; i < settings.size(); ++i )
delete settings[i];
}
// TODO: make this use iterators
void ControllerEmu::UpdateReferences( ControllerInterface& devi )
{
for ( unsigned int g = 0; g<groups.size(); ++g )
for ( unsigned int i = 0; i < groups[g]->controls.size(); ++i )
devi.UpdateReference( groups[g]->controls[i]->control_ref );
}
void ControllerEmu::UpdateDefaultDevice()
{
std::vector<ControlGroup*>::const_iterator i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
{
std::vector<ControlGroup::Control*>::const_iterator ci = (*i)->controls.begin(),
ce = (*i)->controls.end();
for ( ; ci!=ce; ++ci )
(*ci)->control_ref->device_qualifier = default_device;
}
}
void ControllerEmu::LoadConfig( IniFile::Section& sec )
{
const std::string default_dev = sec[ "Device" ];
default_device.FromString( default_dev );
std::vector<ControlGroup*>::const_iterator i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
{
std::string group( (*i)->name ); group += "/";
// settings
std::vector<ControlGroup::Setting*>::const_iterator si = (*i)->settings.begin(),
se = (*i)->settings.end();
for ( ; si!=se; ++si )
(*si)->value = sec.Get(group+(*si)->name, (*si)->default_value*100) / 100;
// controls
std::vector<ControlGroup::Control*>::const_iterator ci = (*i)->controls.begin(),
ce = (*i)->controls.end();
for ( ; ci!=ce; ++ci )
{
// control and dev qualifier
(*ci)->control_ref->control_qualifier.name = sec[group + (*ci)->name];
(*ci)->control_ref->device_qualifier.FromString( sec.Get( group+(*ci)->name+"/Device", default_dev ) );
// range
(*ci)->control_ref->range = sec.Get( group+(*ci)->name+"/Range", 100.0f ) / 100;
// input mode
if ( (*ci)->control_ref->is_input )
((ControllerInterface::InputReference*)((*ci)->control_ref))->mode
= sec.Get( group+(*ci)->name+"/Mode", 0 );
}
}
}
void ControllerEmu::SaveConfig( IniFile::Section& sec )
{
const std::string default_dev = default_device.ToString();
sec[ " Device" ] = default_dev;
std::vector<ControlGroup*>::const_iterator i = groups.begin(),
e = groups.end();
for ( ; i!=e; ++i )
{
std::string group( (*i)->name ); group += "/";
// settings
std::vector<ControlGroup::Setting*>::const_iterator si = (*i)->settings.begin(),
se = (*i)->settings.end();
for ( ; si!=se; ++si )
sec.Set( group+(*si)->name, (*si)->value*100, (*si)->default_value*100 );
// controls
std::vector<ControlGroup::Control*>::const_iterator ci = (*i)->controls.begin(),
ce = (*i)->controls.end();
for ( ; ci!=ce; ++ci )
{
// control and dev qualifier
sec[group + (*ci)->name] = (*ci)->control_ref->control_qualifier.name;
sec.Set( group+(*ci)->name+"/Device", (*ci)->control_ref->device_qualifier.ToString(), default_dev );
// range
sec.Set( group+(*ci)->name+"/Range", (*ci)->control_ref->range*100, 100 );
// input mode
if ( (*ci)->control_ref->is_input )
sec.Set( group+(*ci)->name+"/Mode",
((ControllerInterface::InputReference*)((*ci)->control_ref))->mode, (unsigned int)0 );
}
}
}
ControllerEmu::AnalogStick::AnalogStick( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_STICK )
{
for ( unsigned int i = 0; i < 4; ++i )
controls.push_back( new Input( named_directions[i] ) );
controls.push_back( new Input( modifier ) );
settings.push_back( new Setting("Dead Zone", 0 ) );
settings.push_back( new Setting("Square Stick", 0 ) );
}
ControllerEmu::Buttons::Buttons( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_BUTTONS )
{
settings.push_back( new Setting("Threshold", 0.5f ) );
}
ControllerEmu::MixedTriggers::MixedTriggers( const char* const _name ) : ControlGroup( _name, GROUP_TYPE_MIXED_TRIGGERS )
{
settings.push_back( new Setting("Threshold", 0.9f ) );
}

View File

@ -1,257 +0,0 @@
#include "Wiimote.h"
// buttons
#define WIIMOTE_PAD_LEFT 0x01
#define WIIMOTE_PAD_RIGHT 0x02
#define WIIMOTE_PAD_DOWN 0x04
#define WIIMOTE_PAD_UP 0x08
#define WIIMOTE_PLUS 0x10
#define WIIMOTE_TWO 0x0100
#define WIIMOTE_ONE 0x0200
#define WIIMOTE_B 0x0400
#define WIIMOTE_A 0x0800
#define WIIMOTE_MINUS 0x1000
#define WIIMOTE_HOME 0x8000
// reports
#define REPORT_UNKNOWN 0x10
#define REPORT_LEDS 0x11
#define REPORT_DATA_MODE 0x12
#define REPORT_IR_ENABLE 0x13
#define REPORT_SPEAKER_ENABLE 0x14
#define REPORT_STATUS_REQUEST 0x15
#define REPORT_WRITE_MEMORY 0x16
#define REPORT_READ_MEMORY 0x17
#define REPORT_SPEAKER_DATA 0x18
#define REPORT_SPEAKER_MUTE 0x19
#define REPORT_IR_ENABLE_2 0x1a
#define REPORT_STATUS 0x20
#define REPORT_READ_MEMORY_DATA 0x21
#define REPORT_ACKNOWLEDGE_OUTPUT 0x22
//#define REPORT_DATA_REPORTS 0x30-0x3f
// reporting modes
#define REPORT_MODE_CORE 0x30
#define REPORT_MODE_CORE_ACCEL 0x31
#define REPORT_MODE_CORE_EXTEN8 0x32
#define REPORT_MODE_CORE_ACCEL_IR12 0x33
#define REPORT_MODE_CORE_EXTEN19 0x34
#define REPORT_MODE_CORE_ACCEL_EXTEN16 0x35
#define REPORT_MODE_CORE_IR10_EXTEN9 0x36
#define REPORT_MODE_CORE_ACCEL_IR10_EXTEN6 0x37
#define REPORT_MODE_EXTEN21 0x3d
#define REPORT_MODE_IL_CORE_ACCEL_IR36_1 0x3e
#define REPORT_MODE_IL_CORE_ACCEL_IR36_2 0x3f
// this is all temporary, but sticking with the padspecs ...for now
const u16 button_bitmasks[] =
{
WIIMOTE_A, WIIMOTE_B, WIIMOTE_ONE, WIIMOTE_TWO, WIIMOTE_MINUS, WIIMOTE_PLUS, WIIMOTE_HOME
};
const u16 dpad_bitmasks[] =
{
WIIMOTE_PAD_UP, WIIMOTE_PAD_DOWN, WIIMOTE_PAD_LEFT, WIIMOTE_PAD_RIGHT
};
const char* const named_buttons[] =
{
"A",
"B",
"One",
"Two",
"Minus",
"Plus",
"Home",
};
const char * const named_groups[] =
{
"Buttons", "D-Pad"
};
Wiimote::Wiimote( const unsigned int index ) : m_index(index), m_report_mode(REPORT_MODE_CORE)
{
// buttons
groups.push_back( m_buttons = new Buttons( named_groups[0] ) );
for ( unsigned int i=0; i < sizeof(named_buttons)/sizeof(*named_buttons); ++i )
m_buttons->controls.push_back( new ControlGroup::Input( named_buttons[i] ) );
// dpad
groups.push_back( m_dpad = new Buttons( named_groups[1] ) );
for ( unsigned int i=0; i < 4; ++i )
m_dpad->controls.push_back( new ControlGroup::Input( named_directions[i] ) );
// rumble
groups.push_back( m_rumble = new ControlGroup( "Rumble" ) );
m_rumble->controls.push_back( new ControlGroup::Output( "Motor" ) );
}
std::string Wiimote::GetName() const
{
return std::string("Wiimote") + char('1'+m_index);
}
void Wiimote::Cycle()
{
HIDReport rpt;
rpt << (u8)m_report_mode;
switch ( m_report_mode )
{
//(a1) 30 BB BB
case REPORT_MODE_CORE :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
rpt << buttons;
}
break;
//(a1) 31 BB BB AA AA AA
case REPORT_MODE_CORE_ACCEL :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
rpt << buttons << (u16)0 << (u8)0;
}
break;
//(a1) 32 BB BB EE EE EE EE EE EE EE EE
case REPORT_MODE_CORE_EXTEN8 :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
rpt << buttons << (u64)0;
}
break;
//(a1) 33 BB BB AA AA AA II II II II II II II II II II II II
case REPORT_MODE_CORE_ACCEL_IR12 :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
rpt << buttons << (u64)0 << (u32)0 << (u16)0 << (u8)0;
}
break;
//(a1) 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
case REPORT_MODE_CORE_EXTEN19 :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
rpt << buttons << (u64)0 << (u64)0 << (u16)0 << (u8)0;
}
break;
//(a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
case REPORT_MODE_CORE_ACCEL_EXTEN16 :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
rpt << buttons << (u64)0 << (u64)0 << (u16)0 << (u8)0;
}
break;
//(a1) 36 BB BB II II II II II II II II II II EE EE EE EE EE EE EE EE EE
case REPORT_MODE_CORE_IR10_EXTEN9 :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
rpt << buttons << (u64)0 << (u64)0 << (u16)0 << (u8)0;
}
break;
//(a1) 37 BB BB AA AA AA II II II II II II II II II II EE EE EE EE EE EE
case REPORT_MODE_CORE_ACCEL_IR10_EXTEN6 :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
rpt << buttons << (u64)0 << (u64)0 << (u16)0 << (u8)0;
}
break;
//(a1) 3d EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
case REPORT_MODE_EXTEN21 :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
rpt << buttons << (u64)0 << (u64)0 << (u16)0 << (u8)0;
}
break;
//(a1) 3e/3f BB BB AA II II II II II II II II II II II II II II II II II II
case REPORT_MODE_IL_CORE_ACCEL_IR36_1 :
case REPORT_MODE_IL_CORE_ACCEL_IR36_2 :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
//rpt << buttons << (u64)0 << (u64)0 << (u64)0 << (u64)0 << (u32)0 << (u8)0;
rpt << buttons << (u64)0 << (u64)0 << (u16)0 << (u8)0;
}
break;
default :
break;
}
}
Wiimote& Wiimote::operator<<( HIDReport& rpt_in )
{
const u8 report_id = rpt_in.front(); rpt_in.pop();
HIDReport rpt_out;
switch ( report_id )
{
case REPORT_LEDS :
break;
case REPORT_DATA_MODE :
{
rpt_in.pop(); // continuous
m_report_mode = rpt_in.front();
}
break;
case REPORT_IR_ENABLE :
break;
case REPORT_SPEAKER_ENABLE :
break;
case REPORT_STATUS_REQUEST :
{
u16 buttons;
m_buttons->GetState( &buttons, button_bitmasks );
m_dpad->GetState( &buttons, dpad_bitmasks );
rpt_out << (u8)REPORT_STATUS << buttons << (u16)0 << (u8)0 << (u8)0xFF;
}
break;
case REPORT_WRITE_MEMORY :
break;
case REPORT_READ_MEMORY :
break;
case REPORT_SPEAKER_DATA :
break;
case REPORT_SPEAKER_MUTE :
break;
case REPORT_IR_ENABLE_2 :
break;
case REPORT_STATUS :
break;
case REPORT_READ_MEMORY_DATA :
break;
case REPORT_ACKNOWLEDGE_OUTPUT :
break;
default :
break;
}
return *this;
}

View File

@ -1,46 +0,0 @@
#ifndef _CONEMU_WIIMOTE_H_
#define _CONEMU_WIIMOTE_H_
#include "../../ControllerEmu.h"
#include <queue>
class HIDReport : public std::queue<u8>
{
public:
template <typename T>
HIDReport& operator<<( const T& t )
{
const u8* const e = ((u8*)&t) + sizeof(t);
const u8* i = (u8*)&t;
for ( ;i<e; ++i )
push(*i);
return *this;
}
};
class Wiimote : public ControllerEmu
{
public:
Wiimote( const unsigned int index );
void Cycle();
Wiimote& operator<<( HIDReport& );
std::string GetName() const;
private:
Buttons* m_buttons;
Buttons* m_dpad;
ControlGroup* m_rumble;
// TODO: add forces
// TODO: add ir
const unsigned int m_index;
unsigned int m_report_mode;
};
#endif

View File

@ -1,7 +1,6 @@
#include "GCPad.h"
#include "GCPadEmu.h"
// this is all temporary, but sticking with the padspecs ...for now
const u16 button_bitmasks[] =
{
PAD_BUTTON_A,

View File

@ -1,7 +1,7 @@
#ifndef _CONEMU_GCPAD_H_
#define _CONEMU_GCPAD_H_
#include "../../ControllerEmu.h"
#include <ControllerEmu.h>
class GCPad : public ControllerEmu
{

View File

@ -2,9 +2,10 @@
#include <math.h>
#include "Common.h"
#include "pluginspecs_pad.h"
#include "pluginspecs_wiimote.h"
#include "ControllerInterface/ControllerInterface.h"
#include "GCPadEmu.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigDiag.h"
#endif
@ -16,16 +17,20 @@
#define PLUGIN_VERSION 0x0100
#define PLUGIN_NAME "Dolphin GCPad New"
#ifdef DEBUGFAST
#define PLUGIN_FULL_NAME "Dolphin GCPad New (DebugFast)"
#define PLUGIN_FULL_NAME PLUGIN_NAME" (DebugFast)"
#else
#ifdef _DEBUG
#define PLUGIN_FULL_NAME "Dolphin GCPad New (Debug)"
#define PLUGIN_FULL_NAME PLUGIN_NAME" (Debug)"
#else
#define PLUGIN_FULL_NAME "Dolphin GCPad New"
#define PLUGIN_FULL_NAME PLUGIN_NAME
#endif
#endif
// the plugin
Plugin g_plugin( "GCPadNew", "Pad", "GCPad" );
SPADInitialize *g_PADInitialize = NULL;
#ifdef _WIN32
class wxDLLApp : public wxApp
@ -38,14 +43,6 @@ class wxDLLApp : public wxApp
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
#endif
// copied from GCPad
SPADInitialize *g_PADInitialize = NULL;
// Check if Dolphin is in focus
// ----------------
bool IsFocus()
{
return g_PADInitialize->pRendererHasFocus();
}
// copied from GCPad
HINSTANCE g_hInstance;
@ -67,8 +64,6 @@ wxWindow* GetParentedWxWindow(HWND Parent)
#endif
// /
// the plugin
Plugin g_plugin;
#ifdef _WIN32
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
@ -90,18 +85,32 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
}
#endif
void DeInitPlugin()
{
// i realize i am checking IsInit() twice, just too lazy to change it
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();
int _last_numPAD = 4;
g_plugin.controller_interface.DeInit();
}
}
// if plugin isn't initialized, init and load config
void InitPlugin( void* const hwnd )
{
//g_plugin.controls_crit.Enter(); // enter
//g_plugin.interface_crit.Enter();
// i realize i am checking IsInit() twice, just too lazy to change it
if ( false == g_plugin.controller_interface.IsInit() )
{
// add 4 gcpads
for ( unsigned int i = 0; i<4; ++i )
g_plugin.controllers.push_back( new GCPad( i ) );
// load the saved controller config
g_plugin.LoadConfig();
@ -116,9 +125,6 @@ void InitPlugin( void* const hwnd )
(*i)->UpdateReferences( g_plugin.controller_interface );
}
//g_plugin.interface_crit.Leave();
//g_plugin.controls_crit.Leave(); // leave
}
// I N T E R F A C E
@ -131,10 +137,6 @@ void InitPlugin( void* const hwnd )
//
void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
{
// why not, i guess
if ( NULL == _pPADStatus )
return;
memset( _pPADStatus, 0, sizeof(*_pPADStatus) );
_pPADStatus->err = PAD_ERR_NONE;
// wtf is this?
@ -151,6 +153,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// if we are on the next input cycle, update output and input
// if we can get a lock
static int _last_numPAD = 4;
if ( _numPAD <= _last_numPAD && g_plugin.interface_crit.TryEnter() )
{
g_plugin.controller_interface.UpdateOutput();
@ -160,7 +163,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
_last_numPAD = _numPAD;
// if we want background input or have focus
if ( g_plugin.controllers[_numPAD]->options[0].settings[0]->value || IsFocus() )
if ( g_plugin.controllers[_numPAD]->options[0].settings[0]->value || g_PADInitialize->pRendererHasFocus() )
{
// get input
((GCPad*)g_plugin.controllers[ _numPAD ])->GetInput( _pPADStatus );
@ -201,7 +204,7 @@ void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
if ( g_plugin.controls_crit.TryEnter() )
{
// only on/off rumble, if we have focus or background input on
if ( g_plugin.controllers[_numPAD]->options[0].settings[0]->value || IsFocus() )
if ( g_plugin.controllers[_numPAD]->options[0].settings[0]->value || g_PADInitialize->pRendererHasFocus() )
((GCPad*)g_plugin.controllers[ _numPAD ])->SetOutput( 1 == _uType && _uStrength > 2 );
// leave
@ -241,7 +244,7 @@ void DllConfig(HWND _hParent)
#if defined(HAVE_X11) && HAVE_X11
Display *dpy = NULL;
#endif
if ( g_plugin.controller_interface.IsInit() ) // hack for showing dialog when game isnt running
if ( g_plugin.controller_interface.IsInit() ) // check if game is running
was_init = true;
else
{
@ -278,12 +281,12 @@ void DllConfig(HWND _hParent)
#endif
// /
if ( !was_init ) // hack for showing dialog when game isnt running
if ( !was_init ) // if game is running
{
#if defined(HAVE_X11) && HAVE_X11
XCloseDisplay(dpy);
#endif
g_plugin.controller_interface.DeInit();
DeInitPlugin();
}
}
@ -331,10 +334,8 @@ void Initialize(void *init)
//
void Shutdown(void)
{
//plugin.controls_crit.Enter(); // enter
if ( g_plugin.controller_interface.IsInit() )
g_plugin.controller_interface.DeInit();
//plugin.controls_crit.Leave(); // leave
DeInitPlugin();
}
// ___________________________________________________________________________

View File

@ -653,6 +653,18 @@
>
</File>
</Filter>
<Filter
Name="UDP Wiimote"
>
<File
RelativePath=".\Src\UDPWiimote.cpp"
>
</File>
<File
RelativePath=".\Src\UDPWiimote.h"
>
</File>
</Filter>
<File
RelativePath=".\Src\main.cpp"
>

View File

@ -0,0 +1,591 @@
<?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;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
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 winmm.lib wiiuse.lib rpcrt4.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\Win32/Plugins\Plugin_WiimoteNewD.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;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
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 winmm.lib wiiuse.lib rpcrt4.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_WiimoteNewD.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;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
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 wiiuse.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_WiimoteNew.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"
AdditionalIncludeDirectories="..\..\PluginSpecs;..\..\..\Externals\SDL\Include;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
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 wiiuse.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_WiimoteNew.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;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
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 wiiuse.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_WiimoteNewDF.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;..\..\Core\Common\Src;..\..\Core\InputPluginCommon\Src;..\..\Core\InputCommon\Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
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 wiiuse.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_WiimoteNewDF.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="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\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\Nunchuk.cpp"
>
</File>
<File
RelativePath=".\Src\WiimoteEmu\Attachment\Nunchuk.h"
>
</File>
</Filter>
</Filter>
<File
RelativePath=".\Src\WiimoteNew.cpp"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,36 @@
#include "Attachment.h"
namespace WiimoteEmu
{
// Extension device IDs to be written to the last bytes of the extension reg
static const u8 gh3glp_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x01, 0x03 };
static const u8 ghwtdrums_id[] = { 0x01, 0x00, 0xa4, 0x20, 0x01, 0x03 };
// 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 )
{
((WiimoteEmu::Attachment*)attachments[ active_extension ])->GetState( data );
}

View File

@ -0,0 +1,30 @@
#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 ) {}
std::string GetName() const;
const char* const name;
std::vector<u8> reg;
};
class None : public Attachment
{
public:
None();
};
}
#endif

View File

@ -0,0 +1,143 @@
#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
};
// classic buttons
#define CLASSIC_PAD_RIGHT 0x80
#define CLASSIC_PAD_DOWN 0x40
#define CLASSIC_TRIGGER_L 0x20
#define CLASSIC_MINUS 0x10
#define CLASSIC_HOME 0x08
#define CLASSIC_PLUS 0x04
#define CLASSIC_TRIGGER_R 0x02
#define CLASSIC_NOTHING 0x01
#define CLASSIC_ZL 0x8000
#define CLASSIC_B 0x4000
#define CLASSIC_Y 0x2000
#define CLASSIC_A 0x1000
#define CLASSIC_X 0x0800
#define CLASSIC_ZR 0x0400
#define CLASSIC_PAD_LEFT 0x0200
#define CLASSIC_PAD_UP 0x0100
const u16 classic_button_bitmasks[] =
{
CLASSIC_A,
CLASSIC_B,
CLASSIC_X,
CLASSIC_Y,
CLASSIC_ZL,
CLASSIC_ZR,
CLASSIC_MINUS,
CLASSIC_PLUS,
CLASSIC_HOME,
};
const char* classic_button_names[] =
{
"A","B","X","Y","ZL","ZR","Minus","Plus","Home",
};
const u16 classic_trigger_bitmasks[] =
{
CLASSIC_TRIGGER_L, CLASSIC_TRIGGER_R,
};
const char* const classic_trigger_names[] =
{
"L", "R", "L-Analog", "R-Analog"
};
const u16 classic_dpad_bitmasks[] =
{
CLASSIC_PAD_UP, CLASSIC_PAD_DOWN, CLASSIC_PAD_LEFT, CLASSIC_PAD_RIGHT
};
Classic::Classic() : Attachment( "Classic Controller" )
{
// 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 )
{
wm_classic_extension* const ccdata = (wm_classic_extension*)data;
// left stick
{
u8 x, y;
m_left_stick->GetState( &x, &y, 0x20, 0x1F /*0x15*/ );
ccdata->lx = x;
ccdata->ly = y;
}
// right stick
{
u8 x, y;
m_right_stick->GetState( &x, &y, 0x10, 0x0F /*0x0C*/ );
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, 0x1F );
ccdata->lt1 = trigs[0];
ccdata->lt2 = trigs[0] >> 3;
ccdata->rt = trigs[1];
}
// 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

@ -0,0 +1,22 @@
#include "Attachment.h"
namespace WiimoteEmu
{
class Classic : public Attachment
{
public:
Classic();
void GetState( u8* const data );
private:
Buttons* m_buttons;
Buttons* m_shake;
MixedTriggers* m_triggers;
Buttons* m_dpad;
AnalogStick* m_left_stick;
AnalogStick* m_right_stick;
};
}

View File

@ -0,0 +1,107 @@
#include "Nunchuk.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,
0xee, 0x43 // checksum on the last two bytes
};
// nunchuk buttons
#define NUNCHUK_C 0x02
#define NUNCHUK_Z 0x01
const u8 nunchuk_button_bitmasks[] =
{
NUNCHUK_C,
NUNCHUK_Z,
};
Nunchuk::Nunchuk() : Attachment( "Nunchuk" )
{
// 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" ) );
// force
//groups.push_back( m_tilt = new Tilt( "Tilt" ) );
groups.push_back( m_tilt = new Tilt( "Pitch and Roll" ) );
//groups.push_back( m_swing = new Force( "Swing" ) );
// 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) );
}
void Nunchuk::GetState( u8* const data )
{
wm_extension* const ncdata = (wm_extension*)data;
// stick / not using calibration data for stick, o well
m_stick->GetState( &ncdata->jx, &ncdata->jy, 0x80, 127 );
// tilt
float x, y;
m_tilt->GetState( &x, &y, 0, (PI / 2) ); // 90 degrees
// this isn't doing anything with those low bits in the calib data, o well
const accel_cal* const cal = (accel_cal*)&reg[0x20];
const u8* const zero_g = &cal->zero_g.x;
u8 one_g[3];
for ( unsigned int i=0; i<3; ++i )
one_g[i] = (&cal->one_g.x)[i] - zero_g[i];
// this math should be good enough :P
ncdata->az = u8(sin( (PI / 2) - std::max( abs(x), abs(y) ) ) * one_g[2] + zero_g[2]);
ncdata->ax = u8(sin(x) * -one_g[0] + zero_g[0]);
ncdata->ay = u8(sin(y) * one_g[1] + zero_g[1]);
// shake
const unsigned int btns[] = { 0x01, 0x02, 0x04 };
unsigned int shake = 0;
m_shake->GetState( &shake, btns );
static unsigned int shake_step = 0;
if (shake)
{
shake_step = (shake_step + 1) % sizeof(shake_data);
for ( unsigned int i=0; i<3; ++i )
if ( shake & (1 << i) )
(&ncdata->ax)[i] = shake_data[shake_step];
}
else
shake_step = 0;
// buttons
m_buttons->GetState( &ncdata->bt, nunchuk_button_bitmasks );
// flip the button bits :/
ncdata->bt ^= 0x3;
}
}

View File

@ -0,0 +1,23 @@
#include "Attachment.h"
namespace WiimoteEmu
{
class Nunchuk : public Attachment
{
public:
Nunchuk();
void GetState( u8* const data );
private:
Tilt* m_tilt;
Force* m_swing;
Buttons* m_shake;
Buttons* m_buttons;
AnalogStick* m_stick;
};
}

View File

@ -0,0 +1,443 @@
// 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 "pluginspecs_wiimote.h"
#include "WiimoteEmu.h"
#include "Attachment/Attachment.h"
/* 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];
}
namespace WiimoteEmu
{
void Wiimote::ReportMode(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);
// should I use the rumble var in here?
//m_rumble->controls[0]->control_ref->State( dr->rumble );
m_reporting_auto = dr->all_the_time;
m_reporting_mode = dr->mode;
m_reporting_channel = _channelID;
if (0 == dr->all_the_time)
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);
break;
}
}
/* 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(u16 _channelID, wm_report* sr)
{
INFO_LOG(WIIMOTE, "HidOutputReport (page: %i, cid: 0x%02x, wm: 0x%02x)", m_index, _channelID, sr->wm);
switch (sr->wm)
{
case WM_RUMBLE : // 0x10
m_rumble->controls[0]->control_ref->State( sr->data[0] > 0 );
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(_channelID, (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->data[0] & 0x04) ? 1 : 0;
break;
case WM_SPEAKER_ENABLE : // 0x14
//INFO_LOG(WIIMOTE, "WM Speaker Enable: 0x%02x", sr->data[0]);
m_status.speaker = (sr->data[0] & 0x04) ? 1 : 0;
break;
case WM_REQUEST_STATUS : // 0x15
RequestStatus(_channelID, (wm_request_status*)sr->data);
return; // sends its own ack
break;
case WM_WRITE_DATA : // 0x16
WriteData(_channelID, (wm_write_data*)sr->data);
break;
case WM_READ_DATA : // 0x17
ReadData(_channelID, (wm_read_data*)sr->data);
return; // sends its own ack
break;
case WM_WRITE_SPEAKER_DATA : // 0x18
// 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]);
//m_speaker_mute = (sr->data[0] & 0x04) ? 1 : 0;
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->data[0] & 0x04) ? 1 : 0;
break;
default:
PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->wm);
return; // no ack
break;
}
// send ack
SendAck(_channelID, 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(u16 _channelID, 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;
m_wiimote_init->pWiimoteInput( m_index, _channelID, data, sizeof(data));
}
/* 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(u16 _channelID, wm_request_status* rs, int Extension)
{
// handle switch extension
if ( m_extension->active_extension != m_extension->switch_extension )
{
if ( m_extension->active_extension && m_extension->switch_extension )
// detach extension first
m_extension->active_extension = 0;
else
m_extension->active_extension = m_extension->switch_extension;
// set register, I hate this line
m_register[ 0xa40000 ] = ((WiimoteEmu::Attachment*)m_extension->attachments[ m_extension->active_extension ])->reg;
// Wiibrew: Following a connection or disconnection event on the Extension Port,
// data reporting is disabled and the Data Reporting Mode must be reset before new data can arrive.
m_reporting_auto = false;
}
// extension status
m_status.extension = m_extension->active_extension ? 1 : 0;
// set up report
u8 data[8];
data[0] = 0xA1;
data[1] = WM_STATUS_REPORT;
// status values
*(wm_status_report*)(data + 2) = m_status;
// send report
m_wiimote_init->pWiimoteInput(m_index, _channelID, data, sizeof(data));
}
/* Write data to Wiimote and Extensions registers. */
void Wiimote::WriteData(u16 _channelID, wm_write_data* wd)
{
u32 address = convert24bit(wd->address);
// this is done in ReadDate, but not here in WriteData ?
//u16 size = convert16bit(rd->size);
if (wd->size > 16)
{
PanicAlert("WriteData: size is > 16 bytes");
return;
}
switch (wd->space)
{
case WM_SPACE_EEPROM :
{
static bool first = true;
if (first)
{
PanicAlert("WriteData: first write to EEPROM");
first = false;
}
// 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);
}
break;
case WM_SPACE_REGS1 :
case WM_SPACE_REGS2 :
{
// Write to Control Register
// ignore the 0x010000 bit
address &= 0xFEFFFF;
// 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)
{
// 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 )
{
u8 data[WIIMOTE_REG_EXT_SIZE];
m_register.Read( 0xa40000, data, WIIMOTE_REG_EXT_SIZE );
wiimote_gen_key( &m_ext_key, data + 0x40 );
}
}
break;
}
}
break;
default:
PanicAlert("WriteData: unimplemented parameters!");
break;
}
}
/* Read data from Wiimote and Extensions registers. */
void Wiimote::ReadData(u16 _channelID, wm_read_data* rd)
{
u32 address = convert24bit(rd->address);
u16 size = convert16bit(rd->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)
{
// generate a read error
size = 0;
if (address + size > WIIMOTE_EEPROM_SIZE)
{
PanicAlert("ReadData: address + size out of bounds");
return;
}
}
SendReadDataReply(_channelID, m_eeprom + address, address, size);
}
break;
case WM_SPACE_REGS1 :
case WM_SPACE_REGS2 :
{
// Read from Control Register
// ignore the 0x010000 bit
address &= 0xFEFFFF;
// ignore second byte for extension area
if (0xA4 == (address >> 16))
address &= 0xFF00FF;
u8* const block = new u8[ size ];
m_register.Read( address, block, size );
switch (address >> 16)
{
case 0xa4 :
{
// Encrypt data read from extension register
// Check if encrypted reads is on
if ( m_reg_ext[0xf0] == 0xaa )
{
// I probably totally f'ed this up
wiimote_encrypt(&m_ext_key, block, address & 0xffff, (u8)size);
}
}
break;
case 0xa6 :
{
// motion plus crap copied from old wiimote plugin
//block[0xFC] = 0xA6;
//block[0xFD] = 0x20;
//block[0xFE] = 0x00;
//block[0xFF] = 0x05;
}
break;
}
// Let this function process the message and send it to the Wii
SendReadDataReply(_channelID, block, address, (int)size);
delete[] block;
}
break;
default :
PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x)!", size, rd->space);
break;
}
}
/* 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 Wiimote::SendReadDataReply(u16 _channelID, const void* _Base, unsigned int _Address, unsigned int _Size)
{
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->error = 0;
// 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 == _Size)
{
reply->size = 0x0f;
reply->error = 0x08;
memset(reply->data, 0, sizeof(reply->data));
m_wiimote_init->pWiimoteInput(m_index, _channelID, data, sizeof(data));
}
while (_Size)
{
// Limit the amt to 16 bytes
// AyuanX: the MTU is 640B though... what a waste!
const int amt = std::min( (unsigned int)16, _Size );
// 0x1 means two bytes, 0xf means 16 bytes
reply->size = amt - 1;
reply->address = Common::swap16(_Address);
// Clear the mem first
memset(reply->data, 0, sizeof(reply->data));
// copy piece of mem
memcpy(reply->data, _Base, amt);
// Send a piece
m_wiimote_init->pWiimoteInput(m_index, _channelID, data, sizeof(data));
// advance pointers
_Size -= amt;
_Base = (u8*)_Base + amt;
_Address += amt;
}
}
}

View File

@ -0,0 +1,296 @@
// 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

@ -0,0 +1,41 @@
// 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(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

@ -0,0 +1,492 @@
#include "Attachment/Classic.h"
#include "Attachment/Nunchuk.h"
#include "WiimoteEmu.h"
#include "WiimoteHid.h"
#include <Timer.h>
#include <Common.h>
// buttons
#define WIIMOTE_PAD_LEFT 0x01
#define WIIMOTE_PAD_RIGHT 0x02
#define WIIMOTE_PAD_DOWN 0x04
#define WIIMOTE_PAD_UP 0x08
#define WIIMOTE_PLUS 0x10
#define WIIMOTE_TWO 0x0100
#define WIIMOTE_ONE 0x0200
#define WIIMOTE_B 0x0400
#define WIIMOTE_A 0x0800
#define WIIMOTE_MINUS 0x1000
#define WIIMOTE_HOME 0x8000
namespace WiimoteEmu
{
/* 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 eeprom_data_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 eeprom_data_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
};
// array of accel data to emulate shaking
static const u8 shake_data[8] = { 0x80, 0x40, 0x01, 0x40, 0x80, 0xC0, 0xFF, 0xC0 };
const u16 button_bitmasks[] =
{
WIIMOTE_A, WIIMOTE_B, WIIMOTE_ONE, WIIMOTE_TWO, WIIMOTE_MINUS, WIIMOTE_PLUS, WIIMOTE_HOME
};
const u16 dpad_bitmasks[] =
{
WIIMOTE_PAD_UP, WIIMOTE_PAD_DOWN, WIIMOTE_PAD_LEFT, WIIMOTE_PAD_RIGHT
};
const u16 dpad_sideways_bitmasks[] =
{
WIIMOTE_PAD_RIGHT, WIIMOTE_PAD_LEFT, WIIMOTE_PAD_UP, WIIMOTE_PAD_DOWN
};
const char* const named_buttons[] =
{
"A",
"B",
"One",
"Two",
"Minus",
"Plus",
"Home",
};
void Wiimote::Reset()
{
m_reporting_mode = WM_REPORT_CORE;
// i think these two are good
m_reporting_channel = 0;
m_reporting_auto = false;
// eeprom
memset( m_eeprom, 0, sizeof(m_eeprom) );
// calibration data
memcpy( m_eeprom, eeprom_data_0, sizeof(eeprom_data_0) );
// dunno what this is for, copied from old plugin
memcpy( m_eeprom + 0x16D0, eeprom_data_16D0, sizeof(eeprom_data_16D0) );
// set up the register
m_register.clear();
m_register[0xa20000].resize(WIIMOTE_REG_SPEAKER_SIZE,0);
m_register[0xa40000].resize(WIIMOTE_REG_EXT_SIZE,0);
m_register[0xa60000].resize(WIIMOTE_REG_EXT_SIZE,0);
m_register[0xB00000].resize(WIIMOTE_REG_IR_SIZE,0);
//m_reg_speaker = &m_register[0xa20000][0];
m_reg_ext = &m_register[0xa40000][0];
//m_reg_motion_plus = &m_register[0xa60000][0];
//m_reg_ir = &m_register[0xB00000][0];
// status
memset( &m_status, 0, sizeof(m_status) );
// Battery levels in voltage
// 0x00 - 0x32: level 1
// 0x33 - 0x43: level 2
// 0x33 - 0x54: level 3
// 0x55 - 0xff: level 4
m_status.battery = 0x5f;
}
Wiimote::Wiimote( const unsigned int index, SWiimoteInitialize* const wiimote_initialize )
: m_index(index)
, m_wiimote_init( wiimote_initialize )
{
// reset eeprom/register/values to default
Reset();
// ---- set up all the controls ----
// buttons
groups.push_back( m_buttons = new Buttons( "Buttons" ) );
for ( unsigned int i=0; i < sizeof(named_buttons)/sizeof(*named_buttons); ++i )
m_buttons->controls.push_back( new ControlGroup::Input( named_buttons[i] ) );
// ir
//groups.push_back( m_rumble = new ControlGroup( "IR" ) );
//m_rumble->controls.push_back( new ControlGroup::Output( "X" ) );
//m_rumble->controls.push_back( new ControlGroup::Output( "Y" ) );
//m_rumble->controls.push_back( new ControlGroup::Output( "Distance" ) );
//m_rumble->controls.push_back( new ControlGroup::Output( "Hide" ) );
// forces
groups.push_back( m_tilt = new Tilt( "Pitch and Roll" ) );
//groups.push_back( m_tilt = new Tilt( "Tilt" ) );
//groups.push_back( m_swing = new Force( "Swing" ) );
// 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" ) );
// extension
groups.push_back( m_extension = new Extension( "Extension" ) );
m_extension->attachments.push_back( new WiimoteEmu::None() );
m_extension->attachments.push_back( new WiimoteEmu::Nunchuk() );
m_extension->attachments.push_back( new WiimoteEmu::Classic() );
//m_extension->attachments.push_back( new Attachment::GH3() );
// 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] ) );
// rumble
groups.push_back( m_rumble = new ControlGroup( "Rumble" ) );
m_rumble->controls.push_back( new ControlGroup::Output( "Motor" ) );
// options
groups.push_back( options = new ControlGroup( "Options" ) );
options->settings.push_back( new ControlGroup::Setting( "Background Input", false ) );
options->settings.push_back( new ControlGroup::Setting( "Sideways Wiimote", false ) );
}
std::string Wiimote::GetName() const
{
return std::string("Wiimote") + char('1'+m_index);
}
void Wiimote::Update()
{
const bool is_sideways = options->settings[1]->value > 0;
// update buttons in status struct
m_status.buttons = 0;
m_buttons->GetState( &m_status.buttons, button_bitmasks );
m_dpad->GetState( &m_status.buttons, is_sideways ? dpad_sideways_bitmasks : dpad_bitmasks );
if ( false == m_reporting_auto )
return;
// handle extension switching
if ( m_extension->active_extension != m_extension->switch_extension )
{
RequestStatus( m_reporting_channel, NULL );
// games don't seem to like me sending the status report and the data report
return;
}
// figure out what data we need
size_t rpt_size = 0;
size_t rpt_core = 0;
size_t rpt_accel = 0;
size_t rpt_ir = 0;
size_t rpt_ext = 0;
switch ( m_reporting_mode )
{
//(a1) 30 BB BB
case WM_REPORT_CORE :
rpt_size = 2 + 2;
rpt_core = 2;
break;
//(a1) 31 BB BB AA AA AA
case WM_REPORT_CORE_ACCEL :
rpt_size = 2 + 2 + 3;
rpt_core = 2;
rpt_accel = 2 + 2;
break;
//(a1) 33 BB BB AA AA AA II II II II II II II II II II II II
case WM_REPORT_CORE_ACCEL_IR12 :
rpt_size = 2 + 2 + 3 + 12;
rpt_core = 2;
rpt_accel = 2 + 2;
rpt_ir = 2 + 2 + 3;
break;
//(a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
case WM_REPORT_CORE_ACCEL_EXT16 :
rpt_size = 2 + 2 + 3 + 16;
rpt_core = 2;
rpt_accel = 2 + 2;
rpt_ext = 2 + 2 + 3;
break;
//(a1) 37 BB BB AA AA AA II II II II II II II II II II EE EE EE EE EE EE
case WM_REPORT_CORE_ACCEL_IR10_EXT6 :
rpt_size = 2 + 2 + 3 + 10 + 6;
rpt_core = 2;
rpt_accel = 2 + 2;
rpt_ir = 2 + 2 + 3;
rpt_ext = 2 + 2 + 3 + 10;
break;
default :
//PanicAlert( "Unsupported Reporting Mode" );
return;
break;
}
// set up output report
u8* const rpt = new u8[rpt_size];
memset( rpt, 0, rpt_size );
rpt[0] = 0xA1;
rpt[1] = m_reporting_mode;
// core buttons - always 2
if (rpt_core)
*(wm_core*)(rpt + rpt_core) = m_status.buttons;
// accelerometer
if (rpt_accel)
{
// tilt
float x, y;
m_tilt->GetState( &x, &y, 0, (PI / 2) ); // 90 degrees
// this isn't doing anything with those low bits in the calib data, o well
const accel_cal* const cal = (accel_cal*)&m_eeprom[0x16];
const u8* const zero_g = &cal->zero_g.x;
u8 one_g[3];
for ( unsigned int i=0; i<3; ++i )
one_g[i] = (&cal->one_g.x)[i] - zero_g[i];
// this math should be good enough :P
rpt[rpt_accel + 2] = u8(sin( (PI / 2) - std::max( abs(x), abs(y) ) ) * one_g[2] + zero_g[2]);
if (is_sideways)
{
rpt[rpt_accel + 0] = u8(sin(y) * -one_g[1] + zero_g[1]);
rpt[rpt_accel + 1] = u8(sin(x) * -one_g[0] + zero_g[0]);
}
else
{
rpt[rpt_accel + 0] = u8(sin(x) * -one_g[0] + zero_g[0]);
rpt[rpt_accel + 1] = u8(sin(y) * one_g[1] + zero_g[1]);
}
// shake
const unsigned int btns[] = { 0x01, 0x02, 0x04 };
unsigned int shake = 0;
m_shake->GetState( &shake, btns );
static unsigned int shake_step = 0;
if (shake)
{
shake_step = (shake_step + 1) % sizeof(shake_data);
for ( unsigned int i=0; i<3; ++i )
if ( shake & (1 << i) )
rpt[rpt_accel + i] = shake_data[shake_step];
}
else
shake_step = 0;
}
// TODO: IR
if (rpt_ir)
{
}
// extension
if (rpt_ext)
{
// temporary
m_extension->GetState(rpt + rpt_ext);
wiimote_encrypt(&m_ext_key, rpt + rpt_ext, 0x00, sizeof(wm_extension));
// i dont think anything accesses the extension data like this, but ill support it
memcpy( m_reg_ext + 8, rpt + rpt_ext, sizeof(wm_extension));
}
// send input report
m_wiimote_init->pWiimoteInput( m_index, m_reporting_channel, rpt, (u32)rpt_size );
delete[] rpt;
}
void Wiimote::ControlChannel(u16 _channelID, const void* _pData, u32 _Size)
{
// Check for custom communication
if (99 == _channelID)
{
// wiimote disconnected
//PanicAlert( "Wiimote Disconnected" );
// reset eeprom/register/reporting mode
Reset();
return;
}
hid_packet* hidp = (hid_packet*)_pData;
INFO_LOG(WIIMOTE, "Emu ControlChannel (page: %i, type: 0x%02x, param: 0x%02x)", m_index, 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 (HID_PARAM_INPUT == hidp->param)
{
PanicAlert("HID_TYPE_SET_REPORT - INPUT");
}
else
{
// AyuanX: My experiment shows Control Channel is never used
// shuffle2: but homebrew uses this, so we'll do what we must :)
HidOutputReport(_channelID, (wm_report*)hidp->data);
u8 handshake = HID_HANDSHAKE_SUCCESS;
m_wiimote_init->pWiimoteInput(m_index, _channelID, &handshake, 1);
PanicAlert("HID_TYPE_DATA - OUTPUT: Ambiguous Control Channel Report!");
}
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;
}
}
void Wiimote::InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
{
hid_packet* hidp = (hid_packet*)_pData;
switch (hidp->type)
{
case HID_TYPE_DATA:
switch (hidp->param)
{
case HID_PARAM_OUTPUT :
{
wm_report* sr = (wm_report*)hidp->data;
HidOutputReport(_channelID, sr);
}
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;
}
}
// TODO: i need to test this
void Wiimote::Register::Read( size_t address, void* dst, size_t length )
{
while (length)
{
const std::vector<u8>* block = NULL;
size_t addr_start = 0;
size_t addr_end = address+length;
// TODO: don't need to start at begin() each time
// find block and start of next block
const_iterator
i = begin(),
e = end();
for ( ; i!=e; ++i )
if ( address >= i->first )
{
block = &i->second;
addr_start = i->first;
}
else
{
addr_end = std::min( i->first, addr_end );
break;
}
// read bytes from a mapped block
if (block)
{
const size_t offset = std::min( address - addr_start, block->size() );
const size_t amt = std::min( block->size()-offset, length );
memcpy( dst, &block->operator[](offset), amt );
address += amt;
dst = ((u8*)dst) + amt;
length -= amt;
}
// read zeros for unmapped regions
const size_t amt = addr_end - address;
memset( dst, 0, amt );
address += amt;
dst = ((u8*)dst) + amt;
length -= amt;
}
}
// TODO: i need to test this
void Wiimote::Register::Write( size_t address, void* src, size_t length )
{
while (length)
{
std::vector<u8>* block = NULL;
size_t addr_start = 0;
size_t addr_end = address+length;
// TODO: don't need to start at begin() each time
// find block and start of next block
iterator
i = begin(),
e = end();
for ( ; i!=e; ++i )
if ( address >= i->first )
{
block = &i->second;
addr_start = i->first;
}
else
{
addr_end = std::min( i->first, addr_end );
break;
}
// write bytes to a mapped block
if (block)
{
const size_t offset = std::min( address - addr_start, block->size() );
const size_t amt = std::min( block->size()-offset, length );
memcpy( &block->operator[](offset), src, amt );
address += amt;
src = ((u8*)src) + amt;
length -= amt;
}
// do nothing for unmapped regions
const size_t amt = addr_end - address;
address += amt;
src = ((u8*)src) + amt;
length -= amt;
}
}
}

View File

@ -0,0 +1,89 @@
#ifndef _CONEMU_WIIMOTE_H_
#define _CONEMU_WIIMOTE_H_
#include <ControllerEmu.h>
#include "WiimoteHid.h"
#include "Encryption.h"
#include <vector>
#define PI 3.14159265358979323846
// 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
namespace WiimoteEmu
{
extern const u8 shake_data[8];
class Wiimote : public ControllerEmu
{
public:
Wiimote( const unsigned int index, SWiimoteInitialize* const wiimote_initialize );
void Reset();
void Update();
void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size);
void ControlChannel(u16 _channelID, const void* _pData, u32 _Size);
void ReportMode(u16 _channelID, wm_report_mode* dr);
void HidOutputReport(u16 _channelID, wm_report* sr);
void SendAck(u16 _channelID, u8 _reportID);
void RequestStatus(u16 _channelID, wm_request_status* rs, int Extension = -1);
void WriteData(u16 _channelID, wm_write_data* wd);
void ReadData(u16 _channelID, wm_read_data* rd);
void SendReadDataReply(u16 _channelID, const void* _Base, unsigned int _Address, unsigned int _Size);
std::string GetName() const;
private:
SWiimoteInitialize* const m_wiimote_init;
Buttons* m_buttons;
Buttons* m_dpad;
Buttons* m_shake;
Tilt* m_tilt;
Force* m_swing;
ControlGroup* m_rumble;
Extension* m_extension;
// TODO: add ir
const unsigned int m_index;
bool m_reporting_auto;
unsigned int m_reporting_mode;
unsigned int m_reporting_channel;
wm_status_report m_status;
class Register : public std::map< size_t, std::vector<u8> >
{
public:
void Write( size_t address, void* src, size_t length );
void Read( size_t address, void* dst, size_t length );
} m_register;
//u8 m_eeprom[WIIMOTE_EEPROM_SIZE];
u8 m_eeprom[WIIMOTE_EEPROM_SIZE];
//u8* m_reg_speaker;
//u8* m_reg_motion_plus;
//u8* m_reg_ir;
u8* m_reg_ext;
wiimote_key m_ext_key;
};
}
#endif

View File

@ -0,0 +1,339 @@
// 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_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
{
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

@ -0,0 +1,348 @@
#include <math.h>
#include "Common.h"
#include "pluginspecs_wiimote.h"
#include "ControllerInterface/ControllerInterface.h"
#include "WiimoteEmu/WiimoteEmu.h"
#if defined(HAVE_WX) && HAVE_WX
#include "ConfigDiag.h"
#endif
#include "Config.h"
#if defined(HAVE_X11) && HAVE_X11
#include <X11/Xlib.h>
Display* GCdisplay;
#endif
#define PLUGIN_VERSION 0x0100
#define PLUGIN_NAME "Dolphin Wiimote New Incomplete"
#ifdef DEBUGFAST
#define PLUGIN_FULL_NAME PLUGIN_NAME" (DebugFast)"
#else
#ifdef _DEBUG
#define PLUGIN_FULL_NAME PLUGIN_NAME" (Debug)"
#else
#define PLUGIN_FULL_NAME PLUGIN_NAME
#endif
#endif
#ifdef _WIN32
class wxDLLApp : public wxApp
{
bool OnInit()
{
return true;
};
};
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
#endif
// copied from GCPad
SWiimoteInitialize g_WiimoteInitialize;
// Check if Dolphin is in focus
// ----------------
bool IsFocus()
{
// TODO: this
return true;
}
// copied from GCPad
HINSTANCE g_hInstance;
// copied from GCPad
#if defined(HAVE_WX) && HAVE_WX
wxWindow* GetParentedWxWindow(HWND Parent)
{
#ifdef _WIN32
wxSetInstance((HINSTANCE)g_hInstance);
#endif
wxWindow *win = new wxWindow();
#ifdef _WIN32
win->SetHWND((WXHWND)Parent);
win->AdoptAttributesFromHWND();
#endif
return win;
}
#endif
// /
// the plugin
Plugin g_plugin( "WiimoteNew", "Wiimote", "Wiimote" );
#ifdef _WIN32
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();
g_plugin.controller_interface.DeInit();
}
}
// 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, &g_WiimoteInitialize ) );
// load the saved controller config
g_plugin.LoadConfig();
// needed for Xlib and exclusive dinput
g_plugin.controller_interface.SetHwnd( hwnd );
g_plugin.controller_interface.Init();
// update control refs
std::vector<ControllerEmu*>::const_iterator i = g_plugin.controllers.begin(),
e = g_plugin.controllers.end();
for ( ; i!=e; ++i )
(*i)->UpdateReferences( g_plugin.controller_interface );
}
}
// 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)
{
//PanicAlert( "Wiimote_ControlChannel" );
// TODO: change this to a TryEnter, and make it give empty input on failure
g_plugin.controls_crit.Enter();
((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->ControlChannel( _channelID, _pData, _Size );
g_plugin.controls_crit.Leave();
}
// __________________________________________________________________________________________________
// Function: Wiimote_Input
// 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)
{
//PanicAlert( "Wiimote_InterruptChannel" );
// TODO: change this to a TryEnter, and make it give empty input on failure
g_plugin.controls_crit.Enter();
((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->InterruptChannel( _channelID, _pData, _Size );
g_plugin.controls_crit.Leave();
}
// __________________________________________________________________________________________________
// 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.interface_crit.TryEnter() )
{
g_plugin.controller_interface.UpdateOutput();
g_plugin.controller_interface.UpdateInput();
g_plugin.interface_crit.Leave();
}
_last_number = _number;
((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->Update();
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()
{
//PanicAlert( "Wiimote_GetAttachedControllers" );
// temporary
//return 0x0F;
return 1;
}
// 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(HWND _hParent)
{
bool was_init = false;
if ( g_plugin.controller_interface.IsInit() ) // hack for showing dialog when game isnt running
was_init = true;
else
InitPlugin( _hParent );
// copied from GCPad
#if defined(HAVE_WX) && HAVE_WX
wxWindow *frame = GetParentedWxWindow(_hParent);
ConfigDialog* m_ConfigFrame = new ConfigDialog( frame, g_plugin, PLUGIN_FULL_NAME, was_init );
#ifdef _WIN32
frame->Disable();
m_ConfigFrame->ShowModal();
frame->Enable();
#else
m_ConfigFrame->ShowModal();
#endif
#ifdef _WIN32
wxMilliSleep( 50 ); // hooray for hacks
frame->SetFocus();
frame->SetHWND(NULL);
#endif
m_ConfigFrame->Destroy();
m_ConfigFrame = NULL;
frame->Destroy();
#endif
// /
if ( false == was_init ) // hack for showing dialog when game isnt running
DeInitPlugin();
}
// ___________________________________________________________________________
// Function: DllDebugger
// Purpose: Open the debugger
// input: a handle to the window that calls this function
// output: none
//
void DllDebugger(HWND _hParent, bool Show)
{
// wut?
}
// ___________________________________________________________________________
// 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( ((SPADInitialize*)init)->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)
{
// prolly won't need this
}
// ___________________________________________________________________________
// 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
}