So I'm continuing with my learning process with OpenGL, and have now managed to get a wireframe teapot rendered in fullscreen perspective view, with keyboard controls for the x, y and z axes of rotation, and using the mousewheel to control the field of view. What I'd like to do next is get my joystick working.
The regular Windows messages don't work for the joystick, so I presume it must be operating under the Direct Input system (it's a Saitek Cyborg 3D into the USB port). There are two functions that seem to be critical in using joystick input under Direct Input - SetDataFormat and GetDeviceState. Does anyone know which library files I need to "includelib" to get access to these function? I've tried dinput.lib, dinput8.lib and winmm.lib, and all I ever get is "unresolved external...", so the functions don't seem to be in any of these.
Is direct input supported by MASM32? If so, which library files do I need to includelib to get access to these functions?
My joystick works automatically under Windows, so that's not the problem. And looking at my C++ setup (Borland), it seems that I might be able to get the functions under C++. Maybe even Nasm might have them? But out of principle I'd prefer to continue to work it out under MASM32 and assembly language, if that's possible (which surely it must be, somehow). Do I need to get some additional libraries perhaps? If so, any links as to where I can get them from?
Any help appreciated.
Phil
you might try this package from Franck....
http://perso.orange.fr/franck.charlet/Ogl_Asm.zip (http://perso.orange.fr/franck.charlet/Ogl_Asm.zip)
Yeah, I looked through all Franck's examples, but couldn't find the answer. Couldn't find anything that actually used a Direct Input joystick, just mouse and mouse wheel (which I've already got implemented). Plus lots of copies of C++ header file entries, but again no actual implementation of a Direct Input joystick. That's not to say it might not be there, just that I can't find anything.
Dynamic linking to C:\WINDOWS\system32\dx8vb.dll is not an option, I guess?
If it's COM, http://www.japheth.de/COMnASM.html is a good starting point, plus the posts of ToutEnMasm here and in the old forum (http://www.masmforum.com/board/index.php#1).
also - need be, we can make in INC and import LIB
Hi Hamper,
You may want to download an older DirectX SDK .
I have August 2007 version and in the \Samples\C++\DirectInput folder I see Joystick example.
... or try searching in MSDN Code Samples
I hope you will share with us your impressing demos ;)
Thanks everyone,
I think I'll try using the approach of dynamically linking a .dll library and see if that works.
vertograd, they're not impressing demos, not even particularly impressive - just little programs to lay out the foundations as I'm working my way through OpenGL, trying different things out to gradually learn how it all works.
Read the comments in the source code file first - e.g. spacebar exits.
i needed glut32.dll, but...
nice teapot :t
xp sp3
the rotation works great
very nice :t
zooming in , zooming out , rotation - all works
it's a big progress
Well, trying to work out how to get my joystick working under assembly language has left me baffled and exhausted. I can't find any of the functions used under DirectInput anywhere within the assembly language system. And even if I could, I can't find any examples or tutorials that explain the process in language that I understand ... everything is C++, which might as well be written in Martian to me.
So it seems to me that the only way I'm ever going to accomplish this (seemingly enormous) feat is to take up C++ programming. Now I've got a C++ compiler, and I can program in C, but C++ programming seems like "la la land" programming to me, with all its classes, objects, friendships, inheritance, polymorphism, constructors, destructors and overloading etc. And Micro$oft doesn't help - why use just one data type when 5 or 6 or 7 or more equivalent datatypes but all using different names will do? And why just use a pointer when you could use a pointer to a pointer?
So it's either learn C++ programming, and especially how Micro$oft does it, or pack it in. And at the moment I'm not persuaded to learn C++ programming or learn to love the Micro$oft approach. Maybe I'll just take up server side scripting (if I knew what that was).
But thanks for your help anyway.
hamper,
Don't give up so quickly. I understand your feelings, actually I feel the same: This is COM stuff, and it's utterly clumsy for my taste.
Have a look at this old article: May the Force Feedback Be with You: Grappling with DirectX and DirectInput (http://www.microsoft.com/msj/0298/force.aspx)
We have at least four COM specialists around: Edgar, ToutEnMasm, qWord and Japheth (apologies if somebody else feels also strong enough to attack this :redface:)
Maybe one of them has some time to look into this problem...
Jochen's right - patience
the dinput8.inc file is far from complete
it's just missing a few goodies :P
and, the dinput8.lib file is built, based on the contents of the inc file
a little bit of an advanced technique, but we have been known to update include files and import libraries
the simplest way is probably to use dynamic linking
that will get you up and running
what slows me down (and probably Jochen and others) is that we don't happen to have joysticks
actually, i do have one out in the shed, i think - a Microsoft SideWinder
but, as i recall, it connected to a "game" port, which this machine does not have
i probably have boards, too - lol - heaven only knows if they'll work in this computer
does your joystick connect to a USB port ?
hmmmm - don't recall an adapter
wonder if i have that :P
(http://i.ebayimg.com/t/Microsoft-Sidewinder-Precision-Pro-Joystick-USB-/00/s/MTIwMFgxNjAw/z/gt8AAOxy2HFSWxPG/$%28KGrHqZ,!n4FJKU,FLZ%29BSW%29PF50Zw~~60_35.JPG)
last time i used it, i was running windows 98 :lol:
the soundblaster card on that machine has a game port
jj2007,
That's exactly the tutorial I started working my way through. I'd looked on the net for (and downloaded) anything to do with using a joystick under DirectInput, and that was one of them. When I started working my way through everything, that one seemed to be the easiest to follow. But it all came to a shuddering halt when I realised that none of the functions (at least none after the first one) were actually present in masm32.
dedndave,
USB, unfortunately. If it was one of the older gameport joysticks I could just use the regular Windows messages to pick everything up. Ahhhhh, for the old days when everthing was simpler, eh?
Re "the simplest way is probably to use dynamic linking that will get you up and running", well I looked up how to do that, but it all depends on knowing, of course, which particular .dll you need to dynamically link. I studied the utility "dumpbin" and tried to use that to try and find out which functions were in which libraries, but all I ever got out from it was an empty text file (0 bytes in length).
i wanted to go a similar path
build the directx SDK joystick example, then disassemble it to see the imports
unfortunately, the VS C++ version that i have is apparently too old to build the example
but, let me see if i can struggle my way through the source.....
ahhhh - i found Joystick.exe in the bin folder :P
i used an old DisAsm program to get the imports
those of interest....
Import Module 004: DINPUT8.dll
Addr:0000326C hint(0000) Name: DirectInput8Create
Import Module 006: OLEAUT32.dll
Addr:80000006 hint(0006) Name: OLEAUT32:NoName0000
Addr:80000002 hint(0002) Name: OLEAUT32:NoName0001
Import Module 008: ole32.dll
Addr:000032E0 hint(0010) Name: CoCreateInstance
Addr:000032F4 hint(003E) Name: CoInitialize
Addr:000032CC hint(0063) Name: CoSetProxyBlanket
so, it would seem the dinput8 inc/lib has all we need
what we want is the GUID(s) for the COM interface - that should be a matter of google'ing
CoSetProxyBlanket is a new one on me - i may have to look that one up - lol
Quote from: hamper on December 03, 2013, 05:37:00 AMI studied the utility "dumpbin" and tried to use that to try and find out which functions were in which libraries, but all I ever got out from it was an empty text file (0 bytes in length).
Example:
\masm32\bin\dumpbin /exports dx8vb.dll >1.txtResult attached, but it's not the solution :(
In the link that jj2007 provided a few posts back, the author mentions two possible approaches, and the second approach uses the "CoCreateInstance"... methodology. I'd found the DirectInputCreateA function, but there's loads of other functions used by the author which I couldn't find anywhere (that's not to say they're not there - just that I simply could not find them).
But even if the function CoCreateInstance, et al, have now been found lurking around ole32.dll (thanks dave), it still leaves all the other functions needed, such as CreateDevice, EnumDevices, SetDataFormat, SetCooperativeLevel, and so on, and I've no idea where any of them are. The author mentions one function is in the regular WindowsAPI, but there's no mention of it in the WindowsAPI help file! All very, very confusing to me.
those are "sub-functions" (i forget what they're called - lol) of the COM interface
because a joystick is not the simplest example of COM,
perhaps a simple COM example is in order - to get you warmed up
in the mean time - i am doing some reading on the DirectInput COM interface....
check your PM's
Did not read the whole thread yet, but maybe these functions are the COM-based virtual-table functions of object that was created by DirectInput8Create?
Ah, did not refreshed the page, Dave has already posted this thought.
Will do.
In the meantime I've been running Borland's IMPDEF.EXE program on the following - dinput.dll, dinput8.dll, dx7vb.dll, dx8vb.dll, hid.dll, mmcbase.dll, mmfutil.dll, mmsystem.dll, mmutilse.dll and winmm.dll. It doesn't report any of the elusive functions in any of them. They're also not mentioned in the WindowsAPI. The search continues I guess, but something must be doing the job, because my joystick works automatically under the Windows (e.g. the calibration program from the Start menu).
it's COM stuff
once you create a COM instance, the "virtual-table functions" are available (thanks Alex :biggrin: )
i really like qWord's "METHOD" macro for COM interfaces
i was trying to find a simple example for you to get your feet wet
DEFINE_GUID(GUID_Joystick ,0x6F1D2B70,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
extern HRESULT WINAPI DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter);
DECLARE_INTERFACE_(IDirectInputDevice8A, IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
/*** IDirectInputDevice8A methods ***/
STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE;
STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
STDMETHOD(Acquire)(THIS) PURE;
STDMETHOD(Unacquire)(THIS) PURE;
STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE;
STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE;
STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE;
STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE;
STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE;
STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE;
STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE;
STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE;
STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
STDMETHOD(Poll)(THIS) PURE;
STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE;
STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE;
STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATA,LPCSTR,DWORD) PURE;
STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATA,LPCSTR,DWORD) PURE;
STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERA) PURE;
};
Probably the way to get the interface of Joystic is something like (pseudocode):
LOCAL obj:DWORD
LOCAL wtf:DWORD
invoke DirectInput8Create,GetModuleHandle(0),0800h,offset GUID_Joystick,addr obj, addr wtf
If the call was successfull, then in the obj is the address of the object of DirectInput.
The virtual table is above in the post... i.e., to call the function GetCapabilities, for an instance, you need this:
mov eax,obj
push eax
mov eax,[eax]
call dword ptr [eax+3*4]
Thanks for the PM dedndave, I tried to reply but I'm not sure it worked. Will have to download and read tomorrow now - I've already exceeded my internet usage limit for today, so will have to log off very shortly.
i am doing some reading, Alex
once you get the COM interface going, the next thing to do is to enumerate input devices
for hamper....
here is the MSDN page (with links) for COM interface
if you try to read it like a book, you will be watching porn in about 30 minutes - lol
instead - use it as a reference to look up specific things you have questions about
http://msdn.microsoft.com/en-us/library/windows/desktop/ms680573%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms680573%28v=vs.85%29.aspx)
above, Alex has posted some example COM code
i was going to find one that was really simple - lol
Quote from: hamper on December 03, 2013, 06:08:01 AMAll very, very confusing to me.
Yep, that's COM. There is a good tutorial by Michael Dunn, Introduction to COM - What It Is and How to Use It (http://www.codeproject.com/Articles/633/Introduction-to-COM-What-It-Is-and-How-to-Use-It). COM is very powerful but the learning curve is kind of steep.
Here is a very simple demo, it opens Masm32 in Internet Explorer:
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
.code ; This COM demo opens a page in MS Internet Explorer
CLSID_IExplorer GuidFromString("0002DF01-0000-0000-C000-000000000046")
IID_IWebBrowser2 GuidFromString(D30C1661-CDAF-11D0-8A3E-00C04FC9E26E)
MyBrowser proc uses edi url
LOCAL vEmpty:VARIANT, hWin, WebInterface
ClearLocals
lea edi, WebInterface
pInterface equ dword ptr [edi]
invoke CoCreateInstance, addr CLSID_IExplorer, NULL, CLSCTX_LOCAL_SERVER, addr IID_IWebBrowser2, edi
.if eax==S_OK ; OK, now configure the browser:
CoInvoke pInterface, IWebBrowserVtbl.put_Visible, VARIANT_TRUE
lea edx, vEmpty ; it needs pointers to four empty VARIANTS
CoInvoke pInterface, IWebBrowserVtbl.Navigate, Ole$(url), edx, edx, edx, edx ; COM needs a BSTR, so the ANSI URL needs to be converted
.endif
ret
MyBrowser endp
Init
invoke OleInitialize, NULL
.if eax==S_OK
invoke MyBrowser, Chr$("http://masm32.com/board/index.php?action=unread")
.endif
invoke OleUninitialize
Exit
end start
to understand that code, he also has to learn MasmBasic
probably a bit much to unload on him all at once - COM is bad enough :P
personally, i learned from examples by Donkey (Edgar) and qWord
Edgar's code is in GoAsm, of course - but it still helped a lot
oh boy - i see the MultiMedia library also supports joystick input
much simpler to learn :P
still, i am interested in both methods
a simple MultiMedia console test program to see if any joysticks are connected
results on my machine, XP SP3
Joystick #0: Not Connected
Joystick #1: Not 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
Bravo , Dave :t
MM Input API is much better than DirectX to start with .
Some info on Using Joysticks (http://msdn.microsoft.com/en-us/library/windows/desktop/dd757657(v=vs.85).aspx)
i can't imagine 16 people crowded in front of one computer to play a game - lol
sort of gaming station :biggrin:
Quote from: dedndave on December 03, 2013, 01:27:55 PM
i can't imagine 16 people crowded in front of one computer to play a game - lol
I did a job for a flight sim nut, he had 4 different controllers plugged in - pedals, throttles, stick and another one (don't know what for) and used the keyboard.
Four monitor setup - left, front-left, front-right and right. Wanted a couple behind but the video cards max out at 4.
The best thing?
He has a friend bring his 4 controllers and fly pilot-copilot.
Hi,
Well, well, well. Dug out my joystick. Ran your program, nothing
found. Went to Control Panel, Gaming Options, and ran the install
option. Then your program paused a while, and found it. Kudos I
suppose. Anyway, here is the output from the console.
■ Pentium II class CPU detected.
■ XMS version 2.00 detected.
■ DPMI version 0.90 detected.
Searching ZIP: NOJOY1.ZIP
Inflating: NoJoy.exe
Inflating: NoJoy.asm
F:\TEMP>nojoy
Joystick #0: Not Connected
Joystick #1: Not 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
Press any key to continue ...
F:\TEMP>nojoy
Joystick #0: Connected
Joystick #1: Not 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
Press any key to continue ...
Hm, wonder how long it's been sitting around? It was never
attached to this computer to my knowledge.
HTH,
Steve N.
Edit:
P.S.
I just noticed an On/Off switch on the joystick. And it works.
When in the off position, the joystick is not seen.
Cheers,
SRN
thanks Steve - now that i know it works, i'll try a GUI app that uses it
i used to play with games a little - mostly in the 80's
flight simulators were fun for a while
and - i am into flying - "aced" ground school and have some hours behind the stick, even
but - sims get old fast - lol
i played Dig-Dug (Digger) and Asteroids more
and i was better with the keyboard "yoke" than the joystick
back in the day, a friend of mine had an atari
he and i used to get together and play Archon II
joystick was the only way to fly for that game
I like the odd session on a flight sim, but there's nothing like the real thing ... I'm a member of a gliding club, and fly gliders now and then. You should give it a whiz sometime. It's the most fun you can have with your clothes on. And not as expensive!
But, back to the point, it looks like I'm going to have to grapple with the beast if I'm going to get my joystick working in my own program, so I may as well get started.
Thanks for all the information, tips and links everyone. Looks like I'm going to be busy for a month or so :icon_confused:
Right, let's get started "Chapter 1 - A simple introduction to using COM in assembly language programs".
ummm - did you try the posted test program ?
Wow! Yes, it picks it up as joystick 0.
So presumably (I haven't tried it yet), I could simply read the axes positions using ji.wXpos, ji.wYpos and ji.wZpos?
And also, presumably, I've been stumbling around looking into all the COM stuff when the answer was already there in the winmm functions? Is that right?
I can't believe it's that simple. Seemed like a horrendous chore using the COM approach.
Know any link that documents the various joystick functions in winmm?
EDIT: Silly me, it's all documented on Microsoft's site.
it is documented
and - simpler than COM, probably
however, Multi-Media isn't always simple, either - lol
nothing ever is
if your program can work by reading the position asynchronously, then that may be the easy way
at the moment, i am reading through the documentation
i was trying to write a message-driven app
problem is - no josytick to test with
it looks a little complicated, because of the capture function
it does not work the same as mouse capture
tomorrow, i may have a little program for you and Steve to test for me
i want to see how a window is notified of capture change
i may have to dig out my sidewinder and see if i can hook it up
I'll work on it as well.
Have to log off for a bit now.
Later
Haven't got around to writing myself a little test program yet, in order to check the various reported axes values, POV hat positions and general button use etc. -- still working my way through putting notes together on all the various winmm.lib functions and all the different structures they use etc.
But I've noticed a few things that may be issues with the structures (in windows.inc)...
JOYCAPSA structure
MASM32 has the elements wxmin...wperiodmax inclusive (9 elements) as word types, but Microsoft has them as UINT (dword) types.
JOYINFO structure
MASM32 has all the elements as word types, but Microsoft has them all as dword types.
JOYINFOEX structure
The dwpov element can take a value of -1 (indicating centred), so really it shoud be an sdword type, not a dword (but no big deal).
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
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?
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.....
ok - well, i can't set capture without one connected
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.
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 (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
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
;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
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.
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?
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
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 ::)
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
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.
Acording to dinput8.inc from Dxsdk90 (http://vertexland.narod.ru/data/index.htm):
;***************************************************************************
;*
;* 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
In my example some posts above I used this code to call EnumDevices:
mov eax,[esi]
push 0
push esi
push offset enumdevs
push 0
push esi
call dword ptr [eax+4*4] ; EnumDevices
Here is the displacement is 4 methods - 3 of them are the IUnknown functions, and one is the IDirectInput8 CreateDevice method.
thanks Alex - that was it :t
C:\Documents and Settings\Dave\Desktop => di8
Mouse
Keyboard
Microsoft Wireless Desktop Receiver 3.1
Microsoft Wireless Desktop Receiver 3.1
VJoy Virtual Joystick
VJoy Virtual Joystick
VJoy Virtual Joystick
Press any key to continue ...
C:\Documents and Settings\Dave\Desktop =>
:t
Dave, what if change DIEDFL_ALLDEVICES flag to DIEDFL_ATTACHEDONLY - maybe this will solve the duplicates problem in the enumeration?
right - that should work
my first goal was to get it working like yours :biggrin:
in the EnumDevices documentation, it mentions that duplicate instances are enumerated without setting that flag
http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.idirectinput8.idirectinput8.enumdevices%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.idirectinput8.idirectinput8.enumdevices%28v=vs.85%29.aspx)
by the way....
i have put all the EnumDevices flag constants in the include file
the include file is still a "work in progress"
i will continue to add constants and structures, as required
the next step is to put it into a GUI app and make the joystick "event driven"
My neighbor lent me joystick (http://www.thrustmaster.com/products/tflight-stick-x) for programming experiments and I dared to convert DXSDK JOYSTICK example to MASM (now I understand - I should not do that :biggrin:)
I'm having tons of troubles ... and fun with it :biggrin:
Now , when it at least compiles and shows the dialog , I'm going to make the rest of it working.
At a moment I'm stuck with EnumObjectsCallback routine:
//-----------------------------------------------------------------------------
// Name: EnumObjectsCallback()
// Desc: Callback function for enumerating objects (axes, buttons, POVs) on a
// joystick. This function enables user interface elements for objects
// that are found to exist, and scales axes min/max values.
//-----------------------------------------------------------------------------
BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
VOID* pContext )
{
HWND hDlg = ( HWND )pContext;
static int nSliderCount = 0; // Number of returned slider controls
static int nPOVCount = 0; // Number of returned POV controls
// For axes that are returned, set the DIPROP_RANGE property for the
// enumerated axis in order to scale min/max values.
if( pdidoi->dwType & DIDFT_AXIS )
{
DIPROPRANGE diprg;
diprg.diph.dwSize = sizeof( DIPROPRANGE );
diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER );
diprg.diph.dwHow = DIPH_BYID;
diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis
diprg.lMin = -1000;
diprg.lMax = +1000;
// Set the range for the axis
if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
return DIENUM_STOP;
}
// Set the UI to reflect what objects the joystick supports
if( pdidoi->guidType == GUID_XAxis )
{
EnableWindow( GetDlgItem( hDlg, IDC_X_AXIS ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_X_AXIS_TEXT ), TRUE );
}
if( pdidoi->guidType == GUID_YAxis )
{
EnableWindow( GetDlgItem( hDlg, IDC_Y_AXIS ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_Y_AXIS_TEXT ), TRUE );
}
if( pdidoi->guidType == GUID_ZAxis )
{
EnableWindow( GetDlgItem( hDlg, IDC_Z_AXIS ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_Z_AXIS_TEXT ), TRUE );
}
if( pdidoi->guidType == GUID_RxAxis )
{
EnableWindow( GetDlgItem( hDlg, IDC_X_ROT ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_X_ROT_TEXT ), TRUE );
}
if( pdidoi->guidType == GUID_RyAxis )
{
EnableWindow( GetDlgItem( hDlg, IDC_Y_ROT ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_Y_ROT_TEXT ), TRUE );
}
if( pdidoi->guidType == GUID_RzAxis )
{
EnableWindow( GetDlgItem( hDlg, IDC_Z_ROT ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_Z_ROT_TEXT ), TRUE );
}
if( pdidoi->guidType == GUID_Slider )
{
switch( nSliderCount++ )
{
case 0 :
EnableWindow( GetDlgItem( hDlg, IDC_SLIDER0 ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_SLIDER0_TEXT ), TRUE );
break;
case 1 :
EnableWindow( GetDlgItem( hDlg, IDC_SLIDER1 ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_SLIDER1_TEXT ), TRUE );
break;
}
}
if( pdidoi->guidType == GUID_POV )
{
switch( nPOVCount++ )
{
case 0 :
EnableWindow( GetDlgItem( hDlg, IDC_POV0 ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_POV0_TEXT ), TRUE );
break;
case 1 :
EnableWindow( GetDlgItem( hDlg, IDC_POV1 ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_POV1_TEXT ), TRUE );
break;
case 2 :
EnableWindow( GetDlgItem( hDlg, IDC_POV2 ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_POV2_TEXT ), TRUE );
break;
case 3 :
EnableWindow( GetDlgItem( hDlg, IDC_POV3 ), TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_POV3_TEXT ), TRUE );
break;
}
}
return DIENUM_CONTINUE;
}
I was trying to implement it something like this :
.if rv(IsEqualGUID, ecx, addr ID_XAxis )
fn EnableWindow, rv(GetDlgItem, hDlg, IDC_X_AXIS ), TRUE
fn EnableWindow, rv(GetDlgItem, hDlg, IDC_X_AXIS_TEXT ), TRUE
.elseif rv(IsEqualGUID, ecx ,addr ID_YAxis)
fn EnableWindow, rv(GetDlgItem, hDlg, IDC_Y_AXIS ), TRUE
fn EnableWindow, rv(GetDlgItem, hDlg, IDC_Y_AXIS_TEXT ), TRUE
.elseif rv(IsEqualGUID, ecx , OFFSET ID_ZAxis)
fn EnableWindow, rv(GetDlgItem, hDlg, IDC_Z_AXIS ), TRUE
fn EnableWindow, rv(GetDlgItem, hDlg, IDC_Z_AXIS_TEXT ), TRUE
.elseif rv(IsEqualGUID, ecx ,addr GUID_RxAxis)
... ... ...
where ecx = DIDEVICEOBJECTINSTANCE.guidType , but no luck
Moreover, .ELSEIF cannot have nested .IF block and I didn't succeed with Switch-Case block either .
Is THIS or SIMILAR construction possible (with MASM) ? :
Switch [eax]. DIDEVICEOBJECTINSTANCE.guidType
Case GUID_XAxis
...
Case GUID_YAxis
...
or should the block look like this:
.if rv(IsEqualGUID, ecx, addr ID_XAxis )
fn EnableWindow, rv(GetDlgItem, hDlg, IDC_X_AXIS ), TRUE
fn EnableWindow, rv(GetDlgItem, hDlg, IDC_X_AXIS_TEXT ), TRUE
.endif
.if rv(IsEqualGUID, ecx ,addr ID_YAxis)
fn EnableWindow, rv(GetDlgItem, hDlg, IDC_Y_AXIS ), TRUE
fn EnableWindow, rv(GetDlgItem, hDlg, IDC_Y_AXIS_TEXT ), TRUE
.endif
Any ideas?
EnumObjectsCallback is done
no help needed
thanks
i started making an INC file for direct joy - haven't finished yet
the original goal was to write code that would be event-triggered, rather than polling
after i did some digging, it seems the best method is to use polling, anyways - lol
so - i put it on the back burner
http://www.asmcommunity.net/forums/topic/?id=11310 (http://www.asmcommunity.net/forums/topic/?id=11310)
(gets interesting about half-way down the page)
i read that whole page - only to get to the last post by Scronty to see that polling was better - lol
I use MASM DXSDK package (http://vertexland.narod.ru/data/index.htm) . Thanks to its author(s) for their work: all includes / libs, good set of examples and CHM HELP !!! (in Russian )
Also I want to say THANK YOU to Siekmansky for his DX examples / includes. I was studying his examples before my joining this forum.
Scronty is another name to be mentioned here . He made really great work for DX8.1 - 13 examples and 6 tutorials (from DX SDK) - the best guidance to DirectX for the beginner.
I must admit that MS DXSDK JOYSTICK example is an advanced one . It performs search for XINPUT devices (WMI is used for that goal) and filters them out if co-responding command line option is specified.
Another difficulty is that it widely uses SAFE STRING function StringCchPrintf ( currently I replaced it with wsprintf )
This example requires DINPUTD include from MS DXSDK.
Here's MainDlgProc as it appears in original example :
; -----------------------------------------------------------------------------
; Name: MainDialogProc
; Desc: Handles dialog messages
; -----------------------------------------------------------------------------
MainDlgProc proc hDlg:DWORD, msg:DWORD, wParam:DWORD, lParam:DWORD
; UNREFERENCED_PARAMETER lParam
.if msg == WM_INITDIALOG
INVOKE InitDirectInput,hDlg
.if eax !=0
fn MessageBox,0, chr$("Error Initializing DirectInput"), "DirectInput Sample" , MB_ICONERROR or MB_OK
INVOKE EndDialog, hDlg, 0
.endif
; Set a timer to go off 30 times a second. At every timer message
; the input device will be read
INVOKE SetTimer,hDlg, 0, 1000 / 30, NULL
xor eax,eax
ret
.elseif msg ==WM_ACTIVATE
.if wParam!=WA_INACTIVE && g_pJoystick
; Make sure the device is acquired, if we are gaining focus.
dindev8 Acquire, g_pJoystick
.endif
xor eax,eax
ret
.elseif msg == WM_TIMER
; Update the input device every timer message
INVOKE UpdateInputState, hDlg
.if eax !=0
INVOKE KillTimer, hDlg, 0
fn MessageBox,0,chr$( "Error Reading Input State.",0Dh,0Ah,"The sample will now exit." ), "DirectInput Sample", MB_ICONERROR or MB_OK
INVOKE EndDialog, hDlg, TRUE
.endif
xor eax,eax
ret
.elseif msg == WM_COMMAND
LOWORD wParam
.if eax== IDCANCEL
INVOKE EndDialog,hDlg,0
xor eax,eax
ret
.endif
.elseif msg == WM_DESTROY
; Cleanup everything
INVOKE KillTimer, hDlg, 0
INVOKE FreeDirectInput
xor eax,eax
ret
.endif
mov eax,0 ;
ret ; Message not handled
MainDlgProc endp
Now errors in UpdateInputState routine are causing the "Error Reading Input State.The sample will now exit." MessageBox :
Quote
Poll, g_pJoystick -> 0x8007000C : Failed to poll device(?)
GetDeviceState -> 0x8007001E : DIERR_INPUTLOST (ERROR_READ_FAULT, "May be used to indicate that the device is not sending the correct amount of data.")
[EDIT] : above mentioned error is fixed . The data for XAxis is updated but pressing any button gives an WerFault dialog . Gone debugging ...
[EDIT]:
BINGO!!! Done. All's working
To be polished now ...
[EDIT]: There's one minor problem though . It throws the "Error Reading Input State.The sample will now exit." MessageBox after minimizing or switching to another window. Also there're some slight differences in appearance(see picture below):
[EDIT]: FIXED.
i tried to download the direct x 8 kit and it sends me to a page with 9 on it :(
Quote from: dedndave on January 29, 2014, 05:11:18 AM
i tried to download the direct x 8 kit and it sends me to a page with 9 on it :(
I've got the same result . I use 9. Maybe search for Scronty's dx 8.1 pack if you have DirectX 9 incompatible video adapter ?
Oh, I didn't notice the subtitle of DirectX SDK 8.1 (http://vertexland.narod.ru/data/directx_masm.htm) : for FASM
vertograd,
Nice to know you studied the Direct3d9 includes. :biggrin:
It was quite a task to convert the Direct3d9 includes to assembly manually.
I was still planning to translate DirectInput includes to assembly, never happened.
I just finished a set of includes for DirectX 10 along with DirectInput. They are over in the GoAsm forum and are in GoAsm format, which isn't that much different, and there must be a tool/script that could convert them to MASM. Haven't tested them out yet, but they should be a great start for you.
Quote from: dedndave on January 28, 2014, 03:32:20 PM
i started making an INC file for direct joy - haven't finished yet
the original goal was to write code that would be event-triggered, rather than polling
...
Here's a quick and dirty example of event triggered input handling:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\projects\DINPUT\include\d3d9.inc ; replace with your path
include \masm32\projects\DINPUT\include\dinput8.inc
include \masm32\projects\DINPUT\include\dinputd.inc
includelib \masm32\projects\DINPUT\lib\dinput8.lib
includelib \masm32\projects\DINPUT\lib\dxguid.lib
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
; PROTOTYPES
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
EnumJoysticksCallback PROTO :DWORD,:DWORD
InitDirectInput PROTO
FreeDirectInput PROTO
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
; STRUCTURES
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
DI_ENUM_CONTEXT STRUCT
pPreferredJoyCfg dd ? ; DIJOYCONFIG<>
bPreferredJoyCfgValid BOOLEAN ?
DI_ENUM_CONTEXT ENDS
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
.const
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
IID_IDirectInput GUID IID_IDirectInput8A
waitObj db "MyWaitObject",0
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
.data
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
g_pDI LPDIRECTINPUT8 NULL
g_pJoystick LPDIRECTINPUTDEVICE8 NULL
PreferredJoyCfg DIJOYCONFIG <SIZEOF DIJOYCONFIG,,,,,, >
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
.data?
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
enumContext DI_ENUM_CONTEXT <>
hWaitObj dd ?
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
.code
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
start:
invoke InitDirectInput
.if eax !=0
fn MessageBox,0, chr$("Error Initializing DirectInput"), "DirectInput Sample" , MB_ICONERROR or MB_OK
jmp ext
.endif
invoke CreateEvent, NULL , FALSE, FALSE , addr waitObj
.if eax==0
fn MessageBox,0, LastError$(), "DirectInput Sample:Failed to CreateEvent" , MB_ICONERROR or MB_OK
jmp ext
.endif
mov hWaitObj, eax
dindev8 SetEventNotification, g_pJoystick, hWaitObj
.if eax<0
fn MessageBox,0, LastError$(), "DirectInput Sample:Failed to SetEventNotification" , MB_ICONERROR or MB_OK
jmp ext
.endif
dindev8 Acquire, g_pJoystick
joy:
invoke WaitForSingleObject, hWaitObj, 3000
.if eax== WAIT_OBJECT_0
fn MessageBox,0,chr$("WAIT_OBJECT_0"),"Received Event Notification : ",MB_RETRYCANCEL or MB_ICONINFORMATION
.if eax == 2
jmp ext
.elseif eax == 4
jmp joy
.endif
.elseif eax== WAIT_TIMEOUT
fn MessageBox,0,chr$("WAIT_TIMEOUT"),"Received Event Notification :",MB_ICONEXCLAMATION or MB_OK
.else
fn MessageBox,0,hex$(eax),"WaitForSingleObject returned :", MB_OK
.endif
ext:
fn MessageBox,0,chr$("Exiting..."),"Title",MB_OK
dindev8 SetEventNotification, g_pJoystick, NULL
invoke CloseHandle, hWaitObj
invoke FreeDirectInput
invoke ExitProcess,eax
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
; PROCEDURES
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
;------------------------------------------------------------------------
; Name: InitDirectInput()
; Desc: Initialize the DirectInput variables.
;------------------------------------------------------------------------
InitDirectInput PROC
LOCAL pJoyConfig :DWORD
LOCAL hModule :DWORD
; Register with the DirectInput subsystem and get a pointer
; to a IDirectInput interface we can use.
; Create a DInput object
mov hModule, rv(GetModuleHandle,NULL)
fn DirectInput8Create,hModule,DIRECTINPUT_VERSION,&IID_IDirectInput,&g_pDI,NULL
.if eax != S_OK
fn MessageBox,0,LastError$(),"DirectInput8Create",MB_OK
ret
.endif
; Look for a simple joystick we can use for this sample program.
din8 EnumDevices, g_pDI, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, addr enumContext, DIEDFL_ATTACHEDONLY
.if eax != S_OK
fn MessageBox,0,LastError$(),"din8 EnumDevices",MB_OK
ret
.endif
; Make sure we got a joystick
.if g_pJoystick == 0
fn MessageBox,0, chr$( "Joystick not found. The sample will now exit." ), "DirectInput Sample", MB_ICONERROR or MB_OK
mov eax, -1
ret
.endif
; Set the data format to "simple joystick" - a predefined data format
;
; A data format specifies which controls on a device we are interested in,
; and how they should be reported. This tells DInput that we will be
; passing a DIJOYSTATE2 structure to IDirectInputDevice::GetDeviceState().
dindev8 SetDataFormat, g_pJoystick, addr c_dfDIJoystick2
.if eax != S_OK
fn MessageBox,0,LastError$(),"dindev8 SetDataFormat",MB_OK
ret
.endif
xor eax,eax
ret
InitDirectInput ENDP
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
;------------------------------------------------------------------------
; Name: FreeDirectInput()
; Desc: Initialize the DirectInput variables.
;------------------------------------------------------------------------
FreeDirectInput proc
; Unacquire the device one last time just in case
; the app tried to exit while the device is still acquired.
.if g_pJoystick
dindev8 Unacquire, g_pJoystick
.endif
; Release any DirectInput objects.
dindev8 Release, g_pJoystick
din8 Release, g_pDI
FreeDirectInput endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
;------------------------------------------------------------------------
; Name: EnumJoysticksCallback()
; Desc: Called once for each enumerated joystick. If we find one, create a
; device interface on it so we can play with it.
;------------------------------------------------------------------------
EnumJoysticksCallback proc pdidInstance:DWORD, pContext:DWORD
; DI_ENUM_CONTEXT* pEnumContext = ( DI_ENUM_CONTEXT* )pContext;
mov esi, pdidInstance
mov edx, pContext
; Skip anything other than the perferred joystick device as defined by the control panel.
; Instead you could store all the enumerated joysticks and let the user pick.
lea eax, [esi].DIDEVICEINSTANCE.guidInstance
lea ebx, [edx].DI_ENUM_CONTEXT.pPreferredJoyCfg
lea edi, [ebx].DIJOYCONFIG.guidInstance
mov ecx, rv(IsEqualGUID, eax, edi )
.if [edx].DI_ENUM_CONTEXT.bPreferredJoyCfgValid && ecx == FALSE
mov eax, DIENUM_CONTINUE
.endif
; Obtain an interface to the enumerated joystick.
lea eax, [esi].DIDEVICEINSTANCE.guidInstance
din8 CreateDevice, g_pDI, eax, addr g_pJoystick, NULL
; If it failed, then we can't use this joystick. (Maybe the user unplugged
; it while we were in the middle of enumerating it.)
.if eax != S_OK
mov eax, DIENUM_CONTINUE
ret
.endif
; Stop enumeration. Note: we're just taking the first joystick we get. You
; could store all the enumerated joysticks and let the user pick.
mov eax, DIENUM_STOP
ret
EnumJoysticksCallback endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
END start
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Wednesday, January 29, 2014 4:45:31 AM
You will need MASM DX SDK kit (from link above) to build it.
These structures (defined in DINPUTD.H) are required:
;/* struct for storing x,y, z, and rudder values */
JOYPOS STRUCT
dwX DWORD ?
dwY DWORD ?
dwZ DWORD ?
dwR DWORD ?
dwU DWORD ?
dwV DWORD ?
JOYPOS ENDS
;/* struct for storing ranges */
JOYRANGE STRUCT
jpMin JOYPOS<>
jpMax JOYPOS<>
jpCenter JOYPOS<>
JOYRANGE ENDS
; /*
; * dwTimeout - value at which to timeout joystick polling
; * jrvRanges - range of values app wants returned for axes
; * jpDeadZone - area around center to be considered
; * as "dead". specified as a percentage
; * (0-100). Only X & Y handled by system driver
;
JOYREGUSERVALUES STRUCT
dwTimeOut DWORD ?
jrvRanges JOYRANGE<>
jpDeadZone JOYPOS<>
JOYREGUSERVALUES ENDS
JOYREGHWSETTINGS STRUCT
dwFlags DWORD ?
dwNumButtons DWORD ?
JOYREGHWSETTINGS ENDS
; /* range of values returned by the hardware (filled in by calibration) */
; /*
; * jrvHardware - values returned by hardware
; * dwPOVValues - POV values returned by hardware
; * dwCalFlags - what has been calibrated
;
JOYREGHWVALUES STRUCT
jrvHardware JOYRANGE<>
dwPOVValues DWORD ? ; dwPOVValues[JOY_POV_NUMDIRS];
dwCalFlags DWORD ?
JOYREGHWVALUES ENDS
; /* hardware configuration */
; /*
; * hws - hardware settings
; * dwUsageSettings - usage settings
; * hwv - values returned by hardware
; * dwType - type of joystick
; * dwReserved - reserved for OEM drivers
; */
JOYREGHWCONFIG STRUCT
hws JOYREGHWSETTINGS<>
dwUsageSettings DWORD ?
hwv JOYREGHWVALUES<>
dwType DWORD ?
dwReserved DWORD ?
JOYREGHWCONFIG ENDS
DIJOYCONFIG STRUCT
dwSize DWORD ?
guidInstance GUID<>
hwc JOYREGHWCONFIG<>
dwGain DWORD ?
wszType DWORD ?
wszCallout DWORD ?
guidGameport GUID<>
DIJOYCONFIG ENDS
Siekmansky,
Mostly I studied your examples .Especially I liked "d3d9_alpha" one :t
thanks vertograd :t
You're welcome, Dave
One mistake in EnumJoysticksCallback proc:
Quote
.if [edx].DI_ENUM_CONTEXT.bPreferredJoyCfgValid && ecx == FALSE
mov eax, DIENUM_CONTINUE
ret
.endif
If I remember correctly I can use joystick without using DXINPUT, there is a joystick function on one of the winAPI, it JOYSTICKEX structure or something, its been long time ago. I can use my Playstation 2 USB joystick with it.
the multi-media library has those functions (mmJoy...)
Oh the function name is joyGetPos, use the structure which had EX name on it on the newer version of Windows, it will work on lots of joystick type.
Ok, now we know how to handle joystick input with multimedia library and DIRECT INPUT .
There's another way of doing it - using RAW INPUT API (http://www.codeproject.com/Articles/185522/Using-the-Raw-Input-API-to-Process-Joystick-Input).
Or directly via HID library.
that looks much cleaner that DirectInput :P