;            Name: dx9_resize_window.cpp
;          Author: Kevin Harris
;  Last Modified: 04/21/04
;    Description: This sample demonstrates how to respond to the app's window
;                 getting resized by resizing the front and back buffers of
;                 the Direct3D device to match it. If you don't do this,
;                 Direct3D will be forced to perform a stretch blit when the
;                 window is enlarged and everything rendered will appear
;                 course and blocky. For example, if the initial window size
;                 and Direct3D device are set to 640x480 and you enlarge the
;                 window to be 1024x768, the Direct3D device will continue to
;                 render at 640x480 unless its front and back buffers are
;                 resized accordingly.
;
;                 To see what happens when you don't handle resizing properly,
;                 run the sample and maximize the window. Once maximized,
;                 note how smooth the teapot is and how clean the texturing
;                 on the quad is. Next, grab the window's corner and
;                 considerably reduce the window's size and hit F1 to toggle
;                 off the handling code and maximize it again. When the
;                 window is maximized the teapot and textured quad should
;                 appear highly pixilated.
;
;   Control Keys: F1 - Toggle handling of WM_SIZE window message
;                 Left Mouse Button - Spin the teapot and textured quad
format PE GUI 4.0
entry WinMain

include '%fasminc%\win32a.inc'
include '%fasminc%\equates\MSVCRT.INC'
include '%fasminc%\equates\kernel32.inc'
include '%fasminc%\equates\gdi32.inc'
include '%fasminc%\equates\user32.inc'
include '%fasminc%\equates\comctl32.inc' ;comctl32.dll
include '%fasminc%\equates\comdlg32.inc' ;comdlg32.dll
include '%fasminc%\equates\winmm.inc'

include '%fasminc%\equates\directx\d3d9.inc'
include '%fasminc%\equates\directx\d3dx9.inc'

IDI_DIRECTX_ICON = 107

FVF_Flags_TPV = D3DFVF_XYZ or D3DFVF_NORMAL or D3DFVF_DIFFUSE
FVF_Flags_QV  = D3DFVF_XYZ or D3DFVF_NORMAL or D3DFVF_TEX1

struct TEAPOTVERTEX
       x       dd ?
       y       dd ?
       z       dd ?
       nx      dd ?
       ny      dd ?
       nz      dd ?
       diffuse dd ?
ends

struct QUADVERTEX
       x  dd ?
       y  dd ?
       z  dd ?
       nx dd ?
       ny dd ?
       nz dd ?
       tu dd ?
       tv dd ?
ends

section '.data' data readable writeable
  windowclass  db "WINDOWS DIRECT3D CLASS", 0
  windowtitle  db "Direct3D (DX9) - Resize Window", 0
  align 4

  hWnd		      dd 0
  hinstance	      dd 0
  bHandleWindowResize dd TRUE
  bMousing	      dd FALSE
  pVertices	      dd NULL
  fSpinX	      dd 0.0
  fSpinY	      dd 0.0

  align 8
  dCurTime	 dq 0.0
  dLastTime	 dq 0.0

  ptLastMousePosit    POINT
  ptCurrentMousePosit POINT
  icex		      INITCOMMONCONTROLSEX ;structure for Controls

  D3D9INTERFACEPOINTERSSTART = $
  pD3D		IDirect3D9
  pd3dDevice	IDirect3DDevice9
  pVertexBuffer IDirect3DVertexBuffer9
  pTexture	IDirect3DTexture9
  pTeapotMesh	ID3DXMesh

  d3ddm      D3DDISPLAYMODE
  d3dpp      D3DPRESENTPARAMETERS
  teapotMtrl D3DMATERIAL9
  quadMtrl   D3DMATERIAL9
  pLight0    D3DLIGHT9
  sizeof.D3D9INTERFACEPOINTERS = $ - D3D9INTERFACEPOINTERSSTART

  identity	 D3DXMATRIX 1.0, 0.0, 0.0, 0.0,\ ;this data is an indentity matrix
			    0.0, 1.0, 0.0, 0.0,\
			    0.0, 0.0, 1.0, 0.0,\
			    0.0, 0.0, 0.0, 1.0
  matView	 D3DXMATRIX
  matWorld	 D3DXMATRIX
  matRotation	 D3DXMATRIX
  matTranslation D3DXMATRIX
  matProj	 D3DXMATRIX

  STRUCTARRAY quadVertices, QUADVERTEX,\
	<-1.0,	1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0>,\
	< 1.0,	1.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0>,\
	<-1.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0>,\
	< 1.0, -1.0, 0.0, 0.0, 0.0, -1.0, 1.0, 1.0>

section '.code' code writeable executable

;Name: WinMain() - The application's entry point
proc WinMain  hInstance, hPrevInstance, lpCmdLine, nCmdShow
     local wndClass:WNDCLASSEXA, uMsg:MSG

     cinvoke memset, pD3D, 0, sizeof.D3D9INTERFACEPOINTERS

     mov     [icex.dwSize], sizeof.INITCOMMONCONTROLSEX
     mov     [icex.dwICC], $ffff
     invoke  InitCommonControlsEx, icex

     cinvoke memset, addr wndClass, 0, sizeof.WNDCLASSEXA
     invoke  GetModuleHandle, 0
     mov     [hinstance], eax
     mov     [wndClass.hInstance], eax
     mov     [wndClass.lpszClassName], windowclass
     mov     [wndClass.cbSize], sizeof.WNDCLASSEXA
     mov     [wndClass.style], CS_HREDRAW or CS_VREDRAW
     mov     [wndClass.lpfnWndProc], WindowProc
     invoke  LoadIcon, [hinstance], IDI_DIRECTX_ICON
     mov     [wndClass.hIcon], eax
     mov     [wndClass.hIconSm], eax
     invoke  LoadCursor, NULL, IDC_ARROW
     mov     [wndClass.hCursor], eax
     mov     [wndClass.hbrBackground], NULL
     mov     [wndClass.lpszMenuName], NULL
     mov     [wndClass.cbClsExtra], 0
     mov     [wndClass.cbWndExtra], 0

     invoke  RegisterClassEx, addr wndClass
     .if     eax = NULL
	     invoke  MessageBox, NULL, "RegisterClassEx()", "ERROR", MB_OK or MB_ICONERROR
	     return  FALSE
     .endif

     invoke  CreateWindowEx, NULL, windowclass, windowtitle, WS_OVERLAPPEDWINDOW or\
	     WS_VISIBLE, 0, 0, 640, 480, NULL, NULL, [hinstance], NULL
     .if     eax = NULL
	     invoke  MessageBox, NULL, "CreateWindowEx()", "ERROR", MB_OK or MB_ICONERROR
	     return  FALSE
     .endif
     mov     [hWnd], eax

     call    oneTimeSystemInit
     mov     [uMsg.message], TRUE
     .while  [uMsg.message] <> WM_QUIT
	     invoke  PeekMessage, addr uMsg, NULL, 0, 0, PM_REMOVE
	     .if     eax <> NULL
		     invoke  TranslateMessage, addr uMsg
		     invoke  DispatchMessage, addr uMsg
	     .else
		     call    D3DRender
	     .endif
     .endw
     call    D3DShutDown

     invoke  ExitProcess, 0
     return
endp

proc WindowProc  hWnd, msg, wParam, lParam
     .if     [msg] = WM_KEYDOWN
	     .if     [wParam] = VK_ESCAPE
		     invoke  PostQuitMessage, 0

	     .elseif [wParam] = VK_F1
		     not     [bHandleWindowResize]
	     .endif
	     return  0

     .elseif [msg] = WM_LBUTTONDOWN
	     mov     eax, [lParam]
	     mov     ecx, [lParam]
	     and     eax, $ffff
	     shr     ecx, 16
	     mov     [ptLastMousePosit.x], eax
	     mov     [ptCurrentMousePosit.x], eax
	     mov     [ptLastMousePosit.y], ecx
	     mov     [ptCurrentMousePosit.y], ecx
	     mov     [bMousing], TRUE
	     return  0

     .elseif [msg] = WM_LBUTTONUP
	      mov     [bMousing], FALSE
	      return  0

     .elseif [msg] = WM_MOUSEMOVE
	     finit
	     mov     eax, [lParam]
	     mov     ecx, [lParam]
	     and     eax, $ffff
	     shr     ecx, 16
	     mov     [ptCurrentMousePosit.x], eax
	     mov     [ptCurrentMousePosit.y], ecx

	     .if     [bMousing] = TRUE
		     fld     [fSpinX]
		     fild    [ptCurrentMousePosit.x]
		     fisub   [ptLastMousePosit.x]
		     fsubp
		     fstp    [fSpinX]

		     fld     [fSpinY]
		     fild    [ptCurrentMousePosit.y]
		     fisub   [ptLastMousePosit.y]
		     fsubp
		     fstp    [fSpinY]
	     .endif

	     mov     eax, [ptCurrentMousePosit.x]
	     mov     ecx, [ptCurrentMousePosit.y]
	     mov     [ptLastMousePosit.x], eax
	     mov     [ptLastMousePosit.y], ecx
	     return  0

     .elseif [msg] = WM_SIZE
	     .if     [bHandleWindowResize] = TRUE
		     ;If the device is not NULL and the WM_SIZE message is not a
		     ;SIZE_MINIMIZED event, resize the device's swap buffers to match
		     ;the new window size.
		     .if     [pd3dDevice] <> NULL & [wParam] <> SIZE_MINIMIZED
			     call    invalidateDeviceObjects
			     mov     eax, [lParam]
			     mov     ecx, [lParam]
			     and     eax, $ffff
			     shr     ecx, 16
			     mov     [d3dpp.BackBufferWidth], eax
			     mov     [d3dpp.BackBufferHeight], ecx
			     D3DCALL pd3dDevice, Reset, d3dpp
			     .if     eax = D3DERR_INVALIDCALL
				     invoke  MessageBox, NULL,\
					     "Call to Reset() failed with D3DERR_INVALIDCALL! ",\
					     "ERROR", MB_OK or MB_ICONERROR
			     .endif
			     call    restoreDeviceObjects
		     .endif
	     .endif
	     return  0

     .elseif [msg] = WM_CLOSE
	     invoke  PostQuitMessage, 0
	     return  0

     .elseif [msg] = WM_DESTROY
	     invoke  PostQuitMessage, 0
	     return  0
     .endif

     ;DefWindowProc process all other messages that we don't want
     invoke  DefWindowProc, [hWnd], [msg], [wParam], [lParam]
     return
endp

;Name: oneTimeSystemInit()
;Desc: This function will only be called once during the application's
;      initialization phase. Therefore, it can't contain any resources that
;      need to be restored every time the Direct3D device is lost or the
;      window is resized.
proc oneTimeSystemInit test

     invoke  Direct3DCreate9, D3D_SDK_VERSION
     .if     eax = NULL
	     invoke  MessageBox, NULL, "Direct3DCreate9()", "ERROR", MB_OK or MB_ICONERROR
	     invoke  PostQuitMessage, 0
	     return  FALSE
     .endif
     mov     [pD3D], eax

     D3DCALL pD3D, GetAdapterDisplayMode, D3DADAPTER_DEFAULT, d3ddm
     .if     eax <> D3D_OK
	     invoke  MessageBox, HWND_DESKTOP, "D3D->GetAdapterDisplayMode()", "ERROR",\
		     MB_OK or MB_ICONERROR
	     invoke  PostQuitMessage, 0
	     return
     .endif

     mov     [d3dpp.Windowed], TRUE
     mov     [d3dpp.SwapEffect], D3DSWAPEFFECT_DISCARD
     mov     eax, [d3ddm.Format]
     mov     [d3dpp.BackBufferFormat], eax
     mov     [d3dpp.EnableAutoDepthStencil], TRUE
     mov     [d3dpp.AutoDepthStencilFormat], D3DFMT_D16
     mov     [d3dpp.Presentation_Interval], D3DPRESENT_INTERVAL_IMMEDIATE

     D3DCALL pD3D, CreateDevice, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, [hWnd],\
	     D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp, pd3dDevice
     .if     eax <> D3D_OK | [pd3dDevice] = NULL
	     invoke  MessageBox, [hWnd], "D3D->CreateDevice()", "ERROR", MB_OK or MB_ICONERROR
	     invoke  PostQuitMessage, 0
	     return
     .endif

     ;Setup a material for the teapot
     finit
     fldz
     fstp    [teapotMtrl.Diffuse.r]
     fld1
     fst     [teapotMtrl.Diffuse.g]
     fst     [teapotMtrl.Diffuse.b]
     fst     [teapotMtrl.Diffuse.a]
     fst     [teapotMtrl.Specular.r]
     fst     [teapotMtrl.Specular.g]
     fst     [teapotMtrl.Specular.b]
     fstp    [teapotMtrl.Specular.a]
     fldd    40.0
     fstp    [teapotMtrl.Power]

     ;Setup a material for the textured quad
     fld1
     fst     [quadMtrl.Diffuse.r]
     fst     [quadMtrl.Diffuse.g]
     fst     [quadMtrl.Diffuse.b]
     fst     [quadMtrl.Diffuse.a]
     fst     [quadMtrl.Specular.r]
     fst     [quadMtrl.Specular.g]
     fst     [quadMtrl.Specular.b]
     fstp    [quadMtrl.Specular.a]
     fldd    40.0
     fstp    [quadMtrl.Power]

     ;Setup a simple directional light and some ambient
     mov     [pLight0.Type], D3DLIGHT_DIRECTIONAL
     fld1
     fstp    [pLight0.Direction.x]
     fldz
     fstp    [pLight0.Direction.y]
     fld1
     fst     [pLight0.Direction.z]
     fst     [pLight0.Diffuse.r]
     fst     [pLight0.Diffuse.g]
     fst     [pLight0.Diffuse.b]
     fst     [pLight0.Diffuse.a]
     fst     [pLight0.Specular.r]
     fst     [pLight0.Specular.g]
     fst     [pLight0.Specular.b]
     fstp    [pLight0.Specular.a]

     ;Any resources or settings that need to be restored after losing the
     ;DirectD device should probably be grouped together into one function so
     ;they can be re-created or reset in one call.
     call    restoreDeviceObjects
     return
endp

proc D3DRender
     local tempa:DWORD, tempb:DWORD

     finit
     D3DCALL pd3dDevice, Clear, 0, NULL, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER, $ff5987B3, 1.0, 0

     ;Render a teapot and a textured quad...
     D3DCALL pd3dDevice, BeginScene

     ;D3DXMatrixIdentity(&matView)
     cinvoke memcpy, matView, identity, sizeof.D3DXMATRIX
     D3DCALL pd3dDevice, SetTransform, D3DTS_VIEW, matView

     ;Place and render first teapot...
     fldq    0.01745329252 ;pi/180
     fld     st0
     fmul    [fSpinX]
     fstp    [tempa]
     fmul    [fSpinY]
     fstp    [tempb]
     invoke  D3DXMatrixRotationYawPitchRoll, matRotation, [tempa], [tempb], 0.0
     invoke  D3DXMatrixTranslation, matTranslation, 1.5, 0.0, 5.0
     invoke  D3DXMatrixMultiply, matWorld, matRotation, matTranslation

     D3DCALL pd3dDevice, SetTransform, D3DTS_WORLD, matWorld
     D3DCALL pd3dDevice, SetMaterial, teapotMtrl
     D3DCALL pTeapotMesh, DrawSubset, 0

     ;Place and render textured quad...
     invoke  D3DXMatrixTranslation, matTranslation, -1.5, 0.0, 5.0
     invoke  D3DXMatrixMultiply, matWorld, matRotation, matTranslation
     D3DCALL pd3dDevice, SetTransform, D3DTS_WORLD, matWorld

     D3DCALL pd3dDevice, SetMaterial, quadMtrl
     D3DCALL pd3dDevice, SetTexture, 0, [pTexture]
     D3DCALL pd3dDevice, SetStreamSource, 0, [pVertexBuffer], 0, sizeof.QUADVERTEX
     D3DCALL pd3dDevice, SetFVF, FVF_Flags_QV
     D3DCALL pd3dDevice, DrawPrimitive, D3DPT_TRIANGLESTRIP, 0, 2

     D3DCALL pd3dDevice, EndScene
     D3DCALL pd3dDevice, Present, NULL, NULL, NULL, NULL

     return
endp

proc D3DShutDown
     local strError[255]:BYTE

     call    invalidateDeviceObjects

     .if     [pd3dDevice] <> NULL
	     D3DCALL pd3dDevice, Release
	     .if     eax > 0
		     cinvoke sprintf, addr strError,\
			     <"The device object failed to cleanup properly.",10,13,\
			     "Release() returned a reference count of %d",10,13>, eax
		     invoke  MessageBox, [hWnd], addr strError, "ERROR", MB_OK or MB_ICONERROR
	     .endif
	     mov     [pd3dDevice], NULL
     .endif

     .if     [pD3D] <> NULL
	     D3DCALL pD3D, Release
	     mov     [pD3D], NULL
     .endif
     return
endp

;Name: restoreDeviceObjects()
;Desc: You are encouraged to develop applications with a single code path to
;      respond to device loss. This code path is likely to be similar, if not
;      identical, to the code path taken to initialize the device at startup.
proc restoreDeviceObjects
     local tempa:DWORD

     ;Set some important state settings...
     fldd    640.0
     fldd    480.0
     fdivp
     fstp    [tempa]
     invoke  D3DXMatrixPerspectiveFovLH, matProj, 45.0, [tempa], 0.1, 100.0

     D3DCALL pd3dDevice, SetTransform, D3DTS_PROJECTION, matProj
     D3DCALL pd3dDevice, SetRenderState, D3DRS_ZENABLE, TRUE
     D3DCALL pd3dDevice, SetRenderState, D3DRS_LIGHTING, TRUE
     D3DCALL pd3dDevice, SetRenderState, D3DRS_SPECULARENABLE, TRUE
     D3DCALL pd3dDevice, SetLight, 0, pLight0
     D3DCALL pd3dDevice, LightEnable, 0, TRUE
     D3DCALL pd3dDevice, SetRenderState, D3DRS_AMBIENT, $ff333333

     ;Create a texture object...
     invoke  D3DXCreateTextureFromFile, [pd3dDevice], "test.bmp", pTexture
     .if     eax <> D3D_OK | [pTexture] = NULL
	     invoke  MessageBox, [hWnd], "D3DXCreateTextureFromFile()", "ERROR",\
		     MB_OK or MB_ICONERROR
	     invoke  PostQuitMessage, 0
	     return
     .endif

     D3DCALL pd3dDevice, SetSamplerState, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR
     D3DCALL pd3dDevice, SetSamplerState, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR

     ;Create a vertex buffer...
     ;NOTE: When a device is lost, vertex buffers created using
     ;D3DPOOL_DEFAULT must be released properly before calling
     ;IDirect3DDevice9::Reset.
     D3DCALL pd3dDevice, CreateVertexBuffer, 4*sizeof.QUADVERTEX, D3DUSAGE_WRITEONLY,\
	     FVF_Flags_QV, D3DPOOL_DEFAULT, pVertexBuffer, NULL
     .if     eax <> D3D_OK | [pVertexBuffer] = NULL
	     invoke  MessageBox, [hWnd], "pd3dDevice->CreateVertexBuffer()", "ERROR",\
		     MB_OK or MB_ICONERROR
	     invoke  PostQuitMessage, 0
	     return
     .endif

     D3DCALL pVertexBuffer, Lock, 0, 4*sizeof.QUADVERTEX, pVertices, 0
     .if     eax <> D3D_OK | [pVertices] = NULL
	     invoke  MessageBox, [hWnd], "pVertexBuffer->Lock()", "ERROR", MB_OK or MB_ICONERROR
	     invoke  PostQuitMessage, 0
	     return
     .endif

     cinvoke memcpy, [pVertices], quadVertices, 4*sizeof.QUADVERTEX
     D3DCALL pVertexBuffer, Unlock

     ;Create a mesh object...
     ;NOTE: When a device is lost, meshes created using D3DXMESH_DYNAMIC
     ;must be released properly before calling IDirect3DDevice9::Reset.
     invoke  D3DXLoadMeshFromX, "teapot.x", D3DXMESH_DYNAMIC, [pd3dDevice], NULL, NULL, NULL,\
	     NULL, pTeapotMesh
     .if     eax <> D3D_OK | [pTeapotMesh] = NULL
	     invoke  MessageBox, [hWnd], "D3DXLoadMeshFromX()", "ERROR", MB_OK or MB_ICONERROR
	     invoke  PostQuitMessage, 0
	     return
     .endif

     return
endp

;Name: invalidateDeviceObjects()
;Desc: If the lost device can be restored, the application prepares the
;      device by destroying all video-memory resources and any
;      swap chains. This is typically accomplished by using the SAFE_RELEASE
;      macro.
proc invalidateDeviceObjects
     local strError[256]:BYTE
     ;To see how mismanagement of an object's reference counter can cause us
     ;problems when calling Reset on the device, uncomment the line below.
     ;The line below will call AddRef() on the vertex buffer object, which will
     ;add one to the vertex buffer's reference count. This will cause it
     ;to hang around after we call Release() on it, which is not what we
     ;wanted to happen here.
     ;D3DCALL pVertexBuffer, AddRef
     ;
     ;NOTE: You could use the SAFE_RELEASE macro to invalidate your device
     ;      objects like so:
     ;
     ;D3DCALL pTexture, Release
     ;D3DCALL pVertexBuffer, Release
     ;D3DCALL pTeapotMesh, Release
     ;
     ;But I've chosen a more verbose method (below) which I feel is better
     ;for understanding how the reference counting system can be used to
     ;indentify potential problems.

     ;Invalidate the texture object...
     .if     [pTexture] <> NULL
	     D3DCALL pTexture, Release
	     .if     eax > 0
		     cinvoke sprintf, addr strError,\
			     <"The texture object failed to Release properly.",10,13,\
			      "Release() returned a reference count of %d",10,13>, eax
		     invoke  MessageBox, [hWnd], addr strError, "ERROR", MB_OK or MB_ICONERROR
	     .endif
	     mov     [pTexture], NULL
     .endif

     ;Invalidate the vertex buffer object...
     .if     [pVertexBuffer] <> NULL
	     D3DCALL pVertexBuffer, Release
	     .if     eax > 0
		     cinvoke sprintf, addr strError,\
			     <"The vertex buffer object failed to Release properly.",10,13,\
			      "Release() returned a reference count of %d",10,13>, eax
		     invoke  MessageBox, [hWnd], addr strError, "ERROR", MB_OK or MB_ICONERROR
	     .endif
	     mov     [pVertexBuffer], NULL
     .endif

     ;Invalidate the mesh object...
     .if     [pTeapotMesh] <> NULL
	     D3DCALL pTeapotMesh, Release
	     .if     eax > 0
		     cinvoke sprintf, addr strError,\
			     <"The mesh object failed to Release properly.",10,13,\
			      "Release() returned a reference count of %d",10,13>, eax
		     invoke  MessageBox, [hWnd], addr strError, "ERROR", MB_OK or MB_ICONERROR
	     .endif
	     mov     [pTeapotMesh], NULL
     .endif

     return  S_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_DIRECTX_ICON, LANG_NEUTRAL, main_icon

  icon	  main_icon, icon_data, 'codesampler.ico'

  resdata winxp
	  file '%fasminc%\winxpstyle.xml'
  endres

section '.idata' import data readable writeable

  library kernel32,'KERNEL32.DLL',\
	  user32,'USER32.DLL',\
	  gdi32,'GDI32.DLL',\
	  winmm,'WINMM.DLL',\
	  comctl32,'COMCTL32.DLL',\
	  comdlg32,'COMDLG32.DLL',\
	  msvcrt, 'MSVCRT.DLL',\
	  d3d9,'D3D9.DLL',\
	  d3dx9_24,'D3DX9_24.DLL'

  include '%fasminc%/apia/kernel32.inc'
  include '%fasminc%/apia/user32.inc'
  include '%fasminc%/apia/gdi32.inc'
  include '%fasminc%/apia/winmm.inc'
  include '%fasminc%/apia/comctl32.inc'
  include '%fasminc%/apia/comdlg32.inc'
  include '%fasminc%/apia/msvcrt.inc'
  include '%fasminc%/apia/directx/d3d9.inc'
  include '%fasminc%/apia/directx/d3dx9_24.inc'
