LilyPad: A number of small fixups.

DirectInput devices corresponding XInput devices should be listed as "[Detached]" when XInput is enabled.  No idea if this works, as it requires an XBox 360 controller to fully test.
FF Axes now sorted, rather than being displayed in the order MS returns them.
Small motor DirectInput binding now correctly displays "Square" effect type in list when first created.
Attempt to more accurately model "soft" vs "hard" presses.  Don't have a game where this matters, so no idea if it works.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1607 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
mattmenke 2009-08-06 04:50:55 +00:00
parent 5025b3886e
commit 3cbd298cff
8 changed files with 179 additions and 30 deletions

View File

@ -130,7 +130,11 @@ void SetLogSliderVal(HWND hWnd, int id, HWND hWndText, int val) {
void RefreshEnabledDevices(int updateDeviceList) { void RefreshEnabledDevices(int updateDeviceList) {
// Clears all device state. // Clears all device state.
if (updateDeviceList) EnumDevices(); static int lastXInputState = -1;
if (updateDeviceList || lastXInputState != config.gameApis.xInput) {
EnumDevices(config.gameApis.xInput);
lastXInputState = config.gameApis.xInput;
}
for (int i=0; i<dm->numDevices; i++) { for (int i=0; i<dm->numDevices; i++) {
Device *dev = dm->devices[i]; Device *dev = dm->devices[i];
@ -1094,11 +1098,16 @@ int CreateEffectBinding(Device *dev, wchar_t *effectID, unsigned int port, unsig
if (port > 1 || slot>3 || motor > 1 || !dev->numFFEffectTypes) { if (port > 1 || slot>3 || motor > 1 || !dev->numFFEffectTypes) {
return -1; return -1;
} }
if (!effectID) { ForceFeedbackEffectType *eff = 0;
effectID = dev->ffEffectTypes[0].effectID; if (effectID) {
eff = dev->GetForcefeedbackEffect(effectID);
}
if (!eff) {
eff = dev->ffEffectTypes;
}
if (!eff) {
return -1;
} }
ForceFeedbackEffectType *eff = dev->GetForcefeedbackEffect(effectID);
if (!eff) return -1;
int effectIndex = eff - dev->ffEffectTypes; int effectIndex = eff - dev->ffEffectTypes;
dev->pads[port][slot].ffBindings = (ForceFeedbackBinding*) realloc(dev->pads[port][slot].ffBindings, (dev->pads[port][slot].numFFBindings+1) * sizeof(ForceFeedbackBinding)); dev->pads[port][slot].ffBindings = (ForceFeedbackBinding*) realloc(dev->pads[port][slot].ffBindings, (dev->pads[port][slot].numFFBindings+1) * sizeof(ForceFeedbackBinding));
int newIndex = dev->pads[port][slot].numFFBindings; int newIndex = dev->pads[port][slot].numFFBindings;
@ -1404,7 +1413,14 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
if (index < (unsigned int) dm->numDevices) { if (index < (unsigned int) dm->numDevices) {
Device *dev = dm->devices[index]; Device *dev = dm->devices[index];
ForceFeedbackBinding *b; ForceFeedbackBinding *b;
int count = CreateEffectBinding(dev, 0, port, slot, cmd-ID_BIG_MOTOR, &b); wchar_t *effectID = 0;
if (dev->api == DI) {
// Constant effect.
if (cmd == ID_BIG_MOTOR) effectID = L"13541C20-8E33-11D0-9AD0-00A0C9A06E35";
// Square.
else effectID = L"13541C22-8E33-11D0-9AD0-00A0C9A06E35";
}
int count = CreateEffectBinding(dev, effectID, port, slot, cmd-ID_BIG_MOTOR, &b);
if (b) { if (b) {
int needSet = 1; int needSet = 1;
if (dev->api == XINPUT && dev->numFFAxes == 2) { if (dev->api == XINPUT && dev->numFFAxes == 2) {
@ -1418,7 +1434,6 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
} }
else if (dev->api == DI) { else if (dev->api == DI) {
int bigIndex=0, littleIndex=0; int bigIndex=0, littleIndex=0;
int constantEffect = 0, squareEffect = 0;
int j; int j;
for (j=0; j<dev->numFFAxes; j++) { for (j=0; j<dev->numFFAxes; j++) {
// DI object instance. 0 is x-axis, 1 is y-axis. // DI object instance. 0 is x-axis, 1 is y-axis.
@ -1430,20 +1445,14 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
littleIndex = j; littleIndex = j;
} }
} }
for (j=0; j<dev->numFFEffectTypes; j++) {
if (!wcsicmp(L"13541C20-8E33-11D0-9AD0-00A0C9A06E35", dev->ffEffectTypes[j].effectID)) constantEffect = j;
if (!wcsicmp(L"13541C22-8E33-11D0-9AD0-00A0C9A06E35", dev->ffEffectTypes[j].effectID)) squareEffect = j;
}
needSet = 0; needSet = 0;
if (cmd == ID_BIG_MOTOR) { if (cmd == ID_BIG_MOTOR) {
b->axes[bigIndex].force = BASE_SENSITIVITY; b->axes[bigIndex].force = BASE_SENSITIVITY;
b->axes[littleIndex].force = 1; b->axes[littleIndex].force = 1;
b->effectIndex = constantEffect;
} }
else { else {
b->axes[bigIndex].force = 1; b->axes[bigIndex].force = 1;
b->axes[littleIndex].force = BASE_SENSITIVITY; b->axes[littleIndex].force = BASE_SENSITIVITY;
b->effectIndex = squareEffect;
} }
} }
if (needSet) { if (needSet) {
@ -1695,7 +1704,7 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L
selected = 0; selected = 0;
ListView_SetExtendedListViewStyleEx(hWndList, LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER, LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER); ListView_SetExtendedListViewStyleEx(hWndList, LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER, LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER);
SendMessage(hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); SendMessage(hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM) L"Disabled"); SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM) L"Unplugged");
SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM) L"Dualshock 2"); SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM) L"Dualshock 2");
SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM) L"Guitar"); SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM) L"Guitar");
} }

View File

@ -7,7 +7,7 @@
#include "RawInput.h" #include "RawInput.h"
#include "XInput.h" #include "XInput.h"
void EnumDevices() { void EnumDevices(int hideDXXinput) {
// Needed for enumeration of some device types. // Needed for enumeration of some device types.
dm->ReleaseInput(); dm->ReleaseInput();
InputDeviceManager *oldDm = dm; InputDeviceManager *oldDm = dm;
@ -17,7 +17,7 @@ void EnumDevices() {
EnumWindowsMessagingDevices(); EnumWindowsMessagingDevices();
EnumRawInputDevices(); EnumRawInputDevices();
EnumXInputDevices(); EnumXInputDevices();
EnumDirectInputDevices(); EnumDirectInputDevices(hideDXXinput);
dm->CopyBindings(oldDm->numDevices, oldDm->devices); dm->CopyBindings(oldDm->numDevices, oldDm->devices);

View File

@ -9,5 +9,5 @@ struct InitInfo {
HWND hWndButton; HWND hWndButton;
}; };
void EnumDevices(); void EnumDevices(int hideDXXinput);

View File

@ -9,6 +9,16 @@
#include "PS2Etypes.h" #include "PS2Etypes.h"
#include <stdio.h> #include <stdio.h>
// All for getting GUIDs of XInput devices....
#include <wbemidl.h>
#include <oleauto.h>
// MS's code imports wmsstd.h, thus requiring the entire windows
// media SDK also be installed for a simple macro. This is
// simpler and less silly.
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#endif
// Aka htons, without the winsock dependency. // Aka htons, without the winsock dependency.
inline static u16 flipShort(u16 s) { inline static u16 flipShort(u16 s) {
return (s>>8) | (s<<8); return (s>>8) | (s<<8);
@ -440,10 +450,126 @@ BOOL CALLBACK EnumDeviceObjectsCallback (LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOI
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
} }
// Evil code from MS's site. If only they'd just made a way to get
// an XInput device's GUID directly in the first place...
BOOL IsXInputDevice( const GUID* pGuidProductFromDirectInput )
{
IWbemLocator* pIWbemLocator = NULL;
IEnumWbemClassObject* pEnumDevices = NULL;
IWbemClassObject* pDevices[20] = {0};
IWbemServices* pIWbemServices = NULL;
BSTR bstrNamespace = NULL;
BSTR bstrDeviceID = NULL;
BSTR bstrClassName = NULL;
DWORD uReturned = 0;
bool bIsXinputDevice= false;
UINT iDevice = 0;
VARIANT var;
HRESULT hr;
// CoInit if needed
hr = CoInitialize(NULL);
bool bCleanupCOM = SUCCEEDED(hr);
// Create WMI
hr = CoCreateInstance( __uuidof(WbemLocator),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IWbemLocator),
(LPVOID*) &pIWbemLocator);
if( FAILED(hr) || pIWbemLocator == NULL )
goto LCleanup;
bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );if( bstrNamespace == NULL ) goto LCleanup;
bstrClassName = SysAllocString( L"Win32_PNPEntity" ); if( bstrClassName == NULL ) goto LCleanup;
bstrDeviceID = SysAllocString( L"DeviceID" ); if( bstrDeviceID == NULL ) goto LCleanup;
// Connect to WMI
hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L,
0L, NULL, NULL, &pIWbemServices );
if( FAILED(hr) || pIWbemServices == NULL )
goto LCleanup;
// Switch security level to IMPERSONATE.
CoSetProxyBlanket( pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices );
if( FAILED(hr) || pEnumDevices == NULL )
goto LCleanup;
// Loop over all devices
for( ;; )
{
// Get 20 at a time
hr = pEnumDevices->Next( 10000, 20, pDevices, &uReturned );
if( FAILED(hr) )
goto LCleanup;
if( uReturned == 0 )
break;
for( iDevice=0; iDevice<uReturned; iDevice++ )
{
// For each device, get its device ID
hr = pDevices[iDevice]->Get( bstrDeviceID, 0L, &var, NULL, NULL );
if( SUCCEEDED( hr ) && var.vt == VT_BSTR && var.bstrVal != NULL )
{
// Check if the device ID contains "IG_". If it does, then it's an XInput device
// This information can not be found from DirectInput
if( wcsstr( var.bstrVal, L"IG_" ) )
{
// If it does, then get the VID/PID from var.bstrVal
DWORD dwPid = 0, dwVid = 0;
WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" );
if( strVid && swscanf( strVid, L"VID_%4X", &dwVid ) != 1 )
dwVid = 0;
WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" );
if( strPid && swscanf( strPid, L"PID_%4X", &dwPid ) != 1 )
dwPid = 0;
// Compare the VID/PID to the DInput device
DWORD dwVidPid = MAKELONG( dwVid, dwPid );
if( dwVidPid == pGuidProductFromDirectInput->Data1 )
{
bIsXinputDevice = true;
goto LCleanup;
}
}
}
SAFE_RELEASE( pDevices[iDevice] );
}
}
LCleanup:
if(bstrNamespace)
SysFreeString(bstrNamespace);
if(bstrDeviceID)
SysFreeString(bstrDeviceID);
if(bstrClassName)
SysFreeString(bstrClassName);
for( iDevice=0; iDevice<20; iDevice++ )
SAFE_RELEASE( pDevices[iDevice] );
SAFE_RELEASE( pEnumDevices );
SAFE_RELEASE( pIWbemLocator );
SAFE_RELEASE( pIWbemServices );
if( bCleanupCOM )
CoUninitialize();
return bIsXinputDevice;
}
struct DeviceEnumInfo {
IDirectInput8 *di8;
int ignoreXInput;
};
BOOL CALLBACK EnumCallback (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) { BOOL CALLBACK EnumCallback (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) {
IDirectInput8* di8 = (IDirectInput8*)pvRef; IDirectInput8* di8 = ((DeviceEnumInfo*)pvRef)->di8;
const wchar_t *name; const wchar_t *name;
wchar_t temp[40]; wchar_t temp[40];
//if (((DeviceEnumInfo*)pvRef)->ignoreXInput && lpddi->
if (lpddi->tszInstanceName[0]) { if (lpddi->tszInstanceName[0]) {
name = lpddi->tszInstanceName; name = lpddi->tszInstanceName;
} }
@ -476,11 +602,13 @@ BOOL CALLBACK EnumCallback (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) {
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
} }
void EnumDirectInputDevices() { void EnumDirectInputDevices(int ignoreXInput) {
IDirectInput8* di8 = GetDirectInput(); DeviceEnumInfo enumInfo;
if (!di8) return; enumInfo.di8 = GetDirectInput();
if (!enumInfo.di8) return;
enumInfo.ignoreXInput = ignoreXInput;
di8d.deviceCount = 0; di8d.deviceCount = 0;
di8->EnumDevices(DI8DEVCLASS_ALL, EnumCallback, di8, DIEDFL_ATTACHEDONLY); enumInfo.di8->EnumDevices(DI8DEVCLASS_ALL, EnumCallback, &enumInfo, DIEDFL_ATTACHEDONLY);
ReleaseDirectInput(); ReleaseDirectInput();
} }

View File

@ -1,3 +1,3 @@
#include "InputManager.h" #include "InputManager.h"
void EnumDirectInputDevices(); void EnumDirectInputDevices(int ignoreXInput);

View File

@ -112,15 +112,27 @@ void Device::AddFFAxis(const wchar_t *displayName, int id) {
ffAxes[numFFAxes].id = id; ffAxes[numFFAxes].id = id;
ffAxes[numFFAxes].displayName = wcsdup(displayName); ffAxes[numFFAxes].displayName = wcsdup(displayName);
numFFAxes++; numFFAxes++;
int bindingsExist = 0;
for (int port=0; port<2; port++) { for (int port=0; port<2; port++) {
for (int slot=0; slot<4; slot++) { for (int slot=0; slot<4; slot++) {
for (int i=0; i<pads[port][slot].numFFBindings; i++) { for (int i=0; i<pads[port][slot].numFFBindings; i++) {
ForceFeedbackBinding *b = pads[port][slot].ffBindings+i; ForceFeedbackBinding *b = pads[port][slot].ffBindings+i;
b->axes = (AxisEffectInfo*) realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes)); b->axes = (AxisEffectInfo*) realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes));
memset(b->axes + (numFFAxes-1), 0, sizeof(AxisEffectInfo)); memset(b->axes + (numFFAxes-1), 0, sizeof(AxisEffectInfo));
bindingsExist = 1;
} }
} }
} }
// Generally the case when not loading a binding file.
if (!bindingsExist) {
int i = numFFAxes-1;
ForceFeedbackAxis temp = ffAxes[i];
while (i && temp.id < ffAxes[i-1].id) {
ffAxes[i] = ffAxes[i-1];
i--;
}
ffAxes[i] = temp;
}
} }
void Device::AllocState() { void Device::AllocState() {

View File

@ -969,20 +969,20 @@ u8 CALLBACK PADpoll(u8 value) {
u8 b1 = 0xFF, b2 = 0xFF; u8 b1 = 0xFF, b2 = 0xFF;
for (i = 0; i<4; i++) { for (i = 0; i<4; i++) {
b1 -= (sum->buttons[i]>=128) << i; b1 -= (sum->buttons[i]>=0xF0) << i;
} }
for (i = 0; i<8; i++) { for (i = 0; i<8; i++) {
b2 -= (sum->buttons[i+4]>=128) << i; b2 -= (sum->buttons[i+4]>=0xF0) << i;
} }
if (config.padConfigs[query.port][query.slot].type == GuitarPad && !config.GH2) { if (config.padConfigs[query.port][query.slot].type == GuitarPad && !config.GH2) {
sum->sticks[0].horiz = -255; sum->sticks[0].horiz = -255;
// Not sure about this. Forces wammy to be from 0 to 0x7F. // Not sure about this. Forces wammy to be from 0 to 0x7F.
// if (sum->sticks[2].vert > 0) sum->sticks[2].vert = 0; // if (sum->sticks[2].vert > 0) sum->sticks[2].vert = 0;
} }
b1 -= ((sum->sticks[0].vert<=-128) << 4); b1 -= ((sum->sticks[0].vert<=-0xF0) << 4);
b1 -= ((sum->sticks[0].horiz>=128) << 5); b1 -= ((sum->sticks[0].horiz>=0xF0) << 5);
b1 -= ((sum->sticks[0].vert>=128) << 6); b1 -= ((sum->sticks[0].vert>=0xF0) << 6);
b1 -= ((sum->sticks[0].horiz<=-128) << 7); b1 -= ((sum->sticks[0].horiz<=-0xF0) << 7);
query.response[3] = b1; query.response[3] = b1;
query.response[4] = b2; query.response[4] = b2;

View File

@ -227,7 +227,7 @@ BEGIN
CONTROL "Port 1 Multitap",IDC_MULTITAP1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,152,63,10 CONTROL "Port 1 Multitap",IDC_MULTITAP1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,152,63,10
CONTROL "Port 2 Multitap",IDC_MULTITAP2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,164,63,10 CONTROL "Port 2 Multitap",IDC_MULTITAP2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,164,63,10
CONTROL "",IDC_PAD_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_TABSTOP,81,151,183,50,WS_EX_CLIENTEDGE CONTROL "",IDC_PAD_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_TABSTOP,81,151,183,50,WS_EX_CLIENTEDGE
COMBOBOX IDC_PAD_TYPE,270,152,140,41,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_PAD_TYPE,270,152,140,41,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Use analog mode whenever possible",IDC_ANALOG_START1, CONTROL "Use analog mode whenever possible",IDC_ANALOG_START1,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,270,169,132,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,270,169,132,10
GROUPBOX "Device Diagnostics",IDC_STATIC,7,211,201,99 GROUPBOX "Device Diagnostics",IDC_STATIC,7,211,201,99