Пример #1
0
int SV_GenericIndex( const char *filename )
{
	char	name[64];
	int	i;

	if( !filename || !filename[0] )
		return 0;

	Q_strncpy( name, filename, sizeof( name ));
	COM_FixSlashes( name );

	for( i = 1; i < MAX_CUSTOM && sv.files_precache[i][0]; i++ )
	{
		if( !Q_stricmp( sv.files_precache[i], name ))
			return i;
	}

	if( i == MAX_CUSTOM )
	{
		Host_Error( "SV_GenericIndex: MAX_RESOURCES limit exceeded\n" );
		return 0;
	}

	if( sv.state != ss_loading )
	{
		// g-cont. can we downloading resources in-game ? need testing
		Host_Error( "SV_PrecacheGeneric: ( %s ). Precache can only be done in spawn functions.", name );
		return 0;
	}

	// register new generic resource
	Q_strncpy( sv.files_precache[i], name, sizeof( sv.files_precache[i] ));

	return i;
}
Пример #2
0
/*
=============
COM_LoadFile

=============
*/
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength )
{
	string	name;
	byte	*file, *pfile;
	fs_offset_t	iLength;

	ASSERT( usehunk == 5 );

	if( !filename || !*filename )
	{
		if( pLength ) *pLength = 0;
		return NULL;
	}

	Q_strncpy( name, filename, sizeof( name ));
	COM_FixSlashes( name );

	pfile = FS_LoadFile( name, &iLength, false );
	if( pLength ) *pLength = iLength;

	if( pfile )
	{
		file = malloc( iLength + 1 );
		Q_memcpy( file, pfile, iLength );
		file[iLength] = '\0';
		Mem_Free( pfile );
		pfile = file;
	}

	return pfile;
}
Пример #3
0
/* <2b0b6> ../engine/hashpak.c:1848 */
void HPAK_CheckIntegrity(char *pakname)
{
	char name[256];
	Q_snprintf(name, sizeof(name), "%s", pakname);

	COM_DefaultExtension(name, HASHPAK_EXTENSION);
	COM_FixSlashes(name);
	HPAK_ValidatePak(name);
}
Пример #4
0
/* <9a1a9> ../engine/sv_log.c:162 */
void Log_Open(void)
{
	time_t ltime;
	struct tm *today;
	char szFileBase[MAX_PATH];
	char szTestFile[MAX_PATH];
	int i;
	FileHandle_t fp;
	char *temp;

	if (!g_psvs.log.active || (sv_log_onefile.value != 0.0f && g_psvs.log.file))
		return;

	if (mp_logfile.value == 0.0f)
		Con_Printf("Server logging data to console.\n");
	else
	{
		Log_Close();
		time(&ltime);
		today = localtime(&ltime);

		temp = Cvar_VariableString("logsdir");

		if (!temp || Q_strlen(temp) <= 0 || Q_strstr(temp, ":") || Q_strstr(temp, ".."))
			Q_snprintf(szFileBase, sizeof(szFileBase), "logs/L%02i%02i", today->tm_mon + 1, today->tm_mday);

		else Q_snprintf(szFileBase, sizeof(szFileBase), "%s/L%02i%02i", temp, today->tm_mon + 1, today->tm_mday);

		for (i = 0; i < 1000; i++)
		{
			Q_snprintf(szTestFile, sizeof(szTestFile), "%s%03i.log", szFileBase, i);

			COM_FixSlashes(szTestFile);
			COM_CreatePath(szTestFile);

			fp = FS_OpenPathID(szTestFile, "r", "GAMECONFIG");
			if (!fp)
			{
				COM_CreatePath(szTestFile);
				fp = FS_OpenPathID(szTestFile, "wt", "GAMECONFIG");
				if (fp)
				{
					g_psvs.log.file = (void *)fp;
					Con_Printf("Server logging data to file %s\n", szTestFile);
					Log_Printf("Log file started (file \"%s\") (game \"%s\") (version \"%i/%s/%d\")\n", szTestFile, Info_ValueForKey(Info_Serverinfo(), "*gamedir"), PROTOCOL_VERSION, gpszVersionString, build_number());
				}
				return;
			}
			FS_Close(fp);
		}
		Con_Printf("Unable to open logfiles under %s\nLogging disabled\n", szFileBase);
		g_psvs.log.active = FALSE;
	}
}
Пример #5
0
/*
=============
COM_LoadFile

=============
*/
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength )
{
	string	name;

	if( !filename || !*filename )
	{
		if( pLength ) *pLength = 0;
		return NULL;
	}

	Q_strncpy( name, filename, sizeof( name ));
	COM_FixSlashes( name );

	return FS_LoadFile( name, pLength, false );
}
Пример #6
0
SystemWrapper::library_t *SystemWrapper::GetLibrary(char *name)
{
	char fixedname[MAX_PATH];
	Q_strlcpy(fixedname, name);
	COM_FixSlashes(fixedname);

	library_t *lib = (library_t *)m_Libraries.GetFirst();
	while (lib)
	{
		if (Q_stricmp(lib->name, name) == 0) {
			return lib;
		}

		lib = (library_t *)m_Libraries.GetNext();
	}

	lib = (library_t *)Mem_Malloc(sizeof(library_t));
	if (!lib) {
		DPrintf("ERROR! System::GetLibrary: out of memory (%s).\n", name);
		return nullptr;
	}

	Q_snprintf(lib->name, sizeof(lib->name), "%s." LIBRARY_PREFIX, fixedname);
	FS_GetLocalCopy(lib->name);

	lib->handle = (CSysModule *)Sys_LoadModule(lib->name);
	if (!lib->handle) {
		DPrintf("ERROR! System::GetLibrary: coulnd't load library (%s).\n", lib->name);
		Mem_Free(lib);
		return nullptr;
	}

	lib->createInterfaceFn = (CreateInterfaceFn)Sys_GetFactory(lib->handle);
	if (!lib->createInterfaceFn) {
		DPrintf("ERROR! System::GetLibrary: coulnd't get object factory(%s).\n", lib->name);
		Mem_Free(lib);
		return nullptr;
	}

	m_Libraries.Add(lib);
	DPrintf("Loaded library %s.\n", lib->name);

	return lib;
}
Пример #7
0
/* <2af4b> ../engine/hashpak.c:1678 */
void HPAK_CheckSize(char *pakname)
{
	char fullname[MAX_PATH];
	float maxSize;
	float actualSize;
	FileHandle_t hfile;

	maxSize = hpk_maxsize.value;
	if (!maxSize || pakname == NULL)
		return;

	if (maxSize < 0.0f)
	{
		Con_Printf("hpk_maxsize < 0, setting to 0\n");
		Cvar_DirectSet(&hpk_maxsize, "0");
		return;
	}

	Q_snprintf(fullname, ARRAYSIZE(fullname), "%s", pakname);
#ifdef REHLDS_FIXES
	fullname[ARRAYSIZE(fullname) - 1] = 0;
#endif // REHLDS_FIXES

	COM_DefaultExtension(fullname, HASHPAK_EXTENSION);
	COM_FixSlashes(fullname);

	actualSize = 0.0f;
	maxSize *= 1000000.0f;

	hfile = FS_Open(fullname, "rb");
	if (hfile)
	{
		actualSize = (float)FS_Size(hfile);
		FS_Close(hfile);
	}
	if (actualSize >= maxSize)
	{
		Con_Printf("Server: Size of %s > %f MB, deleting.\n", fullname, hpk_maxsize.value);
		Log_Printf("Server: Size of %s > %f MB, deleting.\n", fullname, hpk_maxsize.value);
		FS_RemoveFile(fullname, 0);
	}
}
void CBaseActionPlaySoundStartDialog::OnCommand( char const *command )
{
	if ( !Q_strcasecmp( command, "choosesound" ) )
	{
		if ( !m_hFileOpenDialog.Get() )
		{
			m_hFileOpenDialog = new vgui::FileOpenDialog( this, "Choose .wav file", true );
		}
		if ( m_hFileOpenDialog )
		{
			char startPath[ MAX_PATH ];
			Q_strncpy( startPath, com_gamedir, sizeof( startPath ) );
			COM_FixSlashes( startPath );
			m_hFileOpenDialog->SetStartDirectory( va( "%s/sound", startPath ) );
			m_hFileOpenDialog->DoModal( false );
		}
		return;
	}
	
	BaseClass::OnCommand( command );
}
void CBaseActionPlaySoundStartDialog::OnFileSelected( char const *fullpath )
{
	if ( !fullpath || !fullpath[ 0 ] )
		return;

	char relativepath[ 512 ];
	g_pFileSystem->FullPathToRelativePath( fullpath, relativepath );

	COM_FixSlashes( relativepath );

	char *soundname = relativepath;
	if ( !Q_strnicmp( relativepath, "sound\\", strlen( "sound\\" ) ) )
	{
		soundname += strlen( "sound\\" );
	}

	m_pSoundName->SetText( soundname );

	if ( m_hFileOpenDialog )
	{
		m_hFileOpenDialog->MarkForDeletion();
	}
}
Пример #10
0
int SV_SoundIndex( const char *filename )
{
	char	name[64];
	int	i;

	// don't precache sentence names!
	if( !filename || !filename[0] || filename[0] == '!' )
		return 0;

	Q_strncpy( name, filename, sizeof( name ));
	COM_FixSlashes( name );

	for( i = 1; i < MAX_SOUNDS && sv.sound_precache[i][0]; i++ )
	{
		if( !Q_stricmp( sv.sound_precache[i], name ))
			return i;
	}

	if( i == MAX_SOUNDS )
	{
		Host_Error( "SV_SoundIndex: MAX_SOUNDS limit exceeded\n" );
		return 0;
	}

	// register new sound
	Q_strncpy( sv.sound_precache[i], name, sizeof( sv.sound_precache[i] ));

	if( sv.state != ss_loading )
	{	
		// send the update to everyone
		BF_WriteByte( &sv.reliable_datagram, svc_soundindex );
		BF_WriteUBitLong( &sv.reliable_datagram, i, MAX_SOUND_BITS );
		BF_WriteString( &sv.reliable_datagram, name );
	}

	return i;
}
Пример #11
0
int SV_ModelIndex( const char *filename )
{
	char	name[64];
	int	i;

	if( !filename || !filename[0] )
		return 0;

	if( *filename == '!' ) filename++;
	Q_strncpy( name, filename, sizeof( name ));
	COM_FixSlashes( name );

	for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ )
	{
		if( !Q_stricmp( sv.model_precache[i], name ))
			return i;
	}

	if( i == MAX_MODELS )
	{
		Host_Error( "SV_ModelIndex: MAX_MODELS limit exceeded\n" );
		return 0;
	}

	// register new model
	Q_strncpy( sv.model_precache[i], name, sizeof( sv.model_precache[i] ));

	if( sv.state != ss_loading )
	{	
		// send the update to everyone
		BF_WriteByte( &sv.reliable_datagram, svc_modelindex );
		BF_WriteUBitLong( &sv.reliable_datagram, i, MAX_MODEL_BITS );
		BF_WriteString( &sv.reliable_datagram, name );
	}

	return i;
}
Пример #12
0
/* <4f3e47> ../game_shared/bot/nav_file.cpp:702 */
bool SaveNavigationMap(const char *filename)
{
	if (filename == NULL)
		return false;

	// Store the NAV file
	COM_FixSlashes(const_cast<char *>(filename));

#ifdef WIN32
	int fd = _open(filename, _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE);
#else
	int fd = creat(filename, S_IRUSR | S_IWUSR | S_IRGRP);
#endif // WIN32

	if (fd < 0)
		return false;

	// store "magic number" to help identify this kind of file
	unsigned int magic = NAV_MAGIC_NUMBER;
	Q_write(fd, &magic, sizeof(unsigned int));

	// store version number of file
	// 1 = hiding spots as plain vector array
	// 2 = hiding spots as HidingSpot objects
	// 3 = Encounter spots use HidingSpot ID's instead of storing vector again
	// 4 = Includes size of source bsp file to verify nav data correlation
	// ---- Beta Release at V4 -----
	// 5 = Added Place info
	unsigned int version = 5;
	Q_write(fd, &version, sizeof(unsigned int));

	// get size of source bsp file and store it in the nav file
	// so we can test if the bsp changed since the nav file was made
	char *bspFilename = GetBspFilename(filename);
	if (bspFilename == NULL)
		return false;

	unsigned int bspSize = (unsigned int)GET_FILE_SIZE(bspFilename);
	CONSOLE_ECHO("Size of bsp file '%s' is %u bytes.\n", bspFilename, bspSize);

	Q_write(fd, &bspSize, sizeof(unsigned int));

	// Build a directory of the Places in this map
	placeDirectory.Reset();

	NavAreaList::iterator it;
	for (it = TheNavAreaList.begin(); it != TheNavAreaList.end(); ++it)
	{
		CNavArea *area = *it;
		Place place = area->GetPlace();

		if (place)
		{
			placeDirectory.AddPlace(place);
		}
	}

	placeDirectory.Save(fd);

	// Store navigation areas
	// store number of areas
	unsigned int count = TheNavAreaList.size();
	Q_write(fd, &count, sizeof(unsigned int));

	// store each area
	for (it = TheNavAreaList.begin(); it != TheNavAreaList.end(); ++it)
	{
		CNavArea *area = *it;
		area->Save(fd, version);
	}

	Q_close(fd);

#ifdef _WIN32
	// output a simple Wavefront file to visualize the generated areas in 3DSMax
	FILE *fp = fopen("c:\\tmp\\nav.obj", "w");
	if (fp)
	{
		for (NavAreaList::iterator iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
		{
			(*iter)->Save(fp);
		}

		fclose(fp);
	}
#endif // _WIN32

	return true;
}
Пример #13
0
/* <2a494> ../engine/hashpak.c:322 */
void HPAK_AddLump(qboolean bUseQueue, char *pakname, struct resource_s *pResource, void *pData, FileHandle_t fpSource)
{
	FileHandle_t iRead;
	FileHandle_t iWrite;
	char name[MAX_PATH];
	char szTempName[MAX_PATH];
	char szOriginalName[MAX_PATH];
	hash_pack_directory_t olddirectory;
	hash_pack_directory_t newdirectory;
	hash_pack_entry_t *pNewEntry;

	byte md5[16];
	MD5Context_t ctx;
	byte *pDiskData;

	if (pakname == NULL)
	{
		Con_Printf("HPAK_AddLump called with invalid arguments:  no .pak filename\n");
		return;
	}
	if (!pResource)
	{
		Con_Printf("HPAK_AddLump called with invalid arguments:  no lump to add\n");
		return;
	}
	if (!pData && !fpSource)
	{
		Con_Printf("HPAK_AddLump called with invalid arguments:  no file handle\n");
		return;
	}
	if (pResource->nDownloadSize < 1024 || (unsigned int)pResource->nDownloadSize > MAX_FILE_SIZE)
	{
		Con_Printf("HPAK_AddLump called with bogus lump, size:  %i\n", pResource->nDownloadSize);
		return;
	}
	Q_memset(&ctx, 0, sizeof(MD5Context_t));
	MD5Init(&ctx);
	if (pData)
		MD5Update(&ctx, (byte *)pData, pResource->nDownloadSize);
	else
	{
		pDiskData = (byte *)Mem_Malloc(pResource->nDownloadSize + 1);
		Q_memset(pDiskData, 0, pResource->nDownloadSize);

		FS_Read(pDiskData, pResource->nDownloadSize, 1, fpSource);
		FS_Seek(fpSource, FS_Tell(fpSource), FILESYSTEM_SEEK_HEAD);

		MD5Update(&ctx, pDiskData, pResource->nDownloadSize);
		Mem_Free(pDiskData);
	}
	MD5Final(md5, &ctx);
	if (Q_memcmp(pResource->rgucMD5_hash, md5, sizeof(md5)) != 0)
	{
		Con_Printf("HPAK_AddLump called with bogus lump, md5 mismatch\n");
		Con_Printf("Purported:  %s\n", MD5_Print(pResource->rgucMD5_hash));
		Con_Printf("Actual   :  %s\n", MD5_Print(md5));
		Con_Printf("Ignoring lump addition\n");
		return;
	}
	if (bUseQueue)
	{
		HPAK_AddToQueue(pakname, pResource, pData, fpSource);
		return;
	}

	Q_snprintf(name, ARRAYSIZE(name), "%s", pakname);
#ifdef REHLDS_FIXES
	name[ARRAYSIZE(name) - 1] = 0;
#endif // REHLDS_FIXES

	COM_DefaultExtension(name, HASHPAK_EXTENSION);
	COM_FixSlashes(name);

	Q_strncpy(szOriginalName, name, ARRAYSIZE(szOriginalName) - 1);
	szOriginalName[ARRAYSIZE(szOriginalName) - 1] = 0;


	iRead = FS_Open(name, "rb");

	if (!iRead)
	{
		HPAK_CreatePak(pakname, pResource, pData, fpSource);
		return;
	}

	COM_StripExtension(name, szTempName);
	COM_DefaultExtension(szTempName, ".hp2");

	iWrite = FS_Open(szTempName, "w+b");
	if (!iWrite)
	{
		FS_Close(iRead);
		Con_Printf("ERROR: couldn't open %s.\n", szTempName);
		return;
	}
	FS_Read(&hash_pack_header, sizeof(hash_pack_header_t), 1, iRead);
	if (hash_pack_header.version != HASHPAK_VERSION)
	{
		FS_Close(iRead);
		FS_Close(iWrite);
		FS_Unlink(szTempName);
		Con_Printf("Invalid .hpk version in HPAK_AddLump\n");
		return;
	}

	FS_Seek(iRead, 0, FILESYSTEM_SEEK_HEAD);
	COM_CopyFileChunk(iWrite, iRead, FS_Size(iRead));
	FS_Seek(iRead, hash_pack_header.nDirectoryOffset, FILESYSTEM_SEEK_HEAD);
	FS_Read(&olddirectory.nEntries, 4, 1, iRead);

	if (olddirectory.nEntries < 1 || (unsigned int)olddirectory.nEntries > MAX_FILE_ENTRIES)
	{
		FS_Close(iRead);
		FS_Close(iWrite);
		FS_Unlink(szTempName);
		Con_Printf("ERROR: .hpk had bogus # of directory entries:  %i\n", olddirectory.nEntries);
		return;
	}

	olddirectory.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * olddirectory.nEntries);

	FS_Read(olddirectory.p_rgEntries, sizeof(hash_pack_entry_t) * olddirectory.nEntries, 1, iRead);
	FS_Close(iRead);

	if (HPAK_FindResource(&olddirectory, pResource->rgucMD5_hash, NULL) != FALSE)
	{
		FS_Close(iWrite);
		FS_Unlink(szTempName);
		Mem_Free(olddirectory.p_rgEntries);
		return;
	}

	newdirectory.nEntries = olddirectory.nEntries + 1;
	newdirectory.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * newdirectory.nEntries);

	Q_memset(newdirectory.p_rgEntries, 0, sizeof(hash_pack_entry_t) * newdirectory.nEntries);
	Q_memcpy(newdirectory.p_rgEntries, olddirectory.p_rgEntries, sizeof(hash_pack_entry_t) * olddirectory.nEntries);

	pNewEntry = NULL;

	for (int i = 0; i < olddirectory.nEntries; i++)
	{
		if (Q_memcmp(pResource->rgucMD5_hash, olddirectory.p_rgEntries[i].resource.rgucMD5_hash, 16) >= 0)
		{
			pNewEntry = &newdirectory.p_rgEntries[i];
#ifndef REHLDS_FIXES
			while (i < olddirectory.nEntries)
			{
				Q_memcpy(&newdirectory.p_rgEntries[i + 1], &olddirectory.p_rgEntries[i], sizeof(hash_pack_entry_t));
				i++;
			}
#else
			Q_memcpy(&newdirectory.p_rgEntries[i + 1], &olddirectory.p_rgEntries[i], (olddirectory.nEntries - i) * sizeof(hash_pack_entry_t));
#endif
			break;
		}
	}

	if (pNewEntry == NULL)
	{
		pNewEntry = &newdirectory.p_rgEntries[newdirectory.nEntries - 1];
	}

	Q_memset(pNewEntry, 0, sizeof(hash_pack_entry_t));
	FS_Seek(iWrite, hash_pack_header.nDirectoryOffset, FILESYSTEM_SEEK_HEAD);

	Q_memcpy(&pNewEntry->resource, pResource, sizeof(resource_t));

	pNewEntry->nOffset = FS_Tell(iWrite);
	pNewEntry->nFileLength = pResource->nDownloadSize;

	if (pData)
		FS_Write(pData, pResource->nDownloadSize, 1, iWrite);

	else COM_CopyFileChunk(iWrite, fpSource, pResource->nDownloadSize);

	hash_pack_header.nDirectoryOffset = FS_Tell(iWrite);

	FS_Write(&newdirectory.nEntries, 4, 1, iWrite);

	for (int j = 0; j < newdirectory.nEntries; j++)
		FS_Write(&newdirectory.p_rgEntries[j], sizeof(hash_pack_entry_t), 1, iWrite);

	if (newdirectory.p_rgEntries)
		Mem_Free(newdirectory.p_rgEntries);

	if (olddirectory.p_rgEntries)
		Mem_Free(olddirectory.p_rgEntries);

	FS_Seek(iWrite, 0, FILESYSTEM_SEEK_HEAD);
	FS_Write(&hash_pack_header, sizeof(hash_pack_header_t), 1, iWrite);
	FS_Close(iWrite);
	FS_Unlink(szOriginalName);
	FS_Rename(szTempName, szOriginalName);
}
Пример #14
0
int main (int argc, char **argv)
{
	int		i, j;
	int		hull;
	entity_t	*ent;
	char	source[1024];
	char	name[1024];
	double		start, end;

	printf( "qcsg.exe v2.8 (%s)\n", __DATE__ );
	printf ("---- qcsg ----\n" );

	for (i=1 ; i<argc ; i++)
	{
		if (!strcmp(argv[i],"-threads"))
		{
			numthreads = atoi (argv[i+1]);
			i++;
		}
		else if (!strcmp(argv[i],"-glview"))
		{
			glview = true;
		}
		else if (!strcmp(argv[i], "-v"))
		{
			printf ("verbose = true\n");
			verbose = true;
		}
		else if (!strcmp(argv[i], "-draw"))
		{
			printf ("drawflag = true\n");
			drawflag = true;
		}
		else if (!strcmp(argv[i], "-noclip"))
		{
			printf ("noclip = true\n");
			noclip = true;
		}
		else if (!strcmp(argv[i], "-onlyents"))
		{
			printf ("onlyents = true\n");
			onlyents = true;
		}
		else if (!strcmp(argv[i], "-nowadtextures"))
		{
			printf ("wadtextures = false\n");
			wadtextures = false;
		}
		else if (!strcmp(argv[i], "-wadinclude"))
		{
			pszWadInclude[nWadInclude++] = strdup( argv[i + 1] );
			i++;
		}
		else if( !strcmp( argv[ i ], "-proj" ) )
		{
			strcpy( qproject, argv[ i + 1 ] );
			i++;
		}
		else if (!strcmp(argv[i], "-hullfile"))
		{
			hullfile = true;
			strcpy( qhullfile, argv[i + 1] );
			i++;
		}
		else if (argv[i][0] == '-')
			Error ("Unknown option \"%s\"", argv[i]);
		else
			break;
	}

	if (i != argc - 1)
		Error ("usage: qcsg [-nowadtextures] [-wadinclude <name>] [-draw] [-glview] [-noclip] [-onlyents] [-proj <name>] [-threads #] [-v] [-hullfile <name>] mapfile");

	SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL);
	start = I_FloatTime ();

	CheckHullFile( hullfile, qhullfile );

	ThreadSetDefault ();
	SetQdirFromPath (argv[i]);

	strcpy (source, ExpandArg (argv[i]));
	COM_FixSlashes(source);
	StripExtension (source);

	strcpy (name, ExpandArg (argv[i]));	
	DefaultExtension (name, ".map");	// might be .reg

	//
	// if onlyents, just grab the entites and resave
	//
	if (onlyents  && !glview)
	{
		char out[1024];
		int	old_entities;
		sprintf (out, "%s.bsp", source);
		LoadBSPFile (out);

		// Get the new entity data from the map file
		LoadMapFile (name);

		// Write it all back out again.
		WriteBSP (source);

		end = I_FloatTime ();
		printf ("%5.0f seconds elapsed\n", end-start);
		return 0;
	}

	//
	// start from scratch
	//
	LoadMapFile (name);

	RunThreadsOnIndividual (nummapbrushes, true, CreateBrush);

	BoundWorld ();

	qprintf ("%5i map planes\n", nummapplanes);

	for (i=0 ; i<NUM_HULLS ; i++)
	{
		char	name[1024];

		if (glview)
			sprintf (name, "%s.gl%i",source, i);
		else
			sprintf (name, "%s.p%i",source, i);
		out[i] = fopen (name, "w");
		if (!out[i])
			Error ("Couldn't open %s",name);
	}

	ProcessModels ();

	qprintf ("%5i csg faces\n", c_csgfaces);
	qprintf ("%5i used faces\n", c_outfaces);
	qprintf ("%5i tiny faces\n", c_tiny);
	qprintf ("%5i tiny clips\n", c_tiny_clip);

	for (i=0 ; i<NUM_HULLS ; i++)
		fclose (out[i]);

	if (!glview)
	{
		EmitPlanes ();
		WriteBSP (source);
	}

	end = I_FloatTime ();
	printf ("%5.0f seconds elapsed\n", end-start);

	return 0;
}
Пример #15
0
/* <2a33c> ../engine/hashpak.c:1401 */
void HPAK_Extract_f(void)
{
	hash_pack_header_t header;
	hash_pack_directory_t directory;
	hash_pack_entry_t *entry;
	char name[MAX_PATH];
	char type[32];
	FileHandle_t fp;
	int nIndex;

	byte *pData;
	int nDataSize;
	FileHandle_t fpOutput;
	char szFileOut[MAX_PATH];

	if (cmd_source != src_command)
		return;

	HPAK_FlushHostQueue();

	if (Cmd_Argc() != 3)
	{
		Con_Printf("Usage:  hpkextract hpkname [all | single index]\n");
		return;
	}
	if (Q_stricmp(Cmd_Argv(2),"all") != 0)
	{
		nIndex = Q_atoi(Cmd_Argv(2));

#ifdef REHLDS_FIXES
		Q_snprintf(name, sizeof(name), "%s", Cmd_Argv(1));
#else
		Q_snprintf(name, 256, "%s", Cmd_Argv(1));
#endif // REHLDS_FIXES
		if (nIndex != -1)
			Con_Printf("Extracting lump %i from %s\n", nIndex, name);
	}
	else
	{
		nIndex = -1;

		Q_snprintf(name, ARRAYSIZE(name), "%s", Cmd_Argv(1));
#ifdef REHLDS_FIXES
		name[ARRAYSIZE(name) - 1] = 0;
#endif // REHLDS_FIXES

		COM_DefaultExtension(name, HASHPAK_EXTENSION);
		Con_Printf("Extracting all lumps from %s.\n", name);
	}

	fp = FS_Open(name, "rb");
	if (!fp)
	{
		Con_Printf("ERROR: couldn't open %s.\n", name);
		return;
	}
	FS_Read(&header, sizeof(hash_pack_header_t), 1, fp);
	if (Q_strncmp(header.szFileStamp, "HPAK", sizeof(header.szFileStamp)))
	{
		Con_Printf("%s is not an HPAK file\n", name);
		FS_Close(fp);
		return;
	}
	if (header.version != HASHPAK_VERSION)
	{
		Con_Printf("hpkextract:  version mismatch\n");
		FS_Close(fp);
		return;
	}
	FS_Seek(fp, header.nDirectoryOffset, FILESYSTEM_SEEK_HEAD);
	FS_Read(&directory.nEntries, 4, 1, fp);
	if (directory.nEntries < 1 || (unsigned int)directory.nEntries > MAX_FILE_ENTRIES)
	{
		Con_Printf("ERROR: HPAK had bogus # of directory entries:  %i\n", directory.nEntries);
		FS_Close(fp);
		return;
	}

	Con_Printf("# of Entries:  %i\n", directory.nEntries);
	Con_Printf("# Type Size FileName : MD5 Hash\n");

	directory.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * directory.nEntries);
	FS_Read(directory.p_rgEntries, sizeof(hash_pack_entry_t) * directory.nEntries, 1, fp);
	for (int nCurrent = 0; nCurrent < directory.nEntries; nCurrent++)
	{
		entry = &directory.p_rgEntries[nCurrent];
		if (nIndex == -1 || nIndex == nCurrent)
		{
			COM_FileBase(entry->resource.szFileName, szFileOut);
			switch (entry->resource.type)
			{
				case t_sound:
					Q_strcpy(type, "sound");
					break;
				case t_skin:
					Q_strcpy(type, "skin");
					break;
				case t_model:
					Q_strcpy(type, "model");
					break;
				case t_decal:
					Q_strcpy(type, "decal");
					break;
				case t_generic:
					Q_strcpy(type, "generic");
					break;
				case t_eventscript:
					Q_strcpy(type, "event");
					break;
				default:
					Q_strcpy(type, "?");
					break;
			}

			Con_Printf("Extracting %i: %10s %.2fK %s\n", nCurrent, type, entry->resource.nDownloadSize / 1024.0f, szFileOut);
			nDataSize = entry->nFileLength;
			if (nDataSize < 1 || (unsigned int)nDataSize >= MAX_FILE_SIZE)
				Con_Printf("Unable to extract data, size invalid:  %s\n", nDataSize);

			else
			{
				pData = (byte *)Mem_Malloc(nDataSize + 1);
				Q_memset(pData, 0, nDataSize);
				FS_Seek(fp, entry->nOffset, FILESYSTEM_SEEK_HEAD);
				FS_Read(pData, nDataSize, 1, fp);
				Q_snprintf(szFileOut, sizeof(szFileOut), "hpklmps\\lmp%04i.wad", nCurrent);
				COM_FixSlashes(szFileOut);
				COM_CreatePath(szFileOut);
				fpOutput = FS_Open(szFileOut, "wb");
				if (fpOutput)
				{
					FS_Write(pData, nDataSize, 1, fpOutput);
					FS_Close(fpOutput);
				}
				else Con_Printf("Error creating lump file %s\n", szFileOut);
				if (pData)
					Mem_Free(pData);
			}
		}
	}

	FS_Close(fp);
	Mem_Free(directory.p_rgEntries);
}
Пример #16
0
int FileSystem_SetGameDirectory(const char *pDefaultDir, const char *pGameDir)
{
	char temp[512];
	char language[256];
	const char *pchLang;

	g_pFileSystem->RemoveAllSearchPaths();
	language[0] = 0;

	if (!bLowViolenceBuild)
	{
		if (CRehldsPlatformHolder::get()->SteamApps() && GetGameAppID() == 70)
		{
			bLowViolenceBuild = CRehldsPlatformHolder::get()->SteamApps()->BIsLowViolence();
		}
	}

	pchLang = CRehldsPlatformHolder::get()->SteamApps() ? CRehldsPlatformHolder::get()->SteamApps()->GetCurrentGameLanguage() : NULL;
	Q_strncpy(language, pchLang ? pchLang : "english", ARRAYSIZE(language));
#ifdef REHLDS_CHECKS
	language[ARRAYSIZE(language) - 1] = 0;
#endif

	if (!g_bIsDedicatedServer && !IsGameSubscribed(pGameDir))
		return 0;

	CRehldsPlatformHolder::get()->SteamAPI_SetBreakpadAppID(GetGameAppID());

	bool bEnableHDPack = BEnabledHDAddon();
	bool bLanguage = (Q_strlen(language) != 0 && Q_stricmp(language, "english")) ? true : false;

	if (!pGameDir)
		pGameDir = pDefaultDir;

	if (pGameDir)
	{
		if (bLowViolenceBuild)
		{
			Q_snprintf(temp, sizeof(temp) - 1, "%s/%s_lv", GetBaseDirectory(), pGameDir);
			temp[sizeof(temp) - 1] = 0;
			COM_FixSlashes(temp);
			g_pFileSystem->AddSearchPathNoWrite(temp, "GAME");
		}
		if (BEnableAddonsFolder())
		{
			Q_snprintf(temp, sizeof(temp) - 1, "%s/%s_addon", GetBaseDirectory(), pGameDir);
			temp[sizeof(temp) - 1] = 0;
			COM_FixSlashes(temp);
			g_pFileSystem->AddSearchPathNoWrite(temp, "GAME");
		}
		if (bLanguage)
		{
			Q_snprintf(temp, sizeof(temp) - 1, "%s/%s_%s", GetBaseDirectory(), pGameDir, language);
			temp[sizeof(temp) - 1] = 0;
			COM_FixSlashes(temp);
			g_pFileSystem->AddSearchPathNoWrite(temp, "GAME");

			if (!COM_CheckParm("-steam"))
			{
				char baseDir[MAX_PATH];
				Q_strncpy(baseDir, GetBaseDirectory(), sizeof(baseDir) - 1);
				baseDir[sizeof(baseDir) - 1] = 0;
				char* tempPtr = Q_strstr(baseDir, "\\game");
				if (tempPtr)
				{
					*tempPtr = 0;
					Q_snprintf(temp, 511, "%s\\localization\\%s_%s", baseDir, pGameDir, language);
					temp[511] = 0;
					COM_FixSlashes(temp);
					g_pFileSystem->AddSearchPathNoWrite(temp, "GAME");
				}
			}
		}
		if (bEnableHDPack)
		{
			Q_snprintf(temp, sizeof(temp) - 1, "%s/%s_hd", GetBaseDirectory(), pGameDir);
			temp[sizeof(temp) - 1] = 0;
			COM_FixSlashes(temp);
			g_pFileSystem->AddSearchPathNoWrite(temp, "GAME");
		}

		Q_snprintf(temp, 511, "%s/%s", GetBaseDirectory(), pGameDir);
		temp[sizeof(temp) - 1] = 0;
		COM_FixSlashes(temp);
		g_pFileSystem->AddSearchPath(temp, "GAME");
		g_pFileSystem->AddSearchPath(temp, "GAMECONFIG");

		Q_snprintf(temp, sizeof(temp) - 1, "%s/%s_downloads", GetBaseDirectory(), pGameDir);
		temp[sizeof(temp) - 1] = 0;
		COM_FixSlashes(temp);
		g_pFileSystem->AddSearchPath(temp, "GAMEDOWNLOAD");

		CheckLiblistForFallbackDir(pGameDir, bLanguage, language, bLowViolenceBuild);
	}
	if (bLanguage)
	{
		if (bLowViolenceBuild)
		{
			Q_snprintf(temp, sizeof(temp) - 1, "%s/%s_lv", GetBaseDirectory(), pDefaultDir);
			temp[sizeof(temp) - 1] = 0;
			COM_FixSlashes(temp);
			g_pFileSystem->AddSearchPathNoWrite(temp, "DEFAULTGAME");
		}

		if (BEnableAddonsFolder())
		{
			Q_snprintf(temp, sizeof(temp) - 1, "%s/%s_addon", GetBaseDirectory(), pDefaultDir);
			temp[sizeof(temp) - 1] = 0;
			COM_FixSlashes(temp);
			g_pFileSystem->AddSearchPathNoWrite(temp, "DEFAULTGAME");
		}

		Q_snprintf(temp, sizeof(temp) - 1, "%s/%s_%s", GetBaseDirectory(), pDefaultDir, language);
		temp[sizeof(temp) - 1] = 0;
		COM_FixSlashes(temp);
		g_pFileSystem->AddSearchPathNoWrite(temp, "DEFAULTGAME");
		if (!COM_CheckParm("-steam"))
		{
			char baseDir[MAX_PATH];

			Q_strncpy(baseDir, GetBaseDirectory(), sizeof(baseDir) - 1);
			baseDir[sizeof(baseDir) - 1] = 0;
			char* tempPtr = Q_strstr(baseDir, "\\game");
			if (tempPtr)
			{
				*tempPtr = 0;
				Q_snprintf(temp, sizeof(temp) - 1, "%s\\localization\\%s_%s", baseDir, pDefaultDir, language);
				temp[sizeof(temp) - 1] = 0;
				COM_FixSlashes(temp);
				g_pFileSystem->AddSearchPathNoWrite(temp, "DEFAULTGAME");
			}
		}
	}
	if (bEnableHDPack)
	{
		Q_snprintf(temp, sizeof(temp) - 1, "%s/%s_hd", GetBaseDirectory(), pDefaultDir);
		temp[sizeof(temp) - 1] = 0;
		COM_FixSlashes(temp);
		g_pFileSystem->AddSearchPathNoWrite(temp, "DEFAULTGAME");
	}

	Q_snprintf(temp, sizeof(temp) - 1, "%s", GetBaseDirectory());
	temp[sizeof(temp) - 1] = 0;
	COM_FixSlashes(temp);
	g_pFileSystem->AddSearchPath(temp, "BASE");

	Q_snprintf(temp, sizeof(temp) - 1, "%s/%s", GetBaseDirectory(), pDefaultDir);
	temp[sizeof(temp) - 1] = 0;
	COM_FixSlashes(temp);
	g_pFileSystem->AddSearchPathNoWrite(temp, "DEFAULTGAME");

	Q_snprintf(temp, sizeof(temp) - 1, "%s/platform", GetBaseDirectory());
	temp[sizeof(temp) - 1] = 0;
	COM_FixSlashes(temp);
	g_pFileSystem->AddSearchPath(temp, "PLATFORM");

	return 1;

}
Пример #17
0
void CheckLiblistForFallbackDir(const char *pGameDir, bool bLanguage, const char *pLanguage, bool bLowViolenceBuild_)
{
	char szTemp[512];
	FileHandle_t hFile;

	Q_snprintf(szTemp, sizeof(szTemp) - 1, "%s/liblist.gam", pGameDir);
	COM_FixSlashes(szTemp);
	g_pFileSystem->GetLocalCopy(szTemp);

	if (Q_stricmp(com_gamedir, pGameDir))
	{
		Q_snprintf(szTemp, 511, "../%s/liblist.gam", pGameDir);
		COM_FixSlashes(szTemp);
		hFile = FS_Open(szTemp, "rt");
	}
	else
		hFile = FS_Open("liblist.gam", "rt");

	if (!hFile)
		return;

	if (FS_EndOfFile(hFile))
	{
		FS_Close(hFile);
		return;
	}
	
	char szFallback[128];
	char szLine[512];

	char *end;
	char *start;
	int bytesToCopy;

	while (1)
	{
		szLine[0] = 0;
		FS_ReadLine(szLine, sizeof(szLine) - 1, hFile);
		szLine[511] = 0;
		if (!Q_strnicmp(szLine, "fallback_dir", Q_strlen("fallback_dir")))
		{
			start = Q_strchr(szLine, '"');
			if (!start)
			{
				FS_Close(hFile);
				return;
			}

			end = Q_strchr(start + 1, '"');
			if (!end)
			{
				FS_Close(hFile);
				return;
			}

			bytesToCopy = (int)(end - start) - 1;
			if (bytesToCopy > sizeof(szFallback) - 2)
			{
				FS_Close(hFile);
				return;
			}
			
			if (bytesToCopy > 0)
				break;
		}
		if (FS_EndOfFile(hFile))
		{
			FS_Close(hFile);
			return;
		}
	}

	Q_strncpy(szFallback, start + 1, bytesToCopy);
	szFallback[bytesToCopy] = 0;

	if (!Q_stricmp(pGameDir, szFallback) )
	{
		FS_Close(hFile);
		return;
	}
	if (bLowViolenceBuild)
	{
		Q_snprintf(szTemp, 511, "%s/%s_lv", GetBaseDirectory(), szFallback);
		szTemp[511] = 0;
		COM_FixSlashes(szTemp);
		g_pFileSystem->AddSearchPathNoWrite(szTemp, "GAME_FALLBACK");
	}
	if (BEnableAddonsFolder())
	{
		Q_snprintf(szTemp, 511, "%s/%s_addon", GetBaseDirectory(), szFallback);
		szTemp[511] = 0;
		COM_FixSlashes(szTemp);
		g_pFileSystem->AddSearchPathNoWrite(szTemp, "GAME_FALLBACK");
	}

	if (bLanguage && pLanguage)
	{
		char baseDir[4096];
		char *tempPtr;

		Q_snprintf(szTemp, 511, "%s/%s_%s", GetBaseDirectory(), szFallback, pLanguage);
		szTemp[511] = 0;
		COM_FixSlashes(szTemp);
		g_pFileSystem->AddSearchPath(szTemp, "GAME_FALLBACK");

		if (!COM_CheckParm("-steam"))
		{
			Q_strncpy(baseDir, GetBaseDirectory(), sizeof(baseDir) - 1);
			baseDir[sizeof(baseDir) - 1] = 0;

			tempPtr = Q_strstr(baseDir, "\\game");
			if (tempPtr)
			{
				*tempPtr = 0;

				Q_snprintf(szTemp, 511, "%s\\localization\\%s_%s", baseDir, szFallback, pLanguage);
				szTemp[511] = 0;

				COM_FixSlashes(szTemp);
				g_pFileSystem->AddSearchPath(szTemp, "GAME_FALLBACK");
			}
		}
	}

	if (BEnabledHDAddon())
	{
		Q_snprintf(szTemp, 511, "%s/%s_hd", GetBaseDirectory(), szFallback);
		szTemp[511] = 0;
		COM_FixSlashes(szTemp);
		g_pFileSystem->AddSearchPathNoWrite(szTemp, "GAME_FALLBACK");
	}

	Q_snprintf(szTemp, 511, "%s/%s", GetBaseDirectory(), szFallback);
	szTemp[511] = 0;
	COM_FixSlashes(szTemp);
	g_pFileSystem->AddSearchPath(szTemp, "GAME_FALLBACK");

	if (Q_stricmp(szFallback, "valve"))
	{
		const int BufLen = 128;
		char *szFileName = new char[BufLen];

		Q_snprintf(szFileName, BufLen - 1, "Resource/%s_%%language%%.txt", szFallback);
		szFileName[BufLen - 1] = 0;

		g_fallbackLocalizationFiles.AddToTail(szFileName);
		CheckLiblistForFallbackDir(szFallback, bLanguage, pLanguage, bLowViolenceBuild);
	}
	FS_Close(hFile);
}
Пример #18
0
qboolean Netchan_CopyFileFragments(netchan_t *chan)
{
	fragbuf_t *p;
	int nsize;
	unsigned char *buffer;
	int pos;
	signed int cursize;
	char filename[MAX_PATH];
	char compressor[32];
	fragbuf_s *n;
	qboolean bCompressed;
	unsigned int uncompressedSize;


	if (!chan->incomingready[FRAG_FILE_STREAM])
		return FALSE;

	p = chan->incomingbufs[FRAG_FILE_STREAM];
	if (!p)
	{
		Con_Printf("%s:  Called with no fragments readied\n", __func__);
		chan->incomingready[FRAG_FILE_STREAM] = FALSE;
		return FALSE;
	}

	bCompressed = FALSE;
	SZ_Clear(&net_message);
	MSG_BeginReading();
	SZ_Write(&net_message, p->frag_message.data, p->frag_message.cursize);
	Q_strncpy(filename, MSG_ReadString(), sizeof(filename) - 1);
	filename[sizeof(filename) - 1] = 0;

	Q_strncpy(compressor, MSG_ReadString(), sizeof(compressor) - 1);
	compressor[sizeof(compressor) - 1] = 0;
	if (!Q_stricmp(compressor, "bz2"))
		bCompressed = TRUE;

	uncompressedSize = (unsigned int)MSG_ReadLong();

#ifdef REHLDS_FIXES
	// TODO: this condition is invalid for server->client
	// TODO: add console message for client
	// TODO: add client name to message
	if (uncompressedSize > 1024 * 64) {
		Con_Printf("Received too large file (size=%u)\nFlushing input queue\n", uncompressedSize);
		Netchan_FlushIncoming(chan, 1);
		return FALSE;
	}
#endif

	if (Q_strlen(filename) <= 0)
	{
		Con_Printf("File fragment received with no filename\nFlushing input queue\n");
		Netchan_FlushIncoming(chan, 1);
		return FALSE;
	}

	if (Q_strstr(filename, ".."))
	{
		Con_Printf("File fragment received with relative path, ignoring\n");
		Netchan_FlushIncoming(chan, 1);
		return FALSE;
	}

	if (filename[0] != '!' && !IsSafeFileToDownload(filename))
	{
		Con_Printf("File fragment received with bad path, ignoring\n");
		Netchan_FlushIncoming(chan, 1);
		return FALSE;
	}
	// This prohibits to write files to FS on server
	if (g_pcls.state == ca_dedicated && filename[0] != '!')
	{
		Con_Printf("File fragment received with bad path, ignoring (2)\n");
		Netchan_FlushIncoming(chan, 1);
		return FALSE;
	}

	Q_strncpy(chan->incomingfilename, filename, MAX_PATH - 1);
	chan->incomingfilename[MAX_PATH - 1] = 0;

	if (filename[0] != '!' && FS_FileExists(filename))
	{
		Con_Printf("Can't download %s, already exists\n", filename);
		Netchan_FlushIncoming(chan, 1);
		return TRUE;
	}

	nsize = 0;
	while (p)
	{
		nsize += p->frag_message.cursize;
		if (p == chan->incomingbufs[FRAG_FILE_STREAM])
			nsize -= msg_readcount;
		p = p->next;
	}

	buffer = (unsigned char*)Mem_ZeroMalloc(nsize + 1);
	if (!buffer)
	{
		Con_Printf("Buffer allocation failed on %i bytes\n", nsize + 1);
		Netchan_FlushIncoming(chan, 1);
		return FALSE;
	}

	p = chan->incomingbufs[FRAG_FILE_STREAM];
	pos = 0;
	while (p)
	{
		n = p->next;

		cursize = p->frag_message.cursize;
		// First message has the file name, don't write that into the data stream, just write the rest of the actual data
		if (p == chan->incomingbufs[FRAG_FILE_STREAM])
		{
			// Copy it in
			cursize -= msg_readcount;
			Q_memcpy(&buffer[pos], &p->frag_message.data[msg_readcount], cursize);
			p->frag_message.cursize = cursize;
		}
		else
		{
			Q_memcpy(&buffer[pos], p->frag_message.data, cursize);
		}
		pos += p->frag_message.cursize;
		Mem_Free(p);
		p = n;

	}

	if (bCompressed)
	{
		unsigned char* uncompressedBuffer = (unsigned char*)Mem_Malloc(uncompressedSize);
		Con_DPrintf("Decompressing file %s (%d -> %d)\n", filename, nsize, uncompressedSize);
		BZ2_bzBuffToBuffDecompress((char*)uncompressedBuffer, &uncompressedSize, (char*)buffer, nsize, 1, 0);
		Mem_Free(buffer);
		pos = uncompressedSize;
		buffer = uncompressedBuffer;
	}

	if (filename[0] == '!')
	{
		if (chan->tempbuffer)
		{
			Con_DPrintf("Netchan_CopyFragments:  Freeing holdover tempbuffer\n");
			Mem_Free(chan->tempbuffer);
		}
		chan->tempbuffer = buffer;
		chan->tempbuffersize = pos;
	}
	else
	{
		char filedir[MAX_PATH];
		char *pszFileName;
		FileHandle_t handle;

#ifdef REHLDS_CHECKS
		Q_strncpy(filedir, filename, sizeof(filedir) - 1);
		filedir[sizeof(filedir) - 1] = 0;
#else
		Q_strncpy(filedir, filename, sizeof(filedir));
#endif // REHLDS_CHECKS
		COM_FixSlashes(filedir);
		pszFileName = Q_strrchr(filedir, '\\');
		if (pszFileName)
		{
			*pszFileName = 0;

#ifdef REHLDS_FIXES
			FS_CreateDirHierarchy(filedir, "GAMEDOWNLOAD");
#endif
		}

#ifndef REHLDS_FIXES
		FS_CreateDirHierarchy(filedir, "GAMEDOWNLOAD");
#endif
		handle = FS_OpenPathID(filename, "wb", "GAMEDOWNLOAD");
		if (!handle)
		{
			Con_Printf("File open failed %s\n", filename);
			Netchan_FlushIncoming(chan, 1);

#ifdef REHLDS_FIXES
			Mem_Free(buffer);
#endif
			return FALSE;
		}

		Sys_Printf("COM_WriteFile: %s\n", filename);
		FS_Write(buffer, pos, 1, handle);
		FS_Close(handle);

		Mem_Free(buffer);
	}
	SZ_Clear(&net_message);
	chan->incomingbufs[FRAG_FILE_STREAM] = nullptr;
	chan->incomingready[FRAG_FILE_STREAM] = FALSE;
	msg_readcount = 0;
	return TRUE;
}
Пример #19
0
bool FS_ParseLiblistGam(const char *filename, const char *gamedir, gameinfo_t *GameInfo)
{
	char *pfile;
	string token;
	
	if(!GameInfo)
		return false;	
	
	char *afile = mpFileSystem->LoadFile(filename, NULL, false);
	
	if(!afile)
		return false;

	// setup default values
	GameInfo->max_edicts = 900;	// default value if not specified
	GameInfo->max_tents = 500;
	GameInfo->max_beams = 128;
	GameInfo->soundclip_dist = 1536;
	GameInfo->max_particles = 4096;
	GameInfo->version = 1.0f;
	GameInfo->falldir[0] = '\0';
	
	GameInfo->title = "New Game";
	GameInfo->gamedir = gamedir;
	GameInfo->basedir = SI.ModuleName;
	GameInfo->sp_entity = "info_player_start";
	GameInfo->mp_entity = "info_player_deathmatch";
	GameInfo->game_dll = "dlls/hl.dll";
	GameInfo->startmap = "newmap";
	GameInfo->dll_path = "cl_dlls";
	GameInfo->iconpath = "game.ico";

	VectorSet(GameInfo->client_mins[0],   0,   0,  0 );
	VectorSet(GameInfo->client_maxs[0],   0,   0,  0 );
	VectorSet(GameInfo->client_mins[1], -16, -16, -36);
	VectorSet(GameInfo->client_maxs[1],  16,  16,  36);
	VectorSet(GameInfo->client_mins[2], -32, -32, -32);
	VectorSet(GameInfo->client_maxs[2],  32,  32,  32);
	VectorSet(GameInfo->client_mins[3], -16, -16, -18);
	VectorSet(GameInfo->client_maxs[3],  16,  16,  18);

	pfile = afile;

	while((pfile = COM_ParseFile(pfile, token)) != NULL)
	{
		if(token == "game")
			pfile = COM_ParseFile(pfile, GameInfo->msTitle);
		if(token == "gamedir")
			pfile = COM_ParseFile(pfile, GameInfo->msGameDir);
		if(token == "fallback_dir")
			pfile = COM_ParseFile(pfile, GameInfo->msFallDir);
		else if(token == "startmap")
		{
			pfile = COM_ParseFile(pfile, GameInfo->msStartMap);
			FS_StripExtension(GameInfo->msStartMap); // HQ2:Amen has extension .bsp
		}
		else if(token == "trainmap" || token == "trainingmap")
		{
			pfile = COM_ParseFile(pfile, GameInfo->msTrainMap);
			FS_StripExtension(GameInfo->msTrainMap); // HQ2:Amen has extension .bsp
		}
		else if(token == "url_info")
			pfile = COM_ParseFile(pfile, GameInfo->msGameURL);
		else if(token == "url_dl")
			pfile = COM_ParseFile(pfile, GameInfo->msUpdateURL);
		else if(token == "gamedll")
		{
			pfile = COM_ParseFile(pfile, GameInfo->msGameDLL);
			COM_FixSlashes(GameInfo->msGameDLL);
		}
		else if(token == "icon")
		{
			pfile = COM_ParseFile(pfile, GameInfo->msIconPath);
			COM_FixSlashes(GameInfo->msIconPath);
			FS_DefaultExtension(GameInfo->msIconPath, ".ico");
		}
		else if(token == "type")
		{
			pfile = COM_ParseFile(pfile, token);

			if(token == "singleplayer_only")
			{
				GameInfo->gamemode = 1;
				strncpy(GameInfo->type, "Single", sizeof(GameInfo->type));
			}
			else if(token == "multiplayer_only")
			{
				GameInfo->gamemode = 2;
				strncpy(GameInfo->type, "Multiplayer", sizeof(GameInfo->type));
			}
			else
			{
				// pass type without changes
				GameInfo->gamemode = 0;
				strncpy(GameInfo->type, token, sizeof(GameInfo->type));
			};
		}
		else if(token == "version")
		{
			pfile = COM_ParseFile(pfile, token);
			GameInfo->version = Q_atof(token);
		}
		else if(token == "size")
		{
			pfile = COM_ParseFile(pfile, token);
			GameInfo->size = Q_atoi(token);
		}
		else if(token == "mpentity")
			pfile = COM_ParseFile(pfile, GameInfo->mp_entity);
		else if(token == "secure")
		{
			pfile = COM_ParseFile(pfile, token);
			GameInfo->secure = Q_atoi(token);
		}
		else if(token == "nomodels")
		{
			pfile = COM_ParseFile(pfile, token);
			GameInfo->nomodels = Q_atoi(token);
		};
	};

	if(!mpFileSystem->IsSysFolderExists(va("%s\\%s", host.rootdir, GameInfo->gamedir)))
		GameInfo->msGameDir = gamedir;

	if(!mpFileSystem->IsSysFolderExists(va("%s\\%s", host.rootdir, GameInfo->falldir)))
		GameInfo->msFallDir = "";

	if(afile != NULL)
		Mem_Free(afile);

	return true;
};