/*
	File	:	directx.cpp
	Author	:	Richard Flower (c) 1998 Core Design
	----------------------------------------------------------------------------------
	Functions
	----------------------------------------------------------------------------------

	DXGetDeviceInfo					-	Get available Device Info
	DXFreeDeviceInfo				-	Free Device Info 
	DXEnumDirectDraw				-	DirectDraw Enumeration Function
	DXBitMask2ShiftCnt				-	Get bits and shift cnt from bitmask
	DXEnumDisplayModes				-	Display mode Enumeration
	DXEnumDirect3D					-	Direct3D Enumeration
	DXEnumTextureFormats			-	Direct3D Device Texture Format Enumeration
	BPPToDDBD						-	Convert bpp to DDBD
	DXFindDevice					-	TEMPORARY ** WON'T WORK PROPERLY ON MULTIPLE HW CONFIGS **
	DXCreateDirectDraw2				-	Create DirectDraw2 Interface
	DXCreateDirect3D2				-	Create Direct3D2 Interface
	DXSetCooperativeLevel			-	Set Cooperative Level
	DXSetVideoMode					-	Set Video Mode
	DXCreateSurface					-	Create DirectDraw Surface
	DXGetAttachedSurface			-	Get Attached Surface
	DXCreateDirect3DDevice			-	Create Direct3D Device
	DXCreateViewPort				-	Create Viewport
	DXGetSurfaceDescription			-	Fill DDSURFACEDESC
  
	----------------------------------------------------------------------------------
*/


//#define DISABLESOFTWARE


#include "standard.h"
#include "directx.h"

// Globals For Enumeration

static LPDIRECTDRAW2		lpDD2;
static LPDIRECT3D2			lpD3D2;
static LPDIRECTDRAWSURFACE3 lpDDSurface;
static LPDIRECT3DDEVICE2	lpD3DDevice;
static HWND					WindowHandle;
static bool bSoftRend = false;

/*
	Function	:	DXGetDeviceInfo
	Useage		:	Fill passed DDDEVICE structure with DD info
*/

void DXGetDeviceInfo(DEVICEINFO* dd,HWND hWnd)
{
	WindowHandle = hWnd;	
	memset(dd,0,sizeof(DEVICEINFO));
	DirectDrawEnumerate(DXEnumDirectDraw,dd);
}

// EOF : DXGetDeviceInfo



/*
	Function	:	DXFreeDeviceInfo
	Useage		:	Free passed DDDEVICE structure
*/

void DXFreeDeviceInfo(DEVICEINFO* dd)
{
	int n,i;

	for(n=0;n<dd->nDDInfo;n++)
	{
		for(i=0;i<dd->DDInfo[n].nD3DInfo;i++)
		{
			free(dd->DDInfo[n].D3DInfo[i].DisplayMode);
			free(dd->DDInfo[n].D3DInfo[i].Texture);		
		}

		free(dd->DDInfo[n].D3DInfo);		
		free(dd->DDInfo[n].DisplayMode);
	}

	free(dd->DDInfo);		

	memset(dd,0,sizeof(DEVICEINFO));
}

// EOF : DXFreeDeviceInfo



/*
	Function	:	DirectDrawEnumerateCallback
	Useage		:	Enumeration of DirectDraw Devices
*/

BOOL CALLBACK DXEnumDirectDraw(GUID FAR* lpGuid,LPSTR lpDeviceDesc,LPSTR lpDeviceName,LPVOID lpContext)
{
	DEVICEINFO*		 dd;
	
	dd = (DEVICEINFO*) lpContext;

	// Allocate Device Structure
	if(dd->nDDInfo == 0)
		dd->DDInfo = (DIRECTDRAWINFO*) malloc(sizeof(DIRECTDRAWINFO));
	else		
		dd->DDInfo = (DIRECTDRAWINFO*) realloc(dd->DDInfo,sizeof(DIRECTDRAWINFO)*(dd->nDDInfo+1));

	// Clear Structure
	memset(&dd->DDInfo[dd->nDDInfo],0,sizeof(DIRECTDRAWINFO));
	
	// Store DirectDraw Info	
	if(lpGuid==NULL)
		dd->DDInfo[dd->nDDInfo].lpGuid = NULL;
	else
	{
		dd->DDInfo[dd->nDDInfo].lpGuid = &dd->DDInfo[dd->nDDInfo].Guid;
		memcpy(&dd->DDInfo[dd->nDDInfo].Guid,lpGuid,sizeof(GUID));
	}

	lstrcpy(dd->DDInfo[dd->nDDInfo].About,lpDeviceDesc);
    lstrcpy(dd->DDInfo[dd->nDDInfo].Name,lpDeviceName);
	
	// Create DD Device To Get Caps
	
	LPDIRECTDRAW lpDDTemp;
	DirectDrawCreate(lpGuid,&lpDDTemp,NULL);
    lpDDTemp->QueryInterface(IID_IDirectDraw2,(LPVOID*)&lpDD2);
	DXRelease(lpDDTemp);

	dd->DDInfo[dd->nDDInfo].DDCaps.dwSize = sizeof(DDCAPS);
    
	lpDD2->GetCaps(&dd->DDInfo[dd->nDDInfo].DDCaps,NULL);
		
	// Set CooperativeLevel For Display Mode Enumeration
	lpDD2->SetCooperativeLevel(NULL,DDSCL_NOWINDOWCHANGES|DDSCL_ALLOWMODEX|DDSCL_FULLSCREEN|DDSCL_NORMAL); 
	
	// Enumerate Display Modes
	lpDD2->EnumDisplayModes(0,NULL,(LPVOID) &dd->DDInfo[dd->nDDInfo],DXEnumDisplayModes);
	
	lpDD2->QueryInterface(IID_IDirect3D2,(void**)&lpD3D2);

	bSoftRend = false;

	lpD3D2->EnumDevices(DXEnumDirect3D,(LPVOID) &dd->DDInfo[dd->nDDInfo]);
	
	lpDD2->SetCooperativeLevel(NULL,DDSCL_NORMAL);

	lpD3D2->Release();

	lpDD2->Release();

	// Increase Number Of Devices
	dd->nDDInfo++;

	return DDENUMRET_OK;
}

// EOF: DirectDrawEnumerateCallback




/*
	Function :	DXBitMask2ShiftCnt
	Useage   :	Convert Bitmask to Shifts and Bit cnt

*/

void DXBitMask2ShiftCnt(unsigned long mask,unsigned char* shift,unsigned char* cnt)
{
	unsigned long m;
	unsigned char n;
	for(n=0,m=mask;!(m&1);n++,m>>=1);
	*shift = n;
	for(n=0;m&1;n++,m>>=1);
	*cnt = n;
}

// EOF : DXBitMask2ShiftCnt



/*
	Function	:	DisplayModesEnumerateCallback
	Useage		:	Enumerate Display Modes
*/

HRESULT CALLBACK DXEnumDisplayModes(LPDDSURFACEDESC lpddsd, LPVOID lpContext)
{
	DIRECTDRAWINFO* DDInfo;
	DDInfo = (DIRECTDRAWINFO*) lpContext;

	// Allocate DisplayMode Structure 
	if(DDInfo->nDisplayMode == 0)
		DDInfo->DisplayMode = (DISPLAYMODE*) malloc(sizeof(DISPLAYMODE));
	else
		DDInfo->DisplayMode = (DISPLAYMODE*) realloc(DDInfo->DisplayMode,sizeof(DISPLAYMODE)*(DDInfo->nDisplayMode+1));

	// Clear Structure 
	memset(&DDInfo->DisplayMode[DDInfo->nDisplayMode],0,sizeof(DISPLAYMODE));
	
	// Store Details Of Display Mode
	DDInfo->DisplayMode[DDInfo->nDisplayMode].w        = lpddsd->dwWidth;
	DDInfo->DisplayMode[DDInfo->nDisplayMode].h        = lpddsd->dwHeight;
	DDInfo->DisplayMode[DDInfo->nDisplayMode].bpp	   = lpddsd->ddpfPixelFormat.dwRGBBitCount;
	DDInfo->DisplayMode[DDInfo->nDisplayMode].bPalette = lpddsd->ddpfPixelFormat.dwFlags&DDPF_PALETTEINDEXED8?true:false;	
	memcpy(&DDInfo->DisplayMode[DDInfo->nDisplayMode].ddsd,lpddsd,sizeof(DDSURFACEDESC));

	if(!DDInfo->DisplayMode[DDInfo->nDisplayMode].bPalette)
	{
		// Get RGBA Bit Counts and Shifts

		DXBitMask2ShiftCnt(lpddsd->ddpfPixelFormat.dwRBitMask,
						   &DDInfo->DisplayMode[DDInfo->nDisplayMode].rshift,
						   &DDInfo->DisplayMode[DDInfo->nDisplayMode].rbpp);

		DXBitMask2ShiftCnt(lpddsd->ddpfPixelFormat.dwGBitMask,
						   &DDInfo->DisplayMode[DDInfo->nDisplayMode].gshift,
						   &DDInfo->DisplayMode[DDInfo->nDisplayMode].gbpp);

		DXBitMask2ShiftCnt(lpddsd->ddpfPixelFormat.dwBBitMask,
						   &DDInfo->DisplayMode[DDInfo->nDisplayMode].bshift,
						   &DDInfo->DisplayMode[DDInfo->nDisplayMode].bbpp);

		if(lpddsd->ddpfPixelFormat.dwRGBAlphaBitMask != 0)
			DXBitMask2ShiftCnt(lpddsd->ddpfPixelFormat.dwRGBAlphaBitMask,
							   &DDInfo->DisplayMode[DDInfo->nDisplayMode].ashift,
							   &DDInfo->DisplayMode[DDInfo->nDisplayMode].abpp);
	}

	// Increase Number Of Display Modes
	DDInfo->nDisplayMode++;

	return DDENUMRET_OK;
}

// EOF : DisplayModesEnumerateCallback


/*
	Function	:	Direct3DEnumerationCallback
	Useage		:	Enumerate Direct3D
*/

HRESULT CALLBACK DXEnumDirect3D(LPGUID lpGuid,LPSTR lpDeviceDesc,LPSTR lpDeviceName,LPD3DDEVICEDESC lpHWDesc,LPD3DDEVICEDESC lpHELDesc,LPVOID lpContext)
{
	int n;

	DIRECTDRAWINFO* DDInfo;
	DDInfo = (DIRECTDRAWINFO*) lpContext;

	if(lpHWDesc->dwFlags == 0)
	{
		// Discard 8 Bit Drivers
		if(lpHELDesc->dcmColorModel&D3DCOLOR_MONO) return D3DENUMRET_OK;
	}


#ifdef DISABLESOFTWARE
	if(lpHWDesc->dwFlags == 0)
		return D3DENUMRET_OK;
#endif

	if(lpHWDesc->dwFlags == 0 && bSoftRend == true)
		return D3DENUMRET_OK;
	
	
	if(lpHWDesc->dwFlags == 0)
	{
		bSoftRend = true;
		strcpy(lpDeviceDesc,"Core Design Software Renderer");
		strcpy(lpDeviceName,"RGB Emulation");
	}

	
	if(DDInfo->nD3DInfo == 0)
		DDInfo->D3DInfo = (DIRECT3DINFO*) malloc(sizeof(DIRECT3DINFO));
	else
		DDInfo->D3DInfo = (DIRECT3DINFO*) realloc(DDInfo->D3DInfo,sizeof(DIRECT3DINFO)*(DDInfo->nD3DInfo+1));
	
	memset(&DDInfo->D3DInfo[DDInfo->nD3DInfo],0,sizeof(DIRECT3DINFO));	
	
	// Store Details Of Driver Information
	if(lpGuid==NULL)
		DDInfo->D3DInfo[DDInfo->nD3DInfo].lpGuid = NULL;
	else
	{
		DDInfo->D3DInfo[DDInfo->nD3DInfo].lpGuid = &DDInfo->D3DInfo[DDInfo->nD3DInfo].Guid;
		memcpy(&DDInfo->D3DInfo[DDInfo->nD3DInfo].Guid,lpGuid,sizeof(GUID));
	}

	lstrcpy(DDInfo->D3DInfo[DDInfo->nD3DInfo].About,lpDeviceDesc);
    lstrcpy(DDInfo->D3DInfo[DDInfo->nD3DInfo].Name,lpDeviceName);	

	// Store Device Descriptions
	if(lpHWDesc->dwFlags != 0)
	{
		DDInfo->D3DInfo[DDInfo->nD3DInfo].bHardware = true;
		memcpy(&DDInfo->D3DInfo[DDInfo->nD3DInfo].DeviceDesc,lpHWDesc,sizeof(D3DDEVICEDESC));
	}
	else
	{
		DDInfo->D3DInfo[DDInfo->nD3DInfo].bHardware = false;
		memcpy(&DDInfo->D3DInfo[DDInfo->nD3DInfo].DeviceDesc,lpHELDesc,sizeof(D3DDEVICEDESC));
	}
	

	if(DDInfo->D3DInfo[DDInfo->nD3DInfo].DeviceDesc.dpcTriCaps.dwAlphaCmpCaps != 0)
		DDInfo->D3DInfo[DDInfo->nD3DInfo].bAlpha = true;
	else
		DDInfo->D3DInfo[DDInfo->nD3DInfo].bAlpha = false;

	// Check Which Video Modes Are Compatable With Driver and copy details

	for(n=0;n<DDInfo->nDisplayMode;n++)
	{
		if(BPPToDDBD(DDInfo->DisplayMode[n].bpp)&DDInfo->D3DInfo[DDInfo->nD3DInfo].DeviceDesc.dwDeviceRenderBitDepth)
		{
			// ToDo: Make a setup specifier
			//		 Only Want 16 Bit Video Modes
		
			if(DDInfo->DisplayMode[n].bpp == 16)	
			{
				if(DDInfo->D3DInfo[DDInfo->nD3DInfo].nDisplayMode == 0)
					DDInfo->D3DInfo[DDInfo->nD3DInfo].DisplayMode = (DISPLAYMODE*) malloc(sizeof(DISPLAYMODE));
				else
					DDInfo->D3DInfo[DDInfo->nD3DInfo].DisplayMode = (DISPLAYMODE*) realloc(DDInfo->D3DInfo[DDInfo->nD3DInfo].DisplayMode,sizeof(DISPLAYMODE)*(DDInfo->D3DInfo[DDInfo->nD3DInfo].nDisplayMode+1));
	
				memcpy(&DDInfo->D3DInfo[DDInfo->nD3DInfo].DisplayMode[DDInfo->D3DInfo[DDInfo->nD3DInfo].nDisplayMode],&DDInfo->DisplayMode[n],sizeof(DISPLAYMODE));
			
				DDInfo->D3DInfo[DDInfo->nD3DInfo].nDisplayMode++;

			
			}
		
		}
	}

	// Setup A D3DDEVICE For Texture Format Enumeration
	// First Try Using the Primary Surface
	
	DDSURFACEDESC ddsd;
	DXInit(ddsd);
	ddsd.dwFlags		   = DDSD_CAPS;
	ddsd.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE|DDSCAPS_3DDEVICE;

	lpDDSurface = NULL;

	DXSetCooperativeLevel(lpDD2,WindowHandle,DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_NOWINDOWCHANGES);
	DXCreateSurface(lpDD2,&ddsd,&lpDDSurface);
	DXSetCooperativeLevel(lpDD2,WindowHandle,DDSCL_NORMAL);
	
	if(lpDDSurface)
	{
		// Try To Create Device			
		lpD3DDevice = NULL;	
		DXCreateDirect3DDevice(lpD3D2,DDInfo->D3DInfo[DDInfo->nD3DInfo].Guid,lpDDSurface,&lpD3DDevice);

		// Check If Device is Ok
			
		if(lpD3DDevice == NULL)
		{
			// No Device, Try Another Surface Format (555 Offscreen)
				
			DXRelease(lpDDSurface);
 
            ddsd.dwSize = sizeof(ddsd);
            ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_HEIGHT | DDSD_WIDTH;
            ddsd.dwWidth = 100;
            ddsd.dwHeight = 100;
            ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY;
            ddsd.ddpfPixelFormat.dwSize            = sizeof(DDPIXELFORMAT);
            ddsd.ddpfPixelFormat.dwFlags           = DDPF_RGB;
            ddsd.ddpfPixelFormat.dwFourCC          = 0;
            ddsd.ddpfPixelFormat.dwRGBBitCount     = 16;
            ddsd.ddpfPixelFormat.dwRBitMask        = 0x7C00; 
            ddsd.ddpfPixelFormat.dwGBitMask        = 0x03E0; 
            ddsd.ddpfPixelFormat.dwBBitMask        = 0x001F;
            ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0x0000;
				
			DXCreateSurface(lpDD2,&ddsd,&lpDDSurface);

			// Try To Create The Device Again
				
			if(lpDDSurface)
				DXCreateDirect3DDevice(lpD3D2,DDInfo->D3DInfo[DDInfo->nD3DInfo].Guid,lpDDSurface,&lpD3DDevice);					
		}

		
		// Now Enumerate The Texture Formats

		if(lpD3DDevice)
		{
			// Enumerate Texture Formats For This D3DDevice
			DDInfo->D3DInfo[DDInfo->nD3DInfo].nTexture = 0;
						
			lpD3DDevice->EnumTextureFormats(DXEnumTextureFormats,(LPVOID) &DDInfo->D3DInfo[DDInfo->nD3DInfo]);

			DXRelease(lpD3DDevice);
			DXRelease(lpDDSurface);
		}
		
	}

	// Increase Number Of Devices

	DDInfo->nD3DInfo++;
    
    return D3DENUMRET_OK;
}

// EOF : Direct3DEnumerationCallback



/*
	Function	:	DXEnumTextureFormats
	Useage		:	Enumerate Texture Formats
*/

HRESULT CALLBACK DXEnumTextureFormats(LPDDSURFACEDESC lpddsd,LPVOID lpContext)
{
	DIRECT3DINFO* D3DInfo;
	D3DInfo = (DIRECT3DINFO*) lpContext;

	if(D3DInfo->nTexture == 0)
		D3DInfo->Texture = (D3DTEXTUREINFO*) malloc(sizeof(D3DTEXTUREINFO));
	else
		D3DInfo->Texture = (D3DTEXTUREINFO*) realloc(D3DInfo->Texture,sizeof(D3DTEXTUREINFO)*(D3DInfo->nTexture+1));


	memset(&D3DInfo->Texture[D3DInfo->nTexture],0,sizeof(D3DTEXTUREINFO));
	memcpy(&D3DInfo->Texture[D3DInfo->nTexture].ddsd,lpddsd,sizeof(DDSURFACEDESC));

	// Is it Palettised

	if(lpddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
	{
		D3DInfo->Texture[D3DInfo->nTexture].bPalette = true;
		D3DInfo->Texture[D3DInfo->nTexture].bpp = 8;
	}
	else if(lpddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
	{
		/*
		D3DInfo->Texture[D3DInfo->nTexture].bPalette = true;
		D3DInfo->Texture[D3DInfo->nTexture].bpp = 4;
		*/
		return D3DENUMRET_OK;
	}
	else
	{
		D3DInfo->Texture[D3DInfo->nTexture].bPalette = false;
		D3DInfo->Texture[D3DInfo->nTexture].bpp = lpddsd->ddpfPixelFormat.dwRGBBitCount;

      	DXBitMask2ShiftCnt(lpddsd->ddpfPixelFormat.dwRBitMask,
						   &D3DInfo->Texture[D3DInfo->nTexture].rshift,
						   &D3DInfo->Texture[D3DInfo->nTexture].rbpp);
		
		DXBitMask2ShiftCnt(lpddsd->ddpfPixelFormat.dwGBitMask,
						   &D3DInfo->Texture[D3DInfo->nTexture].gshift,
						   &D3DInfo->Texture[D3DInfo->nTexture].gbpp);

		DXBitMask2ShiftCnt(lpddsd->ddpfPixelFormat.dwBBitMask,
						   &D3DInfo->Texture[D3DInfo->nTexture].bshift,
						   &D3DInfo->Texture[D3DInfo->nTexture].bbpp);

		if(lpddsd->ddpfPixelFormat.dwRGBAlphaBitMask != 0)
		{
			DXBitMask2ShiftCnt(lpddsd->ddpfPixelFormat.dwRGBAlphaBitMask,
								   &D3DInfo->Texture[D3DInfo->nTexture].ashift,
								   &D3DInfo->Texture[D3DInfo->nTexture].abpp);

			D3DInfo->Texture[D3DInfo->nTexture].bAlpha = true;
		}	
		
	}

	D3DInfo->nTexture++;

	return D3DENUMRET_OK;
}

// EOF : DXEnumTextureFormats





/*
	Function	:	BPPToDDBD
	Useage		:	Convert bpp to DDBD
*/

DWORD BPPToDDBD(int bpp)
{
    switch(bpp)
	{
        case 1:
            return DDBD_1;
        case 2:
            return DDBD_2;
        case 4:
            return DDBD_4;
        case 8:
            return DDBD_8;
        case 16:
            return DDBD_16;
        case 24:
            return DDBD_24;
        case 32:
            return DDBD_32;
    }
	return (DWORD) 0;
}

// EOF : BPPToDDBD



/*
	Function	:	DXCreateDirectDraw
	Useage		:	Create A DirectDraw2 Interface
*/

bool DXCreateDirectDraw(DEVICEINFO* dd,DXCONFIG* DXConfig,LPDIRECTDRAW2* lpDD2)
{
	LPDIRECTDRAW lpDD;
	int RetVal;
	RetVal = DirectDrawCreate(dd->DDInfo[DXConfig->nDD].lpGuid,&lpDD,NULL);
	if(RetVal != DD_OK) return false;
	RetVal = lpDD->QueryInterface(IID_IDirectDraw2,(LPVOID*)lpDD2);
	DXRelease(lpDD);
	if(RetVal != DD_OK)	return false;
	return true;
}

// EOF : DXCreateDirectDraw




/*
	Function	:	DXCreateDirect3D
	Useage		:	Create A Direct3D2 Interface
*/

bool DXCreateDirect3D(LPDIRECTDRAW2 lpDD2,LPDIRECT3D2* lpD3D2)
{
	int RetVal;
	RetVal = lpDD2->QueryInterface(IID_IDirect3D2,(LPVOID*) lpD3D2);
	if(RetVal != DD_OK) return false;
	return true;
}

// EOF : DXCreateDirect3D


/*
	Function	:	DXFindDevice
	Useage		:	Find DEVICEINFO Offsets
*/

bool DXFindDevice(DEVICEINFO* dd,int w,int h,int bpp,bool hw,DXCONFIG* DXConfig)
{
	int i,j,k;
	


	for(i=0;i<dd->nDDInfo;i++)
	{
		for(j=0;j<dd->DDInfo[i].nD3DInfo;j++)
		{
			if(dd->DDInfo[i].D3DInfo[j].bHardware == hw)
			{
				for(k=0;k<dd->DDInfo[i].D3DInfo[j].nDisplayMode;k++)
				{
					if(dd->DDInfo[i].D3DInfo[j].DisplayMode[k].w == w &&
					   dd->DDInfo[i].D3DInfo[j].DisplayMode[k].h == h &&
					   dd->DDInfo[i].D3DInfo[j].DisplayMode[k].bpp == (unsigned long) bpp)
					{
						DXConfig->nDD    = i;
						DXConfig->nD3D   = j;
						DXConfig->nVMode = k;
					//	return true;
					}
				}
			}
		}
	}

	//return false;
	return true;
}

// EOF : DXFindDevice



/*
	Function	:	DXSetCooperativeLevel
	Useage		:	Set Cooperative Level 
*/

bool DXSetCooperativeLevel(LPDIRECTDRAW2 lpDD2,HWND WindowHandle,int Flags)
{
	int RetVal;
	RetVal = lpDD2->SetCooperativeLevel(WindowHandle,Flags);
	if(RetVal != DD_OK) return false;
	return true;
}

// EOF : DXSetCooperativeLevel



/*
	Function	:	DXSetVideoMode
	Useage		:	Set Video Mode
*/

bool DXSetVideoMode(LPDIRECTDRAW2 lpDD2,int w,int h,int bpp)
{
	int RetVal;
	RetVal = lpDD2->SetDisplayMode(w,h,bpp,0,NULL);
	if(RetVal != DD_OK) return false;
	return true;
}

// EOF : DXSetVideoMode




/*
	Function	: DXCreateSurface
	Useage		: Create DirectDraw Surface
*/

bool DXCreateSurface(LPDIRECTDRAW2 lpDD2,DDSURFACEDESC* ddsd,LPDIRECTDRAWSURFACE3* lpSurface)
{
	int RetVal;
	LPDIRECTDRAWSURFACE lps;
	RetVal = lpDD2->CreateSurface(ddsd,&lps,NULL);
	if(RetVal!=DD_OK) return false;
	RetVal = lps->QueryInterface(IID_IDirectDrawSurface3,(LPVOID*) lpSurface);
	DXRelease(lps);
	if(RetVal!=DD_OK) return false;
	return true;
}

// EOF : DXCreateSurface



/*
	Function	:	DXGetAttachedSurface
	Useage		:	Get Interface To Attached Surface
*/

bool DXGetAttachedSurface(LPDIRECTDRAWSURFACE3 lpPrimary,DDSCAPS* ddscaps,LPDIRECTDRAWSURFACE3* lpAttached)
{
	int RetVal;

	RetVal = lpPrimary->GetAttachedSurface(ddscaps,lpAttached);
	if(RetVal != DD_OK)	return false;
	return true;
}

// EOF : DXGetAttachedSurface



/*
	Function	:	DXAddAttachedSurface
	Useage		:	Attach A Surface
*/

bool DXAddAttachedSurface(LPDIRECTDRAWSURFACE3 lpSurface,LPDIRECTDRAWSURFACE3 lpAddSurface)
{
	int RetVal;
	RetVal = lpSurface->AddAttachedSurface(lpAddSurface);
	if(RetVal != DD_OK) return false;
	return true;
}

// EOF : DXAddAttachedSurface



/*
	Function	:	DXCreateDirect3DDevice
	Useage		:	Create A Direct3D Device
*/

bool DXCreateDirect3DDevice(LPDIRECT3D2 lpD3D2,GUID Guid,LPDIRECTDRAWSURFACE3 lpSurface,LPDIRECT3DDEVICE2* lpD3DDevice2)
{
	int RetVal;
	RetVal = lpD3D2->CreateDevice(Guid,(LPDIRECTDRAWSURFACE)lpSurface,lpD3DDevice2);
	if(RetVal != DD_OK) return false;
	return true;
}

// EOF : DXCreateDirect3DDevice




/*
	Function	:	DXCreateViewPort
	Useage		:	Create A Viewport
*/

bool DXCreateViewPort(LPDIRECT3D2 lpD3D,LPDIRECT3DDEVICE2 lpD3DDevice,int w,int h,IDirect3DViewport2** lpViewport)
{
	int RetVal;
	D3DVIEWPORT2 viewdata;

	RetVal = lpD3D->CreateViewport(lpViewport,NULL);
	if(RetVal != DD_OK) return false;

	RetVal = lpD3DDevice->AddViewport(*lpViewport);
	if(RetVal != DD_OK) return false;

	DXInit(viewdata);
	viewdata.dwX	  = 0;
    viewdata.dwY	  = 0;
   	viewdata.dwWidth  = w;
    viewdata.dwHeight = h;
	float inva = (float) ((float)h/(float)w);
	viewdata.dvClipX	  = -1.0F;
    viewdata.dvClipY	  = inva;
   	viewdata.dvClipWidth  = 2.0F;
    viewdata.dvClipHeight = 2.0F*inva;
    viewdata.dvMinZ		  = 0.0F;
    viewdata.dvMaxZ		  = 1.0F;

    RetVal = (*lpViewport)->SetViewport2(&viewdata);
	if(RetVal != DD_OK)	return false;

	RetVal = lpD3DDevice->SetCurrentViewport(*lpViewport);
	
	return true;
}

// EOF : DXCreateViewPort




/*
	Function	:	DXGetSurfaceDescription
	Useage		:	Fill DDSURFACEDESC

*/

void DXGetSurfaceDescription(LPDIRECTDRAWSURFACE3 lpSurface,DDSURFACEDESC* ddsd)
{
	lpSurface->GetSurfaceDesc(ddsd);
}

// EOF : DXGetSurfaceDescription





