Beispiel #1
0
/*
============
FS_ExistsInGameDir

See if a file exists in the mod directory/paks (ignores baseq2)
============
*/
qboolean FS_ExistsInGameDir (char *filename)
{
	size_t			len;
	char			*gamedir;
	char			lowered[MAX_QPATH];
	searchpath_t	*search;
	pack_t			*pak;

	Q_strncpy (lowered, filename, sizeof(lowered)-1);
	fast_strlwr (lowered);

	gamedir = FS_Gamedir();
	len = strlen(gamedir);

	for (search = fs_searchpaths ; search ; search = search->next)
	{
		// is the element a pak file?
		if (search->pack)
		{
			packfile_t	*entry;

			//r1: optimized btree search
			pak = search->pack;

			if (strncmp (pak->filename, gamedir, len))
				continue;

			entry = rbfind (lowered, pak->rb);

			if (entry)
				return true;
		}
		else
		{
			char	netpath[MAX_OSPATH];

			if (strncmp (search->filename, gamedir, len))
				continue;

			Com_sprintf (netpath, sizeof(netpath), "%s/%s",search->filename, filename);

			if (Sys_FileLength (netpath) != -1)
				return true;
		}
	}

	return false;
}
Beispiel #2
0
/*
=================
Mod_LoadSpriteModel
=================
*/
void Mod_LoadSpriteModel (model_t *mod, void *buffer)
{
	dsprite_t	*sprin, *sprout;
	int			i;

	sprin = (dsprite_t *)buffer;
	sprout = (dsprite_t *) Hunk_Alloc (modfilelen);

	sprout->ident = LittleLong(sprin->ident);
	sprout->version = LittleLong(sprin->version);
	sprout->numframes = LittleLong(sprin->numframes);

	if (sprout->version != SPRITE_VERSION)
		VID_Error (ERR_DROP, "sprite %s has wrong version number (%i should be %i)",
				 mod->name, sprout->version, SPRITE_VERSION);

	if (sprout->numframes > MAX_MD2SKINS)
		VID_Error (ERR_DROP, "sprite %s has too many frames (%i > %i)",
				 mod->name, sprout->numframes, MAX_MD2SKINS);

	if (sprout->numframes <= 0)
		VID_Error (ERR_DROP, "sprite %s has no frames", mod->name);

	// byte swap everything
	for (i=0 ; i<sprout->numframes ; i++)
	{
		sprout->frames[i].width = LittleLong(sprin->frames[i].width);
		sprout->frames[i].height = LittleLong(sprin->frames[i].height);
		sprout->frames[i].origin_x = LittleLong(sprin->frames[i].origin_x);
		sprout->frames[i].origin_y = LittleLong(sprin->frames[i].origin_y);
		memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
		fast_strlwr (sprout->frames[i].name);
		mod->skins[i] = GL_FindImage (sprout->frames[i].name, sprout->frames[i].name, it_sprite);

		//r1: sprites crash if they don't have valid skins for framenum so be noisy
		if (!mod->skins[i])
			VID_Printf (PRINT_ALL, "GL_FindImage: Couldn't find skin '%s' for sprite '%s'\n", sprout->frames[i].name, mod->name);
	}

	mod->type = mod_sprite;
}
Beispiel #3
0
/*
=================
Mod_LoadTexinfo
=================
*/
void Mod_LoadTexinfo (lump_t *l)
{
	texinfo_t *in;
//	image_t	*last_image;
	mtexinfo_t *out, *step;
	int 	i, count;
	char	name[MAX_QPATH];
	int		next;
	size_t	length;

	in = (texinfo_t *)(mod_base + l->fileofs);
	
	if (l->filelen % sizeof(*in))
		VID_Error (ERR_DROP, "Mod_LoadTexinfo: funny lump size in %s",loadmodel->name);

	count = l->filelen / sizeof(*in);
	out = (mtexinfo_t *) Hunk_Alloc ( count*sizeof(*out));

	loadmodel->texinfo = out;
	loadmodel->numtexinfo = count;

	for ( i=0 ; i<count ; i++, in++, out++)
	{
		memcpy (out->vecs, in->vecs, sizeof(out->vecs));

		out->flags = LittleLong(in->flags);
		next = LittleLong(in->nexttexinfo);

		if (next > 0)
			out->next = loadmodel->texinfo + next;
		else
		    out->next = NULL;

		fast_strlwr (in->texture);

		out->image = GL_FindImageBase (in->texture, it_wall);

		if (out->image)
			continue;

		Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
		
		if (!GetWalInfo (name, &global_hax_texture_x, &global_hax_texture_y))
		{
			VID_Printf (PRINT_ALL, "Couldn't load %s\n", name);
			out->image = r_notexture;
			continue;
		}

		length = strlen(name);

		if (load_tga_wals)
		{
			//Com_sprintf (name, sizeof(name), "textures/%s.tga", in->texture);
			memcpy (name + length-3, "tga", 3);
			out->image = GL_FindImage (name, in->texture, it_wall);
		}
		else
		{
			out->image = NULL;
		}

		if (!out->image)
		{
			if (load_png_wals)
			{
				memcpy (name + length-3, "png", 3);
				//Com_sprintf (name, sizeof(name), "textures/%s.png", in->texture);
				out->image = GL_FindImage (name, in->texture, it_wall);
			}

			if (!out->image)
			{
				if (load_jpg_wals)
				{
					memcpy (name + length-3, "jpg", 3);
					//Com_sprintf (name, sizeof(name), "textures/%s.jpg", in->texture);
					out->image = GL_FindImage (name, in->texture, it_wall);
				}

				if (!out->image)
				{
					memcpy (name + length-3, "wal", 3);
					//Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
					out->image = GL_FindImage (name, in->texture, it_wall);
					
					if (!out->image)
					{
						VID_Printf (PRINT_ALL, "Couldn't load %s\n", name);
						out->image = r_notexture;
					}
				}
			}
		}

		//last_image = out->image;

		global_hax_texture_x = global_hax_texture_y = 0;
	}

	// count animation frames
	for (i=0 ; i<count ; i++)
	{
		out = &loadmodel->texinfo[i];
		out->numframes = 1;
		for (step = out->next ; step && step != out ; step=step->next)
			out->numframes++;
	}
}
Beispiel #4
0
/*
==================
Mod_ForName

Loads in a model for the given name
==================
*/
model_t *Mod_ForName (const char *name_, qboolean crash)
{
	model_t		*mod;
	model_t		*modelhash;
	mscache_t	*model_size;
	byte		*buf;
	int			i;
	unsigned	hash;

	size_t len = strlen(name_);
	char *name = (char *) alloca(len + 1);
	strcpy(name, name_);

	if (!name || !name[0])
		VID_Error (ERR_DROP, "Mod_ForName: NULL name");
		
	//
	// inline models are grabbed only from worldmodel
	//
	if (name[0] == '*')
	{
		i = atoi(name+1);
		if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
			VID_Error (ERR_DROP, "bad inline model number %d", i);
		return &mod_inline[i];
	}

	fast_strlwr (name);

	hash = hashify (name) % MODEL_HASH_SIZE;

	for (modelhash = models_hash[hash]; modelhash; modelhash = modelhash->hash_next)
	{
		if (!strcmp (modelhash->name, name))
		{
			return modelhash;
		}
	}

	for (model_size = model_size_cache[hash]; model_size; model_size = model_size->hash_next)
	{
		if (!strcmp (model_size->name, name))
			break;
	}

	//
	// search the currently loaded models
	//
	/*for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
	{
		if (!mod->name[0] || mod->hash != hash)
			continue;
		if (!strcmp (mod->name, name) )
			return mod;
	}*/
	
	//
	// find a free model slot spot
	//
	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
	{
		if (!mod->name[0])
			break;	// free spot
	}

	if (i == mod_numknown)
	{
		if (mod_numknown == MAX_MOD_KNOWN)
			VID_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN");
		mod_numknown++;
	}

	strncpy (mod->name, name, sizeof(mod->name)-1);

	//
	// load the file
	//
	modfilelen = FS_LoadFile (name, (void **)&buf);
	if (!buf)
	{
		if (crash)
			VID_Error (ERR_DROP, "Mod_NumForName: %s not found", mod->name);
		mod->name[0] = 0;
		return NULL;
	}
	
	loadmodel = mod;

	//
	// fill it in
	//


	// call the apropriate loader
	
	switch (LittleLong(*(unsigned *)buf))
	{
		case IDALIASHEADER:
			if (model_size)
				loadmodel->extradata = Hunk_Begin (model_size->size, model_size->size);
			else
				loadmodel->extradata = Hunk_Begin (0x200000, 0);
			Mod_LoadAliasModel (mod, buf);
			break;
			
		case IDSPRITEHEADER:
			if (model_size)
				loadmodel->extradata = Hunk_Begin (model_size->size, model_size->size);
			else
				loadmodel->extradata = Hunk_Begin (0x4000, 0);
			Mod_LoadSpriteModel (mod, buf);
			break;
		
		case IDBSPHEADER:
			if (model_size)
				loadmodel->extradata = Hunk_Begin (model_size->size, model_size->size);
			else
				loadmodel->extradata = Hunk_Begin (0x1000000, 0);
			Mod_LoadBrushModel (mod, buf);
			break;

		default:
			VID_Error (ERR_DROP,"Mod_NumForName: unknown 0x%.8x fileid for %s", LittleLong(*(unsigned *)buf), mod->name);
			break;
	}

	if (model_size)
	{
		loadmodel->extradatasize = model_size->size;
	}
	else
	{
		loadmodel->extradatasize = Hunk_End ();

		model_size = (mscache_t	*) malloc (sizeof(*model_size));
		if (!model_size)
			VID_Error (ERR_FATAL, "Mod_ForName: out of memory");
		strcpy (model_size->name, mod->name);
		model_size->size = loadmodel->extradatasize;
		model_size->hash_next = model_size_cache[hash];

		model_size_cache[hash] = model_size;
	}

	mod->hash_next = models_hash[hash];
	models_hash[hash] = mod;

	FS_FreeFile (buf);

	return mod;
}
Beispiel #5
0
/*
=================
Mod_LoadAliasModel
=================
*/
void Mod_LoadAliasModel (model_t *mod, void *buffer)
{
	unsigned int		i;
	dmdl_t				header;
	dmdl_t				*pinmodel, *pheader;
	dstvert_t			*pinst, *poutst;
	dtriangle_t			*pintri, *pouttri;
	daliasframe_t		*pinframe, *poutframe;
	int					*pincmd, *poutcmd;
	int					version;
	unsigned int		required;
	char				*skin_name;

	pinmodel = (dmdl_t *)buffer;

	version = LittleLong(pinmodel->version);
	if (version != ALIAS_VERSION)
		VID_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
				 mod->name, version, ALIAS_VERSION);

	//pheader = Hunk_Alloc (size);
	pheader = &header;
	
	// byte swap the header fields and sanity check
	memcpy (pheader, buffer, sizeof(dmdl_t));

	if (pheader->skinheight > MAX_LBM_HEIGHT)
		Com_DPrintf("model %s has a skin taller than traditional maximum of %d", mod->name,
				   MAX_LBM_HEIGHT);

	if (pheader->num_xyz <= 0)
		VID_Error (ERR_DROP, "model %s has no vertices", mod->name);

	if (pheader->num_xyz > MAX_VERTS)
		VID_Error (ERR_DROP, "model %s has too many vertices", mod->name);

	if (pheader->num_st <= 0)
		VID_Error (ERR_DROP, "model %s has no st vertices", mod->name);

	if (pheader->num_tris <= 0)
		VID_Error (ERR_DROP, "model %s has no triangles", mod->name);

	if (pheader->num_frames <= 0)
		VID_Error (ERR_DROP, "model %s has no frames", mod->name);

	if (pheader->num_skins >= 31)
		VID_Error (ERR_DROP, "model %s has too many skins", mod->name);

	if (pheader->ofs_st <= 0 || pheader->ofs_frames <= 0 || pheader->ofs_glcmds <= 0 ||
		pheader->ofs_skins <= 0 || pheader->ofs_tris <= 0)
		VID_Error (ERR_DROP, "model %s has invalid offsets", mod->name);

	required = 0;

	required += sizeof(dmdl_t);

	required += pheader->num_st * sizeof(dstvert_t);
	required += pheader->num_tris * sizeof(dtriangle_t);
	required += pheader->num_frames * (sizeof(daliasframe_t)-4);

	//variable sized
	required += pheader->num_xyz * pheader->num_frames * sizeof(dtrivertx_t);

	required += pheader->num_glcmds * sizeof(int);
	required += pheader->num_skins * MAX_SKINNAME;

	if (pheader->ofs_end != required)
		VID_Error (ERR_DROP, "model %s has bad size header (%d != %d)", mod->name, pheader->ofs_end, required);

	if (pheader->ofs_frames + pheader->num_frames * sizeof(daliasframe_t) > required)
		VID_Error (ERR_DROP, "model %s has illegal frames offset", mod->name);

	if (pheader->ofs_glcmds + pheader->num_glcmds * sizeof(int) > required)
		VID_Error (ERR_DROP, "model %s has illegal glcmds offset", mod->name);
	
	if (pheader->ofs_skins + pheader->num_skins * MAX_SKINNAME > required)
		VID_Error (ERR_DROP, "model %s has illegal skins offset", mod->name);

	if (pheader->ofs_st + pheader->num_st * sizeof(dstvert_t) > required)
		VID_Error (ERR_DROP, "model %s has illegal vertices offset", mod->name);

	if (pheader->ofs_tris + pheader->num_tris * sizeof(dtriangle_t) > required)
		VID_Error (ERR_DROP, "model %s has illegal triangles offset", mod->name);

	if (pheader->framesize * pheader->num_frames != pheader->num_frames * (int)((sizeof(daliasframe_t)-4) + pheader->num_xyz*sizeof(dtrivertx_t)))
		VID_Error (ERR_DROP, "model %s has invalid frame size", mod->name);

	pheader = (dmdl_t *) Hunk_Alloc (required);
	memcpy (pheader, &header, sizeof(dmdl_t));
	//
// load base s and t vertices (not used in gl version)
//
	pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
	poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);

	memcpy (poutst, pinst, pheader->num_st * sizeof(dstvert_t));

//
// load triangle lists
//
	pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
	pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);

	memcpy (pouttri, pintri, pheader->num_tris * sizeof(dtriangle_t));

//
// load the frames
//

	for (i=0 ; i<pheader->num_frames ; i++)
	{
		pinframe = (daliasframe_t *) ((byte *)pinmodel 
			+ pheader->ofs_frames + i * pheader->framesize);
		poutframe = (daliasframe_t *) ((byte *)pheader 
			+ pheader->ofs_frames + i * pheader->framesize);

		memcpy (poutframe, pinframe, sizeof(daliasframe_t)-4);
		memcpy (poutframe->verts, pinframe->verts, pheader->num_xyz*sizeof(dtrivertx_t));
	}

	mod->type = mod_alias;

	//
	// load the glcmds
	//
	pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
	poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);

	memcpy (poutcmd, pincmd, pheader->num_glcmds * sizeof(int));


	// register all skins
	memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
		pheader->num_skins*MAX_SKINNAME);

	for (i=0 ; i<pheader->num_skins ; i++)
	{
		skin_name = (char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME;
		fast_strlwr (skin_name);
		mod->skins[i] = GL_FindImage (skin_name, skin_name, it_skin);
	}

	mod->mins[0] = -32;
	mod->mins[1] = -32;
	mod->mins[2] = -32;

	mod->maxs[0] = 32;
	mod->maxs[1] = 32;
	mod->maxs[2] = 32;
}
Beispiel #6
0
/*
=================
FS_LoadPackFile

Takes an explicit (not game tree related) path to a pak file.

Loads the header and directory, adding the files at the beginning
of the list so they override previous pack files.
=================
*/
static pack_t /*@null@*/ *FS_LoadPackFile (const char *packfile, const char *ext)
{
	
	int				i;
	void			**newitem;
	pack_t			*pack = NULL;
	packfile_t		*info;

	if (!strcmp (ext, "pak"))
	{
		unsigned		pakLen;
		int				numpackfiles;
		FILE			*packhandle;
		dpackheader_t	header;

		packhandle = fopen(packfile, "rb");

		if (!packhandle)
			return NULL;

		fseek (packhandle, 0, SEEK_END);
		pakLen = ftell (packhandle);
		rewind (packhandle);

		if (fread (&header, sizeof(header), 1, packhandle) != 1)
			Com_Error (ERR_FATAL, "FS_LoadPackFile: Couldn't read pak header from %s", packfile);

		if (LittleLong(header.ident) != IDPAKHEADER)
			Com_Error (ERR_FATAL, "FS_LoadPackFile: %s is not a valid pak file.", packfile);
		
	#if YOU_HAVE_A_BROKEN_COMPUTER
		header.dirofs = LittleLong (header.dirofs);
		header.dirlen = LittleLong (header.dirlen);
	#endif

		if (header.dirlen % sizeof(packfile_t))
			Com_Error (ERR_FATAL, "FS_LoadPackFile: Bad pak file %s (directory length %u is not a multiple of %d)", packfile, header.dirlen, (int)sizeof(packfile_t));

		numpackfiles = header.dirlen / sizeof(packfile_t);

		if (numpackfiles > MAX_FILES_IN_PACK)
			//Com_Error (ERR_FATAL, "FS_LoadPackFile: packfile %s has %i files (max allowed %d)", packfile, numpackfiles, MAX_FILES_IN_PACK);
			Com_Printf ("WARNING: Pak file %s has %i files (max allowed %d) - may not be compatible with other clients\n", LOG_GENERAL, packfile, numpackfiles, MAX_FILES_IN_PACK);

		if (!numpackfiles)
		{
			fclose (packhandle);
			Com_Printf ("WARNING: Empty packfile %s\n", LOG_GENERAL|LOG_WARNING, packfile);
			return NULL;
		}

		//newfiles = Z_TagMalloc (numpackfiles * sizeof(packfile_t), TAGMALLOC_FSLOADPAK);
		info = Z_TagMalloc (numpackfiles * sizeof(packfile_t), TAGMALLOC_FSLOADPAK);

		if (fseek (packhandle, header.dirofs, SEEK_SET))
			Com_Error (ERR_FATAL, "FS_LoadPackFile: fseek() to offset %u in %s failed. Pak file is possibly corrupt.", header.dirofs, packfile);

		if ((int)fread (info, 1, header.dirlen, packhandle) != header.dirlen)
			Com_Error (ERR_FATAL, "FS_LoadPackFile: Error reading packfile directory from %s (failed to read %u bytes at %u). Pak file is possibly corrupt.", packfile, header.dirofs, header.dirlen);

		pack = Z_TagMalloc (sizeof (pack_t), TAGMALLOC_FSLOADPAK);
		pack->type = PAK_QUAKE;
		pack->rb = rbinit ((int (EXPORT *)(const void *, const void *))strcmp, numpackfiles);

		//entry = Z_TagMalloc (sizeof(packfile_t) * numpackfiles, TAGMALLOC_FSLOADPAK);

		for (i=0 ; i<numpackfiles ; i++)
		{
			fast_strlwr (info[i].name);
#if YOU_HAVE_A_BROKEN_COMPUTER
			info[i].filepos = LittleLong(info[i].filepos);
			info[i].filelen = LittleLong(info[i].filelen);
#endif
			if (info[i].filepos + info[i].filelen >= pakLen)
				Com_Error (ERR_FATAL, "FS_LoadPackFile: File '%.64s' in pak file %s has illegal offset %u past end of file %u. Pak file is possibly corrupt.", MakePrintable (info[i].name, 0), packfile, info[i].filepos, pakLen);
			
			newitem = rbsearch (info[i].name, pack->rb);
			*newitem = &info[i];
		}

		Q_strncpy (pack->filename, packfile, sizeof(pack->filename)-1);

		pack->h.handle = packhandle;
		pack->numfiles = numpackfiles;

		Com_Printf ("Added packfile %s (%i files)\n", LOG_GENERAL,  packfile, numpackfiles);
	}
#ifndef NO_ZLIB
	else if (!strcmp (ext, "pkz"))
	{
		unzFile			f;
		unz_global_info	zipinfo;
		char			zipFileName[56];
		unz_file_info	fileInfo;

		f = unzOpen (packfile);
		if (!f)
			return NULL;

		if (unzGetGlobalInfo (f, &zipinfo) != UNZ_OK)
			Com_Error (ERR_FATAL, "FS_LoadPackFile: Couldn't read .zip info from '%s'", packfile);

		info = Z_TagMalloc (zipinfo.number_entry * sizeof(*info), TAGMALLOC_FSLOADPAK);

		pack = Z_TagMalloc (sizeof (pack_t), TAGMALLOC_FSLOADPAK);
		pack->type = PAK_ZIP;
		pack->rb = rbinit ((int (EXPORT *)(const void *, const void *))strcmp, zipinfo.number_entry);

		if (unzGoToFirstFile (f) != UNZ_OK)
			Com_Error (ERR_FATAL, "FS_LoadPackFile: Couldn't seek to first .zip file in '%s'", packfile);

		zipFileName[sizeof(zipFileName)-1] = 0;
		i = 0;
		do
		{
			if (unzGetCurrentFileInfo (f, &fileInfo, zipFileName, sizeof(zipFileName)-1, NULL, 0, NULL, 0) == UNZ_OK)
			{
				//directory, ignored
				if (fileInfo.external_fa & 16)
					continue;
				strcpy (info[i].name, zipFileName);
				info[i].filepos = unzGetOffset (f);
				info[i].filelen = fileInfo.uncompressed_size;
				newitem = rbsearch (info[i].name, pack->rb);
				*newitem = &info[i];
				i++;
			}
		} while (unzGoToNextFile (f) == UNZ_OK);

		pack->h.zhandle = f;
		Com_Printf ("Added zpackfile %s (%i files)\n", LOG_GENERAL,  packfile, i);
	}
#endif
	else
	{
		Com_Error (ERR_FATAL, "FS_LoadPackFile: Unknown type %s", ext);
	}

	return pack;
}
Beispiel #7
0
int EXPORT FS_FOpenFile (const char *filename, FILE **file, handlestyle_t openHandle, qboolean *closeHandle)
{
	fscache_t		*cache;
	searchpath_t	*search;
	pack_t			*pak;
	filelink_t		*link;
	char			netpath[MAX_OSPATH];
	char			lowered[MAX_QPATH];

	// check for links firstal
	if (!fs_noextern->intvalue)
	{
		for (link = fs_links ; link ; link=link->next)
		{
			if (!strncmp (filename, link->from, link->fromlength))
			{
				Com_sprintf (netpath, sizeof(netpath), "%s%s",link->to, filename+link->fromlength);
				if (openHandle != HANDLE_NONE)
				{
					*file = fopen (netpath, "rb");
					if (*file)
					{	
						Com_DPrintf ("link file: %s\n",netpath);
						*closeHandle = true;
						return FS_filelength (*file);
					}
					return -1;
				}
				else
				{
					return Sys_FileLength (netpath);
				}
			}
		}
	}

#ifdef BTREE_SEARCH
	cache = rbfind (filename, rb);
	if (cache)
	{
		cache = *(fscache_t **)cache;
		if (cache->filepath[0] == 0)
		{
			*file = NULL;
			return -1;
		}
#ifdef _DEBUG
		Com_DPrintf ("File '%s' found in cache: %s\n", filename, cache->filepath);
#endif
		if (openHandle != HANDLE_NONE)
		{
			if (cache->pak)
			{
				if (openHandle == HANDLE_DUPE)
				{
					*file = fopen (cache->pak->filename, "rb");
					if (!*file)
					{
						Com_Printf ("WARNING: Cached pak '%s' failed to open! Did you delete it?\n", LOG_WARNING|LOG_GENERAL, cache->pak->filename);
						rbdelete (filename, rb);
						return -1;
					}
					*closeHandle = true;
				}
				else
				{
					*file = cache->pak->h.handle;
					*closeHandle = false;
				}
			}
			else
			{
				*file = fopen (cache->filepath, "rb");
				if (!*file)
				{
					Com_Printf ("WARNING: Cached file '%s' failed to open! Did you delete it?\n", LOG_WARNING|LOG_GENERAL, cache->filepath);
					rbdelete (filename, rb);
					return -1;
				}
					//Com_Error (ERR_FATAL, "Couldn't open %s (cached)", cache->filepath);	

				*closeHandle = true;
			}
			if (cache->fileseek && fseek (*file, cache->fileseek, SEEK_SET))
				Com_Error (ERR_FATAL, "Couldn't seek to offset %u in %s (cached)", cache->fileseek, cache->filepath);
		}
		return cache->filelen;
	}

#elif HASH_CACHE
	hash = hashify (filename);

	cache = &fscache;

	while (cache->next)
	{ 
		cache = cache->next;
		if (cache->hash == hash && !Q_stricmp (cache->filename, filename))
		{
			Com_Printf (" (cached) ", LOG_GENERAL);
			if (cache->filepath[0] == 0)
			{
				*file = NULL;
				return -1;
			}
			*file = fopen (cache->filepath, "rb");
			if (!*file)
				Com_Error (ERR_FATAL, "Couldn't open %s", cache->filepath);	
			fseek (*file, cache->fileseek, SEEK_SET);
			return cache->filelen;
		}
	}
#elif MAGIC_BTREE
	{
		magic_t *magic;

		hash = hashify (filename);

		magic = rbfind ((void *)hash, rb);
		if (magic)
		{
			magic = *(magic_t **)magic;

			do
			{
				cache = magic->entry;
				if (!Q_stricmp (cache->filename, filename))
				{
					if (cache->filepath[0] == 0)
					{
						*file = NULL;
						return -1;
					}
					*file = fopen (cache->filepath, "rb");
					if (!*file)
						Com_Error (ERR_FATAL, "Couldn't open %s", cache->filepath);	
					fseek (*file, cache->fileseek, SEEK_SET);
					return cache->filelen;
				}

				magic = magic->next;
			} while (magic);
		}
	}
#endif

#ifdef _DEBUG
	Com_DPrintf ("File '%s' not found in cache, searching fs_searchpaths\n", filename);
#endif

	Q_strncpy (lowered, filename, sizeof(lowered)-1);
	fast_strlwr (lowered);

	for (search = fs_searchpaths ; search ; search = search->next)
	{
		// is the element a pak file?
		if (search->pack)
		{
//			char		*lower;
			packfile_t	*entry;

			//r1: optimized btree search
			pak = search->pack;

			if (pak->type == PAK_QUAKE)
			{
				entry = rbfind (lowered, pak->rb);

				if (entry)
				{
					entry = *(packfile_t **)entry;

	#ifdef _DEBUG
					Com_DPrintf ("File '%s' found in %s, (%s)\n", filename, pak->filename, entry->name);
	#endif
					if (openHandle != HANDLE_NONE)
					{
						//*file = fopen (pak->filename, "rb");
						if (openHandle == HANDLE_DUPE)
						{
							*file = fopen (pak->filename, "rb");
							*closeHandle = true;	
						}
						else
						{
							*file = pak->h.handle;
							*closeHandle = false;
						}
						//if (!*file)
						//	Com_Error (ERR_FATAL, "Couldn't reopen pak file %s", pak->filename);	

						if (fseek (*file, entry->filepos, SEEK_SET))
							Com_Error (ERR_FATAL, "Couldn't seek to offset %u for %s in %s", entry->filepos, entry->name, pak->filename);
					}

					if (fs_cache->intvalue & 1)
					{
	#if BTREE_SEARCH
						FS_AddToCache (pak->filename, entry->filelen, entry->filepos, filename, pak);
	#elif HASH_CACHE
						FS_AddToCache (hash, pak->filename, entry->filelen, entry->filepos, cache, filename);
	#elif MAGIC_BTREE
						FS_AddToCache (pak->filename, entry->filelen, entry->filepos, filename, hash);
	#endif
					}

					return entry->filelen;
				}
			}
		}
		else if (!fs_noextern->intvalue)
		{
			struct stat	statInfo;
			int filelen;
			// check a file in the directory tree
			
			Com_sprintf (netpath, sizeof(netpath), "%s/%s",search->filename, filename);

			if (openHandle == HANDLE_NONE)
			{
				filelen = Sys_FileLength (netpath);
				if (filelen == -1)
					continue;
				
				if (fs_cache->intvalue & 4)
					FS_AddToCache (netpath, filelen, 0, filename, NULL);

				return filelen;
			}

			//fix for moronic implementations that allow fopen (FILE OPEN) to open a directory
			//(this means you linux and krew)
			if (stat (netpath, &statInfo))
				continue;

			if (statInfo.st_mode & S_IFDIR)
			{
				Com_Printf ("WARNING: Tried to open a directory as a file: %s\n", LOG_WARNING, netpath);
				continue;
			}

			*file = fopen (netpath, "rb");

			if (!*file)
				continue;

			*closeHandle = true;
			
			Com_DPrintf ("FindFile: %s\n",netpath);

			filelen = FS_filelength (*file);
			if (fs_cache->intvalue & 4)
			{
#if BTREE_SEARCH
				FS_AddToCache (netpath, filelen, 0, filename, NULL);
#elif HASH_CACHE
				FS_AddToCache (hash, netpath, filelen, 0, cache, filename);
#elif MAGIC_BTREE
				FS_AddToCache (netpath, filelen, 0, filename, hash);
#endif
			}
			return filelen;
		}
		
	}
	
	Com_DPrintf ("FindFile: can't find %s\n", filename);

	if (fs_cache->intvalue & 2)
	{
#if BTREE_SEARCH
		FS_AddToCache (NULL, 0, 0, filename, NULL);
#elif HASH_CACHE
		FS_AddToCache (hash, NULL, 0, 0, cache, filename);
#elif MAGIC_BTREE
		FS_AddToCache (NULL, 0, 0, filename, hash);
#endif
	}
	
	*file = NULL;
	return -1;
}
Beispiel #8
0
void FS_WhereIs_f (void)
{
	char			*filename;
	searchpath_t	*search;
	pack_t			*pak;
	filelink_t		*link;
	char			netpath[MAX_OSPATH];
	char			lowered[MAX_QPATH];

	if (Cmd_Argc() != 2)
	{
		Com_Printf ("Purpose: Find where a file is being loaded from on the filesystem.\n"
					"Syntax : whereis <path>\n"
					"Example: whereis maps/q2dm1.bsp\n", LOG_GENERAL);
		return;
	}

	filename = Cmd_Argv(1);

	// check for links firstal
	if (!fs_noextern->intvalue)
	{
		for (link = fs_links ; link ; link=link->next)
		{
			if (!strncmp (filename, link->from, link->fromlength))
			{
				int	len;
				Com_sprintf (netpath, sizeof(netpath), "%s%s",link->to, filename+link->fromlength);
				len = Sys_FileLength (netpath);
				if (len != -1)
				{
					Com_Printf ("%s is found on disk as %s (using linkpath), %d bytes.\n", LOG_GENERAL, Cmd_Argv(1), netpath, len);
				}
				else
				{
					Com_Printf ("%s is not found.\n", LOG_GENERAL, Cmd_Argv(1));
				}
				return;
			}
		}
	}

	Q_strncpy (lowered, filename, sizeof(lowered)-1);
	fast_strlwr (lowered);

	for (search = fs_searchpaths ; search ; search = search->next)
	{
		// is the element a pak file?
		if (search->pack)
		{
			packfile_t	*entry;

			//r1: optimized btree search
			pak = search->pack;

			entry = rbfind (lowered, pak->rb);

			if (entry)
			{
				entry = *(packfile_t **)entry;
				Com_Printf ("%s is found in pakfile %s as %s, %d bytes.\n", LOG_GENERAL, Cmd_Argv(1), pak->filename, entry->name, entry->filelen);
				return;
			}
		}
		else if (!fs_noextern->intvalue)
		{
			int filelen;
			// check a file in the directory tree
			
			Com_sprintf (netpath, sizeof(netpath), "%s/%s",search->filename, filename);

			filelen = Sys_FileLength (netpath);
			if (filelen == -1)
				continue;

			Com_Printf ("%s is found on disk as %s, %d bytes.\n", LOG_GENERAL, Cmd_Argv(1), netpath, filelen);
			return;
		}
	}

	Com_Printf ("%s is not found.\n", LOG_GENERAL, Cmd_Argv(1));
}