From d8906d2a0ca92b636b2e228da6431621e0cc9479 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 13 Apr 2010 05:15:38 +0000 Subject: [PATCH] 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 --- Source/Core/InputCommon/InputCommon.vcproj | 68 ++ .../ControllerInterface.cpp | 10 +- .../ControllerInterface/ControllerInterface.h | 0 .../DirectInput/DirectInput.cpp | 0 .../DirectInput/DirectInput.h | 0 .../DirectInput/DirectInputJoystick.cpp | 2 - .../DirectInput/DirectInputJoystick.h | 0 .../DirectInput/DirectInputKeyboardMouse.cpp | 4 +- .../DirectInput/DirectInputKeyboardMouse.h | 0 .../DirectInput/NamedKeys.h | 0 .../Src/ControllerInterface/OSX/OSX.cpp | 202 +++--- .../Src/ControllerInterface/OSX/OSX.h | 136 ++-- .../Src/ControllerInterface/OSX/OSXPrivate.h | 0 .../Src/ControllerInterface/OSX/OSXPrivate.mm | 0 .../Src/ControllerInterface/SDL/SDL.cpp | 0 .../Src/ControllerInterface/SDL/SDL.h | 0 .../Src/ControllerInterface/XInput/XInput.cpp | 10 +- .../Src/ControllerInterface/XInput/XInput.h | 0 .../Src/ControllerInterface/Xlib/Xlib.cpp | 0 .../Src/ControllerInterface/Xlib/Xlib.h | 0 .../InputPluginCommon.vcproj | 450 +++++++++++++ .../InputPluginCommon}/Src/Config.cpp | 13 +- .../InputPluginCommon}/Src/Config.h | 12 +- .../InputPluginCommon}/Src/ConfigDiag.cpp | 244 +++++--- .../InputPluginCommon}/Src/ConfigDiag.h | 49 +- .../Src/ConfigDiagBitmaps.cpp | 23 +- .../InputPluginCommon/Src/ControllerEmu.cpp | 258 ++++++++ .../InputPluginCommon}/Src/ControllerEmu.h | 112 +++- .../InputPluginCommon}/Src/IniFile.cpp | 0 .../InputPluginCommon}/Src/IniFile.h | 0 Source/Dolphin.sln | 47 ++ .../Plugin_GCPadNew/Plugin_GCPadNew.vcproj | 162 +---- .../Plugin_GCPadNew/Src/ControllerEmu.cpp | 138 ---- .../Src/ControllerEmu/Wiimote/Wiimote.cpp | 257 -------- .../Src/ControllerEmu/Wiimote/Wiimote.h | 46 -- .../GCPad/GCPad.cpp => GCPadEmu.cpp} | 3 +- .../GCPad/GCPad.h => GCPadEmu.h} | 2 +- .../Plugins/Plugin_GCPadNew/Src/GCPadNew.cpp | 69 +- .../Plugin_Wiimote/Plugin_Wiimote.vcproj | 12 + .../Plugin_WiimoteNew.vcproj | 591 ++++++++++++++++++ .../Src/WiimoteEmu/Attachment/Attachment.cpp | 36 ++ .../Src/WiimoteEmu/Attachment/Attachment.h | 30 + .../Src/WiimoteEmu/Attachment/Classic.cpp | 143 +++++ .../Src/WiimoteEmu/Attachment/Classic.h | 22 + .../Src/WiimoteEmu/Attachment/Nunchuk.cpp | 107 ++++ .../Src/WiimoteEmu/Attachment/Nunchuk.h | 23 + .../Src/WiimoteEmu/EmuSubroutines.cpp | 443 +++++++++++++ .../Src/WiimoteEmu/Encryption.cpp | 296 +++++++++ .../Src/WiimoteEmu/Encryption.h | 41 ++ .../Src/WiimoteEmu/WiimoteEmu.cpp | 492 +++++++++++++++ .../Src/WiimoteEmu/WiimoteEmu.h | 89 +++ .../Src/WiimoteEmu/WiimoteHid.h | 339 ++++++++++ .../Plugin_WiimoteNew/Src/WiimoteNew.cpp | 348 +++++++++++ 53 files changed, 4398 insertions(+), 931 deletions(-) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/ControllerInterface.cpp (98%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/ControllerInterface.h (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/DirectInput/DirectInput.cpp (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/DirectInput/DirectInput.h (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/DirectInput/DirectInputJoystick.cpp (99%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/DirectInput/DirectInputJoystick.h (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.cpp (99%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.h (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/DirectInput/NamedKeys.h (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/OSX/OSX.cpp (95%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/OSX/OSX.h (95%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/OSX/OSXPrivate.h (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/OSX/OSXPrivate.mm (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/SDL/SDL.cpp (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/SDL/SDL.h (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/XInput/XInput.cpp (93%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/XInput/XInput.h (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/Xlib/Xlib.cpp (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputCommon}/Src/ControllerInterface/Xlib/Xlib.h (100%) create mode 100644 Source/Core/InputPluginCommon/InputPluginCommon.vcproj rename Source/{Plugins/Plugin_GCPadNew => Core/InputPluginCommon}/Src/Config.cpp (68%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputPluginCommon}/Src/Config.h (64%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputPluginCommon}/Src/ConfigDiag.cpp (77%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputPluginCommon}/Src/ConfigDiag.h (79%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputPluginCommon}/Src/ConfigDiagBitmaps.cpp (85%) create mode 100644 Source/Core/InputPluginCommon/Src/ControllerEmu.cpp rename Source/{Plugins/Plugin_GCPadNew => Core/InputPluginCommon}/Src/ControllerEmu.h (60%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputPluginCommon}/Src/IniFile.cpp (100%) rename Source/{Plugins/Plugin_GCPadNew => Core/InputPluginCommon}/Src/IniFile.h (100%) delete mode 100644 Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu.cpp delete mode 100644 Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu/Wiimote/Wiimote.cpp delete mode 100644 Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu/Wiimote/Wiimote.h rename Source/Plugins/Plugin_GCPadNew/Src/{ControllerEmu/GCPad/GCPad.cpp => GCPadEmu.cpp} (96%) rename Source/Plugins/Plugin_GCPadNew/Src/{ControllerEmu/GCPad/GCPad.h => GCPadEmu.h} (93%) create mode 100644 Source/Plugins/Plugin_WiimoteNew/Plugin_WiimoteNew.vcproj create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Attachment.cpp create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Attachment.h create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Classic.cpp create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Classic.h create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Nunchuk.cpp create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Nunchuk.h create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Encryption.cpp create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Encryption.h create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp diff --git a/Source/Core/InputCommon/InputCommon.vcproj b/Source/Core/InputCommon/InputCommon.vcproj index ec422e111c..07a107b4ed 100644 --- a/Source/Core/InputCommon/InputCommon.vcproj +++ b/Source/Core/InputCommon/InputCommon.vcproj @@ -408,6 +408,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp similarity index 98% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/ControllerInterface.cpp rename to Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp index bec1b6e58c..448e7ee0cc 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp @@ -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; } // diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/ControllerInterface.h rename to Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInput.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInput.cpp similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInput.cpp rename to Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInput.cpp diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInput.h b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInput.h similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInput.h rename to Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInput.h diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInputJoystick.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.cpp similarity index 99% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInputJoystick.cpp rename to Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.cpp index 5fd209b7c2..44b0e1ee08 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInputJoystick.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.cpp @@ -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 ); diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInputJoystick.h b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.h similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInputJoystick.h rename to Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.h diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.cpp similarity index 99% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.cpp rename to Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.cpp index 6f79af95e3..071a233887 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.cpp @@ -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; diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.h b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.h similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.h rename to Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboardMouse.h diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/NamedKeys.h b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/NamedKeys.h similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/DirectInput/NamedKeys.h rename to Source/Core/InputCommon/Src/ControllerInterface/DirectInput/NamedKeys.h diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/OSX/OSX.cpp b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSX.cpp similarity index 95% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/OSX/OSX.cpp rename to Source/Core/InputCommon/Src/ControllerInterface/OSX/OSX.cpp index 50d07c0121..7cbb858e48 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/OSX/OSX.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSX.cpp @@ -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& 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& 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 diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/OSX/OSX.h b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSX.h similarity index 95% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/OSX/OSX.h rename to Source/Core/InputCommon/Src/ControllerInterface/OSX/OSX.h index e24194cd84..2d28d1afa7 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/OSX/OSX.h +++ b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSX.h @@ -1,68 +1,68 @@ -#ifndef _CIFACE_OSX_H_ -#define _CIFACE_OSX_H_ - -#include "../ControllerInterface.h" - -namespace ciface -{ - namespace OSX - { - - void Init( std::vector& 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& 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 diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/OSX/OSXPrivate.h b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXPrivate.h similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/OSX/OSXPrivate.h rename to Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXPrivate.h diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/OSX/OSXPrivate.mm b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXPrivate.mm similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/OSX/OSXPrivate.mm rename to Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXPrivate.mm diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/SDL/SDL.cpp b/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/SDL/SDL.cpp rename to Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/SDL/SDL.h b/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.h similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/SDL/SDL.h rename to Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.h diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/XInput/XInput.cpp b/Source/Core/InputCommon/Src/ControllerInterface/XInput/XInput.cpp similarity index 93% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/XInput/XInput.cpp rename to Source/Core/InputCommon/Src/ControllerInterface/XInput/XInput.cpp index d2b31a51b5..16d39289c0 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/XInput/XInput.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/XInput/XInput.cpp @@ -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, ¤t_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 diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/XInput/XInput.h b/Source/Core/InputCommon/Src/ControllerInterface/XInput/XInput.h similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/XInput/XInput.h rename to Source/Core/InputCommon/Src/ControllerInterface/XInput/XInput.h diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/Xlib/Xlib.cpp b/Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.cpp similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/Xlib/Xlib.cpp rename to Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.cpp diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/Xlib/Xlib.h b/Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.h similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerInterface/Xlib/Xlib.h rename to Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.h diff --git a/Source/Core/InputPluginCommon/InputPluginCommon.vcproj b/Source/Core/InputPluginCommon/InputPluginCommon.vcproj new file mode 100644 index 0000000000..33827bd5ab --- /dev/null +++ b/Source/Core/InputPluginCommon/InputPluginCommon.vcproj @@ -0,0 +1,450 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Plugins/Plugin_GCPadNew/Src/Config.cpp b/Source/Core/InputPluginCommon/Src/Config.cpp similarity index 68% rename from Source/Plugins/Plugin_GCPadNew/Src/Config.cpp rename to Source/Core/InputPluginCommon/Src/Config.cpp index 713505818a..f8278225fa 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/Config.cpp +++ b/Source/Core/InputPluginCommon/Src/Config.cpp @@ -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(); } diff --git a/Source/Plugins/Plugin_GCPadNew/Src/Config.h b/Source/Core/InputPluginCommon/Src/Config.h similarity index 64% rename from Source/Plugins/Plugin_GCPadNew/Src/Config.h rename to Source/Core/InputPluginCommon/Src/Config.h index 3b6e8c464a..8ab222efc2 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/Config.h +++ b/Source/Core/InputPluginCommon/Src/Config.h @@ -1,16 +1,12 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#define CONFIG_FILE_NAME "GCPadNew.ini" - -#include "ControllerInterface/ControllerInterface.h" +#include #include "Thread.h" #include "FileUtil.h" #include "IniFile.h" #include "ControllerEmu.h" -#include "ControllerEmu/GCPad/GCPad.h" -#include "ControllerEmu/Wiimote/Wiimote.h" #include #include @@ -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 diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ConfigDiag.cpp b/Source/Core/InputPluginCommon/Src/ConfigDiag.cpp similarity index 77% rename from Source/Plugins/Plugin_GCPadNew/Src/ConfigDiag.cpp rename to Source/Core/InputPluginCommon/Src/ConfigDiag.cpp index 85444cf794..6f99574bc2 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/ConfigDiag.cpp +++ b/Source/Core/InputPluginCommon/Src/ConfigDiag.cpp @@ -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::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::const_iterator - i = (*g)->control_buttons.begin(), - e = (*g)->control_buttons.end(); + std::vector::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::const_iterator - si = (*g)->options.begin(), - se = (*g)->options.end(); + // cboxes + std::vector::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; itextctrl->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::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* 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(); diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ConfigDiag.h b/Source/Core/InputPluginCommon/Src/ConfigDiag.h similarity index 79% rename from Source/Plugins/Plugin_GCPadNew/Src/ConfigDiag.h rename to Source/Core/InputPluginCommon/Src/ConfigDiag.h index 48002f493b..ae72d9914d 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/ConfigDiag.h +++ b/Source/Core/InputPluginCommon/Src/ConfigDiag.h @@ -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 #include @@ -21,38 +21,49 @@ #include #include -#include "ControllerInterface/ControllerInterface.h" +#include #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 control_buttons; }; +class ControlGroupsSizer : public wxBoxSizer +{ +public: + ControlGroupsSizer( ControllerEmu* const controller, wxWindow* const parent, wxWindow* const eventsink, std::vector* 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 ); diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ConfigDiagBitmaps.cpp b/Source/Core/InputPluginCommon/Src/ConfigDiagBitmaps.cpp similarity index 85% rename from Source/Plugins/Plugin_GCPadNew/Src/ConfigDiagBitmaps.cpp rename to Source/Core/InputPluginCommon/Src/ConfigDiagBitmaps.cpp index 476f2e4e75..7f97249c17 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/ConfigDiagBitmaps.cpp +++ b/Source/Core/InputPluginCommon/Src/ConfigDiagBitmaps.cpp @@ -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); diff --git a/Source/Core/InputPluginCommon/Src/ControllerEmu.cpp b/Source/Core/InputPluginCommon/Src/ControllerEmu.cpp new file mode 100644 index 0000000000..b97aecca04 --- /dev/null +++ b/Source/Core/InputPluginCommon/Src/ControllerEmu.cpp @@ -0,0 +1,258 @@ +#include "ControllerEmu.h" + +const char modifier[] = "Modifier"; + + +ControllerEmu::~ControllerEmu() +{ + std::vector::const_iterator + i = groups.begin(), + e = groups.end(); + for ( ; i!=e; ++i ) + delete *i; +} + +ControllerEmu::ControlGroup::~ControlGroup() +{ + std::vector::const_iterator + ci = controls.begin(), + ce = controls.end(); + for ( ; ci!=ce; ++ci ) + delete *ci; + + std::vector::const_iterator + si = settings.begin(), + se = settings.end(); + for ( ; si!=se; ++si ) + delete *si; +} + +void ControllerEmu::UpdateReferences( ControllerInterface& devi ) +{ + std::vector::const_iterator + i = groups.begin(), + e = groups.end(); + for ( ; i!=e; ++i ) + { + std::vector::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::const_iterator + ai = ((Extension*)*i)->attachments.begin(), + ae = ((Extension*)*i)->attachments.end(); + for ( ; ai!=ae; ++ai ) + (*ai)->UpdateReferences( devi ); + } + } +} + +void ControllerEmu::UpdateDefaultDevice() +{ + std::vector::const_iterator + i = groups.begin(), + e = groups.end(); + for ( ; i!=e; ++i ) + { + std::vector::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::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::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::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::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::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::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::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::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::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 ) ); +} diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu.h b/Source/Core/InputPluginCommon/Src/ControllerEmu.h similarity index 60% rename from Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu.h rename to Source/Core/InputPluginCommon/Src/ControllerEmu.h index 24e758d24b..be09b740e7 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu.h +++ b/Source/Core/InputPluginCommon/Src/ControllerEmu.h @@ -9,7 +9,7 @@ //#include #include -#include "ControllerInterface/ControllerInterface.h" +#include #include "IniFile.h" #include @@ -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 + 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 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 diff --git a/Source/Plugins/Plugin_GCPadNew/Src/IniFile.cpp b/Source/Core/InputPluginCommon/Src/IniFile.cpp similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/IniFile.cpp rename to Source/Core/InputPluginCommon/Src/IniFile.cpp diff --git a/Source/Plugins/Plugin_GCPadNew/Src/IniFile.h b/Source/Core/InputPluginCommon/Src/IniFile.h similarity index 100% rename from Source/Plugins/Plugin_GCPadNew/Src/IniFile.h rename to Source/Core/InputPluginCommon/Src/IniFile.h diff --git a/Source/Dolphin.sln b/Source/Dolphin.sln index d256c799f5..ab634c77a0 100644 --- a/Source/Dolphin.sln +++ b/Source/Dolphin.sln @@ -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 diff --git a/Source/Plugins/Plugin_GCPadNew/Plugin_GCPadNew.vcproj b/Source/Plugins/Plugin_GCPadNew/Plugin_GCPadNew.vcproj index 625ff1ddb2..cdedc5333f 100644 --- a/Source/Plugins/Plugin_GCPadNew/Plugin_GCPadNew.vcproj +++ b/Source/Plugins/Plugin_GCPadNew/Plugin_GCPadNew.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu.cpp b/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu.cpp deleted file mode 100644 index 9b1482661c..0000000000 --- a/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu.cpp +++ /dev/null @@ -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; gcontrols.size(); ++i ) - devi.UpdateReference( groups[g]->controls[i]->control_ref ); -} - -void ControllerEmu::UpdateDefaultDevice() -{ - std::vector::const_iterator i = groups.begin(), - e = groups.end(); - for ( ; i!=e; ++i ) - { - std::vector::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::const_iterator i = groups.begin(), - e = groups.end(); - for ( ; i!=e; ++i ) - { - std::string group( (*i)->name ); group += "/"; - - // settings - std::vector::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::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::const_iterator i = groups.begin(), - e = groups.end(); - for ( ; i!=e; ++i ) - { - std::string group( (*i)->name ); group += "/"; - - // settings - std::vector::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::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 ) ); -} diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu/Wiimote/Wiimote.cpp b/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu/Wiimote/Wiimote.cpp deleted file mode 100644 index fb76230533..0000000000 --- a/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu/Wiimote/Wiimote.cpp +++ /dev/null @@ -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; -} diff --git a/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu/Wiimote/Wiimote.h b/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu/Wiimote/Wiimote.h deleted file mode 100644 index 279d48a95d..0000000000 --- a/Source/Plugins/Plugin_GCPadNew/Src/ControllerEmu/Wiimote/Wiimote.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _CONEMU_WIIMOTE_H_ -#define _CONEMU_WIIMOTE_H_ - -#include "../../ControllerEmu.h" - -#include - -class HIDReport : public std::queue -{ -public: - template - HIDReport& operator<<( const T& t ) - { - const u8* const e = ((u8*)&t) + sizeof(t); - const u8* i = (u8*)&t; - for ( ;i class GCPad : public ControllerEmu { diff --git a/Source/Plugins/Plugin_GCPadNew/Src/GCPadNew.cpp b/Source/Plugins/Plugin_GCPadNew/Src/GCPadNew.cpp index 4e0f1f2591..f8be2889db 100644 --- a/Source/Plugins/Plugin_GCPadNew/Src/GCPadNew.cpp +++ b/Source/Plugins/Plugin_GCPadNew/Src/GCPadNew.cpp @@ -2,9 +2,10 @@ #include #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::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(); } // ___________________________________________________________________________ diff --git a/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj b/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj index 58503ed48d..738d574c03 100644 --- a/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj +++ b/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj @@ -653,6 +653,18 @@ > + + + + + + diff --git a/Source/Plugins/Plugin_WiimoteNew/Plugin_WiimoteNew.vcproj b/Source/Plugins/Plugin_WiimoteNew/Plugin_WiimoteNew.vcproj new file mode 100644 index 0000000000..8c4673479f --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Plugin_WiimoteNew.vcproj @@ -0,0 +1,591 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Attachment.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Attachment.cpp new file mode 100644 index 0000000000..172ac6f975 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Attachment.cpp @@ -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( ®[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 ); +} diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Attachment.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Attachment.h new file mode 100644 index 0000000000..9a6cfed9b5 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Attachment.h @@ -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 reg; +}; + +class None : public Attachment +{ +public: + None(); +}; + +} + +#endif diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Classic.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Classic.cpp new file mode 100644 index 0000000000..3938e59360 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Classic.cpp @@ -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( ®[0x20], classic_calibration, sizeof(classic_calibration) ); + // id + memcpy( ®[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; +} + + +} diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Classic.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Classic.h new file mode 100644 index 0000000000..71124c9d2c --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Classic.h @@ -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; +}; + + +} diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Nunchuk.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Nunchuk.cpp new file mode 100644 index 0000000000..cb60dca575 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Nunchuk.cpp @@ -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( ®[0x20], nunchuck_calibration, sizeof(nunchuck_calibration) ); + // id + memcpy( ®[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*)®[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; +} + + +} diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Nunchuk.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Nunchuk.h new file mode 100644 index 0000000000..34f8590130 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/Nunchuk.h @@ -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; +}; + +} diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp new file mode 100644 index 0000000000..6f17c75de0 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp @@ -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 +#include + +#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; + } +} + +} diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Encryption.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Encryption.cpp new file mode 100644 index 0000000000..7099d3a955 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Encryption.cpp @@ -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]; +} diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Encryption.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Encryption.h new file mode 100644 index 0000000000..3e18f4be00 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Encryption.h @@ -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 + diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp new file mode 100644 index 0000000000..049cb4bc58 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp @@ -0,0 +1,492 @@ + +#include "Attachment/Classic.h" +#include "Attachment/Nunchuk.h" + +#include "WiimoteEmu.h" +#include "WiimoteHid.h" + +#include +#include + +// 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* 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* 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; + } +} + +} diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h new file mode 100644 index 0000000000..a6bc9e9266 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h @@ -0,0 +1,89 @@ +#ifndef _CONEMU_WIIMOTE_H_ +#define _CONEMU_WIIMOTE_H_ + +#include + +#include "WiimoteHid.h" +#include "Encryption.h" + +#include + +#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 > + { + 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 diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h new file mode 100644 index 0000000000..e7c338eeda --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h @@ -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 diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp new file mode 100644 index 0000000000..c49f4697dc --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp @@ -0,0 +1,348 @@ + +#include +#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 +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::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::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 +}