DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

w_wad.cpp (9973B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #include "Precompiled.h"
     30 #include "globaldata.h"
     31 
     32 
     33 #include <ctype.h>
     34 #include <sys/types.h>
     35 #include <string.h>
     36 #include <fcntl.h>
     37 #include <sys/stat.h>
     38 #include <vector>
     39 
     40 #include "doomtype.h"
     41 #include "m_swap.h"
     42 #include "i_system.h"
     43 #include "z_zone.h"
     44 
     45 #include "idlib/precompiled.h"
     46 
     47 #ifdef __GNUG__
     48 #pragma implementation "w_wad.h"
     49 #endif
     50 #include "w_wad.h"
     51 
     52 
     53 
     54 //
     55 // GLOBALS
     56 //
     57 
     58 lumpinfo_t*	lumpinfo = NULL;
     59 int			numlumps;
     60 void**		lumpcache;
     61 
     62 
     63 
     64 int filelength (FILE* handle) 
     65 { 
     66 	// DHM - not used :: development tool (loading single lump not in a WAD file)
     67 	return 0;
     68 }
     69 
     70 
     71 void
     72 ExtractFileBase
     73 ( const char*		path,
     74   char*		dest )
     75 {
     76 	const char*	src;
     77 	int		length;
     78 
     79 	src = path + strlen(path) - 1;
     80 
     81 	// back up until a \ or the start
     82 	while (src != path
     83 		&& *(src-1) != '\\'
     84 		&& *(src-1) != '/')
     85 	{
     86 		src--;
     87 	}
     88     
     89 	// copy up to eight characters
     90 	memset (dest,0,8);
     91 	length = 0;
     92 
     93 	while (*src && *src != '.')
     94 	{
     95 		if (++length == 9)
     96 			I_Error ("Filename base of %s >8 chars",path);
     97 
     98 		*dest++ = toupper((int)*src++);
     99 	}
    100 }
    101 
    102 
    103 
    104 
    105 
    106 //
    107 // LUMP BASED ROUTINES.
    108 //
    109 
    110 //
    111 // W_AddFile
    112 // All files are optional, but at least one file must be
    113 //  found (PWAD, if all required lumps are present).
    114 // Files with a .wad extension are wadlink files
    115 //  with multiple lumps.
    116 // Other files are single lumps with the base filename
    117 //  for the lump name.
    118 //
    119 // If filename starts with a tilde, the file is handled
    120 //  specially to allow map reloads.
    121 // But: the reload feature is a fragile hack...
    122 
    123 const char*			reloadname;
    124 
    125 
    126 void W_AddFile ( const char *filename)
    127 {
    128     wadinfo_t		header;
    129     lumpinfo_t*		lump_p;
    130     int		i;
    131     idFile *		handle;
    132     int			length;
    133     int			startlump;
    134     std::vector<filelump_t>	fileinfo( 1 );
    135     
    136     // open the file and add to directory
    137     if ( (handle = fileSystem->OpenFileRead(filename)) == 0)
    138     {
    139 		I_Printf (" couldn't open %s\n",filename);
    140 		return;
    141     }
    142 
    143     I_Printf (" adding %s\n",filename);
    144     startlump = numlumps;
    145 	
    146     if ( idStr::Icmp( filename+strlen(filename)-3 , "wad" ) )
    147     {
    148 		// single lump file
    149 		fileinfo[0].filepos = 0;
    150 		fileinfo[0].size = 0;
    151 		ExtractFileBase (filename, fileinfo[0].name);
    152 		numlumps++;
    153     }
    154     else 
    155     {
    156 		// WAD file
    157 		handle->Read( &header, sizeof( header ) );
    158 		if ( idStr::Cmpn( header.identification,"IWAD",4 ) )
    159 		{
    160 			// Homebrew levels?
    161 			if ( idStr::Cmpn( header.identification, "PWAD", 4 ) )
    162 			{
    163 				I_Error ("Wad file %s doesn't have IWAD "
    164 					"or PWAD id\n", filename);
    165 			}
    166 		    
    167 			// ???modifiedgame = true;		
    168 		}
    169 		header.numlumps = LONG(header.numlumps);
    170 		header.infotableofs = LONG(header.infotableofs);
    171 		length = header.numlumps*sizeof(filelump_t);
    172 		fileinfo.resize(header.numlumps);
    173 		handle->Seek(  header.infotableofs, FS_SEEK_SET );
    174 		handle->Read( &fileinfo[0], length );
    175 		numlumps += header.numlumps;
    176     }
    177 
    178     
    179 	// Fill in lumpinfo
    180 	if (lumpinfo == NULL) {
    181 		lumpinfo = (lumpinfo_t*)malloc( numlumps*sizeof(lumpinfo_t) );
    182 	} else {
    183 		lumpinfo = (lumpinfo_t*)realloc( lumpinfo, numlumps*sizeof(lumpinfo_t) );
    184 	}
    185 
    186 	if (!lumpinfo)
    187 		I_Error ("Couldn't realloc lumpinfo");
    188 
    189 	lump_p = &lumpinfo[startlump];
    190 
    191 	::g->wadFileHandles[ ::g->numWadFiles++ ] = handle;
    192 
    193 	filelump_t * filelumpPointer = &fileinfo[0];
    194 	for (i=startlump ; i<numlumps ; i++,lump_p++, filelumpPointer++)
    195 	{
    196 		lump_p->handle = handle;
    197 		lump_p->position = LONG(filelumpPointer->filepos);
    198 		lump_p->size = LONG(filelumpPointer->size);
    199 		strncpy (lump_p->name, filelumpPointer->name, 8);
    200 	}
    201 }
    202 
    203 
    204 
    205 
    206 //
    207 // W_Reload
    208 // Flushes any of the reloadable lumps in memory
    209 //  and reloads the directory.
    210 //
    211 void W_Reload (void)
    212 {
    213 	// DHM - unused development tool
    214 }
    215 
    216 //
    217 // W_FreeLumps
    218 // Frees all lump data
    219 //
    220 void W_FreeLumps() {
    221 	if ( lumpcache != NULL ) {
    222 		for ( int i = 0; i < numlumps; i++ ) {
    223 			if ( lumpcache[i] ) {
    224 				Z_Free( lumpcache[i] );
    225 			}
    226 		}
    227 
    228 		Z_Free( lumpcache );
    229 		lumpcache = NULL;
    230 	}
    231 
    232 	if ( lumpinfo != NULL ) {
    233 		free( lumpinfo );
    234 		lumpinfo = NULL;
    235 		numlumps = 0;
    236 	}
    237 }
    238 
    239 //
    240 // W_FreeWadFiles
    241 // Free this list of wad files so that a new list can be created
    242 //
    243 void W_FreeWadFiles() {
    244 	for (int i = 0 ; i < MAXWADFILES ; i++) {
    245 		wadfiles[i] = NULL;
    246 		if ( ::g->wadFileHandles[i] ) {
    247 			delete ::g->wadFileHandles[i];
    248 		}
    249 		::g->wadFileHandles[i] = NULL;
    250 	}
    251 	::g->numWadFiles = 0;
    252 	extraWad = 0;
    253 }
    254 
    255 
    256 
    257 //
    258 // W_InitMultipleFiles
    259 // Pass a null terminated list of files to use.
    260 // All files are optional, but at least one file
    261 //  must be found.
    262 // Files with a .wad extension are idlink files
    263 //  with multiple lumps.
    264 // Other files are single lumps with the base filename
    265 //  for the lump name.
    266 // Lump names can appear multiple times.
    267 // The name searcher looks backwards, so a later file
    268 //  does override all earlier ones.
    269 //
    270 void W_InitMultipleFiles (const char** filenames)
    271 {
    272 	int		size;
    273 
    274 	if (lumpinfo == NULL)
    275 	{
    276 		// open all the files, load headers, and count lumps
    277 		numlumps = 0;
    278 
    279 		// will be realloced as lumps are added
    280 		lumpinfo = NULL;
    281 
    282 		for ( ; *filenames ; filenames++)
    283 		{
    284 			W_AddFile (*filenames);
    285 		}
    286 		
    287 		if (!numlumps)
    288 			I_Error ("W_InitMultipleFiles: no files found");
    289 
    290 		// set up caching
    291 		size = numlumps * sizeof(*lumpcache);
    292 		lumpcache = (void**)DoomLib::Z_Malloc(size, PU_STATIC_SHARED, 0 );
    293 
    294 		if (!lumpcache)
    295 			I_Error ("Couldn't allocate lumpcache");
    296 
    297 		memset (lumpcache,0, size);
    298 	} else {
    299 		// set up caching
    300 		size = numlumps * sizeof(*lumpcache);
    301 		lumpcache = (void**)DoomLib::Z_Malloc(size, PU_STATIC_SHARED, 0 );
    302 
    303 		if (!lumpcache)
    304 			I_Error ("Couldn't allocate lumpcache");
    305 
    306 		memset (lumpcache,0, size);
    307 	}
    308 }
    309 
    310 
    311 void W_Shutdown( void ) {
    312 /*
    313 	for (int i = 0 ; i < MAXWADFILES ; i++) {
    314 		if ( ::g->wadFileHandles[i] ) {
    315 			doomFiles->FClose( ::g->wadFileHandles[i] );
    316 		}
    317 	}
    318 
    319 	if ( lumpinfo != NULL ) {
    320 		free( lumpinfo );
    321 		lumpinfo = NULL;
    322 	}
    323 */
    324 	W_FreeLumps();
    325 	W_FreeWadFiles();
    326 }
    327 
    328 //
    329 // W_NumLumps
    330 //
    331 int W_NumLumps (void)
    332 {
    333     return numlumps;
    334 }
    335 
    336 
    337 
    338 //
    339 // W_CheckNumForName
    340 // Returns -1 if name not found.
    341 //
    342 
    343 int W_CheckNumForName (const char* name)
    344 {
    345 	const int NameLength = 9;
    346 
    347     union {
    348 		char	s[NameLength];
    349 		int	x[2];
    350 	
    351     } name8;
    352     
    353     int		v1;
    354     int		v2;
    355     lumpinfo_t*	lump_p;
    356 
    357     // make the name into two integers for easy compares
    358     strncpy (name8.s,name, NameLength - 1);
    359 
    360     // in case the name was a fill 8 chars
    361     name8.s[NameLength - 1] = 0;
    362 
    363     // case insensitive
    364 	for ( int i = 0; i < NameLength; ++i ) {
    365 		name8.s[i] = toupper( name8.s[i] );		
    366 	}
    367 
    368     v1 = name8.x[0];
    369     v2 = name8.x[1];
    370 
    371 
    372     // scan backwards so patch lump files take precedence
    373     lump_p = lumpinfo + numlumps;
    374 
    375     while (lump_p-- != lumpinfo)
    376     {
    377 		if ( *(int *)lump_p->name == v1
    378 			&& *(int *)&lump_p->name[4] == v2)
    379 		{
    380 			return lump_p - lumpinfo;
    381 		}
    382     }
    383 
    384     // TFB. Not found.
    385     return -1;
    386 }
    387 
    388 
    389 
    390 
    391 //
    392 // W_GetNumForName
    393 // Calls W_CheckNumForName, but bombs out if not found.
    394 //
    395 int W_GetNumForName ( const char* name)
    396 {
    397     int	i;
    398 
    399     i = W_CheckNumForName ( name);
    400     
    401     if (i == -1)
    402       I_Error ("W_GetNumForName: %s not found!", name);
    403       
    404     return i;
    405 }
    406 
    407 
    408 //
    409 // W_LumpLength
    410 // Returns the buffer size needed to load the given lump.
    411 //
    412 int W_LumpLength (int lump)
    413 {
    414     if (lump >= numlumps)
    415 		I_Error ("W_LumpLength: %i >= numlumps",lump);
    416 
    417     return lumpinfo[lump].size;
    418 }
    419 
    420 
    421 
    422 //
    423 // W_ReadLump
    424 // Loads the lump into the given buffer,
    425 //  which must be >= W_LumpLength().
    426 //
    427 void
    428 W_ReadLump
    429 ( int		lump,
    430   void*		dest )
    431 {
    432     int			c;
    433     lumpinfo_t*	l;
    434     idFile *		handle;
    435 	
    436     if (lump >= numlumps)
    437 		I_Error ("W_ReadLump: %i >= numlumps",lump);
    438 
    439     l = lumpinfo+lump;
    440 	
    441 	handle = l->handle;
    442 	
    443 	handle->Seek( l->position, FS_SEEK_SET );
    444 	c = handle->Read( dest, l->size );
    445 
    446     if (c < l->size)
    447 		I_Error ("W_ReadLump: only read %i of %i on lump %i",  c,l->size,lump);	
    448 }
    449 
    450 
    451 
    452 
    453 //
    454 // W_CacheLumpNum
    455 //
    456 void*
    457 W_CacheLumpNum
    458 ( int		lump,
    459   int		tag )
    460 {
    461 #ifdef RANGECHECK
    462 	if (lump >= numlumps)
    463 	I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
    464 #endif
    465 
    466 	if (!lumpcache[lump])
    467 	{
    468 		byte*	ptr;
    469 		// read the lump in
    470 		//I_Printf ("cache miss on lump %i\n",lump);
    471 		ptr = (byte*)DoomLib::Z_Malloc(W_LumpLength (lump), tag, &lumpcache[lump]);
    472 		W_ReadLump (lump, lumpcache[lump]);
    473 	}
    474 
    475 	return lumpcache[lump];
    476 }
    477 
    478 
    479 
    480 //
    481 // W_CacheLumpName
    482 //
    483 void*
    484 W_CacheLumpName
    485 ( const char*		name,
    486   int		tag )
    487 {
    488     return W_CacheLumpNum (W_GetNumForName(name), tag);
    489 }
    490 
    491 
    492 void W_Profile (void)
    493 {
    494 }
    495 
    496 
    497