#include "pch.hpp"
//
//===========================================================================//
// File:	 DXRasterizer.cpp												 //
// Contents: DirectDraw Manager routines									 //
//                                                                           //
// Copyright (C) 1999 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
//
#include "DXRasterizer.hpp"
#include "Windows.hpp"
#include "Globals.hpp"
#include "ErrorHandler.hpp"
#include "DirectX.hpp"
#include "Debugger.hpp"
#include "3DRasterizer.hpp"
#include "Texture Manager.hpp"
#include "ControlManager.hpp"
#include "VideoPlayback.hpp"
#include "Font3D.hpp"
#include "Sound Renderer.hpp"
#include "Music.hpp"

extern DWORD gLanguageDLL;
extern DWORD GameNoVsync;
extern DWORD gCaptureDevice; // jcem 0 - main, 1 - radar, 2 - mr, 3/4/5/6/7 - AUX #1-#5
extern DWORD gCaptureScreen;
extern DWORD gNumberCompatFlags;
extern DWORD gCompatFlags;
extern DWORD gCompatFlags1;

DWORD AppWidth,AppHeight,App32T,AppRenderer;
DWORD CurrentRefreshRate=0;
extern DWORD NumMonitors;
extern bool gNoDialogs;
bool DontFastPath;
int HasTLHAL=0;
bool AppStencil;
bool StencilValid=0;
bool AppAA;
bool ModeChanged;
bool Rendererd=0;
extern bool RunFullScreen;
extern HDC DesktopDC;

DWORD AllowBrightness=0;
DWORD AllowContrast=0;

DWORD StencilActive=0;
DDSURFACEDESC2 BBddsd;
DDSURFACEDESC2 ZBddsd;
DWORD ShowFrame;
bool ChangingModes=FALSE;

DWORD GlobalWidth;
DWORD GlobalHeight;
DWORD FirstTime=1;

DWORD DBPixelColor;
DWORD BGMask;
extern bool gUse3D;
bool GlobalZBuffer;
bool GlobalFullScreen;

extern bool gDumpMachineInfo;
extern DWORD gForceAlphaTest;
extern DWORD gForceNoAlphaTest;
extern DWORD gDisableLighting;
extern DWORD gDisableNormalizing;
extern DWORD gDisableHardwareTandL;
extern DWORD gDisableVertexBlending;

extern DWORD g_DDstate;
extern bool g_DDneedsRestore;
extern bool g_DDperformFlip;
extern HWND g_DDhWnd;
extern DWORD gEnableParallel;
extern DWORD GetColor( DWORD Pixel, DWORD Mask );

WINDOWPLACEMENT WindowPlacement;


void InitVertexBuffers();


DWORD TripleBuffer=0;					// Copied from Environment for current card (so can be disabled on 3Dfx)
//
// 2D variables
//
IDirectDrawSurface7*	FrontBufferSurface = NULL;
IDirectDrawSurface7*	BackBufferSurface = NULL;
IDirectDrawSurface7*	g_RefBackBuffer = NULL;		// Referemce rasterizer back buffer
IDirectDrawSurface7*	g_CopyBackBuffer = NULL;
IDirectDrawGammaControl*	GammaControlInterface = NULL;
IDirectDrawColorControl*	ColorControlInterface = NULL;
IDirectDrawClipper*		ClipperObject = NULL;
IDirectDraw7*			DDobject = NULL;			// Primiary DirectDraw object (for persistant surafces)
IDirectDraw7*			CurrentDDobject = NULL;		// DirectDraw object for rendering (can be the same as DDObject)
IDirectDrawSurface7*	ZBufferSurface = NULL;		// ZBuffer surface
IDirectDrawSurface7*	RefZBufferSurface = NULL;	// Referemce rasterizer ZBuffer surface
//sanghoon marker
IDirectDrawSurface7*	SH_TargetBufferSurface = NULL;
IDirectDrawSurface7*	SH_SwirlTexture= NULL;
IDirectDrawSurface7*	SH_GameEndTexture= NULL;
//sanghoon marker

DDSURFACEDESC2			BackBufferddsd;
//
// Variables for dirty rectangles
//
IDirectDrawSurface7*	CopyTarget = NULL;			// Dirty rectangle copy of back buffer
IDirectDrawSurface7*	CopyZBuffer = NULL;			// Dirty rectangle copy of Z buffer
//
// 3D Variables
//
IDirect3D7*				d3d7=0;
IDirect3DDevice7*		d3dDevice7=0;				// Current D3D Device
IDirect3DDevice7*		Refd3dDevice7=0;			// Reference D3D Device
IDirect3DDevice7*		Maind3dDevice7=0;			// Selected D3D Device
int						HardwareRenderer=0;			// Set when using a hardware renderer
D3DDEVICEDESC7			CapsDirect3D;				// Current 3D device caps
DDCAPS					CapsDirectDraw;				// Current DirectDraw device caps

//
// Rectangle on current viewport being rendered to.
//
D3DVIEWPORT7			viewData;
float					gosViewportMulX,gosViewportAddX,gosViewportMulY,gosViewportAddY;

//
// MipMapping flags
//
DWORD HasBiLinear=0;
DWORD HasTriLinear=0;
//
// Card specific changes triggered by these values
//
DWORD HasFog;
DWORD HasClamp;
DWORD HasAlphaTest;
DWORD HasAlphaModes;
DWORD HasMultitextureLightmap;
DWORD HasMultitextureSpecularmap;
DWORD HasMultitextureDetailTexture;
DWORD HasMultitextureLightmapFilter;
DWORD HasMultitextureSpecularmapFilter;
DWORD HasMultitextureDetailTextureFilter;
DWORD HasVertexBlending;

void DirectDrawRelease();


DWORD gosColorTable[]={ 0xffffffff, 0xffff00ff, 0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00, 0xffff0000, 0xff000000, 0xff808080, 0xff800080, 0xff000080, 0xff008080, 0xff008000, 0xff808000, 0xff800000, 0xffff80ff, 0xff8080ff, 0xff80ffff, 0xff80ff80 };
DWORD DepthResults[8];
DWORD DepthPixels;
DWORD GlobalGotoFullScreen=0;
DWORD GlobalGotoWindowMode=0;


//
// Variables for gamma correction
//
BYTE GammaTable[256];
float GammaSetting=0.0;
bool UseGammaCorrection=0;
float UserGamma=1.0f;

//sanghoon begin
bool use_shgui = false;
bool hsh_initialized=false;
bool hsh_mrdev_initialized=false;


#include "coord.cpp"
//#include "hsh_dxras.cpp"
#include "render.hpp"
//sanghoon end

//
// Value range 0-10,000, default 750 (See DirectX docs)
//
void gos_SetBrightnessValue( DWORD Brightness )
{
	gosASSERT( Brightness<=10000 );

	if( AllowBrightness && ColorControlInterface)
	{
		DDCOLORCONTROL colcontrol;
		colcontrol.dwSize=sizeof(colcontrol);
		ColorControlInterface->GetColorControls( &colcontrol );
		colcontrol.lBrightness=Brightness;
		ColorControlInterface->SetColorControls( &colcontrol );
	}
}


//
// Value range 0-20,000, default 10,000 (See DirectX docs)
//
void gos_SetContrastValue( DWORD Contrast )
{
	gosASSERT( Contrast<=20000 );

	if( AllowContrast && ColorControlInterface)
	{
		DDCOLORCONTROL colcontrol;
		colcontrol.dwSize=sizeof(colcontrol);
		ColorControlInterface->GetColorControls( &colcontrol );
		colcontrol.lContrast=Contrast;
		ColorControlInterface->SetColorControls( &colcontrol );
	}
}

//
// This API sets the current gamma correction value. The default value is 1.0 (no correction applied). All color values are effected by (value/255 ^ (1.0/gamma))*255.
//
void gos_SetGammaValue( float Gamma )
{
	gosASSERT( Gamma>0.0f );

	UserGamma=Gamma;

	if( GammaControlInterface )
	{
		DDGAMMARAMP Ramps;
		for( int t0=0; t0<256; t0++ )
		{
			Ramps.green[t0]=Ramps.blue[t0]=Ramps.red[t0]=(WORD)(pow(t0/255.0f,1.0f/Gamma)*65535.0);
		}
		GammaControlInterface->SetGammaRamp( 0, &Ramps );
	}
	else
	{
		if( Gamma!=GammaSetting )
		{
			for( int t0=0; t0<256; t0++ )
			{
				GammaTable[t0]=(BYTE)(pow(t0/255.0f,1.0f/Gamma)*255.0);
			}
			GammaSetting=Gamma;
			UseGammaCorrection=Gamma!=1.0f;			// Only use Gamma correction if not 1.0
			UpdatedState[gos_State_Fog]=1;			// Force fog value to be reloaded
			gos_RecreateTextureHeaps();				// Reload all textures
		}
	}
}




//
// Makes sure the window is ready to be rendered to FALSE=Skip rendering
//
bool CheckWindow()
{
//
// If full screen and deactivated (control alt delete in Windows 2000) - do not render
//
	if( Environment.fullScreen && !gActive )
	{
		SPEW(( GROUP_DIRECTDRAW, "Cant blit - not active" ));
		return FALSE;
	}
//
// If windows is minimized, do not render
//
	if( IsIconic(hWindow) )
	{
		SPEW(( GROUP_DIRECTDRAW, "Cant blit - iconic" ));
		return FALSE;
	}
//
// Make sure the app has not changed any screen information
//
	gosASSERT( GlobalWidth==Environment.screenWidth );
	gosASSERT( GlobalHeight==Environment.screenHeight );
	gosASSERT( GlobalZBuffer==Environment.disableZBuffer );
	gosASSERT( GlobalFullScreen==Environment.fullScreen );
//
// Check if window needs updating (front buffer lost or window updated)
//
	if(	(FrontBufferSurface && DDERR_SURFACELOST==wIsLost(FrontBufferSurface)) || DoUpdateWindow )
	{
		if( DoUpdateWindow )
			SPEW(( GROUP_DIRECTDRAW, "Mode change requested, enter new mode" ));
		else
			SPEW(( GROUP_DIRECTDRAW, "Front Buffer lost, renter same mode" ));

		DoUpdateWindow=0;
		if( Environment.fullScreen )
		{
			if( GlobalGotoWindowMode )
				EnterWindowMode();
			else
				EnterFullScreenMode();
		}
		else
		{
			if( GlobalGotoFullScreen )
				EnterFullScreenMode();
			else
				EnterWindowMode();
		}
		GlobalGotoFullScreen=0;
		GlobalGotoWindowMode=0;
	}
	return TRUE;
}





//
// This call is only valid during GameLogic (not inside update renderers).
//
// Applications should not assume the mode has changed, because the user could always override it, enter a window mode, an error caused software rendering etc...
//
// Applications should always use the current Environment variable for screen width and height. These are valid and will not change during UpdateRenderers.
//
// Applications can use gos_GetMachineInformation to query for device information.
//
// bitDepth can be 16 or 32 only
// Device can be 0 to gos_GetMachineInformation(gos_Info_NumberDevices)-1
//
// disableZBuffer, AntiAlias and RenderToVram can be used during different sections of the game, for example the interface to speed up rendering.
//
// GotoFullScreen if true will force the Game into full screen mode. If false it will stay in the mode it is already in (window/full screen).
//
// DirtyRectangle is Bit 0=Enabled, Bit 1=Save Z buffer rectangles too, Bit 2=Save directly in system memory (don't try video memory).
//
// GotoWindowMode if true will force the game into a window mode. If false it will stay in the mode it is already in. (Not valid when GotoFullScreen is also true)
//
// EnableStencil if true will try to enable an 8 bit stencil buffer. Check Environment.Stencil to see if you have a stencil buffer available
//
// Renderer is 0 for hardware or 3 for Blade
//
void __stdcall gos_SetScreenMode( DWORD Width, DWORD Height, DWORD bitDepth, DWORD Device, bool disableZBuffer, bool AntiAlias, bool RenderToVram, bool GotoFullScreen, int DirtyRectangle, bool GotoWindowMode, bool EnableStencil, DWORD Renderer )
{
	SPEW(( GROUP_DIRECTDRAW, "Mode change requested - gos_SetScreenMode(%d,%d)",Width,Height ));
	gosASSERT( !InUpdateRenderers );
//
// See if nothing has changed - if not don't do anything
//
	if( Width==Environment.screenWidth &&
		Height==Environment.screenHeight &&
		bitDepth==Environment.bitDepth &&
		Device==Environment.FullScreenDevice &&
		disableZBuffer==Environment.disableZBuffer &&
		AntiAlias==Environment.AntiAlias &&
		RenderToVram==Environment.RenderToVram &&
		DirtyRectangle==Environment.DirtyRectangle &&
		EnableStencil==AppStencil &&
		Renderer==Environment.Renderer &&
		GotoFullScreen==0 &&
		GotoWindowMode==0 )
	{
		return;
	}
//
//
//
	WantAA=Environment.AntiAlias=AntiAlias;
	Environment.bitDepth=bitDepth;
	GlobalZBuffer=Environment.disableZBuffer=disableZBuffer;
	Environment.DirtyRectangle=DirtyRectangle;
	Environment.RenderToVram=RenderToVram;
	Environment.FullScreenDevice=Device;
	GlobalWidth=AppWidth=Environment.screenWidth=Width;
	GlobalHeight=AppHeight=Environment.screenHeight=Height;	
	WantRes=0;
	GlobalGotoFullScreen=GotoFullScreen;
	GlobalGotoWindowMode=GotoWindowMode;
	AppStencil=EnableStencil;
	WantSW1=Renderer==1;
	WantSW=Renderer==3;
	WantHW=Renderer==0;

	DoUpdateWindow=1;
}


//
// Copies the back buffer - deals with using the ref rast on a blade window in 32 bit mode (555 to 8888 copy)
//
void CopyBackBuffer( IDirectDrawSurface7* Dest, IDirectDrawSurface7* Source )
{
	if( FrontBufferSurface )
	{
		wBlt( Dest, NULL, Source, NULL, DDBLT_WAIT, 0 );
	}
	else
	{
		HDC SourceDC;
		wGetDC( Source, &SourceDC );
		HDC WinDC;
		wGetDC( Dest, &WinDC );
		if( DesktopBpp==8 )
		{
			SetStretchBltMode( WinDC, HALFTONE );
			StretchBlt( WinDC, 0, 0, Environment.screenWidth, Environment.screenHeight, SourceDC, 0, 0, Environment.screenWidth, Environment.screenHeight, SRCCOPY );
		}
		else
		{
			BitBlt( WinDC, 0, 0, Environment.screenWidth, Environment.screenHeight, SourceDC, 0, 0, SRCCOPY );
		}
		wReleaseDC( Dest, WinDC );
		wReleaseDC( Source, SourceDC );
	}
}



//
// Used to enable reference rasterizer
//
// Type		0 = Reference rasterizer
//			1 = Depth Complexity
//
//
void RenderWithReferenceRasterizer( DWORD Type )
{
	DDSURFACEDESC2 ddsd;
//
// Create the system memory backbuffer
//
	memset( &ddsd, 0 ,sizeof(ddsd) );
	ddsd.dwSize	= sizeof(ddsd); 
	ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
	ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY;
	ddsd.dwWidth = Environment.screenWidth;
	ddsd.dwHeight = Environment.screenHeight;

	wCreateSurface( DDobject, &ddsd, &g_RefBackBuffer, NULL );
//
// Create a surface to hold previous render
//
	wCreateSurface( DDobject, &ddsd, &g_CopyBackBuffer, NULL );
//
// Finish the current scene, copy it to save surface
//
	End3DScene();
	CopyBackBuffer( g_CopyBackBuffer, BackBufferSurface );
//
// Display "Please wait" message
//
	gos_SetupViewport( 0,0,0,0, 0.0, 0.0, 1.0, 1.0 );
	gos_SetRenderState( gos_State_Texture, 0 );
	gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_OneZero );

	DWORD StartX=Environment.screenWidth/2-256;

	DrawSquare( StartX, 128, 512, 128, 0x202060 );

	InitTextDisplay();
	gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_OneZero );

	CurrentX=StartX+136;
	CurrentY=188;
	DrawText( 0xffffff, "Rendering - This may take a few seconds" );
//
// End the scene and display please wait message
//
	End3DScene();
	DisplayBackBuffer();
//
// Reference rasterizer uses a normal system memory 16 bit Z Buffer
//
	if( 0==Type )
	{
		memset( &ddsd, 0 ,sizeof(ddsd) );
		ddsd.dwSize								= sizeof(ddsd); 
		ddsd.dwFlags							= DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
		ddsd.ddsCaps.dwCaps						= DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY;
		ddsd.dwWidth							= Environment.screenWidth; 
		ddsd.dwHeight							= Environment.screenHeight; 
		ddsd.ddpfPixelFormat.dwSize				= sizeof(DDPIXELFORMAT);
		ddsd.ddpfPixelFormat.dwFlags			= DDPF_ZBUFFER;
		ddsd.ddpfPixelFormat.dwZBufferBitDepth	= 16;
		ddsd.ddpfPixelFormat.dwZBitMask			= 0xffff;
		StencilActive=0;
	}
//
// Depth complexity uses a system memory 32 bit Z Buffer with 8 bit stencil
//
	if( 1==Type )
	{
		memset( &ddsd, 0 ,sizeof(ddsd) );
		ddsd.dwSize								= sizeof(ddsd); 
		ddsd.dwFlags							= DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
		ddsd.ddsCaps.dwCaps						= DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY;
		ddsd.dwWidth							= Environment.screenWidth; 
		ddsd.dwHeight							= Environment.screenHeight; 
		ddsd.ddpfPixelFormat.dwSize				= sizeof(DDPIXELFORMAT);
		ddsd.ddpfPixelFormat.dwFlags			= DDPF_ZBUFFER | DDPF_STENCILBUFFER;
		ddsd.ddpfPixelFormat.dwZBufferBitDepth	= 32;
		ddsd.ddpfPixelFormat.dwZBitMask			= 0xffffff00;
		ddsd.ddpfPixelFormat.dwStencilBitDepth	= 8;
		ddsd.ddpfPixelFormat.dwStencilBitMask	= 0x000000ff;
		StencilActive=1;
	}

	wCreateSurface( DDobject, &ddsd, &RefZBufferSurface, NULL );

	wAddAttachedSurface( g_RefBackBuffer, RefZBufferSurface );
//
// Setup the reference rasterizer
//
	wCreateDevice( d3d7, IID_IDirect3DRefDevice, g_RefBackBuffer, &Refd3dDevice7 );
	d3dDevice7=Refd3dDevice7;
//
// Reset precision
//
	gos_MathExceptions( 1, 0 );					// Allow exceptions, double precision
//
// Setup the current viewport
//
	viewData.dwX		= 0;
	viewData.dwY		= 0;
	viewData.dwWidth	= Environment.screenWidth;
	viewData.dwHeight	= Environment.screenHeight;
	viewData.dvMinZ		= 0.0f;
	viewData.dvMaxZ		= 1.0f;
    wSetViewport( d3dDevice7, &viewData );
//
// Make sure textures use system memory copy
//
	int OldHardwareRenderer=HardwareRenderer;
	int OldRenderer=Environment.Renderer;
	DontFastPath=1;
	Environment.Renderer=0;
	HardwareRenderer=0;
	NeedToInitRenderStates=1;

	memset( &RenderStates, 0, sizeof(RenderStates) );
	RenderStates[ gos_State_Filter 			] = gos_FilterNone;
	RenderStates[ gos_State_ZCompare 		] = 1;
	RenderStates[ gos_State_ZWrite 			] = 1;
	RenderStates[ gos_State_Perspective		] = 1;
	RenderStates[ gos_State_AlphaMode 		] = gos_Alpha_OneZero;
	RenderStates[ gos_State_TextureAddress 	] = gos_TextureWrap;
	RenderStates[ gos_State_ShadeMode 		] = gos_ShadeGouraud;
	RenderStates[ gos_State_TextureMapBlend ] = gos_BlendModulateAlpha;
	RenderStates[ gos_State_Culling			] = gos_Cull_None;
	RenderStates[ gos_State_Fog 			] = 0;							// Disabled
	AlphaInvAlpha=0;
//
// Clear depth records and stencil buffer
//
	DepthPixels=0;
	memset( &DepthResults, 0, sizeof(DepthResults) );

	if( 1==Type )
	{
		wClear( d3dDevice7, 0, NULL, D3DCLEAR_STENCIL, 0, 0, 0 );
	}
//
// Render whole scene (without debugger, endscene or flip)
//
	InUpdateRenderers=0;
	gos_UpdateDisplay(0);
//
// End the scene
//
	End3DScene();
//
// If depth complexity, read stencil data and update image with colors
//
	if( 1==Type )
	{
//
// Lock the Z Buffer to read stencil info
//
		DDSURFACEDESC2 Zddsd;
		Zddsd.dwSize = sizeof(Zddsd);
		wLock( RefZBufferSurface, NULL, &Zddsd, DDLOCK_NOSYSLOCK | DDLOCK_WAIT | DDLOCK_READONLY, NULL );
//
// Lock the back buffer to update pixel colors
//
		DDSURFACEDESC2 BBddsd;
		BBddsd.dwSize = sizeof(BBddsd);
		wLock( g_RefBackBuffer, NULL, &BBddsd, DDLOCK_NOSYSLOCK | DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL );
//
// Change stencil buffer results into colors in the back buffer (also record numbers of pixels)
//
		DepthPixels=0;
		for( int Y=0; Y<BBddsd.dwHeight; Y++ )
		{
			for( int X=0; X<BBddsd.dwWidth; X++ )
			{
				DWORD Pix=*((DWORD*)Zddsd.lpSurface+X+(Y*Zddsd.lPitch>>2))&0xff;
				
				if( Pix>7 )
					Pix=7;

				DepthPixels++;
				DepthResults[Pix]++;
				
				Pix=gosColorTable[Pix];
				
				if( 32==BBddsd.ddpfPixelFormat.dwRGBBitCount )
				{
					*((DWORD*)BBddsd.lpSurface+X+(Y*BBddsd.lPitch>>2))=Pix;				
				}
				else
				{
					*((WORD*)BBddsd.lpSurface+X+(Y*BBddsd.lPitch>>1))=(WORD)GetPixelColor(Pix);				
				}
			}
		}
//
// Unlock and update structure with information about surface
//
		wUnlock( g_RefBackBuffer, NULL );
		wUnlock( RefZBufferSurface, NULL );
	}
//
// Now destory reference rasterizer
//
	wRelease( Refd3dDevice7 );
	Refd3dDevice7=0;

	wRelease( RefZBufferSurface );
	RefZBufferSurface=0;
//
// Make rendering goto original surfaces
//
	StencilActive=0;
	HardwareRenderer=OldHardwareRenderer;
	Environment.Renderer=OldRenderer;
	DontFastPath=0;
	d3dDevice7=Maind3dDevice7;
	CopyBackBuffer( BackBufferSurface, g_RefBackBuffer );
	gos_SetupViewport( 0,0,0,0, 0.0, 0.0, 1.0, 1.0 );
//
// Make sure renderstates are reset in hardware
//
	NeedToInitRenderStates=1;
}
















void DirectDrawInstall()
{
//
// Debugging information
//
	SPEW(( GROUP_DIRECTDRAW, "DirectDrawInstall()" ));
//
// Create a global object used for all system memory surfaces
//
	DirectDrawCreateDDObject();
//
// Setup debugger defaults
//
	WantAA=0;
	Want32=0;
	Want32T=0;
	if( Environment.screenWidth==512 )
	{
		WantRes=512;
	}
	else if( Environment.screenWidth==640 )
	{
		WantRes=640;
	}
	else if( Environment.screenWidth==800 )
	{
		WantRes=800;
	}
	else if( Environment.screenWidth==1024 )
	{
		WantRes=1024;
	}
	else if( Environment.screenWidth==1280 )
	{
		WantRes=1280;
	}
	else if( Environment.screenWidth==1600 )
	{
		WantRes=1600;
	}
	else
	{
		WantRes=0;
	}
	WantSW1=Environment.Renderer==1;
	WantSW=Environment.Renderer==3;
	WantHW=Environment.Renderer==0;
	WantRVRAM=Environment.RenderToVram;
	AppAA=Environment.AntiAlias;
	AppRenderer=Environment.Renderer;
	AppStencil=Environment.Stencil;
	App32T=0;
	AppWidth=Environment.screenWidth;
	AppHeight=Environment.screenHeight;
//
// Setup default Gamma table
//
	GammaSetting=1.0f;
	UseGammaCorrection=0;
	for( int t0=0; t0<256; t0++ )
	{
		GammaTable[t0]=(BYTE)float2long((float)(pow(t0/255.0f,1.0f/GammaSetting)*255.0f));
	}
//
// Init all vertex buffer variables
//
	InitVertexBuffers();
//
// Create all buffers (if not just dumping info)
//
	if( !gDumpMachineInfo )
	{
		DirectDrawCreateAllBuffers();
		g_DDstate = 1;
		g_DDperformFlip = TRUE;
	}
//
// Debugging information
//
	SPEW(( GROUP_DIRECTDRAW, "DirectDrawInstall() Finished" ));
}



//
//
//
//
//
void DirectDrawUninstall()
{
	SPEW(( GROUP_DIRECTDRAW, "DirectDrawUninstall()" ));
//
// End any special debugging modes
//
	EndRenderMode();
//
// Release of front and back buffer handled in the surface manager uninstall
//
	DirectDrawRelease();
//
// All surfaces marked as released
//
	FrontBufferSurface=0;
	BackBufferSurface=0;

	if (DDobject)
	{
		wRelease(DDobject);
		DDobject=0;
	}
	g_DDstate = 0;
//
// Now main window can be destroyed
//
	if( hWindow )
	{
		DestroyWindow( hWindow );
		hWindow=0;
	}
	SPEW(( GROUP_DIRECTDRAW, "DirectDrawUninstall() Finished" ));
}




char DisplayInfoText[128];
DWORD EndDisplayInfoTime;
DWORD EnableDisplayInfo=0;


//
// Setup the display information about the display mode for 4 seconds
//
void DisplayModeInfo()
{
	char HardwareBuffer[256];
	sprintf( HardwareBuffer, "%s",DeviceArray[Environment.fullScreen ? Environment.FullScreenDevice : 0].DDid.szDescription );
    sprintf( DisplayInfoText, "%dx%d %s",Environment.screenWidth,Environment.screenHeight,(HardwareRenderer ? HardwareBuffer : (Environment.Renderer==2 ? "Software Reference Rasterizer" : ((Environment.Renderer==1 || gNoBlade) ? "Software RGB/MMX" : "Software Rasterizer" ) )) );
	EnableDisplayInfo=1;
}

//
//
// Force the application to be in windows mode
//
//
void EnterWindowMode()
{
//
// Debugging information
//
	SPEW(( GROUP_DIRECTDRAW, "EnterWindowMode()" ));
//
// Pause sound and music to keep it synched with game
//
	VideoManagerRelease();
	SoundRendererPause();
//
// Debugger overriding full screen mode?
//
	Environment.AntiAlias=WantAA!=0;
	if( Want32 )
		Environment.bitDepth=32;
	Environment.Stencil=AppStencil;
	if( WantRes )
	{
		switch( WantRes )
		{
			case 512:
				GlobalWidth=Environment.screenWidth=512;
				GlobalHeight=Environment.screenHeight=384;
				break;
			case 800:
				GlobalWidth=Environment.screenWidth=800;
				GlobalHeight=Environment.screenHeight=600;
				break;
			case 1024:
				GlobalWidth=Environment.screenWidth=1024;
				GlobalHeight=Environment.screenHeight=768;
				break;
			case 1280:
				GlobalWidth=Environment.screenWidth=1280;
				GlobalHeight=Environment.screenHeight=1024;
				break;
			case 1600:
				GlobalWidth=Environment.screenWidth=1600;
				GlobalHeight=Environment.screenHeight=1200;
				break;
			default:
				GlobalWidth=Environment.screenWidth=640;
				GlobalHeight=Environment.screenHeight=480;
		}
	}
	else
	{
		GlobalWidth=Environment.screenWidth=AppWidth;
		GlobalHeight=Environment.screenHeight=AppHeight;
	}
	Environment.Renderer=WantSW ? 3 : (WantHW ? 0 : (WantSW1 ? 1 : AppRenderer) );
	Environment.RenderToVram=WantRVRAM!=0;
//
// Restore from full screen mode
//
	g_DDstate = 0;
	ChangingModes=TRUE;
	DirectDrawRelease();
	ChangingModes=0;
	GlobalFullScreen=Environment.fullScreen=0;
//
// Make sure bitdepth is 16 or 32 bit to match the desktop
//
	if( DesktopBpp==16 || DesktopBpp==32 )
		Environment.bitDepth=DesktopBpp;
//
// Size window if size changed
//
	RECT rc;
	GetWindowRect(hWindow,&rc);
	RECT rect;
	rect.left=0;
	rect.top=0;
	rect.right=Environment.screenWidth;
	rect.bottom=Environment.screenHeight;
	AdjustWindowRect( &rect, GetWindowLong( hWindow, GWL_STYLE ), FALSE );
	rect.right=rect.right-rect.left;
	rect.bottom=rect.bottom-rect.top;
	SetWindowPos(hWindow,HWND_TOP,0,0,rect.right,rect.bottom,SWP_NOACTIVATE|SWP_NOMOVE|SWP_FRAMECHANGED|SWP_DRAWFRAME|SWP_SHOWWINDOW);
//
// Continue sound and music, recreate textures if not exiting
//
	if( !TerminateGame )
	{
		DirectDrawCreateAllBuffers();
		g_DDstate = 1;
		SoundRendererContinue();
		VideoManagerRestore();
	}
//
// Debugging information
//
	SPEW(( GROUP_DIRECTDRAW, "EnterWindowMode() Finished" ));
}



static FoundNetMeeting;
//
// Look to see if 'Netmeeting' is running
//
BOOL CALLBACK WinEnum( HWND hwnd, LPARAM )
{
	char Buffer[32];
	GetWindowText( hwnd, Buffer, 31 );
	if( 0==strnicmp( Buffer, gos_GetResourceString(gLanguageDLL, GOS_DXRASTERIZER_NETMEETING), strlen(gos_GetResourceString(gLanguageDLL, GOS_DXRASTERIZER_NETMEETING))) )
	{
		FoundNetMeeting=1;
		return FALSE;
	}
	return TRUE;
}

//
//
// Force the application to be in full screen mode
//
//
void EnterFullScreenMode()
{
//
// Debugging information
//
	SPEW(( GROUP_DIRECTDRAW, "EnterFullScreenMode(%s)",DeviceArray[Environment.FullScreenDevice].DDid.szDescription ));
//
// Pause sound and music to keep it synched with game
//
	VideoManagerRelease();
	SoundRendererPause();
//
// Save the old window position before changing modes
//
	if( !Environment.fullScreen )
	{
		WindowPlacement.length=sizeof(WINDOWPLACEMENT);
		GetWindowPlacement(hWindow,&WindowPlacement);
	}
//
// Release all the direct draw surfaces used while in a window
//
	ChangingModes=TRUE;
	g_DDstate = 0;
	DirectDrawRelease();
//
// Now setting up as full screen
//
	GlobalFullScreen=Environment.fullScreen=1;
//
// Create the direct draw object for the full screen device
//
	if( 0==Environment.FullScreenDevice )
	{
		CurrentDDobject=DDobject;		
		wAddRef( CurrentDDobject );					// Addref it so it does not get released
	}
	else
	{
		wDirectDrawCreateEx( &DeviceArray[Environment.FullScreenDevice].DeviceGUID, (void**)&CurrentDDobject, IID_IDirectDraw7, NULL );
	}
//
// Debugger overriding full screen mode?
//
	Environment.AntiAlias=WantAA!=0;
	if( Want32 )
		Environment.bitDepth=32;
	Environment.Stencil=AppStencil;
	if( WantRes )
	{
		switch( WantRes )
		{
			case 512:
				GlobalWidth=Environment.screenWidth=512;
				GlobalHeight=Environment.screenHeight=384;
				break;
			case 800:
				GlobalWidth=Environment.screenWidth=800;
				GlobalHeight=Environment.screenHeight=600;
				break;
			case 1024:
				GlobalWidth=Environment.screenWidth=1024;
				GlobalHeight=Environment.screenHeight=768;
				break;
			case 1280:
				GlobalWidth=Environment.screenWidth=1280;
				GlobalHeight=Environment.screenHeight=1024;
				break;
			case 1600:
				GlobalWidth=Environment.screenWidth=1600;
				GlobalHeight=Environment.screenHeight=1200;
				break;
			default:
				GlobalWidth=Environment.screenWidth=640;
				GlobalHeight=Environment.screenHeight=480;
		}
	}
	else
	{
		GlobalWidth=Environment.screenWidth=AppWidth;
		GlobalHeight=Environment.screenHeight=AppHeight;
	}
	Environment.Renderer=WantSW ? 3 : (WantHW ? 0 : (WantSW1 ? 1 : AppRenderer) );
	Environment.RenderToVram=WantRVRAM!=0;
//
// If using blade, always 16 bit full screen
//
	if( Environment.Renderer>=3 || NumHWDevices==0 )
		Environment.bitDepth=16;
//
// Remove all window styles on full screen windows
//
	SafeFPU();					// Make sure exceptions cannot be generated
	SetWindowLong( hWindow, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE );
//
// Set the DirectDraw Object to full screen mode - disable Control Alt Delete in release
//

	#ifdef LAB_ONLY
		//sanghoon
		wSetCooperativeLevel( CurrentDDobject, hWindow, DDSCL_SETFOCUSWINDOW );
		wSetCooperativeLevel( CurrentDDobject, hWindow, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
	#else
		//sanghoon
		wSetCooperativeLevel( CurrentDDobject, hWindow, DDSCL_SETFOCUSWINDOW );
		wSetCooperativeLevel( CurrentDDobject, hWindow, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
	#endif
//
// Attempt 60Hz full screen mode once, then just use default Hz from then on
//
	HRESULT result;
	if( DeviceArray[Environment.FullScreenDevice].Failed60Hz )
	{
		CurrentRefreshRate=0;
		AllowFail=TRUE;
		result=wSetDisplayMode( CurrentDDobject, Environment.screenWidth, Environment.screenHeight, Environment.bitDepth, 0, 0 );
		AllowFail=FALSE;
	}
	else
	{	
		result=-1;
		if( Environment.MaxRefreshRate )
		{
			if( Environment.bitDepth==16 )
			{
				for( int t0=0; t0<32; t0+=2 )
				{
					if( DeviceArray->Modes16[t0+0]==Environment.screenWidth && DeviceArray->Modes16[t0+1]==Environment.screenHeight )
					{
						CurrentRefreshRate=DeviceArray->Refresh16[t0/2];
						break;
					}
				}
			}
			else
			{
				for( int t0=0; t0<32; t0+=2 )
				{
					if( DeviceArray->Modes32[t0+0]==Environment.screenWidth && DeviceArray->Modes32[t0+1]==Environment.screenHeight )
					{
						CurrentRefreshRate=DeviceArray->Refresh32[t0/2];
						break;
					}
				}
			}
			AllowFail=TRUE;
			result=wSetDisplayMode( CurrentDDobject, Environment.screenWidth, Environment.screenHeight, Environment.bitDepth, CurrentRefreshRate, 0 );
			AllowFail=FALSE;
		}
		if( FAILED(result) )
		{
			CurrentRefreshRate=60;
			AllowFail=TRUE;
			result=wSetDisplayMode( CurrentDDobject, Environment.screenWidth, Environment.screenHeight, Environment.bitDepth, 60, 0 );
			AllowFail=FALSE;
		}
		if( FAILED(result) )
		{
			CurrentRefreshRate=0;
			DeviceArray[Environment.FullScreenDevice].Failed60Hz=true;
			AllowFail=TRUE;
			result=wSetDisplayMode( CurrentDDobject, Environment.screenWidth, Environment.screenHeight, Environment.bitDepth, 0, 0 );
			AllowFail=FALSE;
		}
	}
//
// Any problem entering full screen, try other modes
//
	if( FAILED(result) )
	{
//
// Try 640*480, same bit depth in case 32 bit ran out of memory)
//
		GlobalWidth=Environment.screenWidth=640;
		GlobalHeight=Environment.screenHeight=480;
		AllowFail=1;
		result=wSetDisplayMode( CurrentDDobject, Environment.screenWidth, Environment.screenHeight, Environment.bitDepth, 0, 0 );
		AllowFail=0;
//
// Try 640*480 16 bit
//
		Environment.bitDepth=16;
		AllowFail=1;
		result=wSetDisplayMode( CurrentDDobject, Environment.screenWidth, Environment.screenHeight, Environment.bitDepth, 0, 0 );
		AllowFail=0;
		if( FAILED(result) )
		{
//
// See if "Netmeeting" running
//
			FoundNetMeeting=0;
			EnumWindows( WinEnum, 0 );
			Environment.fullScreen=1;
			ChangingModes=FALSE;
			g_DDstate = 1;
			EnterWindowMode();

			if( FoundNetMeeting )
				PAUSE(( gos_GetResourceString(gLanguageDLL, GOS_DXRASTERIZER_STOPNETMEETING) ));
			else
				PAUSE(( gos_GetResourceString(gLanguageDLL, GOS_DXRASTERIZER_NOFULLSCREEN) ));
			return;
		}
	}

//sanghoon begin
	if(use_shgui){
		HSH_EnterFullScreen2();
	}
//sanghoon end

//
// Changed modes, create all the surfaces
//
	GameOSFPU();				// Restore current GameOS FPU control word setup
	ChangingModes=FALSE;
	DirectDrawCreateAllBuffers();
	g_DDstate = 1;
//
// Make sure we have input focus when full screen
//
	SetFocus( hWindow );
    SetForegroundWindow(hWindow);
//
// Make sure the mouse cannot move off our screen
//
	RECT ClipWindow;
	GetWindowRect( hWindow, &ClipWindow );

	ClipWindow.right=ClipWindow.left+Environment.screenWidth;		// Force clip window size to the current res (fixes Voodoo problems)
	ClipWindow.bottom=ClipWindow.top+Environment.screenHeight;	

	ClipCursor( &ClipWindow );
//
// Continue sound and music
//
	SoundRendererContinue();
	VideoManagerRestore();
//
// Debugging information
//
	SPEW(( GROUP_DIRECTDRAW, "EnterFullScreenMode() Finished" ));
//sanghoon
}





static int ParallelFrame;					// Used to disable renderer parallelism every otehr frame

//
// Ends the 3D scene (PowerVR starts to render)
//
void End3DScene()
{
	if( InsideBeginScene && d3dDevice7 )
	{
		SafeFPU();							// Make sure exceptions cannot be generated
		AllowFail=1;
		wEndScene(d3dDevice7);				// Surface is lost can happen here
		AllowFail=0;
		InsideBeginScene=0;
		GameOSFPU();						// Restore current GameOS FPU control word setup
		Rendererd=1;						// Flag rendered somthing this frame (ie: do a blit or flip!)
//
// If in examine color mode, find the pixel under the mouse cursor
//
		#ifdef LAB_ONLY
		if( RenderMode==ExamineColor )
		{
			DDSURFACEDESC2 BBddsd;
			BBddsd.dwSize = sizeof(BBddsd);
			wLock( BackBufferSurface, NULL, &BBddsd, DDLOCK_WAIT | DDLOCK_READONLY, NULL );
			
			DWORD Pixel;
			if( DBMouseY>=Environment.screenHeight )
				DBMouseY=Environment.screenHeight-1;
			if( DBMouseX>=Environment.screenWidth )
				DBMouseX=Environment.screenWidth-1;
			
			if( BBddsd.ddpfPixelFormat.dwRGBBitCount==16 )
			{
				Pixel=*(WORD*)((BYTE*)BBddsd.lpSurface+BBddsd.lPitch*DBMouseY+DBMouseX*2);
			}
			else
			{
				Pixel=*(DWORD*)((BYTE*)BBddsd.lpSurface+BBddsd.lPitch*DBMouseY+DBMouseX*4);
			}
			DBPixelColor=Pixel;
			wUnlock( BackBufferSurface, NULL );
		}
		#endif
//
// Kill parallelism by locking back buffer every other frame
//
		ParallelFrame++;
		if( !gEnableParallel && (ParallelFrame&1) )
		{
			DDSURFACEDESC2 BBddsd;
			BBddsd.dwSize = sizeof(BBddsd);
			wLock( BackBufferSurface, NULL, &BBddsd, DDLOCK_WAIT, NULL );
			volatile BYTE temp=*(BYTE*)BBddsd.lpSurface;
			temp=temp;
			wUnlock( BackBufferSurface, NULL );
		}
	}
	else
	{
		if( gCaptureScreen && (gCaptureDevice == 0))
		{
			gCaptureScreen=0;
			Rendererd=1;
		}
		else
			Rendererd=0;						// Flag DID NOT render anything this frame (ie: do NOT do a blit or flip!)
	}
	if( VertexBuffersLocked && !TerminateGame )
		STOP(( "Vertex buffer still locked at EndScene"	));
	if( pStateStack && !TerminateGame )
		STOP(( "States pushed on the stack at EndScene" ));
}


//
// Either flips (full screen) or Blts the backbuffer to the primary
//
void DisplayBackBuffer()
{
	RECT Window;
	
	if( !Rendererd )						// If nothing rendered, do not blit or flip
		return;

	if( g_DDstate==1 && (ShowFrame || (0==FrameAdvance || 1==FrameAdvance)) )
	{
		AllowFail=1;
		ShowFrame=0;
		if( g_DDperformFlip )
		{
			if( FrontBufferSurface )
			{
				if( !HardwareRenderer || !Environment.fullScreen || GameNoVsync || gForceNoFlip || Environment.DirtyRectangle )
				{
					Window.left=clientToScreen.x;
					Window.right=clientToScreen.x+Environment.screenWidth;
					Window.top=clientToScreen.y;
					Window.bottom=clientToScreen.y+Environment.screenHeight;
					if( Environment.fullScreen )
					{
						Window.left=0;
						Window.right=Environment.screenWidth;
						Window.top=0;
						Window.bottom=Environment.screenHeight;
					}
//
// Wait until the previous frames BLT has completed
//
					while( DDERR_WASSTILLDRAWING==FrontBufferSurface->GetBltStatus(DDGBS_ISBLTDONE) );
//
// Now BLT to the front buffer (primary)
//
					wBlt( FrontBufferSurface, &Window, BackBufferSurface, NULL, DDBLT_WAIT, NULL );
				}		
				else
				{
#if 0
					//sanghoon marker
extern bool sh_game_started;
					static FILE* fp=0;
					static recorded_count=0;
					static double* pp;
					if(fp){
						if(recorded_count<3000){
							DWORD* lpsurf=(DWORD*)GetSurfacePointer(BackBufferSurface);
							/*
							double * lpdsurf=(double*)lpsurf;
							double * p=pp;
							lpdsurf++;lpdsurf=(double*)((DWORD)lpdsurf&0xFFFFFFF8);
							p++;p=(double*)((DWORD)p&0xFFFFFFF8);
							for(int i=0;i<800*600*2/sizeof(double)-1;i++){
								*p++=*lpdsurf++;
							}
							*/
							//CopyMemory(pp,lpsurf,800*600*2);
							//fwrite(pp,2,800*600,fp);
							//fwrite(lpsurf,2,800*600,fp);
							__int64 memory;
							GetTimeStampStart(memory);
							_asm
							{
								mov edx,lpsurf
								mov ecx,800*600*2/(16*4)

	vlp5:						mov ebx,dword ptr [edx+4* 0]
								mov ebx,dword ptr [edx+4* 1]
								mov ebx,dword ptr [edx+4* 2]
								mov ebx,dword ptr [edx+4* 3]
								mov ebx,dword ptr [edx+4* 4]
								mov ebx,dword ptr [edx+4* 5]
								mov ebx,dword ptr [edx+4* 6]
								mov ebx,dword ptr [edx+4* 7]
								mov ebx,dword ptr [edx+4* 8]
								mov ebx,dword ptr [edx+4* 9]
								mov ebx,dword ptr [edx+4*10]
								mov ebx,dword ptr [edx+4*11]
								mov ebx,dword ptr [edx+4*12]
								mov ebx,dword ptr [edx+4*13]
								mov ebx,dword ptr [edx+4*14]
								mov ebx,dword ptr [edx+4*15]

								add edx,4*16

								dec ecx
								jnz vlp5
							}
							GetTimeStampEnd(memory);
							fprintf(fp,"%I64d\n",memory);
							ReleaseSurfacePointer(BackBufferSurface);
							recorded_count++;
						}else{
							fclose(fp);
							free(pp);
						}
					}else{
						if(sh_game_started){
							fp=fopen("c:\\frames.bin","wb");
							pp=(double*)malloc(800*600*2);
						}
					}
					//sanghoon marker
#endif
					wFlip( FrontBufferSurface,NULL,DDFLIP_DONOTWAIT );//|DDFLIP_INTERVAL2   );
					//sanghoon marker..
					//sanghoon
					//wFlip( FrontBufferSurface,NULL,DDFLIP_WAIT );
				}
			}
			else
			{
//
// GDI is being used to color convert and blit the back buffer (16 or 256 color mode)
//
				HDC SourceDC;
				wGetDC( BackBufferSurface, &SourceDC );
				HDC WinDC=GetDC(hWindow);
				if( DesktopBpp==8 )
				{
					SetStretchBltMode( WinDC, HALFTONE );
					StretchBlt( WinDC, 0, 0, Environment.screenWidth, Environment.screenHeight, SourceDC, 0, 0, Environment.screenWidth, Environment.screenHeight, SRCCOPY );
				}
				else
				{
					BitBlt( WinDC, 0, 0, Environment.screenWidth, Environment.screenHeight, SourceDC, 0, 0, SRCCOPY );
				}
				ReleaseDC( hWindow, WinDC );
				wReleaseDC( BackBufferSurface, SourceDC );
			}
		}
		AllowFail=0;
	}
//
// Check for any textures waiting to be preloaded for the next frame
//
	CheckPreloadTextures();
//
// Reset the 'mode changed flag'
//
	ModeChanged=0;
}




//
//
//
//
//
void DirectDrawRelease()
{
//sanghoon begin
	if(use_shgui){
		HSH_DirectDrawRelease2();
	}
//sanghoon end

	SPEW(( GROUP_DIRECTDRAW, "DirectDrawRelease()" ));
	SafeFPU();
//
// Release the captured mouse
//
	ClipCursor( NULL );
//
// Release the clipper
//
	if (ClipperObject)
	{
		if( FrontBufferSurface )
			wSetClipper( FrontBufferSurface, 0 );
		wRelease(ClipperObject);
		ClipperObject = NULL;
	}
//
// Set any texture stages to NULL
//
	if( Maind3dDevice7 )
	{
		wSetTexture( Maind3dDevice7, 0, 0 );
		wSetTexture( Maind3dDevice7, 1, 0 );
		wSetTexture( Maind3dDevice7, 2, 0 );
	}

//
// Release any video memory textures
//
	ReleaseTextureHeap( 0 );
	SafeFPU();

//
// If there are any textures on the 'Freed' list, delete them now.
// This is to accomodate bad cards like the Intel 740 that do not like
// their textures to be released in the middle of rendering. For those 
// cards, instead of releasing textures that are no longer needed we hold
// them (and reuse them if we can) in this 'Freed' list until we can finally 
// release them safely here just before cleaning up DirectDraw.
//
	VidMemHeap* pLast=0;
	VidMemHeap* pNewEmptyTexture=pFreeVidMemTextures;

	while( pNewEmptyTexture )
	{
		pLast=pNewEmptyTexture;
		pNewEmptyTexture=pNewEmptyTexture->pNext;
		wRelease( pLast->Surface );
		gos_Free( pLast );
	}
	pFreeVidMemTextures=0;
//
// Mark all vertex buffers as invalid (And release them)
//
	InvalidateVertexBuffers();
	SafeFPU();
//
// Destroy render to texture ability
//
	DestroyRenderToTexture();
//
// Release any 3D objects
//
	if( InsideBeginScene && d3dDevice7 )
	{
		wEndScene(d3dDevice7);
		InsideBeginScene=0;
	}
	if( Maind3dDevice7 )
	{
		wRelease( Maind3dDevice7 );
		Maind3dDevice7=0;
	}
	if( d3d7 )
	{
		wRelease( d3d7 );
		d3d7=0;
	}
	DestroyDirtyRectangles();
	if( ZBufferSurface )
	{
		AllowFail=1;
		wDeleteAttachedSurface( BackBufferSurface, 0, ZBufferSurface );
		AllowFail=0;
		wRelease( ZBufferSurface );
		ZBufferSurface=0;
	}
	//sanghoon marker
	//DirectDrawRelease
	if( SH_TargetBufferSurface)
	{
		wRelease( SH_TargetBufferSurface );
		SH_TargetBufferSurface=0;
	}
	if( SH_SwirlTexture)
	{
		wRelease( SH_SwirlTexture );
		SH_SwirlTexture=0;
	}
	if( SH_GameEndTexture)
	{
		wRelease( SH_GameEndTexture );
		SH_GameEndTexture=0;
	}
	//sanghoon marker
	if( GammaControlInterface )
	{
		wRelease( GammaControlInterface );
		GammaControlInterface=0;
	}
	if( ColorControlInterface )
	{
		wRelease( ColorControlInterface );
		ColorControlInterface=0;
	}
	if( BackBufferSurface)
	{
		wRelease( BackBufferSurface );
		BackBufferSurface=0;
	}
	if( FrontBufferSurface)
	{
		wRelease( FrontBufferSurface );
		FrontBufferSurface=0;
	}
//
// If in a full screen mode release it.
//
	if( Environment.fullScreen && 0!=CurrentDDobject)
	{
		SafeFPU();					// Make sure exceptions cannot be generated
		AllowFail=1;
		wRestoreDisplayMode( CurrentDDobject );
		AllowFail=0;
		wSetCooperativeLevel( CurrentDDobject, hWindow, DDSCL_NORMAL );
		
		SPEW(( GROUP_DIRECTDRAW, "SetWindowLong" ));
		SetWindowLong( hWindow, GWL_STYLE, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX|WS_VISIBLE );
		
		SPEW(( GROUP_DIRECTDRAW, "SetWindowPos" ));
		SetWindowPos(hWindow,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_DRAWFRAME|SWP_SHOWWINDOW);

		SPEW(( GROUP_DIRECTDRAW, "SetWindowPlacement" ));
		WindowPlacement.length=sizeof(WINDOWPLACEMENT);
		WindowPlacement.showCmd = SW_SHOWNOACTIVATE;
		SetWindowPlacement( hWindow,&WindowPlacement );

		SPEW(( GROUP_DIRECTDRAW, "Releasing full screen DirectDraw object" ));
		wRelease( CurrentDDobject );
	}
//
// The persistant DDobject is always the current one again
//
	CurrentDDobject=DDobject;
//
//
//
	GameOSFPU();
	SPEW(( GROUP_DIRECTDRAW, "DirectDrawRelease()  Finished" ));
}










//
//
// Create the primary direct draw object and make a list of all valid devices
//
//
void DirectDrawCreateDDObject()
{
//
// Get details on all video cards installed in the system
//
	FindVideoCards();
//
// Create the NULL (primary) DirectDraw object
//
	//sanghoon marker
	/*
	wDirectDrawCreateEx( &DeviceArray[0].DeviceGUID, (void**)&DDobject, IID_IDirectDraw7, NULL );
//	wDirectDrawCreateEx( &DeviceArray[Environment.FullScreenDevice].DeviceGUID, (void**)&DDobject, IID_IDirectDraw7, NULL );
	wSetCooperativeLevel( DDobject, hWindow, DDSCL_NORMAL );
	CurrentDDobject=DDobject;
	*/
	//sanghoon ..
	//wDirectDrawCreateEx(&DeviceArray[0].DeviceGUID, (void**)&DDobject, IID_IDirectDraw7, NULL );
	wDirectDrawCreateEx(NULL, (void**)&DDobject, IID_IDirectDraw7, NULL );

	wSetCooperativeLevel( DDobject, hWindow, DDSCL_NORMAL );
	CurrentDDobject=DDobject;
	//sanghoon marker
//
//
//
	FirstTime=1;
}



//
// Attempt to setup mode, return true if ok
//  Software never fails
//  Renderer 0=Hardware, 1=RGB, 2=Refrast, 3=Blade
//
bool SetupMode( bool FullScreen, DWORD Renderer )
{
	DWORD result=0;
	
	DeviceInfo* CurrentDevice;
	HardwareRenderer=(Renderer==0);
	FrontBufferSurface=0;
	BackBufferSurface=0;
	ClipperObject=0;
	ZBufferSurface=0;
	//sanghoon marker
	SH_TargetBufferSurface = 0;
	SH_SwirlTexture=0;
    SH_GameEndTexture=0;
	//sanghoon marker
	Maind3dDevice7=0;
	d3dDevice7=0;
	DDSURFACEDESC2 ddsd;
//
// Get pointer to current video device
//
	CurrentDevice=&DeviceArray[FullScreen ? Environment.FullScreenDevice : 0 ];
//
// Setup compatibility flags for current card/renderer
//
	if( 0==Renderer )
	{
		if( gNumberCompatFlags==2 )
		{
			if( -1==CurrentDevice->CurrentCard )
				Compatibility3D = 0;
			else
			    Compatibility3D =(KnownCards[ CurrentDevice->CurrentCard ].CompatibilityFlags & ~gCompatFlags) | gCompatFlags1;
		}
		else
		{
			if( gCompatFlags )
				Compatibility3D = gCompatFlags;
			else
			{
				if( -1==CurrentDevice->CurrentCard )
					Compatibility3D = 0;
				else
				{
				    Compatibility3D = KnownCards[ CurrentDevice->CurrentCard ].CompatibilityFlags;
				    if( KnownCards[ CurrentDevice->CurrentCard ].VendorID==0x1002 && KnownCards[ CurrentDevice->CurrentCard ].DeviceID==0x4742 && WindowsNT )
					    Compatibility3D&=~TextureOffset;
                }
			}
		}
	}
	else
	{
		Compatibility3D=0;					// All software rasterizers
	}
//
// Check for card memory and alter defaults
//
	if( Compatibility3D & NoParallelism )
		gEnableParallel=0;
	else
		gEnableParallel=1;
//
// If 4Meg or more texture memory available, force triple buffer
//
	TripleBuffer=0;
	Environment.TripleBuffer=1;
	if( FullScreen && Environment.TripleBuffer )
	{
		TripleBuffer=1;
	}
//
// 3Dfx cards have broken triple buffer hardware currently - so disable it on them
//
	if( Compatibility3D & NoTripleBuffer )
		TripleBuffer=0;
//
// Make full screen blit not flip
//
	if( (Compatibility3D&DefaultBltNotFlip) && FullScreen )
		gForceNoFlip=1;
	else
		gForceNoFlip=0;
//
// Re-read current desktop BPP in case it has changed
//
	DesktopBpp=GetDeviceCaps(DesktopDC,BITSPIXEL);
//
// If wanting hardware acceleration and not 16 or 32 bit mode, fail
//
	if( HardwareRenderer && (DesktopBpp!=16 && DesktopBpp!=32) )
		goto Failed;
//
// Setup full screen or window mode
//
	if( FullScreen )
	{
//
// Full Screen mode - Create the primary and either one or two backbuffers
//
		if( HardwareRenderer || (Environment.RenderToVram && Environment.bitDepth==16) )
		{
			memset(&ddsd,0,sizeof(ddsd));
			ddsd.dwSize = sizeof(ddsd);
			ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
			ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE;
			ddsd.ddsCaps.dwCaps2 = (Environment.AntiAlias && HardwareRenderer) ? DDSCAPS2_HINTANTIALIASING : 0;
			ddsd.dwBackBufferCount = TripleBuffer ? 2 : 1;
//
// If triple buffering fails, use double
//
			AllowFail=TRUE;
			HRESULT result=wCreateSurface( CurrentDDobject, &ddsd, &FrontBufferSurface, NULL);
			AllowFail=FALSE;
			if( FAILED(result) )
			{
				SPEW(( GROUP_DIRECTDRAW, "Triple buffering failed - %s",ErrorNumberToMessage(result) ));
				ddsd.dwBackBufferCount=1;
				AllowFail=TRUE;
				result=wCreateSurface( CurrentDDobject, &ddsd, &FrontBufferSurface, NULL);
				AllowFail=FALSE;
				if( FAILED(result) )
					goto Failed;
			}
//
// Get the backbuffer (And AddRef it - so it can be freed as in a window mode)
//
			DDSCAPS2 ddscaps2;
			memset( &ddscaps2, 0, sizeof(ddscaps2) );
			ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
			wGetAttachedSurface( FrontBufferSurface, &ddscaps2, &BackBufferSurface );
//
// Full Screen - software renderer
//
		}
		else
		{
			if( !HardwareRenderer && Environment.bitDepth!=16 )
			{
//
// Create a 555 backbuffer for blade
//
				memset(&ddsd,0,sizeof(ddsd));
				ddsd.dwSize = sizeof(ddsd);
				ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
				ddsd.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY;
				ddsd.dwWidth = Environment.screenWidth;
				ddsd.dwHeight = Environment.screenHeight;
				ddsd.ddpfPixelFormat.dwSize				= sizeof(DDPIXELFORMAT);
				ddsd.ddpfPixelFormat.dwFlags			= DDPF_RGB;
				ddsd.ddpfPixelFormat.dwRGBBitCount		= 16;
				ddsd.ddpfPixelFormat.dwRBitMask			= 0x00007c00;
				ddsd.ddpfPixelFormat.dwGBitMask			= 0x000003e0;
				ddsd.ddpfPixelFormat.dwBBitMask			= 0x0000001f;

				AllowFail=TRUE;
				HRESULT result=wCreateSurface( DDobject, &ddsd, &BackBufferSurface, NULL );
				AllowFail=FALSE;
				if( FAILED(result) )
					goto Failed;
			}
			else
//
// Get the primary
//
			{
				memset(&ddsd,0,sizeof(ddsd));
				ddsd.dwSize = sizeof(ddsd);
				ddsd.dwFlags = DDSD_CAPS;
				ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
				wCreateSurface( CurrentDDobject, &ddsd, &FrontBufferSurface, NULL );
//
// Create the backbuffer
//
				memset(&ddsd,0,sizeof(ddsd));
				ddsd.dwSize = sizeof(DDSURFACEDESC2);
				ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
				ddsd.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE;
				ddsd.dwWidth = Environment.screenWidth;
				ddsd.dwHeight = Environment.screenHeight;

				AllowFail=TRUE;
				HRESULT result=wCreateSurface( CurrentDDobject, &ddsd, &BackBufferSurface, NULL );
				AllowFail=FALSE;
				if( FAILED(result) )
				{
					STOP(( "Could not create backbuffer - %s", ErrorNumberToMessage(result) ));
				}
			}
		}
	}
	else
	{
		if( !HardwareRenderer && DesktopBpp!=16 )
		{
//
// Create a 555 backbuffer for blade
//
			memset(&ddsd,0,sizeof(ddsd));
			ddsd.dwSize = sizeof(ddsd);
			ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
			ddsd.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY;
			ddsd.dwWidth = Environment.screenWidth;
			ddsd.dwHeight = Environment.screenHeight;
			ddsd.ddpfPixelFormat.dwSize				= sizeof(DDPIXELFORMAT);
			ddsd.ddpfPixelFormat.dwFlags			= DDPF_RGB;
			ddsd.ddpfPixelFormat.dwRGBBitCount		= 16;
			ddsd.ddpfPixelFormat.dwRBitMask			= 0x00007c00;
			ddsd.ddpfPixelFormat.dwGBitMask			= 0x000003e0;
			ddsd.ddpfPixelFormat.dwBBitMask			= 0x0000001f;

			AllowFail=TRUE;
			HRESULT result=wCreateSurface( DDobject, &ddsd, &BackBufferSurface, NULL );
			AllowFail=FALSE;
			if( FAILED(result) )
				goto Failed;
		}
		else
//
// Window 16 or 32 bit mode - Get the primary (This result in unsupported mode in ^ alt del)
//
		{
			memset(&ddsd,0,sizeof(ddsd));
			ddsd.dwSize = sizeof(ddsd);
			ddsd.dwFlags = DDSD_CAPS;
			ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
			bool NoExitLoop=0;
			do
			{
				NoExitLoop=0;
				AllowFail=1;
				FrontBufferSurface=0;
				result=wCreateSurface( DDobject, &ddsd, &FrontBufferSurface, NULL );
				AllowFail=0;
			
				if( DDERR_UNSUPPORTEDMODE==result || 0==FrontBufferSurface )
				{
					WaitMessage();
					NoExitLoop=1;				// Must be in ^Alt Del mode - spin and give up time to windows
				}
					
			} while( NoExitLoop );
//
// Create a clipper for the window
//
			wCreateClipper( DDobject,0, &ClipperObject, NULL );
			wSetHWnd( ClipperObject, 0, hWindow );
			wSetClipper( FrontBufferSurface, ClipperObject );
//
// Create the backbuffer
//
			memset(&ddsd,0,sizeof(ddsd));
			ddsd.dwSize = sizeof(ddsd);
			ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
			ddsd.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN + DDSCAPS_3DDEVICE + ((HardwareRenderer || Environment.RenderToVram ) ? DDSCAPS_VIDEOMEMORY : DDSCAPS_SYSTEMMEMORY);
			ddsd.ddsCaps.dwCaps2 = (Environment.AntiAlias && HardwareRenderer) ? DDSCAPS2_HINTANTIALIASING : 0;
			ddsd.dwWidth = Environment.screenWidth;
			ddsd.dwHeight = Environment.screenHeight;

			AllowFail=TRUE;
			HRESULT result=wCreateSurface( DDobject, &ddsd, &BackBufferSurface, NULL );
			AllowFail=FALSE;
			if( FAILED(result) )
				goto Failed;
		}
	}
//
// Clear the back buffer in case an exception may cause it to be displayed
//
	DDBLTFX ddbltfx;
	memset( &ddbltfx, 0, sizeof(ddbltfx) );
	ddbltfx.dwSize=sizeof(ddbltfx);
	SafeFPU();
	wBlt( BackBufferSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx );
	GameOSFPU();
//
// Save the back buffer details for gosScript / Pane optimizations
//
	BackBufferddsd.dwSize = sizeof(BackBufferddsd);
	wLock( BackBufferSurface, NULL, &BackBufferddsd, DDLOCK_NOSYSLOCK | DDLOCK_WAIT | DDLOCK_READONLY, NULL );
	wUnlock( BackBufferSurface, NULL );
//
// Get the back buffer pixel format
//
	memset(&BBddsd,0,sizeof(ddsd));
	BBddsd.dwSize = sizeof(DDSURFACEDESC2);
	wGetSurfaceDesc( BackBufferSurface,&BBddsd );
//
// nVidia cards cannot do stencil unless 32 bit render target
//
	if( (Compatibility3D & RenderEqualZ) && BBddsd.ddpfPixelFormat.dwRGBBitCount!=32 )
		Environment.Stencil=0;
//
// Get information about the DirectDraw object I'm using
//
	CapsDirectDraw.dwSize = sizeof(CapsDirectDraw);
	if( HardwareRenderer )
		wGetCaps( CurrentDDobject, &CapsDirectDraw, 0);
	else
		wGetCaps( CurrentDDobject, 0, &CapsDirectDraw );
//
// Setup a 16 bit Z Buffer (App is optimized for 16 bit)
//
	if( Environment.disableZBuffer )
	{
		ZBufferSurface=0;
	}
	else
	{
//
// Try creating a 32 bit Z buffer with 8 bit stencil
//
		result=-1;
		if( Environment.Stencil && HardwareRenderer )
		{
			memset( &ddsd, 0 ,sizeof(ddsd) );
			ddsd.dwSize								= sizeof(ddsd); 
			ddsd.dwFlags							= DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
			ddsd.ddsCaps.dwCaps						= DDSCAPS_ZBUFFER | (HardwareRenderer ? DDSCAPS_VIDEOMEMORY : DDSCAPS_SYSTEMMEMORY);
			ddsd.dwWidth							= Environment.screenWidth; 
			ddsd.dwHeight							= Environment.screenHeight; 
			ddsd.ddpfPixelFormat.dwSize				= sizeof(DDPIXELFORMAT);
			ddsd.ddpfPixelFormat.dwFlags			= DDPF_ZBUFFER|DDPF_STENCILBUFFER;
			ddsd.ddpfPixelFormat.dwZBufferBitDepth	= 32;
			ddsd.ddpfPixelFormat.dwZBitMask			= 0xffffff00;
			ddsd.ddpfPixelFormat.dwStencilBitDepth	= 8;
			ddsd.ddpfPixelFormat.dwStencilBitMask	= 0x000000ff;

			AllowFail=1;
			result=wCreateSurface( CurrentDDobject, &ddsd, &ZBufferSurface, NULL );
			AllowFail=0;
		}
//
// Create a 16 bit Z buffer with no stencil
//
		if( FAILED(result) )
		{
			memset( &ddsd, 0 ,sizeof(ddsd) );
			ddsd.dwSize								= sizeof(ddsd); 
			ddsd.dwFlags							= DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
			ddsd.ddsCaps.dwCaps						= DDSCAPS_ZBUFFER | (HardwareRenderer ? DDSCAPS_VIDEOMEMORY : DDSCAPS_SYSTEMMEMORY);
			ddsd.dwWidth							= Environment.screenWidth; 
			ddsd.dwHeight							= Environment.screenHeight; 
			ddsd.ddpfPixelFormat.dwSize				= sizeof(DDPIXELFORMAT);
			ddsd.ddpfPixelFormat.dwFlags			= DDPF_ZBUFFER;
			ddsd.ddpfPixelFormat.dwZBufferBitDepth	= 16;
			ddsd.ddpfPixelFormat.dwZBitMask			= 0xffff;

			AllowFail=1;
			result=wCreateSurface( CurrentDDobject, &ddsd, &ZBufferSurface, NULL );
			AllowFail=0;
		}
//
// If screen bit depth is 32 bit, try a 32 bit Z Buffer
//
		if( FAILED(result) && Environment.bitDepth==32 )
		{
			ddsd.ddpfPixelFormat.dwZBufferBitDepth	= 32;
			ddsd.ddpfPixelFormat.dwZBitMask			= 0xffffffff;
			AllowFail=1;
			result=wCreateSurface( CurrentDDobject, &ddsd, &ZBufferSurface, NULL );
			AllowFail=0;
		}
//
// Otherwise cannot use this mode (out of memory?)
//
		if( FAILED(result) )
		{
			SPEW(( GROUP_DIRECTDRAW, "Could not create Z Buffer (%s)",ErrorNumberToMessage(result) ));
			goto Failed;
		}
		wAddAttachedSurface( BackBufferSurface, ZBufferSurface );

		//sanghoon marker
		{
			DDSURFACEDESC2 rdesc;
			memset(&rdesc,0,sizeof(ddsd));
			rdesc.dwSize = sizeof(rdesc);
			rdesc.dwFlags = DDSD_CAPS| DDSD_WIDTH | DDSD_HEIGHT ;
			rdesc.dwWidth	= 128;
			rdesc.dwHeight	= 128;
			//rdesc.ddsCaps.dwCaps =  DDSCAPS_NONLOCALVIDMEM |DDSCAPS_VIDEOMEMORY  | DDSCAPS_OFFSCREENPLAIN ;
			rdesc.ddsCaps.dwCaps =  DDSCAPS_LOCALVIDMEM |DDSCAPS_VIDEOMEMORY  | DDSCAPS_OFFSCREENPLAIN;// | DDSCAPS_3DDEVICE;
			//rdesc.ddsCaps.dwCaps =  DDSCAPS_OFFSCREENPLAIN ;
			if(FAILED(wCreateSurface( CurrentDDobject, &rdesc, &SH_TargetBufferSurface, NULL ))){
				;//MessageBeep(0);
			}

			const DDPIXELFORMAT DDPF_R5G6B5={sizeof(DDPIXELFORMAT),DDPF_RGB,0,16,0xF800,0x07E0,0x001F,};

			rdesc.dwFlags		 = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_TEXTURESTAGE;
			rdesc.ddsCaps.dwCaps  = DDSCAPS_TEXTURE;
			rdesc.dwWidth	= 256;
			rdesc.dwHeight	= 256;
			rdesc.ddpfPixelFormat = DDPF_R5G6B5;
			rdesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;

			if(SUCCEEDED(wCreateSurface( CurrentDDobject, &rdesc, &SH_SwirlTexture, NULL ))){
				;
				//Draw texture content to screen.   .
			}

			rdesc.dwFlags		 = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_TEXTURESTAGE;
			rdesc.ddsCaps.dwCaps  = DDSCAPS_TEXTURE;
			rdesc.dwWidth	= 1024;
			rdesc.dwHeight	= 1024;
			rdesc.ddpfPixelFormat = DDPF_R5G6B5;
			rdesc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;

			if(SUCCEEDED(wCreateSurface( CurrentDDobject, &rdesc, &SH_GameEndTexture, NULL ))){
				;
				//Draw texture content to screen.   .
			}

		}
		//sanghoon marker
//
// Get the Z buffer pixel format (nVidia may always match front bit depth)
//
		memset( &ZBddsd, 0, sizeof(ZBddsd) );
		ZBddsd.dwSize = sizeof(DDSURFACEDESC2);
		wGetSurfaceDesc( ZBufferSurface, &ZBddsd );
	}
//
// Set flag if stencil supported
//
	StencilValid=ZBddsd.ddpfPixelFormat.dwStencilBitDepth==8;
//
// Create masks for Fog and Background fill colors to match textures
//
	BGMask= (GetColor( 0xffffff, BBddsd.ddpfPixelFormat.dwRBitMask )<<16)+
			(GetColor( 0xffffff, BBddsd.ddpfPixelFormat.dwGBitMask )<<8)+
			 GetColor( 0xffffff, BBddsd.ddpfPixelFormat.dwBBitMask );
//
// Create the IDirect3D7 device
//
	wQueryInterface( CurrentDDobject, IID_IDirect3D7, (void**)&d3d7 );
	gos_MathExceptions(0,0);

	HasTLHAL=0;
    if( Renderer>=3 )
	{
		if( BBddsd.ddpfPixelFormat.dwRGBBitCount!=16 )
			STOP(( gos_GetResourceString(gLanguageDLL, GOS_DXRASTERIZER_BLADEONLY16) ));
		AllowFail=1;
		if( gNoBlade )
			result=wCreateDevice( d3d7, IID_IDirect3DRGBDevice, BackBufferSurface, &Maind3dDevice7 );
		else
			result=wCreateDevice( d3d7, IID_IDirect3DBladeDevice, BackBufferSurface, &Maind3dDevice7 );
		AllowFail=0;
	}
	else if( Renderer==0 )
	{
		if( gDisableHardwareTandL )
		{
			AllowFail=1;
			result=wCreateDevice( d3d7, IID_IDirect3DHALDevice, BackBufferSurface, &Maind3dDevice7 );
			AllowFail=0;
		}
		else
		{
			AllowFail=1;
			result=wCreateDevice( d3d7, IID_IDirect3DTnLHalDevice, BackBufferSurface, &Maind3dDevice7 );
			AllowFail=0;
			if( FAILED(result) )
			{
				AllowFail=1;
				result=wCreateDevice( d3d7, IID_IDirect3DHALDevice, BackBufferSurface, &Maind3dDevice7 );
				AllowFail=0;
			}
			else
			{
				HasTLHAL=1;
			}
		}
	}
	else if( Renderer==1 )
	{
		AllowFail=1;
		result=wCreateDevice( d3d7, IID_IDirect3DRGBDevice, BackBufferSurface, &Maind3dDevice7 );
		AllowFail=0;
	}
	else
	{
		AllowFail=1;
		result=wCreateDevice( d3d7, IID_IDirect3DRefDevice, BackBufferSurface, &Maind3dDevice7 );
		AllowFail=0;
	}
	gos_MathExceptions(1,0);
	if( FAILED(result) )
	{
		SPEW(( GROUP_DIRECTDRAW, "Could not create 3D device ( %s)",ErrorNumberToMessage(result) ));
		goto Failed;
	}
//
// Save a copy of the d3dDevice
//
	d3dDevice7=Maind3dDevice7;
//
// Create a viewport, attach it to the device
//
	viewData.dwX		= 0;
	viewData.dwY		= 0;
	viewData.dwWidth	= Environment.screenWidth;
	viewData.dwHeight	= Environment.screenHeight;
	viewData.dvMinZ		= 0.0f;
	viewData.dvMaxZ		= 1.0f;
    wSetViewport( d3dDevice7, &viewData );
//
// Get information about the current 3D Device
//
	wGetCaps( d3dDevice7, &CapsDirect3D );
//
// Oxygen GVX1 cards have bad cap - check and reset it here
//
// If the max texture repeat is scaled by the texture size, make sure the largest texture size is supported!
//
	if( CapsDirect3D.dwMaxTextureRepeat && 0==(CapsDirect3D.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE) )
	{
		if( CapsDirect3D.dwMaxTextureRepeat <= CapsDirect3D.dwMaxTextureHeight )
			CapsDirect3D.dpcTriCaps.dwTextureCaps|=D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE;
	}
//
// Riva 128 cards claim 2k*2k texture size possible - reduce this!
//
	if( Compatibility3D&LimitTextureSize )
	{
		CapsDirect3D.dwMaxTextureHeight=256;
		CapsDirect3D.dwMaxTextureWidth=256;
	}
//
// Do not allow non-square textures if certain drivers have problems
//
	if( Compatibility3D&ForceSquareTextures )
	{
		CapsDirect3D.dpcTriCaps.dwTextureCaps|=D3DPTEXTURECAPS_SQUAREONLY;
	}
//
// Make sure at least 1 valid texture format is supported
//
	ValidTextures=0;
	AllowFail=1;
	result=wEnumTextureFormats( d3dDevice7, CheckEnumProc, 0 );
	AllowFail=0;
	if( FAILED(result) || 0==ValidTextures )
	{
		SPEW(( GROUP_DIRECTDRAW, "3D device does not support valid texture formats" ));
		goto Failed;
	}
//
//	Not enough texture memory?
//
	if( 0==gUse3D && HardwareRenderer )
	{
		DWORD CardMemory=CurrentDevice->TotalLocalTex;
//
// If a split video memory card like a Voodoo, double the texture memory.
//
		if( Compatibility3D&AllowLowMemoryCard )
			CardMemory*=2;
//
// If AGP not broken, include in texture memory estimates
//
		if( 0==(Compatibility3D&BadAGP) )
			CardMemory+=CurrentDevice->TotalTex;	
//
// Check for enough texture memory (Voodoo 2 allowed)
//
		if( Environment.MinimumTextureMemory && (CardMemory<Environment.MinimumTextureMemory*1024) )
		{	
			SPEW(( GROUP_DIRECTDRAW, "3D device did not support enough texture memory (%d bytes)",CurrentDevice->TotalLocalTex ));
			goto Failed;
		}
//
// Check for 'LowEndCard' flag
//
		if( Environment.DisableLowEndCard && (Compatibility3D&LowEndCard) )
		{
			SPEW(( GROUP_DIRECTDRAW, "3D device is on low end card list" ));
			goto Failed;
		}
//
// If attempting dirty rectange blitting, disallow PowerVR type cards
//
		if( Environment.DirtyRectangle )
		{
			SPEW(( GROUP_DIRECTDRAW, "Card is a scene based renderer" ));
			if( 0!=(CapsDirectDraw.dwCaps2 & DDCAPS2_NO2DDURING3DSCENE) )
				goto Failed;
		}
//
// Test the device to see if it meets minimum requirements
//
		if( 0==(CapsDirect3D.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_NEAREST)
		 || 0==(CapsDirect3D.dpcTriCaps.dwSrcBlendCaps & D3DPBLENDCAPS_SRCALPHA)
		 || 0==(CapsDirect3D.dpcTriCaps.dwDestBlendCaps & D3DPBLENDCAPS_INVSRCALPHA)
		 || 0==(CapsDirect3D.dpcTriCaps.dwMiscCaps & D3DPMISCCAPS_CULLNONE)
		 || 0==(CapsDirect3D.dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_MODULATE)
		 || 0==(CapsDirect3D.dpcTriCaps.dwTextureAddressCaps & D3DPTADDRESSCAPS_WRAP)
		 || 0==(CapsDirect3D.dpcTriCaps.dwTextureCaps&D3DPTEXTURECAPS_PERSPECTIVE) )
		{
			SPEW(( GROUP_DIRECTDRAW, "3D device does not support base capabilities" ));
			goto Failed;
		}
	}
//
// If using dirty rectangles, create copy buffers
//
	CreateCopyBuffers();
//
// Mode passed
//
	return 1;

//
// Failed - release everything created
//
Failed:
	SafeFPU();
	if( d3dDevice7 )
	{
		wRelease( d3dDevice7 );
		d3dDevice7=0;
        Maind3dDevice7=0;
    }
	if( d3d7 )
	{
		wRelease( d3d7 );
		d3d7=0;
	}
	if( ZBufferSurface )
	{
		AllowFail=1;
		wDeleteAttachedSurface( BackBufferSurface, 0, ZBufferSurface );
		AllowFail=0;
		wRelease( ZBufferSurface );
		ZBufferSurface=0;
	}
	//sanghoon
	//SetupMode
	if( SH_TargetBufferSurface)
	{
		wRelease( SH_TargetBufferSurface );
		SH_TargetBufferSurface=0;
	}
	if( SH_GameEndTexture)
	{
		wRelease( SH_GameEndTexture );
		SH_GameEndTexture=0;
	}
	if( SH_SwirlTexture)
	{
		wRelease( SH_SwirlTexture );
		SH_SwirlTexture=0;
	}
	//sanghoon
	if( ClipperObject )
	{
		if( FrontBufferSurface )
			wSetClipper( FrontBufferSurface, 0 );
		wRelease( ClipperObject );
		ClipperObject=0;
	}
	if( GammaControlInterface )
	{
		wRelease( GammaControlInterface );
		GammaControlInterface=0;
	}
	if( ColorControlInterface )
	{
		wRelease( ColorControlInterface );
		ColorControlInterface=0;
	}
	if( BackBufferSurface )
	{
		wRelease( BackBufferSurface );
		BackBufferSurface=0;
	}
	if( FrontBufferSurface )
	{
		wRelease( FrontBufferSurface );
		FrontBufferSurface=0;
	}
	GameOSFPU();
	return 0;
}







//
// Find capabilities of mode
//
void GetModeCaps()
{
	HasGuardBandClipping=(CapsDirect3D.dvGuardBandLeft<=-2047.0f && CapsDirect3D.dvGuardBandTop<=-2047.0f && CapsDirect3D.dvGuardBandRight>=2047.0f && CapsDirect3D.dvGuardBandBottom>=2047.0f );
	MinGuardBandClip=CapsDirect3D.dvGuardBandLeft < CapsDirect3D.dvGuardBandTop ? CapsDirect3D.dvGuardBandTop : CapsDirect3D.dvGuardBandLeft;
	MaxGuardBandClip=CapsDirect3D.dvGuardBandRight > CapsDirect3D.dvGuardBandBottom ? CapsDirect3D.dvGuardBandRight : CapsDirect3D.dvGuardBandBottom;
	HasAGP=0!=(CapsDirect3D.dwDevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM);
	HasSpecular=0!=(CapsDirect3D.dpcTriCaps.dwShadeCaps & (D3DPSHADECAPS_SPECULARFLATRGB|D3DPSHADECAPS_SPECULARGOURAUDRGB) );
	HasDither=0!=(CapsDirect3D.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER);
	HasAntiAlias=0!=(CapsDirect3D.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT);
	HasMipLodBias=0!=(CapsDirect3D.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS);
	HasDecal=0!=(CapsDirect3D.dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_DECAL);
	HasModulateAlpha=0!=(CapsDirect3D.dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_MODULATEALPHA);
	HasAdd=0!=(CapsDirect3D.dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_ADD);
	HasMipMap=0!=(CapsDirect3D.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPNEAREST);
	HasClamp=0!=(CapsDirect3D.dpcTriCaps.dwTextureAddressCaps & D3DPTADDRESSCAPS_CLAMP);
	HasVertexBlending=CapsDirect3D.wMaxVertexBlendMatrices>=2;
//
// See if Mipmap allowed
//
	if( Compatibility3D&NoMipMap )
		HasMipMap=0;
//
// Find modes for bi and tri linear filtering
//
	if( HasMipMap)
	{
		HasBiLinear=0!=(CapsDirect3D.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPLINEAR);
		HasTriLinear=0!=(CapsDirect3D.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR);
	}
	else
	{
		HasBiLinear=0!=(CapsDirect3D.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR);
		HasTriLinear=0;
	}
//
// Find fog modes available
//
	HasFog=0!=(CapsDirect3D.dpcTriCaps.dwRasterCaps & (D3DPRASTERCAPS_FOGTABLE|D3DPRASTERCAPS_FOGVERTEX));
	if( Compatibility3D&NoFog )
		HasFog=0;
//
// Find if any ALPHA ONE as source modes are supported
//
	HasAlphaModes=0!=(CapsDirect3D.dpcTriCaps.dwDestBlendCaps & D3DPBLENDCAPS_ONE);
//
// See if Trilinear filtering allowed
//
	if( Compatibility3D&NoTriLinear )
		HasTriLinear=0;
//
// Find if AlphaTesting is available
//
	HasAlphaTest=0!=(CapsDirect3D.dpcTriCaps.dwAlphaCmpCaps & D3DPCMPCAPS_NOTEQUAL);
//
// See if AlphaTesting allowed
//
	if( Compatibility3D&NoAlphaTest )
		HasAlphaTest=0;
//
// No texture selected to start with, so no max u or v
//
	#ifdef _ARMOR
		HasMaxUV=0;
	#endif
//
// See if multitexture modes are possible on the current device
//
	HasMultitextureLightmap=0;
	HasMultitextureSpecularmap=0;
	HasMultitextureDetailTexture=0;
	HasMultitextureLightmapFilter=0;
	HasMultitextureSpecularmapFilter=0;
	HasMultitextureDetailTextureFilter=0;
	if( HardwareRenderer && 0==(Compatibility3D & NoMultitexture) )
	{
		DWORD Device=Environment.fullScreen ? Environment.FullScreenDevice : 0;
		HasMultitextureLightmap=DeviceArray[Device].MultitextureLightMap==D3D_OK;
		HasMultitextureSpecularmap=DeviceArray[Device].MultitextureSpecularMap==D3D_OK;
		HasMultitextureDetailTexture=DeviceArray[Device].MultitextureDetail==D3D_OK;
		HasMultitextureLightmapFilter=DeviceArray[Device].MultitextureLightMapFilter;
		HasMultitextureSpecularmapFilter=DeviceArray[Device].MultitextureSpecularMapFilter;
		HasMultitextureDetailTextureFilter=DeviceArray[Device].MultitextureDetailFilter;
	}
//
// RGB / Refrast rasterizer supports all modes
//
	else if( 1==Environment.Renderer || 2==Environment.Renderer )
	{
		HasMultitextureLightmap=1;
		HasMultitextureSpecularmap=1;
		HasMultitextureDetailTexture=1;
	}
}




//
//
// Create the front and back buffers for window or full screen mode
//
// If in 3D mode create all the 3D devices
//
void DirectDrawCreateAllBuffers()
{
	bool ValidMode=0;
//
// Debugging information
//
	SPEW(( GROUP_DIRECTDRAW, "DirectDrawCreateAllBuffers()" ));
//
// Attempt hardware unless overridden, and 16 or 32 bit desktop (And hardware was found during enumeration)
//
	if( 0==Environment.Renderer && NumHWDevices )
	{
		if( !(0==Environment.fullScreen && DesktopBpp!=16 && DesktopBpp!=32) )
		{
			ValidMode=SetupMode( Environment.fullScreen, 0 );
		}
	}
//
// If hardware not valid or renderer overridden, goto software
//
	if( !ValidMode )
	{
		if( 0==RunFullScreen && 0==Environment.Renderer && FirstTime && NumHWDevices && (DesktopBpp==16 || DesktopBpp==32) )
		{
			ErrorMessageTitle="No 3D acceleration when running in a window";
//
// Am I skipping all dialogs?
//
			if( 0==gNoDialogs )
			{
				DoColorDialog();
				if( ErrorReturn==-1 )
					ExitGameOS();
				if( ErrorReturn==1 )
				{
					for( int t0=0; t0<NumDevices; t0++ )
					{ 
						if( DeviceArray[t0].D3DCaps.dwDevCaps&D3DDEVCAPS_HWRASTERIZATION )
						{
							Environment.FullScreenDevice=t0;
							break;
						}
					}
					RunFullScreen=1;
				}
			}
		}
//
// Try going into a software mode
//
		ValidMode=SetupMode( Environment.fullScreen, Environment.Renderer ? Environment.Renderer : 3 );
//
// If software does not have enough video memory to render there, render to system memory
//
		if( !ValidMode && Environment.RenderToVram )
		{
			Environment.RenderToVram=0;
			ValidMode=SetupMode( Environment.fullScreen, Environment.Renderer ? Environment.Renderer : 3 );
		}
	}
	FirstTime=0;
//
// If Software didn't work - really bad!
//
    if( !ValidMode )
    {
		STOP(( "No software rasterizer available" ));
    }
//
// Debugging information
//
	SPEW(( GROUP_DIRECTDRAW, "DirectDrawCreateAllBuffers() Done 2D Setup" ));
//
// Get caps, init textures
//
	GetModeCaps();
//
// Query the gamma control interface from the front buffer
//
	GammaControlInterface=0;
	if( 0==(Compatibility3D & DisableColorControl) && FrontBufferSurface && Environment.fullScreen && (CapsDirectDraw.dwCaps2&DDCAPS2_PRIMARYGAMMA) )
	{
		AllowFail=1;
		HRESULT hr=wQueryInterface( FrontBufferSurface, IID_IDirectDrawGammaControl, (void**)&GammaControlInterface );
		AllowFail=0;
		if( SUCCEEDED(hr) )
		{
			gos_SetGammaValue( UserGamma );
			UseGammaCorrection=0;
		}
	}
//
// Setup software gamma in a window or if somthing goes wrong
//
	if( 0==GammaControlInterface )
	{
		if( GammaSetting!=UserGamma )
		{
			GammaSetting=UserGamma;
			for( int t0=0; t0<256; t0++ )
			{
				GammaTable[t0]=(BYTE)(pow(t0/255.0f,1.0f/GammaSetting)*255.0);
			}
			if( GammaSetting!=1.0f )
				UseGammaCorrection=1;
			UpdatedState[gos_State_Fog]=1;			// Force fog value to be reloaded
		}
	}
//
// See if color control exist
//
	AllowBrightness=0;
	AllowContrast=0;
	ColorControlInterface=0;
	if( 0==(Compatibility3D & DisableColorControl) && FrontBufferSurface )
	{
		AllowFail=1;
		HRESULT hr=wQueryInterface( FrontBufferSurface, IID_IDirectDrawColorControl, (void**)&ColorControlInterface );
		AllowFail=0;

		if( SUCCEEDED(hr) )
		{
			DDCOLORCONTROL colcontrol;
			colcontrol.dwSize=sizeof(colcontrol);
			ColorControlInterface->GetColorControls( &colcontrol );
			if( colcontrol.dwFlags&DDCOLOR_BRIGHTNESS )
				AllowBrightness=1;
			if( colcontrol.dwFlags&DDCOLOR_CONTRAST )
				AllowContrast=1;
		}
	}
//
// Setup textures, if this fails, resort to software
//
	DWORD result=gos_RecreateTextureHeaps();

	if( 0==result && 3!=Environment.Renderer )
	{
		SafeFPU();
		if( d3dDevice7 )
		{
			wRelease( d3dDevice7 );
			d3dDevice7=0;
			Maind3dDevice7=0;
		}
		if( d3d7 )
		{
			wRelease( d3d7 );
			d3d7=0;
		}
		DestroyDirtyRectangles();
		if( ZBufferSurface )
		{
			AllowFail=1;
			wDeleteAttachedSurface( BackBufferSurface, 0, ZBufferSurface );
			AllowFail=0;
			wRelease( ZBufferSurface );
			ZBufferSurface=0;
		}
		//sanghoon marker
		//DirectDrawCreateAllBuffers
		if( SH_TargetBufferSurface)
		{
			wRelease( SH_TargetBufferSurface );
			SH_TargetBufferSurface=0;
		}
		if( SH_GameEndTexture)
		{
			wRelease( SH_GameEndTexture );
			SH_GameEndTexture=0;
		}
		if( SH_SwirlTexture)
		{
			wRelease( SH_SwirlTexture );
			SH_SwirlTexture=0;
		}
		//sanghoon marker
		if( ClipperObject )
		{
			if( FrontBufferSurface )
				wSetClipper( FrontBufferSurface, 0 );
			wRelease( ClipperObject );
			ClipperObject=0;
		}
		if( BackBufferSurface )
		{
			wRelease( BackBufferSurface );
			BackBufferSurface=0;
		}
		if( FrontBufferSurface )
		{
			wRelease( FrontBufferSurface );
			FrontBufferSurface=0;
		}
		GameOSFPU();
		ValidMode=SetupMode( Environment.fullScreen, 3 );
		if( !ValidMode )
		{
			STOP(( "No software rasterizer available" ));
		}
		GetModeCaps();
		gos_RecreateTextureHeaps();
	}
//
// Set flag to reinit renderstates inside the BeginScene
//
	StencilActive=0;
	NeedToInitRenderStates=1;
//
// Set the 'mode changed flag'
//
	ModeChanged=1;
//
// If no stencil buffer created, reset status
//
	if( !StencilValid )
		Environment.Stencil=0;
//
// Recreate any vertex buffers that previously existed
//
	ReCreateVertexBuffers();
//
// Record pixel format of backbuffer
//
	UpdateBackBufferFormat();
//
// Update the DC
//
	if (DesktopDC)
	{
		ReleaseDC(NULL, DesktopDC);
		DesktopDC = GetDC(NULL);
	}
//
// Setup texture to render to
//
	InitRenderToTexture();
//
// Show renderer and size for 4 seconds
//
#ifdef LAB_ONLY
	DisplayModeInfo();
#endif
//
// Debugging information
//
	SPEW(( GROUP_DIRECTDRAW, "DirectDrawCreateAllBuffers() Done 3D Setup" ));
}

