News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Getting my joystick working under Direct Input

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

Previous topic - Next topic

Antariy

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.

dedndave

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 =>


Antariy

Dave, what if change DIEDFL_ALLDEVICES flag to DIEDFL_ATTACHEDONLY - maybe this will solve the duplicates problem in the enumeration?

dedndave

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

by the way....
i have put all the EnumDevices flag constants in the include file

dedndave

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"

GoneFishing

My neighbor lent me joystick 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?

GoneFishing

EnumObjectsCallback is done
no help needed
thanks

dedndave

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

(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

GoneFishing

#69
I use MASM DXSDK package . 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.

dedndave

i tried to download the direct x 8 kit and it sends me to a page with 9 on it   :(

GoneFishing

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 : for FASM 

Siekmanski

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.
Creative coders use backward thinking techniques as a strategy.

satpro

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.

GoneFishing

#74
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