News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

RawInputs organization

Started by zemtex, January 30, 2011, 12:00:35 AM

Previous topic - Next topic

zemtex

I've uset GetRawInputData and it should be catched in the WM_INPUT message.

But now i'm implementing GetRawInputBuffer to reduce amount of WM_INPUT messages retrieved. Mice equipment today is very high resolution and can easily flood my program with WM_INPUT messages, so I figure using a buffered version of RawInput is the best solution.

My question is, where should I process it, microsoft sample use GetRawInputBuffer using a private windows message. Can I catch it in the peekmessage loop and just dump the WM_INPUT message from the windows procedure handler?

(Btw, there was not a single hit on "RawInput" or "GetRawInputBuffer" on this site, about time someone started such a thread :8))
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

qWord

Well, there is no need for buffered input, because you can handle the WM_INPUT message. The buffered method needs a timer or some other event, that let you read the input.
Quote from: zemtex on January 30, 2011, 12:00:35 AMMice equipment today is very high resolution and can easily flood my program with WM_INPUT messages, so I figure using a buffered version of RawInput is the best solution.
why? - for both methods you must process the same number of event at a time.

qWord
FPU in a trice: SmplMath
It's that simple!

zemtex

If you move your mouse 500 pixels across with a 5700 dpi mouse and press 3-4 keys at the same time, it will generate events at the same pace, thats true, but the WM_INPUT version will rerun and fill in a message structure for each event over and over, while the buffered variant will only need to process it once without having the message resent.

If you use the buffered variant you will have code that runs and loops undisturbed, if you use the other variant you will run code, parse a long msg structure again and this adds overhead.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

qWord

maybe your underrated the speed of today's computers  :bg
FPU in a trice: SmplMath
It's that simple!

zemtex

There is no doubt that a modern computer can handle both ways, I even doubt you would notice any difference. Thats not the case, the case is when you combine the methods with demanding game-code, what will be the result then.

To tell the truth, I was tempted to use the easiest variant. But I don't go for cheap solutions just because the other is harder to implement. Thats a bad habit.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

zemtex

Btw, do you know of a good way to implement the buffered variant, are you absolutely sure you have to use a timer, can you not parse the structures in the message loop?
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

jj2007

You checked this, I suppose?

QuoteGetRawInputBuffer Function

Performs a buffered read of the raw input data.
Syntax
Copy

UINT WINAPI GetRawInputBuffer(
  __out_opt  PRAWINPUT pData,
  __inout    PUINT pcbSize,
  __in       UINT cbSizeHeader
);


Parameters

pData [out, optional]

    Type: PRAWINPUT

    A pointer to a buffer of RAWINPUT structures that contain the raw input data. If NULL, the minimum required buffer, in bytes, is returned in *pcbSize.

zemtex

Been readin all the ms docs yesterday, almost any sublink from that page is purple as i've clicked almost all of them and gone deeper into the topic. I spent about 6 hours reading on the subject.

I've already implemented the non-buffered variant and to tell the truth, its not that bad, the amount of messages it generates is really not as bad as I thought and it shouldnt produce a problem on performance.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

qWord

hi,
I've also played a bit with it and end up in an bug in WOW64. However, after some fix it works: look for the line
Quote.if [edi].RAWINPUT.data.keyboard.VKey+8 == VK_J
the displacement of 8 is normally not needed - but win7-x64 seems to use wrong struct definition (WIN64) for the RAWINPUTHEADER-struct.(?)

include masm32rt.inc

.686p
.mmx
.xmm

RAWINPUTDEVICE struct
    usUsagePage USHORT  ?
    usUsage     USHORT  ?
    dwFlags     DWORD   ?
    hwndTarget  HWND    ?
RAWINPUTDEVICE ends

RAWINPUTHEADER  struct
    dwType  DWORD   ?
    dwSize  DWORD   ?
    hDevice HANDLE  ?
    wParam  WPARAM  ?
RAWINPUTHEADER  ends
PRAWINPUTHEADER typedef ptr RAWINPUTHEADER

RAWMOUSE struct
    usFlags WORD    ?
    union
        ulButtons   DWORD   ?
        struct
            usButtonFlags   WORD    ?
            usButtonData    WORD    ?
        ends
    ends
    ulRawButtons        DWORD   ?
    lLastX              SDWORD  ?
    lLastY              SDWORD  ?
    ulExtraInformation  DWORD   ?
RAWMOUSE ends
PRAWMOUSE typedef ptr RAWMOUSE

RAWKEYBOARD struct
    MakeCode            WORD    ?
    Flags               WORD    ?
    Reserved            WORD    ?
    VKey                WORD    ?
    Message             DWORD   ?
    ExtraInformation    DWORD   ?
RAWKEYBOARD ends
PRAWKEYBOARD typedef ptr RAWKEYBOARD

RAWHID struct
    dwSizeHid   DWORD ?
    dwCount     DWORD ?
    bRawData    BYTE 1 dup (?)
RAWHID ends
PRAWHID typedef ptr RAWHID

RAWINPUT struct
    header  RAWINPUTHEADER  <>
    union data
        mouse       RAWMOUSE    <>
        keyboard    RAWKEYBOARD <>
        hid         RAWHID      <>
    ends
RAWINPUT ends
PRAWINPUT typedef ptr RAWINPUT

RawInputThread proto hWnd:HWND

.data?
    hInstance                   HINSTANCE   ?
    dwThreadID                  DWORD       ?
    hCloseevent                 HANDLE      ?
    hwnd                        HWND        ?
.code

WndProc proto hWnd:HWND,uMgs:UINT,wParam:WPARAM,lParam:LPARAM

main proc
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG

    mov hInstance,rv(GetModuleHandle,0)
    mov wc.hInstance,eax
    mov wc.cbSize,SIZEOF wc
    mov wc.style,CS_HREDRAW or CS_VREDRAW or CS_SAVEBITS
    mov wc.lpfnWndProc,OFFSET WndProc
    mov wc.cbClsExtra,0
    mov wc.cbWndExtra,0
    mov wc.hIcon,rv(LoadIcon,0,IDI_APPLICATION)
    mov wc.hIconSm,eax
    mov wc.hCursor,rv(LoadCursor,0,IDC_ARROW)
    mov wc.lpszMenuName,0
    mov wc.hbrBackground,rv(GetStockObject,WHITE_BRUSH);
    mov wc.lpszClassName,chr$("Win32Wnd")
    invoke RegisterClassEx,ADDR wc
    mov ebx,ASM(mov edi,rv(GetSystemMetrics,SM_CXSCREEN))
    mov esi,rv(GetSystemMetrics,SM_CYSCREEN)
    shr ebx,1
    shr eax,1
    shr edi,2
    shr esi,2
    mov esi,rv(CreateWindowEx,0,wc.lpszClassName,"Win32Wnd",WS_VISIBLE or WS_SYSMENU or WS_MAXIMIZEBOX or WS_MINIMIZEBOX or WS_SIZEBOX,edi,esi,ebx,eax,0,0,hInstance,0)
    mov hwnd,eax
    invoke UpdateWindow,esi
   
    .while 1
        invoke GetMessage,ADDR msg,0,0,0
        .break .if !eax || eax == -1
        invoke TranslateMessage,ADDR msg
        invoke DispatchMessage,ADDR msg     
    .endw

    xor eax,eax
    ret
   
main endp

WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

    .if uMsg == WM_CLOSE
        invoke SetEvent,hCloseevent
        invoke PostQuitMessage,0
    .elseif uMsg == WM_CREATE       
        mov hCloseevent,rv(CreateEvent,0,1,0,0)     
        invoke CreateThread,0,0,OFFSET RawInputThread,hCloseevent,0,ADDR dwThreadID
    .else
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .endif
   
    xor eax,eax
    ret
   
WndProc endp



RawInputThread proc hCloseEvent:HANDLE
LOCAL rid:RAWINPUTDEVICE
LOCAL hWndDummy:HWND
LOCAL cbSize:DWORD
LOCAL msg:MSG

    mov hWndDummy,rv(CreateWindowEx,0,"button",0,0,0,0,1,1,0,0,hInstance,0)

    mov rid.usUsagePage,1
    mov rid.usUsage,6
    mov rid.dwFlags,0
    m2m rid.hwndTarget,hWndDummy
    invoke RegisterRawInputDevices,ADDR rid,1,SIZEOF RAWINPUTDEVICE

    .while 1
        invoke MsgWaitForMultipleObjects,1,ADDR hCloseEvent,0,INFINITE,QS_RAWINPUT
        .if eax == WAIT_OBJECT_0+1
            .break .if rv(GetRawInputBuffer,0,ADDR cbSize,SIZEOF RAWINPUTHEADER)
            mov eax,cbSize
            imul eax,eax,16
            mov cbSize,eax
            .break .if !ASM(mov edi,alloc(cbSize))
            .while 1
                .if ASM( mov esi,rv(GetRawInputBuffer,edi,ADDR cbSize,SIZEOF RAWINPUTHEADER)) != -1 && eax
                    mov ebx,edi
                    push esi
                    .while esi
                        .if [edi].RAWINPUT.header.dwType == RIM_TYPEKEYBOARD
                            .if [edi].RAWINPUT.data.keyboard.VKey+8 == VK_J   ; !!!  fix for wow64
                                fn MessageBox,hwnd,"sdfsdf",0,0
                            .endif
                        .endif
                        ; align 4 needed !
                        add edi,SIZEOF RAWINPUT + 3
                        and edi,-4
                        dec esi
                    .endw
                    pop esi
                .else
                    .break
                .endif
            .endw
            .while 1
                .break .if !rv(PeekMessage,ADDR msg,0,WM_INPUT,WM_INPUT,PM_REMOVE)
            .endw
            free edi           
        .else
            .break 
        .endif
    .endw
    invoke DestroyWindow,hWndDummy
   
    ret
   
RawInputThread endp
end main
FPU in a trice: SmplMath
It's that simple!

zemtex

The RAWMOUSE structure is bad unless you add 2 bytes at the beginning. It is off by 2 bytes using win32.

The windows documentation says that RawMouse usFlags is a word sized, but I need to add 2 bytes for the adressing to be correct.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

qWord

well, the struct RAWINPUT must be/is aligned to 4 - have you checked this?
FPU in a trice: SmplMath
It's that simple!

zemtex

I was about to say so, windows aligns the structure.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

zemtex

I had my structures defined individually, because of that I had to align the RawMouse structure individually for it to work, so I simply just merged all structures and nested them.


RawInput struct 4

   header   RawInputHeader {}
   UNION data
      STRUCT mouse
         usFlags         word ?
         UNION
            ulButtons   dword ?
            STRUCT
               usButtonFlags   word ?
               usButtonData   word ?
            ENDS
         ENDS
         ulRawButtons      dword ?
         lLastX         dword ?
         lLastY         dword ?
         ulExtraInformation   dword ?
      ENDS

      STRUCT keyboard
         MakeCode      word ?
         Flags         word ?
         Reserved      word ?
         VKey         word ?
         Message         dword ?
         ExtraInformation   dword ?
      ENDS

      STRUCT hid
         dwSizeHid   dword ?
         dwCount      dword ?
         bRawData   byte ?
      ENDS
   ENDS

RawInput ends
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

qWord

have you tested my program on your machine? (after removing the +8)
FPU in a trice: SmplMath
It's that simple!

zemtex

I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.