Files
funnygame/engine/filesystem.cpp
2025-07-20 00:45:31 +03:00

289 lines
7.6 KiB
C++

#include "interface.h"
#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;
interface CFileSystem: public IFileSystem
{
public:
virtual void Init() override {}
virtual void Frame() override {}
virtual void Deinit() override {}
virtual void InitFilesystem( void ) override;
virtual void AddGameDirectory( const char *psz ) override;
virtual bool LoadPackFile( const char *szFilename ) override;
virtual void CreatePath( const char *szPath ) override;
virtual FileHandle_t Open( const char *szFilename, EFileOptions options ) override;
virtual void Close( FileHandle_t file ) override;
virtual size_t Size( FileHandle_t file ) override;
virtual size_t Read( FileHandle_t file, void *pOutput, size_t nSize) override;
virtual size_t ReadLine( FileHandle_t file, void *pOutput, size_t nSize) override;
virtual size_t Write( FileHandle_t file, void *pInput, size_t nSize) override;
virtual size_t Seek( FileHandle_t file, size_t nSize) override;
virtual size_t Tell( FileHandle_t file, size_t nSize) override;
virtual size_t fprintf( FileHandle_t file, const char *szFormat, ...) override;
static void AddDirectory( const char *psz );
static void AddFile( const char *psz );
};
DECLARE_ENGINE_INTERFACE(FileSystem, CFileSystem);
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CFileSystem::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")
{
FileSystem()->LoadPackFile(psz);
};
}
//-----------------------------------------------------------------------------
// Adds directory which can contain pack files
//-----------------------------------------------------------------------------
void CFileSystem::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 CFileSystem::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 CFileSystem::CreatePath( const char *szPath )
{
}
//-----------------------------------------------------------------------------
// Opens file
// If it is located in a pack then it can only be read
//-----------------------------------------------------------------------------
FileHandle_t CFileSystem::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 CFileSystem::Close( FileHandle_t file )
{
/* close only fs files */
if (file->file)
{
V_fclose(file->file);
}
delete file;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
size_t CFileSystem::Size( FileHandle_t file )
{
return file->nSize;
}
//-----------------------------------------------------------------------------
// Reads nSize bytes of file
//-----------------------------------------------------------------------------
size_t CFileSystem::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 CFileSystem::ReadLine( FileHandle_t file, void *pOutput, size_t nSize)
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
size_t CFileSystem::Write( FileHandle_t file, void *pInput, size_t nSize)
{
}
size_t CFileSystem::Seek( FileHandle_t file, size_t nSize)
{
}
size_t CFileSystem::Tell( FileHandle_t file, size_t nSize)
{
}
size_t CFileSystem::fprintf( FileHandle_t file, const char *szFormat, ...)
{
}