#include "pch.hpp"
//
//===========================================================================//
// File:	 VideoCard.cpp													 //
// Project:  GameOS					                                         //
// Contents: Routines to detect and work around video card differences		 //
//---------------------------------------------------------------------------//
// Date      Who    Modification                                             //
// 12/17/98  AG     Created													 //
//---------------------------------------------------------------------------//
// Copyright (C) 1999 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
//
#include "DXRasterizer.hpp"
#include "DirectX.hpp"
#include "Windows.hpp"
#include "ErrorHandler.hpp"
#include "Registry.hpp"

__int64 GetDriverFileDetails( FixedLengthString& Buffer, char* DriverName, bool SoundInfo=0 );
DWORD VideoMemorySize=0;
int VoodooCard=0;
extern DWORD gUseBlade;
void CheckDevices();

extern DWORD gNumberCompatFlags;
extern DWORD gCompatFlags;
extern DWORD gCompatFlags1;
extern int g_nTypeOfMFDs; // 0 - no MFDs, 1 - orginal(5+1=dual & single), 2 - B&W(3 + 1=1 dual), 3 - color(3 + 1=2 dual)

DWORD NumBuffered=0;

typedef struct
{
	GUID*	lpGUID;
	GUID	GUID;
	char*	lpDriverDescription;
	char*	lpDriverName;

} videoDevices;

videoDevices BufferedDevices[8];

int g_nDualHead = -1; // jcem
int g_nDualHead2 = -1; // jcem
int g_nNonDualHead = -1; // jcem
int g_nMFD1 = -1; // mode 4: left 640x480 MFD monitor
int g_nMFD2 = -1; // mode 4: right 640x480 MFD monitor
// MSL 5.03 Mechview
int g_nMechViewType; // jcem : 0 - no mechview, 1 - on radar screen, 2 - on main screen

CardInfo KnownCards[]={
//
//    Vendor DeviceID DriverHigh  DriverLow	  NTDriverH   NTDriveL    Card Name	        Generic Name			Compatibility flags
//
	{ 0x1142, 0x643d, 0x0004000a, 0x00010819, 0x00000000, 0x00000000, "3Dfx",			"Rush (Alliance)",		Disable1024x768 + NoAlphaTest + NoTripleBuffer + NoFog },
	{ 0x10d9, 0x8626, 0x0004000a, 0x00010819, 0x00000000, 0x00000000, "3Dfx",			"Rush (Macronix)",		Disable1024x768 + NoAlphaTest + NoTripleBuffer + NoFog },
	{ 0x121a, 0x0001, 0x0004000a, 0x00010010, 0x00000000, 0x00000000, "3Dfx",			"Voodoo 1",				Disable1024x768 + NoTripleBuffer + BadMouse },
	{ 0x121a, 0x0002, 0x0004000b, 0x0001015e, 0x00000000, 0x00000000, "3Dfx",			"Voodoo 2",				Disable1024x768 + AllowLowMemoryCard + NoDisablePerspective + NoParallelism + NoTripleBuffer + BadMouse },
	{ 0x121a, 0x0003, 0x0004000a, 0x0001017a, 0x00000000, 0x00000000, "3Dfx",			"Banshee",				AllowLowMemoryCard + NoParallelism + NoMipMap },
	{ 0x121a, 0x0005, 0x0004000c, 0x000104bd, 0x00050000, 0x08930011, "3Dfx",			"Voodoo 3",				NoParallelism + AllowLowMemoryCard },
	{ 0x121a, 0x0009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "3Dfx",			"Voodoo 5",				0 },

	{ 0x104a, 0x0010, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "ST",				"Kyro",					SceneRenderer },

	{ 0x1002, 0x4354, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "ATI",			"Mach 64",				0 },
	{ 0x1002, 0x4358, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "ATI",			"Mach 64",				0 },
	{ 0x1002, 0x4742, 0x0004000b, 0x000113A9, 0x00000000, 0x00000000, "ATI",			"3D Rage Pro",			BrokenAlphaTest + TextureOffset + DefaultBltNotFlip },			// John Lange
	{ 0x1002, 0x4744, 0x0004000b, 0x000113A9, 0x00000000, 0x00000000, "ATI",			"Rage Pro",				BrokenAlphaTest + TextureOffset },			// Ryan on Spike 2001
	{ 0x1002, 0x474d, 0x0004000b, 0x000113A9, 0x00000000, 0x00000000, "ATI",			"3D Rage Pro",			BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x474e, 0x0004000b, 0x000113A9, 0x00000000, 0x00000000, "ATI",			"3D Rage Pro",			BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x4750, 0x0004000b, 0x000113A9, 0x00000000, 0x00000000, "ATI",			"Rage Pro",				BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x4752, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"Rage XL",				BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x4754, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"3D Rage IIC PCI",		BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x4755, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"Rage II",				BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x4756, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"3D Rage IIC PCI",		BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x4757, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"3D Rage IIC AGP",		BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x4758, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "ATI",			"Mach 64",				0 },
	{ 0x1002, 0x475A, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"3D Rage IIC AGP",		BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x4c42, 0x0004000a, 0x00010940, 0x00000000, 0x00000000, "ATI",			"Rage LT Pro",			0 },
	{ 0x1002, 0x4c47, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"3D Rage LT",			BrokenAlphaTest },
	{ 0x1002, 0x4c49, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"3D Rage LT Pro",		BrokenAlphaTest },
	{ 0x1002, 0x4c4d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "ATI",			"Mobility-P",			BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x4c50, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"3D Rage LT Pro",		BrokenAlphaTest },
	{ 0x1002, 0x5246, 0x0004000b, 0x00010837, 0x00000000, 0x00000000, "ATI",			"Rage 128",				0 },
	{ 0x1002, 0x524c, 0x0004000b, 0x00010837, 0x00000000, 0x00000000, "ATI",			"Rage 128",				0 },
	{ 0x1002, 0x5245, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "ATI",			"Rage 128 GL",			0 },
	{ 0x1002, 0x5046, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "ATI",			"Rage Fury",			NoParallelism },
	{ 0x1002, 0x5654, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"Rage II",				BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x5655, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"Rage II",				BrokenAlphaTest + TextureOffset },
	{ 0x1002, 0x5656, 0x0004000a, 0x00010937, 0x00000000, 0x00000000, "ATI",			"264VT4",				BrokenAlphaTest + TextureOffset },
	{ 0x109e, 0x2164, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "STB",			"VideoRage",			0 },						// Gateway only card (Destination systems)
	{ 0x1002, 0x5144, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "ATI",			"Radion",				0 },
	{ 0x1002, 0x4c46, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "ATI",			"Mobility 128",			0 },

	{ 0x104c, 0x3d04, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "3DLabs",			"Permedia 2",			DisableColorControl + TextureOffset + DefaultBltNotFlip },
	{ 0x104c, 0x3d07, 0x0004000a, 0x00010839, 0x00000000, 0x00000000, "3DLabs",			"Permedia 2",			DisableColorControl + TextureOffset + DefaultBltNotFlip + NoMipMap },
	{ 0x10ba, 0x0301, 0x0004000a, 0x00010839, 0x00000000, 0x00000000, "3DLabs",			"Permedia 2",			DisableColorControl + TextureOffset },
	{ 0x3d3d, 0x0002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "3DLabs",			"GLiNT",				0 },
	{ 0x3d3d, 0x0003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "3DLabs",			"GLiNT",				0 },
	{ 0x3d3d, 0x0006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "3DLabs",			"GLiNT",				0 },
	{ 0x1048, 0x8901, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "3DLabs",			"GLiNT",				0 },
	{ 0x3d3d, 0x0009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "3DLabs",			"Permedia 2",			DisableColorControl },
	{ 0x3d3d, 0x000a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "3DLabs",			"Permedia 3",			0 },

	{ 0x1013, 0x0038, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Cirrus",			"GD7548",				0 },
	{ 0x1013, 0x00a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Cirrus",			"GD5430",				0 },
	{ 0x1013, 0x00a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Cirrus",			"GD5434",				0 },
	{ 0x1013, 0x00ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Cirrus",			"GD5436",				0 },
	{ 0x1013, 0x00b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Cirrus",			"GD5446",				0 },
	{ 0x1013, 0x00bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Cirrus",			"GD5480",				0 },
	{ 0x1013, 0x00d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Cirrus",			"GD5464",				0 },
	{ 0x1013, 0x00d6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Cirrus",			"GD5465",				0 },
	{ 0x1013, 0x0301, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Cirrus",			"GD5446",				0 },
	{ 0x1013, 0x1202, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Cirrus",			"GD7543",				0 },

	{ 0x105d, 0x2309, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "#9",				"Imagine 128",			0 },
	{ 0x105d, 0x2339, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "#9",				"Imagine 128 II",		0 },
	{ 0x105d, 0x493d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "#9",				"Revolution 3D",		0 },
	{ 0x105d, 0x5348, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "#9",				"Revolution IV",		0 },

	{ 0x102c, 0x0024, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "C&T",			"65554",				0 },
	{ 0x102c, 0x00e5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "C&T",			"65555",				0 },
	{ 0x102c, 0x00f4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "C&T",			"65554",				0 },
	{ 0x102c, 0x00c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "C&T",			"69000",				0 },
	{ 0x102c, 0x00e0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "C&T",			"65550",				0 },
	{ 0x102c, 0x00e4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "C&T",			"65554",				0 },
	{ 0x102c, 0x00e5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "C&T",			"65555",				0 },

	{ 0x1163, 0x0001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Rendition",		"Verite 1000",			0 },
	{ 0x1163, 0x2000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Rendition",		"Verite 2100",			0 },

	{ 0x110b, 0x0004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Chromatic",		"MPact",				Bad4444 + BadAGP },

	{ 0x100e, 0x9001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Weitek",			"P9000",				0 },
	{ 0x100e, 0x9100, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Weitek",			"P9100",				0 },

	{ 0x0e11, 0x3032, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Compaq",			"QVision",				0 },

	{ 0x1039, 0x0204, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "SIS",			"6215",					0 },
	{ 0x1039, 0x0205, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "SIS",			"6205",					0 },
	{ 0x1039, 0x6326, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "SIS",			"6326",					0 },
	{ 0x1039, 0x6306, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "SIS",			"6306",					TextureOffset },

	{ 0x1011, 0x0004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Digital",		"TGA",					0 },
	{ 0x1011, 0x000d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Digital",		"TGA2",					0 },

	{ 0x10c8, 0x0001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "NeoMagic",		"128",					0 },
	{ 0x10c8, 0x0002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "NeoMagic",		"128",					0 },
	{ 0x10c8, 0x0003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "NeoMagic",		"128ZV",				0 },
	{ 0x10c8, 0x0004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "NeoMagic",		"128XD",				0 },
	{ 0x10c8, 0x0005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "NeoMagic",		"256AV",				0 },
	{ 0x10c8, 0x0016, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "NeoMagic",		"256XL+",				NoMipMap + DisableTextureDeletes + ForceSquareTextures + LimitTextureSize },
	{ 0x10c8, 0x0083, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "NeoMagic",		"128ZV+",				0 },

	{ 0x100c, 0x3202, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Tseng Labs",		"ET4000",				0 },
	{ 0x100c, 0x3208, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Tseng Labs",		"ET6000",				0 },

	{ 0x5333, 0x5631, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Virge",				0 },
	{ 0x5333, 0x8811, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Trio64VX",				0 },
	{ 0x5333, 0x8812, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Trio64VX",				0 },
	{ 0x5333, 0x883d, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Virge VX",				0 },
	{ 0x5333, 0x8880, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Virge",				0 },
	{ 0x5333, 0x88c0, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Virge",				0 },
	{ 0x5333, 0x88c1, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Virge",				0 },
	{ 0x5333, 0x88d0, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Virge",				0 },
	{ 0x5333, 0x88d1, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Virge",				0 },
	{ 0x5333, 0x88f0, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Virge",				0 },
	{ 0x5333, 0x8901, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Trio64DX",				0 },
	{ 0x5333, 0x8904, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Trio 3D",				0 },
	{ 0x5333, 0x8a01, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Virge DX/GX",			0 },
	{ 0x5333, 0x8a10, 0x0004000a, 0x0000083f, 0x00000000, 0x00000000, "S3",				"Virge GX2",			0 },
	{ 0x5333, 0x8a13, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "S3",				"Trio3D",				0 },
	{ 0x5333, 0x8a20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "S3",				"Savage 3D",			0 },
	{ 0x5333, 0x8a21, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "S3",				"Savage 3D S3",			0 },
	{ 0x5333, 0x8a22, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "S3",				"Savage 3D S4",			NoParallelism | NoTriLinear | NoMultitexture },
	{ 0x5333, 0x8c01, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "S3",				"Virge MX",				0 },
	{ 0x5333, 0x8c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "S3",				"Savage MX",			0 },
	{ 0x5333, 0x9102, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "S3",				"Savage 2000",			DefaultBltNotFlip | TextureOffset | BadAGP | NoParallelism | SlowDisplayModeChange},

	{ 0x102b, 0x1000, 0x0004000a, 0x0001100e, 0x00000000, 0x00000000, "Matrox",			"G100 PCI",				0 },
	{ 0x102b, 0x1001, 0x0004000a, 0x0001100e, 0x00000000, 0x00000000, "Matrox",			"G100 AGP",				0 },
	{ 0x102b, 0x0518, 0x0004000a, 0x0001100e, 0x00000000, 0x00000000, "Matrox",			"Millennium",			0 },
	{ 0x102b, 0x0519, 0x0004000a, 0x0001100e, 0x00000000, 0x00000000, "Matrox",			"Millennium",			0 },
	{ 0x102b, 0x051a, 0x0004000a, 0x0001100e, 0x00000000, 0x00000000, "Matrox",			"Mystique",				0 },
	{ 0x102b, 0x051b, 0x0004000a, 0x0001100e, 0x00000000, 0x00000000, "Matrox",			"Millennium II PCI",	0 },
	{ 0x102b, 0x051f, 0x0004000a, 0x0001100e, 0x00000000, 0x00000000, "Matrox",			"Millennium II AGP",	0 },
	{ 0x102b, 0x0520, 0x0004000b, 0x00010514, 0x00000000, 0x00000000, "Matrox",			"G200 PCI",				0 },
	{ 0x102b, 0x0521, 0x0004000b, 0x00010514, 0x00000000, 0x00000000, "Matrox",			"G200 AGP",				0 },
	{ 0x102b, 0x0525, 0x0004000b, 0x00010514, 0x00000000, 0x00000000, "Matrox",			"G400",					0 },
	{ 0x102b, 0x0d10, 0x0004000a, 0x0001100e, 0x00000000, 0x00000000, "Matrox",			"Mystique",				0 },

	{ 0x10de, 0x0020, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva TNT",				RenderEqualZ },
	{ 0x10de, 0x0028, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva TNT2",			RenderEqualZ },
	{ 0x10de, 0x0029, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva ULTRA",			RenderEqualZ },
	{ 0x10de, 0x002c, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva TNT Vanta",		RenderEqualZ },		// Kona (szobell)
	{ 0x10de, 0x002d, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva TNT",				RenderEqualZ },		// Kona (szobell)
	{ 0x12D2, 0x0018, 0x0004000b, 0x00010155, 0x00000000, 0x00000000, "nVidia",			"Riva 128",				NoStretchTexture+LimitTextureSize+TextureOffset+NoTriLinear+RenderEqualZ+Limit500VidTextures },
	{ 0x10de, 0x0100, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva GeForce",			RenderEqualZ },
	{ 0x10de, 0x0101, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva GeForce DDR",		RenderEqualZ },
	{ 0x10de, 0x0103, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva GeForce Quadro",	RenderEqualZ },
	{ 0x10de, 0x0150, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva GeForce 2",		RenderEqualZ },
	{ 0x10de, 0x0152, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva GeForce 2 Ultra",	RenderEqualZ },
 	{ 0x10de, 0x0185, 0x0004000c, 0x0001026a, 0x0005000c, 0x0001026a, "nVidia",			"Riva GeForce4 MX 4000",		RenderEqualZ },
  
	{ 0x8086, 0x7800, 0x0004000a, 0x000108b4, 0x00000000, 0x00000000, "Intel",			"740",					Bad8888 + NoMipMap + DisableTextureDeletes + ForceSquareTextures + LimitTextureSize },
	{ 0x8086, 0x1240, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Intel",			"752",					Bad8888 + NoMipMap + DisableTextureDeletes + ForceSquareTextures + LimitTextureSize },
	{ 0x8086, 0x7121, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Intel",			"810",					Bad8888 + NoMipMap + DisableTextureDeletes + ForceSquareTextures + LimitTextureSize },
	{ 0x8086, 0x7123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Intel",			"810",					Bad8888 + NoMipMap + DisableTextureDeletes + ForceSquareTextures + LimitTextureSize },
	{ 0x8086, 0x7125, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Intel",			"810e",					Bad8888 + NoMipMap + DisableTextureDeletes + ForceSquareTextures + LimitTextureSize },

	{ 0x1033, 0x0067, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "VideoLogic",		"PowerVR2",				SceneRenderer },
	{ 0x1033, 0x0046, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "VideoLogic",		"PowerVR",				SceneRenderer },

	{ 0x1023, 0x8420, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"CyberBlade i7",		0 },
	{ 0x1023, 0x9320, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"Cyber9320",			0 },
	{ 0x1023, 0x9388, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"Cyber9388",			0 },
	{ 0x1023, 0x9397, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"Cyber9397",			0 },
	{ 0x1023, 0x939A, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"Cyber9397 DVD",		0 },
	{ 0x1023, 0x9440, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"Cyber",				0 },
	{ 0x1023, 0x9520, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"Cyber9520",			0 },
	{ 0x1023, 0x9525, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"Cyber9520 DVD",		0 },
	{ 0x1023, 0x9540, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"CyberBlade E4",		0 },
	{ 0x1023, 0x9660, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"Cyber9385",			0 },
	{ 0x1023, 0x9750, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"975",					0 },
	{ 0x1023, 0x9754, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"9753",					0 },
	{ 0x1023, 0x9850, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"3DImage",				0 },
	{ 0x1023, 0x9880, 0x00000000, 0x00000000, 0x00000000, 0x00000000, "Trident",		"Blade 3D",				0 },
};













//
// This is the current cards compatiblity flags
//
DWORD Compatibility3D;





//
// Maximum of 8 3D devices allowed in system
//
DeviceInfo	DeviceArray[8];
DeviceInfo*	pDeviceArray;
DWORD		NumDevices;
DWORD		NumHWDevices;
DWORD		NumMonitors;

//
// Prototypes
//
BOOL CALLBACK DirectDrawEnumerateExCallback( GUID* lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID, HMONITOR hm );
BOOL CALLBACK DirectDrawEnumerateCallback( GUID* lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID );
HRESULT CALLBACK EnumModesCallback2( LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext );






	

//
//
// Called once at startup, enumerate and get caps of all 3D video cards
//
//
void FindVideoCards()
{
	SPEW(( GROUP_GAMEOS, "FindVideoCards()" ));
//
// Build a list of all valid devices in the system
//
	NumMonitors=0;					// 0=Only primary, 2=two monitors
	NumDevices=0;
	NumHWDevices=0;
	NumBuffered=0;
	pDeviceArray=DeviceArray;
//
// Disable all hardware devices?
//
	if( gUseBlade )
		return;
//
// Enumerate all D3D cards
//
	gos_MathExceptions( 0,0 );
	wDirectDrawEnumerate(DirectDrawEnumerateCallback,DirectDrawEnumerateExCallback,0);
	gos_MathExceptions(1,0);
//
// Now test them all
//
	CheckDevices();
//
// On a multimonitor system remove the NULL device
//
	if( NumMonitors>=2 && NumDevices )
	{
//
// Find the real device GUID that matches the primary
//
		for( int t0=1; t0<NumDevices; t0++ )
		{
			if( DeviceArray[t0].DDid.guidDeviceIdentifier==DeviceArray[0].DDid.guidDeviceIdentifier )
			{
				DeviceArray[0]=DeviceArray[t0];
				while( t0+1<NumDevices )
				{
					DeviceArray[t0]=DeviceArray[t0+1];
					t0++;
				}
				NumDevices-=1;
			}
		}
	}
//
// Make sure initial full screen device is valid. -1 means select 1st
//

    // jcem - dual heads...
    {
		for(int t0 = 0; t0 < NumDevices; t0++)
		{
			for( int t1=0; t1<sizeof(DeviceArray[0].Modes16) / sizeof(WORD); t1+=2 )
			{
				if ((DeviceArray[t0].Modes16[t1+0]==1280) && (DeviceArray[t0].Modes16[t1+1]==480))
				{
					if (g_nDualHead == -1)
					{
						g_nDualHead = t0;
					}
					else if (g_nDualHead2 == -1)
					{
						g_nDualHead2 = t0;
					}
					break;
				}
			}
		}
	}
    // jcem
	//if( Environment.FullScreenDevice==-1 )
	{
		for( int t0=0; t0<NumDevices; t0++ )
		{
			if( DeviceArray[t0].D3DCaps.dwDevCaps&D3DDEVCAPS_HWRASTERIZATION  && (t0 != g_nDualHead) && (t0 != g_nDualHead2))
			{
				Environment.FullScreenDevice=t0;
				break;
			}
		}
	}
	if( Environment.FullScreenDevice>=NumDevices || Environment.FullScreenDevice<0 )
		Environment.FullScreenDevice=0;
    // jcem
    if (g_nDualHead != -1) {
		if (g_nDualHead2 != -1) {
			g_nNonDualHead = g_nDualHead2;
		}
    }
    if (g_nNonDualHead == -1) {
			for( int t0=0; t0<NumDevices; t0++ )
			{ 
				if( (t0 != Environment.FullScreenDevice) && (t0 != g_nDualHead) && DeviceArray[t0].D3DCaps.dwDevCaps&D3DDEVCAPS_HWRASTERIZATION )
				{
					g_nNonDualHead = t0;
				break;
			}
		}
	}
    // Mode 4 (split dual 640x480): find two extra D3D devices beyond
    // FullScreenDevice and g_nNonDualHead.  These need no special resolution.
    {
        int found = 0;
        for (int t0 = 0; t0 < NumDevices && found < 2; t0++) {
            if (t0 == Environment.FullScreenDevice) continue;
            if (t0 == g_nNonDualHead)               continue;
            if (DeviceArray[t0].D3DCaps.dwDevCaps & D3DDEVCAPS_HWRASTERIZATION) {
                if (found == 0) g_nMFD1 = t0;
                else            g_nMFD2 = t0;
                found++;
            }
        }
    }
    // jcem
//
// Check any known video cards have up to date drivers (Only on Windows9x)
//
	#ifdef LAB_ONLY
	DWORD LastBadCard=-1;
	DWORD BadVendor=-1;
	DWORD BadDevice=-1;
	#endif
	for( int device=0; device<NumDevices; device++ )
	{
		DeviceArray[device].CurrentCard=-1;
		DeviceArray[device].CurrentVendor=0;

		if( DeviceArray[device].DDid.dwVendorId )				// When vendor is 0, don't check device or driver
		{
			for( int card=0; card<(sizeof(KnownCards)/sizeof(CardInfo)); card++ )
			{
				if( KnownCards[card].VendorID		== DeviceArray[device].DDid.dwVendorId )
					DeviceArray[device].CurrentVendor=KnownCards[card].VendorName;					// Found the correct Vendor?

				if( KnownCards[card].VendorID		== DeviceArray[device].DDid.dwVendorId &&
					KnownCards[card].DeviceID		== DeviceArray[device].DDid.dwDeviceId )		// Found Vendor and Device?
				{
					DeviceArray[device].CurrentCard=card;

					#ifdef LAB_ONLY
					if( card!=LastBadCard )
					{
						char* OSVersion="";
						DWORD DrvH=KnownCards[card].DriverH;			// Win9x drivers
						DWORD DrvL=KnownCards[card].DriverL;
						if( WindowsNT )
						{
							OSVersion="Win2k\\";						// Win2K drivers
							DrvH=KnownCards[card].NTDriverH;
							DrvL=KnownCards[card].NTDriverL;
						}

						if((DrvH || DrvL) &&
						   (DrvH != DeviceArray[device].DDid.liDriverVersion.HighPart ||
							DrvL != DeviceArray[device].DDid.liDriverVersion.LowPart ))				// In LAB_ONLY check driver
						{
//							char Buffer1[32];
//							char Buffer2[32];
							if( DeviceArray[device].DDid.liDriverVersion.HighPart || DeviceArray[device].DDid.liDriverVersion.LowPart )		// If driver number is 0, don't prompt for upgrade
							{
								LastBadCard=card;
//								PAUSE(( "Update your %s %s driver (%s) with the driver in \\\\AAS1\\Coretech\\Drivers\\%s%s (%s)         ",
//										KnownCards[card].VendorName, KnownCards[card].CardName,
//										VersionNumber( Buffer1, DeviceArray[device].DDid.liDriverVersion.HighPart, DeviceArray[device].DDid.liDriverVersion.LowPart ),
//										OSVersion,
//										KnownCards[card].VendorName,
//										VersionNumber( Buffer2, DrvH, DrvL ) ));
							}
						}
					}
					#endif
				}
			}

			if( -1==DeviceArray[device].CurrentCard )												// Unknown card?
			{
				#ifdef LAB_ONLY
				char Buffer[128];
				char Buffer1[32];
				if( BadVendor!=DeviceArray[device].DDid.dwVendorId &&
					BadDevice!=DeviceArray[device].DDid.dwDeviceId )
				{
#if 0 // jcem
					if( DeviceArray[device].CurrentVendor )
					{
						sprintf( Buffer, "WARNING: Untested chip from %s, Device=0x%x, Driver version %s", DeviceArray[device].CurrentVendor, DeviceArray[device].DDid.dwDeviceId, VersionNumber( Buffer1, DeviceArray[device].DDid.liDriverVersion.HighPart ,DeviceArray[device].DDid.liDriverVersion.LowPart) );
					}
					else
					{
						sprintf( Buffer, "WARNING: Untested video card - Vendor=0x%x, Device=0x%x, Driver version %s", DeviceArray[device].DDid.dwVendorId, DeviceArray[device].DDid.dwDeviceId,  VersionNumber(Buffer1, DeviceArray[device].DDid.liDriverVersion.HighPart ,DeviceArray[device].DDid.liDriverVersion.LowPart) );
					}
					PAUSE(( Buffer ));
#endif
					BadVendor=DeviceArray[device].DDid.dwVendorId;
					BadDevice=DeviceArray[device].DDid.dwDeviceId;
				}
				#endif
			}
		}
	}
//
// Now check for bad registry entries for known cards
//
	#ifdef LAB_ONLY
	for( device=0; device<NumDevices; device++ )
	{
		if( DeviceArray[device].DDid.dwVendorId==0x121a && DeviceArray[device].DDid.dwDeviceId==0x0002 )
		{
			char* Temp=ReadRegistry( "Software\\3dfx Interactive\\Voodoo2\\D3D", "SSTV2_AUTOMIPMAP", 1 );
			if( Temp && *Temp && *Temp=='1' )
				PAUSE(( "Please disable Voodoo2 automatic mipmapping in the 3Dfx advanced control panel" ));
		}
	}
	#endif
//
//
//
	SPEW(( GROUP_GAMEOS, "FindVideoCards() - Finished" ));
}



























DWORD Modes16=0;
DWORD Modes32=0;
DWORD ModesZ=0;
//
// Screen modes enum callback
//
// Throw out modes that cannot fit front, back and Z buffer in video memory
//
HRESULT CALLBACK EnumModesCallback2( LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext )
{
	if( lpDDSurfaceDesc->dwWidth >= 512 && lpDDSurfaceDesc->dwHeight >= 384 )
	{
		if( !((Compatibility3D&Disable1024x768) && lpDDSurfaceDesc->dwWidth>=1024 && lpDDSurfaceDesc->dwHeight>=768) )
		{
			if( lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==16 && Modes16<16*2 )
			{
				bool unique=1;
				for( int t0=0; t0<Modes16; t0+=2 )
				{
					if((pDeviceArray->Modes16[t0+0]==(WORD)lpDDSurfaceDesc->dwWidth &&
						pDeviceArray->Modes16[t0+1]==(WORD)lpDDSurfaceDesc->dwHeight) )
					{
						if( pDeviceArray->Refresh16[t0/2]<(WORD)lpDDSurfaceDesc->dwRefreshRate )
							pDeviceArray->Refresh16[t0/2]=(WORD)lpDDSurfaceDesc->dwRefreshRate;
						unique=0;
						break;
					}
				}
				if( unique && (VoodooCard || VideoMemorySize>(lpDDSurfaceDesc->dwWidth*lpDDSurfaceDesc->dwHeight*2*3) ))
				{
					pDeviceArray->Modes16[Modes16+0]=(WORD)lpDDSurfaceDesc->dwWidth;
					pDeviceArray->Modes16[Modes16+1]=(WORD)lpDDSurfaceDesc->dwHeight;
					pDeviceArray->Refresh16[Modes16/2]=(WORD)lpDDSurfaceDesc->dwRefreshRate;
					Modes16+=2;
				}
			}
			if( lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==32 && Modes32<16*2 )
			{
				bool unique=1;
				for( int t0=0; t0<Modes32; t0+=2 )
				{
					if((pDeviceArray->Modes32[t0+0]==(WORD)lpDDSurfaceDesc->dwWidth &&
						pDeviceArray->Modes32[t0+1]==(WORD)lpDDSurfaceDesc->dwHeight) )
					{
						if( pDeviceArray->Refresh32[t0/2]<(WORD)lpDDSurfaceDesc->dwRefreshRate )
							pDeviceArray->Refresh32[t0/2]=(WORD)lpDDSurfaceDesc->dwRefreshRate;
						unique=0;
						break;
					}
				}
				if( unique && (VoodooCard || VideoMemorySize>(lpDDSurfaceDesc->dwWidth*lpDDSurfaceDesc->dwHeight*4*3) ))
				{
					pDeviceArray->Modes32[Modes32+0]=(WORD)lpDDSurfaceDesc->dwWidth;
					pDeviceArray->Modes32[Modes32+1]=(WORD)lpDDSurfaceDesc->dwHeight;
					pDeviceArray->Refresh32[Modes32/2]=(WORD)lpDDSurfaceDesc->dwRefreshRate;
					Modes32+=2;
				}
			}
		}
	}
	return D3DENUMRET_OK;
}

//
//
//
HRESULT CALLBACK EnumZCallback( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext )
{
	memcpy( &pDeviceArray->ZFormats[ModesZ], lpDDPixFmt, sizeof(DDPIXELFORMAT) );
	ModesZ++;
	if( ModesZ>=16 )
		return D3DENUMRET_CANCEL;
	else
		return D3DENUMRET_OK;
}




DWORD TextureNum=0;
//
// Texture enum callback
//
HRESULT CALLBACK D3DEnumPixelFormatsCallback( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext )
{
	memcpy( &pDeviceArray->TextureFormats[TextureNum], lpDDPixFmt, sizeof(DDPIXELFORMAT) );
	TextureNum++;
	if( TextureNum>=16 )
		return D3DENUMRET_CANCEL;
	else
		return D3DENUMRET_OK;
}

D3DDEVICEDESC7 HalDesc;
bool FoundHal;
//
// Device enum callback - Save HAL device details
//
HRESULT CALLBACK D3DEnumDevicesCallback( LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC7 lpD3DHWDeviceDesc, LPVOID lpContext )
{
	if( lpD3DHWDeviceDesc->dwDevCaps&D3DDEVCAPS_HWRASTERIZATION )
	{
		memcpy( &HalDesc, lpD3DHWDeviceDesc, sizeof(HalDesc) );
		FoundHal=1;
	}
	return D3DENUMRET_OK;
}







//
// Deal with both types of DDRAW enumeration
//
BOOL DoEnum( GUID* lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName )
{
	DWORD Failed=0;
	bool EntereredFullScreen=0;
//
// Create a DirectDraw object - may fail on cards with NO hardware, like Oxygen 202 cards.
//
	AllowFail=1;
	HRESULT result=wDirectDrawCreateEx( lpGUID, (void**)&DDobject, IID_IDirectDraw7, NULL );
	AllowFail=0;
	if( FAILED(result) )
	{
		DDobject=0;
	    return DDENUMRET_OK;
	}

	wSetCooperativeLevel( DDobject, hWindow,DDSCL_NORMAL);
//
// Create a dummy primary (Unused, but TNT2's required before ValidateDevice worked properly)
//
	DDSURFACEDESC2 ddsd;
	memset(&ddsd,0,sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags        = DDSD_CAPS;
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
	AllowFail=TRUE;
	result=wCreateSurface( DDobject, &ddsd, &FrontBufferSurface, NULL);
	AllowFail=FALSE;
	if( FAILED(result) )
	{
		wRelease( DDobject );
		DDobject=0;
	    return DDENUMRET_OK;
	}
//
// See how much memory is on the card - if less than 8Meg goto full screen mode during testing (make sure low end cards are as accruate as possible)
//
	DDSCAPS2 ddscaps2;
	memset( &ddscaps2, 0, sizeof(ddscaps2) );
	ddscaps2.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
	DWORD Junk;
	DWORD Mem=0;
	AllowFail=1;
	result=wGetAvailableVidMem( DDobject, &ddscaps2, &Mem, &Junk );
	AllowFail=0;
//
// If in 256 color mode, change to 800*600*16
//
	DDPIXELFORMAT ddfm;
	memset( &ddfm, 0, sizeof(ddfm) );
	ddfm.dwSize=sizeof(ddfm);

	AllowFail=1;
	wGetPixelFormat( FrontBufferSurface, &ddfm );
	AllowFail=0;
	if( (ddfm.dwFlags & DDPF_PALETTEINDEXED8) || (Mem<8*1024*1024) )
	{
		EntereredFullScreen=1;
		AllowFail=1;
		wRelease( FrontBufferSurface );
		wSetCooperativeLevel(DDobject, hWindow, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
		wSetDisplayMode( DDobject, 800, 600, 16, 0, 0 );

		result=wCreateSurface( DDobject, &ddsd, &FrontBufferSurface, NULL);
		AllowFail=FALSE;
		if( FAILED(result) )
		{
			wRestoreDisplayMode( DDobject );
			wSetCooperativeLevel( DDobject, hWindow, DDSCL_NORMAL );
			wRelease( DDobject );
			DDobject=0;
			return DDENUMRET_OK;
		}
	}
//
// Get hardware caps
//
	pDeviceArray->DDCaps.dwSize = sizeof(pDeviceArray->DDCaps);
	wGetCaps( DDobject, &pDeviceArray->DDCaps, 0 );
//
// Get the font buffer surface description
//
	DDSURFACEDESC2 FBddsd;
	FBddsd.dwSize=sizeof(FBddsd);
	wGetSurfaceDesc( FrontBufferSurface, &FBddsd );
//
// Set disabled for multitexture by default
//
	pDeviceArray->MultitextureLightMap=1;
	pDeviceArray->MultitextureSpecularMap=1;
	pDeviceArray->MultitextureDetail=1;
	pDeviceArray->MultitextureLightMapFilter=0;
	pDeviceArray->MultitextureSpecularMapFilter=0;
	pDeviceArray->MultitextureDetailFilter=0;
//
// Get DirectDraw device information
//
	AllowFail=1;
	result=wGetDeviceIdentifier( DDobject, &pDeviceArray->DDid, 0 );
	AllowFail=0;
	if( FAILED(result) )
	{
		memset( &pDeviceArray->DDid, 0, sizeof(pDeviceArray->DDid) );
		strcpy( pDeviceArray->DDid.szDriver, "Default" );
		strcpy( pDeviceArray->DDid.szDescription, "Default" );
	}
//
// Setup Compatibility3D flags for this card used during Enum display modes)
//
	Compatibility3D=0;
	
	if( pDeviceArray->DDid.dwVendorId )
	{
		for( int card=0; card<(sizeof(KnownCards)/sizeof(CardInfo)); card++ )
		{
			if( KnownCards[card].VendorID		== pDeviceArray->DDid.dwVendorId &&
				KnownCards[card].DeviceID		== pDeviceArray->DDid.dwDeviceId )		// Found Vendor and Device?
			{
				if( gNumberCompatFlags==2 )
				{
					Compatibility3D =(KnownCards[ card ].CompatibilityFlags & ~gCompatFlags) | gCompatFlags1;
				}
				else
				{
					if( gCompatFlags )
						Compatibility3D = gCompatFlags;
					else
						Compatibility3D = KnownCards[ card ].CompatibilityFlags;
				}
				break;
			}
		}
	}
//
// On Windows 2000, check driver versions using driver file information
//
	if( WindowsNT )
	{
		FixedLengthString Buffer(1024);
		__int64 Version=GetDriverFileDetails( Buffer, pDeviceArray->DDid.szDriver );
		pDeviceArray->DDid.liDriverVersion.HighPart=(DWORD)(Version>>32);
		pDeviceArray->DDid.liDriverVersion.LowPart=(DWORD)(Version&0xffffffff);
	}
//
// Get any FourCC codes supported
//
	DWORD Number4CC=16;
	memset( &pDeviceArray->FourCC[0], ' ', 4*16 );
	wGetFourCCCodes( DDobject, &Number4CC, (unsigned long*)&pDeviceArray->FourCC[0] );
//
// Check if Voodoo1 or Voodoo2 (incorrect video memory sizes)
//
	VoodooCard=0;
	if( pDeviceArray->DDid.dwVendorId==0x121a && (pDeviceArray->DDid.dwDeviceId==1 || pDeviceArray->DDid.dwDeviceId==2) )
		VoodooCard=1;
//
// Get main and texture memory
//
	memset( &ddscaps2, 0, sizeof(ddscaps2) );
	ddscaps2.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
	AllowFail=TRUE;
	result=wGetAvailableVidMem( DDobject, &ddscaps2, &pDeviceArray->TotalVid, &Junk );
	ddscaps2.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_TEXTURE;
	wGetAvailableVidMem( DDobject, &ddscaps2, &pDeviceArray->TotalLocalTex, &Junk );
	ddscaps2.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_TEXTURE;
	wGetAvailableVidMem( DDobject, &ddscaps2, &pDeviceArray->TotalTex, &Junk );
	AllowFail=FALSE;
//
// If AGP memory is disabled on this card, return 0 for available AGP memory
//
	if( Compatibility3D&BadAGP )
	{
		pDeviceArray->TotalTex=0;
	}
//
// Enum display modes
//
	VideoMemorySize=pDeviceArray->TotalVid;
	memset( &pDeviceArray->Modes16[0], 0 ,sizeof(pDeviceArray->Modes16) );
	memset( &pDeviceArray->Modes32[0], 0 ,sizeof(pDeviceArray->Modes32) );
	memset( &pDeviceArray->ZFormats[0], 0 ,sizeof(pDeviceArray->ZFormats) );
	memset( &pDeviceArray->D3DCaps, 0, sizeof(pDeviceArray->D3DCaps) );
	memset( &pDeviceArray->TextureFormats[0], 0, sizeof(pDeviceArray->TextureFormats) );
	FoundHal=0;
	Modes16=0;
	Modes32=0;
	ModesZ=0;
	wEnumDisplayModes( DDobject, DDEDM_REFRESHRATES, NULL, 0, EnumModesCallback2 );
//
// Create a temp IDirect3D3 device
//
	memset( &pDeviceArray->D3DCaps, 0, sizeof(pDeviceArray->D3DCaps) );
	wQueryInterface( DDobject, IID_IDirect3D7, (void**)&d3d7 );
//
// Enum Z buffer formats
//
	AllowFail=TRUE;
	wEnumZBufferFormats( d3d7, IID_IDirect3DHALDevice, EnumZCallback, 0 );
	AllowFail=FALSE;
//
// Create a test 16 bit texture surface (try 565 then 555)
//
	BackBufferSurface=0;
	ddsd.dwFlags						= DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
	ddsd.ddsCaps.dwCaps					= DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_3DDEVICE;
	ddsd.dwWidth						= 128;
	ddsd.dwHeight						= 128;
	ddsd.ddpfPixelFormat.dwSize			= sizeof(DDPIXELFORMAT);
	ddsd.ddpfPixelFormat.dwFlags		= DDPF_RGB;					// BUGBUG - cannot create this when in 32 bit desktop mode!
	ddsd.ddpfPixelFormat.dwRGBBitCount	= 16;
	ddsd.ddpfPixelFormat.dwRBitMask		= 0x0000F800;
	ddsd.ddpfPixelFormat.dwGBitMask		= 0x000007E0;				// Try 565 surface
	ddsd.ddpfPixelFormat.dwBBitMask		= 0x0000001F;
	AllowFail=TRUE;
	result=wCreateSurface( DDobject, &ddsd, &BackBufferSurface, NULL);
	AllowFail=FALSE;

	if( FAILED(result) )
	{
		ddsd.ddpfPixelFormat.dwRBitMask		= 0x00007C00;
		ddsd.ddpfPixelFormat.dwGBitMask		= 0x000003E0;			// Try 555 surface
		ddsd.ddpfPixelFormat.dwBBitMask		= 0x0000001F;
		AllowFail=TRUE;
		result=wCreateSurface( DDobject, &ddsd, &BackBufferSurface, NULL);
		AllowFail=FALSE;
	}

	if( FBddsd.ddpfPixelFormat.dwRGBBitCount==32 && FAILED(result) )
	{
		ddsd.ddpfPixelFormat.dwRGBBitCount	= 32;
		ddsd.ddpfPixelFormat.dwRBitMask		= 0x00FF0000;
		ddsd.ddpfPixelFormat.dwGBitMask		= 0x0000FF00;			// Try 0888 surface
		ddsd.ddpfPixelFormat.dwBBitMask		= 0x000000FF;
		AllowFail=TRUE;
		result=wCreateSurface( DDobject, &ddsd, &BackBufferSurface, NULL);
		AllowFail=FALSE;
	}

	if( FAILED(result) )
	{
		ddsd.ddpfPixelFormat.dwRGBBitCount	= 16;
		ddsd.ddsCaps.dwCaps					= DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE;
		ddsd.ddpfPixelFormat.dwRBitMask		= 0x00007C00;
		ddsd.ddpfPixelFormat.dwGBitMask		= 0x000003E0;			// Try TEXTURE 555 surface
		ddsd.ddpfPixelFormat.dwBBitMask		= 0x0000001F;
		AllowFail=TRUE;
		result=wCreateSurface( DDobject, &ddsd, &BackBufferSurface, NULL);
		AllowFail=FALSE;
	}

	if( FAILED(result) )
	{
		ddsd.ddpfPixelFormat.dwRBitMask		= 0x0000F800;
		ddsd.ddpfPixelFormat.dwGBitMask		= 0x000007E0;			// Try TEXTURE 565 surface
		ddsd.ddpfPixelFormat.dwBBitMask		= 0x0000001F;
		AllowFail=TRUE;
		result=wCreateSurface( DDobject, &ddsd, &BackBufferSurface, NULL);
		AllowFail=FALSE;
	}

	if( FAILED(result) )
	{
		ddsd.ddpfPixelFormat.dwRGBBitCount	= 32;
		ddsd.ddpfPixelFormat.dwRBitMask		= 0x00FF0000;
		ddsd.ddpfPixelFormat.dwGBitMask		= 0x0000FF00;			// Try 0888 surface
		ddsd.ddpfPixelFormat.dwBBitMask		= 0x000000FF;
		AllowFail=TRUE;
		result=wCreateSurface( DDobject, &ddsd, &BackBufferSurface, NULL);
		AllowFail=FALSE;
	}

	if( FAILED(result) )
	{
		ddsd.ddpfPixelFormat.dwRGBBitCount	= 32;
		ddsd.ddpfPixelFormat.dwRBitMask		= 0x00FF0000;
		ddsd.ddpfPixelFormat.dwGBitMask		= 0x0000FF00;			// Try TEXTURE 0888 surface
		ddsd.ddpfPixelFormat.dwBBitMask		= 0x000000FF;
		AllowFail=TRUE;
		result=wCreateSurface( DDobject, &ddsd, &BackBufferSurface, NULL);
		AllowFail=FALSE;
	}

	if( SUCCEEDED(result) )
	{
//
// Rectangular or linear video memory
//
		wGetSurfaceDesc( BackBufferSurface, &ddsd );
		pDeviceArray->LinearMemory=ddsd.lPitch==((ddsd.ddpfPixelFormat.dwRGBBitCount>>3)*ddsd.dwWidth);
//
// Enumerate for the HAL device, if not disabled
//
		wEnumDevices( d3d7, D3DEnumDevicesCallback, 0 );
		if( FoundHal )
		{
//
// Store CAPS returned about HAL
//
			memcpy( &pDeviceArray->D3DCaps, &HalDesc, sizeof(HalDesc) );
//
// If 32 bit rendering is not suppored do not enumerate 32 bit video modes.
//
			if( 0==(HalDesc.dwDeviceRenderBitDepth&DDBD_32) )
				memset( &pDeviceArray->Modes32[0], 0 ,sizeof(pDeviceArray->Modes32) );
//
// If the card can texture, store texture formats available
//
			TextureNum=0;
			if( pDeviceArray->D3DCaps.dpcTriCaps.dwTextureCaps&D3DPTEXTURECAPS_PERSPECTIVE )
			{
				AllowFail=TRUE;
				result=wCreateDevice( d3d7, IID_IDirect3DHALDevice, BackBufferSurface, &d3dDevice7 );
				AllowFail=FALSE;
				if( SUCCEEDED(result) )
				{
//
// Get 1st 16 texture modes supported
//
					wEnumTextureFormats( d3dDevice7, D3DEnumPixelFormatsCallback, 0 );
//
// Now check for multitexture support
//
					if( 0==(pDeviceArray->D3DCaps.dwDevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) &&		// Disallow Voodoo2 (separate TMU's)
						0!=(pDeviceArray->D3DCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2)  &&				// And ignore non-DX6 drivers
						pDeviceArray->D3DCaps.wMaxTextureBlendStages>=2 &&									// Must be at least 2 stages supported
						pDeviceArray->D3DCaps.wMaxSimultaneousTextures>=2 )									// Must have at least 2 textures supported
					{
//
// Try light map
//
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_MINFILTER, D3DTFN_LINEAR );
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR );			// Trilinear base texture
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_MIPFILTER, D3DTFP_LINEAR );
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_MINFILTER, D3DTFN_LINEAR );
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_MAGFILTER, D3DTFG_LINEAR );			// Bilinear lightmap texture
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_MIPFILTER, D3DTFP_NONE );

						wSetTextureStageState( d3dDevice7, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_COLOROP, D3DTOP_MODULATE );

						wSetTextureStageState( d3dDevice7, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );

						wSetTextureStageState( d3dDevice7, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_COLOROP, D3DTOP_MODULATE2X );

						wSetTextureStageState( d3dDevice7, 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );

						wSetTextureStageState( d3dDevice7, 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
						wSetTextureStageState( d3dDevice7, 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
//
// See if mode is possible
//
						pDeviceArray->MultitextureLightMapFilter=0;
						DWORD Passes=0;
						AllowFail=1;
						pDeviceArray->MultitextureLightMap=wValidateDevice( d3dDevice7, &Passes );
						AllowFail=0;
						if( Passes!=1 && D3D_OK==pDeviceArray->MultitextureLightMap )					// Disable if more than one pass required
						{
							pDeviceArray->MultitextureLightMap=1;
						}
//
// See if tri-linear filtering was the problem (TNT2 on 5.22 drivers)
//
						if( D3D_OK!=pDeviceArray->MultitextureLightMap )
						{
							wSetTextureStageState( d3dDevice7, 0, D3DTSS_MIPFILTER, D3DTFP_NONE );
							AllowFail=1;
							pDeviceArray->MultitextureLightMap=wValidateDevice( d3dDevice7, &Passes );
							AllowFail=0;
							if( Passes!=1 && D3D_OK==pDeviceArray->MultitextureLightMap )					// Disable if more than one pass required
							{
								pDeviceArray->MultitextureLightMap=1;
							}
							if( D3D_OK==pDeviceArray->MultitextureLightMap )
							{
								pDeviceArray->MultitextureLightMapFilter=1;
							}
						}
//
// Now try specular light map
//
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_MINFILTER, D3DTFN_LINEAR );
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR );			// Trilinear base texture
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_MIPFILTER, D3DTFP_LINEAR );
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_MINFILTER, D3DTFN_LINEAR );
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_MAGFILTER, D3DTFG_LINEAR );			// Bilinear lightmap texture
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_MIPFILTER, D3DTFP_NONE );

						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_COLOROP, D3DTOP_MODULATE );

						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );

						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_COLOROP, D3DTOP_ADD );

						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );

						wSetTextureStageState(  d3dDevice7, 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
						wSetTextureStageState(  d3dDevice7, 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
//
// See if mode is possible
//
						pDeviceArray->MultitextureSpecularMapFilter=0;
						AllowFail=1;
						Passes=0;
						pDeviceArray->MultitextureSpecularMap=wValidateDevice( d3dDevice7, &Passes );
						AllowFail=0;
						if( Passes!=1 && D3D_OK==pDeviceArray->MultitextureSpecularMap )
							pDeviceArray->MultitextureSpecularMap=1;
//
// See if tri-linear filtering was the problem (TNT2 on 5.22 drivers)
//
						if( D3D_OK!=pDeviceArray->MultitextureSpecularMap )
						{
							wSetTextureStageState( d3dDevice7, 0, D3DTSS_MIPFILTER, D3DTFP_NONE );
							AllowFail=1;
							pDeviceArray->MultitextureSpecularMap=wValidateDevice( d3dDevice7, &Passes );
							AllowFail=0;
							if( Passes!=1 && D3D_OK==pDeviceArray->MultitextureSpecularMap )				// Disable if more than one pass required
							{
								pDeviceArray->MultitextureSpecularMap=1;
							}
							if( D3D_OK==pDeviceArray->MultitextureSpecularMap )
							{
								pDeviceArray->MultitextureSpecularMapFilter=1;
							}
						}
//
// Now try detail texture
//
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_MINFILTER, D3DTFN_LINEAR );
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR );			// Trilinear base texture
						wSetTextureStageState( d3dDevice7, 0, D3DTSS_MIPFILTER, D3DTFP_LINEAR );
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_MINFILTER, D3DTFN_LINEAR );
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_MAGFILTER, D3DTFG_LINEAR );			// Bilinear lightmap texture
						wSetTextureStageState( d3dDevice7, 1, D3DTSS_MIPFILTER, D3DTFP_NONE );

						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );

						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
						wSetTextureStageState(  d3dDevice7, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );

						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA );

						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
						wSetTextureStageState(  d3dDevice7, 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );

						wSetTextureStageState(  d3dDevice7, 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
						wSetTextureStageState(  d3dDevice7, 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
//
// See if mode is possible
//
						pDeviceArray->MultitextureDetailFilter=0;
						AllowFail=1;
						Passes=0;
						pDeviceArray->MultitextureDetail=wValidateDevice( d3dDevice7, &Passes );
						AllowFail=0;
						if( Passes!=1 && D3D_OK==pDeviceArray->MultitextureDetail )
							pDeviceArray->MultitextureDetail=1;
//
// See if tri-linear filtering was the problem (TNT2 on 5.22 drivers)
//
						if( D3D_OK!=pDeviceArray->MultitextureDetail )
						{
							wSetTextureStageState( d3dDevice7, 0, D3DTSS_MIPFILTER, D3DTFP_NONE );
							AllowFail=1;
							pDeviceArray->MultitextureDetail=wValidateDevice( d3dDevice7, &Passes );
							AllowFail=0;
							if( Passes!=1 && D3D_OK==pDeviceArray->MultitextureDetail )					// Disable if more than one pass required
							{
								pDeviceArray->MultitextureDetail=1;
							}
							if( D3D_OK==pDeviceArray->MultitextureDetail )
							{
								pDeviceArray->MultitextureDetailFilter=1;
							}
						}
					}
//
// Release HAL device
//
					wRelease( d3dDevice7 );
					d3dDevice7=0;
				}
			}
		}
		wRelease( BackBufferSurface );
		BackBufferSurface=0;
	}
	wRelease( d3d7 );
	d3d7=0;
//
// Release dummy front buffer
//
	wRelease( FrontBufferSurface );
	FrontBufferSurface=0;
//
// Restore screen mode
//
	if( EntereredFullScreen )
	{
		AllowFail=1;
		wRestoreDisplayMode( DDobject );
		wSetCooperativeLevel( DDobject, hWindow, DDSCL_NORMAL );
		AllowFail=0;
	}
//
// Release DirectDraw object
//
	wRelease( DDobject );
	DDobject=0;
//
// Add to list
//
	if( !Failed )
	{
		if( lpGUID )
		{
			pDeviceArray->DeviceGUID=*lpGUID;
		}
		else
		{
			memset( &pDeviceArray->DeviceGUID, 0, sizeof( GUID ));
		}

		pDeviceArray++;
		NumDevices++;
		if( FoundHal )
			NumHWDevices++;
	}
    return (NumDevices<8) ? DDENUMRET_OK : DDENUMRET_CANCEL;
}




//
// After enumeration, check all the devices
//
void CheckDevices()
{
	for( int t0=0; t0<NumBuffered; t0++ )
	{
		DoEnum( BufferedDevices[ t0 ].lpGUID, BufferedDevices[ t0 ].lpDriverDescription, BufferedDevices[ t0 ].lpDriverName );
		gos_Free( BufferedDevices[ t0 ].lpDriverDescription );
		gos_Free( BufferedDevices[ t0 ].lpDriverName );
	}
}


//
// During enumeration, save all information in an array
//
BOOL BufferDevice( GUID* lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName )
{
	if( lpGUID )
	{
		BufferedDevices[ NumBuffered ].GUID=*lpGUID;
		BufferedDevices[ NumBuffered ].lpGUID=&BufferedDevices[ NumBuffered ].GUID;
	}
	else
	{
		BufferedDevices[ NumBuffered ].lpGUID=0;
	}

	BufferedDevices[ NumBuffered ].lpDriverDescription=(char*)gos_Malloc( strlen(lpDriverDescription)+1 );

	BufferedDevices[ NumBuffered ].lpDriverName=(char*)gos_Malloc( strlen(lpDriverName)+1 );

	strcpy( BufferedDevices[ NumBuffered ].lpDriverDescription, lpDriverDescription );

	strcpy( BufferedDevices[ NumBuffered ].lpDriverName, lpDriverName );

	NumBuffered++;

	return (NumBuffered<8) ? DDENUMRET_OK : DDENUMRET_CANCEL;
}


//
// 0 - primary display driver - "Display" - 0
// x - matrox - //display1 - 0x11a2
// x - ati graphics - //display2 - 0x11e0
//
// Ddraw enumeration in Win98 or NT and DX6
//
BOOL WINAPI DirectDrawEnumerateExCallback( GUID* lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID, HMONITOR hm )
{
	if( hm )
		NumMonitors++;
	return BufferDevice( lpGUID, lpDriverDescription, lpDriverName );
}
//
// Ddraw enumeration in Win95
//
BOOL WINAPI DirectDrawEnumerateCallback( GUID* lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID )
{
	return BufferDevice( lpGUID, lpDriverDescription, lpDriverName );
}




