source-engine/utils/xbox/makexvcd/makexvcd.cpp
FluorescentCIAAfricanAmerican 3bf9df6b27 1
2020-04-22 12:56:21 -04:00

933 lines
22 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: vcd_sound_check.cpp : Defines the entry point for the console application.
//
//=============================================================================//
#include <stdio.h>
#include <windows.h>
#include "tier0/dbg.h"
#include "tier1/utldict.h"
#include "filesystem.h"
#include "FileSystem_Tools.h"
#include "tier1/KeyValues.h"
#include "cmdlib.h"
#include "scriplib.h"
#include "vstdlib/random.h"
#include "choreoscene.h"
#include "choreoevent.h"
#include "iscenetokenprocessor.h"
#include "tier1/utlbuffer.h"
#include "tier1/checksum_crc.h"
#include "pacifier.h"
#include "SceneCache.h"
#include "SoundEmitterSystem/isoundemittersystembase.h"
#include "ModelSoundsCache.h"
#include "Datacache/imdlcache.h"
#include "datacache/idatacache.h"
#include "studio.h"
#include "appframework/appframework.h"
#include "tier0/icommandline.h"
#include "istudiorender.h"
#include "materialsystem/imaterialsystem.h"
#include "vphysics_interface.h"
#include "icvar.h"
#include "vstdlib/cvar.h"
#include "eventlist.h"
// #define TESTING 1
bool uselogfile = false;
bool modelsoundscache = false;
bool scenecache = false;
bool virtualmodel = false;
bool buildxcds = false;
struct AnalysisData
{
CUtlSymbolTable symbols;
};
static AnalysisData g_Analysis;
static char g_szCurrentGameDir[ 512 ];
IFileSystem *filesystem = NULL;
IMDLCache *g_pMDLCache = NULL;
ISoundEmitterSystemBase *soundemitterbase = NULL;
static CUniformRandomStream g_Random;
IUniformRandomStream *random = &g_Random;
static bool spewed = false;
static CUtlCachedFileData< CSceneCache > g_SceneCache( "scene.cache", SCENECACHE_VERSION, 0, UTL_CACHED_FILE_USE_FILESIZE );
static CUtlCachedFileData< CModelSoundsCache > g_ModelSoundsCache( "modelsounds.cache", MODELSOUNDSCACHE_VERSION, 0, UTL_CACHED_FILE_USE_FILESIZE );
//-----------------------------------------------------------------------------
// FIXME: This trashy glue code is really not acceptable. Figure out a way of making it unnecessary.
//-----------------------------------------------------------------------------
const studiohdr_t *studiohdr_t::FindModel( void **cache, char const *pModelName ) const
{
MDLHandle_t handle = g_pMDLCache->FindMDL( pModelName );
*cache = (void*)handle;
return g_pMDLCache->GetStudioHdr( handle );
}
virtualmodel_t *studiohdr_t::GetVirtualModel( void ) const
{
return g_pMDLCache->GetVirtualModel( (MDLHandle_t)virtualModel );
}
byte *studiohdr_t::GetAnimBlock( int i ) const
{
return g_pMDLCache->GetAnimBlock( (MDLHandle_t)virtualModel, i );
}
int studiohdr_t::GetAutoplayList( unsigned short **pOut ) const
{
return g_pMDLCache->GetAutoplayList( (MDLHandle_t)virtualModel, pOut );
}
const studiohdr_t *virtualgroup_t::GetStudioHdr( void ) const
{
return g_pMDLCache->GetStudioHdr( (MDLHandle_t)cache );
}
//-----------------------------------------------------------------------------
// Purpose: Helper for parsing scene data file
//-----------------------------------------------------------------------------
class CSceneTokenProcessor : public ISceneTokenProcessor
{
public:
const char *CurrentToken( void );
bool GetToken( bool crossline );
bool TokenAvailable( void );
void Error( const char *fmt, ... );
};
//-----------------------------------------------------------------------------
// Purpose:
// Output : const char
//-----------------------------------------------------------------------------
const char *CSceneTokenProcessor::CurrentToken( void )
{
return token;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : crossline -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CSceneTokenProcessor::GetToken( bool crossline )
{
return ::GetToken( crossline ) ? true : false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CSceneTokenProcessor::TokenAvailable( void )
{
return ::TokenAvailable() ? true : false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *fmt -
// ... -
//-----------------------------------------------------------------------------
void CSceneTokenProcessor::Error( const char *fmt, ... )
{
char string[ 2048 ];
va_list argptr;
va_start( argptr, fmt );
Q_vsnprintf( string, sizeof(string), fmt, argptr );
va_end( argptr );
Warning( "%s", string );
Assert(0);
}
static CSceneTokenProcessor g_TokenProcessor;
SpewRetval_t SpewFunc( SpewType_t type, char const *pMsg )
{
spewed = true;
printf( "%s", pMsg );
OutputDebugString( pMsg );
if ( type == SPEW_ERROR )
{
printf( "\n" );
OutputDebugString( "\n" );
}
return SPEW_CONTINUE;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : depth -
// *fmt -
// ... -
//-----------------------------------------------------------------------------
void vprint( int depth, const char *fmt, ... )
{
char string[ 8192 ];
va_list va;
va_start( va, fmt );
vsprintf( string, fmt, va );
va_end( va );
FILE *fp = NULL;
if ( uselogfile )
{
fp = fopen( "log.txt", "ab" );
}
while ( depth-- > 0 )
{
printf( " " );
OutputDebugString( " " );
if ( fp )
{
fprintf( fp, " " );
}
}
::printf( "%s", string );
OutputDebugString( string );
if ( fp )
{
char *p = string;
while ( *p )
{
if ( *p == '\n' )
{
fputc( '\r', fp );
}
fputc( *p, fp );
p++;
}
fclose( fp );
}
}
void logprint( char const *logfile, const char *fmt, ... )
{
char string[ 8192 ];
va_list va;
va_start( va, fmt );
vsprintf( string, fmt, va );
va_end( va );
FILE *fp = NULL;
static bool first = true;
if ( first )
{
first = false;
fp = fopen( logfile, "wb" );
}
else
{
fp = fopen( logfile, "ab" );
}
if ( fp )
{
char *p = string;
while ( *p )
{
if ( *p == '\n' )
{
fputc( '\r', fp );
}
fputc( *p, fp );
p++;
}
fclose( fp );
}
}
void Con_Printf( const char *fmt, ... )
{
va_list args;
static char output[1024];
va_start( args, fmt );
vprintf( fmt, args );
vsprintf( output, fmt, args );
vprint( 0, output );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void printusage( void )
{
vprint( 0, "usage: makexvcd [options] -game gamedir\n\
\t-v = verbose output\n\
\t-m = rebuild modelsounds.cache\n\
\t-x = rebuild .xcd files\n\
\t-s = rebuild scene.cache\n\
\t-z = rebuild virtualmodel.cache (xbox only)\n\
\t-l = log to file log.txt\n\
\ne.g.: makexvcd -s -m -game episodic\n" );
// Exit app
exit( 1 );
}
void BuildFileList_R( CUtlVector< CUtlSymbol >& files, char const *dir, char const *extension )
{
WIN32_FIND_DATA wfd;
char directory[ 256 ];
char filename[ 256 ];
HANDLE ff;
Q_snprintf( directory, sizeof( directory ), "%s\\*.*", dir );
#if defined( TESTING )
if ( files.Count() > 100 )
return;
#endif
if ( ( ff = FindFirstFile( directory, &wfd ) ) == INVALID_HANDLE_VALUE )
return;
int extlen = strlen( extension );
do
{
#if defined( TESTING )
if ( files.Count() > 100 )
return;
#endif
if ( wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
if ( wfd.cFileName[ 0 ] == '.' )
continue;
// Recurse down directory
Q_snprintf( filename, sizeof( filename ), "%s\\%s", dir, wfd.cFileName );
BuildFileList_R( files, filename, extension );
}
else
{
int len = strlen( wfd.cFileName );
if ( len > extlen )
{
if ( !stricmp( &wfd.cFileName[ len - extlen ], extension ) )
{
char filename[ MAX_PATH ];
Q_snprintf( filename, sizeof( filename ), "%s\\%s", dir, wfd.cFileName );
_strlwr( filename );
Q_FixSlashes( filename );
CUtlSymbol sym = g_Analysis.symbols.AddString( filename );
files.AddToTail( sym );
if ( !( files.Count() % 3000 ) )
{
vprint( 0, "...found %i .%s files\n", files.Count(), extension );
}
}
}
}
} while ( FindNextFile( ff, &wfd ) );
}
void BuildFileList( char const *basedir, CUtlVector< CUtlSymbol >& files, char const *rootdir, char const *extension )
{
files.RemoveAll();
char root[ 512 ];
Q_snprintf( root, sizeof( root ), "%s\\%s", basedir, rootdir );
BuildFileList_R( files, root, extension );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CheckLogFile( void )
{
if ( uselogfile )
{
_unlink( "log.txt" );
vprint( 0, " Outputting to log.txt\n" );
}
}
void PrintHeader()
{
vprint( 0, "Valve Software - CompileVCD.exe (%s)\n", __DATE__ );
vprint( 0, "--- Binary .vcd compiler ---\n" );
}
//-----------------------------------------------------------------------------
// Purpose: For each .wav file in the list, see if any vcd file in the list references it
// First build an index of .wav to .vcd mappings, then search wav list and print results
// Input : vcdfiles -
// wavfiles -
//-----------------------------------------------------------------------------
struct VCDList
{
VCDList()
{
}
VCDList( const VCDList& src )
{
int c = src.vcds.Count();
for ( int i = 0 ; i < c; i++ )
{
vcds.AddToTail( src.vcds[ i ] );
}
}
VCDList& operator =( const VCDList& src )
{
if ( this == &src )
return *this;
int c = src.vcds.Count();
for ( int i = 0 ; i < c; i++ )
{
vcds.AddToTail( src.vcds[ i ] );
}
return *this;
}
CUtlVector< CUtlSymbol > vcds;
};
void AppendDisposition( CUtlVector< CUtlSymbol >& disposition, char const *fmt, ... )
{
char string[ 2048 ];
va_list argptr;
va_start( argptr, fmt );
_vsnprintf( string, sizeof( string ), fmt, argptr );
va_end( argptr );
CUtlSymbol sym;
sym = string;
disposition.AddToTail( sym );
}
CChoreoScene *BlockingLoadScene( char const *vcdname )
{
// Load the .vcd
char scenefile[ MAX_PATH ];
Q_snprintf( scenefile, sizeof( scenefile ), "%s\\%s", g_szCurrentGameDir, vcdname );
LoadScriptFile( scenefile );
CChoreoScene *scene = ChoreoLoadScene( scenefile, NULL, &g_TokenProcessor, Con_Printf );
return scene;
}
void ProcessVCD( char const *vcdname, CUtlVector< CUtlSymbol >& disposition )
{
if ( verbose )
{
vprint( 0, "Processing '%s'\n", vcdname );
}
bool rebuild = false;
FileHandle_t fh = filesystem->Open( vcdname, "rb", "GAME" );
if ( fh == FILESYSTEM_INVALID_HANDLE )
{
Error( "Couldn't open '%s' for reading.", vcdname );
return;
}
size_t bufSize = filesystem->Size( fh );
char *buffer = new char[ bufSize + 1 ];
filesystem->Read( buffer, bufSize, fh );
filesystem->Close( fh );
buffer[ bufSize ] = 0;
CRC32_t crc;
CRC32_Init( &crc );
CRC32_ProcessBuffer( &crc, buffer, bufSize );
CRC32_Final( &crc );
delete[] buffer;
// Now load the file as a binary if it exists...
char binfile[ 512 ];
Q_strncpy( binfile, vcdname, sizeof( binfile ) );
Q_SetExtension( binfile, ".xcd", sizeof( binfile ) );
if ( buildxcds )
{
fh = filesystem->Open( binfile, "rb", "GAME" );
if ( fh == FILESYSTEM_INVALID_HANDLE )
{
AppendDisposition( disposition, "Built '%s'\n", binfile );
rebuild = true;
}
else
{
// Read the first bit of data and check
char crcdata[ 12 ];
filesystem->Read( crcdata, sizeof( crcdata ), fh );
filesystem->Close( fh );
CUtlBuffer buf;
buf.Put( crcdata, sizeof( crcdata ) );
CRC32_t fileCRC = 0;
if ( !CChoreoScene::GetCRCFromBuffer( buf, (unsigned int &)fileCRC ) )
{
AppendDisposition( disposition, "Rebuilt '%s' due to version change\n", binfile );
rebuild = true;
}
else
{
if ( fileCRC != crc )
{
AppendDisposition( disposition, "Rebuilt '%s' due to crc change\n", binfile );
rebuild = true;
}
}
}
}
// Validate the scene cache
g_SceneCache.RebuildItem( vcdname + strlen( g_szCurrentGameDir ) + 1 );
if ( !rebuild )
return;
// Remove current binary
if ( filesystem->FileExists( binfile, "GAME" ) )
{
_unlink( binfile );
}
// Load the .vcd
LoadScriptFile( (char *)vcdname );
CChoreoScene *scene = ChoreoLoadScene( vcdname, NULL, &g_TokenProcessor, Con_Printf );
if ( scene )
{
scene->SaveBinary( binfile, NULL, crc );
delete scene;
}
}
void CompileVCDs( CUtlVector< CUtlSymbol >& vcds )
{
CUtlVector< CUtlSymbol > disposition;
StartPacifier( "CompileVCDs" );
int i;
int c = vcds.Count();
for ( i = 0 ; i < c; ++i )
{
UpdatePacifier( (float)i / (float)c );
ProcessVCD( g_Analysis.symbols.String( vcds[ i ] ), disposition );
}
EndPacifier();
if ( verbose )
{
c = disposition.Count();
for ( i = 0; i < c; ++i )
{
Warning( "%s", disposition[ i ].String() );
}
}
}
static CUtlMap< CStudioHdr *, MDLHandle_t > g_ModelMap( 0, 0, DefLessFunc( CStudioHdr * ) );
CStudioHdr *ModelSoundsCache_LoadModel( char const *filename )
{
MDLHandle_t handle = g_pMDLCache->FindMDL( filename );
CStudioHdr *studioHdr = new CStudioHdr( g_pMDLCache->GetStudioHdr( handle ), g_pMDLCache );
g_ModelMap.Insert( studioHdr, handle );
if ( studioHdr->IsValid() )
return studioHdr;
return NULL;
}
void ModelSoundsCache_FinishModel( CStudioHdr *hdr )
{
int idx = g_ModelMap.Find( hdr );
if ( idx != g_ModelMap.InvalidIndex() )
{
g_pMDLCache->Release( g_ModelMap[ idx ] );
g_ModelMap.RemoveAt( idx );
}
delete hdr;
}
void ModelSoundsCache_PrecacheScriptSound( const char *soundname )
{
}
void ProcessMDL( char const *mdlname, CUtlVector< CUtlSymbol >& disposition )
{
if ( verbose )
{
vprint( 0, "Processing '%s'\n", mdlname );
}
if ( Q_stristr( mdlname, "ghostanim" ) )
{
int n =3 ;
}
// Validate the model sounds cache
g_ModelSoundsCache.RebuildItem( mdlname + strlen( g_szCurrentGameDir ) + 1 );
}
void CompileMDLs( CUtlVector< CUtlSymbol >& mdls )
{
CUtlVector< CUtlSymbol > disposition;
StartPacifier( "CompileMDLs" );
int i;
int c = mdls.Count();
for ( i = 0 ; i < c; ++i )
{
UpdatePacifier( (float)i / (float)c );
ProcessMDL( g_Analysis.symbols.String( mdls[ i ] ), disposition );
}
EndPacifier();
c = disposition.Count();
for ( i = 0; i < c; ++i )
{
Warning( "%s", disposition[ i ].String() );
}
}
//-----------------------------------------------------------------------------
// The application object
//-----------------------------------------------------------------------------
class CMakeCachesApp : public CSteamAppSystemGroup
{
public:
// Methods of IApplication
virtual bool Create();
virtual bool PreInit();
virtual int Main();
virtual void PostShutdown();
virtual void Destroy();
private:
// Sets up the search paths
bool SetupSearchPaths();
};
bool CMakeCachesApp::Create()
{
SpewOutputFunc( SpewFunc );
SpewActivate( "makexvcd", 2 );
// Add in the cvar factory
AppModule_t cvarModule = LoadModule( VStdLib_GetICVarFactory() );
AddSystem( cvarModule, VENGINE_CVAR_INTERFACE_VERSION );
AppSystemInfo_t appSystems[] =
{
{ "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION },
{ "studiorender.dll", STUDIO_RENDER_INTERFACE_VERSION },
{ "vphysics.dll", VPHYSICS_INTERFACE_VERSION },
{ "datacache.dll", DATACACHE_INTERFACE_VERSION },
{ "datacache.dll", MDLCACHE_INTERFACE_VERSION },
{ "datacache.dll", STUDIO_DATA_CACHE_INTERFACE_VERSION },
{ "soundemittersystem.dll", SOUNDEMITTERSYSTEM_INTERFACE_VERSION },
{ "", "" } // Required to terminate the list
};
if ( !AddSystems( appSystems ) )
return false;
g_pFileSystem = filesystem = (IFileSystem*)FindSystem( FILESYSTEM_INTERFACE_VERSION );
g_pMDLCache = (IMDLCache*)FindSystem( MDLCACHE_INTERFACE_VERSION );
soundemitterbase = (ISoundEmitterSystemBase*)FindSystem(SOUNDEMITTERSYSTEM_INTERFACE_VERSION);
g_pMaterialSystem = (IMaterialSystem*)FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION );
if ( !soundemitterbase || !g_pMDLCache || !filesystem || !g_pMaterialSystem )
{
Error("Unable to load required library interface!\n");
}
g_pMaterialSystem->SetShaderAPI( "shaderapiempty.dll" );
return true;
}
void CMakeCachesApp::Destroy()
{
g_pFileSystem = filesystem = NULL;
soundemitterbase = NULL;
g_pMDLCache = NULL;
}
//-----------------------------------------------------------------------------
// Sets up the game path
//-----------------------------------------------------------------------------
bool CMakeCachesApp::SetupSearchPaths()
{
CFSSteamSetupInfo steamInfo;
steamInfo.m_pDirectoryName = NULL;
steamInfo.m_bOnlyUseDirectoryName = false;
steamInfo.m_bToolsMode = true;
steamInfo.m_bSetSteamDLLPath = true;
steamInfo.m_bSteam = filesystem->IsSteam();
if ( FileSystem_SetupSteamEnvironment( steamInfo ) != FS_OK )
return false;
CFSMountContentInfo fsInfo;
fsInfo.m_pFileSystem = filesystem;
fsInfo.m_bToolsMode = true;
fsInfo.m_pDirectoryName = steamInfo.m_GameInfoPath;
if ( FileSystem_MountContent( fsInfo ) != FS_OK )
return false;
// Finally, load the search paths for the "GAME" path.
CFSSearchPathsInit searchPathsInit;
searchPathsInit.m_pDirectoryName = steamInfo.m_GameInfoPath;
searchPathsInit.m_pFileSystem = fsInfo.m_pFileSystem;
if ( FileSystem_LoadSearchPaths( searchPathsInit ) != FS_OK )
return false;
char platform[MAX_PATH];
Q_strncpy( platform, steamInfo.m_GameInfoPath, MAX_PATH );
Q_StripTrailingSlash( platform );
Q_strncat( platform, "/../platform", MAX_PATH, MAX_PATH );
fsInfo.m_pFileSystem->AddSearchPath( platform, "PLATFORM" );
// Set gamedir.
Q_MakeAbsolutePath( gamedir, sizeof( gamedir ), steamInfo.m_GameInfoPath );
Q_AppendSlash( gamedir, sizeof( gamedir ) );
return true;
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CMakeCachesApp::PreInit( )
{
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
filesystem->SetWarningFunc( Warning );
// Add paths...
if ( !SetupSearchPaths() )
return false;
return true;
}
void CMakeCachesApp::PostShutdown()
{
}
//-----------------------------------------------------------------------------
// main application
//-----------------------------------------------------------------------------
int CMakeCachesApp::Main()
{
for ( int i=1 ; i<CommandLine()->ParmCount() ; i++)
{
if ( CommandLine()->GetParm( i )[ 0 ] == '-' )
{
switch( CommandLine()->GetParm( i )[ 1 ] )
{
case 'l':
uselogfile = true;
break;
case 'v':
verbose = true;
break;
case 'g': // -game
++i;
break;
case 'm':
modelsoundscache = true;
break;
case 's':
scenecache = true;
break;
case 'x':
buildxcds = true;
break;
case 'z':
virtualmodel = true;
break;
default:
printusage();
break;
}
}
}
if ( CommandLine()->ParmCount() < 2 || ( i != CommandLine()->ParmCount() ) )
{
PrintHeader();
printusage();
}
CheckLogFile();
PrintHeader();
vprint( 0, " Compiling binary .vcd files to .xvcd ...\n" );
char vcddir[ 256 ];
char modelsdir[ 256 ];
Q_snprintf( vcddir, sizeof( vcddir ), "scenes", CommandLine()->GetParm( i - 1 ) );
Q_snprintf( modelsdir, sizeof( modelsdir ), "models", CommandLine()->GetParm( i - 1 ) );
if ( !strstr( vcddir, "scenes" ) )
{
vprint( 0, ".vcd dir %s looks invalid (format: u:/game/hl2/scenes)\n", vcddir );
return 0;
}
if ( !strstr( modelsdir, "models" ) )
{
vprint( 0, ".mdl dir %s looks invalid (format: u:/game/hl2/models)\n", modelsdir );
return 0;
}
char binaries[MAX_PATH];
Q_strncpy( binaries, gamedir, MAX_PATH );
Q_StripTrailingSlash( binaries );
Q_strncat( binaries, "/../bin", MAX_PATH, MAX_PATH );
filesystem->AddSearchPath( binaries, "EXECUTABLE_PATH");
soundemitterbase->ModInit();
// Delete the scene cache file
if ( scenecache ) filesystem->RemoveFile( "scene.cache", "MOD" );
if ( modelsoundscache ) filesystem->RemoveFile( "modelsounds.cache", "MOD" );
if ( virtualmodel ) filesystem->RemoveFile( "virtualmodel.cache", "MOD" );
CUtlSymbolTable pathStrings;
CUtlVector< CUtlSymbol > searchList;
char searchPaths[ 512 ];
filesystem->GetSearchPath( "GAME", true, searchPaths, sizeof( searchPaths ) );
// We want to walk them in reverse order so newer files are "overrides" for older ones, so we add them to a list in reverse order
for ( char *path = strtok( searchPaths, ";" ); path; path = strtok( NULL, ";" ) )
{
char dir[ 512 ];
Q_strncpy( dir, path, sizeof( dir ) );
Q_FixSlashes( dir );
Q_strlower( dir );
Q_StripTrailingSlash( dir );
CUtlSymbol sym = pathStrings.AddString( dir );
// Push them on head so we can walk them in reverse order
searchList.AddToHead( sym );
}
if ( scenecache )
{
g_SceneCache.Init();
}
if ( modelsoundscache )
{
g_ModelSoundsCache.Init();
g_pMDLCache->InitPreloadData( true );
}
EventList_RegisterSharedEvents();
for ( int sp = 0; sp < searchList.Count(); ++sp )
{
char const *basedir = pathStrings.String( searchList[ sp ] );
Q_strncpy( g_szCurrentGameDir, basedir, sizeof( g_szCurrentGameDir ) );
vprint( 0, "Processing gamedir %s\n", basedir );
if ( scenecache )
{
vprint( 1, "Building list of .vcd files\n" );
CUtlVector< CUtlSymbol > vcdfiles;
BuildFileList( basedir, vcdfiles, vcddir, ".vcd" );
vprint( 1, "found %i .vcd files\n", vcdfiles.Count() );
CompileVCDs( vcdfiles );
}
if ( modelsoundscache )
{
vprint( 1, "Building list of .mdl files\n" );
CUtlVector< CUtlSymbol > mdlfiles;
BuildFileList( basedir, mdlfiles, modelsdir, ".mdl" );
vprint( 1, "found %i .mdl files\n", mdlfiles.Count() );
CompileMDLs( mdlfiles );
}
}
if ( scenecache )
{
if ( g_SceneCache.IsDirty() )
{
g_SceneCache.Save();
}
g_SceneCache.Shutdown();
}
if ( modelsoundscache )
{
if ( g_ModelSoundsCache.IsDirty() )
{
g_ModelSoundsCache.Save();
}
g_ModelSoundsCache.Shutdown();
g_pMDLCache->ShutdownPreloadData();
}
soundemitterbase->ModShutdown();
return 0;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : argc -
// argv[] -
// Output : int
//-----------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
CommandLine()->CreateCmdLine( argc, argv );
CMakeCachesApp sceneManagerApp;
CSteamApplication steamApplication( &sceneManagerApp );
int nRetVal = steamApplication.Run();
return nRetVal;
}