News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Getting my joystick working under Direct Input

Started by hamper, December 01, 2013, 10:00:30 AM

Previous topic - Next topic

dedndave

yes - i caught the JOYCAPS issue and made notes in the appropriate sub-forum
here's what i plan to use
_JOYCAPS    STRUCT
  wMid        WORD  ?
  wPid        WORD  ?
  szPname     TCHAR MAXPNAMELEN dup(?)             ;32
  wXmin       UINT  ?
  wXmax       UINT  ?
  wYmin       UINT  ?
  wYmax       UINT  ?
  wZmin       UINT  ?
  wZmax       UINT  ?
  wNumButtons UINT  ?
  wPeriodMin  UINT  ?
  wPeriodMax  UINT  ?
  wRmin       UINT  ?
  wRmax       UINT  ?
  wUmin       UINT  ?
  wUmax       UINT  ?
  wVmin       UINT  ?
  wVmax       UINT  ?
  wCaps       UINT  ?
  wMaxAxes    UINT  ?
  wNumAxes    UINT  ?
  wMaxButtons UINT  ?
  szRegKey    TCHAR MAXPNAMELEN dup(?)             ;32
  szOEMVxD    TCHAR MAX_JOYSTICKOEMVXDNAME dup(?)  ;260
_JOYCAPS    ENDS


i hadn't checked the others, yet
probably won't need JOYINFOEX

hamper

I've been running a few tests using the functions in winmm.lib.

The function joyGetPos, used with a JOYINFO structure, works fine. It isn't just restricted to 4 buttons as advertised - it picks up all the buttons without problem. The members definitely have to be dword (not word as per MASM32).
The function joyGetPosEx, used with a JOYINFOEX structure, works fine. It picks up all the axes, buttons and POV hat positions etc.
I didn't need to use joySetCapture first with either of these - they just worked straight off.

But I haven't yet been able to get any response from the MM_JOY1MOVE message, with or without first using the joySetCapture function. More testing to do on this, then.

I've also tried to get information on the joy32Message function that's prototyped in winmm.inc, but haven't been able to find anything on it yet. I did a search on Microsoft's site and it didn't come up with any reference for it. So I don't yet know what this function does. Looks suspiciously like something to do with joystick messages though, doesn't it?



dedndave

from what i can gather, the messages are sent only to a window that has joySetCapture

the problem that i'm having is determining if any window has joy capture
and - when capture changes - how is the window losing capture notified

even though i don't have a joystick connected, i can do some testing by running 2 test apps   :P

joy32Message is probably an internal function


also - i read something about registering a window message
more reading.....

dedndave

ok - well, i can't set capture without one connected

hamper

If joySetCapture has been used, the joystick is automatically released when the window is destroyed.

But I'm getting some very wierd results from the message MM_JOY1MOVE...

The MM_JOY1MOVE message is getting repeatedly posted to the message queue when the joystick is connected, and after I have invoked joySetCapture, but ONLY when I move the window around using the mouse! If I just move the joystick, the message doesn't get posted at all. Very strange. And it doesn't get posted at all unless the joystick is connected, or if joySetCapture is omitted.

I've tried using different parameters for joySetCapture, and either nothing happens at all, or the message gets posted in response to the mouse moving the window. Nothing gets posted if I just move the mouse cursor itself - just if it moves the window. Another wierd thing is that the messages get posted according to the polling frequency I've specified in joySetCapture, but never when I move the joystick - only ever when I move the window around on the desktop using the mouse.

So I guess the upshot of everything so far is that the joyGetPos and joyGetPosEx functions work fine with their JOYINFO and JOYINFOEX structures, and the other regular functions are ok too, but the joystick messages don't work. So just use joyGetPos (or joyGetPosEx for rudder and POV) in a loop, or as required.

dedndave

you have to read the joySetCapture documentation carefully
there are 2 basic modes - time-based and event-based
you probably have it set up as time-based, so messages are received periodically
the other way - you have to set a threshold level to generate an event message

in the mean time, i found a simple solution to my problem
a virtual joystick emulator
http://headsoft.com.au/index.php?category=vjoy

i set up 2 virtual joysticks...

Joystick #0: Connected
Joystick #1: Connected
Joystick #2: Not Connected
Joystick #3: Not Connected
Joystick #4: Not Connected
Joystick #5: Not Connected
Joystick #6: Not Connected
Joystick #7: Not Connected
Joystick #8: Not Connected
Joystick #9: Not Connected
Joystick #10: Not Connected
Joystick #11: Not Connected
Joystick #12: Not Connected
Joystick #13: Not Connected
Joystick #14: Not Connected
Joystick #15: Not Connected


so, let's see where i can go from there - after my nap   :P

Antariy

A crude attampt to use DirectInput - just enumerate devices, interesting what will it output for the joystick attached.


include \masm32\include\masm32rt.inc
include \masm32\include\wininet.inc
includelib \masm32\lib\wininet.lib

.686
.mmx
.xmm

.data

.code

enumdevs proc uses esi DIDEVICEINSTANCE:DWORD, pVoid:DWORD
    mov esi,DIDEVICEINSTANCE
    lea ecx,[esi+300]
    invoke crt_printf,CTXT("Attached device: %s",13,10),ecx   


ret
enumdevs endp

start proc
LOCAL ci:CLSID
LOCAL buf[128]:BYTE
LOCAL hlib:DWORD
LOCAL padr:DWORD
LOCAL obj:DWORD

lea edi,buf
lea edx,ci
mov esi,offset CTXT("{BF798030-483A-4DA2-AA99-5D64ED369700}")

push 16*2+4+1+2
pop ecx
push edx
xor eax,eax
push edi
@@:
lodsb
stosw
loop @B

call CLSIDFromString

xor eax,eax
lea edx,obj
lea ecx,ci

push eax
push edx
push ecx

invoke crt_printf,CTXT("%p, %p, %p",13,10)
push 0800h

invoke GetModuleHandle,0
push eax

invoke LoadLibrary,CTXT("dinput8.dll")
mov hlib,eax
invoke GetProcAddress,eax,CTXT("DirectInput8Create")
mov padr,eax

call eax

mov esi,obj

invoke crt_printf,CTXT("Object: %p",13,10),esi

mov eax,[esi]
push 0
push esi
push offset enumdevs
push 0
push esi
call dword ptr [eax+4*4] ; EnumDevices

invoke crt__getch
invoke crt_exit,0
            
start endp


end start



Output (without joysticks):

0012FFB0, 0012FF24, 00000000
Object: 0015B0BC
Attached device: Mouse
Attached device: Keyboard

dedndave

;include \masm32\include\wininet.inc
;includelib \masm32\lib\wininet.lib


:biggrin:

0012FFB0, 0012FF24, 00000000
Object: 00145744
Attached device: Mouse
Attached device: Keyboard
Attached device: Microsoft Wireless Desktop Receiver 3.1
Attached device: Microsoft Wireless Desktop Receiver 3.1
Attached device: VJoy Virtual Joystick
Attached device: VJoy Virtual Joystick
Attached device: VJoy Virtual Joystick


:t

although, only 1 Desktop Receiver
only 2 Virtual Joysticks

that happens quite often with other enumerations
for example, when i enumerate console Terminal fonts, the 8x12 font always shows up twice

it may be that the driver simply reserves that many channels, too

FORTRANS

Hi,

   FWIW.  PS/2 mouse and keyboard, analog joystick.


0012FFB0, 0012FF24, 00000000
Object: 00143994
Attached device: Mouse
Attached device: Keyboard
Attached device: 3-axis, 2-button joystick


Regards,

Steve N.

Antariy

Thank you, Dave and Steve! :biggrin:

Dave, yes I think you're right about enumeration duplication :t Interesting, what is the "Desktop Receiver"? Is that also some virtual device? I.e., software extension using driver to make some functionality? If so, it looks like those virtual devices have this enumeration problem?

dedndave

that's the wireless transceiver for the mouse/keyboard
which - i only have one
the enumeration dup's may have something to do with XP Media Center Edition

dedndave

from what i gather, if you use joySetCapture to set up event-based (threshold) messages,
the buttons no longer send messages - just joystick movement

well, that was dumb, microsoft   ::)

dedndave

#57
i am trying to create a clean DirectInput8 interface include file

all seems fine, until i call the EnumDevices method
it returns EAX = 2  (file not found ?), which isn't even in the list of valid return values   :(

i must be doing something wrong, in terms of calling the COM function
i tried a few different variations on the EnumDevices parms with no luck
maybe someone more experienced with COM can spot the error of my ways

EDIT: attachment removed
see reply #61

Antariy

Dave, you defined the object virtual-table layout so:

IDirectInput8 STRUCT
  METHOD(CreateDevice,           _this:LPVOID,rguid:LPVOID,lplpDirectInputDevice:LPVOID,pUnkOuter:LPVOID)
  METHOD(EnumDevices,            _this:LPVOID,dwDevType:DWORD,lpCallback:LPVOID,pvRef:LPVOID,dwFlags:DWORD)
  METHOD(GetDeviceStatus,        _this:LPVOID,rguidInstance:LPVOID)
  METHOD(RunControlPanel,        _this:LPVOID,hwndOwner:HWND,dwFlags:DWORD)
  METHOD(Initialize,             _this:LPVOID,hinst:HINSTANCE,dwVersion:DWORD)
  METHOD(FindDevice,             _this:LPVOID,rguidClass:LPVOID,ptszName:LPCSTR,pguidInstance:LPVOID)
  METHOD(EnumDevicesBySemantics, _this:LPVOID,ptszUserName:LPCSTR,lpdiActionFormat:LPVOID,lpCallback:LPVOID,pvRef:LPVOID,dwFlags:DWORD)
  METHOD(ConfigureDevices,       _this:LPVOID,lpdiCallback:LPVOID,lpdiCDParams:LPVOID,dwFlags:DWORD,pvRefData:LPVOID)
IDirectInput8 ENDS


but there is a need to insert three addresses more at the start of the struct:

QueryInterface Returns pointers to supported interfaces.
AddRef Increments reference count.
Release Decrements reference count.


because the COM objects are inheriting the standard IUnknown interface methods (functions) - they are go first in the every object's VTable, the same implies for every interface with inheritance - the methods of the father interface are going first in the VTable (struct) of the child interface, of some class (interface definition) will be derived from IDirectInput, for an instance, then it will have all the methods of the IUnknown, then IDirectInput, then its own methods in the order.

GoneFishing

Acording to dinput8.inc from Dxsdk90:

;***************************************************************************
;*
;*  Return Codes
;*
;***************************************************************************

; The operation completed successfully.

   DI_OK                       EQU     S_OK

; The device exists but is not currently attached.

   DI_NOTATTACHED              EQU     S_FALSE

; The device buffer overflowed.  Some input was lost.

   DI_BUFFEROVERFLOW           EQU     S_FALSE

; The change in device properties had no effect

   DI_PROPNOEFFECT             EQU     S_FALSE

; The operation had no effect.

   DI_NOEFFECT                 EQU     S_FALSE

; The device is a polled device.  As a result, device buffering
; will not collect any data and event notifications will not be
; signalled until GetDeviceState is called.

   DI_POLLEDDEVICE             EQU     000000002h     

;  The parameters of the effect were successfully updated by
;  IDirectInputEffect::SetParameters, but the effect was not
;  downloaded because the device is not exclusively acquired
;  or because the DIEP_NODOWNLOAD flag was passed.

   DI_DOWNLOADSKIPPED          EQU     000000003h     

;  The parameters of the effect were successfully updated by
;  IDirectInputEffect::SetParameters, but in order to change
;  the parameters, the effect needed to be restarted.

   DI_EFFECTRESTARTED          EQU     000000004h     

;  The parameters of the effect were successfully updated by
;  IDirectInputEffect::SetParameters, but some of them were
;  beyond the capabilities of the device and were truncated.

   DI_TRUNCATED               EQU     000000008h     

;  The settings have been successfully applied but could not be
;  persisted.

   DI_SETTINGSNOTSAVED          EQU     00000000Bh     

;  Equal to DI_EFFECTRESTARTED | DI_TRUNCATED.

   DI_TRUNCATEDANDRESTARTED     EQU     00000000Ch     

;  A SUCCESS code indicating that settings cannot be modified.

   DI_WRITEPROTECT               EQU     000000013h