2022-04-09 00:59:42 +02:00
# include "core/stdafx.h"
2022-04-09 16:16:40 +02:00
# include "tier1/cvar.h"
2022-04-09 00:59:42 +02:00
# include "filesystem/basefilesystem.h"
# include "filesystem/filesystem.h"
2023-05-22 12:32:49 +02:00
# include "bspfile.h"
# include "engine/modelloader.h"
2024-02-25 23:55:12 +01:00
static ConVar fs_showWarnings ( " fs_showWarnings " , " 0 " , FCVAR_DEVELOPMENTONLY | FCVAR_ACCESSIBLE_FROM_THREADS , " Logs the FileSystem warnings to the console, filtered by 'fs_warning_level' ( !slower! ) . " , true, 0.f, true, 2.f, " 0 = log to file . 1 = 0 + log to console . 2 = 1 + log to notify " ) ;
2024-02-24 02:15:09 +01:00
2022-04-09 00:59:42 +02:00
//---------------------------------------------------------------------------------
// Purpose: prints the output of the filesystem based on the warning level
// Input : *this -
// level -
// *pFmt -
//---------------------------------------------------------------------------------
void CBaseFileSystem : : Warning ( CBaseFileSystem * pFileSystem , FileWarningLevel_t level , const char * pFmt , . . . )
{
2023-03-26 16:21:49 +02:00
if ( level > = FileWarningLevel_t : : FILESYSTEM_WARNING_REPORTALLACCESSES )
{
2023-05-22 12:32:49 +02:00
// Logging reads are very verbose! Explicitly toggle..
2023-03-26 17:46:30 +02:00
if ( ! fs_showAllReads - > GetBool ( ) )
2023-03-26 16:21:49 +02:00
{
return ;
}
}
2023-03-26 16:09:05 +02:00
va_list args ;
va_start ( args , pFmt ) ;
2024-02-24 02:15:09 +01:00
CoreMsgV ( LogType_t : : LOG_WARNING , static_cast < LogLevel_t > ( fs_showWarnings . GetInt ( ) ) , eDLL_T : : FS , " filesystem " , pFmt , args ) ;
2023-03-26 16:09:05 +02:00
va_end ( args ) ;
2022-04-09 00:59:42 +02:00
}
//---------------------------------------------------------------------------------
2022-11-08 01:11:14 +01:00
// Purpose: attempts to load files from disk if exist before loading from VPK/cache
// Input : *pszFilePath -
2022-11-06 12:21:21 +01:00
// Output : handle to file on success, NULL on failure
2022-04-09 00:59:42 +02:00
//---------------------------------------------------------------------------------
2022-11-08 01:11:14 +01:00
bool CBaseFileSystem : : VCheckDisk ( const char * pszFilePath )
2022-04-09 00:59:42 +02:00
{
2022-11-08 01:11:14 +01:00
// Only load material files from the disk if the mode isn't zero,
// use -novpk to load valve materials from the disk.
2023-07-03 02:14:39 +02:00
if ( FileSystem ( ) - > CheckVPKMode ( 0 ) & & V_strstr ( pszFilePath , " .vmt " ) )
2022-11-08 01:11:14 +01:00
{
return false ;
}
2023-07-03 02:14:39 +02:00
if ( V_IsAbsolutePath ( pszFilePath ) )
2023-03-18 21:36:05 +01:00
{
// Skip absolute file paths.
return false ;
}
2023-07-03 02:14:39 +02:00
CUtlString filePath ;
filePath . Format ( " platform/%s " , pszFilePath ) ;
filePath . FixSlashes ( ) ;
filePath = filePath . Replace ( " \\ * \\ " , " " ) ;
2022-04-09 00:59:42 +02:00
2023-07-03 02:14:39 +02:00
if ( : : FileExists ( filePath . Get ( ) ) )
2022-11-08 01:11:14 +01:00
{
return true ;
}
return false ;
}
//---------------------------------------------------------------------------------
// Purpose: loads files from VPK
// Input : *this -
// *pResults -
// *pszFilePath -
// Output : handle to file on success, NULL on failure
//---------------------------------------------------------------------------------
2023-11-26 13:21:20 +01:00
FileHandle_t CBaseFileSystem : : VReadFromVPK ( CBaseFileSystem * pFileSystem , FileHandle_t pResults , const char * pszFilePath )
2022-11-08 01:11:14 +01:00
{
if ( VCheckDisk ( pszFilePath ) )
2022-04-09 00:59:42 +02:00
{
2022-06-12 12:14:31 +02:00
* reinterpret_cast < int64_t * > ( pResults ) = - 1 ;
return pResults ;
2022-04-09 00:59:42 +02:00
}
2022-11-08 01:11:14 +01:00
2024-01-02 15:21:36 +01:00
return CBaseFileSystem__LoadFromVPK ( pFileSystem , pResults , pszFilePath ) ;
2022-04-09 00:59:42 +02:00
}
//---------------------------------------------------------------------------------
2022-11-08 01:11:14 +01:00
// Purpose: loads files from cache
2022-11-06 12:21:21 +01:00
// Input : *this -
2022-04-09 00:59:42 +02:00
// *pszFilePath -
2023-05-20 14:04:33 +02:00
// *pCache -
2022-04-09 00:59:42 +02:00
// Output : true if file exists, false otherwise
//---------------------------------------------------------------------------------
2023-11-26 13:21:20 +01:00
bool CBaseFileSystem : : VReadFromCache ( CBaseFileSystem * pFileSystem , const char * pszFilePath , FileSystemCache * pCache )
2022-04-09 00:59:42 +02:00
{
2022-11-08 01:11:14 +01:00
if ( VCheckDisk ( pszFilePath ) )
2022-04-09 00:59:42 +02:00
{
return false ;
}
2022-11-08 01:11:14 +01:00
2024-01-02 15:21:36 +01:00
bool result = CBaseFileSystem__LoadFromCache ( pFileSystem , pszFilePath , pCache ) ;
2023-05-20 14:04:33 +02:00
return result ;
2022-11-06 12:21:21 +01:00
}
2023-05-22 12:32:49 +02:00
//---------------------------------------------------------------------------------
// Purpose: mounts a BSP packfile lump as search path
// Input : *this -
// *pPath -
// *pPathID -
// *addType -
//---------------------------------------------------------------------------------
void CBaseFileSystem : : VAddMapPackFile ( CBaseFileSystem * pFileSystem , const char * pPath , const char * pPathID , SearchPathAdd_t addType )
{
// Since the mounting of the packfile lump is performed before the BSP header
// is loaded and parsed, we have to do it here. The internal 'AddMapPackFile'
// function has been patched to load the fields in the global 's_MapHeader'
// field, instead of the one that is getting initialized (see r5apex.patch).
if ( s_MapHeader - > ident ! = IDBSPHEADER | | s_MapHeader - > version ! = BSPVERSION )
{
FileHandle_t hBspFile = FileSystem ( ) - > Open ( pPath , " rb " , pPathID ) ;
if ( hBspFile ! = FILESYSTEM_INVALID_HANDLE )
{
memset ( s_MapHeader , ' \0 ' , sizeof ( BSPHeader_t ) ) ;
FileSystem ( ) - > Read ( s_MapHeader , sizeof ( BSPHeader_t ) , hBspFile ) ;
}
}
// If a lump exists, replace the path pointer with that of the lump so that
// the internal function loads this instead.
char lumpPathBuf [ MAX_PATH ] ;
V_snprintf ( lumpPathBuf , sizeof ( lumpPathBuf ) , " %s.%.4X.bsp_lump " , pPath , LUMP_PAKFILE ) ;
if ( FileSystem ( ) - > FileExists ( lumpPathBuf , pPathID ) )
{
pPath = lumpPathBuf ;
}
2024-01-02 15:21:36 +01:00
CBaseFileSystem__AddMapPackFile ( pFileSystem , pPath , pPathID , addType ) ;
2023-05-22 12:32:49 +02:00
}
2022-11-06 12:21:21 +01:00
//---------------------------------------------------------------------------------
// Purpose: attempts to mount VPK file for filesystem usage
// Input : *this -
// *pszVpkPath -
// Output : pointer to VPK on success, NULL on failure
//---------------------------------------------------------------------------------
VPKData_t * CBaseFileSystem : : VMountVPKFile ( CBaseFileSystem * pFileSystem , const char * pszVpkPath )
{
2024-01-02 15:21:36 +01:00
int nHandle = CBaseFileSystem__GetMountedVPKHandle ( pFileSystem , pszVpkPath ) ;
VPKData_t * pPakData = CBaseFileSystem__MountVPKFile ( pFileSystem , pszVpkPath ) ;
2022-11-06 12:21:21 +01:00
2022-11-10 01:20:45 +01:00
if ( pPakData )
2022-11-06 12:21:21 +01:00
{
2022-11-10 01:20:45 +01:00
if ( nHandle < 0 ) // Only log if VPK hasn't been mounted yet.
{
2023-08-21 19:12:29 +02:00
: : Msg ( eDLL_T : : FS , " Mounted vpk file: '%s' with handle: '%i' \n " , pszVpkPath , pPakData - > m_nHandle ) ;
2022-11-10 01:20:45 +01:00
}
2022-11-06 12:21:21 +01:00
}
2022-11-10 01:20:45 +01:00
else // VPK failed to load or does not exist...
2022-11-06 12:21:21 +01:00
{
2022-11-06 14:21:27 +01:00
: : Warning ( eDLL_T : : FS , " Unable to mount vpk file: '%s' \n " , pszVpkPath ) ;
2022-11-06 12:21:21 +01:00
}
return pPakData ;
}
//---------------------------------------------------------------------------------
// Purpose: unmount a VPK file
// Input : *this -
// *pszVpkPath -
// Output : pointer to formatted VPK path string
//---------------------------------------------------------------------------------
const char * CBaseFileSystem : : VUnmountVPKFile ( CBaseFileSystem * pFileSystem , const char * pszVpkPath )
{
2024-01-02 15:21:36 +01:00
int nHandle = CBaseFileSystem__GetMountedVPKHandle ( pFileSystem , pszVpkPath ) ;
const char * pRet = CBaseFileSystem__UnmountVPKFile ( pFileSystem , pszVpkPath ) ;
2022-11-06 12:21:21 +01:00
if ( nHandle > = 0 )
{
2023-08-21 19:12:29 +02:00
: : Msg ( eDLL_T : : FS , " Unmounted vpk file: '%s' with handle: '%i' \n " , pszVpkPath , nHandle ) ;
2022-11-06 12:21:21 +01:00
}
return pRet ;
2022-04-09 00:59:42 +02:00
}
2022-11-23 12:18:33 +01:00
//---------------------------------------------------------------------------------
// Purpose: reads a string until its null terminator
// Input : *pFile -
// Output : string
//---------------------------------------------------------------------------------
2023-05-29 21:41:17 +02:00
CUtlString CBaseFileSystem : : ReadString ( FileHandle_t pFile )
2022-11-23 12:18:33 +01:00
{
2023-05-29 21:41:17 +02:00
CUtlString result ;
2022-11-23 12:18:33 +01:00
char c = ' \0 ' ;
do
{
Read ( & c , sizeof ( char ) , pFile ) ;
if ( c )
2023-05-29 21:41:17 +02:00
result + = c ;
2022-11-23 12:18:33 +01:00
} while ( c ) ;
2023-05-29 21:41:17 +02:00
return result ;
2022-11-23 12:18:33 +01:00
}
2023-11-26 13:21:20 +01:00
void VBaseFileSystem : : Detour ( const bool bAttach ) const
2022-04-09 00:59:42 +02:00
{
2024-01-02 15:21:36 +01:00
DetourSetup ( & CBaseFileSystem__Warning , & CBaseFileSystem : : Warning , bAttach ) ;
DetourSetup ( & CBaseFileSystem__LoadFromVPK , & CBaseFileSystem : : VReadFromVPK , bAttach ) ;
DetourSetup ( & CBaseFileSystem__LoadFromCache , & CBaseFileSystem : : VReadFromCache , bAttach ) ;
DetourSetup ( & CBaseFileSystem__AddMapPackFile , & CBaseFileSystem : : VAddMapPackFile , bAttach ) ;
DetourSetup ( & CBaseFileSystem__MountVPKFile , & CBaseFileSystem : : VMountVPKFile , bAttach ) ;
DetourSetup ( & CBaseFileSystem__UnmountVPKFile , & CBaseFileSystem : : VUnmountVPKFile , bAttach ) ;
2022-04-09 00:59:42 +02:00
}
2022-05-27 22:38:49 +02:00
CBaseFileSystem * g_pFileSystem = nullptr ;