mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-23 22:56:50 +00:00
933 lines
22 KiB
C++
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;
|
|
} |