//AndreyCh 28.06.2006
//http://pascal.vov.ru/
//sofandr@mail.ru


#pragma option w32     //создание Windows GUI EXE.
//#pragma option J0      //не включать startup code.
#pragma option w       //Включить предупреждение.
//#pragma option DBG     //отладочная инфа
//#pragma option oir-    //отключение оптимизации
#pragma option ba-     //поэлементная адресация массива
//  
//  
#include <Windows.h>         // включаем заголовочный файл Windows
#include <d3dtypes.h>


#define D3D_SDK_VERSION 31



extern WINAPI "D3D9.DLL"{
Direct3DCreate9(UINT SDKVersion);
}

WNDCLASSEX wc;
DWORD hInstance;
MSG msg;
DWORD hWnd;

char sClassName="D3D9 Sample";
char sTitle="D3D9 Window";


//IUnknown methods
struct IDirect3D9 {

    /*** IUnknown methods ***/
  long stdcall (*QueryInterface)();
  long stdcall (*AddRef)();
  long stdcall (*Release)();

    /*** IDirect3D9 methods ***/
  long stdcall (*RegisterSoftwareDevice)();
  long stdcall (*GetAdapterCount)();
  long stdcall (*GetAdapterIdentifier)();
  long stdcall (*GetAdapterModeCount)();
  long stdcall (*EnumAdapterModes)();
  long stdcall (*GetAdapterDisplayMode)();
  long stdcall (*CheckDeviceType)();
  long stdcall (*CheckDeviceFormat)();
  long stdcall (*CheckDeviceMultiSampleType)();
  long stdcall (*CheckDepthStencilMatch)();
  long stdcall (*CheckDeviceFormatConversion)();
  long stdcall (*GetDeviceCaps)();
  long stdcall (*GetAdapterMonitor)();
  long stdcall (*CreateDevice)();

};

//IUnknown methods
struct IDirect3DDevice9
{
    /*** IUnknown methods ***/
  long stdcall (*QueryInterface)();
  long stdcall (*AddRef)();
  long stdcall (*Release)();


    /*** IDirect3DDevice9 methods ***/
  long stdcall (*TestCooperativeLevel)();
  long stdcall (*GetAvailableTextureMem)();
  long stdcall (*EvictManagedResources)();
  long stdcall (*GetDirect3D)();
  long stdcall (*GetDeviceCaps)();
  long stdcall (*GetDisplayMode)();
  long stdcall (*GetCreationParameters)();
  long stdcall (*SetCursorProperties)();
  long stdcall (*SetCursorPosition)();
  long stdcall (*ShowCursor)();
  long stdcall (*CreateAdditionalSwapChain)();
  long stdcall (*GetSwapChain)();
  long stdcall (*GetNumberOfSwapChains)();
  long stdcall (*Reset)();
  long stdcall (*Present)();
  long stdcall (*GetBackBuffer)();
  long stdcall (*GetRasterStatus)();
  long stdcall (*SetDialogBoxMode)();
  long stdcall (*SetGammaRamp)();
  long stdcall (*GetGammaRamp)();
  long stdcall (*CreateTexture)();
  long stdcall (*CreateVolumeTexture)();
  long stdcall (*CreateCubeTexture)();
  long stdcall (*CreateVertexBuffer)();
  long stdcall (*CreateIndexBuffer)();
  long stdcall (*CreateRenderTarget)();
  long stdcall (*CreateDepthStencilSurface)();
  long stdcall (*UpdateSurface)();
  long stdcall (*UpdateTexture)();
  long stdcall (*GetRenderTargetData)();
  long stdcall (*GetFrontBufferData)();
  long stdcall (*StretchRect)();
  long stdcall (*ColorFill)();
  long stdcall (*CreateOffscreenPlainSurface)();
  long stdcall (*SetRenderTarget)();
  long stdcall (*GetRenderTarget)();
  long stdcall (*SetDepthStencilSurface)();
  long stdcall (*GetDepthStencilSurface)();
  long stdcall (*BeginScene)();
  long stdcall (*EndScene)();
  long stdcall (*Clear)();
  long stdcall (*SetTransform)();
  long stdcall (*GetTransform)();
  long stdcall (*MultiplyTransform)();
  long stdcall (*SetViewport)();
  long stdcall (*GetViewport)();
  long stdcall (*SetMaterial)();
  long stdcall (*GetMaterial)();
  long stdcall (*SetLight)();
  long stdcall (*GetLight)();
  long stdcall (*LightEnable)();
  long stdcall (*GetLightEnable)();
  long stdcall (*SetClipPlane)();
  long stdcall (*GetClipPlane)();
  long stdcall (*SetRenderState)();
  long stdcall (*GetRenderState)();
  long stdcall (*CreateStateBlock)();
  long stdcall (*BeginStateBlock)();
  long stdcall (*EndStateBlock)();
  long stdcall (*SetClipStatus)();
  long stdcall (*GetClipStatus)();
  long stdcall (*GetTexture)();
  long stdcall (*SetTexture)();
  long stdcall (*GetTextureStageState)();
  long stdcall (*SetTextureStageState)();
  long stdcall (*GetSamplerState)();
  long stdcall (*SetSamplerState)();
  long stdcall (*ValidateDevice)();
  long stdcall (*SetPaletteEntries)();
  long stdcall (*GetPaletteEntries)();
  long stdcall (*SetCurrentTexturePalette)();
  long stdcall (*GetCurrentTexturePalette)();
  long stdcall (*SetScissorRect)();
  long stdcall (*GetScissorRect)();
  long stdcall (*SetSoftwareVertexProcessing)();
  long stdcall (*GetSoftwareVertexProcessing)();
  long stdcall (*SetNPatchMode)();
  long stdcall (*GetNPatchMode)();
  long stdcall (*DrawPrimitive)();
  long stdcall (*DrawIndexedPrimitive)();
  long stdcall (*DrawPrimitiveUP)();
  long stdcall (*DrawIndexedPrimitiveUP)();
  long stdcall (*ProcessVertices)();
  long stdcall (*CreateVertexDeclaration)();
  long stdcall (*SetVertexDeclaration)();
  long stdcall (*GetVertexDeclaration)();
  long stdcall (*SetFVF)();
  long stdcall (*GetFVF)();
  long stdcall (*CreateVertexShader)();
  long stdcall (*SetVertexShader)();
  long stdcall (*GetVertexShader)();
  long stdcall (*SetVertexShaderConstantF)();
  long stdcall (*GetVertexShaderConstantF)();
  long stdcall (*SetVertexShaderConstantI)();
  long stdcall (*GetVertexShaderConstantI)();
  long stdcall (*SetVertexShaderConstantB)();
  long stdcall (*GetVertexShaderConstantB)();
  long stdcall (*SetStreamSource)();
  long stdcall (*GetStreamSource)();
  long stdcall (*SetStreamSourceFreq)();
  long stdcall (*GetStreamSourceFreq)();
  long stdcall (*SetIndices)();
  long stdcall (*GetIndices)();
  long stdcall (*CreatePixelShader)();
  long stdcall (*SetPixelShader)();
  long stdcall (*GetPixelShader)();
  long stdcall (*SetPixelShaderConstantF)();
  long stdcall (*GetPixelShaderConstantF)();
  long stdcall (*SetPixelShaderConstantI)();
  long stdcall (*GetPixelShaderConstantI)();
  long stdcall (*SetPixelShaderConstantB)();
  long stdcall (*GetPixelShaderConstantB)();
  long stdcall (*DrawRectPatch)();
  long stdcall (*DrawTriPatch)();
  long stdcall (*DeletePatch)();
  long stdcall (*CreateQuery)();
};

struct IDirect3DVertexBuffer9 
{
    /*** IUnknown methods ***/
    /*** IUnknown methods ***/
  long stdcall (*QueryInterface)();
  long stdcall (*AddRef)();
  long stdcall (*Release)();

    /*** IDirect3DResource9 methods ***/
   long stdcall (*GetDevice)();
   long stdcall (*SetPrivateData)();
   long stdcall (*GetPrivateData)();
   long stdcall (*FreePrivateData)();
   long stdcall (*SetPriority)();
   long stdcall (*GetPriority)();
   long stdcall (*PreLoad)();
   long stdcall (*GetType)();
   long stdcall (*Lock)();
   long stdcall (*Unlock)();
   long stdcall (*GetDesc)();

};


/* Resize Optional Parameters */
struct D3DPRESENT_PARAMETERS
{
    UINT                BackBufferWidth;
    UINT                BackBufferHeight;
//    D3DFORMAT           BackBufferFormat;
    DWORD            BackBufferFormat;

    UINT                BackBufferCount;

//    D3DMULTISAMPLE_TYPE MultiSampleType;
    DWORD               MultiSampleType;

    DWORD               MultiSampleQuality;

//    D3DSWAPEFFECT       SwapEffect;
    DWORD               SwapEffect;

    HWND                hDeviceWindow;
    BOOL                Windowed;
    BOOL                EnableAutoDepthStencil;
//    D3DFORMAT           AutoDepthStencilFormat;
    DWORD               AutoDepthStencilFormat;

    DWORD               Flags;

    /* FullScreen_RefreshRateInHz must be zero for Windowed mode */
    UINT                FullScreen_RefreshRateInHz;
    UINT                PresentationInterval;
};


struct CUSTOMVERTEX  {
float	x;	
float	y;	
float	z;	
float	rhw;	
DWORD	color;	
};

struct VERTICES {
CUSTOMVERTEX vertice0;
CUSTOMVERTEX vertice1;
CUSTOMVERTEX vertice2;
};

VERTICES vertices={
200.0f,  50.0f, 0.5f, 1.0f, 0ffff0000h, 
350.0f, 350.0f, 0.5f, 1.0f, 0ff00ff00h, 
50.0f,  350.0f, 0.5f, 1.0f, 0ff00ffffh 
};


#define D3DSWAPEFFECT_DISCARD 1
#define D3DFMT_UNKNOWN  0
#define D3DDEVTYPE_HAL  1
#define D3DCREATE_SOFTWARE_VERTEXPROCESSING     0x00000020L
#define D3DADAPTER_DEFAULT                     0
#define D3DPOOL_DEFAULT  0
#define D3D_OK 0h


DWORD  D3D;
DWORD  D3DDevice;
DWORD  D3DVB;
D3DPRESENT_PARAMETERS d3dpp;
DWORD pVertices;

DWORD InitD3D()
{
	Direct3DCreate9(D3D_SDK_VERSION);
	if (EAX==0)
		return;
	
	D3D=EAX;

	EAX=#d3dpp;
	RtlZeroMemory(EAX, sizeof(D3DPRESENT_PARAMETERS));
	d3dpp.Windowed=TRUE;
	d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat=D3DFMT_UNKNOWN;
	EAX=#d3dpp;

	$push ebx

	EBX = D3D; EBX = DSDWORD[EBX];
	EBX.IDirect3D9.CreateDevice(D3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, EAX, #D3DDevice);

	$pop ebx

	IF  (EAX!=D3D_OK){
		$XOR EAX, EAX
		RETURN;
            }


	$push ebx

	EBX = D3DDevice; EBX = DSDWORD[EBX];
	EBX.IDirect3DDevice9.CreateVertexBuffer(D3DDevice, sizeof(vertices), 0, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, D3DPOOL_DEFAULT, #D3DVB, 0);

	$pop ebx

	IF  (EAX!=D3D_OK){
		$XOR EAX, EAX
		RETURN;
            }

	$push ebx

	EAX=#pVertices;
	EBX = D3DVB; EBX = DSDWORD[EBX];
        EBX.IDirect3DVertexBuffer9.Lock(D3DVB, 0, sizeof(vertices), EAX, 0);

	$pop ebx

	IF  (EAX!=D3D_OK){
		$XOR EAX, EAX
		RETURN;
            }

	RtlMoveMemory(pVertices, #vertices, sizeof(vertices));

	$push ebx

	EBX = D3DVB; EBX = DSDWORD[EBX];
        EBX.IDirect3DVertexBuffer9.Unlock(D3DVB);

	$pop ebx

	EAX=1;


}



ReleaseD3D()
{
	$push ebx

		IF(D3DVB != 0) {
			EBX = D3DVB; EBX = DSDWORD[EBX];
			EBX.IDirectDrawSurface.Release(D3DVB);
			D3DVB = 0;
		}

		IF(D3DDevice != 0) {
			EBX = D3DDevice; EBX = DSDWORD[EBX];
			EBX.IDirectDrawSurface.Release(D3DDevice);
                        D3DDevice = 0;
		}

		IF(D3D != 0) {
			EBX = D3D; EBX = DSDWORD[EBX];
			EBX.IDirectDrawSurface.Release(D3D);
                        D3D = 0;
		}



	$pop ebx
}




//D3DCOLOR_XRGB D3DCOLOR_BLUE={0xff, 0, 0, 255};
//DWORD D3DCOLOR_BLUE=0xFF0000FF;
//#define RGBA_MAKE(r,g,b,a)   a<<8|r<<8|g<<8|b
DWORD D3DCOLOR_BLUE=RGBA_MAKE(0,0,255,255);
Render(){

	EBX = D3DDevice; EBX = DSDWORD[EBX];
	EBX.IDirect3DDevice9.Clear(D3DDevice, 0, 0, D3DCLEAR_TARGET, D3DCOLOR_BLUE, 1.0f, 0);
	//------------------------------------


	EBX = D3DDevice; EBX = DSDWORD[EBX];
        EBX.IDirect3DDevice9.BeginScene(D3DDevice);

	EBX = D3DDevice; EBX = DSDWORD[EBX];
        EBX.IDirect3DDevice9.SetStreamSource(D3DDevice, 0, D3DVB, 0, sizeof(CUSTOMVERTEX));

	EBX = D3DDevice; EBX = DSDWORD[EBX];
        EBX.IDirect3DDevice9.SetFVF(D3DDevice, D3DFVF_XYZRHW | D3DFVF_DIFFUSE );

	EBX = D3DDevice; EBX = DSDWORD[EBX];
        EBX.IDirect3DDevice9.DrawPrimitive(D3DDevice, D3DPT_TRIANGLELIST, 0, 1 );


	EBX = D3DDevice; EBX = DSDWORD[EBX];
        EBX.IDirect3DDevice9.EndScene(D3DDevice);






	//------------------------------------
	EBX = D3DDevice; EBX = DSDWORD[EBX];
	EBX.IDirect3DDevice9.Present(D3DDevice, 0, 0, 0, 0);

}

WndProc(DWORD hWnd, uMsg, wParam, lParam)
{
	EAX=uMsg;
	IF (EAX==WM_DESTROY) {
		PostQuitMessage(0);
		$XOR EAX, EAX;
		RETURN;
	}

        RETURN (DefWindowProc(hWnd, uMsg, wParam, lParam));

}

main()
{
	GetModuleHandle(0); 
	wc.cbSize=sizeof(WNDCLASSEX);
	wc.style=CS_CLASSDC;
	wc.lpfnWndProc=#WndProc;
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hInstance=EAX;
	wc.hIcon=0;
	wc.hCursor=0;
	wc.hbrBackground=0;
	wc.lpszMenuName=0;
	wc.lpszClassName=#sClassName;
	wc.hIconSm=0;
	RegisterClassEx(#wc);

	CreateWindowEx( 0, #sClassName, #sTitle, WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 512, 512, 0, 0, hInstance, 0);
	hWnd=EAX;

	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);

	InitD3D();
	IF (EAX!=1) GOTO Exit;




    do {
	IF(PeekMessage(#msg, NULL, 0, 0, PM_REMOVE)) {
	    TranslateMessage(#msg);
	    DispatchMessageA(#msg);
	}

	// this does all the graphics update
	Render();

    } while(msg.message != WM_QUIT);

Exit:

    // Deinit 
ReleaseD3D();


    ExitProcess(0);


} 

