#include "tier0/platform.h" #include "tier1/commandline.h" #include "filesystem.h" #include "unistd.h" #include #define BASEDIR "rtt" #define GAMEDIR "funnygame" struct PackHeader_t { char id[8]; unsigned long long offset; unsigned long long size; }; struct PackDirectory_t { char name[56]; unsigned long long offset; unsigned long long size; }; struct Pack_t { FILE* handle; PackHeader_t header; CUtlVector files; }; struct FileDirectory_t { CUtlString path; Pack_t pack; }; CUtlString fs_basedir; CUtlString fs_gamedir; CUtlSelfReferencingVector fs_directories; class CFileSystem: public IFileSystem { public: static void AddDirectory( const char *psz ); static void AddFile( const char *psz ); }; //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void IFileSystem::InitFilesystem() { #ifdef STATIC_BUILD fs_basedir = ICommandLine::ParamValue("-basedir"); if ( fs_basedir == 0 ) fs_basedir=BASEDIR; if ( fs_basedir.GetString()[0] == '-' ) fs_basedir=BASEDIR; fs_gamedir = ICommandLine::ParamValue("-gamedir"); if ( fs_gamedir == 0 ) fs_gamedir=GAMEDIR; if ( fs_gamedir.GetString()[0] == '-' ) fs_gamedir=GAMEDIR; AddGameDirectory(fs_gamedir); #endif AddGameDirectory("."); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CFileSystem::AddFile( const char *psz ) { CUtlString extension = Plat_GetExtension(psz); if (extension=="pak") { IFileSystem::LoadPackFile(psz); }; } //----------------------------------------------------------------------------- // Adds directory which can contain pack files //----------------------------------------------------------------------------- void IFileSystem::AddGameDirectory( const char *psz ) { FileDirectory_t dir = {}; dir.path = psz; fs_directories.AppendTail(dir); Plat_ListDirRecursive(psz, CFileSystem::AddFile, 0); for (auto &dir: fs_directories) { V_printf("%s\n",(char*)dir.path); }; }; //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- bool IFileSystem::LoadPackFile( const char *szFilename ) { Pack_t pack = {}; PackHeader_t header = {}; unsigned long long nNumFiles = 0; PackDirectory_t *pDirs = NULL; FILE* f = V_fopen(szFilename, "rb"); if (!f) Plat_FatalErrorFunc("Failed to open %s",szFilename); V_fread(&header,1,sizeof(header),f); // check for rttpacku if ( header.id[0]!='r' || header.id[1] != 't' || header.id[2] != 't' || header.id[3]!='p' || header.id[4]!='a' || header.id[5] != 'c' || header.id[6] != 'k' || header.id[7]!='u' ) { Plat_FatalErrorFunc("%s is not a pack file",szFilename); } nNumFiles = header.size/sizeof(PackDirectory_t); pDirs = (PackDirectory_t*)V_malloc(header.size); V_fseek(f, header.offset, SEEK_SET); V_fread(pDirs, sizeof(PackDirectory_t), nNumFiles, f); pack.header = header; pack.handle = f; pack.files = CUtlVector(nNumFiles); V_memcpy(pack.files.GetData(),pDirs, header.size); V_free(pDirs); nNumFiles = header.size/sizeof(PackDirectory_t); FileDirectory_t fd = {}; fd.path = szFilename; fd.pack = pack; fs_directories.AppendTail(fd); return true; } //----------------------------------------------------------------------------- // Creates path //----------------------------------------------------------------------------- void IFileSystem::CreatePath( const char *szPath ) { } //----------------------------------------------------------------------------- // Opens file // If it is located in a pack then it can only be read //----------------------------------------------------------------------------- FileHandle_t IFileSystem::Open( const char *szFilename, EFileOptions options ) { if (options == IFILE_READ) { FILE *file = V_fopen(szFilename, "rb"); /* found in fs */ if ( file != NULL ) { FileHandle_t filehandle = new FileHandle_s; filehandle->file = file; filehandle->nPtr = 0; filehandle->options = IFILE_READ; /* get size */ V_fseek(file, 0, SEEK_END); filehandle->nSize = V_ftell(file); V_fseek(file, 0, SEEK_SET); return filehandle; } /* not found in fs, try to search in packs */ for ( auto &pak: fs_directories ) { for ( auto &file: pak.pack.files ) { if ( !strncmp(file.name, szFilename, 56) ) { FileHandle_t filehandle = new FileHandle_s; filehandle->file = 0; filehandle->parent = pak.pack.handle; filehandle->nSize = file.size; filehandle->nOffset = file.offset; filehandle->nPtr = 0; filehandle->options = IFILE_READ; return filehandle; } } }; } return 0; } //----------------------------------------------------------------------------- // Closes file //----------------------------------------------------------------------------- void IFileSystem::Close( FileHandle_t file ) { /* close only fs files */ if (file->file) { V_fclose(file->file); } delete file; } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- size_t IFileSystem::Size( FileHandle_t file ) { return file->nSize; } //----------------------------------------------------------------------------- // Reads nSize bytes of file //----------------------------------------------------------------------------- size_t IFileSystem::Read( FileHandle_t file, void *pOutput, size_t nSize) { if (file->file) { size_t readsize = V_fread(pOutput, 1, nSize, file->file); file->nPtr+=readsize; return readsize; } size_t readsize = V_fseek(file->parent, file->nOffset, file->nPtr); V_fread(pOutput, 1, nSize, file->parent); return readsize; } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- size_t IFileSystem::ReadLine( FileHandle_t file, void *pOutput, size_t nSize) { } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- size_t IFileSystem::Write( FileHandle_t file, void *pInput, size_t nSize) { }