format PE64 GUI 5.0 entry start include 'win64a.inc' include 'ddraw64.inc' section '.text' code readable executable start: sub rsp,8 and [DDraw],0 and [DDSPrimary],0 and [DDSBack],0 invoke GetModuleHandle,NULL mov [hinstance],rax mov [wc.hInstance],rax invoke LoadIcon,NULL,IDI_APPLICATION mov [wc.hIcon],rax invoke LoadCursor,NULL,IDC_ARROW mov [wc.hCursor],rax invoke RegisterClassEx,wc test rax,rax jz startup_error invoke CreateWindowEx,\ 0,_class,_title,WS_POPUP+WS_VISIBLE,0,0,0,0,NULL,NULL,[hinstance],NULL test rax,rax jz startup_error mov [hwnd],rax invoke DirectDrawCreate,NULL,DDraw,NULL test rax,rax jnz ddraw_error cominvk DDraw,SetCooperativeLevel,\ [hwnd],DDSCL_EXCLUSIVE+DDSCL_FULLSCREEN test rax,rax jnz ddraw_error cominvk DDraw,SetDisplayMode,\ 640,480,32 test rax,rax jnz ddraw_error mov [ddsd.dwSize],sizeof.DDSURFACEDESC mov [ddsd.dwFlags],DDSD_CAPS+DDSD_BACKBUFFERCOUNT mov [ddsd.ddsCaps.dwCaps],DDSCAPS_PRIMARYSURFACE+DDSCAPS_FLIP+DDSCAPS_COMPLEX mov [ddsd.dwBackBufferCount],1 cominvk DDraw,CreateSurface,\ ddsd,DDSPrimary,NULL or eax,eax jnz ddraw_error mov [ddscaps.dwCaps],DDSCAPS_BACKBUFFER cominvk DDSPrimary,GetAttachedSurface,\ ddscaps,DDSBack or eax,eax jnz ddraw_error refresh: cominvk DDSPrimary,IsLost test rax,rax jz paint cmp eax,DDERR_SURFACELOST jne end_loop cominvk DDSPrimary,Restore paint: mov [ddsd.dwSize],sizeof.DDSURFACEDESC mov [ddsd.dwFlags],0 cominvk DDSBack,Lock,NULL,ddsd,DDLOCK_SURFACEMEMORYPTR+DDLOCK_WAIT,NULL test rax,rax jnz main_loop mov rdi,[ddsd.lpSurface] mov r10d,[ddsd.lPitch] xor edx,edx movsd xmm8,[y_top] screen: xor ebx,ebx movsd xmm7,[x_left] unpcklpd xmm7,xmm8 row: mov rcx,255 xorpd xmm1,xmm1 iterate: movapd xmm3,xmm1 unpckhpd xmm3,xmm3 mulsd xmm3,xmm1 addsd xmm3,xmm3 mulpd xmm1,xmm1 movapd xmm2,xmm1 ; for SSE3-capable processor unpckhpd xmm2,xmm2 ; these three instructions can be subsd xmm1,xmm2 ; replaced with HSUBPD XMM1,XMM1 unpcklpd xmm1,xmm3 addpd xmm1,xmm7 movapd xmm0,xmm1 mulpd xmm0,xmm0 movapd xmm2,xmm0 ; for SSE3-capable processor shufpd xmm2,xmm2,1 ; these three instructions can be addsd xmm0,xmm2 ; replaced with HADDPD XMM0,XMM0 sqrtpd xmm0,xmm0 comisd xmm0,[limit] ja over loop iterate over: xor al,al stosb mov al,cl stosb ror al,3 stosb stosb movsd xmm0,[x_step] addpd xmm7,xmm0 inc ebx cmp ebx,640 jb row sub rdi,640*4 add rdi,r10 subsd xmm8,[y_step] inc edx cmp edx,480 jb screen mov [refresh_needed],0 cominvk DDSBack,Unlock,NULL cominvk DDSPrimary,Flip,0,0 main_loop: invoke PeekMessage,msg,NULL,0,0,PM_NOREMOVE or eax,eax jz no_message invoke GetMessage,msg,NULL,0,0 cmp eax,1 jb end_loop jne no_message invoke TranslateMessage,msg invoke DispatchMessage,msg cmp [refresh_needed],0 jne refresh jmp main_loop no_message: invoke WaitMessage jmp main_loop ddraw_error: invoke wsprintf,buffer,_ddraw_error,rax invoke MessageBox,[hwnd],buffer,_error,MB_OK+MB_ICONERROR invoke DestroyWindow,[hwnd] invoke PostQuitMessage,2 jmp main_loop startup_error: invoke MessageBox,[hwnd],_startup_error,_error,MB_OK+MB_ICONERROR invoke ExitProcess,1 end_loop: cominvk DDraw,RestoreDisplayMode cmp [DDSBack],0 je back_surface_released cominvk DDSPrimary,DeleteAttachedSurface,0,DDSBack back_surface_released: cmp [DDSPrimary],0 je primary_surface_released cominvk DDSPrimary,Release primary_surface_released: cmp [DDraw],0 je ddraw_released cominvk DDraw,Release ddraw_released: invoke ExitProcess,[msg.wParam] proc WindowProc uses rbx rsi rdi, hwnd,wmsg,wparam,lparam cmp edx,WM_CREATE je .wmcreate cmp edx,WM_DESTROY je .wmdestroy cmp edx,WM_LBUTTONDOWN je .wmlbuttondown cmp edx,WM_RBUTTONDOWN je .wmrbuttondown cmp edx,WM_KEYDOWN je .wmkeydown cmp edx,WM_ACTIVATE je .wmactivate .defwindowproc: invoke DefWindowProc,rcx,rdx,r8,r9 jmp .finish .wmcreate: xor eax,eax jmp .finish .wmactivate: test r8,r8 jz .finish or [refresh_needed],1 jmp .finish .wmlbuttondown: movapd xmm0,[step] divpd xmm0,[zoom] movapd xmm1,xmm0 subpd xmm1,[step] movapd [step],xmm0 movzx eax,r9w cvtsi2sd xmm3,eax shr r9,16 movzx eax,r9w cvtsi2sd xmm4,eax unpcklpd xmm3,xmm4 mulpd xmm1,xmm3 xorpd xmm1,[negate] addpd xmm1,[origin] movapd [origin],xmm1 or [refresh_needed],1 jmp .finish .wmrbuttondown: movapd xmm0,[step] mulpd xmm0,[zoom] movapd xmm1,xmm0 subpd xmm1,[step] movapd [step],xmm0 movzx eax,r9w cvtsi2sd xmm3,eax shr r9,16 movzx eax,r9w cvtsi2sd xmm4,eax unpcklpd xmm3,xmm4 mulpd xmm1,xmm3 xorpd xmm1,[negate] addpd xmm1,[origin] movapd [origin],xmm1 or [refresh_needed],1 jmp .finish .wmkeydown: cmp r8d,VK_ESCAPE jne .finish .wmdestroy: invoke PostQuitMessage,0 xor eax,eax .finish: ret endp section '.data' data readable writeable wc WNDCLASSEX sizeof.WNDCLASSEX,0,WindowProc,0,0,NULL,NULL,NULL,NULL,NULL,_class,NULL _title db 'flat assembler DirectDraw application',0 _class db 'FDDRAW64',0 _error db 'Error',0 _startup_error db 'Startup failed',0 _ddraw_error db 'Direct Draw initialization failed (error code 0x%x).',0 align 16 ; SSE data follows label origin dqword x_left dq -2.2 y_top dq 1.25 label step dqword x_step dq 0.0045 y_step dq 0.0052 label zoom dqword dq 1.2,1.2 label negate dqword dq 8000000000000000h,0 limit dq 2.5 section '.bss' readable writeable hinstance dq ? hwnd dq ? msg MSG ddsd DDSURFACEDESC ddscaps DDSCAPS DDraw DirectDraw DDSPrimary DirectDrawSurface DDSBack DirectDrawSurface rect RECT refresh_needed dd ? buffer rb 100h section '.idata' import data readable library kernel32,'KERNEL32.DLL',\ user32,'USER32.DLL',\ ddraw,'DDRAW.DLL' include 'api\kernel32.inc' include 'api\user32.inc' import ddraw,\ DirectDrawCreate,'DirectDrawCreate'