Example #1
0
void Cache_Print_Sounds_And_Totals (void)
{
	char buf[50];
	cache_system_t	*cd;
	cache_system_t *sortarray[MAX_SFX];
	long i=0,j=0;
	long totalsndbytes=0;
	FileHandle_t file = g_pFileSystem->Open(mem_dbgfile.GetString(), "a");
	int subtot=0;

	if (!file)
		return;

	memset(sortarray,sizeof(cache_system_t*)*MAX_SFX,0);

	//pack names into the array.
	for (cd = cache_head.next ; cd != &cache_head ; cd = cd->next)
	{
		if (Q_stristr(cd->name,".wav"))
		{
			sortarray[i++]=cd;
		}
	}

	qsort(sortarray,i,sizeof(cache_system_t*),CacheSystemCompare);


	if (!file)
		return;
	g_pFileSystem->FPrintf(file,"\nCACHED SOUNDS:\n");

	
	//now process the sorted list.  (totals by directory)
	for (j=0;j<i;j++)
	{
		
		g_pFileSystem->FPrintf(file, "\t%16.16s : %s\n", Q_pretifymem(sortarray[j]->size,buf),sortarray[j]->name);
		totalsndbytes+=sortarray[j]->size;

#ifdef _WIN32
		if (j+1==i || ComparePath1(sortarray[j]->name,sortarray[j+1]->name)==0)
		{
			char pathbuf[512];
			_splitpath(sortarray[j]->name,NULL,pathbuf,NULL,NULL);
			g_pFileSystem->FPrintf(file, "\tTotal Bytes used in \"%s\": %s\n",pathbuf,Q_pretifymem(totalsndbytes-subtot,buf));
			subtot=totalsndbytes;
		}
#endif

	}
		


	g_pFileSystem->FPrintf(file,"Total bytes in cache used by sound:  %s\n",Q_pretifymem(totalsndbytes,buf));
	g_pFileSystem->Close(file);
}
Example #2
0
void Cache_Print_Models_And_Totals (void)
{
	char buf[50];
	cache_system_t	*cd;
	cache_system_t *sortarray[512];
	long i=0,j=0;
	long totalbytes=0;
	FileHandle_t file = g_pFileSystem->Open(mem_dbgfile.GetString(), "a");
	int subtot=0;

	if (!file)
		return;



	memset(sortarray,sizeof(cache_system_t*)*512,0);

	//pack names into the array.
	for (cd = cache_head.next ; cd != &cache_head ; cd = cd->next)
	{
		if (strstr(cd->name,".mdl"))
		{
			sortarray[i++]=cd;
		}
	}

	qsort(sortarray,i,sizeof(cache_system_t*),CacheSystemCompare);




	g_pFileSystem->FPrintf(file,"\nCACHED MODELS:\n");

	
	//now process the sorted list.  
	for (j=0;j<i;j++)
	{
		int k;
		mstudiotexture_t	*ptexture;
		studiohdr_t			*phdr=(studiohdr_t*)sortarray[j]->user->data;


		ptexture = (mstudiotexture_t *)( ((char*)phdr) + phdr->textureindex);

		subtot=0;
		for (k = 0; k < phdr->numtextures; k++)
			subtot+=ptexture[k].width * ptexture[k].height+768; // (256*3 for the palette)

		g_pFileSystem->FPrintf(file, "\t%16.16s : %s\n", Q_pretifymem(sortarray[j]->size,buf),sortarray[j]->name);
		totalbytes+=sortarray[j]->size;
	}

	
	g_pFileSystem->FPrintf(file,"Total bytes in cache used by models:  %s\n",Q_pretifymem(totalbytes,buf));
	g_pFileSystem->Close(file);
}
Example #3
0
void Netchan_ReportFlow( netchan_t *chan )
{
	char	incoming[CS_SIZE];
	char	outgoing[CS_SIZE];

	ASSERT( chan != NULL );

	Q_strcpy( incoming, Q_pretifymem((float)chan->flow[FLOW_INCOMING].totalbytes, 3 ));
	Q_strcpy( outgoing, Q_pretifymem((float)chan->flow[FLOW_OUTGOING].totalbytes, 3 ));

	MsgDev( D_INFO, "Signon network traffic:  %s from server, %s to server\n", incoming, outgoing );
}
Example #4
0
/*
============
Cache_Print

============
*/
void Cache_Print (void)
{
	cache_system_t	*cd;
	cache_system_t *sortarray[512];
	int i=0,j=0;

	FileHandle_t file = g_pFileSystem->Open(mem_dbgfile.GetString(), "a");
	if (!file)
		return;

	
	memset(sortarray,sizeof(cache_system_t*)*512,0);
	
	g_pFileSystem->FPrintf(file,"\nCACHE:\n");

	for (cd = cache_head.next ; cd != &cache_head ; cd = cd->next)
	{
		sortarray[i++]=cd;
	}

	//Sort the array alphabetically
	qsort(sortarray,i,sizeof(cache_system_t*),CacheSystemCompare);
	
	for(j=0;j<i;j++)
		g_pFileSystem->FPrintf(file, "%16.16s : %-16s\n", Q_pretifymem(sortarray[j]->size), sortarray[j]->name);

	g_pFileSystem->Close(file);
}
Example #5
0
int MEM_Summary_Console( void )
{
	Msg("MEMORY:  Engine hunk, cache, and zone:\n------------------------------------\n");
	Msg("\tTotal memory available:    %s\n",Q_pretifymem(hunk_size));
	Msg("\tTotal used in low hunk:    %s\n",Q_pretifymem(hunk_low_used));
	Msg("\tTotal used in high hunk:   %s\n",Q_pretifymem(hunk_high_used));
	Msg("\tTotal cache space:         %s\n",Q_pretifymem(hunk_size - hunk_low_used - hunk_high_used));
	Msg("\tTotal cache used:          %s\n",Q_pretifymem(Cache_TotalUsed()));
	Msg("\tTotal memory available:    %s\n",Q_pretifymem(hunk_size - hunk_low_used - hunk_high_used-Cache_TotalUsed()));

	Msg("------------------------------------\n");

	return hunk_size;
}
Example #6
0
void MEM_Summary(void)
{
	FileHandle_t file = g_pFileSystem->Open(mem_dbgfile.GetString(), "a");
	int CacheUsed=Cache_TotalUsed();
	char buf[50];
	if (!file)
		return;


	g_pFileSystem->FPrintf(file, "MEMORY SUMMARY:\n------------------------------------\n");
	g_pFileSystem->FPrintf(file, "\tTotal memory available:    %s\n",Q_pretifymem(hunk_size,buf));
	g_pFileSystem->FPrintf(file, "\tTotal used in low hunk:    %s\n",Q_pretifymem(hunk_low_used,buf));
	g_pFileSystem->FPrintf(file, "\tTotal used in high hunk:   %s\n",Q_pretifymem(hunk_high_used,buf));
	g_pFileSystem->FPrintf(file, "\tTotal cache space:         %s\n",Q_pretifymem(hunk_size - hunk_low_used - hunk_high_used,buf));
	g_pFileSystem->FPrintf(file, "\tTotal cache used:          %s\n",Q_pretifymem(CacheUsed,buf));
	g_pFileSystem->FPrintf(file, "\tTotal memory available:    %s\n",Q_pretifymem(hunk_size - hunk_low_used - hunk_high_used-CacheUsed,buf));
	g_pFileSystem->FPrintf(file, "------------------------------------\n\n");

	g_pFileSystem->Close(file);
}
int main( int argc, char *argv[] )
{
	if ( argc < 2 )
	{
		Msg("Usage:\nmakephx [options] <FILESPEC>\ne.g. makephx [-r] *.phy\n");
		return 0;
	}

	CommandLine()->CreateCmdLine( argc, argv );
	g_bRecursive = CommandLine()->FindParm("-r") > 0 ? true : false;
	g_bQuiet = CommandLine()->FindParm("-quiet") > 0 ? true : false;
	InitFilesystem( "*.*" );
	InitVPhysics();
	// disable automatic packing, we want to do this ourselves.
	physcollision->SetPackOnLoad( false );
	MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
	InstallSpewFunction();

	g_pModelConfig = new KeyValues("config");
	g_pModelConfig->LoadFromFile( g_pFullFileSystem, "phx.cfg", "GAME" );
	g_TotalOut = 0;
	g_TotalCompress = 0;
	FileFindHandle_t handle;
	char fullpath[1024], currentFile[1024], dirName[1024], nameext[256];
	strcpy( fullpath, argv[argc-1] );
	strcpy( fullpath, ExpandPath( fullpath ) );
	strcpy( fullpath, ExpandArg( fullpath ) );
	Q_strncpy(dirName, fullpath, sizeof(dirName));
	Q_StripFilename(dirName);
	Q_strncpy(nameext, fullpath + strlen(dirName)+1, sizeof(nameext));
	CUtlVector< const char * > directoryList;
	directoryList.AddToTail( strdup(dirName) );
	int current = 0;
	int count = 0;
	do 
	{
		if ( g_bRecursive )
		{
			MakeFilename( currentFile, sizeof(currentFile), directoryList[current], "*.*" );
			const char *pFilename = g_pFullFileSystem->FindFirst( currentFile, &handle );
			while ( pFilename )
			{
				if ( pFilename[0] != '.' && g_pFullFileSystem->FindIsDirectory( handle ) )
				{
					MakeDirname( currentFile, sizeof(currentFile), directoryList[current], pFilename );
					directoryList.AddToTail(strdup(currentFile));
				}
				pFilename = g_pFullFileSystem->FindNext( handle );
			}
			g_pFullFileSystem->FindClose( handle );
		}

		MakeFilename(currentFile, sizeof(currentFile), directoryList[current], nameext);
		const char *pFilename = g_pFullFileSystem->FindFirst( currentFile, &handle );
		while ( pFilename )
		{
			phyfile_t phy;
			MakeFilename(currentFile, sizeof(currentFile), directoryList[current], pFilename);
			LoadPHYFile( &phy, currentFile );
			if ( phy.collide.isPacked || phy.collide.solidCount < 1 )
			{
				Msg("%s is not a valid PHY file\n", currentFile );
			}
			else
			{
				WritePHXFile( currentFile, phy );
				count++;
			}
			UnloadPHYFile( &phy );
			pFilename = g_pFullFileSystem->FindNext( handle );
		}
		g_pFullFileSystem->FindClose( handle );
		current++;
	} while( current < directoryList.Count() );

	if ( count )
	{
		if (!g_bQuiet)
		{
			Msg("\n------\nTotal %s, %s\nSaved %s\n", Q_pretifymem( g_TotalOut ), Q_pretifymem( g_TotalCompress ), Q_pretifymem( g_TotalOut - g_TotalCompress ) );
			Msg("%.2f%% savings\n", ((float)(g_TotalOut-g_TotalCompress) / (float)g_TotalOut) * 100.0f );
		}
	}
	else
	{
		Msg("No files found in %s!\n", directoryList[current] );
	}

	return 0;
}
Example #8
0
//-----------------------------------------------------------------------------
// Purpose: Loads up all camera samples from a .dem file into the passed in context.
// Input  : *filename - 
//			smoothing - 
//-----------------------------------------------------------------------------
void LoadSmoothingInfo( const char *filename, CSmoothingContext& smoothing )
{
	char name[ MAX_OSPATH ];
	Q_strncpy (name, filename, sizeof(name) );
	Q_DefaultExtension( name, ".dem", sizeof( name ) );

	CToolDemoFile demoFile;

	if ( !demoFile.Open( filename, true )  )
	{
		Warning( "ERROR: couldn't open %s.\n", name );
		return;
	}

	demoheader_t * header = demoFile.ReadDemoHeader();

	if ( !header )
	{
		demoFile.Close();
		return;
	}

	Msg( "\n\n" );
	Msg( "--------------------------------------------------------------\n" );
	Msg( "demofilestamp:     '%s'\n", header->demofilestamp );
	Msg( "demoprotocol:      %i\n", header->demoprotocol );
	Msg( "networkprotocol:   %i\n", header->networkprotocol );
	Msg( "servername:        '%s'\n", header->servername );
	Msg( "clientname:        '%s'\n", header->clientname );
	Msg( "mapname:           '%s'\n", header->mapname );
	Msg( "gamedirectory:     '%s'\n", header->gamedirectory );
	Msg( "playback_time:     %f seconds\n", header->playback_time );
	Msg( "playback_ticks:    %i ticks\n", header->playback_ticks );
	Msg( "playback_frames:   %i frames\n", header->playback_frames );
	Msg( "signonlength:      %s\n", Q_pretifymem( header->signonlength ) );

	smoothing.active = true;
	Q_strncpy( smoothing.filename, name, sizeof(smoothing.filename) );

	smoothing.smooth.RemoveAll();

	ClearSmoothingInfo( smoothing );

	ParseSmoothingInfo( demoFile, smoothing.smooth );

	Msg( "--------------------------------------------------------------\n" );
	Msg( "smoothing data:    %i samples\n", smoothing.smooth.Count() );

	if ( verbose )
	{
		int c = smoothing.smooth.Count();
		for ( int i = 0; i < c; ++i )
		{
			demosmoothing_t& sample = smoothing.smooth[ i ];

			Msg( "Sample %i:\n", i );
			Msg( "  file pos:         %i\n", sample.file_offset );
			Msg( "  tick:             %i\n", sample.frametick );
			Msg( "  flags:	          %s\n", DescribeFlags( sample.info.flags ) );

			Msg( "  Original Data:\n" );
			Msg( "  origin:           %.4f %.4f %.4f\n", sample.info.viewOrigin.x, sample.info.viewOrigin.y, sample.info.viewOrigin.z );
			Msg( "  viewangles:       %.4f %.4f %.4f\n", sample.info.viewAngles.x, sample.info.viewAngles.y, sample.info.viewAngles.z );
			Msg( "  localviewangles:  %.4f %.4f %.4f\n", sample.info.localViewAngles.x, sample.info.localViewAngles.y, sample.info.localViewAngles.z );

			Msg( "  Resampled Data:\n" );
			Msg( "  origin:           %.4f %.4f %.4f\n", sample.info.viewOrigin2.x, sample.info.viewOrigin2.y, sample.info.viewOrigin2.z );
			Msg( "  viewangles:       %.4f %.4f %.4f\n", sample.info.viewAngles2.x, sample.info.viewAngles2.y, sample.info.viewAngles2.z );
			Msg( "  localviewangles:  %.4f %.4f %.4f\n", sample.info.localViewAngles2.x, sample.info.localViewAngles2.y, sample.info.localViewAngles2.z );

			Msg( "\n" );

		}
	}
	
	demoFile.Close();
}
Example #9
0
/*
==============
Hunk_Print

If "all" is specified, every single allocation is printed.
Otherwise, allocations with the same name will be totaled up before printing.
==============
*/
void Hunk_Print (qboolean all)
{
	hunk_t	*h, *next, *endlow, *starthigh, *endhigh;
	int		count, sum;
	int		totalblocks;
	char	name[HUNK_NAME_LEN+1];

	name[HUNK_NAME_LEN] = 0;
	count = 0;
	sum = 0;
	totalblocks = 0;
	
	FileHandle_t file = g_pFileSystem->Open(mem_dbgfile.GetString(), "a");
	if (!file)
		return;

	h = (hunk_t *)hunk_base;
	endlow = (hunk_t *)(hunk_base + hunk_low_used);
	starthigh = (hunk_t *)(hunk_base + hunk_size - hunk_high_used);
	endhigh = (hunk_t *)(hunk_base + hunk_size);

	//Con_Printf ("          :%8i total hunk size\n", hunk_size);
	//Con_Printf ("-------------------------\n");
	g_pFileSystem->FPrintf(file, "          :%16.16s total hunk size\n", Q_pretifymem(hunk_size));
	g_pFileSystem->FPrintf(file, "-------------------------\n");

	while (1)
	{
	//
	// skip to the high hunk if done with low hunk
	//
		if ( h == endlow )
		{
			g_pFileSystem->FPrintf(file, "-------------------------\n");
			g_pFileSystem->FPrintf(file, "          :%16.16s REMAINING\n", Q_pretifymem(hunk_size - hunk_low_used - hunk_high_used));
			g_pFileSystem->FPrintf(file, "-------------------------\n");
			h = starthigh;
		}
		
	//
	// if totally done, break
	//
		if ( h == endhigh )
			break;

	//
	// run consistancy checks
	//
		if (h->sentinal != HUNK_SENTINAL)
			Sys_Error ("Hunk_Check: trahsed sentinal");
		if (h->size < 16 || h->size + (byte *)h - hunk_base > hunk_size)
			Sys_Error ("Hunk_Check: bad size");
			
		next = (hunk_t *)((byte *)h+h->size);
		count++;
		totalblocks++;
		sum += h->size;

	//
	// print the single block
	//
		memcpy (name, h->name, HUNK_NAME_LEN);
		if (all)
			g_pFileSystem->FPrintf(file, "%8p :%16.16s %16s\n",h, Q_pretifymem(h->size), name);
			
	//
	// print the total
	//
		if (next == endlow || next == endhigh || 
		strncmp (h->name, next->name, HUNK_NAME_LEN) )
		{
			if (!all)
				g_pFileSystem->FPrintf(file, "          :%16.16s %16s (TOTAL)\n",Q_pretifymem(sum), name);
			count = 0;
			sum = 0;
		}

		h = next;
	}

	g_pFileSystem->FPrintf(file, "-------------------------\n");
	g_pFileSystem->FPrintf(file, "%8i total blocks\n", totalblocks);
	g_pFileSystem->Close(file);
}
Example #10
0
void MEM_PrintHunk( void ) 
{ 
	SMemoryBin *pHunkBins = NULL, *pCur = NULL;
	FileHandle_t file = g_pFileSystem->Open(mem_dbgfile.GetString(), "a");

	hunk_t *h = (hunk_t *)hunk_base;

	hunk_t *endlow = (hunk_t *)(hunk_base + hunk_low_used);
	hunk_t *starthigh = (hunk_t *)(hunk_base + hunk_size - hunk_high_used);
	hunk_t *endhigh = (hunk_t *)(hunk_base + hunk_size);

	if (!file)
		return;

	g_pFileSystem->FPrintf(file, "\n\nHunk:\n\n" ); 

	while (1)
	{
		//
		// skip to the high hunk if done with low hunk
		//
		if ( h == endlow )
			h = starthigh;
		
		//
		// if totally done, break
		//
		if ( h == endhigh )
			break;

		// total up info
		pCur = pHunkBins;
		while( pCur )
		{
			if( !strncmp( pCur->binName, h->name, sizeof( h->name ) ) )
			{
				pCur->size += h->size;
				break;
			}

			pCur = pCur->pNext;
		}

		// If we ran out of bins, make a newmem one.
		if( !pCur )
		{
			pCur = (SMemoryBin *) malloc( sizeof( SMemoryBin ) );
			Q_strncpy( pCur->binName, h->name, sizeof(pCur->binName) );

			pCur->size = h->size;

			pCur->pNext = pHunkBins;
			pHunkBins = pCur;
		}

		// next block
		h = (hunk_t *)((byte *)h + h->size);
	}

	pCur = pHunkBins;
	while( pCur )
	{
		SMemoryBin *pLast = pCur;

		g_pFileSystem->FPrintf(file, "%16.16s : %16s \n", Q_pretifymem(pCur->size), pCur->binName);

		pCur = pCur->pNext;
		free( pLast );
	}

	pHunkBins = NULL;
	g_pFileSystem->Close(file);
//	Hunk_Print( 1 ); 
}
void Correlate( CUtlRBTree< ReferencedFile, int >& referencedfiles, CUtlVector< FileEntry >& contentfiles, const char *modname )
{
	int i;
	int c = contentfiles.Count();
	
	double totalDiskSize = 0;
	double totalReferencedDiskSize = 0;
	double totalWhiteListDiskSize = 0;

	for ( i = 0; i < c; ++i )
	{
		totalDiskSize += contentfiles [ i ].size;
	}

	vprint( 0, "Content tree size on disk %s\n", Q_pretifymem( totalDiskSize, 3 ) );
	
	// Analysis is to walk tree and see which files on disk are referenced in the .lst files
	// Need a fast lookup from file symbol to referenced list
	CUtlRBTree< ReferencedFile, int >	tree( 0, 0, ReferencedFileLessFunc );
	c = referencedfiles.Count();
	for ( i = 0 ; i < c; ++i )
	{
		tree.Insert( referencedfiles[ i ] );
	}

	// Now walk the on disk file and see check off resources which are in referenced
	c = contentfiles.Count();
	int invalidindex = tree.InvalidIndex();
	unsigned int refcounted = 0;
	unsigned int whitelisted = 0;

	filesystem->RemoveFile( CFmtStr( "%swhitelist.lst", g_szReslistDir ), "GAME" );

	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = contentfiles[ i ];

		ReferencedFile foo;
		foo.sym = entry.sym;

		bool gameref = tree.Find( foo ) != invalidindex;
		char const *fn = g_Analysis.symbols.String( entry.sym );

		bool whitelist = g_WhiteList.Find( entry.sym ) != g_WhiteList.InvalidIndex();

		if ( gameref || whitelist )
		{
			entry.referenced = gameref ? REFERENCED_GAME : REFERENCED_WHITELIST;
			totalReferencedDiskSize += entry.size;
			if ( entry.referenced == REFERENCED_WHITELIST )
			{
				logprint( CFmtStr( "%swhitelist.lst", g_szReslistDir ), "\"%s\\%s\"\n", modname, fn );

				totalWhiteListDiskSize += entry.size;
				++whitelisted;
			}
			++refcounted;
		}
	}

	vprint( 0, "Found %i referenced (%i whitelist) files in tree, %s\n", refcounted, whitelisted, Q_pretifymem( totalReferencedDiskSize, 2 ) );
	vprint( 0, "%s appear unused\n", Q_pretifymem( totalDiskSize - totalReferencedDiskSize, 2 ) );

	// Now sort and dump the unreferenced ones..
	vprint( 0, "Sorting unreferenced files list...\n" );

	CUtlRBTree< FileEntry, int >	unreftree( 0, 0, FileEntryLessFunc );
	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = contentfiles[ i ];
		if ( entry.referenced != REFERENCED_NO )
			continue;

		unreftree.Insert( entry );
	}

	// Now walk the unref tree in order
	i = unreftree.FirstInorder();
	invalidindex = unreftree.InvalidIndex();
	int index = 0;
	while ( i != invalidindex )
	{
		FileEntry & entry = unreftree[ i ];

		if ( showreferencedfiles )
		{
			vprint( 1, "%6i %12s: %s\n", ++index, Q_pretifymem( entry.size, 2 ), g_Analysis.symbols.String( entry.sym ) );
		}
		
		i = unreftree.NextInorder( i );
	}

	if ( showmapfileusage )
	{
		vprint( 0, "Writing referenced.csv...\n" );

		// Now walk the list of referenced files and print out how many and which maps reference them
		i = tree.FirstInorder();
		invalidindex = tree.InvalidIndex();
		index = 0;
		while ( i != invalidindex )
		{
			ReferencedFile & entry = tree[ i ];

			char ext[ 32 ];
			Q_ExtractFileExtension( g_Analysis.symbols.String( entry.sym ), ext, sizeof( ext ) );

			logprint( "referenced.csv", "\"%s\",\"%s\",%d", g_Analysis.symbols.String( entry.sym ), ext, entry.maplist.Count() );

			int mapcount = entry.maplist.Count();
			for ( int j = 0 ; j < mapcount; ++j )
			{
				char basemap[ 128 ];
				Q_FileBase( g_Analysis.symbols.String( entry.maplist[ j ] ), basemap, sizeof( basemap ) );
				logprint( "referenced.csv", ",\"%s\"", basemap );
			}

			logprint( "referenced.csv", "\n" );
			
			i = tree.NextInorder( i );
		}
	}


	vprint( 0, "\nBuilding directory summary list...\n" );

	// Now build summaries by root branch off of gamedir (e.g., for sound, materials, models, etc.)
	CUtlDict< DirEntry, int > directories;
	invalidindex = directories.InvalidIndex();
	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = contentfiles[ i ];

		// Get the dir name
		char const *dirname = g_Analysis.symbols.String( entry.sym );

		const char *backslash = strstr( dirname, "\\" );

		char dir[ 256 ];
		if ( !backslash )
		{
			dir[0] = 0;
		}
		else
		{
			Q_strncpy( dir, dirname, backslash - dirname + 1);
		}

		
		int idx = directories.Find( dir );
		if ( idx == invalidindex )
		{
			DirEntry foo;
			idx = directories.Insert( dir, foo );
		}

		DirEntry & de = directories[ idx ];
		de.total += entry.size;
		if ( entry.referenced == REFERENCED_NO )
		{
			de.unreferenced += entry.size;
		}
		if ( entry.referenced == REFERENCED_WHITELIST )
		{
			de.whitelist += entry.size;
		}
	}

	if ( spewdeletions )
	{
		// Spew deletion commands to console
		if ( immediatedelete )
		{
			vprint( 0, "\n\nDeleting files...\n" );
		}
		else
		{
			vprint( 0, "\n\nGenerating deletions.bat\n" );
		}

		i = unreftree.FirstInorder();
		invalidindex = unreftree.InvalidIndex();
		float deletionSize = 0.0f;
		int deletionCount = 0;

		while ( i != invalidindex )
		{
			FileEntry & entry = unreftree[ i ];
			i = unreftree.NextInorder( i );

			// Don't delete stuff that's in the white list
			if ( g_WhiteList.Find( entry.sym ) != g_WhiteList.InvalidIndex() )
			{
				if ( verbose )
				{
					vprint( 0, "whitelist blocked deletion of %s\n", g_Analysis.symbols.String( entry.sym ) );
				}
				continue;
			}

			++deletionCount;
			deletionSize += entry.size;

			if ( immediatedelete ) 
			{
				if ( _chmod( g_Analysis.symbols.String( entry.sym ), _S_IWRITE ) == -1 )
				{
					vprint( 0, "Could not find file %s\n", g_Analysis.symbols.String( entry.sym ) );
				}
				if ( _unlink( g_Analysis.symbols.String( entry.sym ) ) == -1 )
				{
					vprint( 0, "Could not delete file %s\n", g_Analysis.symbols.String( entry.sym ) );
				}

				if ( deletionCount % 1000 == 0 )
				{
					vprint( 0, "...deleted %i files\n", deletionCount );
				}
			}
			else
			{
				logprint( "deletions.bat", "del \"%s\" /f\n",  g_Analysis.symbols.String( entry.sym ) );
			}
		}

		vprint( 0, "\nFile deletion (%d files, %s)\n\n", deletionCount, Q_pretifymem(deletionSize, 2) );
	}

	double grand_total = 0;
	double grand_total_unref = 0;
	double grand_total_white = 0;

	char totalstring[ 20 ];
	char unrefstring[ 20 ];
	char refstring[ 20 ];
	char whiteliststring[ 20 ];

	vprint( 0, "---------------------------------------- Summary ----------------------------------------\n" );

	vprint( 0, "% 15s               % 15s               % 15s               % 15s %12s\n",
		"Referenced",
		"WhiteListed",
		"Unreferenced",
		"Total",
		"Directory" );

	// Now walk the dictionary in order
	i = directories.First();
	while ( i != invalidindex )
	{
		DirEntry & de = directories[ i ];

		double remainder = de.total - de.unreferenced;

		float percent_unref = 0.0f;
		float percent_white = 0.0f;
		if ( de.total > 0 )
		{
			percent_unref = 100.0f * (float)de.unreferenced / (float)de.total;
			percent_white = 100.0f * (float)de.whitelist / (float)de.total;
		}

		Q_strncpy( totalstring, Q_pretifymem( de.total, 2 ), sizeof( totalstring ) );
		Q_strncpy( unrefstring, Q_pretifymem( de.unreferenced, 2 ), sizeof( unrefstring ) );
		Q_strncpy( refstring, Q_pretifymem( remainder, 2 ), sizeof( refstring ) );
		Q_strncpy( whiteliststring, Q_pretifymem( de.whitelist, 2 ), sizeof( whiteliststring ) );

		vprint( 0, "%15s (%8.3f%%)   %15s (%8.3f%%)   %15s (%8.3f%%)   %15s => dir: %s\n",
			refstring, 100.0f - percent_unref, whiteliststring, percent_white, unrefstring, percent_unref, totalstring, directories.GetElementName( i ) );

		grand_total += de.total;
		grand_total_unref += de.unreferenced;
		grand_total_white += de.whitelist;

		i = directories.Next( i );
	}

	Q_strncpy( totalstring, Q_pretifymem( grand_total, 2 ), sizeof( totalstring ) );
	Q_strncpy( unrefstring, Q_pretifymem( grand_total_unref, 2 ), sizeof( unrefstring ) );
	Q_strncpy( refstring, Q_pretifymem( grand_total - grand_total_unref, 2 ), sizeof( refstring ) );
	Q_strncpy( whiteliststring, Q_pretifymem( grand_total_white, 2 ), sizeof( whiteliststring ) );

	double percent_unref = 100.0 * grand_total_unref / grand_total;
	double percent_white = 100.0 * grand_total_white / grand_total;

	vprint( 0, "-----------------------------------------------------------------------------------------\n" );
	vprint( 0, "%15s (%8.3f%%)   %15s (%8.3f%%)   %15s (%8.3f%%)   %15s\n",
		refstring, 100.0f - percent_unref, whiteliststring, percent_white, unrefstring, percent_unref, totalstring );
}
Example #12
0
static qboolean HPAK_Validate( const char *filename, qboolean quiet )
{
	file_t		*f;
	hpak_dir_t	*dataDir;
	hpak_header_t	hdr;
	byte		*dataPak;
	int		i, num_lumps;
	MD5Context_t	MD5_Hash;
	string		pakname;
	resource_t	*pRes;
	char		md5[16];

	if( quiet ) HPAK_FlushHostQueue();

	// not an error - just flush queue
	if( !filename || !*filename )
		return true;

	Q_strncpy( pakname, filename, sizeof( pakname ));
	FS_StripExtension( pakname );
	FS_DefaultExtension( pakname, ".hpk" );

	f = FS_Open( pakname, "rb", false );
	if( !f )
	{
		MsgDev( D_INFO, "Couldn't find %s.\n", pakname );
		return true;
	}

	if( !quiet ) MsgDev( D_INFO, "Validating %s\n", pakname );

	FS_Read( f, &hdr, sizeof( hdr ));
	if( hdr.ident != IDCUSTOMHEADER || hdr.version != IDCUSTOM_VERSION )
	{
		MsgDev( D_ERROR, "HPAK_ValidatePak: %s does not have a valid HPAK header.\n", pakname );
		FS_Close( f );
		return false;
	}

	FS_Seek( f, hdr.seek, SEEK_SET );
	FS_Read( f, &num_lumps, sizeof( num_lumps ));

	if( num_lumps < 1 || num_lumps > MAX_FILES_IN_WAD )
	{
		MsgDev( D_ERROR, "HPAK_ValidatePak: %s has too many lumps %u.\n", pakname, num_lumps );
		FS_Close( f );
		return false;
	}

	if( !quiet ) MsgDev( D_INFO, "# of Entries:  %i\n", num_lumps );

	dataDir = Z_Malloc( sizeof( hpak_dir_t ) * num_lumps );
	FS_Read( f, dataDir, sizeof( hpak_dir_t ) * num_lumps );

	if( !quiet ) MsgDev( D_INFO, "# Type Size FileName : MD5 Hash\n" );

	for( i = 0; i < num_lumps; i++ )
	{
		if( dataDir[i].size < 1 || dataDir[i].size > 131071 )
		{
			// odd max size
			MsgDev( D_ERROR, "HPAK_ValidatePak: lump %i has invalid size %s\n", i, Q_pretifymem( dataDir[i].size, 2 ));
			Mem_Free( dataDir );
			FS_Close(f);
			return false;
		}

		dataPak = Z_Malloc( dataDir[i].size );
		FS_Seek( f, dataDir[i].seek, SEEK_SET );
		FS_Read( f, dataPak, dataDir[i].size );

		Q_memset( &MD5_Hash, 0, sizeof( MD5Context_t ));
		MD5Init( &MD5_Hash );
		MD5Update( &MD5_Hash, dataPak, dataDir[i].size );
		MD5Final( md5, &MD5_Hash );

		pRes = &dataDir[i].DirectoryResource;

		MsgDev( D_INFO, "%i:      %s %s %s:   ", i, HPAK_TypeFromIndex( pRes->type ),
		Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName );  

		if( Q_memcmp( md5, pRes->rgucMD5_hash, 0x10 ))
		{
			if( quiet )
			{
				MsgDev( D_ERROR, "HPAK_ValidatePak: %s has invalid checksum.\n", pakname );
				Mem_Free( dataPak );
				Mem_Free( dataDir );
				FS_Close( f );
				return false;
			}
			else MsgDev( D_INFO, "failed\n" );
		}
		else
		{
			if( !quiet ) MsgDev( D_INFO, "OK\n" );
		}

		// at this point, it's passed our checks.
		Mem_Free( dataPak );
	}

	Mem_Free( dataDir );
	FS_Close( f );
	return true;
}
Example #13
0
void HPAK_AddLump( qboolean add_to_queue, const char *name, resource_t *DirEnt, byte *data, file_t *f )
{
	int		i, position, length;
	string		pakname1, pakname2;
	char		md5[16];
	MD5Context_t	MD5_Hash;
	hpak_container_t	hpak1, hpak2;
	file_t		*f1, *f2;
	hpak_dir_t	*dirs;
	byte		*temp;

	if( !name || !name[0] )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: NULL name\n" );
		return;
	}

	if( !DirEnt )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: invalid lump\n" );
		return;
	}

	if( data == NULL && f == NULL )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: missing lump data\n" );
		return;
	}

	if( DirEnt->nDownloadSize < 1024 || DirEnt->nDownloadSize > 131072 )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: invalid size %s\n", Q_pretifymem( DirEnt->nDownloadSize, 2 ));
		return;
	}

	// hash it
	Q_memset( &MD5_Hash, 0, sizeof( MD5Context_t ));
	MD5Init( &MD5_Hash );

	if( data == NULL )
	{
		// there are better ways
		position = FS_Tell( f );
		temp = Z_Malloc( DirEnt->nDownloadSize );
		FS_Read( f, temp, DirEnt->nDownloadSize );
		FS_Seek( f, position, SEEK_SET );

		MD5Update( &MD5_Hash, temp, DirEnt->nDownloadSize );
		Mem_Free( temp );
	}
	else
	{
		MD5Update( &MD5_Hash, data, DirEnt->nDownloadSize );
	}

	MD5Final( md5, &MD5_Hash );

	if( Q_memcmp( md5, DirEnt->rgucMD5_hash, 0x10 ))
	{
		MsgDev( D_ERROR, "HPAK_AddLump: bad checksum for %s. Ignored\n", DirEnt->szFileName );
		return;
	}

	if( add_to_queue )
	{
		HPAK_AddToQueue( name, DirEnt, data, f );
		return;
	}

	Q_strncpy( pakname1, name, sizeof( pakname1 ));
	FS_StripExtension( pakname1 );
	FS_DefaultExtension( pakname1, ".hpk" );

	f1 = FS_Open( pakname1, "rb", false );

	if( !f1 )
	{
		// create new pack
		HPAK_CreatePak( name, DirEnt, data, f );
		return;
	}

	Q_strncpy( pakname2, pakname1, sizeof( pakname2 ));
	FS_StripExtension( pakname2 );
	FS_DefaultExtension( pakname2, ".hp2" );

	f2 = FS_Open( pakname2, "w+b", false );

	if( !f2 )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: couldn't open %s.\n", pakname2 );
		FS_Close( f1 );
		return;
	}

	// load headers
	FS_Read( f1, &hash_pack_header, sizeof( hpak_header_t ));

	if( hash_pack_header.version != IDCUSTOM_VERSION )
	{
		// we don't check the HPAK bit for some reason.
		MsgDev( D_ERROR, "HPAK_AddLump: %s does not have a valid header.\n", pakname2 );
		FS_Close( f1 );
		FS_Close( f2 );
	}

	length = FS_FileLength( f1 );
	HPAK_FileCopy( f2, f1, length );

	FS_Seek( f1, hash_pack_header.seek, SEEK_SET );
	FS_Read( f1, &hpak1.count, sizeof( hpak1.count ));

	if( hpak1.count < 1 || hpak1.count > MAX_FILES_IN_WAD )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: %s contain too many lumps.\n", pakname1 );
		FS_Close( f1 );
		FS_Close( f2 );
		return;
	}

	// load the data
	hpak1.dirs = Z_Malloc( sizeof( hpak_dir_t ) * hpak1.count );
	FS_Read( f1, hpak1.dirs, sizeof( hpak_dir_t ) * hpak1.count );
	FS_Close( f1 );

	if( HPAK_FindResource( &hpak1, DirEnt->rgucMD5_hash, NULL ))
	{
		Mem_Free( hpak1.dirs );
		FS_Close( f2 );
	}

	// make a new container
	hpak2.count = hpak1.count;
	hpak2.dirs = Z_Malloc( sizeof( hpak_dir_t ) * hpak2.count );
	Q_memcpy( hpak2.dirs, hpak1.dirs, hpak1.count );

	for( i = 0, dirs = NULL; i < hpak1.count; i++ )
	{
		if( Q_memcmp( hpak1.dirs[i].DirectoryResource.rgucMD5_hash, DirEnt->rgucMD5_hash, 16 ) < 0 )
		{
			dirs = &hpak1.dirs[i];
			while( i < hpak1.count )
			{
				hpak2.dirs[i+1] = hpak1.dirs[i];
				i++;
			}
			break;
		}
	}

	if( dirs == NULL ) dirs = &hpak2.dirs[hpak2.count-1];

	Q_memset( dirs, 0, sizeof( hpak_dir_t ));
	FS_Seek( f2, hash_pack_header.seek, SEEK_SET );
	dirs->DirectoryResource = *DirEnt;
	dirs->seek = FS_Tell( f2 );
	dirs->size = DirEnt->nDownloadSize;

	if( !data ) HPAK_FileCopy( f2, f, dirs->size );
	else FS_Write( f2, data, dirs->size );

	hash_pack_header.seek = FS_Tell( f2 );
	FS_Write( f2, &hpak2.count, sizeof( hpak2.count ));

	for( i = 0; i < hpak2.count; i++ )
	{
		FS_Write( f2, &hpak2.dirs[i], sizeof( hpak_dir_t ));
	}

	// finalize
	Mem_Free( hpak1.dirs );
	Mem_Free( hpak2.dirs );

	FS_Seek( f2, 0, SEEK_SET );
	FS_Write( f2, &hash_pack_header, sizeof( hpak_header_t ));
	FS_Close( f2 );

	FS_Delete( pakname1 );
	FS_Rename( pakname2, pakname1 );
}