www.pudn.com > coolMEMORY.rar > AS.cpp


//----------------------------------------------------------------------------- 
// File: AS.cpp 
//----------------------------------------------------------------------------- 
 
#include "AS_Engine.h" 
 
 
// Variables: ***************************************************************** 
AS_PROGRAM_INFO _ASProgramInfo; 
AS_ENGINE *_AS; 
UCHAR ASKeys[256]; 
BOOL ASKeyPressed[256], ASKeyFirst[256]; 
int iASResult; 
DEVMODE	ASSavedDisplayMode; 
// Multi-texture: 
PFNGLMULTITEXCOORD2FARBPROC	glMultiTexCoord2fARB = 0; 
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = 0; 
PFNGLCLIENTACTIVETEXTUREARBPROC	glClientActiveTextureARB = 0; 
// Compiled array vertex: 
PFNGLLOCKARRAYSEXTPROC glLockArraysEXT = 0; 
PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT = 0; 
// General speed variables 
long g_lProgramStartTime	= 0;		// The Program Start Time 
long g_lGameLength			= 0;		// Application Run Time Variable 
long g_lNow	                = 0;		// The Actual Time 
long g_lLastlooptime		= 0;		// Time When Last Loop Was Started 
long g_lDeltatime			= 0;		// Change In Time Since Last Iteration 
long g_lGameTimer = 0; // The game timer. Could be paused 
/////////////////////////////////////////////////////////////////////////////// 
 
// Functions: ***************************************************************** 
HRESULT ASDraw(AS_WINDOW *); 
HRESULT ASCheck(AS_WINDOW *); 
void ASSwapBuffers(HDC, AS_WINDOW *, BOOL); 
char *ASGetFileName(HWND,  char *, char *, BOOL, BOOL, char *); 
void ASLoadTextures(char (*)[256], int, AS_TEXTURE *); 
void ASDestroyTextures(int, AS_TEXTURE *); 
void ASGenOpenGLTextures(int, AS_TEXTURE *); 
void ASDestroyOpenGLTextures(int, AS_TEXTURE *); 
int ASCheckTextureSize(int); 
BOOL ASLoadJpegRGB(AS_TEXTURE *, char *); 
BOOL ASLoadBmp(AS_TEXTURE *, char *); 
BOOL ASLoadPpm(AS_TEXTURE *, char *); 
BOOL ASLoadTga(AS_TEXTURE *, char *); 
void ASSavePpm(AS_TEXTURE *, char *); 
DWORD ASGetCpuSpeed(void); 
void ASRemoveDirectory(char *); 
void ASDrawBoundingBox(float [2][3], float); 
/////////////////////////////////////////////////////////////////////////////// 
 
 
// AS_PROGRAM_INFO functions: ************************************************* 
void AS_PROGRAM_INFO::Init(void) 
{ // begin AS_PROGRAM_INFO() 
	strcpy(byVersion, GAME_VERSION); 
	strcpy(byDate, __DATE__); 
	strcpy(byTime, __TIME__); 
} // end AS_PROGRAM_INFO() 
 
// AS_ENGINE functions: ******************************************************* 
AS_ENGINE::AS_ENGINE(HINSTANCE hInstanceT, LPSTR lpCmdLineT, int iCmdShowT, BOOL bOnlyOne) 
{ // begin AS_ENGINE::AS_ENGINE() 
	DWORD i = 256; 
	int AS_WINDOW_ID; 
	BOOL bTemp; 
	char byTemp[256], *pbyTemp; 
 
	// Init all: 
	memset((this), 0, sizeof(AS_ENGINE)); 
	_AS = this; 
	GetLocalTime(&StartTime); 
	 
	// Set important stuff 
	hInstance = hInstanceT; 
	lpCmdLine = lpCmdLineT; 
	iCmdShow = iCmdShowT; 
    hMutex = OpenMutex(SYNCHRONIZE, FALSE, GAME_NAME); 
    if(hMutex) 
    { 
        if(bOnlyOne) 
		{ 
			CloseHandle(hMutex); 
			MessageBox(0, M_TheProgramIsAlreadyRunning, GAME_NAME, MB_ICONERROR | MB_OK); 
			bShutDown = TRUE; 
			return; 
		} 
    } 
    else 
        hMutex = CreateMutex(NULL, TRUE, GAME_NAME); 
	SetPriorityClass(hInstance, 31); 
	SetThreadPriority(hInstance, 31); 
	_ASProgramInfo.Init(); 
	bActive = TRUE; 
	ASBuildSqrtTable(); 
 
	// Initalize the random generator 
	srand((unsigned) time(NULL)); 
 
	// Find path info 
	GetModuleFileName(hInstance, byProgramExeName, 256); 
	_splitpath(byProgramExeName, byProgramDrive, byProgramDir, NULL, NULL); 
	sprintf(byProgramPath, "%s%s", byProgramDrive, byProgramDir); 
	SetCurrentDirectory(byProgramPath); 
	GetUserName(byUserName, &i); 
 
	// Get general game information: 
	sprintf(byTemp, "%s"AS_GAME_INFO_FILE"", byProgramPath); 
	bLog = GetPrivateProfileInt("general", "log", 1, byTemp); 
	bDebugMode = GetPrivateProfileInt("general", "debug_mode", 0, byTemp); 
	bStartErrorMessage = GetPrivateProfileInt("general", "start_error_message", 1, byTemp); 
	bShowIntro = GetPrivateProfileInt("general", "show_intro", 1, byTemp); 
	 
	// Get directories information: 
	GetPrivateProfileString("directories", "languages", "Data\\Languages", byLanguagesDirectory, 256, byTemp); 
	GetPrivateProfileString("directories", "objects", "Data\\Objects", byObjectsDirectory, 256, byTemp); 
	GetPrivateProfileString("directories", "bitmaps", "Data\\Bitmaps", byBitmapsDirectory, 256, byTemp); 
	GetPrivateProfileString("directories", "music", "Data\\Music", byMusicDirectory, 256, byTemp); 
	GetPrivateProfileString("directories", "sound", "Data\\Sound", bySoundDirectory, 256, byTemp); 
	GetPrivateProfileString("directories", "card_styles", "Data\\CardStyles", byCardStylesDirectory, 256, byTemp); 
	GetPrivateProfileString("directories", "screenshots", "Data\\CardStyles", byScreenshotsDirectory, 256, byTemp); 
	 
	// Get filenames: 
	GetPrivateProfileString("filenames", "log_filename", "Config.ini", byLogFilename, 256, byTemp); 
	GetPrivateProfileString("filenames", "config_filename", "Config.ini", byConfigFilename, 256, byTemp); 
 
	// Get other game information: 
	GetPrivateProfileString("other", "standart_card_style", "Animals", byStandartCardStyle, 256, byTemp); 
	GetPrivateProfileString("other", "standart_music", "r-summer.xm", byStandartMusic, 256, byTemp); 
		 
	// Load the configuration:	 
	_ASConfig = new AS_CONFIG; 
	sprintf(byTemp, "%s%s", byProgramPath, byConfigFilename); 
	_ASConfig->Load(byTemp); 
 
	//  
	// Open the log: 
	// Clear the log contents: 
	if(!(pLogFile = fopen(byLogFilename, "w"))) 
	{ // Give out an error message: 
		sprintf(byTemp, "Couldn't open the log (%s)\nGo sure that all program-files ready for writing!", AS_LOG_FILE); 
		MessageBox(NULL, byTemp, T_Error, MB_OK | MB_ICONINFORMATION); 
		bLog = FALSE; // Disable the log 
	} 
 
	// Create the log header: 
	WriteLogMessage("Log-system activated"); 
	WriteLogMessage("\n"); 
	WriteLogMessage("< "GAME_NAME" "GAME_VERSION" >"); 
	WriteLogMessage("Build: %s %s", _ASProgramInfo.byDate, _ASProgramInfo.byTime); 
	WriteLogMessage("Program start time: Date: %d.%d.%d - Time: %d:%d:%d:%d", StartTime.wMonth, StartTime.wDay, StartTime.wYear,  
																	 StartTime.wHour, StartTime.wMinute,  
																	 StartTime.wSecond, StartTime.wMilliseconds); 
	WriteLogMessage("\n"); 
 
	// Print out the general system info: 
	WriteLogMessage("General system info:"); 
	WriteLogMessage("User name: %s", byUserName); 
	WriteLogMessage("CPU: %d Mhz", ASGetCpuSpeed()); 
	if(GetSystemMetrics(SM_MOUSEPRESENT)) 
		WriteLogMessage("There is a mouse"); 
	else 
		WriteLogMessage("There is no mouse"); 
	WriteLogMessage("Number of mouse buttons: %d", GetSystemMetrics(SM_CMOUSEBUTTONS)); 
	WriteLogMessage("Display resolution: %dx%d", GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); 
 
	// Print out path information: 
	WriteLogMessage("Path information:"); 
	WriteLogMessage("Program path: %s", byProgramPath); 
	WriteLogMessage("Game info file: "AS_GAME_INFO_FILE""); 
	WriteLogMessage("Config filename: %s", byConfigFilename); 
	WriteLogMessage("Languages directory: %s", byLanguagesDirectory); 
	WriteLogMessage("Objects directory: %s", byObjectsDirectory); 
	WriteLogMessage("Bitmaps directory: %s", byBitmapsDirectory); 
	WriteLogMessage("Music directory: %s", byMusicDirectory); 
	WriteLogMessage("Sound directory: %s", bySoundDirectory); 
	WriteLogMessage("Card styles directory: %s", byCardStylesDirectory); 
	WriteLogMessage("Screenshot directory: %s", byScreenshotsDirectory); 
 
	// Last log setup text: 
	WriteLogMessage("\n\n"); 
	WriteLogMessage("Messages:"); 
 
    // Init FPS: 
	dwFPSTimeNow = GetTickCount(); 
	dwFPSTimeLast = GetTickCount(); 
	dwFPSTimeDifference = 0; 
	iFPSRenderedFrames = iFPSFramesSinceCheck = 0; 
	fFPS = 0.0f; 
	EnumerateDisplayModeInfos(); 
 
	// Enumerate the languages: 
	EnumerateLanguages(); 
 
	// Initalize DirectInput: 
	WriteLogMessage("Initalize DirectInput"); 
 
	// Get the OpenGL stuff: 
	WriteLogMessage("Get OpenGL information"); 
	bTemp = _ASConfig->bFullScreen;  
	_ASConfig->bFullScreen = 0;  
	ASCreateWindow(WindowProc, AS_WINDOW_NAME, AS_WINDOW_NAME, _ASConfig->iWindowWidth, _ASConfig->iWindowHeight, NULL, FALSE, ASDraw, ASCheck, NULL, TRUE); 
	AS_WINDOW_ID = GetWindows()-1; 
	ASInitOpenGL(&pWindow[AS_WINDOW_ID], 
				 NULL, 
				 pWindow[AS_WINDOW_ID].GethDC(), 
				 pWindow[AS_WINDOW_ID].GethRC(), FALSE); 
	glGetIntegerv(GL_MAX_LIGHTS, &iMaxLights); 
	InitExtensions(); 
	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &iMaxTextureSize); 
	ASDestroyOpenGL(&pWindow[AS_WINDOW_ID], 
					NULL, 
				    *pWindow[AS_WINDOW_ID].GethDC(), 
				    *pWindow[AS_WINDOW_ID].GethRC()); 
	ASDestroyWindow(pWindow[AS_WINDOW_ID].GethWnd(), AS_WINDOW_NAME); 
	_ASConfig->bFullScreen = bTemp;  
	WriteLogMessage("OpenGL information received"); 
 
	// Print out the OpenGL information: 
	WriteLogMessage("Show OpenGL information"); 
	WriteLogMessage("Version:"); 
	WriteLogMessageS(pbyOpenGLVersion); 
	WriteLogMessage("Chip info:"); 
	WriteLogMessageS(pbyOpenGLChipInfo); 
	WriteLogMessage("Renderer info:"); 
	WriteLogMessageS(pbyOpenGLRendererInfo); 
	WriteLogMessage("Extensions info:"); 
	pbyTemp = pbyOpenGLExtensionInfo;  
	for(;;) 
	{ 
		if(sscanf(pbyTemp, "%s", byTemp) == EOF) 
			break; 
		WriteLogMessage(byTemp); 
		if(*(pbyTemp+strlen(byTemp)+1) == 0) 
			break; 
		pbyTemp += strlen((const char *) byTemp)+1; 
	} 
	WriteLogMessage("Max texture size: %dx%d", iMaxTextureSize, iMaxTextureSize); 
	WriteLogMessage("That's all from OpenGL"); 
 
	if(!bOnlyConfig) 
		ASInitFmod(); 
 
	// Init complete: 
	g_lProgramStartTime = GetTickCount(); 
	WriteLogMessage("AS-Engine init complete"); 
} // end AS_ENGINE::AS_ENGINE() 
 
AS_ENGINE::~AS_ENGINE(void) 
{ // begin AS_ENGINE::~AS_ENGINE() 
	char byTemp[256]; 
 
	// Shut down the program: 
	WriteLogMessage("Program loop left"); 
	WriteLogMessage("Shut down program"); 
	if(!bOnlyConfig) 
		ASDestroyFmod(); 
 
	// Check if there was an error: 
	_ASConfig->bError = _ASConfig->bSetError; 
	_ASConfig->bFirstRun = FALSE; 
	if(_ASConfig->bError) 
		MessageBox(NULL, M_ProgramEndErrorDetected, GAME_NAME, MB_OK | MB_ICONINFORMATION); 
 
	// Save the configuration:	 
	sprintf(byTemp, "%s%s", byProgramPath, byConfigFilename); 
	_ASConfig->Save(byTemp); 
 
	// Delete OpenGL information 
	SAFE_DELETE(pbyOpenGLVersion); 
	SAFE_DELETE(pbyOpenGLChipInfo); 
	SAFE_DELETE(pbyOpenGLRendererInfo); 
	SAFE_DELETE(pbyOpenGLExtensionInfo); 
 
	// Delete last stuff: 
	DestroyDisplayModeInfo(); 
	DestroyLanguage(); 
 
	// Close the Log: 
	WriteLogMessage("Shut down AS-Engine"); 
	WriteLogMessage("Close log"); 
	if(pLogFile) 
		fclose(pLogFile); 
 
	delete _ASConfig; 
} // end AS_ENGINE::~AS_ENGINE() 
 
void AS_ENGINE::WriteLogMessage(const char *pbyMessage, ...) 
{ // begin AS_ENGINE::WriteLogMessage() 
	va_list arg_list; 
 
	// Could we write into the log? 
	if(!bLog || !pLogFile) 
		return; // Nope! 
	 
	// Initialize variable argument list: 
	va_start(arg_list, pbyMessage); 
 
	// Write the text and a newline: 
	vfprintf(pLogFile, pbyMessage, arg_list); 
	putc('\n', pLogFile); 
	fflush(pLogFile); 
 
	va_end(arg_list); 
} // end AS_ENGINE::WriteLogMessage() 
 
void AS_ENGINE::WriteLogMessageS(const char *pbyMessage) 
{ // begin AS_ENGINE::WriteLogMessageS() 
	// Could we write into the log? 
	if(!bLog || !pLogFile) 
		return; // Nope! 
	 
	// Write the text and a newline: 
	fprintf(pLogFile, pbyMessage); 
	putc('\n', pLogFile); 
	fflush(pLogFile); 
} // end AS_ENGINE::WriteLogMessageS() 
 
HWND AS_ENGINE::ASCreateWindow(WNDPROC WindowProc, 
							   LPCTSTR pbyTitle, 
							   LPCTSTR pbyName, 
							   DWORD dwWidth, 
							   DWORD dwHeight, 
			   				   HMENU Menu, 
							   BOOL bFullScreen, 
							   HRESULT (*pDrawTemp)(AS_WINDOW *), 
							   HRESULT (*pCheckTemp)(AS_WINDOW *), 
							   HBRUSH hBackground, 
							   BOOL bIsMainWindowT) 
{ // begin AS_ENGINE::ASCreateWindow() 
	HWND hWnd; 
		 
	WriteLogMessage("Create window"); 
	if(bMainWindow && bIsMainWindowT) 
	{ 
		WriteLogMessage("There is already a main window!"); 
		return NULL; 
	} 
	WriteLogMessage("Titel: %s", pbyTitle); 
	WriteLogMessage("Name: %s", pbyName); 
	WriteLogMessage("Width: %d", dwWidth); 
	WriteLogMessage("Height: %d", dwHeight); 
	WriteLogMessage("Full screen: %d", bFullScreen); 
	iWindows++; 
	pWindow = (AS_WINDOW *) realloc(pWindow, sizeof(AS_WINDOW)*iWindows); 
	hWnd = pWindow[iWindows-1].ASCreateWindow(WindowProc,  
											  pbyTitle, 
											  pbyName, 
											  dwWidth, 
											  dwHeight, 
											  Menu, 
											  bFullScreen, 
											  pDrawTemp, 
											  pCheckTemp, 
											  hBackground, 
											  bIsMainWindowT); 
	pWindow[iWindows-1].SetID(iWindows-1); 
	WriteLogMessage("Window(ID: %d) successful created", iWindows-1); 
	if(!bMainWindow && bIsMainWindowT) 
		bMainWindow = TRUE; 
	return hWnd; 
} // end AS_ENGINE::ASCreateWindow() 
 
HRESULT AS_ENGINE::ASDestroyWindow(HWND *hWnd, LPCTSTR pbyName) 
{ // begin AS_ENGINE::ASDestroyWindow() 
	LPTSTR lpClassName = new char[MAX_PATH]; 
	int i; 
	 
	WriteLogMessage("Destroy window"); 
	WriteLogMessage("Name: %s", pbyName); 
	if(!hWnd) 
	{ // Find the window self: 
		for(i = 0; i < iWindows; i++) 
		{ 
			GetClassName(*pWindow[i].GethWnd(), lpClassName, MAX_PATH); 
			if(!strcmp(lpClassName, pbyName)) 
			{ // We´ve found the window! 
				HWND hTemp;  
 
				hTemp = *pWindow[i].GethWnd(); 
				hWnd = &hTemp; 
				break; 
			} 
		} 
	} 
	if(!hWnd) 
		return 1; 
	for(i = 0; i < iWindows; i++) 
		if(*pWindow[i].GethWnd() == *hWnd) 
		{ 
			WriteLogMessage("ID: %d", i); 
			if(pWindow[i].GetIsMainWindow()) 
				bMainWindow = FALSE; 
			pWindow[i].ASDestroyWindow(hWnd, pbyName);			 
			pWindow[i] = pWindow[iWindows-1]; 
			iWindows--; 
			pWindow = (AS_WINDOW *) realloc(pWindow, sizeof(AS_WINDOW)*iWindows); 
			WriteLogMessage("Window successful destroyed"); 
			return 0; 
		} 
	return 1; 
} // end AS_ENGINE::ASDestroyWindow() 
 
HRESULT AS_ENGINE::EnumerateDisplayModeInfos(void) 
{ // begin AS_ENGINE::EnumerateDisplayModeInfos() 
	DEVMODE devMode; 
 
	DestroyDisplayModeInfo(); 
	WriteLogMessage("Enumerate display modes..."); 
	for(int i = 0;;i++)  
	{ 
		if(!EnumDisplaySettings(NULL, i, &devMode))  
			break; 
		AddDisplayModeInfo(devMode); 
	} 
	WriteLogMessage("Complete"); 
    return 0; 
} // end AS_ENGINE::EnumerateDisplayModeInfos() 
 
HRESULT AS_ENGINE::AddDisplayModeInfo(DEVMODE lpDevMode) 
{ // begin AS_ENGINE::AddDisplayModeInfo() 
	if(lpDevMode.dmBitsPerPel < 16) 
		return 1; 
	DisplayModeInfo.Number++; 
	DisplayModeInfo.pDevMode = (DEVMODE *) realloc(DisplayModeInfo.pDevMode, sizeof(DEVMODE)*DisplayModeInfo.Number); 
	if(!DisplayModeInfo.pDevMode) 
		return 1; 
	CopyMemory(&DisplayModeInfo.pDevMode[DisplayModeInfo.Number-1], &lpDevMode, sizeof(DEVMODE)); 
	WriteLogMessage("Found: %dx%dx%d", DisplayModeInfo.pDevMode[DisplayModeInfo.Number-1].dmPelsWidth, 
									   DisplayModeInfo.pDevMode[DisplayModeInfo.Number-1].dmPelsHeight, 
									   DisplayModeInfo.pDevMode[DisplayModeInfo.Number-1].dmBitsPerPel); 
	return 0; 
} // end AS_ENGINE::AddDisplayModeInfo() 
 
HRESULT AS_ENGINE::DestroyDisplayModeInfo(void) 
{ // begin AS_ENGINE::DestroyDisplayModeInfo() 
	if(DisplayModeInfo.pDevMode) 
		free(DisplayModeInfo.pDevMode); 
	DisplayModeInfo.pDevMode = NULL; 
	DisplayModeInfo.Number = 0; 
	return 0; 
} // end AS_ENGINE::DestroyDisplayModeInfo() 
 
void AS_ENGINE::UpdateWindows(void) 
{ // begin AS_ENGINE::UpdateWindows() 
	// Check the speed control stuff 
	g_lNow = GetTickCount(); 
	g_lDeltatime = g_lNow-g_lLastlooptime; 
	if(!bPause && g_lDeltatime) 
		g_lGameTimer += g_lDeltatime; 
	if(g_lDeltatime > 100) 
		g_lDeltatime = 100; 
	g_lLastlooptime = g_lNow; 
	g_lGameLength = (g_lNow-g_lProgramStartTime)/1000;	 
 
	// Check the windows 
	for(int i = 0; i < iWindows; i++) 
	{ 
		pWindow[i].Check(); 
		pWindow[i].Draw(); 
	} 
	UpdateFPS(); 
} // end AS_ENGINE::UpdateWindows() 
 
int AS_ENGINE::FindWindowID(HWND hWnd) 
{ // begin AS_ENGINE::FindWindowID() 
	for(int i = 0; i < iWindows; i++) 
		if(*pWindow[i].GethWnd() == hWnd) 
			return i; 
	return -1; 
} // end AS_ENGINE::FindWindowID() 
 
float AS_ENGINE::UpdateFPS(void) 
{ // begin AS_ENGINE::UpdateFPS() 
	dwFPSTimeNow = GetTickCount(); 
	dwFPSTimeDifference = dwFPSTimeNow-dwFPSTimeLast; 
	iFPSRenderedFrames++; 
	iFPSFramesSinceCheck++; 
	if(dwFPSTimeDifference > 1000) 
	{ 
		fFPS = (float) iFPSFramesSinceCheck*1000/dwFPSTimeDifference; 
		dwFPSTimeLast = dwFPSTimeNow; 
		iFPSFramesSinceCheck = 0; 
	} 
    return fFPS; 
} // end AS_ENGINE::UpdateFPS() 
 
void AS_ENGINE::ShowMouseCursor(BOOL bState) 
{ // begin AS_ENGINE::ShowMouseCursor() 
	int i; 
	 
	// Disables/Enables the mouse cursor: 
	if(!bState) 
	{ 
		for(;;) 
		{ 
			i = ShowCursor(FALSE); 
			if(i < 0) 
				break; 
		} 
	} 
	else 
	{ 
		for(;;) 
		{ 
			i = ShowCursor(TRUE); 
			if(i >= 0) 
				break; 
		} 
	} 
} // end AS_ENGINE::ShowMouseCursor() 
 
BOOL AS_ENGINE::IsExtensionSupported(const char *pbyExtension) 
{ // begin AS_ENGINE::IsExtensionSupported() 
	const GLubyte *pbyExtensions = NULL; 
	const GLubyte *pbyStart; 
	GLubyte *pbyWhere, *pbyTerminator; 
 
	// Extension names should not have spaces: 
	pbyWhere = (GLubyte *) strchr(pbyExtension, ' '); 
	if(pbyWhere || *pbyExtension == '\0') 
		return 0; 
	pbyExtensions = glGetString(GL_EXTENSIONS); 
	 
	// It takes a bit of care to be fool-proof about parsing the 
	// OpenGL extensions string. Don't be fooled by sub-strings, 
	// etc: 
	pbyStart = pbyExtensions; 
	for(;;)  
	{ 
		pbyWhere = (GLubyte *) strstr((const char *) pbyStart, pbyExtension); 
		if(!pbyWhere) 
			break; 
		pbyTerminator = pbyWhere+strlen(pbyExtension); 
		if(pbyWhere == pbyStart || *(pbyWhere - 1) == ' ') 
			if(*pbyTerminator == ' ' || *pbyTerminator == '\0') 
				return 1; 
		pbyStart = pbyTerminator; 
	} 
	return 0; 
} // end AS_ENGINE::IsExtensionSupported() 
 
void AS_ENGINE::InitExtensions(void) 
{ // begin AS_ENGINE::InitExtensions() 
	// Multi-texture: 
    bMultitexSupported = FALSE; 
	if(!IsExtensionSupported("GL_ARB_multitexture")) 
	{ 
		_AS->WriteLogMessage("Extension GL_ARB_multitexture not found!"); 
		_ASConfig->bMultitexturing = FALSE; 
	} 
	else 
	{ 
		glActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB"); 
		glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB"); 
		glClientActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glClientActiveTextureARB"); 
		if(!glActiveTextureARB || !glMultiTexCoord2fARB || !glClientActiveTextureARB) 
		{ 
			_AS->WriteLogMessage("Couldn't use extension GL_ARB_multitexture!"); 
			_ASConfig->bMultitexturing = FALSE; 
		} 
		else 
			bMultitexSupported = TRUE; 
	} 
 
	// Compiled-vertex-arrays: 
	bCompiledVertexArraySupported = FALSE; 
	if(!IsExtensionSupported("GL_EXT_compiled_vertex_array")) 
	{ 
		_AS->WriteLogMessage("Extension GL_EXT_compiled_vertex_array not found!"); 
		_ASConfig->bMultitexturing = FALSE; 
	} 
	else 
	{ 
		glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) wglGetProcAddress("glLockArraysEXT"); 
		glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) wglGetProcAddress("glUnlockArraysEXT"); 
		if(!glLockArraysEXT || !glUnlockArraysEXT) 
			_AS->WriteLogMessage("Couldn't use extension GL_EXT_compiled_vertex_array!"); 
		else 
			bCompiledVertexArraySupported = TRUE; 
	} 
} // end AS_ENGINE::InitExtensions() 
 
 
// Functions: ***************************************************************** 
// Temporarily draw function: 
HRESULT ASDraw(AS_WINDOW *pWindow) 
{ // begin ASDraw() 
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
	ASSwapBuffers(*pWindow->GethDC(), pWindow, FALSE); 
	return 0; 
} // end ASDraw() 
 
// Temporarily check function: 
HRESULT ASCheck(AS_WINDOW *pWindow) 
{ // begin ASCheck() 
	return 0; 
} // end ASCheck() 
 
void ASSwapBuffers(HDC hDC, AS_WINDOW *pWindow, BOOL bShowInfo) 
{ // begin ASSwapBuffers() 
	char byTemp[256]; 
 
	glEnable(GL_TEXTURE_2D); 
	glEnable(GL_BLEND); 
	glDisable(GL_LIGHTING); 
 
	// Deactivate all lights: 
	if(_ASConfig->byLight) 
	{ 
		for(int i = 0; i < 8; i++) 
			glDisable(GL_LIGHT0+i); 
	} 
	_AS->iActiveLights = 0; 
 
	glColor4f(1.0f, 1.0f, 1.0f, 0.95f); 
	if(_ASConfig->bShowFPS && bShowInfo) 
	{ // Display FPS: 
		sprintf(byTemp, "FPS: %.2f", _AS->GetFPS()); 
		if(!pWindow) 
			ASPrint(0, 10, byTemp, 0); 
		else 
			pWindow->Print(0, 10, byTemp, 0, 0); 
	} 
	glFlush(); 
	SwapBuffers(hDC); 
 
	// Check for screenshot: 
	if(_AS->bMakeScreenshot) 
	{ 
		_AS->bMakeScreenshot = FALSE; 
		pWindow->MakeScreenshot(NULL); 
	} 
} // end ASSwapBuffers() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Opens an dialog to get an filename: 
char *ASGetFileName(HWND hWnd, char *pbyTitle, char *pbyFilter, 
					BOOL bMode, BOOL bMultiSelect, char *pbyInitalDir) 
{ // begin ASGetFileName() 
    static char file[256]; 
    static char fileTitle[256]; 
    OPENFILENAME ofn; 
 
    lstrcpy( file, ""); 
    lstrcpy( fileTitle, ""); 
    ofn.lStructSize       = sizeof(OPENFILENAME); 
    ofn.hwndOwner         = hWnd; 
#ifdef WIN32 
    ofn.hInstance         = (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE); 
#else 
    ofn.hInstance         = (HINSTANCE) GetWindowWord(hWnd, GWW_HINSTANCE); 
#endif 
    ofn.lpstrFilter       = pbyFilter; 
    ofn.lpstrCustomFilter = (LPSTR) NULL; 
    ofn.nMaxCustFilter    = 0L; 
    ofn.nFilterIndex      = 1L; 
    ofn.lpstrFile         = file; 
    ofn.nMaxFile          = sizeof(file); 
    ofn.lpstrFileTitle    = fileTitle; 
    ofn.nMaxFileTitle     = sizeof(fileTitle); 
    ofn.lpstrInitialDir   = pbyInitalDir; 
    ofn.lpstrTitle        = pbyTitle; 
    ofn.nFileOffset       = 0; 
    ofn.nFileExtension    = 0; 
    ofn.lpstrDefExt       = pbyFilter; 
	ofn.lCustData         = 0; 
	ofn.Flags = OFN_PATHMUSTEXIST | OFN_ENABLESIZING | OFN_HIDEREADONLY | OFN_NONETWORKBUTTON; 
    if(!bMode) // We load a file... 
		ofn.Flags |= OFN_FILEMUSTEXIST; 
	if(bMultiSelect) 
		ofn.Flags |= OFN_ALLOWMULTISELECT; 
    if (GetOpenFileName(&ofn)) 
	    return (char *) ofn.lpstrFile; 
	return NULL; 
} // end ASGetFileName() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Loads all textures in the list: 
void ASLoadTextures(char (*byFilename)[256], int iTextures, AS_TEXTURE *Texture) 
{ // begin ASLoadTextures() 
	char byTemp[256]; 
	int i; 
 
	_AS->WriteLogMessage("Load textures"); 
	for(i = 0; i < iTextures; i++) 
	{ 
		sprintf(byTemp, "%s%s\\%s", _AS->byProgramPath, _AS->byBitmapsDirectory, byFilename[i]); 
		strcpy(Texture[i].byFilename, byTemp); 
		if(ASCheckStringEnding(byTemp, "jpg")) 
			ASLoadJpegRGB(&Texture[i], byTemp); 
		else 
		if(ASCheckStringEnding(byTemp, "bmp")) 
			ASLoadBmp(&Texture[i], byTemp); 
		else 
		if(ASCheckStringEnding(byTemp, "ppm")) 
			ASLoadPpm(&Texture[i], byTemp); 
		else 
		if(ASCheckStringEnding(byTemp, "tga")) 
			ASLoadTga(&Texture[i], byTemp); 
	} 
	_AS->WriteLogMessage("Load textures: OK"); 
} // begin ASLoadTextures() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Destroy all textures in the list: 
void ASDestroyTextures(int iTextures, AS_TEXTURE *Texture) 
{ // begin ASDestroyTextures() 
	if(!Texture[0].pbyData) 
		return; 
	_AS->WriteLogMessage("Destroy textures"); 
	for(int i = 0; i < iTextures; i++) 
	{ 
		_AS->WriteLogMessage(Texture[i].byFilename); 
		free(Texture[i].pbyData); 
		Texture[i].pbyData = NULL; 
	} 
} // end ASDestroyTextures() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Generates all OpenGL textures: 
void ASGenOpenGLTextures(int iTextures, AS_TEXTURE *Texture) 
{ // begin ASGenOpenGLTextures() 
	if(!Texture[0].pbyData) 
		return; 
	_AS->WriteLogMessage("Generate OpenGL textures"); 
	for(int i = 0; i < iTextures; i++) 
	{ 
		_AS->WriteLogMessage(Texture[i].byFilename); 
		glGenTextures(1, &Texture[i].iOpenGLID); 
		glBindTexture(GL_TEXTURE_2D, Texture[i].iOpenGLID); 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 
		if(_ASConfig->bUseMipmaps) 
		{ 
			if(_ASConfig->bFastTexturing) 
			{ 
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); 
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST); 
				gluBuild2DMipmaps(GL_TEXTURE_2D, Texture[i].byColorComponents, Texture[i].iWidth, 
								  Texture[i].iHeight, Texture[i].iFormat, GL_UNSIGNED_BYTE, 
								  Texture[i].pbyData); 
			} 
			else 
			{ 
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); 
				gluBuild2DMipmaps(GL_TEXTURE_2D, Texture[i].byColorComponents, Texture[i].iWidth, 
								  Texture[i].iHeight, Texture[i].iFormat, GL_UNSIGNED_BYTE, 
								  Texture[i].pbyData); 
			} 
		} 
		else 
		{ 
			if(_ASConfig->bFastTexturing) 
			{ 
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); 
				glTexImage2D(GL_TEXTURE_2D, 0, Texture[i].byColorComponents, Texture[i].iWidth, 
							 Texture[i].iHeight, 0, Texture[i].iFormat, GL_UNSIGNED_BYTE, 
							 Texture[i].pbyData); 
			} 
			else 
			{ 
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
				glTexImage2D(GL_TEXTURE_2D, 0, Texture[i].byColorComponents, Texture[i].iWidth, 
							 Texture[i].iHeight, 0, Texture[i].iFormat, GL_UNSIGNED_BYTE, 
							 Texture[i].pbyData); 
			} 
		} 
	} 
	_AS->WriteLogMessage("Generate OpenGL textures: OK"); 
} // end ASGenOpenGLTextures() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Destroys all OpenGL textures: 
void ASDestroyOpenGLTextures(int iTextures, AS_TEXTURE *Texture) 
{ // begin ASDestroyOpenGLTextures() 
	if(!Texture[0].pbyData) 
		return; 
	_AS->WriteLogMessage("Destroy OpenGL textures"); 
	for(int i = 0; i < iTextures; i++) 
	{ 
		_AS->WriteLogMessage(Texture[i].byFilename); 
		glDeleteTextures(1, &Texture[i].iOpenGLID); 
	} 
} // end ASDestroyOpenGLTextures() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Make sure dimension is a power of 2: 
int ASCheckTextureSize(int iX) 
{ // begin ASCheckTextureSize() 
    if (iX == 2 || iX == 4 ||  
        iX == 8 || iX == 16 ||  
        iX == 32 || iX == 64 || 
        iX == 128 || iX == 256 || 
		iX == 512 || iX == 1024) 
        return true; 
	return false; 
} // end ASCheckTextureSize() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Loads a jpg texture: 
BOOL ASLoadJpegRGB(AS_TEXTURE *pTexture, char *pbyFilename) 
{ // begin ASLoadJpegRGB() 
	JPEG_CORE_PROPERTIES jcProps; 
	 
	_AS->WriteLogMessage("Load jpg: %s", pbyFilename); 
	memset(&jcProps, 0, sizeof(JPEG_CORE_PROPERTIES)); 
	ijlInit(&jcProps); 
	jcProps.JPGFile = pbyFilename; 
	ijlRead(&jcProps, IJL_JFILE_READPARAMS); 
 
	pTexture->iWidth = (int) jcProps.JPGWidth; 
	pTexture->iHeight = (int) jcProps.JPGHeight; 
 
	// Make sure dimension is a power of 2: 
    if(!ASCheckTextureSize(pTexture->iWidth) || !ASCheckTextureSize(pTexture->iHeight)) 
		_AS->WriteLogMessage("Texture size is no dimension of 2. Maybe there could be some troubles with it!"); 
	if(pTexture->iWidth > _AS->iMaxTextureSize || pTexture->iHeight > _AS->iMaxTextureSize) 
		_AS->WriteLogMessage("Texture size is to large for that system! (max: %dx%d)", _AS->iMaxTextureSize, _AS->iMaxTextureSize); 
 
	// Setup texture information: 
	pTexture->iFormat = GL_RGB; 
	pTexture->iImageBits = 24; 
	pTexture->byColorComponents = 3; 
 
	pTexture->pbyData = (BYTE *) malloc(pTexture->iWidth*pTexture->iHeight*pTexture->byColorComponents); 
	jcProps.DIBWidth = jcProps.JPGWidth; 
	jcProps.DIBHeight = jcProps.JPGHeight; 
	jcProps.DIBChannels = 3; 
	jcProps.DIBColor = IJL_RGB; 
	jcProps.DIBPadBytes = 0; 
	jcProps.DIBBytes = (BYTE *) pTexture->pbyData; 
	jcProps.JPGColor = IJL_YCBCR; 
	if(ijlRead(&jcProps, IJL_JFILE_READWHOLEIMAGE) != IJL_OK) 
	{ 
		SAFE_DELETE(pTexture->pbyData); 
		return true; 
	} 
	ijlFree(&jcProps); 
	 
	return false; 
} // end ASLoadJpegRGB() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Loads a bmp texture: 
BOOL ASLoadBmp(AS_TEXTURE *pTexture, char *pbyFilename) 
{ // begin ASLoadBmp() 
	AUX_RGBImageRec *pImage; 
	int i; 
 
	if(!(pImage = auxDIBImageLoad(pbyFilename))) 
		return true; 
 
	// Get texture dimension: 
	pTexture->iWidth = pImage->sizeX; 
	pTexture->iHeight = pImage->sizeY; 
 
	// Setup texture information: 
	pTexture->iFormat = GL_RGB; 
	pTexture->iImageBits = 24; 
	pTexture->byColorComponents = 3; 
 
	// Make sure dimension is a power of 2: 
	if(!ASCheckTextureSize(pTexture->iWidth) || !ASCheckTextureSize(pTexture->iHeight)) 
		_AS->WriteLogMessage("Texture size is no dimension of 2. Maybe there could be some troubles with it!"); 
	if(pTexture->iWidth > _AS->iMaxTextureSize || pTexture->iHeight > _AS->iMaxTextureSize) 
		_AS->WriteLogMessage("Texture size is to large for that system! (max: %dx%d)", _AS->iMaxTextureSize, _AS->iMaxTextureSize); 
	 
	pTexture->pbyData = (BYTE *) malloc(pTexture->iWidth*pTexture->iHeight*pTexture->byColorComponents); 
 
	// Get the fliped texture data: 
	for(i = 0; i < pTexture->iHeight; i++) 
		memcpy(&pTexture->pbyData[pTexture->byColorComponents*i*pTexture->iWidth], 
			   &pImage->data[pTexture->byColorComponents*(pTexture->iHeight-i-1)*pTexture->iWidth], 
			   pTexture->byColorComponents*pTexture->iWidth); 
 
	free(pImage->data); 
 
	return false; 
} // end ASLoadBmp() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Loads a ppm texture: 
BOOL ASLoadPpm(AS_TEXTURE *pTexture, char *pbyFilename) 
{ // begin ASLoadPpm() 
	int x, y; 
	FILE *fp; 
	 
	fp = fopen(pbyFilename, "rb"); 
	if(!fp) 
		return true; 
	 
	// Get the PPM bitmap size: 
	fscanf(fp, "P6\n%d %d\n255\n", &pTexture->iWidth, &pTexture->iHeight); 
	pTexture->iFormat = GL_RGB; 
	pTexture->iImageBits = 16; 
	pTexture->byColorComponents = 3; 
 
	// Go sure dimension is a power of 2: 
	if(!ASCheckTextureSize(pTexture->iWidth) || !ASCheckTextureSize(pTexture->iHeight)) 
		_AS->WriteLogMessage("Texture size is no dimension of 2. Maybe there could be some troubles with it!"); 
	if(pTexture->iWidth > _AS->iMaxTextureSize || pTexture->iHeight > _AS->iMaxTextureSize) 
		_AS->WriteLogMessage("Texture size is to large for that system! (max: %dx%d)", _AS->iMaxTextureSize, _AS->iMaxTextureSize); 
 
	pTexture->pbyData = (BYTE *) malloc(pTexture->iWidth*pTexture->iHeight*3); 
	if(!pTexture->pbyData) 
		return true; 
 
	// Now load in the bitmap: 
	for(y = 0; y < pTexture->iHeight; y++) 
	{ 
		for(x = 0; x < pTexture->iWidth; x++) 
		{ 
			pTexture->pbyData[(y*pTexture->iWidth+x)*3] = fgetc(fp); 
			pTexture->pbyData[(y*pTexture->iWidth+x)*3+1] = fgetc(fp); 
			pTexture->pbyData[(y*pTexture->iWidth+x)*3+2] = fgetc(fp); 
		} 
	} 
	fclose(fp); 
 
	return false; 
} // end ASLoadPpm() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Loads up a targa file. Supported types are 8,24 and 32 uncompressed images.   
BOOL ASLoadTga(AS_TEXTURE *pTexture, char *pbyFilename) 
{ // begin ASLoadTga() 
    BYTE byType[4], byInfo[7]; 
	BYTE byTemp, *pbyData; 
	int i, iSize, iBread; 
    FILE *fp; 
 
    if(!(fp = fopen(pbyFilename, "r+bt"))) 
        return true; 
         
    fread(&byType, sizeof(BYTE), 3, fp); // Read in colormap info and image type, byte 0 ignored 
    fseek(fp, 12, SEEK_SET); // Seek past the header and useless info 
    fread(&byInfo, sizeof(BYTE), 6, fp); 
 
    if(byType[1] != 0 || (byType[2] != 2 && byType[2] != 3)) 
        return true; 
	 
    pTexture->iWidth = byInfo[0]+byInfo[1]*256;  
    pTexture->iHeight = byInfo[2]+byInfo[3]*256; 
     
	// Make sure dimension is a power of 2: 
    if(!ASCheckTextureSize(pTexture->iWidth) || !ASCheckTextureSize(pTexture->iHeight)) 
		_AS->WriteLogMessage("Texture size is no dimension of 2. Maybe there could be some troubles with it!"); 
	if(pTexture->iWidth > _AS->iMaxTextureSize || pTexture->iHeight > _AS->iMaxTextureSize) 
		_AS->WriteLogMessage("Texture size is to large for that system! (max: %dx%d)", _AS->iMaxTextureSize, _AS->iMaxTextureSize); 
 
    pTexture->iImageBits = byInfo[4];  
    iSize = pTexture->iWidth*pTexture->iHeight; 
 
    // Make sure we are load a supported type: 
    if(pTexture->iImageBits != 32 && pTexture->iImageBits != 24 && pTexture->iImageBits != 8) 
        return true; 
	pTexture->byColorComponents = (char) pTexture->iImageBits/8; 
	 
	// Get texture data: 
    switch(pTexture->iImageBits) 
	{ 
		case 32: 
			if(!(pbyData = (BYTE *) malloc(iSize*4))) 
				return true;  
			if(!(pTexture->pbyData = (BYTE *) malloc(iSize*4))) 
				return true;  
 
			iBread = fread(pbyData, sizeof(BYTE), iSize*4, fp);  
 
			// TGA is stored in BGRA: 
			if(iBread != iSize*4) 
			{ 
				free(pbyData); 
				free(pTexture->pbyData); 
				return true; 
			} 
 
			for(i = 0; i < iSize*4; i += 4) 
			{ 
				byTemp = pbyData[i]; 
				pbyData[i] = pbyData[i+2]; 
				pbyData[i+2] = byTemp; 
			} 
 
			pTexture->iFormat = GL_RGBA; 
		break; 
 
		case 24: 
			if(!(pbyData = (BYTE *) malloc(iSize*3))) 
				return true;  
			if(!(pTexture->pbyData = (BYTE *) malloc(iSize*3))) 
				return true;  
 
			iBread = fread(pbyData, sizeof(BYTE), iSize*3, fp);  
 
			// TGA is stored in BGR: 
			if(iBread != iSize*3) 
			{ 
				free(pbyData); 
				free(pTexture->pbyData); 
				return true; 
			} 
 
			for(i = 0; i < iSize*3; i += 3) 
			{ 
				byTemp = pbyData[i]; 
				pbyData[i] = pbyData[i+2]; 
				pbyData[i+2] = byTemp; 
			} 
 
			pTexture->iFormat = GL_RGB; 
		break; 
		 
		case 8: 
			if(!(pbyData = (BYTE *) malloc(iSize))) 
				return true;  
			if(!(pTexture->pbyData = (BYTE *) malloc(iSize))) 
				return true;  
 
			iBread = fread(pbyData, sizeof(BYTE), iSize, fp);  
 
			if(iBread != iSize) 
			{ 
				free(pbyData); 
				free(pTexture->pbyData); 
				return true; 
			} 
 
			pTexture->iFormat = GL_LUMINANCE; 
		break; 
 
		default: return true; 
	} 
 
    fclose(fp); 
 
	// Flip texture data: 
	for(i = 0; i < pTexture->iHeight; i++) 
		memcpy(&pTexture->pbyData[pTexture->byColorComponents*i*pTexture->iWidth], 
			   &pbyData[pTexture->byColorComponents*(pTexture->iHeight-i-1)*pTexture->iWidth], 
			   pTexture->byColorComponents*pTexture->iWidth); 
	free(pbyData); 
     
	return false; 
} // end ASLoadTga() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Saves a ppm texture: 
void ASSavePpm(AS_TEXTURE *pTextureT, char *pbyFilename) 
{ // begin ASSavePpm() 
	int x, y, c; 
	FILE *fp; 
 
	if(!pTextureT->pbyData) 
		return; 
 
	fp = fopen(pbyFilename, "wb"); 
	if(!fp) 
		return; 
 
	// Write the PPM file: 
	fprintf (fp, "P6\n%d %d\n255\n", pTextureT->iWidth, pTextureT->iHeight); 
	for(y = 0; y < pTextureT->iHeight; y++) 
	{ 
		for(x = 0; x < pTextureT->iWidth; x++) 
		{ 
			c = 0xff & pTextureT->pbyData[((pTextureT->iHeight-1-y)*pTextureT->iWidth+x)*3]; 
			fputc(c, fp); 
			c = 0xff & pTextureT->pbyData[((pTextureT->iHeight-1-y)*pTextureT->iWidth+x)*3+1]; 
			fputc (c, fp); 
			c = 0xff & pTextureT->pbyData[((pTextureT->iHeight-1-y)*pTextureT->iWidth+x)*3+2]; 
			fputc(c, fp); 
		} 
	} 
	fclose(fp); 
} // end ASSavePpm() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Gets the CPU speed: 
DWORD ASGetCpuSpeed(void) 
{ // begin ASGetCpuSpeed() 
  int timeStart = 0; 
  int timeStop = 0; 
  unsigned long StartTicks = 0; 
  unsigned long EndTicks = 0; 
  unsigned long TotalTicks = 0; 
  unsigned long cpuSpeed = 0; 
 
  timeStart = timeGetTime(); 
  for(;;) 
  { 
    timeStop = timeGetTime(); 
    if((timeStop-timeStart) > 1) 
	{ // rollover past 1 
		__asm 
		{ 
			xor eax, eax 
			xor ebx, ebx 
			xor ecx, ecx 
			xor edx, edx 
			_emit 0x0f // CPUID 
			_emit 0xa2 
			_emit 0x0f // RTDSC 
			_emit 0x31 
			mov [StartTicks], eax // Tick counter starts here 
		} 
		break; 
    } 
  } 
  timeStart = timeStop; 
  for(;;) 
  { 
    timeStop = timeGetTime(); 
    if((timeStop-timeStart) > 1000) 
	{ // one second 
		__asm 
		{ 
			xor eax, eax 
			xor ebx, ebx 
			xor ecx, ecx 
			xor edx, edx 
			_emit 0x0f 
			_emit 0xa2 
			_emit 0x0f 
			_emit 0x31 
			mov [EndTicks], eax 
		} 
      break; 
    } 
  } 
  TotalTicks = EndTicks-StartTicks; // total 
  cpuSpeed = TotalTicks/1000000; // speed 
  return((DWORD) cpuSpeed); 
} // end ASGetCpuSpeed() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Removes an directory, but first it removes all files in it: 
void ASRemoveDirectory(char *pbyFilename) 
{ // begin ASRemoveDirectory() 
	WIN32_FIND_DATA FindFileData; 
	char byTemp[256]; 
	HANDLE Find; 
	                    
	// Delete all files in this dictory: 
    sprintf(byTemp, "%s*.*", pbyFilename); 
	Find = FindFirstFile(byTemp, &FindFileData); 
	for(;;) 
	{ 
		if(FindFileData.cFileName[0] != '.' && FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) 
		{ // We found a new sub directory: 
			sprintf(byTemp, "%s%s\\", pbyFilename, FindFileData.cFileName); 
			ASRemoveDirectory(byTemp); 
		} 
		else 
		{ 
			sprintf(byTemp, "%s%s", pbyFilename, FindFileData.cFileName); 
			remove(byTemp); 
		} 
		if(!FindNextFile(Find, &FindFileData)) 
			break; 
	} 
	FindClose(Find); 
	// Remove the empty dictory: 
	RemoveDirectory(pbyFilename); 
} // end ASRemoveDirectory() 
 
/////////////////////////////////////////////////////////////////////////////// 
// Checks if a string ends which a given string: 
BOOL ASCheckStringEnding(char *pbyText, char byEnding[256]) 
{ // begin ASCheckStringEnding() 
	_strlwr(pbyText); 
	for(int i = 0; i < (signed) strlen(byEnding); i++) 
	{ 
		if(pbyText[strlen(pbyText)-(strlen(byEnding)-i)] != byEnding[i]) 
			break; 
	} 
	if(i == (signed) strlen(byEnding)) 
	   return true; 
 
	return false; 
} // end ASCheckStringEnding()