diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 22632ea61d6..2bd5d6c325a 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -366,6 +366,29 @@ static inline LPDIOBJECTDATAFORMAT dataformat_to_odf(LPCDIDATAFORMAT df, int idx return (LPDIOBJECTDATAFORMAT)((LPBYTE)df->rgodf + idx * df->dwObjSize); } +/* dataformat_to_odf_by_type + * Find the Nth object of the selected type in the DataFormat + */ +LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD type) +{ + int i, nfound = 0; + + for (i=0; i < df->dwNumObjs; i++) + { + LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(df, i); + + if (odf->dwType & type) + { + if (n == nfound) + return odf; + + nfound++; + } + } + + return NULL; +} + static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *format) { DataTransform *dt; diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 503698a024a..6c061b2d64b 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -125,6 +125,7 @@ extern void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) DECLSPEC_HIDDEN; extern const char *_dump_dinput_GUID(const GUID *guid) DECLSPEC_HIDDEN; extern DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic) DECLSPEC_HIDDEN; +extern LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD type) DECLSPEC_HIDDEN; /* And the stubs */ extern HRESULT WINAPI IDirectInputDevice2AImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) DECLSPEC_HIDDEN; diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h index 6573de0bbb3..3c4776e7fc5 100644 --- a/dlls/dinput/dinput_private.h +++ b/dlls/dinput/dinput_private.h @@ -71,5 +71,6 @@ extern void _copy_diactionformatWtoA(LPDIACTIONFORMATA, LPDIACTIONFORMATW) DECLS #define DIKEYBOARD_MASK 0x81000000 #define DIMOUSE_MASK 0x82000000 +#define DIGENRE_ANY 0xFF000000 #endif /* __WINE_DLLS_DINPUT_DINPUT_PRIVATE_H */ diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c index 68dcc6a7e75..b5c028cabb1 100644 --- a/dlls/dinput/joystick.c +++ b/dlls/dinput/joystick.c @@ -432,9 +432,47 @@ HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, LPCWSTR lpszUserName, DWORD dwFlags) { + JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); + int i, j, has_actions = 0; + DWORD object_types[] = { DIDFT_AXIS, DIDFT_BUTTON }; + DWORD type_map[] = { DIDFT_RELAXIS, DIDFT_PSHBUTTON }; + FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags); - return DI_NOEFFECT; + for (i=0; i < lpdiaf->dwNumActions; i++) + { + DWORD inst = (0x000000ff & (lpdiaf->rgoAction[i].dwSemantic)) - 1; + DWORD type = 0x000000ff & (lpdiaf->rgoAction[i].dwSemantic >> 8); + DWORD genre = 0xff000000 & lpdiaf->rgoAction[i].dwSemantic; + + /* Only consider actions of the right genre */ + if (lpdiaf->dwGenre != genre && genre != DIGENRE_ANY) continue; + + for (j=0; j < sizeof(object_types)/sizeof(object_types[0]); j++) + { + if (type & object_types[j]) + { + /* Assure that the object exists */ + LPDIOBJECTDATAFORMAT odf = dataformat_to_odf_by_type(This->base.data_format.wine_df, inst, DIDFT_BUTTON); + + if (odf != NULL) + { + lpdiaf->rgoAction[i].dwObjID = type_map[j] | (0x0000ff00 & (inst << 8)); + lpdiaf->rgoAction[i].guidInstance = This->base.guid; + lpdiaf->rgoAction[i].dwHow = DIAH_DEFAULT; + + has_actions = 1; + + /* No need to try other types if the action was already mapped */ + break; + } + } + } + } + + if (!has_actions) return DI_NOEFFECT; + + return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags); } HRESULT WINAPI JoystickAGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface,