Added support for X360pad rumble

Need someone who has a X360pad to test.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4929 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
ayuanx 2010-01-23 12:36:30 +00:00
parent 2098271bc8
commit 1ecbcb39ea
5 changed files with 163 additions and 90 deletions

View File

@ -97,17 +97,17 @@ int GetXI(int Controller, int Button)
{ {
// Update the internal status // Update the internal status
DWORD dwResult; DWORD dwResult;
dwResult = XInputGetState( Controller, &g_Controllers[Controller].state ); dwResult = XInputGetState(Controller, &g_Controllers[Controller].state);
if( dwResult != ERROR_SUCCESS ) return -1; if (dwResult != ERROR_SUCCESS) return -1;
switch(Button) switch (Button)
{ {
case InputCommon::XI_TRIGGER_L: case InputCommon::XI_TRIGGER_L:
return g_Controllers[0].state.Gamepad.bLeftTrigger; return g_Controllers[Controller].state.Gamepad.bLeftTrigger;
case InputCommon::XI_TRIGGER_R: case InputCommon::XI_TRIGGER_R:
return g_Controllers[0].state.Gamepad.bRightTrigger; return g_Controllers[Controller].state.Gamepad.bRightTrigger;
default: default:
return 0; return 0;

View File

@ -23,6 +23,10 @@
#include "ConfigBox.h" #include "ConfigBox.h"
#endif #endif
#ifdef _WIN32
#include "XInput.h"
#endif
// Declare config window so that we can write debugging info to it from functions in this file // Declare config window so that we can write debugging info to it from functions in this file
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
GCPadConfigDialog* m_ConfigFrame = NULL; GCPadConfigDialog* m_ConfigFrame = NULL;
@ -457,7 +461,15 @@ bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_N
{ {
if (_NumPads > GCMapping[i].ID) if (_NumPads > GCMapping[i].ID)
if(joyinfo.at(GCMapping[i].ID).Good) if(joyinfo.at(GCMapping[i].ID).Good)
{
GCMapping[i].joy = joyinfo.at(GCMapping[i].ID).joy; GCMapping[i].joy = joyinfo.at(GCMapping[i].ID).joy;
#ifdef _WIN32
XINPUT_STATE xstate;
DWORD xresult = XInputGetState(GCMapping[i].ID, &xstate);
if (xresult == ERROR_SUCCESS)
GCMapping[i].TriggerType = InputCommon::CTL_TRIGGER_XINPUT;
#endif
}
} }
return Success; return Success;

View File

@ -18,6 +18,10 @@
#include "GCpad.h" #include "GCpad.h"
#ifdef _WIN32
#include "XInput.h"
#endif
#ifdef RUMBLE_HACK #ifdef RUMBLE_HACK
@ -35,57 +39,63 @@ BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContex
BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext); BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext);
void SetDeviceForcesXY(int pad, int nXYForce); void SetDeviceForcesXY(int pad, int nXYForce);
HRESULT InitRumble(HWND hWnd); HRESULT InitRumble(HWND hWnd);
void Rumble_DInput(int _ID, unsigned int _Strength);
void Rumble_XInput(int _ID, unsigned int _Strength);
LPDIRECTINPUT8 g_Rumble; // DInput Rumble object LPDIRECTINPUT8 g_Rumble; // DInput Rumble object
RUMBLE pRumble[4]; // 4 GC Rumble Pads RUMBLE pRumble[4]; // 4 GC Rumble Pads
//////////////////////
// Use PAD rumble
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void Pad_Use_Rumble(u8 _numPAD)
{
if (!g_Rumble)
{
// GetForegroundWindow() always sends the good HWND
if (FAILED(InitRumble(GetForegroundWindow())))
PanicAlert("Could not initialize Rumble!");
} else
{
// Acquire gamepad
if (pRumble[_numPAD].g_pDevice != NULL)
pRumble[_numPAD].g_pDevice->Acquire();
}
}
////////////////////////////////////////////////////
// Set PAD rumble. Explanation: Stop = 0, Rumble = 1
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength) void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
{ {
if (GCMapping[_numPAD].ID >= NumPads || !GCMapping[_numPAD].Rumble) if (GCMapping[_numPAD].ID >= NumPads || !GCMapping[_numPAD].Rumble)
return; return;
Pad_Use_Rumble(_numPAD); unsigned int Strength = 0;
int Strenght = 0;
if (_uType == 1 && _uStrength > 2) if (_uType == 1 && _uStrength > 2)
{ {
// it looks like _uStrength is equal to 3 everytime anyway... Strength = 1000 * GCMapping[_numPAD].RumbleStrength;
Strenght = 1000 * GCMapping[_numPAD].RumbleStrength; Strength = Strength > 10000 ? 10000 : Strength;
Strenght = Strenght > 10000 ? 10000 : Strenght;
} }
else
Strenght = 0;
SetDeviceForcesXY(_numPAD, Strenght); if (GCMapping[_numPAD].TriggerType == InputCommon::CTL_TRIGGER_XINPUT)
Rumble_XInput(GCMapping[_numPAD].ID, Strength);
else
Rumble_DInput(GCMapping[_numPAD].ID, Strength);
} }
// Rumble stuff :D! ////////////////////////////////////////////////////
// ---------------- // Set rumble with XInput.
// void Rumble_XInput(int _ID, unsigned int _Strength)
{
#ifdef _WIN32
XINPUT_VIBRATION vib;
vib.wLeftMotorSpeed = _Strength;
vib.wRightMotorSpeed = _Strength;
XInputSetState(_ID, &vib);
#endif
}
////////////////////////////////////////////////////
// Set rumble with DInput.¯¯¯¯¯¯¯¯¯¯¯¯
void Rumble_DInput(int _ID, unsigned int _Strength)
{
if (!g_Rumble)
{
// GetForegroundWindow() always sends the good HWND
if (FAILED(InitRumble(GetForegroundWindow())))
PanicAlert("Could not initialize Rumble!");
}
else
{
// Acquire gamepad
if (pRumble[_ID].g_pDevice != NULL)
pRumble[_ID].g_pDevice->Acquire();
}
SetDeviceForcesXY(_ID, _Strength);
}
HRESULT InitRumble(HWND hWnd) HRESULT InitRumble(HWND hWnd)
{ {
@ -238,7 +248,6 @@ BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContex
{ {
// a DInput device is created even if rumble is disabled on startup // a DInput device is created even if rumble is disabled on startup
// this way, you can toggle the rumble setting while in game // this way, you can toggle the rumble setting while in game
//if (GCMapping[i].enabled) // && GCMapping[i].rumble
pRumble[i].g_pDevice = pDevice; // everything looks good, save the DInput device pRumble[i].g_pDevice = pDevice; // everything looks good, save the DInput device
} }
} }
@ -257,13 +266,27 @@ BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pCont
void PAD_RumbleClose() void PAD_RumbleClose()
{ {
for (int i = 0; i < 4; i++)
{
if (GCMapping[i].ID < NumPads)
if (GCMapping[i].TriggerType == InputCommon::CTL_TRIGGER_XINPUT)
{
#ifdef _WIN32
// Kill Xpad rumble
XINPUT_VIBRATION vib;
vib.wLeftMotorSpeed = 0;
vib.wRightMotorSpeed = 0;
XInputSetState(GCMapping[i].ID, &vib);
#endif
}
else
{
// It may look weird, but we don't free anything here, it was the cause of crashes // It may look weird, but we don't free anything here, it was the cause of crashes
// on stop, and the DLL isn't unloaded anyway, so the pointers stay // on stop, and the DLL isn't unloaded anyway, so the pointers stay
// We just stop the rumble in case it's still playing an effect. // We just stop the rumble in case it's still playing an effect.
for (int i=0; i<4; i++) if (pRumble[GCMapping[i].ID].g_pDevice && pRumble[GCMapping[i].ID].g_pEffect)
{ pRumble[GCMapping[i].ID].g_pEffect->Stop();
if (pRumble[i].g_pDevice && pRumble[i].g_pEffect) }
pRumble[i].g_pEffect->Stop();
} }
} }

View File

@ -35,6 +35,10 @@
#include "Encryption.h" // for extension encryption #include "Encryption.h" // for extension encryption
#include "Config.h" // for g_Config #include "Config.h" // for g_Config
#ifdef _WIN32
#include "XInput.h"
#endif
extern SWiimoteInitialize g_WiimoteInitialize; extern SWiimoteInitialize g_WiimoteInitialize;
namespace WiiMoteEmu namespace WiiMoteEmu
@ -87,9 +91,16 @@ bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_N
{ {
if (_NumPads > WiiMapping[i].ID) if (_NumPads > WiiMapping[i].ID)
if(_joyinfo.at(WiiMapping[i].ID).Good) if(_joyinfo.at(WiiMapping[i].ID).Good)
{
WiiMapping[i].joy = _joyinfo.at(WiiMapping[i].ID).joy; WiiMapping[i].joy = _joyinfo.at(WiiMapping[i].ID).joy;
#ifdef _WIN32
XINPUT_STATE xstate;
DWORD xresult = XInputGetState(WiiMapping[i].ID, &xstate);
if (xresult == ERROR_SUCCESS)
WiiMapping[i].TriggerType = InputCommon::CTL_TRIGGER_XINPUT;
#endif
}
} }
return WasGotten; return WasGotten;
} }

View File

@ -20,6 +20,10 @@
#include "../../../Core/InputCommon/Src/SDL.h" // Core #include "../../../Core/InputCommon/Src/SDL.h" // Core
#include "EmuDefinitions.h" #include "EmuDefinitions.h"
#ifdef _WIN32
#include "XInput.h"
#endif
namespace WiiMoteEmu namespace WiiMoteEmu
{ {
@ -57,58 +61,67 @@ BOOL CALLBACK EnumFFDevicesCallback(const DIDEVICEINSTANCE* pInst, VOID* pContex
BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext); BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext);
void SetDeviceForcesXY(int pad, int nXYForce); void SetDeviceForcesXY(int pad, int nXYForce);
HRESULT InitRumble(HWND hWnd); HRESULT InitRumble(HWND hWnd);
void Rumble_DInput(int _ID, unsigned int _Strength);
void Rumble_XInput(int _ID, unsigned int _Strength);
LPDIRECTINPUT8 g_Rumble; // DInput Rumble object LPDIRECTINPUT8 g_Rumble; // DInput Rumble object
RUMBLE pRumble[MAX_WIIMOTES]; RUMBLE pRumble[MAX_WIIMOTES];
//////////////////////
// Use PAD rumble
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void Pad_Use_Rumble(u8 _numPAD)
////////////////////////////////////////////////////
// Set PAD rumble. Explanation: Stop = 0, Rumble = 1
void PAD_Rumble(u8 _numPAD, unsigned int _uType)
{
if (WiiMapping[_numPAD].ID >= NumPads || !WiiMapping[_numPAD].Rumble)
return;
unsigned int Strength = 0;
if (_uType == 1)
{
Strength = 1000 * (WiiMapping[_numPAD].RumbleStrength);
Strength = Strength > 10000 ? 10000 : Strength;
}
if (WiiMapping[_numPAD].TriggerType == InputCommon::CTL_TRIGGER_XINPUT)
Rumble_XInput(WiiMapping[_numPAD].ID, Strength);
else
Rumble_DInput(WiiMapping[_numPAD].ID, Strength);
}
////////////////////////////////////////////////////
// Set rumble with XInput.
void Rumble_XInput(int _ID, unsigned int _Strength)
{
#ifdef _WIN32
XINPUT_VIBRATION vib;
vib.wLeftMotorSpeed = _Strength;
vib.wRightMotorSpeed = _Strength;
XInputSetState(_ID, &vib);
#endif
}
////////////////////////////////////////////////////
// Set rumble with DInput.¯¯¯¯¯¯¯¯¯¯¯¯
void Rumble_DInput(int _ID, unsigned int _Strength)
{ {
if (!g_Rumble) if (!g_Rumble)
{ {
// GetForegroundWindow() always sends the good HWND // GetForegroundWindow() always sends the good HWND
if (FAILED(InitRumble(GetForegroundWindow()))) if (FAILED(InitRumble(GetForegroundWindow())))
PanicAlert("Could not initialize Rumble!"); PanicAlert("Could not initialize Rumble!");
} else
{
// Acquire gamepad
if (pRumble[_numPAD].g_pDevice != NULL)
pRumble[_numPAD].g_pDevice->Acquire();
}
}
////////////////////////////////////////////////////
// Set PAD rumble. Explanation: Stop = 0, Rumble = 1
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
void PAD_Rumble(u8 _numPAD, unsigned int _uType)
{
if (WiiMapping[_numPAD].ID >= NumPads || !WiiMapping[_numPAD].Rumble)
return;
Pad_Use_Rumble(_numPAD);
int Strenght = 0;
if (_uType == 1)
{
// it looks like _uStrength is equal to 3 everytime anyway...
Strenght = 1000 * (WiiMapping[_numPAD].RumbleStrength);
Strenght = Strenght > 10000 ? 10000 : Strenght;
} }
else else
Strenght = 0; {
// Acquire gamepad
if (pRumble[_ID].g_pDevice != NULL)
pRumble[_ID].g_pDevice->Acquire();
}
SetDeviceForcesXY(_numPAD, Strenght); SetDeviceForcesXY(_ID, _Strength);
} }
// Rumble stuff :D!
// ----------------
//
HRESULT InitRumble(HWND hWnd) HRESULT InitRumble(HWND hWnd)
{ {
DIPROPDWORD dipdw; DIPROPDWORD dipdw;
@ -279,13 +292,27 @@ BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pCont
void PAD_RumbleClose() void PAD_RumbleClose()
{ {
for (int i = 0; i < MAX_WIIMOTES; i++)
{
if (WiiMapping[i].ID < NumPads)
if (WiiMapping[i].TriggerType == InputCommon::CTL_TRIGGER_XINPUT)
{
#ifdef _WIN32
// Kill Xpad rumble
XINPUT_VIBRATION vib;
vib.wLeftMotorSpeed = 0;
vib.wRightMotorSpeed = 0;
XInputSetState(WiiMapping[i].ID, &vib);
#endif
}
else
{
// It may look weird, but we don't free anything here, it was the cause of crashes // It may look weird, but we don't free anything here, it was the cause of crashes
// on stop, and the DLL isn't unloaded anyway, so the pointers stay // on stop, and the DLL isn't unloaded anyway, so the pointers stay
// We just stop the rumble in case it's still playing an effect. // We just stop the rumble in case it's still playing an effect.
for (int i = 0; i < MAX_WIIMOTES; i++) if (pRumble[WiiMapping[i].ID].g_pDevice && pRumble[WiiMapping[i].ID].g_pEffect)
{ pRumble[WiiMapping[i].ID].g_pEffect->Stop();
if (pRumble[i].g_pDevice && pRumble[i].g_pEffect) }
pRumble[i].g_pEffect->Stop();
} }
} }