253 lines
6.3 KiB
C++
253 lines
6.3 KiB
C++
#include "tier0/platform.h"
|
|
#include "tier1/commandline.h"
|
|
#include "filesystem.h"
|
|
#include "unistd.h"
|
|
#include <cstdio>
|
|
|
|
#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<PackDirectory_t> files;
|
|
};
|
|
struct FileDirectory_t
|
|
{
|
|
CUtlString path;
|
|
Pack_t pack;
|
|
};
|
|
|
|
|
|
CUtlString fs_basedir;
|
|
CUtlString fs_gamedir;
|
|
CUtlSelfReferencingVector<FileDirectory_t> 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<PackDirectory_t>(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)
|
|
{
|
|
|
|
}
|