Lucas asked:
Should I correct the tabs and align the parameters in the function prototype when I implement them?
If you do a significant rewrite of a function, or are implementing it for the first time, I think it's ok to use more standard code style in your new code, or to update the style of adjacent old code (like a prototype) related to your change.
I'm having some issues with test that inject input. For instance this code ( http://pastebin.com/gan0Niqj ) works as expected under wine and wine with dinput8.dll , but fails in every windows version... I tried a version with SendInput and had the same results...
Anyone has some insight on this?
Cheers
On Sun, Jun 12, 2011 at 10:45:38PM -0300, Lucas Zawacki wrote:
I'm having some issues with test that inject input. For instance this code ( http://pastebin.com/gan0Niqj ) works as expected under wine and wine with dinput8.dll , but fails in every windows version... I tried a version with SendInput and had the same results...
Anyone has some insight on this?
What does keybd_event() do?
I suspect that Windows might not hooking the keyboard for DirectInput usage, but attaches to some lower layer in the input stack.
Ciao, Marcus
What does keybd_event() do?
It seems to send WM_KEY and WM_KEYDOWN events to a window http://msdn.microsoft.com/en-us/library/ms646304%28VS.85%29.aspx
I suspect that Windows might not hooking the keyboard for DirectInput usage, but attaches to some lower layer in the input stack.
I'm not finding the exact paragraph now, but I remember reading something along this lines in MSDN.
OK, so here is my second try at some patches. These mostly implement keyboard action mapping and there's plenty of tests to go together with it. I believe the keyboard part is pretty much done, as is SetActionMap. Of course I'm ignoring the username strings and all the device ownership part, I'll leave that for later.
As before I'll leave the patches here to get some feedback before I try to commit.
Cheers
On Mon, Jun 13, 2011 at 07:17:04PM -0300, Lucas Zawacki wrote:
OK, so here is my second try at some patches. These mostly implement keyboard action mapping and there's plenty of tests to go together with it. I believe the keyboard part is pretty much done, as is SetActionMap. Of course I'm ignoring the username strings and all the device ownership part, I'll leave that for later.
As before I'll leave the patches here to get some feedback before I try to commit.
Looks good to me. I spotted one small flaw in binary logic:
+/* This is used for the action mapping of constants such as DIKEYBOARD_SPACE */ +static DWORD keyboard_semantic_to_obj_id(DWORD dwSemantic) +{
- /* dwSemantic=810004df is dwObjID=0xdf04 */
- return 0x0000ffff & ( (dwSemantic << 8) | (dwSemantic >> 8) );
+}
The >>8 shift will drag in bits 16-23 from dwSemantic, which is probably not intended.
(think dwSemantic = 0x4242df04 , it will roate in the 0x42)
dwSemantic &= 0x0000ffff;
before the operation will help.
If no negative comments appear, please post them as 1 patch per email to wine-patches ;)
Ciao, Marcus
On 06/13/2011 04:17 PM, Lucas Zawacki wrote:
OK, so here is my second try at some patches. These mostly implement keyboard action mapping and there's plenty of tests to go together with it. I believe the keyboard part is pretty much done, as is SetActionMap. Of course I'm ignoring the username strings and all the device ownership part, I'll leave that for later.
As before I'll leave the patches here to get some feedback before I try to commit.
Subject: dinput: EnumDevicesBySemantics enumerating system keyboard and mouse
- DWORD callbackFlags = 0;
- ret = lpCallback(&didevi, lpdid, callbackFlags , 0, pvRef);
I'd like to see a test for callbackFlags = 0. My notes indicate this should be DIEDBS_MAPPEDPRI1 instead.
Also please implement unicode method and call it from ascii. (IDirectInput8AImpl_EnumDevicesBySemantics -> IDirectInput8WImpl_EnumDevicesBySemantics)
Subject: dinput: SetActionMap setting the device buffer and data format.
- IDirectInputDevice8_SetDataFormat(iface, This->data_format.wine_df);
You do not want to do that. It's internal data format which does not have to be anything like real data format. You need to build your data format based on action mapping. I had something like this, not sure if it is correct:
+ DIDATAFORMAT data_format; + DIOBJECTDATAFORMAT *obj_df; + + data_format.dwSize = sizeof(data_format); + data_format.dwObjSize = sizeof(DIOBJECTDATAFORMAT); + data_format.dwFlags = DIDF_ABSAXIS; + data_format.dwDataSize = lpdiaf->dwDataSize; + data_format.dwNumObjs = lpdiaf->dwNumActions; + data_format.rgodf = (LPDIOBJECTDATAFORMAT)obj_df; + + for (i = 0; i < lpdiaf->dwNumActions; i++) + { + if ((lpdiaf->rgoAction[i].dwSemantic & 0x81000400) == 0x81000400) + /* Keyboard */ + memcpy(&obj_df[i], &c_dfDIKeyboard.rgodf[DIDFT_GETINSTANCE(lpdiaf->rgoAction[i].dwObjID)], c_dfDIKeyboard.dwObjSize); + else if ((lpdiaf->rgoAction[i].dwSemantic & 0x82000000) == 0x82000000) + /* Mouse */ + memcpy(&obj_df[i], &c_dfDIMouse2.rgodf[DIDFT_GETINSTANCE(lpdiaf->rgoAction[i].dwObjID)], c_dfDIMouse2.dwObjSize); + + obj_df[i].dwOfs = i * 4; + + This->action_map[DIDFT_GETINSTANCE(lpdiaf->rgoAction[i].dwObjID)] = lpdiaf->rgoAction[i].uAppData; + }
- /* search for actions for this device and apply them */
- for (i=0; i < lpdiaf->dwNumActions; i++) {
if (IsEqualGUID( &lpdiaf->rgoAction[i].guidInstance, &This->guid ) ) {
As I asked before, please put curly braces on a separate line.
Vitaliy.
Also please implement unicode method and call it from ascii. (IDirectInput8AImpl_EnumDevicesBySemantics -> IDirectInput8WImpl_EnumDevicesBySemantics)
Sorry if that's a stupid question, but what should I do with the string parameters? Is it ok to call a W function with the A parameters?
- IDirectInputDevice8_SetDataFormat(iface, This->data_format.wine_df);
You do not want to do that. It's internal data format which does not have to be anything like real data format. You need to build your data format based on action mapping. I had something like this, not sure if it is correct:
Thanks, that's interesting. I'll look further into this.
On Tue, Jun 14, 2011 at 02:07:32PM -0300, Lucas Zawacki wrote:
Also please implement unicode method and call it from ascii. (IDirectInput8AImpl_EnumDevicesBySemantics -> IDirectInput8WImpl_EnumDevicesBySemantics)
Sorry if that's a stupid question, but what should I do with the string parameters? Is it ok to call a W function with the A parameters?
No, it would need to converted back and forth.
I think for the first committed patches having them seperate is fine, it could be factored out later, as W<->A conversion for the callback handler will be tricky.
Ciao, Marfcus
On 06/14/2011 03:09 PM, Marcus Meissner wrote:
On Tue, Jun 14, 2011 at 02:07:32PM -0300, Lucas Zawacki wrote:
Also please implement unicode method and call it from ascii. (IDirectInput8AImpl_EnumDevicesBySemantics -> IDirectInput8WImpl_EnumDevicesBySemantics)
Sorry if that's a stupid question, but what should I do with the string parameters? Is it ok to call a W function with the A parameters?
No, it would need to converted back and forth.
I think for the first committed patches having them seperate is fine, it could be factored out later, as W<->A conversion for the callback handler will be tricky.
Because callback doesn't have any string parameters it would be an easy thing to do.
Vitaliy.
Because callback doesn't have any string parameters it would be an easy thing to do.
I've made an EnumDevicesBySemantics version using A -> W calls, but it turned out to be trickier than I thought because the callback function is passed the device interfaces and then the A callback gets W interfaces. I'll send the patches with corrections later today but I really think the implementation for EnumDevicesBySemantics should remain separate right now.
Is there any problem with the latest patches I sent? They're sitting there with the 'New' status but I have no feedback (good or bad) about them.
Cheers
2011/6/20 Lucas Zawacki lfzawacki@gmail.com:
Because callback doesn't have any string parameters it would be an easy thing to do.
I've made an EnumDevicesBySemantics version using A -> W calls, but it turned out to be trickier than I thought because the callback function is passed the device interfaces and then the A callback gets W interfaces. I'll send the patches with corrections later today but I really think the implementation for EnumDevicesBySemantics should remain separate right now.
there was no commit round today yet. usually allow for 2 days to pass if your patches are still "new". if then there is no feedback you can try asking in #winehackers
2011/6/24 Lucas Zawacki lfzawacki@gmail.com
Is there any problem with the latest patches I sent? They're sitting there with the 'New' status but I have no feedback (good or bad) about them.
Cheers
2011/6/20 Lucas Zawacki lfzawacki@gmail.com:
Because callback doesn't have any string parameters it would be an easy thing to do.
I've made an EnumDevicesBySemantics version using A -> W calls, but it turned out to be trickier than I thought because the callback function is passed the device interfaces and then the A callback gets W interfaces. I'll send the patches with corrections later today but I really think the implementation for EnumDevicesBySemantics should remain separate right now.
Is there any problem with the latest patches I sent? They're sitting there with the 'New' status but I have no feedback
(good or bad) about them.
Cheers
Hi Lucas,
i put your patches on top of 1.3.23 and kick in Need For Speed Undeground 1, i.e. testing bug 8754.
As a hello word programmer, i can't judge the code quality, but i can say, that it worked nearly flawlessly. I was able to drive/play on keyboard :-D
The only issue i found in NFS's keyboard configuration: * When i press PAUSE KEY, then NFS says "Num_Lock" * When i press NUMLOCK KEY, then NFS says "Pause"
Native dinput8 behaves correctly. But who cares to drive on such two strange KEYs ;)
Good job! Tell uncle Google, that he can fill up your pockets :))
W.
As a hello word programmer, i can't judge the code quality, but i can say, that it worked nearly flawlessly. I was able to drive/play on keyboard :-D
That's very nice to hear :)
The only issue i found in NFS's keyboard configuration:
- When i press PAUSE KEY, then NFS says "Num_Lock"
- When i press NUMLOCK KEY, then NFS says "Pause"
Hmm, actually I construct the mapping based on the positions of the objects in the keyboard dataformat and PAUSE and NUM LOCK seem to be in different positions in native and wine. Attached are two dumps of the keyboard objects with builtin and native dinput for comparison.
On 06/24/2011 11:10 PM, Lucas Zawacki wrote:
As a hello word programmer, i can't judge the code quality, but i can say, that it worked nearly flawlessly. I was able to drive/play on keyboard :-D
That's very nice to hear :)
The only issue i found in NFS's keyboard configuration:
- When i press PAUSE KEY, then NFS says "Num_Lock"
- When i press NUMLOCK KEY, then NFS says "Pause"
Hmm, actually I construct the mapping based on the positions of the objects in the keyboard dataformat and PAUSE and NUM LOCK seem to be in different positions in native and wine. Attached are two dumps of the keyboard objects with builtin and native dinput for comparison.
This is not related to data format. But auto-generated events in x11drv to turn on/off num/lock. Apparently native dinput has a mechanism to ignore these events.
Vitaliy.
Hey guys, how are you doing? I've got some patches for you.
The first is a refactoring of the BuildActionMap implementations for keyboard and mouse. I think with 'semantic_to_obj_id' the mapping is pretty much correct for keyboard and mouse and it's being done "the right way".
The second patch is much like one I sent some time ago, it's SetActionMap for keyboard and mouse, this time (hopefully) with the dataformat stuff done right too. I've split it up in a third patch, which implements the "action mapping" per se.
Anyway, tomorrow I'll code some mouse tests to be sure that this is working.
Cheers
On Thu, Jun 30, 2011 at 02:56:08AM -0300, Lucas Zawacki wrote:
Hey guys, how are you doing? I've got some patches for you.
The first is a refactoring of the BuildActionMap implementations for keyboard and mouse. I think with 'semantic_to_obj_id' the mapping is pretty much correct for keyboard and mouse and it's being done "the right way".
The second patch is much like one I sent some time ago, it's SetActionMap for keyboard and mouse, this time (hopefully) with the dataformat stuff done right too. I've split it up in a third patch, which implements the "action mapping" per se.
Anyway, tomorrow I'll code some mouse tests to be sure that this is working.
Cheers
From 37e5a1e6d51778ee0d5c0f3081dad8ca1431968f Mon Sep 17 00:00:00 2001 From: Lucas Fialho Zawacki lfzawacki@gmail.com Date: Fri, 10 Jun 2011 21:43:53 -0300 Subject: dinput: Keyboard and mouse implementation of BuildActionMap (try 4)
+DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic) +{
...
- if (!found) return 0;
So 0 is the not found case...
DWORD obj_id = semantic_to_obj_id(&This->base, lpdiaf->rgoAction[i].dwSemantic);
if (obj_id != -1)
But here you check for -1.
DWORD obj_id = semantic_to_obj_id(&This->base, lpdiaf->rgoAction[i].dwSemantic);
if (obj_id != -1)
and here. (both mouse and keyboard code)
should probably check for 0 there, also as DWORD is unsigned ;)
Ciao, Marcus
Ouch, that is a leftover from an older try at this code. So much for double checking the patches...
2011/6/30 Marcus Meissner meissner@suse.de:
On Thu, Jun 30, 2011 at 02:56:08AM -0300, Lucas Zawacki wrote:
Hey guys, how are you doing? I've got some patches for you.
The first is a refactoring of the BuildActionMap implementations for keyboard and mouse. I think with 'semantic_to_obj_id' the mapping is pretty much correct for keyboard and mouse and it's being done "the right way".
The second patch is much like one I sent some time ago, it's SetActionMap for keyboard and mouse, this time (hopefully) with the dataformat stuff done right too. I've split it up in a third patch, which implements the "action mapping" per se.
Anyway, tomorrow I'll code some mouse tests to be sure that this is working.
Cheers
From 37e5a1e6d51778ee0d5c0f3081dad8ca1431968f Mon Sep 17 00:00:00 2001 From: Lucas Fialho Zawacki lfzawacki@gmail.com Date: Fri, 10 Jun 2011 21:43:53 -0300 Subject: dinput: Keyboard and mouse implementation of BuildActionMap (try 4)
+DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic) +{
...
- if (!found) return 0;
So 0 is the not found case...
- DWORD obj_id = semantic_to_obj_id(&This->base, lpdiaf->rgoAction[i].dwSemantic);
- if (obj_id != -1)
But here you check for -1.
- DWORD obj_id = semantic_to_obj_id(&This->base, lpdiaf->rgoAction[i].dwSemantic);
- if (obj_id != -1)
and here. (both mouse and keyboard code)
should probably check for 0 there, also as DWORD is unsigned ;)
Ciao, Marcus
Hi guys.
Now that all the initial patches are in I have several smaller tasks to work on as listed here http://lfzawacki.heroku.com/wine/published/Road+Map and hopefully they're more straightforward. I've already started working on getting EnumDevicesBySemantics correct with joysticks and the passed flags and, after that, BuildActionMap for the joysticks will follow. Maybe now it's time to discuss how to implement EnumDevicesBySemantics as a crosscall, but I really don't know how to do it (or if it's worth it) and everywhere I look in dinput I see similar cases of this "duplication pattern".
Another thing that I've been thinking is that I might as well end up rolling a version of ConfigureDevices (http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.idirectinput8....) because so far I've seen two of the games affected by bug 8754 use it to configure controls. I've not had time to find and test all of them, but if someone on the list knows about other games that use it I'd like to be informed.
Last but not least, thanks for Wylda for testing NFSU and keeping bug 8754 informed. I actually can't run the game properly, most likely because of the crappy intel graphics card in my laptop.
Anyway, feedback on the tasks is welcome.
--- lfz
Hey, I've got a couple patches implementing build and setactionmap for joysticks and I'd like you guys to give them a look.
These implementations are very generic and I think I could use them for the keyboard and the mouse too. If everything's alright with these patches that'll be my next step.
The mapping can be tested this small app I built: https://github.com/downloads/lfzawacki/dinput-samples/dolphin.exe provided that you have one joystick attached (it will chose the first one if there are more).
Cheers :)
2011/7/5 Lucas Zawacki lfzawacki@gmail.com:
Hi guys.
Now that all the initial patches are in I have several smaller tasks to work on as listed here http://lfzawacki.heroku.com/wine/published/Road+Map and hopefully they're more straightforward. I've already started working on getting EnumDevicesBySemantics correct with joysticks and the passed flags and, after that, BuildActionMap for the joysticks will follow. Maybe now it's time to discuss how to implement EnumDevicesBySemantics as a crosscall, but I really don't know how to do it (or if it's worth it) and everywhere I look in dinput I see similar cases of this "duplication pattern".
Another thing that I've been thinking is that I might as well end up rolling a version of ConfigureDevices (http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.idirectinput8....) because so far I've seen two of the games affected by bug 8754 use it to configure controls. I've not had time to find and test all of them, but if someone on the list knows about other games that use it I'd like to be informed.
Last but not least, thanks for Wylda for testing NFSU and keeping bug 8754 informed. I actually can't run the game properly, most likely because of the crappy intel graphics card in my laptop.
Anyway, feedback on the tasks is welcome.
lfz
On Tue, Jul 19, 2011 at 09:40:37PM -0300, Lucas Zawacki wrote:
Hey, I've got a couple patches implementing build and setactionmap for joysticks and I'd like you guys to give them a look.
The patches look good to my eyes.
This part:
if ((lpdiaf->rgoAction[i].dwSemantic & genre) == genre)
still looks strange (as the first genre should be a some kind of bitmask instead of genre?), but will likely work as-is for now.
These implementations are very generic and I think I could use them for the keyboard and the mouse too. If everything's alright with these patches that'll be my next step.
The mapping can be tested this small app I built: https://github.com/downloads/lfzawacki/dinput-samples/dolphin.exe provided that you have one joystick attached (it will chose the first one if there are more).
Works with my Joystick here at least.
Not sure what it should output, A and X button works, the ranges go to 10/-10 expect for "Down" just going to -5 (might be a issue with the joystick).
Ciao, Marcus
2011/7/5 Lucas Zawacki lfzawacki@gmail.com:
Hi guys.
Now that all the initial patches are in I have several smaller tasks to work on as listed here http://lfzawacki.heroku.com/wine/published/Road+Map and hopefully they're more straightforward. I've already started working on getting EnumDevicesBySemantics correct with joysticks and the passed flags and, after that, BuildActionMap for the joysticks will follow. Maybe now it's time to discuss how to implement EnumDevicesBySemantics as a crosscall, but I really don't know how to do it (or if it's worth it) and everywhere I look in dinput I see similar cases of this "duplication pattern".
Another thing that I've been thinking is that I might as well end up rolling a version of ConfigureDevices (http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.idirectinput8....) because so far I've seen two of the games affected by bug 8754 use it to configure controls. I've not had time to find and test all of them, but if someone on the list knows about other games that use it I'd like to be informed.
Last but not least, thanks for Wylda for testing NFSU and keeping bug 8754 informed. I actually can't run the game properly, most likely because of the crappy intel graphics card in my laptop.
Anyway, feedback on the tasks is welcome.
lfz
From b492c54d5ca7179e0905f63cec183d0920555e1d Mon Sep 17 00:00:00 2001 From: Lucas Fialho Zawacki lfzawacki@gmail.com Date: Tue, 19 Jul 2011 17:52:12 -0300 Subject: [PATCH 1/4] dinput: EnumDevicesBySemantics enumerating joysticks with priority flags
Added an utility function that checks the priority of a device for a given mapping. This can be modified later to return priority 2 mappings, if necessary.
dlls/dinput/dinput_main.c | 50 ++++++++++++++++++++++++++++++++------------ 1 files changed, 36 insertions(+), 14 deletions(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index b653307..1d59cdc 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -317,6 +317,38 @@ void _copy_diactionformatWtoA(LPDIACTIONFORMATA to, LPDIACTIONFORMATW from) } }
+/* _diactionformat_priorityA
- Given a DIACTIONFORMAT structure and a DI genre, returns the enumeration
- priority. Joysticks should pass the game genre, and mouse or keyboard their
- respective DI*_MASK
- */
+static DWORD _diactionformat_priorityA(LPDIACTIONFORMATA lpdiaf, DWORD genre) +{
- int i;
- DWORD priorityFlags = 0;
- /* If there's at least one action for the device it's priority 1 */
- for(i=0; i < lpdiaf->dwActionSize; i++)
if ((lpdiaf->rgoAction[i].dwSemantic & genre) == genre)
priorityFlags |= DIEDBS_MAPPEDPRI1;
- return priorityFlags;
+}
+static DWORD _diactionformat_priorityW(LPDIACTIONFORMATW lpdiaf, DWORD genre) +{
- int i;
- DWORD priorityFlags = 0;
- /* If there's at least one action for the device it's priority 1 */
- for(i=0; i < lpdiaf->dwActionSize; i++)
if ((lpdiaf->rgoAction[i].dwSemantic & genre) == genre)
priorityFlags |= DIEDBS_MAPPEDPRI1;
- return priorityFlags;
+}
/******************************************************************************
- IDirectInputA_EnumDevices
*/ @@ -877,7 +909,7 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics( { TRACE(" - checking device %u ('%s')\n", i, dinput_devices[i]->name);
callbackFlags = 0;
callbackFlags = _diactionformat_priorityA(lpdiActionFormat, lpdiActionFormat->dwGenre); /* Default behavior is to enumerate attached game controllers */ enumSuccess = dinput_devices[i]->enum_deviceA(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY | dwFlags, &didevi, This->dwVersion, j); if (enumSuccess)
@@ -895,16 +927,11 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics( /* Enumerate keyboard and mouse */ for(i=0; i < sizeof(guids)/sizeof(guids[0]); i++) {
callbackFlags = 0;
callbackFlags = _diactionformat_priorityA(lpdiActionFormat, actionMasks[i]); IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL); IDirectInputDevice_GetDeviceInfo(lpdid, &didevi);
/* If there's at least one action for the device it's priority 1 */
for(j=0; j < lpdiActionFormat->dwActionSize; j++)
if ((lpdiActionFormat->rgoAction[j].dwSemantic & actionMasks[i]) == actionMasks[i])
callbackFlags |= DIEDBS_MAPPEDPRI1;
}if (lpCallback(&didevi, lpdid, callbackFlags, sizeof(guids)/sizeof(guids[0]) - (i+1), pvRef) == DIENUM_STOP) return DI_OK;
@@ -942,7 +969,7 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics( { TRACE(" - checking device %u ('%s')\n", i, dinput_devices[i]->name);
callbackFlags = 0;
callbackFlags = _diactionformat_priorityW(lpdiActionFormat, lpdiActionFormat->dwGenre); /* Default behavior is to enumerate attached game controllers */ enumSuccess = dinput_devices[i]->enum_deviceW(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY | dwFlags, &didevi, This->dwVersion, j); if (enumSuccess)
@@ -960,16 +987,11 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics( /* Enumerate keyboard and mouse */ for(i=0; i < sizeof(guids)/sizeof(guids[0]); i++) {
callbackFlags = 0;
callbackFlags = _diactionformat_priorityW(lpdiActionFormat, actionMasks[i]); IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL); IDirectInputDevice_GetDeviceInfo(lpdid, &didevi);
/* If there's at least one action for the device it's priority 1 */
for(j=0; j < lpdiActionFormat->dwActionSize; j++)
if ((lpdiActionFormat->rgoAction[j].dwSemantic & actionMasks[i]) == actionMasks[i])
callbackFlags |= DIEDBS_MAPPEDPRI1;
}if (lpCallback(&didevi, lpdid, callbackFlags, sizeof(guids)/sizeof(guids[0]) - (i+1), pvRef) == DIENUM_STOP) return DI_OK;
-- 1.7.0.4
From 2c97c4d622a4731721705b81416191b47b738d71 Mon Sep 17 00:00:00 2001 From: Lucas Fialho Zawacki lfzawacki@gmail.com Date: Tue, 19 Jul 2011 20:25:48 -0300 Subject: [PATCH 2/4] dinput: BuildActionMap for all joysticks. For the moment only for buttons and axis.
Added an utility function that finds the Nth dataformat object of a given type.
dlls/dinput/device.c | 23 +++++++++++++++++++++++ dlls/dinput/device_private.h | 1 + dlls/dinput/joystick.c | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 1 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 22632ea..2bd5d6c 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 503698a..6c061b2 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/joystick.c b/dlls/dinput/joystick.c index 68dcc6a..d821748 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_BUTTON, DIDFT_AXIS };
- DWORD type_map[] = { DIDFT_PSHBUTTON, DIDFT_RELAXIS };
- 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) 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,
1.7.0.4
From a71ddba6092dd7a843c5359b26c4e9254311edfb Mon Sep 17 00:00:00 2001 From: Lucas Fialho Zawacki lfzawacki@gmail.com Date: Tue, 19 Jul 2011 20:44:36 -0300 Subject: [PATCH 3/4] dinput: SetActionMap for joysticks.
dlls/dinput/joystick.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 59 insertions(+), 1 deletions(-)
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c index d821748..c63def9 100644 --- a/dlls/dinput/joystick.c +++ b/dlls/dinput/joystick.c @@ -500,9 +500,67 @@ HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPCWSTR lpszUserName, DWORD dwFlags) {
- JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
- DIDATAFORMAT data_format;
- DIOBJECTDATAFORMAT *obj_df = NULL;
- int i, action = 0, num_actions = 0;
- unsigned int offset = 0;
- FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
- return DI_NOEFFECT;
- if (This->base.acquired) return DIERR_ACQUIRED;
- data_format.dwSize = sizeof(data_format);
- data_format.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
- data_format.dwFlags = DIDF_RELAXIS;
- data_format.dwDataSize = lpdiaf->dwDataSize;
- /* count the actions */
- for (i=0; i < lpdiaf->dwNumActions; i++)
if (IsEqualGUID(&This->base.guid, &lpdiaf->rgoAction[i].guidInstance))
num_actions++;
- if (num_actions == 0) return DI_NOEFFECT;
- This->base.num_actions = num_actions;
- /* Construct the dataformat and actionmap */
- obj_df = HeapAlloc(GetProcessHeap(), 0, sizeof(DIOBJECTDATAFORMAT)*num_actions);
- data_format.rgodf = (LPDIOBJECTDATAFORMAT)obj_df;
- data_format.dwNumObjs = num_actions;
- This->base.action_map = HeapAlloc(GetProcessHeap(), 0, sizeof(ActionMap)*num_actions);
- for (i = 0; i < lpdiaf->dwNumActions; i++)
- {
if (IsEqualGUID(&This->base.guid, &lpdiaf->rgoAction[i].guidInstance))
{
LPDIDATAFORMAT df = This->base.data_format.wine_df;
DWORD inst = DIDFT_GETINSTANCE(lpdiaf->rgoAction[i].dwObjID);
DWORD type = DIDFT_GETTYPE(lpdiaf->rgoAction[i].dwObjID);
LPDIOBJECTDATAFORMAT obj;
if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON;
if (type == DIDFT_RELAXIS) type = DIDFT_AXIS;
obj = dataformat_to_odf_by_type(df, inst, type);
memcpy(&obj_df[action], obj, df->dwObjSize);
This->base.action_map[action].uAppData = lpdiaf->rgoAction[i].uAppData;
This->base.action_map[action].offset = offset;
obj_df[action].dwOfs = offset;
offset += (type & DIDFT_BUTTON) ? 1 : 4;
action++;
}
- }
- IDirectInputDevice8_SetDataFormat(iface, &data_format);
- HeapFree(GetProcessHeap(), 0, obj_df);
- return IDirectInputDevice8WImpl_SetActionMap(iface, lpdiaf, lpszUserName, dwFlags);
}
HRESULT WINAPI JoystickAGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
1.7.0.4
From 4f18cfb471707c461135ecfde5f975324b37e696 Mon Sep 17 00:00:00 2001 From: Lucas Fialho Zawacki lfzawacki@gmail.com Date: Tue, 19 Jul 2011 21:03:16 -0300 Subject: [PATCH 4/4] dinput: SetActionMap setting the axis range according to the action format
dlls/dinput/device.c | 8 ++++++++ dlls/dinput8/tests/device.c | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 2bd5d6c..58d4e14 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -1483,9 +1483,17 @@ HRESULT WINAPI IDirectInputDevice8WImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface DWORD dwFlags) { DIPROPDWORD dp;
DIPROPRANGE dpr;
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
dpr.diph.dwSize = sizeof(DIPROPRANGE);
dpr.lMin = lpdiaf->lAxisMin;
dpr.lMax = lpdiaf->lAxisMax;
dpr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dpr.diph.dwHow = DIPH_DEVICE;
IDirectInputDevice8_SetProperty(iface, DIPROP_RANGE, &dpr.diph);
if (lpdiaf->dwBufferSize > 0) { dp.diph.dwSize = sizeof(DIPROPDWORD);
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index cedad80..31e2e3f 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -132,6 +132,7 @@ static BOOL CALLBACK enumeration_callback( { HRESULT hr; DIPROPDWORD dp;
- DIPROPRANGE dpr; struct enum_data *data = pvRef; if (!data) return DIENUM_CONTINUE;
@@ -179,6 +180,20 @@ static BOOL CALLBACK enumeration_callback( ok (SUCCEEDED(hr), "GetProperty failed hr=%08x\n", hr); ok (dp.dwData == data->lpdiaf->dwBufferSize, "SetActionMap must set the buffer, buffersize=%d\n", dp.dwData);
- /* Test axis range */
- memset(&dpr, 0, sizeof(dpr));
- dpr.diph.dwSize = sizeof(dpr);
- dpr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- dpr.diph.dwHow = DIPH_DEVICE;
- hr = IDirectInputDevice_GetProperty(lpdid, DIPROP_RANGE, &dpr.diph);
- /* Only test if device supports the range property */
- if (SUCCEEDED(hr))
- {
ok (dpr.lMin == data->lpdiaf->lAxisMin, "SetActionMap must set the min axis range expected=%d got=%d\n", data->lpdiaf->lAxisMin, dpr.lMin);
ok (dpr.lMax == data->lpdiaf->lAxisMax, "SetActionMap must set the max axis range expected=%d got=%d\n", data->lpdiaf->lAxisMax, dpr.lMax);
- }
- /* SetActionMap has set the data format so now it should work */ hr = IDirectInputDevice8_Acquire(lpdid); ok (SUCCEEDED(hr), "Acquire failed hr=%08x\n", hr);
-- 1.7.0.4
Hello!
Here's a lot of patches with a ConfigureDevices implementation. These patches can be tested with this app I built that uses ConfigureDevices to set up a joystick action mapping (https://github.com/downloads/lfzawacki/dinput-samples/dolphin-plugin.exe) . I also tested it with the Rally Trophy and Star Sonata games.
Any advice on the dialog code is appreciated, it's the first time I've coded something like this and may have missed some things.
This implementation still lacks some things:
* Implement username property for devices * Tracking down a bug with Rally Trophy that makes the mouse disappear while inside the ConfigureDevices dialog. * Implement the "Sort Assigned" checkbox * Some fixes to the code
I'll let the code resting here while I keep working on this stuff.
Cheers :)
On Fri, Jul 29, 2011 at 05:48:43PM -0300, Lucas Zawacki wrote:
Hello!
Here's a lot of patches with a ConfigureDevices implementation. These patches can be tested with this app I built that uses ConfigureDevices to set up a joystick action mapping (https://github.com/downloads/lfzawacki/dinput-samples/dolphin-plugin.exe) . I also tested it with the Rally Trophy and Star Sonata games.
Any advice on the dialog code is appreciated, it's the first time I've coded something like this and may have missed some things.
This implementation still lacks some things:
- Implement username property for devices
- Tracking down a bug with Rally Trophy that makes the mouse disappear
while inside the ConfigureDevices dialog.
- Implement the "Sort Assigned" checkbox
- Some fixes to the code
I'll let the code resting here while I keep working on this stuff.
If this is to some degree functional it can also be included already :)
One thing in 0001:
- /* Copy action names */
- for (i=0; i < diafW.dwNumActions; i++)
- {
const char* from = lpdiCDParams->lprgFormats->rgoAction[i].u.lptszActionName;
WCHAR *to = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*MAX_PATH);
MultiByteToWideChar(CP_ACP, 0, from , -1, to , MAX_PATH);
diafW.rgoAction[i].u.lptszActionName = to;
- }
The pattern to do this is usually by querying MBtoWC for the result length and then allocating and doing it for real (untested):
const char* from = lpdiCDParams->lprgFormats->rgoAction[i].u.lptszActionName; WCHAR *to; DWORD len;
len = MultiByteToWideChar(CP_ACP, 0, from , -1, NULL , 0); to = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, from , -1, to, len); diafW.rgoAction[i].u.lptszActionName = to;
- hr = IDirectInput8WImpl_ConfigureDevices(&This->IDirectInput8W_iface, lpdiCallback, &diCDParamsW, dwFlags, pvRefData);
Should the action format be copied back on error?
- /* Copy back configuration */
- _copy_diactionformatWtoA(lpdiCDParams->lprgFormats, &diafW);
- /* Free memory */
- for (i=0; i < diafW.dwNumActions; i++)
HeapFree(GetProcessHeap(), 0, (LPVOID) diafW.rgoAction[i].u.lptszActionName);
- HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
FIXME("(this=%p,%p,%p,%04x,%p): stub\n", This, lpdiCallback, lpdiCDParams,
dwFlags, pvRefData);
return 0;
- return hr;
I also read over the dialog stuff ... I did not see anything problematic, looked to my untrained eyes :)
Ciao, Marcus
Hello. I need some help here.
Before commiting the ConfigureDevices patches tried to add a couple simple tests for the function, the problem is that I now have to test a dialog. What is the best way to do it? I'm thinking of creating another thread and sending the desired messages to the dialog, is that a good option? I'm open to suggestions.
On Fri, Jun 24, 2011 at 01:37:41PM -0300, Lucas Zawacki wrote:
Is there any problem with the latest patches I sent? They're sitting there with the 'New' status but I have no feedback (good or bad) about them.
I think there are still in the backlog. If there are not in Mondays commit round, resend them on Tuesday or so :)
Ciao, Marcus
On 06/12/2011 07:45 PM, Lucas Zawacki wrote:
I'm having some issues with test that inject input. For instance this code ( http://pastebin.com/gan0Niqj ) works as expected under wine and wine with dinput8.dll , but fails in every windows version... I tried a version with SendInput and had the same results...
Anyone has some insight on this?
keybd_event( key, 0, 0, 0);
Have you tried using more meaningful parameters then 0?
Vitaliy.
keybd_event( key, 0, 0, 0); Have you tried using more meaningful parameters then 0?
Yes, I've tried issuing a scan code as the second parameter, it was no use. I tried sending the keybd_event and then sending another one with KEYEVENTF_KEYUP to "emulate" a key press and a release and still no change. I've tried setting dummy values as the last parameter, but had similar results. I don't know what it's for and msdn was not helpful...
On 06/14/2011 10:57 AM, Lucas Zawacki wrote:
keybd_event( key, 0, 0, 0); Have you tried using more meaningful parameters then 0?
Yes, I've tried issuing a scan code as the second parameter, it was no use. I tried sending the keybd_event and then sending another one with KEYEVENTF_KEYUP to "emulate" a key press and a release and still no change. I've tried setting dummy values as the last parameter, but had similar results. I don't know what it's for and msdn was not helpful...
On Windows dinput really does talk to the driver directly. That's why you don't see those injected events. At least you can test things with native dinput on Wine. And don't include tests in your patches. Just use them to validate that everything is working.
Vitaliy.