2
0
mirror of https://github.com/FWGS/xash3d-fwgs synced 2024-11-28 21:10:16 +01:00

filesystem: add functions to directly look up into archives

This commit is contained in:
Alibek Omarov 2024-11-23 13:56:53 +03:00
parent 567cf44111
commit b94446161e
2 changed files with 86 additions and 33 deletions

View File

@ -2477,45 +2477,19 @@ static void FS_CustomFree( void *data )
Mem_Free( data );
}
/*
============
FS_LoadFile
Filename are relative to the xash directory.
Always appends a 0 byte.
============
*/
static byte *FS_LoadFile_( const char *path, fs_offset_t *filesizeptr, const qboolean gamedironly, const qboolean custom_alloc )
static byte *FS_LoadFileFromArchive( searchpath_t *sp, const char *path, int pack_ind, fs_offset_t *filesizeptr, const qboolean sys_malloc )
{
searchpath_t *search;
fs_offset_t filesize;
file_t *file;
byte *buf;
char netpath[MAX_SYSPATH];
int pack_ind;
void *( *pfnAlloc )( size_t ) = custom_alloc ? FS_CustomAlloc : malloc;
void ( *pfnFree )( void * ) = custom_alloc ? FS_CustomFree : free;
// some mappers used leading '/' or '\' in path to models or sounds
if( path[0] == '/' || path[0] == '\\' )
path++;
if( path[0] == '/' || path[0] == '\\' )
path++;
if( !fs_searchpaths || FS_CheckNastyPath( path ))
return NULL;
search = FS_FindFile( path, &pack_ind, netpath, sizeof( netpath ), gamedironly );
if( !search )
return NULL;
void *( *pfnAlloc )( size_t ) = sys_malloc ? malloc : FS_CustomAlloc;
void ( *pfnFree )( void * ) = sys_malloc ? free : FS_CustomFree;
// custom load file function for compressed files
if( search->pfnLoadFile )
return search->pfnLoadFile( search, netpath, pack_ind, filesizeptr, pfnAlloc, pfnFree );
if( sp->pfnLoadFile )
return sp->pfnLoadFile( sp, path, pack_ind, filesizeptr, pfnAlloc, pfnFree );
file = search->pfnOpenFile( search, netpath, "rb", pack_ind );
file = sp->pfnOpenFile( sp, path, "rb", pack_ind );
if( !file ) // TODO: indicate errors
return NULL;
@ -2538,6 +2512,38 @@ static byte *FS_LoadFile_( const char *path, fs_offset_t *filesizeptr, const qbo
return buf;
}
/*
============
FS_LoadFile
Filename are relative to the xash directory.
Always appends a 0 byte.
============
*/
static byte *FS_LoadFile_( const char *path, fs_offset_t *filesizeptr, const qboolean gamedironly, const qboolean custom_alloc )
{
searchpath_t *search;
char netpath[MAX_SYSPATH];
int pack_ind;
// some mappers used leading '/' or '\' in path to models or sounds
if( path[0] == '/' || path[0] == '\\' )
path++;
if( path[0] == '/' || path[0] == '\\' )
path++;
if( !fs_searchpaths || FS_CheckNastyPath( path ))
return NULL;
search = FS_FindFile( path, &pack_ind, netpath, sizeof( netpath ), gamedironly );
if( !search )
return NULL;
return FS_LoadFileFromArchive( search, netpath, pack_ind, filesizeptr, !custom_alloc );
}
byte *FS_LoadFileMalloc( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
{
return FS_LoadFile_( path, filesizeptr, gamedironly, false );
@ -2976,6 +2982,29 @@ static qboolean FS_IsArchiveExtensionSupported( const char *ext, uint flags )
return false;
}
static searchpath_t *FS_GetArchiveByName( const char *name, searchpath_t *prev )
{
searchpath_t *sp = prev ? prev->next : fs_searchpaths;
for( ; sp; sp = sp->next )
{
if( !Q_stricmp( COM_FileWithoutPath( sp->filename ), name ))
return sp;
}
return NULL;
}
static int FS_FindFileInArchive( searchpath_t *sp, const char *path, char *truepath, size_t len )
{
return sp->pfnFindFile( sp, path, truepath, len );
}
static file_t *FS_OpenFileFromArchive( searchpath_t *sp, const char *path, const char *mode, int pack_ind )
{
return sp->pfnOpenFile( sp, path, mode, pack_ind );
}
void FS_InitMemory( void )
{
fs_mempool = Mem_AllocPool( "FileSystem Pool" );
@ -3106,6 +3135,10 @@ const fs_api_t g_api =
FS_LoadFileMalloc,
FS_IsArchiveExtensionSupported,
FS_GetArchiveByName,
FS_FindFileInArchive,
FS_OpenFileFromArchive,
FS_LoadFileFromArchive,
};
int EXPORT GetFSAPI( int version, fs_api_t *api, fs_globals_t **globals, fs_interface_t *engfuncs );

View File

@ -51,6 +51,8 @@ enum
FS_GAMEDIRONLY_SEARCH_FLAGS = FS_GAMEDIR_PATH | FS_CUSTOM_PATH | FS_GAMERODIR_PATH
};
typedef struct searchpath_s searchpath_t;
// IsArchiveExtensionSupported flags
enum
{
@ -201,8 +203,26 @@ typedef struct fs_api_t
// like LoadFile but returns pointer that can be free'd using standard library function
byte *(*LoadFileMalloc)( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
// queries supported archive formats
// **** archive interface ****
// query supported formats
qboolean (*IsArchiveExtensionSupported)( const char *ext, uint flags );
// to speed up archive lookups, this function can be used to get the archive object by it's name
// because archive can share the name, you can call this function repeatedly to get all archives
searchpath_t *(*GetArchiveByName)( const char *name, searchpath_t *prev );
// return an index into the archive and a true path, if possible
int (*FindFileInArchive)( searchpath_t *sp, const char *path, char *outpath, size_t len );
// similarly to Open, opens file but from specified archive
// NOTE: for speed reasons, path is case-sensitive here!
// Use FindFileInArchive to retrieve real path from caseinsensitive FS emulation!
file_t *(*OpenFileFromArchive)( searchpath_t *, const char *path, const char *mode, int pack_ind );
// similarly to LoadFile, loads whole file into memory from specified archive
// NOTE: for speed reasons, path is case-sensitive here!
// Use FindFileInArchive to retrieve real path from caseinsensitive FS emulation!
byte *(*LoadFileFromArchive)( searchpath_t *sp, const char *path, int pack_ind, fs_offset_t *filesizeptr, const qboolean sys_malloc );
} fs_api_t;
typedef struct fs_interface_t