flat assembler
Message board for the users of flat assembler.

Index > Windows > StretchDIBits() call not painting black as expected

Author
Thread Post new topic Reply to topic
B.Dubious



Joined: 04 Apr 2020
Posts: 22
B.Dubious 31 May 2021, 18:26
I started trying to pick up some fasm a while back and after not touching it for a long while I've started trying to pick it up again but I'm not at all sure why my program isn't painting the screen black. I got it working with patblt but I can't figure out why the program isn't painting black.

I have a call to virtualAlloc which gets 2 gigs of memory which looks like this.

Code:
       format PE64 
entry main 

include 'C:\Users\bmowo\Desktop\Tools\fasm\INCLUDE\win64a.inc'
include '.\main_data.asm'

section '.text' code readable executable 
main:
        sub     rsp,8

        invoke  GetModuleHandle,0
        mov     [WindowClass.hInstance], rax
        invoke LoadIcon,0,IDI_APPLICATION
        mov     [WindowClass.hIcon],rax
        mov     [WindowClass.hIconSm],rax
        invoke LoadCursor,0,IDC_ARROW
        mov     [WindowClass.hCursor],rax

        mov rax, CS_OWNDC or CS_HREDRAW or CS_VREDRAW
        mov [WindowClass.style], eax
        
        invoke  RegisterClassExA,WindowClass
        test rax, rax
        jz exit 

        invoke CreateWindowExA,0,WindowClassName,WindowTitle, WS_VISIBLE+WS_OVERLAPPEDWINDOW,\
                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0,0,[WindowClass.hInstance],0

        mov [WindowHandle], rax
        test rax, rax
        jz exit

        mov rax, 2*gigabyte 
        mov r10d, MEM_COMMIT or MEM_RESERVE
        invoke VirtualAlloc,0,eax,r10d,PAGE_READWRITE
        mov [Memory], rax

;       ;clear buffer
;       loopCount equ 20000
;       byteOffset equ 4
;
;       mov r8, 0
;       mov r11, [Memory]
;.clearloop:
;       mov [r11], dword 0xadde
;
;       add r11, byteOffset
;       ;add r8, 1
;       inc r8
;       cmp r8, loopCount
;       jne .clearloop
;
;       restore loopCount
;       restore byteOffset

        mov [GlobalRunning], 1
.main_loop:
        cmp [GlobalRunning], 0
        je exit

        stdcall Win32MessagePump
        jmp .main_loop

exit:
        invoke  ExitProcess,[Message.wParam]

;------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ 

proc BlitBuffer
        locals
                Width dd 0              
                Height dd 0
                PixelsBase dq 0
                DC dq 0
                BitmapInfo BITMAPINFO 0
                ScreenRect RECT 
        endl

        ;get window region
        lea rax, [ScreenRect]
        invoke GetClientRect, [WindowHandle], rax

        ;calculate width and height
        mov ecx, [ScreenRect.bottom]
        sub ecx, [ScreenRect.top]
        mov [Height], ecx

        mov ecx, [ScreenRect.left]
        sub ecx, [ScreenRect.right]
        mov [Width], ecx


        BitmapInfoHeaderSize equ 40
        BI_RGB equ 0
        mov [BitmapInfo.biSize], BitmapInfoHeaderSize ;sizeof bitmapinfoheader is 40
        mov eax, [Width]
        mov [BitmapInfo.biWidth], eax
        mov eax, [Height]
        mov [BitmapInfo.biHeight], eax
        mov [BitmapInfo.biPlanes], 1
        mov [BitmapInfo.biBitCount], 32
        mov [BitmapInfo.biCompression], BI_RGB
        mov [BitmapInfo.biSizeImage], 0
        mov [BitmapInfo.biXPelsPerMeter], 0
  mov [BitmapInfo.biYPelsPerMeter], 0
  mov [BitmapInfo.biClrUsed], 0 
  mov [BitmapInfo.biClrImportant], 0
        mov [BitmapInfo.RGBQUADa], 0
        mov [BitmapInfo.RGBQUADb], 0
        mov [BitmapInfo.RGBQUADc], 0
        mov [BitmapInfo.RGBQUADd], 0

        mov rax, [Memory] 
        mov [PixelsBase], rax

        invoke GetDC, [WindowHandle]
        mov [DC], rax
        
        lea rax, [BitmapInfo]

        DIB_RGB_COLORS equ 0
        invoke StretchDIBits, [DC],0,0,[Width],[Height],0,0,[Width],[Height],[PixelsBase], rax,DIB_RGB_COLORS,SRCCOPY

        ret
endp 

proc Win32ToggleWindowFullScreen

locals
        WindowStyle dd 0
        MonitorInfo MONITORINFO sizeof.MONITORINFO
endl

        GWL_STYLE equ -16
        SWP_NOOWNERZORDER equ 0x0200 
        SWP_FRAMECHANGED equ 0x0020
        SWP_NOMOVE equ 0x0002 
        SWP_NOSIZE equ 0x0001 
        SWP_NOZORDER equ 0x0004
        HWND_TOP equ 0 
        SWP_FRAMECHANGED equ 0x0020
        WS_OVERLAPPEDWINDOW equ 0xcf0000
        MONITOR_DEFAULTTOPRIMARY equ 1 

        invoke GetWindowLongA, [WindowHandle], GWL_STYLE
        mov [WindowStyle], eax

        mov rbx, WS_OVERLAPPEDWINDOW
        and eax, ebx
        jz .else
        
        invoke GetWindowPlacement, [WindowHandle], GlobalWindowPlacement
        mov r8, rax
        cmp rax, 1
        jb .end 
        
        invoke MonitorFromWindow,[WindowHandle], MONITOR_DEFAULTTOPRIMARY
        lea rbx, [MonitorInfo]
        invoke GetMonitorInfoA,rax,rbx
        cmp rax, 1
        jb .end

        mov rbx, not WS_OVERLAPPEDWINDOW ;not rbx
        mov eax, [WindowStyle]
        and eax, ebx

        invoke SetWindowLongA, [WindowHandle], GWL_STYLE, eax

        mov eax, [MonitorInfo.rcMonitor.right]
        sub eax, [MonitorInfo.rcMonitor.left]

        mov r10d, [MonitorInfo.rcMonitor.bottom]
        sub r10d, [MonitorInfo.rcMonitor.top] 

        mov r11, HWND_TOP or SWP_NOOWNERZORDER or SWP_FRAMECHANGED 

        invoke SetWindowPos, [WindowHandle],0,[MonitorInfo.rcMonitor.left],[MonitorInfo.rcMonitor.top],eax,r10d,r11d
        jmp .end

.else:
        mov eax, [WindowStyle]
        or rax, WS_OVERLAPPEDWINDOW
        invoke SetWindowLongA, [WindowHandle],GWL_STYLE,eax
        invoke SetWindowPlacement,[WindowHandle],GlobalWindowPlacement

        mov rax, SWP_NOOWNERZORDER or SWP_FRAMECHANGED or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER 
        invoke SetWindowPos,[WindowHandle],0,0,0,0,0,eax

.end:
        ret
endp

proc Win32MessagePump

.while_message:  

        invoke PeekMessageA,Message,[WindowHandle],0,0,PM_REMOVE 
        cmp eax, 0
        je .end

        cmp [Message.message], WM_KEYDOWN
        je .keydown

        cmp [Message.message], WM_PAINT
        je .paint

.default:
        invoke TranslateMessage,Message
        invoke DispatchMessage,Message
        jmp .while_message

.keydown:
        stdcall Win32ToggleWindowFullScreen

.paint:

                invoke BeginPaint,[WindowHandle],PaintStruct

                stdcall BlitBuffer

                invoke EndPaint,[WindowHandle],PaintStruct

        jmp .while_message

.end:
        
        ret
endp

proc Win32CallbackProc ;hwnd,wmsg,wparam,lparam
        
        cmp edx, WM_DESTROY 
        cmp edx, WM_CLOSE
        cmp edx, WM_QUIT
                je .close

        .default:
                invoke  DefWindowProcA,rcx,rdx,r8,r9
                jmp .end

        .close:
                mov [GlobalRunning], 0
                jmp .end
                                
.end:
        ret
endp
    



I expected that since the buffer is a large 2 gig zero buffer I should be getting a black screen. But that is not the case. I'm not getting errors from windows and it runs just fine. I have no idea what I'm doing wrong and I really can't progress until I know whats going on here.


Description:
Download
Filename: main_data.asm
Filesize: 2.32 KB
Downloaded: 1748 Time(s)

Description:
Download
Filename: main.asm
Filesize: 5.28 KB
Downloaded: 1687 Time(s)



Last edited by B.Dubious on 01 Jun 2021, 00:36; edited 3 times in total
Post 31 May 2021, 18:26
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20445
Location: In your JS exploiting you and your system
revolution 31 May 2021, 19:22
You need to check that the allocation succeeded.

For 32-bit code it is usually impossible to allocate 2GB in one block because of the layout of the address space.
Post 31 May 2021, 19:22
View user's profile Send private message Visit poster's website Reply with quote
B.Dubious



Joined: 04 Apr 2020
Posts: 22
B.Dubious 31 May 2021, 19:31
I'm fairly sure the allocation succeeded, it's a 64 bit portable executable. I did checks on it with GetLastError and I stepped through with the debugger and rax gets a plausible address which I've tried writing to without crashing. I've tried a number of things and nothing has worked, I just can't see what's wrong with the code at all... but it doesn't work so I must be missing something.
Post 31 May 2021, 19:31
View user's profile Send private message Reply with quote
B.Dubious



Joined: 04 Apr 2020
Posts: 22
B.Dubious 31 May 2021, 23:26
I've gone through and tidied up a bit. I'll attach the files in case someone fancies having a go at fixing it. I'm still totally confused why I can't get this to draw. I'm going to have to give up on it for tonight at least... I'll try grind at it some more soon.
Post 31 May 2021, 23:26
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 767
tthsqe 01 Jun 2021, 11:31
I will have a look.
Post 01 Jun 2021, 11:31
View user's profile Send private message Reply with quote
B.Dubious



Joined: 04 Apr 2020
Posts: 22
B.Dubious 01 Jun 2021, 17:21
Have any luck? I've been over it again and again and I just don't know what's wrong. I might try do some other programs without graphics and see if I realise anything once I've learned some more fasm programming. Driving me crazy!
Post 01 Jun 2021, 17:21
View user's profile Send private message Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 794
Location: Adelaide
sinsi 01 Jun 2021, 20:58
Code:
       lea rax, [BitmapInfo]

        DIB_RGB_COLORS equ 0
        invoke StretchDIBits, [DC],0,0,[Width],[Height],0,0,[Width],[Height],[PixelsBase], rax,DIB_RGB_COLORS,SRCCOPY
    

I think the invoke macro uses RAX, so your initial LEA RAX,[BitmapInfo] is wiped out. Change the two RAXs to R11 and we get a black window.
Post 01 Jun 2021, 20:58
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 767
tthsqe 01 Jun 2021, 22:47
A few things here:
1. The lea rax, [BitmapInfo] is being clobbered by the invoke StretchDIBits. If I use .. , addr BitmapInfo, .. it works.
2. Probably some rectangles need to be invalidated?
3.Inside the Ein32CallBackProc, there should probably be a je .close after each cmp edx, ... . Otherwise it doest exit when I close it.
4.format PE64 GUI
Post 01 Jun 2021, 22:47
View user's profile Send private message Reply with quote
B.Dubious



Joined: 04 Apr 2020
Posts: 22
B.Dubious 01 Jun 2021, 23:27
Thanks guys, the clobber was the problem. That should have been more obvious to me but I guess I'm pretty daft!
I've followed some of your recommendations tthsqe but I'll have to look up why PE64 GUI.

At least now I can get started on my program! That was the most painful time I've ever had getting pixels on the screen to date.
I'll need to be careful with macros in future
Post 01 Jun 2021, 23:27
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.