News:

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

Main Menu

SetPixel failure!

Started by felipe, April 04, 2018, 10:02:30 AM

Previous topic - Next topic

felipe

Does anyone can help to understand why this code fails  :(. The weird problem is that in my pc only fails when the window gets maximized  :redface:. Thanks for any reply. .exe attached. It would be so nice to be able to debug the wndproc  :(. Is this even possible? debug the callbacks functions in windows api  :redface:?


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Created by Felipe at 2018-04-03
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

.686
.model      flat,stdcall
option      casemap:none
include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\user32.inc
include     \masm32\include\gdi32.inc
includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\user32.lib
includelib  \masm32\lib\gdi32.lib

.data
align 1
class_name  byte        "main window class",0
wnd_name    byte        "JUST TESTING",0

.data?
align 4
hinstance   dword       ?
hwindow     dword       ?
hdevicec    dword       ?

.code
align 4
start:
            push        ebp
            mov         ebp,esp
           
            push        NULL                                                ; Get a handle for the program instance.
            call        GetModuleHandle
           
            mov         hinstance,eax
           
            sub         esp,76                                              ; WNDCLASSEX and MSG.
                                                     
            mov         dword ptr[ebp-48],48                                ; The size of the structure.
            mov         dword ptr[ebp-44],CS_HREDRAW or CS_VREDRAW          ; The style of the class.
            mov         [ebp-40],wndproc
            mov         dword ptr[ebp-36],0                                 ; No extra
            mov         dword ptr[ebp-32],0                                 ;   bytes.
            mov         eax,hinstance
            mov         [ebp-28],eax

            push        500                                                 ; The smile icon.
            push        hinstance                                           
            call        LoadIcon

            mov         [ebp-24],eax                                        ; hIcon.

            push        600                                                 ; The smile cursor.
            push        hinstance                                             
            call        LoadCursor

            mov         [ebp-20],eax                                        ; hCursor.

            push        WHITE_BRUSH                                         ; Typical background color for a window.
            call        GetStockObject                                      ; Get the handle of the brush.

            mov         [ebp-16],eax                                        ; hBrush.
            mov         dword ptr[ebp-12],NULL                              ; No menu.
            mov         [ebp-8],offset class_name
            mov         dword ptr[ebp-4],NULL                               ; Use the same app icon for the small one.

            lea         eax,[ebp-48]                                        ; WNDCLASSEX.

            push        eax
            call        RegisterClassEx

            push        NULL                                                ; No value passed to the window.
            push        hinstance
            push        NULL                                                ; No menu.
            push        NULL                                                ; No parent of the window.
            push        CW_USEDEFAULT                                       ; Default height.
            push        CW_USEDEFAULT                                       ; Default width.
            push        CW_USEDEFAULT                                       ; Default position
            push        CW_USEDEFAULT                                       ;  of the window.
            push        WS_OVERLAPPEDWINDOW                                 ; Typical main window style.
            push        offset wnd_name                                     ; Name of the main window.   
            push        offset class_name
            push        WS_EX_OVERLAPPEDWINDOW                              ; Some extension of the style.
            call        CreateWindowEx

            mov         hwindow,eax

            push        SW_SHOWNORMAL                                       ; Displaying the window for the first time.
            push        eax
            call        ShowWindow                                         

            push        hwindow
            call        UpdateWindow                                        ; Update the client area.

            lea         esi,[ebp-76]                                        ; MSG.

align 4
msgloop:
            push        0                                                   ; Retrieve all
            push        0                                                   ;  available messages.
            push        NULL                                                ; Messages of any window of this thread.
            push        esi                 
            call        GetMessage
         
            cmp         eax,0
            je          end_program

            push        esi
            call        TranslateMessage                                    ; Translate keyboard to messages.

            push        esi
            call        DispatchMessage                                     ; Dispatch messages to wndproc.

            jmp         msgloop                                             ; Loop until get the WM_QUIT message.

align 4
end_program:
            mov         eax,[ebp-68]                                        ; wParam (exit code).

            mov         esp,ebp
            pop         ebp
 
            push        eax                                 
            call        ExitProcess                                         ; End the program.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

align 4
wndproc:                                                                    ; The window procedure for the main window class.
            push        ebp
            mov         ebp,esp

            sub         esp,80                                              ; RECT AND PAINTSTRUC.
           
            cmp         dword ptr[ebp+12],WM_PAINT                          ; The client area was invalid.
            jne         check_destroy

            push        esi                                                 ; Intel ABI.
            push        edi
            push        ebx

            lea         esi,[ebp-80]                                        ; RECT.                                                       

            push        esi
            push        hwindow
            call        GetClientRect                                       ; Get the coordinates of the client area of the window.
           
            lea         esi,[ebp-64]                                        ; PAINTSTRUCT.

            push        esi
            push        hwindow
            call        BeginPaint                                          ; So, it must be painted again.

            mov         hdevicec,eax
           
            lea         esi,[ebp-80]                                        ; RECT.
            mov         edi,[esi]                                           ; First column.
            mov         ebx,[esi+4]                                         ; First row.
           
           
align
test_pixar:
            push        000000ffh                                           ; Red.                                           
            push        ebx                                                 ; Row.
            push        edi                                                 ; Column.
            push        hdevicec
            call        SetPixel                                            ; Setting pixels, oh yeah!

            inc         edi                                                 ; Next column.
            cmp         edi,dword ptr[esi+8]                                ; Last column of this row?
            jna         test_pixar                                          ;  No, so keep filling the row.
         
            mov         edi,[esi]                                           ; First column.                                     
            inc         ebx                                                 ; Next row.
            cmp         ebx,[esi+12]                                        ; Last row?
            jna         test_pixar                                          ;  No, so keep painting.

            lea         esi,[ebp-64]                                        ; PAINTSTRUCT.

            push        esi
            push        hwindow
            call        EndPaint
         
            xor         eax,eax

            pop         ebx                                                 ; Intel ABI.
            pop         edi
            pop         esi         
           
            mov         esp,ebp
            pop         ebp

            ret         16 
           

align 4
check_destroy:
            cmp         dword ptr[ebp+12],WM_DESTROY
            jne         do_the_default

            push        0                                                   ; Exit code (wParam in WM_QUIT).
            call        PostQuitMessage                                     ; Notify to windows that this is the end of the application.   
           
            xor         eax,eax
           
            mov         esp,ebp
            pop         ebp
           
            ret         16
           

align 4
do_the_default:
            push        dword ptr[ebp+20]                                   ; lParam.
            push        dword ptr[ebp+16]                                   ; wParam.
            push        dword ptr[ebp+12]                                   ; The message.
            push        dword ptr[ebp+8]                                    ; Handle of the window.
            call        DefWindowProc                                       ; Default processing for all the other messages.

            mov         esp,ebp
            pop         ebp

            ret         16
           
            end         start

felipe

If it can be of any help, when i write the max row number hard coded to 800, it works well in full screen. But with greater numbers like 850 and 900 it fails again.  :idea:

       
            mov         edi,[esi]                                           ; First column.                                     
            inc         ebx                                                 ; Next row.
            cmp         ebx,800                                             ; Last row?
            jna         test_pixar                                          ;  No, so keep painting.


felipe

Maybe SetPixel only works with screen of 1024x768?  :redface:

felipe

Also by fails i mean that does not behave properly. It start to paint but doesn't come to the last row, in the title bar says: "this program doesn't respond" and then start again to paint from the top. This repeats, probably forever.  :idea:

raymond

The amount of memory allocated for video may be limited to the size of 'full screen'. Trying to access memory outside that allocation may result in failure of your program.

In the following code portion, try modifying the hilighted blue instructions with the red ones and see what happens.

            inc         edi                                                 ; Next column.
            cmp         edi,dword ptr[esi+8]                                ; Last column of this row?
            jna         test_pixar                                          ;  No, so keep filling the row.
            jb          test_pixar                                          ;  No, so keep filling the row.
         
            mov         edi,[esi]                                           ; First column.                                     
            inc         ebx                                                 ; Next row.
            cmp         ebx,[esi+12]                                        ; Last row?
            jna         test_pixar                                          ;  No, so keep painting
            jb          test_pixar                                          ;  No, so keep painting
Whenever you assume something, you risk being wrong half the time.
http://www.ray.masmcode.com

felipe

I played a lot with the conditions of the loop before, and the same problem. I have done again what you suggested and happens the same. My screen resolution is of 1280x1024  :idea:. Thanks.   :icon14:

jj2007

Quote from: felipe on April 04, 2018, 10:02:30 AMIt would be so nice to be able to debug the wndproc  :(. Is this even possible? debug the callbacks functions in windows api  :redface:?

; include \masm32\include\masm32rt.inc
include \masm32\MasmBasic\MasmBasic.inc
...
WndProc proc uses esi edi ebx hWnd, uMsg, wParam:WPARAM, lParam:LPARAM
  inc msgCount
  NoDebMsg CATSTR NoDebMsg, <, WM_ENTERIDLE> ; don't show this message
  deb 4, "msg", chg:msgCount ; this console deb will only be shown if chg:xxx has changed; needs OPT_Susy Console


Typical output:msg     1       WM_NULL
msg     2       WM_GETMINMAXINFO
msg     3       WM_NCCREATE
msg     4       WM_NCCALCSIZE
msg     5       WM_CREATE
msg     6       WM_WINDOWPOSCHANGING
msg     7       WM_NCCALCSIZE
msg     8       WM_WINDOWPOSCHANGED
msg     9       WM_MOVE
msg     10      WM_SIZE
msg     11      WM_PARENTNOTIFY
msg     12      WM_WINDOWPOSCHANGING
msg     13      WM_ACTIVATEAPP
msg     14      WM_NCACTIVATE
msg     15      WM_ACTIVATE
msg     16      WM_IME_SETCONTEXT
msg     17      WM_IME_NOTIFY
msg     18      WM_SETFOCUS
msg     19      WM_KILLFOCUS
msg     20      WM_IME_SETCONTEXT
msg     21      WM_COMMAND: code 0, ID 1
msg     22      WM_SHOWWINDOW
msg     23      WM_WINDOWPOSCHANGING


Once you know for which message your program hangs, you can debug it inside the respective handler, either with Olly or similar, or with a simple deb 4 message: mov ebx, rv(CreateMenu) ; create the main menu
  deb 4, "create menu", wParam, lParam, eax, $Err$()


Output:create menu
wParam          0
lParam          1637212
eax             197920829
$Err$()         Operazione completata.__


I suspect it's your WM_PAINT handler. The deb macro accepts all kind of variables; if you want to see a pointer as text, prepend a $, e.g. $Err$() or $edi, etc; $$edi would show Unicode text.

aw27

Your code actually works but is really a whole lot of computation inside wndproc, freezing all the other messages, namely WM_SIZE.
My display is 1920x1080

dedndave

yes - SetPixel is slow, so it will require some processing time

but, what i am not seeing is code to handle WM_CREATE and WM_CLOSE
i don't recall what the default process is for those two messages are, but i always handle them

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

    mov     eax,uMsg
    .if eax==WM_CREATE
        mov     edx,hWnd
        mov     hwndMain,edx
        xor     eax,eax

    .elseif eax==WM_CLOSE
        INVOKE  DestroyWindow,hWnd
        xor     eax,eax

    .elseif eax==WM_DESTROY
        INVOKE  PostQuitMessage,NULL
        xor     eax,eax

    .else
        INVOKE  DefWindowProc,hWnd,uMsg,wParam,lParam

    .endif
    ret

WndProc ENDP


add your WM_PAINT handler to that, and see how it goes
for testing, just do the first 10 rows and 10 columns   :biggrin:
once you know that's all working correctly, try for full window

there are faster ways to do this.....
create a red brush
PatBlt the red brush into a memory DC + CompatibleBitmap
BitBlt from the memory DC to the screen DC using the update region in the PAINTSTRUCT

raymond

Quote from: aw27 on April 04, 2018, 04:43:50 PM
Your code actually works but is really a whole lot of computation inside wndproc, freezing all the other messages, namely WM_SIZE.
My display is 1920x1080

What did you expect by calling a Windows procedure over 2,000,000 times to simply change the content of a single memory dword on each occasion.

If you are looking for speed, do it yourself without all that SetPixel procedure overhead. It would be at least 20x faster.
Whenever you assume something, you risk being wrong half the time.
http://www.ray.masmcode.com

HSE

Fantastic code Felipe!
Remember me fakirs   :biggrin:
You must see in Rossler atractors thread how to change pixel value  :t
Equations in Assembly: SmplMath

felipe

@dedndave:i did that and still doesn't work. But with less rows work fine.

@raymond: That's interesting.Probably i was thinking something like: "ok windows should do whatever we told if we use the api." Is good to know than is not all too much high level, even with windows.

@HSE: i knew that this function is old (even gdi dosn't appear in the win api page of microsoft, only appears gdi+ as deprecated). But i was experimenting for first time with such a function. I will try to learn how to use directX. Soon as i can i will load some game, or something like that.

@jj: Don't know if i will use that, but seems like debugging those procedures is not easy or trivial. Now i see why in a recent thread about debugging (i think) someones talk about using message boxes (probably to show variables).

Thanks to all.  :icon14:

Aside note: Have you ever drink too much beer for a single night? :greensml:

hutch--

I use an ancient technique for testing results in a callback like a WndProc, I use the title bar, status bar or anything that does not lock up the display so you can see what a value is from inside the WndProc. Ain't subtle but it works fine. I rarely use a debugger these days as the technique I use is fast and simple. The other factor is I don't like the crippleware that debuggers are these days, I started with Microsoft Codeview debuggers and later use SoftIce and these later things work like toys in comparison.

jj2007

Quote from: felipe on April 05, 2018, 10:53:17 AM@jj: Don't know if i will use that, but seems like debugging those procedures is not easy or trivial. Now i see why in a recent thread about debugging (i think) someones talk about using message boxes (probably to show variables).

It is easy and trivial, and message boxes are a pain in the a**. All you need is a console and a good debug macro. I do that all the time.

Siekmanski

To prevent locking events when debugging in realtime, I write to a memory buffer ( often a circulair buffer ) with or without timestamps. This is very handy when debugging realtime Audio & Graphics routines.
Creative coders use backward thinking techniques as a strategy.