joystick GetDeviceData patch
Rob Crittenden <[email protected]>
| Newsgroups | gmane.comp.emulators.winex.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi. I'm not sure if this got rejected or not so I'm resubmitting it. This is an implemention of GetDeviceData() for joysticks. It is based heavily on the existing mouse and keyboard implementations. From my testing using simple test programs as well as with BF1942 it works and doesn't break mice. This makes a minor change to the mouse code by adding an overflow state that isn't actually used, but since the mouse and joystick share code it had to be. I was able to get BF1942 to play nicely after a fashion. I found the mapping capabilities very wanting. After mapping 1 axis anything else I tried to map would also map to that axis. The workaround is to map 1 axis at a time by saving and exiting the options screen between mappings (or was that quit the game altogether?). Mapping buttons doesn't have this problem. I've got some pretty lame joysticks but using a MS Sidewinder I was able to map forward/back/left/right movement plus fire/alt-fire and was able to play after a fashion. It takes some practice to get the +/- axis set properly but once I got it everything was fine. You have to click on the forward/back left/right to get the right +/- otherwise forward is back and left is right. rob
joystick.diff
(text/plain, 5 KB)
Index: dinput/device_private.h
===================================================================
RCS file: /cvsroot/winex/dlls/dinput/device_private.h,v
retrieving revision 1.11
diff -u -r1.11 device_private.h
--- dinput/device_private.h 15 Nov 2003 01:15:01 -0000 1.11
+++ dinput/device_private.h 23 Feb 2004 15:14:52 -0000
@@ -58,6 +58,8 @@
This->data_queue[This->queue_head].dwSequence = seq; \
This->queue_head = nq; \
} \
+ else \
+ This->overflow = TRUE; \
} \
}
Index: dinput/joystick/main.c
===================================================================
RCS file: /cvsroot/winex/dlls/dinput/joystick/main.c,v
retrieving revision 1.7
diff -u -r1.7 main.c
--- dinput/joystick/main.c 18 Feb 2004 22:27:38 -0000 1.7
+++ dinput/joystick/main.c 23 Feb 2004 15:14:55 -0000
@@ -83,8 +83,10 @@
DataFormat* wine_df;
ObjProps* props;
HANDLE hEvent;
+ CRITICAL_SECTION crit;
LPDIDEVICEOBJECTDATA data_queue;
int queue_head, queue_tail, queue_len;
+ BOOL overflow;
/* effects */
DWORD dwAutoCenter;
@@ -208,9 +210,13 @@
newDevice->props[u].lMax = 0xFFFF;
newDevice->props[u].lDeadZone = 1000; /* 10% */
newDevice->props[u].lSaturation = 0; /* 0% */
+ newDevice->queue_len = -1; /* unbuffered */
+ newDevice->overflow = FALSE;
}
}
+ InitializeCriticalSection(&(newDevice->crit));
+
newDevice->dwGain = 10000;
newDevice->dwAutoCenter = 0;
for (u=0; u<MAX_EFFECTS; u++)
@@ -292,6 +298,8 @@
if (This->data_queue != NULL)
HeapFree(GetProcessHeap(),0,This->data_queue);
+ DeleteCriticalSection(&(This->crit));
+
/* Free the DataFormat */
HeapFree(GetProcessHeap(), 0, This->offset_array);
HeapFree(GetProcessHeap(), 0, This->buffer);
@@ -448,21 +456,56 @@
DWORD flags
) {
ICOM_THIS(JoystickAImpl,iface);
+ DWORD len, count, nqtail;
+ int ret = DI_OK;
- FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
+ TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
if (!This->acquired)
return DIERR_NOTACQUIRED;
- joy_polldev(This, FALSE, TRUE);
- if (flags & DIGDD_PEEK)
- FIXME("DIGDD_PEEK\n");
- *entries = 0;
+ if (This->queue_len == -1)
+ return DIERR_NOTBUFFERED;
+
+ if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3))
+ return DIERR_INVALIDPARAM;
- if (dod == NULL) {
- } else {
+ EnterCriticalSection(&(This->crit));
+
+ len = ((This->queue_head < This->queue_tail) ? This->queue_len : 0)
+ + (This->queue_head - This->queue_tail);
+ if (len > *entries) len = *entries;
+
+ count = 0;
+ nqtail = This->queue_tail;
+ while ((count < *entries || *entries == INFINITE) && count < len) {
+ if (dod != NULL) {
+ LPDIDEVICEOBJECTDATA pd = (LPDIDEVICEOBJECTDATA)((BYTE *)dod + dodsize * count);
+ pd->dwOfs = This->data_queue[nqtail].dwOfs;
+ pd->dwData = This->data_queue[nqtail].dwData;
+ pd->dwTimeStamp = This->data_queue[nqtail].dwTimeStamp;
+ pd->dwSequence = This->data_queue[nqtail].dwSequence;
+ }
+ nqtail++;
+ if (nqtail >= This->queue_len) nqtail -= This->queue_len;
+ count++;
}
- return 0;
+
+ if (This->overflow)
+ ret = DI_BUFFEROVERFLOW;
+
+ if (!(flags & DIGDD_PEEK)) {
+ This->queue_tail = nqtail;
+ This->overflow = FALSE;
+ }
+
+ TRACE("%s %ld events %s\n", *entries == INFINITE ? "Flushing" : "Returning", count, ret == DI_OK ? "" : "BUFFEROVERFLOW");
+
+ *entries = count;
+
+ LeaveCriticalSection(&(This->crit));
+
+ return ret;
}
int find_object(JoystickAImpl *This, DWORD dwHow, DWORD dwObj)
@@ -519,7 +562,13 @@
case (DWORD) DIPROP_BUFFERSIZE: {
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
- FIXME("buffersize = %ld\n",pd->dwData);
+ TRACE("buffersize(%ld)\n", pd->dwData);
+
+ This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
+ pd->dwData * sizeof(DIDEVICEOBJECTDATA));
+ This->queue_head = 0;
+ This->queue_tail = 0;
+ This->queue_len = pd->dwData;
break;
}
case (DWORD)DIPROP_RANGE: {
Index: dinput/mouse/main.c
===================================================================
RCS file: /cvsroot/winex/dlls/dinput/mouse/main.c,v
retrieving revision 1.47
diff -u -r1.47 main.c
--- dinput/mouse/main.c 18 Feb 2004 22:27:38 -0000 1.47
+++ dinput/mouse/main.c 23 Feb 2004 15:14:58 -0000
@@ -136,6 +136,7 @@
DWORD win_centerX, win_centerY;
LPDIDEVICEOBJECTDATA data_queue;
int queue_head, queue_tail, queue_len;
+ BOOL overflow;
/* warping: whether we need to move mouse back to middle once we
* reach window borders (for e.g. shooters, "surface movement" games) */
WARP_STATUS need_warp;