
format PE64
entry main 

include '\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
	
	invoke	RegisterClassExA,WindowClass
	test rax, rax
	jz error 

	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
	invoke GetDC, [WindowHandle]
	mov [WindowDC], rax

	test rax, rax
	jz error

	stdcall Win32InitDrawBuffer,960,540, GlobalDrawBuffer

	mov [GlobalRunning], 1
.loop:
	cmp [GlobalRunning], 0
	je exit

	call Win32MessagePump
	stdcall Win32DisplayBuffer,[WindowDC],GlobalDrawBuffer

	jmp .loop

error:
	call Win32ErrorEncountered

exit:
invoke	ExitProcess,[Message.wParam]

;---

proc Win32ErrorEncountered
	invoke MessageBoxA,0,SystemCallError,WindowTitle,MB_ICONERROR+MB_OK

	ret
endp

proc ClearBuffer ;colour, buffer
	
	lea r8, [rdx + 8] ;PixelPointer
	mov r8, [r8]
	
	;iterations 
	lea rax, [rdx+16]
	lea rbx, [rdx+20]
	mov eax, [rax]
	mov ebx, [rbx]
	mul ebx

.nextPixel:
	mov [r8], ecx
	add r8, 4
	 
	dec rax
	cmp rax, 0
	jne .nextPixel

	ret
endp

proc Win32DisplayBuffer ; dc, *buffer
	locals
		Width dd 0		
		Height dd 0
		Pixels dq 0
		DC dq 0
		Buffer dq 0
	endl

	mov [DC], rcx
	mov [Buffer], rdx

	lea rax, [rdx+16]
	mov rax, [rax]
	mov [Width], eax
	lea rbx, [rdx+20]
	mov rbx, [rbx]
	mov [Height], ebx
	
	lea rax, [rdx+8]
	mov [Pixels], rax

	stdcall ClearBuffer, 0xFF0000FF, rdx

int3
	mov rbx, GlobalDrawBuffer
	mov rax, [Buffer]
	mov rax, [Pixels]
	invoke StretchDIBits, [DC],0,0,[Width],[Height],0,0,[Width],[Height],[Pixels],[Buffer],DIB_RGB_COLORS,SRCCOPY
	cinvoke GetLastError

	ret
endp

proc Win32InitDrawBuffer   ;width, height, buffer 
locals
	PixelsPointer dq 0
endl

	lea rax, [r8+8]
	mov [PixelsPointer], rax

	mov rax, [rax]
	cmp rax, 0
	je @f

	invoke VirtualFree,rax,0,MEM_RELEASE
	cmp rax, 0
	je .end

@@:

	mov rax, r8
	mov rbx, sizeof.BITMAPINFOHEADER
	mov [rax], rbx ;header size
	add rax, 4
	mov [rax], ecx ;width
	add rax, 4 
	mov [rax], edx ;height
	add rax, 4 
	mov bx, 1 ;planes
	mov [rax], bx
	add rax, 2 
	mov bx, 32 ;bitcout
	mov [rax], bx
	add rax, 2 
	mov ebx, BI_RGB ;compression
	mov [rax], ebx
	

;set width and height in buffer
	lea rax, [r8+16]
	mov [rax], ecx
	lea rax, [r8+20]
	mov [rax], edx

	mov rax, rcx
	mul rdx
	mov r10, 4
	mul r10
	mov r10, MEM_COMMIT
	or r10, MEM_RESERVE 
	invoke VirtualAlloc,0,eax,r10d,PAGE_READWRITE
	test rax, rax
	jz error

	mov rbx, [PixelsPointer]
	mov [rbx], rax

.end:
	ret
endp

proc Win32MessagePump; uses WindowHandle

.while_message:	 

	;invoke PeekMessageA, Message, WindowHandle,0,0, PM_REMOVE   ;TODO why does this freeze up?
	invoke GetMessage,Message,0,0,0 ;TODO replace with peekmessage
	test rax, -1
	jz error


	cmp eax, 0
	je .end
	
	cmp [Message.message], WM_QUIT
	mov [GlobalRunning], 0
	je .end

	cmp [Message.message], WM_PAINT
	je .paint

	cmp [Message.message], WM_KEYDOWN
	je .keydown

	invoke TranslateMessage,Message
	invoke DispatchMessage,Message

	jmp .while_message

.paint:
	stdcall Win32DisplayBuffer,[WindowDC],GlobalDrawBuffer
	jmp .while_message

.keydown:
	jmp .while_message

.end:
	
	ret
endp

proc Win32CallbackProc ;proc WndProc uses rbx rsi rdi, hwnd,wmsg,wparam,lparam
	cmp edx, WM_DESTROY 
        je .destroy

  .default:
				invoke	DefWindowProcA,rcx,rdx,r8,r9
        jmp .end
  .destroy:
        invoke PostQuitMessage,0
        xor rax,rax
  .end:
        ret
endp


