format PE64 GUI
entry WINMAIN
use64

include '%fasminc%\win64a.inc'
include '%fasminc%\equates\msvcrt64.inc'
include '%fasminc%\equates\kernel64.inc'
include '%fasminc%\equates\user64.inc'
include '%fasminc%\equates\gdi64.inc'

include '%fasminc%\equates\directx\d3d9.inc'
include '%fasminc%\equates\directx\d3dx9.inc'

MACRO D3DXMatrixIdentity PMatrix*
{
	mov	dword [PMatrix +  0],3f800000h
	mov	dword [PMatrix +  4],0
	mov	dword [PMatrix +  8],0
	mov	dword [PMatrix + 12],0
	mov	dword [PMatrix + 16],0
	mov	dword [PMatrix + 20],3f800000h
	mov	dword [PMatrix + 24],0
	mov	dword [PMatrix + 28],0
	mov	dword [PMatrix + 32],0
	mov	dword [PMatrix + 36],0
	mov	dword [PMatrix + 40],3f800000h
	mov	dword [PMatrix + 44],0
	mov	dword [PMatrix + 48],0
	mov	dword [PMatrix + 52],0
	mov	dword [PMatrix + 56],0
	mov	dword [PMatrix + 60],3f800000h
}

IDI_APPLICATION = 110
D3DFVF = D3DFVF_XYZ or D3DFVF_NORMAL or D3DFVF_TEX1
gWinWidth = 640
gWinHeight = 480

section '.data' data readable writeable
  windowtitle  db "Win64 DX",0
  windowclass  db "FASMWIN64",0
  errortxt     db "ERROR", 0
  regwinerror  db "RegisterClassEx()",0
  createwindow db "CreateWindowEx()",0
  d3derr       db "D3DCreate9()",0
  d3dderr      db "D3DCreateDevice9()",0
  displayerr   db "GetAdapterDisplayMode()",0
  vertbufferr  db "CreateVertexBuffer()",0
  vertlockerr  db "VertexBufferLock()",0
  vertunlockerr  db "VertexBufferUnlock()",0
  SWFile       db "STONEWALL.PNG",0
  textureerr   db "CreateTexture()",0

  align 8
  struct CUSTOMVERTEX
       x dd ?
       y dd ?
       z dd ?
       nx dd ?
       ny dd ?
       nz dd ?
       u dd ?
       v dd ?
  ends


  align 8
  vecEye D3DXVECTOR3 0.0,30.0,0.0
  align 8
  vecAt D3DXVECTOR3 0.0,0.0,20.0
  align 8
  vecUp D3DXVECTOR3 0.0,1.0,0.0
	
  align 16
  matView D3DXMATRIX
  align 16
  matProj D3DXMATRIX
  align 16
  matWorld D3DXMATRIX
  align 16
  matTrans D3DMATRIX

  align 8
  hinstance dq ?
  mainhwnd  dq ?
  wc WNDCLASSEXA ?
  align 8
  msg  MSG

  align 8
  pD3D9 IDirect3D9
  pD3DD9 IDirect3DDevice9
  pD3DVertexBufferFloor IDirect3DVertexBuffer9
  pD3DTextureFloor IDirect3DTexture9
  pVertBuffer dq 0

  align 8
  D3D_DISPLAYMODE D3DDISPLAYMODE
  align 8
  g_pp D3DPRESENTPARAMETERS

  align 8
  dFLOORVERTICES  CUSTOMVERTEX -64.0, 0.0, -64.0, 0.0, 0.0, 1.0, 0.0, 1.0
		  CUSTOMVERTEX -64.0, 0.0, 64.0, 0.0, 0.0, 1.0, 0.0, 0.0
		  CUSTOMVERTEX 64.0, 0.0, -64.0, 0.0, 0.0, 1.0, 1.0, 1.0
		  CUSTOMVERTEX 64.0, 0.0, 64.0, 0.0, 0.0, 1.0, 1.0, 0.0




section '.code' code readable executable

proc WINMAIN  hInstance, hprevinstance, lpcmdline, ncmdshow
     local qalign:QWORD

     fastcall [memset], wc, 0, sizeof.WNDCLASSEXA
     invoke  GetModuleHandle, 0
     mov     [hinstance], rax
     mov     [wc.hInstance], rax
     mov     [wc.cbSize], sizeof.WNDCLASSEXA ;size of structure
     invoke  LoadIcon, [hinstance], IDI_APPLICATION
     mov     [wc.hIcon], rax
     mov     [wc.hIconSm], rax
     invoke  LoadCursor, 0, IDC_ARROW
     mov     [wc.hCursor], rax
     mov     [wc.style], CS_HREDRAW or CS_VREDRAW
     mov     [wc.lpfnWndProc], WindowProc
     mov     [wc.cbClsExtra], 0
     mov     [wc.cbWndExtra], 0
     mov     [wc.hbrBackground], NULL
     mov     [wc.lpszMenuName], 0
     mov     [wc.lpszClassName], windowclass

     invoke RegisterClassEx, wc
     .if     rax = NULL
	     invoke  MessageBox, NULL, regwinerror, errortxt, MB_OK or MB_ICONERROR
	     return  0
     .endif

     invoke CreateWindowEx, NULL, windowclass, windowtitle, WS_OVERLAPPEDWINDOW + WS_VISIBLE,\
	     128, 128, gWinWidth, gWinHeight, NULL, NULL, [hinstance], NULL
     .if     rax = NULL
	     invoke  MessageBox, NULL, createwindow, errortxt, MB_OK or MB_ICONERROR
	     return  0
     .endif
     mov     [mainhwnd], rax

     call INIT3D
     call INITSCENE
     call CREATEFLOOR

     mov     [msg.message], TRUE
     .while  [msg.message] <> WM_QUIT
	     invoke  PeekMessage, msg, NULL, 0, 0, PM_REMOVE
	     .if     rax <> NULL
		     invoke  TranslateMessage, msg
		     invoke  DispatchMessage, msg
	     .else
		     call RENDERSCENE
	     .endif
     .endw

     call CLOSE3D

     invoke  UnregisterClass,wc,[hinstance]
     invoke  ExitProcess, 0
     return
endp

proc WindowProc ;hwnd, wmsg, wparam, lparam
     local hdc:QWORD
     ;Note that first four parameters are passed in registers,
     ;while names given in the declaration of procedure refer to the stack
     ;space reserved for them - you may store them there to be later accessible
     ;if the contents of registers gets destroyed. This may look like:
     ;mov     [hwnd],rcx
     ;mov     [wmsg],rdx
     ;mov     [wparam],r8
     ;mov     [lparam],r9

     .if rdx = WM_CLOSE
	     invoke  PostQuitMessage, 0
	     return  0
     .endif
			    ;[hwnd], [wmsg], [wparam], [lparam]
     invoke  DefWindowProc, rcx, rdx, r8, r9
     return
endp

proc INIT3D
     local qalign:QWORD
     invoke Direct3DCreate9, D3D_SDK_VERSION
     mov [pD3D9],rax
     .if rax = NULL
	 invoke MessageBox,0,d3derr,errortxt,MB_OK or MB_ICONSTOP
	 return FALSE
     .endif

     fastcall [memset], D3D_DISPLAYMODE, 0, sizeof.D3DDISPLAYMODE

     cominvk pD3D9,GetAdapterDisplayMode,0,D3D_DISPLAYMODE
     .if rax <> D3D_OK
	 invoke MessageBox,0,displayerr,errortxt,MB_OK or MB_ICONSTOP
	 return FALSE
     .endif

     fastcall [memset], g_pp, 0, sizeof.D3DPRESENTPARAMETERS

     mov [g_pp.Windowed],TRUE
     mov [g_pp.SwapEffect],D3DSWAPEFFECT_DISCARD
     mov eax,[D3D_DISPLAYMODE.Format]
     mov [g_pp.BackBufferFormat],eax ;D3DFMT_A8R8G8B8
     mov [g_pp.BackBufferWidth],gWinWidth
     mov [g_pp.BackBufferHeight],gWinHeight
     mov [g_pp.EnableAutoDepthStencil], TRUE
     mov [g_pp.AutoDepthStencilFormat],D3DFMT_D24S8
     mov [g_pp.PresentationInterval],D3DPRESENT_INTERVAL_IMMEDIATE

     cominvk pD3D9,CreateDevice,D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,[mainhwnd], \
	     D3DCREATE_HARDWARE_VERTEXPROCESSING,g_pp,pD3DD9

     .if rax <> D3D_OK
	 invoke MessageBox,0,d3dderr,errortxt,MB_OK or MB_ICONSTOP
	 return FALSE
     .endif

     return D3D_OK
endp

proc CLOSE3D
     local qalign:QWORD

     .if [pD3DTextureFloor]<>NULL
	 cominvk pD3DTextureFloor,Release
     .endif

     .if [pD3DVertexBufferFloor]<>NULL
	 cominvk pD3DVertexBufferFloor,Release
     .endif

     .if [pD3DD9]<> NULL
	 cominvk pD3DD9,Release
     .endif

     .if [pD3D9]<> NULL
	 cominvk pD3D9,Release
     .endif

     return D3D_OK
endp

proc INITSCENE
     local qalign:QWORD

     fastcall [memset], matView, 0, sizeof.D3DXMATRIX
     fastcall [memset], matProj, 0, sizeof.D3DXMATRIX

     invoke D3DXMatrixLookAtLH,addr matView,addr vecEye,addr vecAt,addr vecUp
     cominvk pD3DD9,SetTransform,D3DTS_VIEW,addr matView
     invoke D3DXMatrixPerspectiveFovLH,addr matProj,float 1.570796327,float 1.0,float 1.0,float 300.0

     cominvk pD3DD9,SetTransform,D3DTS_PROJECTION,addr matProj
     cominvk pD3DD9,SetRenderState,D3DRS_LIGHTING,FALSE
     cominvk pD3DD9,SetRenderState,D3DRS_FILLMODE,D3DFILL_SOLID
     cominvk pD3DD9,SetRenderState,D3DRS_ZENABLE,TRUE

     return D3D_OK
endp

proc CREATEFLOOR
     local qalign:QWORD

     cominvk pD3DD9,CreateVertexBuffer,sizeof.CUSTOMVERTEX*4,D3DUSAGE_WRITEONLY,\
	     D3DFVF,D3DPOOL_DEFAULT,pD3DVertexBufferFloor,0

     .if rax <> D3D_OK
	 invoke MessageBox,0,vertbufferr,errortxt,MB_OK or MB_ICONSTOP
	 return FALSE
     .endif

     cominvk pD3DVertexBufferFloor,Lock,0,0,pVertBuffer,0
     .if rax <> D3D_OK
	 invoke MessageBox,0,vertlockerr,errortxt,MB_OK or MB_ICONSTOP
	 return FALSE
     .endif

     mov rsi,dFLOORVERTICES
     mov rdi,[pVertBuffer]
     cld
     mov rcx,sizeof.CUSTOMVERTEX*4/8
     rep movsq

      cominvk pD3DVertexBufferFloor,Unlock
     .if rax <> D3D_OK
	 invoke MessageBox,0,vertunlockerr,errortxt,MB_OK or MB_ICONSTOP
	 return FALSE
     .endif

     invoke D3DXCreateTextureFromFile,[pD3DD9],SWFile,pD3DTextureFloor

     .if rax <> D3D_OK
	 invoke MessageBox,0,textureerr,errortxt,MB_OK or MB_ICONSTOP
	 return FALSE
     .endif

     return D3D_OK
endp

proc RENDERSCENE
     local qalign:QWORD

     cominvk pD3DD9,Clear,DWORD 0,DWORD 0,D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,DWORD 00205090h,float 1.0, DWORD 0

     cominvk pD3DD9,BeginScene

	call RENDERFLOOR

     cominvk pD3DD9,EndScene

     cominvk pD3DD9,Present,0,0,0,0
     return D3D_OK
endp

proc RENDERFLOOR
     local qalign:QWORD

     D3DXMatrixIdentity matTrans

     cominvk pD3DD9,SetTexture,0,[pD3DTextureFloor]
     invoke D3DXMatrixTranslation,addr matTrans,float 0.0,float -5.0,float 0.0
;     sub rsp,20h
;     mov rax, 0.0
;     movq xmm3,rax
;     mov rax, -5.0
;     movq xmm2,rax
;     mov rax, 0.0
;     movq xmm1,rax
;     mov rcx, matTrans
;     call [D3DXMatrixTranslation]
;     add rsp,20h

     cominvk pD3DD9,SetStreamSource,0,[pD3DVertexBufferFloor],0,sizeof.CUSTOMVERTEX
     cominvk pD3DD9,SetTransform,D3DTS_WORLD,addr matTrans
     cominvk pD3DD9,DrawPrimitive,D3DPT_TRIANGLESTRIP,0,2
     cominvk pD3DD9,SetTexture,0,NULL
     return D3D_OK
endp


section '.rsrc' resource data readable
  directory RT_MANIFEST, manifest, RT_ICON, icons, RT_GROUP_ICON, group_icons

  resource manifest, 1, LANG_NEUTRAL, winxp
  resource icons, 1, LANG_NEUTRAL, icon_data
  resource group_icons, IDI_APPLICATION, LANG_NEUTRAL, main_icon

  icon	   main_icon, icon_data, 'directx.ico'

  resdata  winxp
	   file '%fasminc%\winxpstyle.xml'
  endres

section '.idata' import data readable writeable

  library kernel64,'KERNEL32.DLL',\
	  user64,'USER32.DLL',\
	  gdi64,'GDI32.DLL',\
	  d3d9,'D3D9.DLL',\
	  d3dx9_40,'D3DX9_40.DLL',\
	  msvcrt64,'MSVCRT.DLL'

  include '%fasminc%\apia7\kernel64.inc'
  include '%fasminc%\apia7\user64.inc'
  include '%fasminc%\apia7\gdi64.inc'
  include '%fasminc%\apia7\msvcrt64.inc'
  include '%fasminc%\apia7\directx\d3d9.inc'
  include '%fasminc%\apia7\directx\d3dx9_40.inc'
