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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.