Tutorial *16*

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.



 
Sign up
Login:
Passwd:
[Remember Me]