mirror of
https://github.com/UberGames/lilium-voyager.git
synced 2024-11-10 14:41:42 +00:00
- Small change to search path order - local files not in .pk3s take precedence over files in pk3s. Should make life easier for modders/mappers wanting to override textures that are already contained in some older pk3
- Make VM loading more robust, change loading order: when vm_* == 0 first try loading DLL, then QVM in *each* search directory/path - Fix FS_FileForHandle that would return a FILE pointer to invalid file handle 0
This commit is contained in:
parent
1ff28b3b2e
commit
9219cde4e8
6 changed files with 584 additions and 368 deletions
|
@ -215,6 +215,7 @@ typedef struct fileInPack_s {
|
|||
} fileInPack_t;
|
||||
|
||||
typedef struct {
|
||||
char pakPathname[MAX_OSPATH]; // c:\quake3\baseq3
|
||||
char pakFilename[MAX_OSPATH]; // c:\quake3\baseq3\pak0.pk3
|
||||
char pakBasename[MAX_OSPATH]; // pak0
|
||||
char pakGamename[MAX_OSPATH]; // baseq3
|
||||
|
@ -230,6 +231,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
char path[MAX_OSPATH]; // c:\quake3
|
||||
char fullpath[MAX_OSPATH]; // c:\quake3\baseq3
|
||||
char gamedir[MAX_OSPATH]; // baseq3
|
||||
} directory_t;
|
||||
|
||||
|
@ -393,7 +395,7 @@ static fileHandle_t FS_HandleForFile(void) {
|
|||
}
|
||||
|
||||
static FILE *FS_FileForHandle( fileHandle_t f ) {
|
||||
if ( f < 0 || f > MAX_FILE_HANDLES ) {
|
||||
if ( f < 1 || f > MAX_FILE_HANDLES ) {
|
||||
Com_Error( ERR_DROP, "FS_FileForHandle: out of range" );
|
||||
}
|
||||
if (fsh[f].zipFile == qtrue) {
|
||||
|
@ -413,6 +415,25 @@ void FS_ForceFlush( fileHandle_t f ) {
|
|||
setvbuf( file, NULL, _IONBF, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_fplength
|
||||
================
|
||||
*/
|
||||
|
||||
long FS_fplength(FILE *h)
|
||||
{
|
||||
long pos;
|
||||
long end;
|
||||
|
||||
pos = ftell(h);
|
||||
fseek(h, 0, SEEK_END);
|
||||
end = ftell(h);
|
||||
fseek(h, pos, SEEK_SET);
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_filelength
|
||||
|
@ -422,18 +443,16 @@ it will return the size of the pak file, not the expected
|
|||
size of the file.
|
||||
================
|
||||
*/
|
||||
int FS_filelength( fileHandle_t f ) {
|
||||
int pos;
|
||||
int end;
|
||||
long FS_filelength(fileHandle_t f)
|
||||
{
|
||||
FILE *h;
|
||||
|
||||
h = FS_FileForHandle(f);
|
||||
pos = ftell (h);
|
||||
fseek (h, 0, SEEK_END);
|
||||
end = ftell (h);
|
||||
fseek (h, pos, SEEK_SET);
|
||||
|
||||
return end;
|
||||
if(h == NULL)
|
||||
return -1;
|
||||
else
|
||||
return FS_fplength(h);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -570,6 +589,28 @@ void FS_HomeRemove( const char *homePath ) {
|
|||
fs_gamedir, homePath ) );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_FileInPathExists
|
||||
|
||||
Tests if path and file exists
|
||||
================
|
||||
*/
|
||||
qboolean FS_FileInPathExists(const char *testpath)
|
||||
{
|
||||
FILE *filep;
|
||||
|
||||
filep = fopen(testpath, "rb");
|
||||
|
||||
if(filep)
|
||||
{
|
||||
fclose(filep);
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_FileExists
|
||||
|
@ -582,17 +623,7 @@ NOTE TTimo: this goes with FS_FOpenFileWrite for opening the file afterwards
|
|||
*/
|
||||
qboolean FS_FileExists(const char *file)
|
||||
{
|
||||
FILE *f;
|
||||
char *testpath;
|
||||
|
||||
testpath = FS_BuildOSPath( fs_homepath->string, fs_gamedir, file );
|
||||
|
||||
f = fopen( testpath, "rb" );
|
||||
if (f) {
|
||||
fclose( f );
|
||||
return qtrue;
|
||||
}
|
||||
return qfalse;
|
||||
return FS_FileInPathExists(FS_BuildOSPath(fs_homepath->string, fs_gamedir, file));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -604,18 +635,12 @@ Tests if the file exists
|
|||
*/
|
||||
qboolean FS_SV_FileExists( const char *file )
|
||||
{
|
||||
FILE *f;
|
||||
char *testpath;
|
||||
|
||||
testpath = FS_BuildOSPath( fs_homepath->string, file, "");
|
||||
testpath[strlen(testpath)-1] = '\0';
|
||||
|
||||
f = fopen( testpath, "rb" );
|
||||
if (f) {
|
||||
fclose( f );
|
||||
return qtrue;
|
||||
}
|
||||
return qfalse;
|
||||
return FS_FileInPathExists(testpath);
|
||||
}
|
||||
|
||||
|
||||
|
@ -669,7 +694,8 @@ Search for a file somewhere below the home path then base path
|
|||
in that order
|
||||
===========
|
||||
*/
|
||||
int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp ) {
|
||||
long FS_SV_FOpenFileRead(const char *filename, fileHandle_t *fp)
|
||||
{
|
||||
char *ospath;
|
||||
fileHandle_t f = 0;
|
||||
|
||||
|
@ -1040,6 +1066,256 @@ qboolean FS_IsDemoExt(const char *filename, int namelen)
|
|||
return qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
FS_FOpenFileReadDir
|
||||
|
||||
Tries opening file "filename" in searchpath "search"
|
||||
Returns filesize and an open FILE pointer.
|
||||
===========
|
||||
*/
|
||||
extern qboolean com_fullyInitialized;
|
||||
|
||||
long FS_FOpenFileReadDir(const char *filename, searchpath_t *search, fileHandle_t *file, qboolean uniqueFILE)
|
||||
{
|
||||
long hash;
|
||||
pack_t *pak;
|
||||
fileInPack_t *pakFile;
|
||||
directory_t *dir;
|
||||
char *netpath;
|
||||
FILE *filep;
|
||||
int len;
|
||||
|
||||
if(filename == NULL)
|
||||
Com_Error(ERR_FATAL, "FS_FOpenFileRead: NULL 'filename' parameter passed");
|
||||
|
||||
// qpaths are not supposed to have a leading slash
|
||||
if(filename[0] == '/' || filename[0] == '\\')
|
||||
filename++;
|
||||
|
||||
// make absolutely sure that it can't back up the path.
|
||||
// The searchpaths do guarantee that something will always
|
||||
// be prepended, so we don't need to worry about "c:" or "//limbo"
|
||||
if(strstr(filename, ".." ) || strstr(filename, "::"))
|
||||
{
|
||||
if(file == NULL)
|
||||
return qfalse;
|
||||
|
||||
*file = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// make sure the q3key file is only readable by the quake3.exe at initialization
|
||||
// any other time the key should only be accessed in memory using the provided functions
|
||||
if(com_fullyInitialized && strstr(filename, "q3key"))
|
||||
{
|
||||
if(file == NULL)
|
||||
return qfalse;
|
||||
|
||||
*file = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(file == NULL)
|
||||
{
|
||||
// just wants to see if file is there
|
||||
|
||||
// is the element a pak file?
|
||||
if(search->pack)
|
||||
{
|
||||
hash = FS_HashFileName(filename, search->pack->hashSize);
|
||||
|
||||
if(search->pack->hashTable[hash])
|
||||
{
|
||||
// look through all the pak file elements
|
||||
pak = search->pack;
|
||||
pakFile = pak->hashTable[hash];
|
||||
|
||||
do
|
||||
{
|
||||
// case and separator insensitive comparisons
|
||||
if(!FS_FilenameCompare(pakFile->name, filename))
|
||||
{
|
||||
// found it!
|
||||
if(pakFile->len)
|
||||
return pakFile->len;
|
||||
else
|
||||
{
|
||||
// It's not nice, but legacy code depends
|
||||
// on positive value if file exists no matter
|
||||
// what size
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
pakFile = pakFile->next;
|
||||
} while(pakFile != NULL);
|
||||
}
|
||||
}
|
||||
else if(search->dir)
|
||||
{
|
||||
dir = search->dir;
|
||||
|
||||
netpath = FS_BuildOSPath(dir->path, dir->gamedir, filename);
|
||||
filep = fopen (netpath, "rb");
|
||||
|
||||
if(filep)
|
||||
{
|
||||
len = FS_fplength(filep);
|
||||
fclose(filep);
|
||||
|
||||
if(len)
|
||||
return len;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
*file = FS_HandleForFile();
|
||||
fsh[*file].handleFiles.unique = uniqueFILE;
|
||||
|
||||
// is the element a pak file?
|
||||
if(search->pack)
|
||||
{
|
||||
hash = FS_HashFileName(filename, search->pack->hashSize);
|
||||
|
||||
if(search->pack->hashTable[hash])
|
||||
{
|
||||
// disregard if it doesn't match one of the allowed pure pak files
|
||||
if(!FS_PakIsPure(search->pack))
|
||||
{
|
||||
*file = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// look through all the pak file elements
|
||||
pak = search->pack;
|
||||
pakFile = pak->hashTable[hash];
|
||||
|
||||
do
|
||||
{
|
||||
// case and separator insensitive comparisons
|
||||
if(!FS_FilenameCompare(pakFile->name, filename))
|
||||
{
|
||||
// found it!
|
||||
|
||||
// mark the pak as having been referenced and mark specifics on cgame and ui
|
||||
// shaders, txt, arena files by themselves do not count as a reference as
|
||||
// these are loaded from all pk3s
|
||||
// from every pk3 file..
|
||||
len = strlen(filename);
|
||||
|
||||
if (!(pak->referenced & FS_GENERAL_REF))
|
||||
{
|
||||
if(!FS_IsExt(filename, ".shader", len) &&
|
||||
!FS_IsExt(filename, ".txt", len) &&
|
||||
!FS_IsExt(filename, ".cfg", len) &&
|
||||
!FS_IsExt(filename, ".config", len) &&
|
||||
!FS_IsExt(filename, ".bot", len) &&
|
||||
!FS_IsExt(filename, ".arena", len) &&
|
||||
!FS_IsExt(filename, ".menu", len) &&
|
||||
!strstr(filename, "levelshots"))
|
||||
{
|
||||
pak->referenced |= FS_GENERAL_REF;
|
||||
}
|
||||
}
|
||||
|
||||
if(strstr(filename, "qagame.qvm"))
|
||||
pak->referenced |= FS_QAGAME_REF;
|
||||
if(strstr(filename, "cgame.qvm"))
|
||||
pak->referenced |= FS_CGAME_REF;
|
||||
if(strstr(filename, "ui.qvm"))
|
||||
pak->referenced |= FS_UI_REF;
|
||||
|
||||
if(uniqueFILE)
|
||||
{
|
||||
// open a new file on the pakfile
|
||||
fsh[*file].handleFiles.file.z = unzOpen(pak->pakFilename);
|
||||
|
||||
if(fsh[*file].handleFiles.file.z == NULL)
|
||||
Com_Error(ERR_FATAL, "Couldn't open %s", pak->pakFilename);
|
||||
}
|
||||
else
|
||||
fsh[*file].handleFiles.file.z = pak->handle;
|
||||
|
||||
Q_strncpyz(fsh[*file].name, filename, sizeof(fsh[*file].name));
|
||||
fsh[*file].zipFile = qtrue;
|
||||
|
||||
// set the file position in the zip file (also sets the current file info)
|
||||
unzSetOffset(fsh[*file].handleFiles.file.z, pakFile->pos);
|
||||
|
||||
// open the file in the zip
|
||||
unzOpenCurrentFile(fsh[*file].handleFiles.file.z);
|
||||
fsh[*file].zipFilePos = pakFile->pos;
|
||||
|
||||
if(fs_debug->integer)
|
||||
{
|
||||
Com_Printf("FS_FOpenFileRead: %s (found in '%s')\n",
|
||||
filename, pak->pakFilename);
|
||||
}
|
||||
|
||||
return pakFile->len;
|
||||
}
|
||||
|
||||
pakFile = pakFile->next;
|
||||
} while(pakFile != NULL);
|
||||
}
|
||||
}
|
||||
else if(search->dir)
|
||||
{
|
||||
// check a file in the directory tree
|
||||
|
||||
// if we are running restricted, the only files we
|
||||
// will allow to come from the directory are .cfg files
|
||||
len = strlen(filename);
|
||||
// FIXME TTimo I'm not sure about the fs_numServerPaks test
|
||||
// if you are using FS_ReadFile to find out if a file exists,
|
||||
// this test can make the search fail although the file is in the directory
|
||||
// I had the problem on https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8
|
||||
// turned out I used FS_FileExists instead
|
||||
if(fs_numServerPaks)
|
||||
{
|
||||
if(!FS_IsExt(filename, ".cfg", len) && // for config files
|
||||
!FS_IsExt(filename, ".menu", len) && // menu files
|
||||
!FS_IsExt(filename, ".game", len) && // menu files
|
||||
!FS_IsExt(filename, ".cfg", len) && // for journal files
|
||||
!FS_IsDemoExt(filename, len)) // demos
|
||||
{
|
||||
*file = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
dir = search->dir;
|
||||
|
||||
netpath = FS_BuildOSPath(dir->path, dir->gamedir, filename);
|
||||
filep = fopen(netpath, "rb");
|
||||
|
||||
if (filep == NULL)
|
||||
{
|
||||
*file = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Q_strncpyz(fsh[*file].name, filename, sizeof(fsh[*file].name));
|
||||
fsh[*file].zipFile = qfalse;
|
||||
|
||||
if(fs_debug->integer)
|
||||
{
|
||||
Com_Printf("FS_FOpenFileRead: %s (found in '%s/%s')\n", filename,
|
||||
dir->path, dir->gamedir);
|
||||
}
|
||||
|
||||
fsh[*file].handleFiles.file.o = filep;
|
||||
return FS_fplength(filep);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
FS_FOpenFileRead
|
||||
|
@ -1050,242 +1326,134 @@ Used for streaming data out of either a
|
|||
separate file or a ZIP file.
|
||||
===========
|
||||
*/
|
||||
extern qboolean com_fullyInitialized;
|
||||
|
||||
int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueFILE ) {
|
||||
long FS_FOpenFileRead(const char *filename, fileHandle_t *file, qboolean uniqueFILE)
|
||||
{
|
||||
searchpath_t *search;
|
||||
char *netpath;
|
||||
pack_t *pak;
|
||||
fileInPack_t *pakFile;
|
||||
directory_t *dir;
|
||||
long hash;
|
||||
FILE *temp;
|
||||
int l;
|
||||
long len;
|
||||
|
||||
hash = 0;
|
||||
|
||||
if ( !fs_searchpaths ) {
|
||||
if(!fs_searchpaths)
|
||||
Com_Error(ERR_FATAL, "Filesystem call made without initialization");
|
||||
}
|
||||
|
||||
if ( file == NULL ) {
|
||||
// just wants to see if file is there
|
||||
for ( search = fs_searchpaths ; search ; search = search->next ) {
|
||||
//
|
||||
if ( search->pack ) {
|
||||
hash = FS_HashFileName(filename, search->pack->hashSize);
|
||||
}
|
||||
// is the element a pak file?
|
||||
if ( search->pack && search->pack->hashTable[hash] ) {
|
||||
// look through all the pak file elements
|
||||
pak = search->pack;
|
||||
pakFile = pak->hashTable[hash];
|
||||
do {
|
||||
// case and separator insensitive comparisons
|
||||
if ( !FS_FilenameCompare( pakFile->name, filename ) ) {
|
||||
// found it!
|
||||
return qtrue;
|
||||
}
|
||||
pakFile = pakFile->next;
|
||||
} while(pakFile != NULL);
|
||||
} else if ( search->dir ) {
|
||||
dir = search->dir;
|
||||
|
||||
netpath = FS_BuildOSPath( dir->path, dir->gamedir, filename );
|
||||
temp = fopen (netpath, "rb");
|
||||
if ( !temp ) {
|
||||
continue;
|
||||
}
|
||||
fclose(temp);
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if ( !filename ) {
|
||||
Com_Error( ERR_FATAL, "FS_FOpenFileRead: NULL 'filename' parameter passed" );
|
||||
}
|
||||
|
||||
// qpaths are not supposed to have a leading slash
|
||||
if ( filename[0] == '/' || filename[0] == '\\' ) {
|
||||
filename++;
|
||||
}
|
||||
|
||||
// make absolutely sure that it can't back up the path.
|
||||
// The searchpaths do guarantee that something will always
|
||||
// be prepended, so we don't need to worry about "c:" or "//limbo"
|
||||
if ( strstr( filename, ".." ) || strstr( filename, "::" ) ) {
|
||||
*file = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// make sure the q3key file is only readable by the quake3.exe at initialization
|
||||
// any other time the key should only be accessed in memory using the provided functions
|
||||
if( com_fullyInitialized && strstr( filename, "q3key" ) ) {
|
||||
*file = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// search through the path, one element at a time
|
||||
//
|
||||
|
||||
*file = FS_HandleForFile();
|
||||
fsh[*file].handleFiles.unique = uniqueFILE;
|
||||
|
||||
for ( search = fs_searchpaths ; search ; search = search->next ) {
|
||||
//
|
||||
if ( search->pack ) {
|
||||
hash = FS_HashFileName(filename, search->pack->hashSize);
|
||||
}
|
||||
// is the element a pak file?
|
||||
if ( search->pack && search->pack->hashTable[hash] ) {
|
||||
// disregard if it doesn't match one of the allowed pure pak files
|
||||
if ( !FS_PakIsPure(search->pack) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// look through all the pak file elements
|
||||
pak = search->pack;
|
||||
pakFile = pak->hashTable[hash];
|
||||
do {
|
||||
// case and separator insensitive comparisons
|
||||
if ( !FS_FilenameCompare( pakFile->name, filename ) ) {
|
||||
// found it!
|
||||
|
||||
// mark the pak as having been referenced and mark specifics on cgame and ui
|
||||
// shaders, txt, arena files by themselves do not count as a reference as
|
||||
// these are loaded from all pk3s
|
||||
// from every pk3 file..
|
||||
l = strlen(filename);
|
||||
|
||||
if (!(pak->referenced & FS_GENERAL_REF))
|
||||
for(search = fs_searchpaths; search; search = search->next)
|
||||
{
|
||||
if(!FS_IsExt(filename, ".shader", l) &&
|
||||
!FS_IsExt(filename, ".txt", l) &&
|
||||
!FS_IsExt(filename, ".cfg", l) &&
|
||||
!FS_IsExt(filename, ".config", l) &&
|
||||
!FS_IsExt(filename, ".bot", l) &&
|
||||
!FS_IsExt(filename, ".arena", l) &&
|
||||
!FS_IsExt(filename, ".menu", l) &&
|
||||
!strstr(filename, "levelshots"))
|
||||
len = FS_FOpenFileReadDir(filename, search, file, uniqueFILE);
|
||||
|
||||
if(file == NULL)
|
||||
{
|
||||
pak->referenced |= FS_GENERAL_REF;
|
||||
if(len > 0)
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(pak->referenced & FS_QAGAME_REF) && strstr(filename, "qagame.qvm")) {
|
||||
pak->referenced |= FS_QAGAME_REF;
|
||||
}
|
||||
if (!(pak->referenced & FS_CGAME_REF) && strstr(filename, "cgame.qvm")) {
|
||||
pak->referenced |= FS_CGAME_REF;
|
||||
}
|
||||
if (!(pak->referenced & FS_UI_REF) && strstr(filename, "ui.qvm")) {
|
||||
pak->referenced |= FS_UI_REF;
|
||||
}
|
||||
|
||||
if ( uniqueFILE ) {
|
||||
// open a new file on the pakfile
|
||||
fsh[*file].handleFiles.file.z = unzOpen (pak->pakFilename);
|
||||
if (fsh[*file].handleFiles.file.z == NULL) {
|
||||
Com_Error (ERR_FATAL, "Couldn't open %s", pak->pakFilename);
|
||||
}
|
||||
} else {
|
||||
fsh[*file].handleFiles.file.z = pak->handle;
|
||||
}
|
||||
Q_strncpyz( fsh[*file].name, filename, sizeof( fsh[*file].name ) );
|
||||
fsh[*file].zipFile = qtrue;
|
||||
// set the file position in the zip file (also sets the current file info)
|
||||
unzSetOffset(fsh[*file].handleFiles.file.z, pakFile->pos);
|
||||
// open the file in the zip
|
||||
unzOpenCurrentFile( fsh[*file].handleFiles.file.z );
|
||||
fsh[*file].zipFilePos = pakFile->pos;
|
||||
|
||||
if ( fs_debug->integer ) {
|
||||
Com_Printf( "FS_FOpenFileRead: %s (found in '%s')\n",
|
||||
filename, pak->pakFilename );
|
||||
}
|
||||
return pakFile->len;
|
||||
}
|
||||
pakFile = pakFile->next;
|
||||
} while(pakFile != NULL);
|
||||
} else if ( search->dir ) {
|
||||
// check a file in the directory tree
|
||||
|
||||
// if we are running restricted, the only files we
|
||||
// will allow to come from the directory are .cfg files
|
||||
l = strlen( filename );
|
||||
// FIXME TTimo I'm not sure about the fs_numServerPaks test
|
||||
// if you are using FS_ReadFile to find out if a file exists,
|
||||
// this test can make the search fail although the file is in the directory
|
||||
// I had the problem on https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8
|
||||
// turned out I used FS_FileExists instead
|
||||
if(fs_numServerPaks)
|
||||
else
|
||||
{
|
||||
if(!FS_IsExt(filename, ".cfg", l) && // for config files
|
||||
!FS_IsExt(filename, ".menu", l) && // menu files
|
||||
!FS_IsExt(filename, ".game", l) && // menu files
|
||||
!FS_IsExt(filename, ".cfg", l) && // for journal files
|
||||
!FS_IsDemoExt(filename, l)) // demos
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(len >= 0 && *file)
|
||||
return len;
|
||||
}
|
||||
|
||||
dir = search->dir;
|
||||
|
||||
netpath = FS_BuildOSPath( dir->path, dir->gamedir, filename );
|
||||
fsh[*file].handleFiles.file.o = fopen (netpath, "rb");
|
||||
if ( !fsh[*file].handleFiles.file.o ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Q_strncpyz( fsh[*file].name, filename, sizeof( fsh[*file].name ) );
|
||||
fsh[*file].zipFile = qfalse;
|
||||
if ( fs_debug->integer ) {
|
||||
Com_Printf( "FS_FOpenFileRead: %s (found in '%s/%s')\n", filename,
|
||||
dir->path, dir->gamedir );
|
||||
}
|
||||
|
||||
return FS_filelength (*file);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FS_MISSING
|
||||
if (missingFiles) {
|
||||
if(missingFiles)
|
||||
fprintf(missingFiles, "%s\n", filename);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(file)
|
||||
*file = 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
FS_FindVM
|
||||
|
||||
char *FS_FindDll( const char *filename ) {
|
||||
searchpath_t *search;
|
||||
Find a suitable VM file in search path order.
|
||||
|
||||
In each searchpath try:
|
||||
- open DLL file if DLL loading enabled
|
||||
- open QVM file
|
||||
|
||||
Enable search for DLL by setting enableDll to FSVM_ENABLEDLL
|
||||
|
||||
write found DLL or QVM to "found" and return VMI_NATIVE if DLL, VMI_COMPILED if QVM
|
||||
Return the searchpath in "startSearch".
|
||||
=================
|
||||
*/
|
||||
|
||||
vmInterpret_t FS_FindVM(void **startSearch, char *found, int foundlen, const char *name, int enableDll)
|
||||
{
|
||||
searchpath_t *search, *lastSearch;
|
||||
directory_t *dir;
|
||||
|
||||
if ( !fs_searchpaths ) {
|
||||
Com_Error( ERR_FATAL, "Filesystem call made without initialization" );
|
||||
}
|
||||
|
||||
for ( search = fs_searchpaths ; search ; search = search->next ) {
|
||||
if ( search->dir ) {
|
||||
FILE *f;
|
||||
pack_t *pack;
|
||||
char dllName[MAX_OSPATH], qvmName[MAX_OSPATH];
|
||||
char *netpath;
|
||||
|
||||
if(!fs_searchpaths)
|
||||
Com_Error(ERR_FATAL, "Filesystem call made without initialization");
|
||||
|
||||
if(enableDll)
|
||||
Com_sprintf(dllName, sizeof(dllName), "%s" ARCH_STRING DLL_EXT, name);
|
||||
|
||||
Com_sprintf(qvmName, sizeof(dllName), "vm/%s.qvm", name);
|
||||
|
||||
lastSearch = *startSearch;
|
||||
if(*startSearch == NULL)
|
||||
search = fs_searchpaths;
|
||||
else
|
||||
search = lastSearch->next;
|
||||
|
||||
while(search)
|
||||
{
|
||||
if(search->dir)
|
||||
{
|
||||
dir = search->dir;
|
||||
netpath = FS_BuildOSPath( dir->path, dir->gamedir, filename );
|
||||
f = fopen( netpath, "rb" );
|
||||
if (f) {
|
||||
fclose( f );
|
||||
return netpath;
|
||||
}
|
||||
|
||||
if(enableDll)
|
||||
{
|
||||
netpath = FS_BuildOSPath(dir->path, dir->gamedir, dllName);
|
||||
|
||||
if(FS_FileInPathExists(netpath))
|
||||
{
|
||||
Q_strncpyz(found, netpath, foundlen);
|
||||
*startSearch = search;
|
||||
|
||||
return VMI_NATIVE;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
if(FS_FOpenFileReadDir(qvmName, search, NULL, qfalse) > 0)
|
||||
{
|
||||
*startSearch = search;
|
||||
return VMI_COMPILED;
|
||||
}
|
||||
}
|
||||
else if(search->pack)
|
||||
{
|
||||
pack = search->pack;
|
||||
|
||||
if(lastSearch && lastSearch->pack)
|
||||
{
|
||||
// make sure we only try loading one VM file per game dir
|
||||
// i.e. if VM from pak7.pk3 fails we won't try one from pak6.pk3
|
||||
|
||||
if(!FS_FilenameCompare(lastSearch->pack->pakPathname, pack->pakPathname))
|
||||
{
|
||||
search = search->next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(FS_FOpenFileReadDir(qvmName, search, NULL, qfalse) > 0)
|
||||
{
|
||||
*startSearch = search;
|
||||
|
||||
return VMI_COMPILED;
|
||||
}
|
||||
}
|
||||
|
||||
search = search->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1572,17 +1740,20 @@ int FS_FileIsInPAK(const char *filename, int *pChecksum ) {
|
|||
|
||||
/*
|
||||
============
|
||||
FS_ReadFile
|
||||
FS_ReadFileDir
|
||||
|
||||
Filename are relative to the quake search path
|
||||
a null buffer will just return the file length without loading
|
||||
If searchPath is non-NULL search only in that specific search path
|
||||
============
|
||||
*/
|
||||
int FS_ReadFile( const char *qpath, void **buffer ) {
|
||||
long FS_ReadFileDir(const char *qpath, void *searchPath, void **buffer)
|
||||
{
|
||||
fileHandle_t h;
|
||||
searchpath_t *search;
|
||||
byte* buf;
|
||||
qboolean isConfig;
|
||||
int len;
|
||||
long len;
|
||||
|
||||
if ( !fs_searchpaths ) {
|
||||
Com_Error( ERR_FATAL, "Filesystem call made without initialization" );
|
||||
|
@ -1639,8 +1810,19 @@ int FS_ReadFile( const char *qpath, void **buffer ) {
|
|||
isConfig = qfalse;
|
||||
}
|
||||
|
||||
search = searchPath;
|
||||
|
||||
if(search == NULL)
|
||||
{
|
||||
// look for it in the filesystem or pack files
|
||||
len = FS_FOpenFileRead(qpath, &h, qfalse);
|
||||
}
|
||||
else
|
||||
{
|
||||
// look for it in a specific search path only
|
||||
len = FS_FOpenFileReadDir(qpath, search, &h, qfalse);
|
||||
}
|
||||
|
||||
if ( h == 0 ) {
|
||||
if ( buffer ) {
|
||||
*buffer = NULL;
|
||||
|
@ -1687,6 +1869,19 @@ int FS_ReadFile( const char *qpath, void **buffer ) {
|
|||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
FS_ReadFile
|
||||
|
||||
Filename are relative to the quake search path
|
||||
a null buffer will just return the file length without loading
|
||||
============
|
||||
*/
|
||||
long FS_ReadFile(const char *qpath, void **buffer)
|
||||
{
|
||||
return FS_ReadFileDir(qpath, NULL, buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
FS_FreeFile
|
||||
|
@ -2541,6 +2736,33 @@ void FS_TouchFile_f( void ) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
FS_Which
|
||||
============
|
||||
*/
|
||||
|
||||
qboolean FS_Which(const char *filename, void *searchPath)
|
||||
{
|
||||
searchpath_t *search = searchPath;
|
||||
|
||||
if(FS_FOpenFileReadDir(filename, search, NULL, qfalse) > 0)
|
||||
{
|
||||
if(search->pack)
|
||||
{
|
||||
Com_Printf("File \"%s\" found in \"%s\"\n", filename, search->pack->pakFilename);
|
||||
return qtrue;
|
||||
}
|
||||
else if(search->dir)
|
||||
{
|
||||
Com_Printf( "File \"%s\" found at \"%s\"\n", filename, search->dir->fullpath);
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
FS_Which_f
|
||||
|
@ -2548,16 +2770,8 @@ FS_Which_f
|
|||
*/
|
||||
void FS_Which_f( void ) {
|
||||
searchpath_t *search;
|
||||
char *netpath;
|
||||
pack_t *pak;
|
||||
fileInPack_t *pakFile;
|
||||
directory_t *dir;
|
||||
long hash;
|
||||
FILE *temp;
|
||||
char *filename;
|
||||
char buf[ MAX_OSPATH ];
|
||||
|
||||
hash = 0;
|
||||
filename = Cmd_Argv(1);
|
||||
|
||||
if ( !filename[0] ) {
|
||||
|
@ -2571,39 +2785,12 @@ void FS_Which_f( void ) {
|
|||
}
|
||||
|
||||
// just wants to see if file is there
|
||||
for ( search = fs_searchpaths ; search ; search = search->next ) {
|
||||
if ( search->pack ) {
|
||||
hash = FS_HashFileName(filename, search->pack->hashSize);
|
||||
}
|
||||
// is the element a pak file?
|
||||
if ( search->pack && search->pack->hashTable[hash] ) {
|
||||
// look through all the pak file elements
|
||||
pak = search->pack;
|
||||
pakFile = pak->hashTable[hash];
|
||||
do {
|
||||
// case and separator insensitive comparisons
|
||||
if ( !FS_FilenameCompare( pakFile->name, filename ) ) {
|
||||
// found it!
|
||||
Com_Printf( "File \"%s\" found in \"%s\"\n", filename, pak->pakFilename );
|
||||
for(search = fs_searchpaths; search; search = search->next)
|
||||
{
|
||||
if(FS_Which(filename, search))
|
||||
return;
|
||||
}
|
||||
pakFile = pakFile->next;
|
||||
} while(pakFile != NULL);
|
||||
} else if ( search->dir ) {
|
||||
dir = search->dir;
|
||||
|
||||
netpath = FS_BuildOSPath( dir->path, dir->gamedir, filename );
|
||||
temp = fopen (netpath, "rb");
|
||||
if ( !temp ) {
|
||||
continue;
|
||||
}
|
||||
fclose(temp);
|
||||
Com_sprintf( buf, sizeof( buf ), "%s/%s", dir->path, dir->gamedir );
|
||||
FS_ReplaceSeparators( buf );
|
||||
Com_Printf( "File \"%s\" found at \"%s\"\n", filename, buf );
|
||||
return;
|
||||
}
|
||||
}
|
||||
Com_Printf("File not found: \"%s\"\n", filename);
|
||||
return;
|
||||
}
|
||||
|
@ -2634,7 +2821,7 @@ void FS_AddGameDirectory( const char *path, const char *dir ) {
|
|||
int i;
|
||||
searchpath_t *search;
|
||||
pack_t *pak;
|
||||
char *pakfile;
|
||||
char curpath[MAX_OSPATH + 1], *pakfile;
|
||||
int numfiles;
|
||||
char **pakfiles;
|
||||
|
||||
|
@ -2647,22 +2834,11 @@ void FS_AddGameDirectory( const char *path, const char *dir ) {
|
|||
|
||||
Q_strncpyz( fs_gamedir, dir, sizeof( fs_gamedir ) );
|
||||
|
||||
//
|
||||
// add the directory to the search path
|
||||
//
|
||||
search = Z_Malloc (sizeof(searchpath_t));
|
||||
search->dir = Z_Malloc( sizeof( *search->dir ) );
|
||||
|
||||
Q_strncpyz( search->dir->path, path, sizeof( search->dir->path ) );
|
||||
Q_strncpyz( search->dir->gamedir, dir, sizeof( search->dir->gamedir ) );
|
||||
search->next = fs_searchpaths;
|
||||
fs_searchpaths = search;
|
||||
|
||||
// find all pak files in this directory
|
||||
pakfile = FS_BuildOSPath( path, dir, "" );
|
||||
pakfile[ strlen(pakfile) - 1 ] = 0; // strip the trailing slash
|
||||
Q_strncpyz(curpath, FS_BuildOSPath(path, dir, ""), sizeof(curpath));
|
||||
curpath[strlen(curpath) - 1] = '\0'; // strip the trailing slash
|
||||
|
||||
pakfiles = Sys_ListFiles( pakfile, ".pk3", NULL, &numfiles, qfalse );
|
||||
pakfiles = Sys_ListFiles(curpath, ".pk3", NULL, &numfiles, qfalse);
|
||||
|
||||
qsort( pakfiles, numfiles, sizeof(char*), paksort );
|
||||
|
||||
|
@ -2670,8 +2846,10 @@ void FS_AddGameDirectory( const char *path, const char *dir ) {
|
|||
pakfile = FS_BuildOSPath( path, dir, pakfiles[i] );
|
||||
if ( ( pak = FS_LoadZipFile( pakfile, pakfiles[i] ) ) == 0 )
|
||||
continue;
|
||||
|
||||
Q_strncpyz(pak->pakPathname, curpath, sizeof(pak->pakPathname));
|
||||
// store the game name for downloading
|
||||
strcpy(pak->pakGamename, dir);
|
||||
Q_strncpyz(pak->pakGamename, dir, sizeof(pak->pakGamename));
|
||||
|
||||
fs_packFiles += pak->numfiles;
|
||||
|
||||
|
@ -2683,6 +2861,19 @@ void FS_AddGameDirectory( const char *path, const char *dir ) {
|
|||
|
||||
// done
|
||||
Sys_FreeFileList( pakfiles );
|
||||
|
||||
//
|
||||
// add the directory to the search path
|
||||
//
|
||||
search = Z_Malloc (sizeof(searchpath_t));
|
||||
search->dir = Z_Malloc( sizeof( *search->dir ) );
|
||||
|
||||
Q_strncpyz(search->dir->path, path, sizeof(search->dir->path));
|
||||
Q_strncpyz(search->dir->fullpath, curpath, sizeof(search->dir->fullpath));
|
||||
Q_strncpyz(search->dir->gamedir, dir, sizeof(search->dir->gamedir));
|
||||
|
||||
search->next = fs_searchpaths;
|
||||
fs_searchpaths = search;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -614,7 +614,7 @@ qboolean FS_FileExists( const char *file );
|
|||
|
||||
qboolean FS_CreatePath (char *OSPath);
|
||||
|
||||
char *FS_FindDll( const char *filename );
|
||||
vmInterpret_t FS_FindVM(void **startSearch, char *found, int foundlen, const char *name, int enableDll);
|
||||
|
||||
char *FS_BuildOSPath( const char *base, const char *game, const char *qpath );
|
||||
qboolean FS_CompareZipChecksum(const char *zipfile);
|
||||
|
@ -630,9 +630,9 @@ fileHandle_t FS_FCreateOpenPipeFile( const char *filename );
|
|||
// will properly create any needed paths and deal with seperater character issues
|
||||
|
||||
fileHandle_t FS_SV_FOpenFileWrite( const char *filename );
|
||||
int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
|
||||
long FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
|
||||
void FS_SV_Rename( const char *from, const char *to );
|
||||
int FS_FOpenFileRead( const char *qpath, fileHandle_t *file, qboolean uniqueFILE );
|
||||
long FS_FOpenFileRead( const char *qpath, fileHandle_t *file, qboolean uniqueFILE );
|
||||
// if uniqueFILE is true, then a new FILE will be fopened even if the file
|
||||
// is found in an already open pak file. If uniqueFILE is false, you must call
|
||||
// FS_FCloseFile instead of fclose, otherwise the pak FILE would be improperly closed
|
||||
|
@ -651,7 +651,8 @@ int FS_Read( void *buffer, int len, fileHandle_t f );
|
|||
void FS_FCloseFile( fileHandle_t f );
|
||||
// note: you can't just fclose from another DLL, due to MS libc issues
|
||||
|
||||
int FS_ReadFile( const char *qpath, void **buffer );
|
||||
long FS_ReadFileDir(const char *qpath, void *searchPath, void **buffer);
|
||||
long FS_ReadFile(const char *qpath, void **buffer);
|
||||
// returns the length of the file
|
||||
// a null buffer will just return the file length without loading
|
||||
// as a quick check for existance. -1 length == not present
|
||||
|
@ -668,7 +669,7 @@ void FS_FreeFile( void *buffer );
|
|||
void FS_WriteFile( const char *qpath, const void *buffer, int size );
|
||||
// writes a complete file, creating any subdirectories needed
|
||||
|
||||
int FS_filelength( fileHandle_t f );
|
||||
long FS_filelength(fileHandle_t f);
|
||||
// doesn't work for files that are opened from a pack file
|
||||
|
||||
int FS_FTell( fileHandle_t f );
|
||||
|
@ -726,6 +727,7 @@ void FS_FilenameCompletion( const char *dir, const char *ext,
|
|||
qboolean stripExt, void(*callback)(const char *s), qboolean allowNonPureFilesOnDisk );
|
||||
|
||||
const char *FS_GetCurrentGameDir(void);
|
||||
qboolean FS_Which(const char *filename, void *searchPath);
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
|
|
@ -377,15 +377,20 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) {
|
|||
// load the image
|
||||
Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name );
|
||||
Com_Printf( "Loading vm file %s...\n", filename );
|
||||
length = FS_ReadFile( filename, &header.v );
|
||||
|
||||
length = FS_ReadFileDir(filename, vm->searchPath, &header.v);
|
||||
|
||||
if ( !header.h ) {
|
||||
Com_Printf( "Failed.\n" );
|
||||
VM_Free( vm );
|
||||
|
||||
Com_Printf(S_COLOR_YELLOW "Warning: Couldn't open VM file %s\n", filename);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// show where the qvm was loaded from
|
||||
Cmd_ExecuteString( va( "which %s\n", filename ) );
|
||||
FS_Which(filename, vm->searchPath);
|
||||
|
||||
if( LittleLong( header.h->vmMagic ) == VM_MAGIC_VER2 ) {
|
||||
Com_Printf( "...which has vmMagic VM_MAGIC_VER2\n" );
|
||||
|
@ -400,9 +405,13 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) {
|
|||
|| header.h->bssLength < 0
|
||||
|| header.h->dataLength < 0
|
||||
|| header.h->litLength < 0
|
||||
|| header.h->codeLength <= 0 ) {
|
||||
|| header.h->codeLength <= 0 )
|
||||
{
|
||||
VM_Free(vm);
|
||||
Com_Error( ERR_FATAL, "%s has bad header", filename );
|
||||
FS_FreeFile(header.v);
|
||||
|
||||
Com_Printf(S_COLOR_YELLOW "Warning: %s has bad header\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
} else if( LittleLong( header.h->vmMagic ) == VM_MAGIC ) {
|
||||
// byte swap the header
|
||||
|
@ -415,14 +424,21 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) {
|
|||
if ( header.h->bssLength < 0
|
||||
|| header.h->dataLength < 0
|
||||
|| header.h->litLength < 0
|
||||
|| header.h->codeLength <= 0 ) {
|
||||
|| header.h->codeLength <= 0 )
|
||||
{
|
||||
VM_Free(vm);
|
||||
Com_Error( ERR_FATAL, "%s has bad header", filename );
|
||||
FS_FreeFile(header.v);
|
||||
|
||||
Com_Printf(S_COLOR_YELLOW "Warning: %s has bad header\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
VM_Free( vm );
|
||||
Com_Error( ERR_FATAL, "%s does not have a recognisable "
|
||||
"magic number in its header", filename );
|
||||
FS_FreeFile(header.v);
|
||||
|
||||
Com_Printf(S_COLOR_YELLOW "Warning: %s does not have a recognisable "
|
||||
"magic number in its header\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// round up to next power of 2 so all data operations can
|
||||
|
@ -524,7 +540,9 @@ vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
|
|||
vmInterpret_t interpret ) {
|
||||
vm_t *vm;
|
||||
vmHeader_t *header;
|
||||
int i, remaining;
|
||||
int i, remaining, retval;
|
||||
char filename[MAX_OSPATH];
|
||||
void *startSearch = NULL;
|
||||
|
||||
if ( !module || !module[0] || !systemCalls ) {
|
||||
Com_Error( ERR_FATAL, "VM_Create: bad parms" );
|
||||
|
@ -554,24 +572,40 @@ vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
|
|||
vm = &vmTable[i];
|
||||
|
||||
Q_strncpyz(vm->name, module, sizeof(vm->name));
|
||||
vm->systemCall = systemCalls;
|
||||
|
||||
if ( interpret == VMI_NATIVE ) {
|
||||
// try to load as a system dll
|
||||
Com_Printf( "Loading dll file %s.\n", vm->name );
|
||||
vm->dllHandle = Sys_LoadDll( module, &vm->entryPoint, VM_DllSyscall );
|
||||
if ( vm->dllHandle ) {
|
||||
do
|
||||
{
|
||||
retval = FS_FindVM(&startSearch, filename, sizeof(filename), module, (interpret == VMI_NATIVE));
|
||||
|
||||
if(retval == VMI_NATIVE)
|
||||
{
|
||||
Com_Printf("Try loading dll file %s\n", filename);
|
||||
|
||||
vm->dllHandle = Sys_LoadDll(filename, &vm->entryPoint, VM_DllSyscall);
|
||||
|
||||
if(vm->dllHandle)
|
||||
{
|
||||
vm->systemCall = systemCalls;
|
||||
return vm;
|
||||
}
|
||||
|
||||
Com_Printf( "Failed to load dll, looking for qvm.\n" );
|
||||
interpret = VMI_COMPILED;
|
||||
Com_Printf("Failed loading dll, trying next\n");
|
||||
}
|
||||
else if(retval == VMI_COMPILED)
|
||||
{
|
||||
vm->searchPath = startSearch;
|
||||
if((header = VM_LoadQVM(vm, qtrue)))
|
||||
break;
|
||||
|
||||
// load the image
|
||||
if( !( header = VM_LoadQVM( vm, qtrue ) ) ) {
|
||||
return NULL;
|
||||
// VM_Free overwrites the name on failed load
|
||||
Q_strncpyz(vm->name, module, sizeof(vm->name));
|
||||
}
|
||||
} while(retval >= 0);
|
||||
|
||||
if(retval < 0)
|
||||
return NULL;
|
||||
|
||||
vm->systemCall = systemCalls;
|
||||
|
||||
// allocate space for the jump targets, which will be filled in by the compile/prep functions
|
||||
vm->instructionCount = header->instructionCount;
|
||||
|
|
|
@ -142,6 +142,7 @@ struct vm_s {
|
|||
//------------------------------------
|
||||
|
||||
char name[MAX_QPATH];
|
||||
void *searchPath; // hint for FS_ReadFileDir()
|
||||
|
||||
// for dynamic linked modules
|
||||
void *dllHandle;
|
||||
|
|
|
@ -147,7 +147,7 @@ typedef struct {
|
|||
// a -1 return means the file does not exist
|
||||
// NULL can be passed for buf to just determine existance
|
||||
int (*FS_FileIsInPAK)( const char *name, int *pCheckSum );
|
||||
int (*FS_ReadFile)( const char *name, void **buf );
|
||||
long (*FS_ReadFile)( const char *name, void **buf );
|
||||
void (*FS_FreeFile)( void *buf );
|
||||
char ** (*FS_ListFiles)( const char *name, const char *extension, int *numfilesfound );
|
||||
void (*FS_FreeFileList)( char **filelist );
|
||||
|
|
|
@ -412,35 +412,23 @@ void Sys_UnloadDll( void *dllHandle )
|
|||
Sys_LoadDll
|
||||
|
||||
Used to load a development dll instead of a virtual machine
|
||||
#1 look in fs_homepath
|
||||
#2 look in fs_basepath
|
||||
=================
|
||||
*/
|
||||
void * QDECL Sys_LoadDll( const char *name,
|
||||
void *Sys_LoadDll(const char *name,
|
||||
intptr_t (QDECL **entryPoint)(int, ...),
|
||||
intptr_t (*systemcalls)(intptr_t, ...))
|
||||
{
|
||||
void *libHandle;
|
||||
void (*dllEntry)(intptr_t (*syscallptr)(intptr_t, ...));
|
||||
char fname[MAX_OSPATH];
|
||||
char *netpath;
|
||||
|
||||
assert(name);
|
||||
|
||||
Com_sprintf(fname, sizeof(fname), "%s" ARCH_STRING DLL_EXT, name);
|
||||
Com_Printf( "Loading DLL file: %s\n", name);
|
||||
libHandle = Sys_LoadLibrary(name);
|
||||
|
||||
netpath = FS_FindDll(fname);
|
||||
|
||||
if(!netpath) {
|
||||
Com_Printf( "Sys_LoadDll(%s) could not find it\n", fname );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Com_Printf( "Loading DLL file: %s\n", netpath);
|
||||
libHandle = Sys_LoadLibrary(netpath);
|
||||
|
||||
if(!libHandle) {
|
||||
Com_Printf( "Sys_LoadDll(%s) failed:\n\"%s\"\n", netpath, Sys_LibraryError() );
|
||||
if(!libHandle)
|
||||
{
|
||||
Com_Printf("Sys_LoadDll(%s) failed:\n\"%s\"\n", name, Sys_LibraryError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue