Although the 3dfxvgl.dll driver file will be in the windows \ system directory on 9X if a Voodoo 1, 2 or Rush is present and the current drivers have been installed (using e.g. GLSetup, see the external links section), simply checking for the presence of the driver dll does not guarantee that 3dfx hardware is there, since it might have been removed after driver installation. Also, if you dynamically load 3dfxvgl.dll using LoadLibrary (or load it implicitly by runnning code linked to 3dfxvgl.lib, see the downloads section) and the hardware is not present, 3dfxvgl.dll will fault at runtime when DLL_THREAD_PROCESS_ATTACH is called during the dll load and Glide is initialised but cannot find any 3dfx hardware. The function below dynamically loads the glide2x dll, imports the grSstQueryBoards function (which can be called without initialising Glide) and uses it to determine whether any 3dfx cards are actually present in the machine. The function ought to be futureproof as long as glide2x.dll is contained in future 3dfx driver distributions as well as Glide 3 or later version dlls, and should be fairly easy to modify if glide2x.dll is replaced. ------------------------------------------------------------------------------------------------ // prototypes for dynamic link #include "glide.h" BOOL (__stdcall* GLIDEFUN_grSstQueryBoards) (GrHwConfiguration* hwconfig); bool GlideReports3dfxBoardPresent(void) { char GlideDriver[] = "glide2x.dll"; // load glide HMODULE hmGlide = LoadLibrary(GlideDriver); if (hmGlide) { // get query function GLIDEFUN_grSstQueryBoards = (BOOL (__stdcall*)(GrHwConfiguration* hwconfig)) GetProcAddress(hmGlide, "_grSstQueryBoards@4"); if (GLIDEFUN_grSstQueryBoards) { GrHwConfiguration GlideHwConfig; GLIDEFUN_grSstQueryBoards(&GlideHwConfig); if (GlideHwConfig.num_sst > 0) { FreeLibrary(hmGlide); return true; } else { FreeLibrary(hmGlide); return false; } } else { FreeLibrary(hmGlide); return false; } } else { return false; } } ------------------------------------------------------------------------------------------------ Checking for the presence of 3dfx hardware, however, is not enough to guarantee that 3dfxvgl.dll (if present) will work properly. Consider the case of a machine which begins life with a Voodoo 1 and some generic 2d card onboard, and a copy of the 3dfxvgl.dll standalone driver (correctly) installed by GLSetup, but for which the Voodoo 1 and 2d card are then removed and replaced with a 3dfx Banshee and GLSetup run again. In this case 3dfxvgl.dll will be present in the windows \ system directory, and 3dfx hardware is installed, but 3dfxvgl.dll is not an appropriate choice for runtime rendering (it should not fault on startup, but will not render correctly; the Banshee ICD driver should be loaded through the Microsoft opengl32.dll instead). The function below attempts to identify the precise type of any 3dfx cards present and determine whether any of them are "standalone" (Voodoo 1, 2 or Rush) types, using Glide2x. Like the "GlideReports3dfxBoardPresent" function above, it works by dynamically loading Glide, and should be safe to run even if glide is not installed, or no 3dfx hardware is present. I would be grateful for comments as to whether this function actually works and correctly identifies different varieties of 3dfx board as "standalone" (Voodoo 1, 2 or Rush) or "ICD" (Banshee, Voodoo 3, or later), sent to the mailing address on the front page of the site. I have done some testing, but obviously not on every possible type of OEM manufactured 3dfx card. If it fails, it would be interesting to know the exact type of 3dfx card involved (including OEM manufacturer), the type reported in the GrHwConfiguration structure, and the numerical value of the fbiRev value (if any). ------------------------------------------------------------------------------------------------ // Glide stuff // prototype for dynamic link #include "glide.h" BOOL (__stdcall* GLIDEFUN_grSstQueryBoards) (GrHwConfiguration* hwconfig); void (__stdcall* GLIDEFUN_grGlideInit) (void); void (__stdcall* GLIDEFUN_grGlideShutdown) (void); BOOL (__stdcall* GLIDEFUN_grSstQueryHardware) (GrHwConfiguration* hwconfig); static bool GlideReports3dfxStandaloneBoardPresent(void) { char GlideDriver[] = "glide2x.dll"; // load glide HMODULE hmGlide = LoadLibrary(GlideDriver); if (hmGlide) { // Glide2x driver dll found // get functions GLIDEFUN_grSstQueryBoards = (BOOL (__stdcall*)(GrHwConfiguration* hwconfig)) GetProcAddress(hmGlide, "_grSstQueryBoards@4"); GLIDEFUN_grGlideInit = (void (__stdcall*)(void)) GetProcAddress(hmGlide, "_grGlideInit@0"); GLIDEFUN_grGlideShutdown = (void (__stdcall*)(void)) GetProcAddress(hmGlide, "_grGlideShutdown@0"); GLIDEFUN_grSstQueryHardware = (BOOL (__stdcall*)(GrHwConfiguration* hwconfig)) GetProcAddress(hmGlide, "_grSstQueryHardware@4"); if ((GLIDEFUN_grSstQueryBoards) && (GLIDEFUN_grGlideInit) && (GLIDEFUN_grGlideShutdown) && (GLIDEFUN_grSstQueryHardware)) { GrHwConfiguration GlideHwConfig; GLIDEFUN_grSstQueryBoards(&GlideHwConfig); if (GlideHwConfig.num_sst > 0) { // hardware present; we can initialise Glide GLIDEFUN_grGlideInit(); // fill out hardware structure properly GLIDEFUN_grSstQueryHardware(&GlideHwConfig); // search for a Voodoo 1, Rush or 2 (standalone) type // in data for all boards found bool StandaloneCardPresent = false; for (int i=0; ((i 0x1000 { // standalone card type Voodoo 1 / 2 StandaloneCardPresent = true; } } else if (type == GR_SSTTYPE_SST96) // Voodoo Rush { // standalone card type Voodoo Rush StandaloneCardPresent = true; } } // shut down glide GLIDEFUN_grGlideShutdown(); FreeLibrary(hmGlide); return StandaloneCardPresent; } else { FreeLibrary(hmGlide); return false; } } else { FreeLibrary(hmGlide); return false; } } else { return false; } } ------------------------------------------------------------------------------------------------