|
Mailto: AnthonyJ@planetquake.com
The player setup
menu does not always display all the models that are installed. Many users
have identified this is being caused by free-floating files inside the
baseq2\players directory. This tutorial gives the fix for this bug (and
potentially other similar faults).
The cause of
this bug are the two functions Sys_FindFirst() and Sys_FindNext(). Here are
the two original functions (for win32 - from win32\q_shwin.c):
char *Sys_FindFirst (char *path, unsigned musthave, unsigned canthave ) { struct _finddata_t findinfo; if (findhandle) Sys_Error ("Sys_BeginFind without close"); findhandle = 0; COM_FilePath (path, findbase); findhandle = _findfirst (path, &findinfo); if (findhandle == -1) return NULL; if ( !CompareAttributes( findinfo.attrib, musthave, canthave ) ) return NULL; Com_sprintf (findpath, sizeof(findpath), "%s/%s", findbase, findinfo.name); return findpath; } char *Sys_FindNext ( unsigned musthave, unsigned canthave ) { struct _finddata_t findinfo; if (findhandle == -1) return NULL; if (_findnext (findhandle, &findinfo) == -1) return NULL; if ( !CompareAttributes( findinfo.attrib, musthave, canthave ) ) return NULL; Com_sprintf (findpath, sizeof(findpath), "%s/%s", findbase, findinfo.name); return findpath; } |
|
You will
notice that if a file fails the attribute test in CompareAttributes, these
functions will not continue to search for further matching files. This is the
cause of this bug, since the player menu calls FS_ListFiles() requesting only
directories be listed - so when Sys_FindNext hits a file, it will stop even
if there are further directories yet to be enumerated.
To fix this bug,
simply replace these two functions with ones that loop in the case of failed
attribute test - for example:
char *Sys_FindFirst (char *path, unsigned musthave, unsigned canthave ) { struct _finddata_t findinfo; if (findhandle) Sys_Error ("Sys_BeginFind without close"); findhandle = 0; COM_FilePath (path, findbase); findhandle = _findfirst(path, &findinfo); while ((findhandle != -1)) { if (CompareAttributes(findinfo.attrib, musthave, canthave)) { Com_sprintf (findpath, sizeof(findpath), "%s/%s", findbase, findinfo.name); return findpath; } else if (_findnext(findhandle, &findinfo) == -1) { _findclose(findhandle); findhandle = -1; } } return NULL; } char *Sys_FindNext ( unsigned musthave, unsigned canthave ) { struct _finddata_t findinfo; if (findhandle == -1) return NULL; while (_findnext(findhandle, &findinfo) != -1) { if (CompareAttributes(findinfo.attrib, musthave, canthave)) { Com_sprintf (findpath, sizeof(findpath), "%s/%s", findbase, findinfo.name); return findpath; } } return NULL; } |
|
It is perhaps
worth noting that this bug does not affect unix based implementations of quake2,
since the implementation of these functions is only incorrect in the win32
versions of these files.
|