Esempio n. 1
0
void CUtlString::FixSlashes( char cSeparator/*=CORRECT_PATH_SEPARATOR*/ )
{
	if ( m_pString )
	{
		V_FixSlashes( m_pString, cSeparator );
	}
}
Esempio n. 2
0
//-----------------------------------------------------------------------------
// Purpose: Composes a path and filename together, inserting a path separator
//			if need be
// Input:	path - path to use
//			filename - filename to use
//			dest - buffer to compose result in
//			destSize - size of destination buffer
//-----------------------------------------------------------------------------
void V_ComposeFileName( const char *path, const char *filename, char *dest, int destSize )
{
	V_strncpy( dest, path, destSize );
	V_AppendSlash( dest, destSize );
	V_strncat( dest, filename, destSize, COPY_ALL_CHARACTERS );
	V_FixSlashes( dest );
}
//-----------------------------------------------------------------------------
// Remove entry from dictionary, Returns TRUE if removed.
//-----------------------------------------------------------------------------
bool RemoveFileFromResourceList( const char *pFilename, CUtlRBTree< CUtlString, int > *pTree )
{
	char szOutName[MAX_PATH];
	char *pOutName;
	V_strncpy( szOutName, pFilename, sizeof( szOutName ) );
	V_FixSlashes( szOutName );
	V_RemoveDotSlashes( szOutName );
	V_strlower( szOutName );
	pOutName = szOutName;

	// strip any prefixed game name
	for ( int i = 0; g_GameNames[i] != NULL; i++ )
	{
		size_t len = strlen( g_GameNames[i] );
		if ( !V_strnicmp( pOutName, g_GameNames[i], len ) && pOutName[len] == '\\' )
		{
			// skip past game name and slash
			pOutName += len+1;
			break;
		}
	}

	if ( pTree->Find( pOutName ) != pTree->InvalidIndex() )
	{
		pTree->Remove( pOutName );
		return true;
	}

	return false;
}
Esempio n. 4
0
//-----------------------------------------------------------------------------
// Fixes up a file name, removing dot slashes, fixing slashes, converting to lowercase, etc.
//-----------------------------------------------------------------------------
void V_FixupPathName( char *pOut, size_t nOutLen, const char *pPath )
{
	V_strncpy( pOut, pPath, nOutLen );
	V_FixSlashes( pOut );
	V_RemoveDotSlashes( pOut );
	V_FixDoubleSlashes( pOut );
	V_strlower( pOut );
}
Esempio n. 5
0
static int sourceop_fullpathtodatadir(lua_State *L)
{
    char path[1024];

    V_snprintf(path, sizeof(path), "%s/%s", pAdminOP.GameDir(), pAdminOP.DataDir());
    V_FixSlashes(path);
    lua_pushstring(L, path);
    return 1;
}
Esempio n. 6
0
//---------------------------------------------------------------------------------
// Adds a path to sys.path (relative to g_GamePaths.GetSPDir()).
//---------------------------------------------------------------------------------
void AddToSysPath( const char* path )
{
	char szFolderPath[MAX_GAME_PATH];
	V_snprintf(szFolderPath, MAX_GAME_PATH, "%s%s", g_GamePaths.GetSPDir(), path);
	V_FixSlashes(szFolderPath);

	DevMsg(1, "[SP] Adding %s to path\n", szFolderPath);
	std::string szCommandString = "sys.path.append(r\"" + std::string(szFolderPath) + "\")";
	PyRun_SimpleString(szCommandString.c_str());
}
Esempio n. 7
0
//---------------------------------------------------------------------------------
// Adds a path to sys.path (relative to GetSourcePythonDir()).
//---------------------------------------------------------------------------------
void AddToSysPath( const char* path )
{
	char szFolderPath[MAX_PATH_LENGTH];
	V_snprintf(szFolderPath, MAX_PATH_LENGTH, "%s%s", GetSourcePythonDir(), path);
	V_FixSlashes(szFolderPath);

	DevMsg(1, MSG_PREFIX "Adding %s to path\n", szFolderPath);
	std::string szCommandString = "sys.path.append(r\"" + std::string(szFolderPath) + "\")";
	PyRun_SimpleString(szCommandString.c_str());
}
static void FileSystem_AddLoadedSearchPath( 
	CFSSearchPathsInit &initInfo, 
	const char *pPathID, 
	bool *bFirstGamePath, 
	const char *pBaseDir, 
	const char *pLocation,
	bool bLowViolence )
{
	char fullLocationPath[MAX_PATH];
	Q_MakeAbsolutePath( fullLocationPath, sizeof( fullLocationPath ), pLocation, pBaseDir );

	// Now resolve any ./'s.
	V_FixSlashes( fullLocationPath );
	if ( !V_RemoveDotSlashes( fullLocationPath ) )
		Error( "FileSystem_AddLoadedSearchPath - Can't resolve pathname for '%s'", fullLocationPath );
	
	// Add language, mod, and gamebin search paths automatically.
	if ( Q_stricmp( pPathID, "game" ) == 0 )
	{
		// add the low violence path
		if ( bLowViolence )
		{
			char szPath[MAX_PATH];
			Q_snprintf( szPath, sizeof(szPath), "%s_lv", fullLocationPath );
			initInfo.m_pFileSystem->AddSearchPath( szPath, pPathID, PATH_ADD_TO_TAIL );
		}
		
		// add the language path
		if ( initInfo.m_pLanguage )
		{
			AddLanguageGameDir( initInfo.m_pFileSystem, fullLocationPath, initInfo.m_pLanguage );
		}

		if ( CommandLine()->FindParm( "-tempcontent" ) != 0 )
		{
			char szPath[MAX_PATH];
			Q_snprintf( szPath, sizeof(szPath), "%s_tempcontent", fullLocationPath );
			initInfo.m_pFileSystem->AddSearchPath( szPath, pPathID, PATH_ADD_TO_TAIL );
		}

		// mark the first "game" dir as the "MOD" dir
		if ( *bFirstGamePath )
		{
			*bFirstGamePath = false;
			initInfo.m_pFileSystem->AddSearchPath( fullLocationPath, "MOD", PATH_ADD_TO_TAIL );
			Q_strncpy( initInfo.m_ModPath, fullLocationPath, sizeof( initInfo.m_ModPath ) );
		}
	
		// add the game bin
		AddGameBinDir( initInfo.m_pFileSystem, fullLocationPath );
	}

	initInfo.m_pFileSystem->AddSearchPath( fullLocationPath, pPathID, PATH_ADD_TO_TAIL );
}
bool FileSystem_IsHldsUpdateToolDedicatedServer()
{
	// To determine this, we see if the directory our executable was launched from is "orangebox".
	// We only are under "orangebox" if we're run from hldsupdatetool.
	char baseDir[MAX_PATH];
	if ( !FileSystem_GetBaseDir( baseDir, sizeof( baseDir ) ) )
		return false;

	V_FixSlashes( baseDir );
	V_StripTrailingSlash( baseDir );
	const char *pLastDir = V_UnqualifiedFileName( baseDir );
	return ( pLastDir && V_stricmp( pLastDir, "orangebox" ) == 0 );
}
Esempio n. 10
0
static int lua_include(lua_State *L)
{
    char filepath[512];
    const char *script = lua_tostring(L, 1);

    if(strstr(script, "..") || strstr(script, ":") || strstr(script, "%") || script[0] == '\\' || script[0] == '/')
    {
        CAdminOP::ColorMsg(CONCOLOR_LUA_ERR, "invalid include path `%s'\n", script);
        return 0;
    }

    Q_snprintf(filepath, sizeof(filepath), "%s/%s", lastscriptpath, script);
    V_FixSlashes(filepath);

    return handle_script(L, filepath);
}
Esempio n. 11
0
static int file_write(lua_State *L)
{
    char filepath[512];
    const char *file = luaL_checkstring(L, 1);
    const char *str = luaL_checkstring(L, 2);

    Q_snprintf(filepath, sizeof(filepath), "%s/%s/%s", pAdminOP.GameDir(), pAdminOP.DataDir(), file);
    V_FixSlashes(filepath);

    FILE *fp = fopen(filepath, "wt");
    if(fp)
    {
        fputs(str, fp);
        fclose(fp);
    }
    return 0;
}
Esempio n. 12
0
bool DFIsAdminTutLocked( void )
{
    char gamedir[256];
    char filepath[512];
    FILE *fp;

    engine->GetGameDir(gamedir, sizeof(gamedir));

    Q_snprintf(filepath, sizeof(filepath), "%s/%s/admintut_lock.txt", gamedir, pAdminOP.DataDir());
    V_FixSlashes(filepath);
    fp = fopen(filepath, "rt");
    if(fp)
    {
        fclose(fp);
        return true;
    }
    return false;
}
FSReturnCode_t FileSystem_LoadSearchPaths( CFSSearchPathsInit &initInfo )
{
	if ( !initInfo.m_pFileSystem || !initInfo.m_pDirectoryName )
		return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_LoadSearchPaths: Invalid parameters specified." );

	KeyValues *pMainFile, *pFileSystemInfo, *pSearchPaths;
	FSReturnCode_t retVal = LoadGameInfoFile( initInfo.m_pDirectoryName, pMainFile, pFileSystemInfo, pSearchPaths );
	if ( retVal != FS_OK )
		return retVal;
	
	// All paths except those marked with |gameinfo_path| are relative to the base dir.
	char baseDir[MAX_PATH];
	if ( !FileSystem_GetBaseDir( baseDir, sizeof( baseDir ) ) )
		return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetBaseDir failed." );

	// The MOD directory is always the one that contains gameinfo.txt
	Q_strncpy( initInfo.m_ModPath, initInfo.m_pDirectoryName, sizeof( initInfo.m_ModPath ) );

	#define GAMEINFOPATH_TOKEN		"|gameinfo_path|"
	#define BASESOURCEPATHS_TOKEN	"|all_source_engine_paths|"

	const char *pszExtraSearchPath = CommandLine()->ParmValue( "-insert_search_path" );
	if ( pszExtraSearchPath )
	{
		CUtlStringList vecPaths;
		V_SplitString( pszExtraSearchPath, ",", vecPaths );
		FOR_EACH_VEC( vecPaths, idxExtraPath )
		{
			char szAbsSearchPath[MAX_PATH];
			Q_StripPrecedingAndTrailingWhitespace( vecPaths[ idxExtraPath ] );
			V_MakeAbsolutePath( szAbsSearchPath, sizeof( szAbsSearchPath ), vecPaths[ idxExtraPath ], baseDir );
			V_FixSlashes( szAbsSearchPath );
			if ( !V_RemoveDotSlashes( szAbsSearchPath ) )
				Error( "Bad -insert_search_path - Can't resolve pathname for '%s'", szAbsSearchPath );
			V_StripTrailingSlash( szAbsSearchPath );
			FileSystem_AddLoadedSearchPath( initInfo, "GAME", szAbsSearchPath, false );
			FileSystem_AddLoadedSearchPath( initInfo, "MOD", szAbsSearchPath, false );
		}
	}
//-----------------------------------------------------------------------------
//	ExcludePathsDlg_Setup
//
//-----------------------------------------------------------------------------
void ExcludePathsDlg_Setup( HWND hWnd )
{
	TreeView_SetBkColor( GetDlgItem( hWnd, IDC_PATHS_TREE ), g_backgroundColor );

	CheckDlgButton( hWnd, IDC_PATHS_LINKGAMEDIRS, g_bLinkGameDirs ? BST_CHECKED : BST_UNCHECKED );

	// read the exisiting exclude paths
	g_ExcludePaths.Purge();
	char szFilename[MAX_PATH];
	V_ComposeFileName( g_localPath, EXCLUDEPATHS_FILE, szFilename, sizeof( szFilename ) );
	if ( Sys_Exists( szFilename ) )
	{
		Sys_LoadScriptFile( szFilename );
		while ( 1 ) 
		{
			char *pToken = Sys_GetToken( true );
			if ( !pToken || !pToken[0] )
			{
				break;
			}
			Sys_StripQuotesFromToken( pToken );
			if ( !stricmp( pToken, "*" ) )
			{
				pToken = "";
			}
			else if ( pToken[0] == '\\' )
			{
				pToken++;
			}
		
			char szPath[MAX_PATH];
			V_ComposeFileName( ROOT_NAME, pToken, szPath, sizeof( szPath ) );
			V_FixSlashes( szPath );

			g_ExcludePaths.AddToTail( szPath );
		}
	}
}
Esempio n. 15
0
//-----------------------------------------------------------------------------
// Purpose: Strip off the last directory from dirName
// Input  : *dirName - 
//			maxlen - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool V_StripLastDir( char *dirName, int maxlen )
{
	if( dirName[0] == 0 || 
		!V_stricmp( dirName, "./" ) || 
		!V_stricmp( dirName, ".\\" ) )
		return false;
	
	int len = V_strlen( dirName );

	Assert( len < maxlen );

	// skip trailing slash
	if ( PATHSEPARATOR( dirName[len-1] ) )
	{
		len--;
	}

	while ( len > 0 )
	{
		if ( PATHSEPARATOR( dirName[len-1] ) )
		{
			dirName[len] = 0;
			V_FixSlashes( dirName, CORRECT_PATH_SEPARATOR );
			return true;
		}
		len--;
	}

	// Allow it to return an empty string and true. This can happen if something like "tf2/" is passed in.
	// The correct behavior is to strip off the last directory ("tf2") and return true.
	if( len == 0 )
	{
		V_snprintf( dirName, maxlen, ".%c", CORRECT_PATH_SEPARATOR );
		return true;
	}

	return true;
}
Esempio n. 16
0
static int file_read(lua_State *L)
{
    char buf[4096];
    char filepath[512];
    const char *file = luaL_checkstring(L, 1);

    Q_snprintf(filepath, sizeof(filepath), "%s/%s/%s", pAdminOP.GameDir(), pAdminOP.DataDir(), file);
    V_FixSlashes(filepath);

    FILE *fp = fopen(filepath, "rt");
    if(fp)
    {
        int top = lua_gettop(L);
        int pushes = 0;
        int len;

        while(!feof(fp))
        {
            if(len = fread(buf, 1, sizeof(buf), fp))
            {
                luaL_checkstack(L, 1, "file read");
                lua_pushlstring(L, buf, len);
                pushes++;
            }
        }
        fclose(fp);

        if(pushes)
        {
            lua_concat(L, pushes);
            return 1;
        }
    }

    lua_pushstring(L, "");
    return 1;
}
Esempio n. 17
0
void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char *pStartingDir )
{
	if ( V_IsAbsolutePath( pPath ) )
	{
		// pPath is not relative.. just copy it.
		V_strncpy( pOut, pPath, outLen );
	}
	else
	{
		// Make sure the starting directory is absolute..
		if ( pStartingDir && V_IsAbsolutePath( pStartingDir ) )
		{
			V_strncpy( pOut, pStartingDir, outLen );
		}
		else
		{
			if ( !_getcwd( pOut, outLen ) )
				Error( "V_MakeAbsolutePath: _getcwd failed." );

			if ( pStartingDir )
			{
				V_AppendSlash( pOut, outLen );
				V_strncat( pOut, pStartingDir, outLen, COPY_ALL_CHARACTERS );
			}
		}

		// Concatenate the paths.
		V_AppendSlash( pOut, outLen );
		V_strncat( pOut, pPath, outLen, COPY_ALL_CHARACTERS );
	}

	if ( !V_RemoveDotSlashes( pOut ) )
		Error( "V_MakeAbsolutePath: tried to \"..\" past the root." );

	V_FixSlashes( pOut );
}
Esempio n. 18
0
bool V_RemoveDotSlashes( char *pFilename, char separator )
{
	// Remove '//' or '\\'
	char *pIn = pFilename;
	char *pOut = pFilename;
	bool bPrevPathSep = false;
	while ( *pIn )
	{
		bool bIsPathSep = PATHSEPARATOR( *pIn );
		if ( !bIsPathSep || !bPrevPathSep )
		{
			*pOut++ = *pIn;
		}
		bPrevPathSep = bIsPathSep;
		++pIn;
	}
	*pOut = 0;

	// Get rid of "./"'s
	pIn = pFilename;
	pOut = pFilename;
	while ( *pIn )
	{
		// The logic on the second line is preventing it from screwing up "../"
		if ( pIn[0] == '.' && PATHSEPARATOR( pIn[1] ) &&
			(pIn == pFilename || pIn[-1] != '.') )
		{
			pIn += 2;
		}
		else
		{
			*pOut = *pIn;
			++pIn;
			++pOut;
		}
	}
	*pOut = 0;

	// Get rid of a trailing "/." (needless).
	int len = strlen( pFilename );
	if ( len > 2 && pFilename[len-1] == '.' && PATHSEPARATOR( pFilename[len-2] ) )
	{
		pFilename[len-2] = 0;
	}

	// Each time we encounter a "..", back up until we've read the previous directory name,
	// then get rid of it.
	pIn = pFilename;
	while ( *pIn )
	{
		if ( pIn[0] == '.' && 
			 pIn[1] == '.' && 
			 (pIn == pFilename || PATHSEPARATOR(pIn[-1])) &&	// Preceding character must be a slash.
			 (pIn[2] == 0 || PATHSEPARATOR(pIn[2])) )			// Following character must be a slash or the end of the string.
		{
			char *pEndOfDots = pIn + 2;
			char *pStart = pIn - 2;

			// Ok, now scan back for the path separator that starts the preceding directory.
			while ( 1 )
			{
				if ( pStart < pFilename )
					return false;

				if ( PATHSEPARATOR( *pStart ) )
					break;

				--pStart;
			}

			// Now slide the string down to get rid of the previous directory and the ".."
			memmove( pStart, pEndOfDots, strlen( pEndOfDots ) + 1 );

			// Start over.
			pIn = pFilename;
		}
		else
		{
			++pIn;
		}
	}
	
	V_FixSlashes( pFilename, separator );	
	return true;
}
Esempio n. 19
0
//---------------------------------------------------------------------------------
// Initializes python.
//---------------------------------------------------------------------------------
bool CPythonManager::Initialize( void )
{
	// Construct a path to the python engine directory.
	char szPythonHome[MAX_PATH_LENGTH];
	V_snprintf(szPythonHome, MAX_PATH_LENGTH, "%s/Python3", GetSourcePythonDir());
	V_FixSlashes(szPythonHome);
	DevMsg(1, MSG_PREFIX "Python home path set to %s\n", szPythonHome);

	// Convert to wide char for python.
	wchar_t wszPythonHome[MAX_PATH_LENGTH];
	V_strtowcs(szPythonHome, -1, wszPythonHome, MAX_PATH_LENGTH);

	// Set that as the python home directory.
 	Py_SetPythonHome(wszPythonHome);
 	Py_SetProgramName(wszPythonHome);
	Py_SetPath(wszPythonHome);

	// Initialize python and its namespaces.
	Py_Initialize();

	// Print some information
	DevMsg(1, MSG_PREFIX "Python version %s initialized!\n", Py_GetVersion());
	
	// Set sys.argv and update sys.path
	DevMsg(1, MSG_PREFIX "Setting sys.argv...\n");
	ICommandLine* pCommandLine = CommandLine();

	int iParamCount = pCommandLine->ParmCount();
	wchar_t** argv = new wchar_t*[iParamCount];
	for (int i=0; i < iParamCount; i++)
	{
		const char* szParam = pCommandLine->GetParm(i);
		int iParamLength = strlen(szParam);

		wchar_t* wszParam = new wchar_t[iParamLength+1];
		// Not sure what's wrong with V_strtowcs, but it seems like it
		// doesn't convert the string correctly on Linux
		mbstowcs(wszParam, szParam, iParamLength+1);

		argv[i] = wszParam;
	}
	PySys_SetArgv(iParamCount, argv);

	// Make sure sys is imported.
	PyRun_SimpleString("import sys");

	// Add the Python API path.
	AddToSysPath("/packages/source-python");

	// Add operating system specific paths.
#if defined(WIN32)
	AddToSysPath("/Python3/plat-win");
#else
	AddToSysPath("/Python3/plat-linux");

	// We've got a bunch of linux shared objects here we need to load.
	AddToSysPath("/Python3/lib-dynload");
#endif

	// Site packages for any extra packages...
	AddToSysPath("/packages/site-packages");

	// Add the custom packages path.
	AddToSysPath("/packages/custom");

	// And of course, the plugins directory for script imports.
	AddToSysPath("/plugins");

	// Initialize all converters
	InitConverters();

	// Initialize all submodules
	if (!modulsp_init())
	{
		Msg(MSG_PREFIX "Failed to initialize internal modules.\n");
		return false;
	}

	// Import the main module file.
	DevMsg(1, MSG_PREFIX "Loading main module...\n");

	try {
		python::import("__init__").attr("load")();
	}
	catch( ... ) {
		PyErr_Print();
		PyErr_Clear();
		Msg(MSG_PREFIX "Failed to load the main module.\n");
		return false;
	}

	return true;
}
Esempio n. 20
0
//---------------------------------------------------------------------------------
// Initializes python.
//---------------------------------------------------------------------------------
bool CPythonManager::Initialize( void )
{
	// Construct a path to the python engine directory.
	char szPythonHome[MAX_GAME_PATH];
	V_snprintf(szPythonHome, MAX_GAME_PATH, "%s/Python3", g_GamePaths.GetSPDir());
	V_FixSlashes(szPythonHome);
	DevMsg(1, "[SP] Python home path set to %s\n", szPythonHome);

	// Convert to wide char for python.
	wchar_t wszPythonHome[1024];
	V_strtowcs(szPythonHome, -1, wszPythonHome, 1024);

	// Set that as the python home directory.
 	Py_SetPythonHome(wszPythonHome);
 	Py_SetProgramName(wszPythonHome);
	Py_SetPath(wszPythonHome);

	// Initialize python and its namespaces.
	Py_Initialize();

	// Print some information
	DevMsg(1, "Python version %s initialized!\n", Py_GetVersion());

	// Make sure sys is imported.
	PyRun_SimpleString("import sys");

	// Add the Python API path.
	AddToSysPath("/packages/source-python");

	// Add operating system specific paths.
#if defined(WIN32)
	AddToSysPath("/Python3/plat-win");
#else
	AddToSysPath("/Python3/plat-linux");

	// We've got a bunch of linux shared objects here we need to load.
	AddToSysPath("/Python3/lib-dynload");
#endif

	// Site packages for any extra packages...
	AddToSysPath("/packages/site-packages");

	// Add the custom packages path.
	AddToSysPath("/packages/custom");

	// And of course, the plugins directory for script imports.
	AddToSysPath("/plugins");

	// Initialize all converters
	InitConverters();

	// Initialize all submodules
	modulsp_init();

	// Import the main module file.
	DevMsg(1, "[SP] Importing main module..\n");
	BEGIN_BOOST_PY()

		python::import("__init__");

	END_BOOST_PY_NORET(); // Noret because we have more stuff to do after this import.

	DevMsg(0, "[Source.Python] Loaded successfully.\n");

	return true;
}
//-----------------------------------------------------------------------------
// Generate a tree containing files from a reslist.  Returns TRUE if successful.
//-----------------------------------------------------------------------------
bool LoadReslist( const char *pReslistName, CUtlRBTree< CUtlString, int > *pTree )
{
	CUtlBuffer buffer;
	if ( !scriptlib->ReadFileToBuffer( pReslistName, buffer, true ) )
	{
		return false;
	}

	char szBasename[MAX_PATH];
	V_FileBase( pReslistName, szBasename, sizeof( szBasename ) );

	characterset_t breakSet;
	CharacterSetBuild( &breakSet, "" );

	// parse reslist
	char szToken[MAX_PATH];
	char szBspName[MAX_PATH];
	szBspName[0] = '\0';
	for ( ;; )
	{
		int nTokenSize = buffer.ParseToken( &breakSet, szToken, sizeof( szToken ) );
		if ( nTokenSize <= 0 )
		{
			break;
		}

		// reslists are pc built, filenames can be sloppy
		V_strlower( szToken );
		V_FixSlashes( szToken );
		V_RemoveDotSlashes( szToken );

		// can safely cull filetypes that are ignored by queued loader at runtime
		bool bKeep = false;
		const char *pExt = V_GetFileExtension( szToken );
		if ( !pExt )
		{
			// unknown
			continue;
		}
		else if ( !V_stricmp( pExt, "vmt" ) || 
				!V_stricmp( pExt, "vhv" ) || 
				!V_stricmp( pExt, "mdl" ) || 
				!V_stricmp( pExt, "raw" ) || 
				!V_stricmp( pExt, "wav" ) )
		{
			bKeep = true;
		}
		else if ( !V_stricmp( pExt, "mp3" ) )
		{
			// change to .wav
			V_SetExtension( szToken, ".wav", sizeof( szToken ) );
			bKeep = true;
		}
		else if ( !V_stricmp( pExt, "bsp" ) )
		{
			// reslists erroneously have multiple bsps
			if ( !V_stristr( szToken, szBasename ) )
			{
				// wrong one, cull it
				continue;
			}
			else
			{
				// right one, save it
				strcpy( szBspName, szToken );
				bKeep = true;
			}
		}

		if ( bKeep )
		{
			FindOrAddFileToResourceList( szToken, pTree );
		}
	}

	if ( !szBspName[0] )
	{
		// reslist is not bsp derived, nothing more to do
		return true;
	}

	CUtlVector< CUtlString > bspList;
	bool bOK = GetDependants_BSP( szBspName, &bspList );
	if ( !bOK )
	{
		return false;
	}
	
	// add all the bsp dependants to the resource list
	for ( int i=0; i<bspList.Count(); i++ )
	{
		FindOrAddFileToResourceList( bspList[i].String(), pTree );
	}

	// iterate all the models in the resource list, get all their dependents
	CUtlVector< CUtlString > modelList;
	for ( int i = pTree->FirstInorder(); i != pTree->InvalidIndex(); i = pTree->NextInorder( i ) )
	{
		const char *pExt = V_GetFileExtension( pTree->Element( i ).String() );
		if ( !pExt || V_stricmp( pExt, "mdl" ) )
		{
			continue;
		}

		if ( !GetDependants_MDL( pTree->Element( i ).String(), &modelList ) )
		{
			return false;
		}
	}

	// add all the model dependents to the resource list
	for ( int i=0; i<modelList.Count(); i++ )
	{
		FindOrAddFileToResourceList( modelList[i].String(), pTree );
	}

	// check for optional commentary, include wav dependencies
	char szCommentaryName[MAX_PATH];
	V_ComposeFileName( g_szGamePath, szBspName, szCommentaryName, sizeof( szCommentaryName ) );
	V_StripExtension( szCommentaryName, szCommentaryName, sizeof( szCommentaryName ) );
	V_strncat( szCommentaryName, "_commentary.txt", sizeof( szCommentaryName ) );
	CUtlBuffer commentaryBuffer;
	if ( ReadFileToBuffer( szCommentaryName, commentaryBuffer, true, true ) )
	{
		// any single token may be quite large to due to text
		char szCommentaryToken[8192];
		for ( ;; )
		{
			int nTokenSize = commentaryBuffer.ParseToken( &breakSet, szCommentaryToken, sizeof( szCommentaryToken ) );
			if ( nTokenSize < 0 )
			{
				break;
			}
			if ( nTokenSize > 0 && !V_stricmp( szCommentaryToken, "commentaryfile" ) )
			{
				// get the commentary file
				nTokenSize = commentaryBuffer.ParseToken( &breakSet, szCommentaryToken, sizeof( szCommentaryToken ) );
				if ( nTokenSize > 0 )
				{
					// skip past sound chars
					char *pName = szCommentaryToken;
					while ( *pName && IsSoundChar( *pName ) )
					{
						pName++;
					}
					char szWavFile[MAX_PATH];
					V_snprintf( szWavFile, sizeof( szWavFile ), "sound/%s", pName );
					FindOrAddFileToResourceList( szWavFile, pTree );
				}
			}
		}
	}

	// check for optional blacklist
	char szBlacklist[MAX_PATH];
	V_ComposeFileName( g_szGamePath, "reslistfixes_xbox.xsc", szBlacklist, sizeof( szBlacklist ) );
	CUtlBuffer blacklistBuffer;
	if ( ReadFileToBuffer( szBlacklist, blacklistBuffer, true, true ) )
	{
		for ( ;; )
		{
			int nTokenSize = blacklistBuffer.ParseToken( &breakSet, szToken, sizeof( szToken ) );
			if ( nTokenSize <= 0 )
			{
				break;
			}

			bool bAdd;
			if ( !V_stricmp( szToken, "-" ) )
			{
				bAdd = false;
			}
			else if ( !V_stricmp( szToken, "+" ) )
			{
				bAdd = true;
			}
			else
			{
				// bad syntax, skip line
				Msg( "Bad Syntax, expecting '+' or '-' as first token in reslist fixup file '%s'.\n", szBlacklist );
				continue;
			}

			// get entry
			nTokenSize = blacklistBuffer.ParseToken( &breakSet, szToken, sizeof( szToken ) );
			if ( nTokenSize <= 0 )
			{
				break;
			}

			if ( bAdd )	
			{
				FindOrAddFileToResourceList( szToken, pTree );
			}
			else
			{
				RemoveFileFromResourceList( szToken, pTree );
			}
		}
	}

	return true;
}
static void FileSystem_AddLoadedSearchPath( 
	CFSSearchPathsInit &initInfo, 
	const char *pPathID, 
	bool *bFirstGamePath, 
	const char *pBaseDir, 
	const char *pLocation,
	bool bLowViolence )
{
	char fullLocationPath[MAX_PATH];
	Q_MakeAbsolutePath( fullLocationPath, sizeof( fullLocationPath ), pLocation, pBaseDir );

	// Now resolve any ./'s.
	V_FixSlashes( fullLocationPath );
	if ( !V_RemoveDotSlashes( fullLocationPath ) )
		Error( "FileSystem_AddLoadedSearchPath - Can't resolve pathname for '%s'", fullLocationPath );

	// Add language, mod, and gamebin search paths automatically.
	if ( Q_stricmp( pPathID, "game" ) == 0 )
	{
		bool bDoAllPaths = true;
#if defined( _X360 ) && defined( LEFT4DEAD )
		// hl2 is a vestigal mistake due to shaders, xbox needs to prevent any search path bloat
		if ( V_stristr( fullLocationPath, "\\hl2" ) )
		{
			bDoAllPaths = false;
		}
#endif

		// add the language path, needs to be topmost, generally only contains audio
		// and the language localized movies (there are 2 version one normal, one LV)
		// this trumps the LV english movie as desired for the language
		if ( initInfo.m_pLanguage && bDoAllPaths )
		{
			AddLanguageGameDir( initInfo.m_pFileSystem, fullLocationPath, initInfo.m_pLanguage );
		}

		// next add the low violence path
		if ( bLowViolence && bDoAllPaths )
		{
			char szPath[MAX_PATH];
			Q_snprintf( szPath, sizeof(szPath), "%s_lv", fullLocationPath );
			initInfo.m_pFileSystem->AddSearchPath( szPath, pPathID, PATH_ADD_TO_TAIL );
		}
		
		if ( CommandLine()->FindParm( "-tempcontent" ) != 0 && bDoAllPaths )
		{
			char szPath[MAX_PATH];
			Q_snprintf( szPath, sizeof(szPath), "%s_tempcontent", fullLocationPath );
			initInfo.m_pFileSystem->AddSearchPath( szPath, pPathID, PATH_ADD_TO_TAIL );
		}

		// mark the first "game" dir as the "MOD" dir
		if ( *bFirstGamePath )
		{
			*bFirstGamePath = false;
			initInfo.m_pFileSystem->AddSearchPath( fullLocationPath, "MOD", PATH_ADD_TO_TAIL );
			Q_strncpy( initInfo.m_ModPath, fullLocationPath, sizeof( initInfo.m_ModPath ) );
		}
	
		if ( bDoAllPaths )
		{
			// add the game bin
			AddGameBinDir( initInfo.m_pFileSystem, fullLocationPath );
		}
	}

	initInfo.m_pFileSystem->AddSearchPath( fullLocationPath, pPathID, PATH_ADD_TO_TAIL );
}
Esempio n. 23
0
void C_MountManager::Init()
{
	DevMsg("MountManager: Init\n");

	// Get all Steam library folders
	HKEY key;
	if (RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Valve\\Steam"), &key) == ERROR_SUCCESS)
	{
		char value[AA_MAX_STRING];
		DWORD value_length = AA_MAX_STRING;
		DWORD flags = REG_SZ;
		RegQueryValueEx(key, "SteamPath", NULL, &flags, (LPBYTE)&value, &value_length);
		RegCloseKey(key);

		V_FixSlashes(value);
		/*
		if (value[3] == '\\')
		{
			std::string buf = value;
			buf = buf.substr(0, 2) + buf.substr(3);
			Q_strcpy(value, buf.c_str());
		}
		*/

		// primary
		m_libraryPaths.push_back(VarArgs("%s\\SteamApps\\common\\", value));

		// primary mod
		//if (g_pFullFileSystem->FindFirstEx(VarArgs("%s\\SteamApps\\sourcemods", value), "", &pHandle))
		if (g_pFullFileSystem->IsDirectory(VarArgs("%s\\SteamApps\\sourcemods", value)))
			m_libraryPaths.push_back(VarArgs("%s\\SteamApps\\sourcemods\\", value));
		//g_pFullFileSystem->FindClose(pHandle);

		// load %value/config/config.vdf to find other library paths
		KeyValues* pConfigKV = new KeyValues("InstallConfigStore");
		//pConfigKV->UsesEscapeSequences(true);
		if (pConfigKV->LoadFromFile(g_pFullFileSystem, VarArgs("%s\\config\\config.vdf", value), ""))
		{
			// For now, try searching until a search path is not found.
			// However, search paths may not be sequential, there might be numbers missing.
			// If that turns out to be the case, just check for the 1st 100 paths or something.

			std::string buf;
			std::string base = "Software/Valve/Steam/BaseInstallFolder_";
			KeyValues* pKey = pConfigKV->FindKey(VarArgs("%s1", base.c_str()));
			for (int i = 2; pKey; i++)
			{
				buf = pKey->GetString();
				if (buf.at(3) == '\\')
					buf = buf.substr(0, 2) + buf.substr(3);

			//	DevMsg("here it found: %s\n", buf.c_str());
				m_libraryPaths.push_back(VarArgs("%s\\SteamApps\\common\\", buf.c_str()));

				if (g_pFullFileSystem->IsDirectory(VarArgs("%s\\SteamApps\\sourcemods", buf.c_str())))
					m_libraryPaths.push_back(VarArgs("%s\\SteamApps\\sourcemods\\", buf.c_str()));
				
				pKey = pConfigKV->FindKey(VarArgs("%s%i", base.c_str(), i));
			}
		}
		pConfigKV->deleteThis();
	}

	/*
	for (unsigned int i = 0; i < m_libraryPaths.size(); i++)
	{
		DevMsg("Path: %s\n", m_libraryPaths[i].c_str());
	}
	*/
}
Esempio n. 24
0
//----------------------------------------------------------------------
// Get list of files that a model requires.
//----------------------------------------------------------------------
bool GetDependants_MDL( const char *pModelName, CUtlVector< CUtlString > *pList )
{
	if ( !g_bModPathIsValid )
	{
		Msg( "Indeterminate mod path, Cannot perform BSP conversion\n" );
		return false;
	}

	CUtlBuffer sourceBuf;
	if ( !g_pFullFileSystem->ReadFile( pModelName, "GAME", sourceBuf ) )
	{
		Msg( "Error! Couldn't open file '%s'!\n", pModelName ); 
		return false;
	}

	studiohdr_t *pStudioHdr = (studiohdr_t *)sourceBuf.Base();
	Studio_ConvertStudioHdrToNewVersion( pStudioHdr );
	if ( pStudioHdr->version != STUDIO_VERSION )
	{
		Msg( "Error! Bad Model '%s', Expecting Version (%d), got (%d)\n", pModelName, STUDIO_VERSION, pStudioHdr->version ); 
		return false;
	}

	char szOutName[MAX_PATH];
	if ( pStudioHdr->flags & STUDIOHDR_FLAGS_OBSOLETE )
	{
		V_strncpy( szOutName, "materials/sprites/obsolete.vmt", sizeof( szOutName ) );
		V_FixSlashes( szOutName );
		pList->AddToTail( szOutName );
	}
	else if ( pStudioHdr->textureindex != 0 )
	{
		// iterate each texture
		int	i;
		int	j;
		for ( i = 0; i < pStudioHdr->numtextures; i++ )
		{
			// iterate through all directories until a valid material is found
			bool bFound = false;
			for ( j = 0; j < pStudioHdr->numcdtextures; j++ )
			{
				char szPath[MAX_PATH];
				V_ComposeFileName( "materials", pStudioHdr->pCdtexture( j ), szPath, sizeof( szPath ) );

				// should have been fixed in studiomdl
				// some mdls are ending up with double slashes, borking loads
				int len = strlen( szPath );
				if ( len > 2 && szPath[len-2] == '\\' && szPath[len-1] == '\\' )
				{
					szPath[len-1] = '\0';
				}
			
				V_ComposeFileName( szPath, pStudioHdr->pTexture( i )->pszName(), szOutName, sizeof( szOutName ) ); 
				V_SetExtension( szOutName, ".vmt", sizeof( szOutName ) );

				if ( g_pFullFileSystem->FileExists( szOutName, "GAME" ) )
				{
					bFound = true;
					break;
				}
			}

			if ( bFound )
			{
				pList->AddToTail( szOutName );
			}
		}
	}
	
	return true;
}
Esempio n. 25
0
//---------------------------------------------------------------------------------
// This function will load libraries and return true if they load successfully.
//
//---------------------------------------------------------------------------------
void* SPLoadLibrary( IVEngineServer* engine, const char* libraryPath )
{
	DevMsg(1, MSG_PREFIX "Loading library: %s\n", libraryPath);
	char szFullPath[MAX_PATH_LENGTH];
	char szGamePath[MAX_PATH_LENGTH];
	char szError[MAX_PATH_LENGTH];
	V_strncpy(szError, "[SP-LOADER] - No error found\n", MAX_PATH_LENGTH);

	engine->GetGameDir(szGamePath, MAX_PATH_LENGTH);
	GenerateSymlink(szGamePath);

	V_snprintf(szFullPath, sizeof(szFullPath), "%s/addons/source-python/%s",
		szGamePath, libraryPath);

	// Fix up the slahes.
	V_FixSlashes(szFullPath);

#if defined(_WIN32)
	void* hModule = (void *)LoadLibrary(szFullPath);
	if (!hModule)
	{
		// I hate windows programming...
		DWORD nErrorCode = GetLastError();
		LPVOID lpMsgBuf;
		DWORD nBufferLength = FormatMessage(
			FORMAT_MESSAGE_ALLOCATE_BUFFER |
			FORMAT_MESSAGE_FROM_SYSTEM |
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			nErrorCode,
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			(LPTSTR) &lpMsgBuf,
			0, NULL );

		if(nBufferLength == 0)

		{
			V_snprintf(szError, sizeof(szError),
			   "[SP-LOADER] Could not obtain a valid translation for error. (Code: %d)\n",
			   nErrorCode);
		}
		else
		{
			char szResult[MAX_ERROR_LENGTH];
			memset(szResult, '\0', MAX_ERROR_LENGTH);

			// Too lazy to bring across any windows functions, cast myself from wide to narrow
			for (unsigned int i=0; i < nBufferLength; ++i)
			{
				szResult[i] = static_cast<char>(static_cast<LPCSTR>(lpMsgBuf)[i]);
			}

			V_snprintf(szError, sizeof(szError),
			   "[SP-LOADER] (Code: %d) %s",
			   nErrorCode,
			   szResult/*.c_str()*/);

			LocalFree(lpMsgBuf);
		}
	}
#else
	void* hModule = (void *)dlopen(szFullPath, RTLD_NOW | RTLD_GLOBAL);
	if (!hModule)
	{
		V_snprintf(szError, sizeof(szError), "[SP-LOADER] Error Reported: %s\n",
			dlerror());
	}
#endif

	if( !hModule ) {
		Warning("=========================================================================\n");
		Warning("[SP-LOADER] Could not load library: %s\n", libraryPath);
		Warning(szError);
		Warning("=========================================================================\n");
		return hModule;
	}

	return hModule;
}
Esempio n. 26
0
//-----------------------------------------------------------------------------
// A Scene image file contains all the compiled .XCD
//-----------------------------------------------------------------------------
bool CSceneImage::CreateSceneImageFile( CUtlBuffer &targetBuffer, char const *pchModPath, bool bLittleEndian, bool bQuiet, ISceneCompileStatus *pStatus )
{
	CUtlVector<fileList_t>	vcdFileList;
	CUtlSymbolTable			vcdSymbolTable( 0, 32, true );

	Msg( "\n" );

	// get all the VCD files according to the seacrh paths
	char searchPaths[512];
	g_pFullFileSystem->GetSearchPath( "GAME", false, searchPaths, sizeof( searchPaths ) );
	char *pPath = strtok( searchPaths, ";" );
	while ( pPath )
	{
		int currentCount = vcdFileList.Count();

		char szPath[MAX_PATH];
		V_ComposeFileName( pPath, "scenes/*.vcd", szPath, sizeof( szPath ) );

		scriptlib->FindFiles( szPath, true, vcdFileList );

		Msg( "Scenes: Searching '%s' - Found %d scenes.\n", szPath, vcdFileList.Count() - currentCount );

		pPath = strtok( NULL, ";" );
	}

	if ( !vcdFileList.Count() )
	{
		Msg( "Scenes: No Scene Files found!\n" );
		return false;
	}

	// iterate and convert all the VCD files
	bool bGameIsTF = V_stristr( pchModPath, "\\tf" ) != NULL;
	for ( int i=0; i<vcdFileList.Count(); i++ )
	{
		const char *pFilename = vcdFileList[i].fileName.String();
		const char *pSceneName = V_stristr( pFilename, "scenes\\" );
		if ( !pSceneName )
		{
			continue;
		}

		if ( !bLittleEndian && bGameIsTF && V_stristr( pSceneName, "high\\" ) )
		{
			continue;
		}

		// process files in order they would be found in search paths
		// i.e. skipping later processed files that match an earlier conversion
		UtlSymId_t symbol = vcdSymbolTable.Find( pSceneName );
		if ( symbol == UTL_INVAL_SYMBOL )
		{
			vcdSymbolTable.AddString( pSceneName );

			pStatus->UpdateStatus( pFilename, bQuiet, i, vcdFileList.Count() );

			if ( !CreateTargetFile_VCD( pFilename, "", false, bLittleEndian ) )
			{
				Error( "CreateSceneImageFile: Failed on '%s' conversion!\n", pFilename );
			}


		}
	}

	if ( !g_SceneFiles.Count() )
	{
		// nothing to do
		return true;
	}

	Msg( "Scenes: Finalizing %d unique scenes.\n", g_SceneFiles.Count() );


	// get the string pool
	CUtlVector< unsigned int > stringOffsets;
	CUtlBuffer stringPool;
	g_ChoreoStringPool.GetTableAndPool( stringOffsets, stringPool );

	if ( !bQuiet )
	{
		Msg( "Scenes: String Table: %d bytes\n", stringOffsets.Count() * sizeof( int ) );
		Msg( "Scenes: String Pool: %d bytes\n", stringPool.TellMaxPut() );
	}

	// first header, then lookup table, then string pool blob
	int stringPoolStart = sizeof( SceneImageHeader_t ) + stringOffsets.Count() * sizeof( int );
	// then directory
	int sceneEntryStart = stringPoolStart + stringPool.TellMaxPut();
	// then variable sized summaries
	int sceneSummaryStart = sceneEntryStart + g_SceneFiles.Count() * sizeof( SceneImageEntry_t );
	// then variable sized compiled binary scene data
	int sceneDataStart = 0;

	// construct header
	SceneImageHeader_t imageHeader = { 0 };
	imageHeader.nId = SCENE_IMAGE_ID;
	imageHeader.nVersion = SCENE_IMAGE_VERSION;
	imageHeader.nNumScenes = g_SceneFiles.Count();
	imageHeader.nNumStrings = stringOffsets.Count();
	imageHeader.nSceneEntryOffset = sceneEntryStart;
	if ( !bLittleEndian )
	{
		imageHeader.nId = BigLong( imageHeader.nId );
		imageHeader.nVersion = BigLong( imageHeader.nVersion );
		imageHeader.nNumScenes = BigLong( imageHeader.nNumScenes );
		imageHeader.nNumStrings = BigLong( imageHeader.nNumStrings );
		imageHeader.nSceneEntryOffset = BigLong( imageHeader.nSceneEntryOffset );
	}
	targetBuffer.Put( &imageHeader, sizeof( imageHeader ) );

	// header is immediately followed by string table and pool
	for ( int i = 0; i < stringOffsets.Count(); i++ )
	{
		unsigned int offset = stringPoolStart + stringOffsets[i];
		if ( !bLittleEndian )
		{
			offset = BigLong( offset );
		}
		targetBuffer.PutInt( offset );
	}
	Assert( stringPoolStart == targetBuffer.TellMaxPut() );
	targetBuffer.Put( stringPool.Base(), stringPool.TellMaxPut() );

	// construct directory
	CUtlSortVector< SceneImageEntry_t, CSceneImageEntryLessFunc > imageDirectory;
	imageDirectory.EnsureCapacity( g_SceneFiles.Count() );

	// build directory
	// directory is linear sorted by filename checksum for later binary search
	for ( int i = 0; i < g_SceneFiles.Count(); i++ )
	{
		SceneImageEntry_t imageEntry = { 0 };

		// name needs to be normalized for determinstic later CRC name calc
		// calc crc based on scenes\anydir\anyscene.vcd
		char szCleanName[MAX_PATH];
		V_strncpy( szCleanName, g_SceneFiles[i].fileName.String(), sizeof( szCleanName ) );
		V_strlower( szCleanName );
		V_FixSlashes( szCleanName );
		char *pName = V_stristr( szCleanName, "scenes\\" );
		if ( !pName )
		{
			// must have scenes\ in filename
			Error( "CreateSceneImageFile: Unexpected lack of scenes prefix on %s\n", g_SceneFiles[i].fileName.String() );
		}

		CRC32_t crcFilename = CRC32_ProcessSingleBuffer( pName, strlen( pName ) );
		imageEntry.crcFilename = crcFilename;

		// temp store an index to its file, fixup later, necessary to access post sort
		imageEntry.nDataOffset = i;
		if ( imageDirectory.Find( imageEntry ) != imageDirectory.InvalidIndex() )
		{
			// filename checksums must be unique or runtime binary search would be bogus
			Error( "CreateSceneImageFile: Unexpected filename checksum collision!\n" );
		}		

		imageDirectory.Insert( imageEntry );
	}

	// determine sort order and start of data after dynamic summaries
	CUtlVector< int > writeOrder;
	writeOrder.EnsureCapacity( g_SceneFiles.Count() );
	sceneDataStart = sceneSummaryStart;
	for ( int i = 0; i < imageDirectory.Count(); i++ )
	{
		// reclaim offset, indicates write order of scene file
		int iScene = imageDirectory[i].nDataOffset;
		writeOrder.AddToTail( iScene );

		// march past each variable sized summary to determine start of scene data
		int numSounds = g_SceneFiles[iScene].soundList.Count();
		sceneDataStart += sizeof( SceneImageSummary_t ) + ( numSounds - 1 ) * sizeof( int );
	}

	// finalize and write directory
	Assert( sceneEntryStart == targetBuffer.TellMaxPut() );
	int nSummaryOffset = sceneSummaryStart;
	int nDataOffset = sceneDataStart;
	for ( int i = 0; i < imageDirectory.Count(); i++ )
	{
		int iScene = writeOrder[i];

		imageDirectory[i].nDataOffset = nDataOffset;
		imageDirectory[i].nDataLength = g_SceneFiles[iScene].compiledBuffer.TellMaxPut();
		imageDirectory[i].nSceneSummaryOffset = nSummaryOffset;
		if ( !bLittleEndian )
		{
			imageDirectory[i].crcFilename = BigLong( imageDirectory[i].crcFilename );
			imageDirectory[i].nDataOffset = BigLong( imageDirectory[i].nDataOffset );
			imageDirectory[i].nDataLength = BigLong( imageDirectory[i].nDataLength );
			imageDirectory[i].nSceneSummaryOffset = BigLong( imageDirectory[i].nSceneSummaryOffset );
		}
		targetBuffer.Put( &imageDirectory[i], sizeof( SceneImageEntry_t ) );

		int numSounds = g_SceneFiles[iScene].soundList.Count();
		nSummaryOffset += sizeof( SceneImageSummary_t ) + (numSounds - 1) * sizeof( int );

		nDataOffset += g_SceneFiles[iScene].compiledBuffer.TellMaxPut();
	}

	// finalize and write summaries
	Assert( sceneSummaryStart == targetBuffer.TellMaxPut() );
	for ( int i = 0; i < imageDirectory.Count(); i++ )
	{
		int iScene = writeOrder[i];
		int msecs = g_SceneFiles[iScene].msecs;
		int soundCount = g_SceneFiles[iScene].soundList.Count();
		if ( !bLittleEndian )
		{
			msecs = BigLong( msecs );
			soundCount = BigLong( soundCount );
		}
		targetBuffer.PutInt( msecs );
		targetBuffer.PutInt( soundCount );
		for ( int j = 0; j < g_SceneFiles[iScene].soundList.Count(); j++ )
		{
			int soundId = g_SceneFiles[iScene].soundList[j];
			if ( !bLittleEndian )
			{
				soundId = BigLong( soundId );
			}
			targetBuffer.PutInt( soundId );
		}
	}

	// finalize and write data
	Assert( sceneDataStart == targetBuffer.TellMaxPut() );
	for ( int i = 0; i < imageDirectory.Count(); i++ )
	{	
		int iScene = writeOrder[i];
		targetBuffer.Put( g_SceneFiles[iScene].compiledBuffer.Base(), g_SceneFiles[iScene].compiledBuffer.TellMaxPut() );
	}

	if ( !bQuiet )
	{
		Msg( "Scenes: Final size: %.2f MB\n", targetBuffer.TellMaxPut() / (1024.0f * 1024.0f ) );
	}

	// cleanup
	g_SceneFiles.Purge();

	return true;
}