Re: joystick GetDeviceData patch
Rob Crittenden <[email protected]>
| Newsgroups | gmane.comp.emulators.winex.devel |
|---|---|
| Message-ID | <[email protected]> |
On Tue, 30 Mar 2004, Ove Kaaven wrote: > The device.c part of this patch is probably not supposed be included. > The rest seems OK, except for a couple of things. Ack, yeah, I got tired of seeing those. Didn't mean to include it. > 1. I'm wondering if the overflow flag really should be cleared when the > app is just peeking with DIGDD_PEEK now? You had it differently in your > previous version of the patch? Ah, yeah, right. My thinking last night was "Why clear the flag with every fetch even when it hasn't overflowed?" I wasn't thinking about the PEEK case. I've fixed it. > 2. You seem to be removing the joy_polldev() call from GetDeviceData. I > don't think you should. For Linux 2.2, 2.4, and 2.6, the device is not > really a polled device, so we do not specify the DIDOI_POLLED flag. > There's a chance some games may actually honor this flag properly, by > not calling Poll when it's absent, and these would not work if you > remove the call. Hmm. Yeah, I don't know why I took that out. It turns out the BF1942 calls GetDeviceState() as well and this ends up queuing up any events. My sample program (from DX9 joystick example) didn't originally call GetDeviceData(), I just hacked it to call it and display the # of events that were returned but still report any events using GetDeviceState(). So basically I goofed in removing it and my 2 test programs didn't catch it. I added a call to joy_polldev() and removed the state check from my sample and it still works. > By the way, there's a bug in joy_polldev, where the GEN_EVENT macro is > fed the original dwData from the device driver, instead of the > range-adjusted value (dwOut) which was written to > This->buffer+odf->dwOfs. Feel free to fix it. It could even be related > to your axis problem. Sure, included. Another patch is attached. Thanks for your patience. rob
joystick.diff
(text/plain, 7.3 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 30 Mar 2004 14:36:10 -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.6
diff -u -r1.6 main.c
--- dinput/joystick/main.c 21 Dec 2003 04:13:30 -0000 1.6
+++ dinput/joystick/main.c 30 Mar 2004 14:36:13 -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;
@@ -210,6 +212,10 @@
newDevice->props[u].lSaturation = 0; /* 0% */
}
}
+ newDevice->queue_len = -1; /* unbuffered */
+ newDevice->overflow = FALSE;
+
+ InitializeCriticalSection(&(newDevice->crit));
newDevice->dwGain = 10000;
newDevice->dwAutoCenter = 0;
@@ -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);
@@ -350,6 +358,7 @@
HRESULT hr;
DWORD dwObj;
DWORD dwData;
+ DWORD dwEvent;
DWORD dwTimeStamp;
do {
@@ -360,9 +369,10 @@
odf = &This->drvdf->rgodf[dwObj];
/* update state buffer */
- if (odf->dwType & DIDFT_BUTTON)
+ if (odf->dwType & DIDFT_BUTTON) {
*(BYTE*)(This->buffer+odf->dwOfs) = dwData;
- else if (odf->dwType & DIDFT_AXIS) {
+ dwEvent = dwData;
+ } else if (odf->dwType & DIDFT_AXIS) {
/* FIXME: cache these */
LONG pmin = This->props[dwObj].lMin;
LONG pmax = This->props[dwObj].lMax;
@@ -382,12 +392,15 @@
dwOut = (pmin + pmax) / 2;
*(DWORD*)(This->buffer+odf->dwOfs) = dwOut;
- } else
+ dwEvent = dwOut;
+ } else {
*(DWORD*)(This->buffer+odf->dwOfs) = dwData;
+ dwEvent = dwData;
+ }
/* generate event */
if (gen_event) {
- GEN_EVENT(This->offset_array[dwObj],dwData,dwTimeStamp,(This->dinput->evsequence)++);
+ GEN_EVENT(This->offset_array[dwObj],dwEvent,dwTimeStamp,(This->dinput->evsequence)++);
}
} while (TRUE);
}
@@ -448,21 +461,62 @@
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;
+ if (This->queue_len == -1)
+ return DIERR_NOTBUFFERED;
+
+ if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3))
+ return DIERR_INVALIDPARAM;
+
+ /* Check for any events */
joy_polldev(This, FALSE, TRUE);
- if (flags & DIGDD_PEEK)
- FIXME("DIGDD_PEEK\n");
- *entries = 0;
- 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->overflow = FALSE;
+ }
+ }
+
+ if (!(flags & DIGDD_PEEK)) {
+ This->queue_tail = nqtail;
+ }
+
+ TRACE("Application %s %ld event(s). %s\n", *entries == INFINITE ? "flushing" : "retrieving", count, ret == DI_OK ? "" : "BUFFEROVERFLOW");
+
+ *entries = count;
+
+ LeaveCriticalSection(&(This->crit));
+
+ return ret;
}
int find_object(JoystickAImpl *This, DWORD dwHow, DWORD dwObj)
@@ -519,7 +573,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.46.2.2
diff -u -r1.46.2.2 main.c
--- dinput/mouse/main.c 2 Mar 2004 17:21:18 -0000 1.46.2.2
+++ dinput/mouse/main.c 30 Mar 2004 14:36:16 -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;
@@ -222,6 +223,9 @@
newDevice->win = GetDesktopWindow();
newDevice->dwCoopLevel = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND;
+ newDevice->queue_len = -1; /* unbuffered */
+ newDevice->overflow = FALSE;
+
return newDevice;
}
@@ -806,6 +810,7 @@
) {
ICOM_THIS(SysMouseAImpl,iface);
DWORD len, count, nqtail;
+ int ret = DI_OK;
TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
@@ -814,6 +819,10 @@
return DIERR_NOTACQUIRED;
}
+ if (This->queue_len == -1) {
+ return DIERR_NOTBUFFERED;
+ }
+
EnterCriticalSection(&(This->crit));
len = ((This->queue_head < This->queue_tail) ? This->queue_len : 0)
@@ -851,8 +860,16 @@
}
*entries = count;
}
- if (!(flags & DIGDD_PEEK))
+ if (This->overflow) {
+ ret = DI_BUFFEROVERFLOW;
+ if (!(flags & DIGDD_PEEK)) {
+ This->overflow = FALSE;
+ }
+ }
+
+ if (!(flags & DIGDD_PEEK)) {
This->queue_tail = nqtail;
+ }
LeaveCriticalSection(&(This->crit));
@@ -862,7 +879,7 @@
dinput_window_check(This);
dinput_mouse_warp(This, FALSE);
}
- return 0;
+ return ret;
}
/******************************************************************************