1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: w_wad.c 1564 2020-12-19 06:21:07Z wesleyjohnson $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Portions Copyright (C) 1998-2016 by DooM Legacy Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program 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 //
20 // $Log: w_wad.c,v $
21 // Revision 1.34 2004/04/20 00:34:26 andyp
22 // Linux compilation fixes and string cleanups
23 //
24 // Revision 1.33 2002/07/29 21:52:25 hurdler
25 // Revision 1.32 2002/07/26 15:21:36 hurdler
26 // Revision 1.31 2002/01/14 18:54:45 hurdler
27 // Revision 1.30 2001/07/28 16:18:37 bpereira
28 // Revision 1.29 2001/05/27 13:42:48 bpereira
29 //
30 // Revision 1.28 2001/05/21 14:57:05 crashrl
31 // Readded directory crawling file search function
32 //
33 // Revision 1.27 2001/05/16 22:33:34 bock
34 // Initial FreeBSD support.
35 //
36 // Revision 1.26 2001/05/16 17:12:52 crashrl
37 // Added md5-sum support, removed recursiv wad search
38 //
39 // Revision 1.25 2001/04/17 22:26:07 calumr
40 // Initial Mac add
41 //
42 // Revision 1.24 2001/03/03 06:17:34 bpereira
43 // Revision 1.23 2001/02/28 17:50:55 bpereira
44 // Revision 1.22 2001/02/24 13:35:21 bpereira
45 //
46 // Revision 1.21 2001/01/25 22:15:44 bpereira
47 // added heretic support
48 //
49 // Revision 1.20 2000/10/04 16:19:24 hurdler
50 // Change all those "3dfx names" to more appropriate names
51 //
52 // Revision 1.19 2000/09/28 20:57:19 bpereira
53 // Revision 1.18 2000/08/31 14:30:56 bpereira
54 //
55 // Revision 1.17 2000/08/11 21:37:17 hurdler
56 // fix win32 compilation problem
57 //
58 // Revision 1.16 2000/08/11 19:10:13 metzgermeister
59 // Revision 1.15 2000/07/01 09:23:49 bpereira
60 //
61 // Revision 1.14 2000/05/09 20:57:58 hurdler
62 // use my own code for colormap (next time, join with Boris own code)
63 // (necessary due to a small bug in Boris' code (not found) which shows strange effects under linux)
64 //
65 // Revision 1.13 2000/04/30 10:30:10 bpereira
66 //
67 // Revision 1.12 2000/04/27 17:43:19 hurdler
68 // colormap code in hardware mode is now the default
69 //
70 // Revision 1.11 2000/04/16 18:38:07 bpereira
71 //
72 // Revision 1.10 2000/04/13 23:47:47 stroggonmeth
73 // See logs
74 //
75 // Revision 1.9 2000/04/11 19:07:25 stroggonmeth
76 // Finished my logs, fixed a crashing bug.
77 //
78 // Revision 1.8 2000/04/09 02:30:57 stroggonmeth
79 // Fixed missing sprite def
80 //
81 // Revision 1.7 2000/04/08 11:27:29 hurdler
82 // fix some boom stuffs
83 //
84 // Revision 1.6 2000/04/07 01:39:53 stroggonmeth
85 // Fixed crashing bug in Linux.
86 // Made W_ColormapNumForName search in the other direction to find newer colormaps.
87 //
88 // Revision 1.5 2000/04/06 20:40:22 hurdler
89 // Mostly remove warnings under windows
90 //
91 // Revision 1.4 2000/04/05 15:47:47 stroggonmeth
92 // Added hack for Dehacked lumps. Transparent sprites are now affected by colormaps.
93 //
94 // Revision 1.3 2000/04/04 00:32:48 stroggonmeth
95 // Initial Boom compatability plus few misc changes all around.
96 //
97 // Revision 1.2 2000/02/27 00:42:11 hurdler
98 // Revision 1.1.1.1 2000/02/22 20:32:33 hurdler
99 // Initial import into CVS (v1.29 pr3)
100 //
101 //
102 // DESCRIPTION:
103 // Handles WAD file header, directory, lump I/O.
104 //
105 //-----------------------------------------------------------------------------
106
107 #include <fcntl.h>
108 // open
109 #include <unistd.h>
110 // close, read, lseek
111
112 #include "doomincl.h"
113 #include "w_wad.h"
114 #include "z_zone.h"
115
116 #include "v_video.h"
117 // HWR_patchstore
118 #include "d_netfil.h"
119 #include "dehacked.h"
120 // DEH_LoadDehackedLump
121 #include "r_defs.h"
122 #include "i_system.h"
123
124 #include "md5.h"
125 #include "m_swap.h"
126
127 #ifdef HWRENDER
128 #include "hardware/hw_main.h"
129 #endif
130
131
132
133 //===========================================================================
134 // GLOBALS
135 //===========================================================================
136 int numwadfiles; // number of active wadfiles
137 wadfile_t * wadfiles[MAX_WADFILES]; // 0 to numwadfiles-1 are valid
138 // wadfile_t are Z_MALLOC
139
140
141 // Return the wadfile info for the lumpnum
lumpnum_to_wad(lumpnum_t lumpnum)142 wadfile_t * lumpnum_to_wad( lumpnum_t lumpnum )
143 {
144 // level_lumpnum contains index to the wad
145 int wadnum = WADFILENUM( lumpnum );
146 if( wadnum < numwadfiles )
147 return wadfiles[ wadnum ];
148 return NULL;
149 }
150
151
152 // W_Shutdown
153 // Closes all of the WAD files before quitting
154 // If not done on a Mac then open wad files
155 // can prevent removable media they are on from
156 // being ejected
W_Shutdown(void)157 void W_Shutdown(void)
158 {
159 #ifdef ZIP_WAD
160 WZ_close_all();
161 #endif
162 while (numwadfiles--)
163 {
164 wadfile_t * wf = wadfiles[numwadfiles];
165 if( wf->handle >= 0 )
166 close(wf->handle);
167 }
168 }
169
170 //===========================================================================
171 // WAD ROUTINES
172 //===========================================================================
173
174 // Lump Markers
175
176 typedef struct {
177 char markername[9];
178 uint8_t marker_namespace; // start marker namespace
179 } marker_ident_t;
180
181 // At the end of each section, return to LNS_global namespace.
182 #define NUM_MARKER_IDENT 12
183 // Fill each string with 0, out to 8 characters.
184 marker_ident_t marker_ident[ NUM_MARKER_IDENT ] =
185 {
186 { "S_START\0", LNS_sprite }, // S_START to S_END
187 { "S_END\0\0\0", LNS_global },
188 { "F_START\0", LNS_flat }, // F_START to F_END
189 { "F_END\0\0\0", LNS_global },
190 { "C_START\0", LNS_colormap }, // C_START to C_END
191 { "C_END\0\0\0", LNS_global },
192 { "SS_START", LNS_sprite }, // SS_START to SS_END
193 { "SS_END\0\0", LNS_global },
194 { "FF_START", LNS_flat }, // FF_START to FF_END
195 { "FF_END\0\0", LNS_global },
196 { "PP_START", LNS_patch }, // PP_START to PP_END
197 { "PP_END\0\0", LNS_global },
198 };
199
200
201 // Make the name into numerical for easy compares.
numerical_name(const char * name,lump_name_t * numname)202 void numerical_name( const char * name, lump_name_t * numname )
203 {
204 numname->namecode = 0; // clear
205 strncpy (numname->s, name, 8);
206 // in case the name was a full 8 chars (has no 0 term)
207 numname->s[8] = 0;
208 // case insensitive compares
209 strupr (numname->s);
210 // numname.namecode can now be used for compares as uint64_t
211 }
212
213 // Return FC_ indicator
W_filename_classify(const char * filename)214 byte W_filename_classify( const char * filename )
215 {
216 const char * extp = strrchr( filename, '.' );
217 if( extp )
218 {
219 // has a dot extension
220 extp ++;
221 if( strcasecmp( extp, "wad" ) == 0 )
222 return FC_wad;
223 if( strcasecmp( extp, "deh" ) == 0 )
224 return FC_deh;
225 if( strcasecmp( extp, "bex" ) == 0 )
226 return FC_bex;
227 if( strcasecmp( extp, "zip" ) == 0 )
228 return FC_zip;
229 }
230 return FC_other;
231 }
232
233
234
235 // W_AddFile
236 // All files are optional, but at least one file must be
237 // found (PWAD, if all required lumps are present).
238 // Files with a .wad extension are wadlink files
239 // with multiple lumps.
240 // Other files are single lumps with the base filename
241 // for the lump name.
242 //
243
244
245 #ifdef WADFILE_RELOAD
246 // If filename starts with a tilde, the file is handled
247 // specially to allow map reloads.
248 // But: the reload feature is a fragile hack...
249
250 // [WDJ] FIXME: never set anymore
251 static lumpnum_t reload_lumpnum = NO_LUMP;
252 static char* reload_filename = NULL;
253 #endif
254
255
256 // Allocate a wadfile, setup the lumpinfo (directory) and
257 // lumpcache, add the wadfile to the current active wadfiles
258 //
259 // Now returns index into wadfiles[], you can get wadfile_t*
260 // with:
261 // wadfiles[<return value>]
262 //
263 // return -1 in case of problem
264 //
265 // BP: Can now load dehacked files (ext .deh)
266 // Called by W_Init_MultipleFiles, P_AddWadFile.
W_Load_WadFile(const char * filename)267 int W_Load_WadFile ( const char * filename )
268 {
269 // findfile requires a buffer of (at least) MAX_WADPATH
270 char filenamebuf[MAX_WADPATH];
271 char * msg;
272 lumpinfo_t * lumpinfo = NULL;
273 lumpcache_t * lumpcache;
274 wadfile_t * wadfile;
275 #ifdef HWRENDER
276 MipPatch_t * grPatch;
277 #endif
278 int filenum; // return value
279 int numlumps = 0;
280 int handle = -1;
281 filestatus_e fs;
282 int i, m;
283 int length;
284 unsigned int file_size;
285 lump_namespace_e within_namespace = LNS_global;
286
287 byte fc = W_filename_classify( filename );
288 if( fc == FC_other )
289 goto return_fail;
290
291 //
292 // check if limit of active wadfiles
293 //
294 filenum = numwadfiles;
295 if( filenum >= MAX_WADFILES )
296 {
297 msg = "Maximum wad files reached";
298 goto return_fail_msg;
299 }
300
301 strncpy(filenamebuf, filename, MAX_WADPATH-1);
302 filenamebuf[MAX_WADPATH-1] = '\0';
303
304 #ifdef ZIPWAD
305 // When not ziplib_present, then cannot have archive_open.
306 if( archive_open )
307 {
308 handle = WZ_open_file_z( filename );
309 if( handle == FH_none )
310 {
311 msg = "Cannot open";
312 goto return_fail_msg;
313 }
314
315 file_size = WZ_filesize( filenamebuf );
316
317 handle = -3;
318 }
319 else
320 #endif
321 {
322 struct stat bufstat;
323
324 // open wad file
325 handle = open (filenamebuf, O_RDONLY|O_BINARY, 0666);
326 if( handle == -1 )
327 {
328 // not in cur dir, must search
329 nameonly(filenamebuf); // only search for the name
330
331 // findfile returns dir+filename
332 // Owner security permissions.
333 fs = findfile(filenamebuf, NULL, false, /*OUT*/ filenamebuf);
334 if( fs == FS_NOTFOUND )
335 {
336 msg = "Not found";
337 goto return_fail_msg;
338 }
339
340 handle = open (filenamebuf, O_RDONLY|O_BINARY, 0666);
341 if( handle == -1 )
342 {
343 msg = "Cannot open";
344 goto return_fail_msg;
345 }
346 }
347
348 // Get the filesize
349 fstat(handle,&bufstat);
350 file_size = bufstat.st_size;
351 }
352
353 if( fc == FC_zip )
354 {
355 #ifdef ZIPWAD
356 if( ! ziplib_present )
357 {
358 msg = "Cannot read zip file, ziplib not present.";
359 goto read_failure;
360 }
361
362 // Other files are keep open until shutdown,
363 // but zip files are not accessed by handle.
364 close( handle );
365 handle = -2;
366 numlumps = 0;
367 lumpinfo = NULL;
368 #else
369 msg = "Cannot read zip file, do not have ziplib option.";
370 goto read_failure;
371 #endif
372 }
373 else
374
375 // detect dehacked file with the "deh" extension, or bex files
376 if( fc == FC_deh || fc == FC_bex )
377 {
378 // This code emulates a wadfile with one lump name "DEHACKED"
379 // at position 0 and size of the whole file.
380 // This allow deh file to be copied by network and loaded at the
381 // console, like wad files.
382 numlumps = 1;
383 lumpinfo = Z_Malloc (sizeof(lumpinfo_t),PU_STATIC,NULL);
384 lumpinfo->position = 0;
385 lumpinfo->size = file_size;
386 lumpinfo->lump_namespace = LNS_dehacked;
387 memcpy(lumpinfo->name, "DEHACKED", 8); // name array, no term
388 }
389 else if( fc == FC_wad )
390 {
391 // wad file
392 wadinfo_t header;
393 lumpinfo_t* lump_p;
394 filelump_t* fileinfo;
395 filelump_t* flp;
396 int rs;
397
398 // read the header
399 #ifdef ZIPWAD
400 if( archive_open )
401 {
402 // read file in zip archive
403 rs = WZ_read_archive_file( 0, sizeof(header), (byte*)&header );
404 if( rs < 0 )
405 goto read_failure;
406 }
407 else
408 #endif
409 {
410 rs = read (handle, &header, sizeof(header));
411 if( rs < 0 )
412 goto read_failure;
413 }
414
415 if (strncmp(header.identification,"IWAD",4))
416 {
417 // Homebrew levels?
418 if (strncmp(header.identification,"PWAD",4))
419 {
420 msg = "Does not have IWAD or PWAD id";
421 goto close_with_msg;
422 }
423 // ???modifiedgame = true;
424 }
425 header.numlumps = LE_SWAP32(header.numlumps);
426 header.infotableofs = LE_SWAP32(header.infotableofs);
427
428 // read wad file directory
429 length = header.numlumps * sizeof(filelump_t);
430 fileinfo = calloc (length, sizeof(*fileinfo)); // temp alloc, zeroed
431
432 // Read fileinfo at offset specified in header.
433 #ifdef ZIPWAD
434 if( archive_open )
435 {
436 // read file (already open) in zip archive
437 rs = WZ_read_archive_file( header.infotableofs, length, (byte*)fileinfo );
438 if( rs < 0 )
439 goto read_failure;
440 }
441 else
442 #endif
443 {
444 lseek (handle, header.infotableofs, SEEK_SET);
445 rs = read (handle, fileinfo, length);
446 if( rs < 0 )
447 goto read_failure;
448 }
449
450 numlumps = header.numlumps;
451
452 within_namespace = LNS_global; // each wad starts in global namespace
453
454 // fill in lumpinfo array for this wad
455 flp = fileinfo;
456 lump_p = lumpinfo = Z_Malloc (numlumps*sizeof(lumpinfo_t),PU_STATIC,NULL);
457 for (i=0 ; i<numlumps ; i++, lump_p++, flp++)
458 {
459 // Make name compatible with compares using numerical_name.
460 *((uint64_t*)&lump_p->name) = 0; // clear
461 strncpy (lump_p->name, flp->name, 8);
462 // Check for namespace markers using clean lump name.
463 for( m=0; m < NUM_MARKER_IDENT; m++ )
464 {
465 // Fast numerical name compare.
466 if( *((uint64_t*)&lump_p->name) == *((uint64_t*)&marker_ident[m].markername) )
467 within_namespace = marker_ident[m].marker_namespace;
468 }
469 // No uppercase because no other port does it here, and it would
470 // catch lowercase named lumps that otherwise would be ignored.
471 lump_p->lump_namespace = within_namespace;
472 lump_p->position = LE_SWAP32(flp->filepos);
473 lump_p->size = LE_SWAP32(flp->size);
474 }
475 free(fileinfo);
476 }
477
478 //
479 // link wad file to search files
480 //
481 wadfile = Z_Malloc (sizeof (wadfile_t),PU_STATIC,NULL);
482 wadfile->filename = Z_StrDup(filenamebuf);
483 wadfile->handle = handle;
484 wadfile->numlumps = numlumps;
485 wadfile->lumpinfo = lumpinfo;
486 wadfile->filesize = file_size;
487
488 //
489 // add the wadfile
490 //
491 wadfiles[filenum] = wadfile;
492 numwadfiles++;
493
494 //
495 // generate md5sum
496 //
497 {
498 //#define DEBUG_MD5_TIME
499 #ifdef DEBUG_MD5_TIME
500 // [WDJ] Do not know why timing the md5 calc was important, ever.
501 int t;
502 if( devparm >= 3 )
503 t = I_GetTime();
504 #endif
505
506 #ifdef ZIPWAD
507 if( archive_open )
508 {
509 // Need to get proper md5 because client may have same files,
510 // but not in a zip archive. They may have unzipped them.
511 WZ_md5_stream( filenamebuf, wadfile->md5sum );
512 }
513 else
514 #endif
515 {
516 FILE * fhandle = fopen(filenamebuf, "rb");
517 md5_stream (fhandle, wadfile->md5sum);
518 fclose(fhandle);
519 }
520
521 #ifdef DEBUG_MD5_TIME
522 if( devparm >= 3 )
523 {
524 GenPrintf(EMSG_dev, "Load_WadFile %s: md5 calc took %f second\n",
525 filenamebuf, (float)(I_GetTime()-t)/TICRATE);
526 }
527 #endif
528 }
529
530 #ifdef ZIPWAD
531 wadfile->classify = fc;
532 wadfile->lumpcache = NULL;
533 wadfile->hwrcache = NULL;
534 // Immediately after the archive wadfile_t are the wadfile_t for files within the archive.
535 wadfile->archive_num_wadfile = 0; // number of wadfile in this archive
536 wadfile->archive_parent = 0xFF; // contained in archive wadfile index, 0xFF= normal file
537
538 if( fc == FC_zip )
539 {
540 // New zip file.
541 // This is indirect recursive call, that alters this wadfile (by filenum), so it must be setup first.
542 int numfile = WZ_Load_zip_archive( filenamebuf, filenum );
543 if( numfile <= 0 )
544 goto return_fail; // no files
545
546 return filenum;
547 }
548 else if( archive_open )
549 {
550 // File is in zip archive, link to the parent zip archive.
551 if( archive_filenum < filenum ) // file in zip archive
552 {
553 wadfile->archive_parent = archive_filenum; // contained in archive wadfile index, 0xFF= normal file
554 wadfiles[archive_filenum]->archive_num_wadfile++;
555 }
556 }
557 #endif
558
559 // Load the file data
560
561 //
562 // set up caching
563 //
564 length = numlumps * sizeof(lumpcache_t);
565 lumpcache = Z_Malloc (length,PU_STATIC,NULL);
566
567 memset (lumpcache, 0, length);
568 wadfile->lumpcache = lumpcache;
569
570 #ifdef HWRENDER
571 //faB: now allocates MipPatch info structures STATIC from the start,
572 // because these were causing a lot of fragmentation of the heap,
573 // considering they are never freed.
574 length = numlumps * sizeof(MipPatch_t);
575 grPatch = Z_Malloc (length, PU_HWRPATCHINFO, NULL); //never freed
576 // set mipmap.downloaded to false
577 memset (grPatch, 0, length);
578 for (i=0; i<numlumps; i++)
579 {
580 // store the software patch lump number for each MipPatch
581 grPatch[i].patch_lumpnum = WADLUMP(filenum,i); // form file/lump
582 }
583 wadfile->hwrcache = grPatch;
584 #endif
585
586 GenPrintf(EMSG_info, "Added file %s (%i lumps)\n", filenamebuf, numlumps);
587 W_Load_DehackedLumps( filenum );
588
589 return filenum;
590
591 read_failure:
592 msg = "read failure";
593
594 close_with_msg:
595 if( handle >= 0 )
596 close( handle );
597 #ifdef ZIPWAD
598 if( archive_open )
599 WZ_close( FH_zip_file );
600 #endif
601
602 return_fail_msg:
603 GenPrintf(EMSG_warn, "File %s: %s\n", filenamebuf, msg );
604 return_fail:
605 return -1; // fail
606 }
607
608
609
610 #ifdef WADFILE_RELOAD
611 // !!!NOT CHECKED WITH NEW WAD SYSTEM
612 //
613 // W_Reload
614 // Flushes any of the reloadable lumps in memory
615 // and reloads the lump directory.
616 //
617 // Called from: P_SetupLevel
W_Reload(void)618 void W_Reload (void)
619 {
620 wadinfo_t header;
621 int lumpcount;
622 lumpinfo_t* lump_p;
623 int i;
624 int handle;
625 int length;
626 int filenum, lumpnum;
627 filelump_t* fileinfo;
628 filelump_t* flp;
629 lumpcache_t* lumpcache;
630
631 if (!reload_filename)
632 return;
633
634 handle = open (reload_filename,O_RDONLY | O_BINARY);
635 if( handle == -1)
636 I_Error ("W_Reload: couldn't open %s",reload_filename);
637
638 read (handle, &header, sizeof(header));
639 lumpcount = LE_SWAP32(header.numlumps);
640 header.infotableofs = LE_SWAP32(header.infotableofs);
641 length = lumpcount*sizeof(filelump_t);
642 fileinfo = calloc (length, sizeof(*fileinfo)); // temp alloc, zeroed
643 lseek (handle, header.infotableofs, SEEK_SET);
644 read (handle, fileinfo, length);
645
646 // Fill in lumpinfo
647 filenum = WADFILENUM(reload_lumpnum);
648 lumpnum = LUMPNUM(reload_lumpnum);
649 lump_p = & wadfiles[filenum]->lumpinfo[ lumpnum ];
650 lumpcache = wadfiles[filenum]->lumpcache;
651
652 flp = fileinfo;
653 // Only index lumpcache by lumpnum.
654 for (i=lumpnum ; i<lumpnum+lumpcount ; i++)
655 {
656 if (lumpcache[i])
657 Z_Free (lumpcache[i]);
658
659 lump_p->position = LE_SWAP32(flp->filepos);
660 lump_p->size = LE_SWAP32(flp->size);
661 lump_p++;
662 flp++;
663 }
664
665 close (handle);
666 free(fileinfo);
667 }
668 #endif
669
670
671 //
672 // W_Init_MultipleFiles
673 // Pass a null terminated list of files to use.
674 // All files are optional, but at least one file must be found.
675 // Any load failure is indicated to the caller, for error handling.
676 // Files with a .wad extension are idlink files
677 // with multiple lumps.
678 // Other files are single lumps with the base filename
679 // for the lump name.
680 // Lump names can appear multiple times.
681 // The name searcher looks backwards, so a later file
682 // does override all earlier ones.
683 //
684 // Return 0 when any file load does not succeed
685 // Called by: D_DoomMain
W_Init_MultipleFiles(char ** filenames)686 int W_Init_MultipleFiles ( char ** filenames )
687 {
688 int rc = 1;
689
690 // open all the files, load headers, and count lumps
691 numwadfiles = 0;
692
693 // will be realloced as lumps are added
694 for ( ; *filenames ; filenames++)
695 {
696 if( W_Load_WadFile (*filenames) == -1 )
697 {
698 rc = 0;
699 GenPrintf( EMSG_warn, "File not found: %s\n", *filenames );
700 }
701 }
702
703 if (!numwadfiles)
704 {
705 I_SoftError ("W_Init_MultipleFiles: no files found\n");
706 fatal_error = 1;
707 }
708
709 return rc;
710 }
711
712
713 //===========================================================================
714 // LUMP BASED ROUTINES
715 //===========================================================================
716
717 //
718 // W_CheckNumForName
719 // Lists are currently used by flats and colormaps.
720 // These are faster as they skip checking some names.
721 // Patches within textures use namespace to protect against trying to use
722 // another lump of the same name (colormap) as a patch.
723
724 // Return lump id, or NO_LUMP if name not found.
W_Check_Namespace(const char * name,lump_namespace_e within_namespace)725 lumpnum_t W_Check_Namespace (const char* name, lump_namespace_e within_namespace)
726 {
727 lumpnum_t alternate = NO_LUMP;
728 int i,j;
729 lump_name_t name8;
730 lumpinfo_t* lump_p;
731
732 numerical_name( name, & name8 );
733
734 // Scan wad files backwards so PWAD files take precedence.
735 for (i = numwadfiles-1 ; i>=0; i--)
736 {
737 // Scan forward within a wad file.
738 lump_p = wadfiles[i]->lumpinfo;
739 if( ! lump_p ) continue;
740
741 for (j = 0; j<wadfiles[i]->numlumps; j++,lump_p++)
742 {
743 // Fast numerical name compare.
744 if ( *(uint64_t *)lump_p->name == name8.namecode )
745 {
746 // Name matches.
747 // Check if lump is from the wanted namespace.
748 if( within_namespace == LNS_any
749 || lump_p->lump_namespace == within_namespace )
750 {
751 // Return wad/lump identifier
752 return WADLUMP(i,j);
753 }
754 // Wrong namespace.
755 if( alternate == NO_LUMP ) // remember first lump found
756 alternate = WADLUMP(i,j); // wad/lump identifier
757 }
758 }
759 }
760 // Not found.
761 // Return first matching lump found in any namespace.
762 if( alternate != NO_LUMP )
763 return alternate;
764
765 return NO_LUMP;
766 }
767
768 // Return lump id, or NO_LUMP if name not found.
W_CheckNumForName(const char * name)769 lumpnum_t W_CheckNumForName (const char* name)
770 {
771 return W_Check_Namespace( name, LNS_any );
772 }
773
774
775 //
776 // Same as the original, but checks in one pwad only
777 // (Used for sprites loading)
778 // wadid : the wad number
779 // startlump : the lump number (without wad id) to start the search
780 // Return lump number, or NO_LUMP.
W_CheckNumForNamePwad(const char * name,int wadid,int startlump)781 lumpnum_t W_CheckNumForNamePwad (const char* name, int wadid, int startlump)
782 {
783 int i;
784 lump_name_t name8;
785 lumpinfo_t* lump_p;
786
787 // make the name into numerical for easy compares
788 numerical_name( name, & name8 );
789
790 //
791 // scan forward
792 // start at 'startlump', useful parameter when there are multiple
793 // resources with the same name
794 //
795 if (startlump < wadfiles[wadid]->numlumps)
796 {
797 lump_p = wadfiles[wadid]->lumpinfo + startlump;
798 if( ! lump_p )
799 return NO_LUMP;
800
801 for (i = startlump; i<wadfiles[wadid]->numlumps; i++,lump_p++)
802 {
803 // Fast numerical name compare.
804 if ( *(uint64_t *)lump_p->name == name8.namecode )
805 {
806 return WADLUMP(wadid,i);
807 }
808 }
809 }
810
811 // not found.
812 return NO_LUMP;
813 }
814
815
816
817 //
818 // W_GetNumForName
819 // Calls W_CheckNumForName, but bombs out if not found.
820 //
W_GetNumForName(const char * name)821 lumpnum_t W_GetNumForName (const char* name)
822 {
823 lumpnum_t ln;
824
825 ln = W_CheckNumForName (name);
826
827 if( ! VALID_LUMP(ln) )
828 {
829 #ifdef DEBUG_CHEXQUEST
830 I_SoftError ("W_GetNumForName: %s not found!\n", name); // [WDJ] 4/28/2009 Chexquest
831 #else
832 I_Error ("W_GetNumForName: %s not found!\n", name);
833 #endif
834 }
835
836 return ln;
837 }
838
839 // Scan wads files forward, IWAD precedence.
W_CheckNumForNameFirst(const char * name)840 lumpnum_t W_CheckNumForNameFirst (const char* name)
841 {
842 int i, j;
843 lump_name_t name8;
844 lumpinfo_t* lump_p;
845
846 numerical_name( name, & name8 );
847
848 // scan wad files forward, when original wad resources
849 // must take precedence
850 for (i = 0; i<numwadfiles; i++)
851 {
852 lump_p = wadfiles[i]->lumpinfo;
853 if( ! lump_p ) continue;
854
855 for (j = 0; j<wadfiles[i]->numlumps; j++,lump_p++)
856 {
857 if ( *(uint64_t *)lump_p->name == name8.namecode )
858 {
859 return WADLUMP(i,j);
860 }
861 }
862 }
863
864 return NO_LUMP;
865 }
866
867 //
868 // W_GetNumForNameFirst : like W_GetNumForName, but scans FORWARD
869 // so it gets resources from the original wad first
870 // (this is used only to get S_START for now, in r_data.c)
W_GetNumForNameFirst(const char * name)871 lumpnum_t W_GetNumForNameFirst (const char* name)
872 {
873 lumpnum_t ln;
874
875 ln = W_CheckNumForNameFirst (name);
876 if( ! VALID_LUMP(ln) )
877 I_Error ("W_GetNumForNameFirst: %s not found!", name);
878
879 return ln;
880 }
881
882
883 //
884 // W_LumpLength
885 // Returns the buffer size needed to load the given lump.
886 //
W_LumpLength(lumpnum_t lump)887 int W_LumpLength (lumpnum_t lump)
888 {
889 #ifdef PARANOIA
890 // if (lump<0) I_Error("W_LumpLength: lump not exist\n");
891 if( ! VALID_LUMP(lump) ) I_Error("W_LumpLength: lump not exist\n");
892
893 if (LUMPNUM(lump) >= wadfiles[WADFILENUM(lump)]->numlumps)
894 I_Error ("W_LumpLength: %i >= numlumps",lump);
895 #endif
896 lumpinfo_t * lump_p = wadfiles[WADFILENUM(lump)]->lumpinfo;
897 if( lump_p == NULL )
898 return 0;
899
900 return lump_p[ LUMPNUM(lump) ].size;
901 }
902
903
904
905 //
906 // W_ReadLumpHeader : read 'size' bytes of lump
907 // sometimes just the header is needed
908 //
909 //Fab:02-08-98: now returns the number of bytes read (should == size)
W_ReadLumpHeader(lumpnum_t lump,void * dest,int size)910 int W_ReadLumpHeader ( lumpnum_t lump,
911 void* dest,
912 int size )
913 {
914 lumpinfo_t* lif;
915 wadfile_t * wf;
916 int ln1, wn1;
917 int handle;
918 int bytesread = 0;
919
920 ln1 = LUMPNUM(lump);
921 wn1 = WADFILENUM(lump);
922 wf = wadfiles[ wn1 ];
923
924 #ifdef PARANOIA
925 // if (lump<0) I_Error("W_ReadLumpHeader: lump not exist\n");
926 if ( ! VALID_LUMP(lump) )
927 I_Error("W_ReadLumpHeader: Invalid lump id\n");
928
929 if( ln1 >= wf->numlumps )
930 I_Error ("W_ReadLumpHeader: %i >= numlumps",lump);
931 #endif
932
933 if( wf->lumpinfo == NULL )
934 return 0;
935
936 lif = & wf->lumpinfo[ ln1 ];
937
938 // empty resource (usually markers like S_START, F_END ..)
939 if (lif->size==0)
940 return 0;
941
942 #ifdef LOADING_DISK_ICON
943 // the good ole 'loading' disc icon TODO: restore it :)
944 I_BeginRead ();
945 // After this point must go thorugh I_EndRead() before can return.
946 #endif
947
948 handle = wf->handle; //lif->handle;
949
950 #ifdef WADFILE_RELOAD
951 if (lif->handle == -1)
952 {
953 // reloadable file, so use open / read / close
954 handle = open (reload_filename,O_RDONLY|O_BINARY,0666);
955 if( handle == -1 )
956 {
957 I_SoftError ("W_ReadLumpHeader: couldn't open %s\n", reload_filename);
958 goto done;
959 }
960 }
961 #endif
962
963 // 0 size means read all the lump
964 if (!size || size>lif->size)
965 size = lif->size;
966
967 // Read lump at offset.
968 #ifdef ZIPWAD
969 if( wf->archive_num_wadfile )
970 {
971 // An archive, cannot read lump.
972 return 0;
973 }
974 else if( wf->archive_parent < 0xFF ) // valid parent archive
975 {
976 // From file in zip archive.
977 bytesread = WZ_read_wadfile_from_archive_file_offset( wn1, wf, lif->position, size, /*OUT*/ dest );
978 }
979 else
980 #endif
981 {
982 lseek (handle, lif->position, SEEK_SET);
983 bytesread = read (handle, dest, size);
984 }
985
986 #ifdef WADFILE_RELOAD
987 if (lif->handle == -1)
988 close (handle);
989 #endif
990
991 #ifdef WADFILE_RELOAD
992 done:
993 #endif
994 #ifdef LOADING_DISK_ICON
995 I_EndRead ();
996 #endif
997 return bytesread;
998 }
999
1000
1001 //
1002 // W_ReadLump
1003 // Loads the lump into the given buffer,
1004 // which must be >= W_LumpLength().
1005 //
1006 //added:06-02-98: now calls W_ReadLumpHeader() with full lump size.
1007 // 0 size means the size of the lump, see W_ReadLumpHeader
W_ReadLump(lumpnum_t lump,void * dest)1008 void W_ReadLump ( lumpnum_t lump,
1009 void* dest )
1010 {
1011 W_ReadLumpHeader (lump, dest, 0);
1012 }
1013
1014
1015 // ==========================================================================
1016 // W_CacheLumpNum
1017 // ==========================================================================
1018 // [WDJ] Indicates cache miss, new lump read requires endian fixing.
1019 boolean lump_read; // set by W_CacheLumpNum
1020
W_CacheLumpNum(lumpnum_t lumpnum,int ztag)1021 void* W_CacheLumpNum ( lumpnum_t lumpnum, int ztag )
1022 {
1023 lumpcache_t* lumpcache;
1024
1025 //SoM: 4/8/2000: Don't keep doing operations to the lump variable!
1026 unsigned int llump = LUMPNUM(lumpnum);
1027 unsigned int lfile = WADFILENUM(lumpnum);
1028
1029 #ifdef DEBUG_CHEXQUEST
1030 // [WDJ] Crashes in chexquest with black screen, cannot debug
1031 if( ! VALID_LUMP(lumpnum) ) {
1032 lump_read = 0; // no data
1033 // [WDJ] prevent SIGSEGV in chexquest
1034 I_SoftError ("W_CacheLumpNum: not VALID_LUMP passed!\n");
1035 return NULL;
1036 }
1037 #endif
1038 #ifdef PARANOIA
1039 // check return value of a previous W_CheckNumForName()
1040 //SoM: 4/8/2000: Do better checking. No more SIGSEGV's!
1041 if( ! VALID_LUMP(lumpnum) ) // [WDJ] must be first to protect use as index
1042 I_Error ("W_CacheLumpNum: not VALID_LUMP passed!\n");
1043 if (lfile >= numwadfiles)
1044 I_Error("W_CacheLumpNum: %i >= numwadfiles(%i)\n", lfile, numwadfiles);
1045 if (llump >= wadfiles[lfile]->numlumps)
1046 I_Error ("W_CacheLumpNum: %i >= numlumps", llump);
1047 // if(llump < 0) // not possible
1048 // I_Error ("W_CacheLumpNum: %i < 0!\n", llump);
1049 #endif
1050
1051 lumpcache = wadfiles[lfile]->lumpcache;
1052 if (!lumpcache[llump])
1053 {
1054 // read the lump in
1055
1056 //debug_Printf ("cache miss on lump %i\n",lump);
1057 byte* ptr = Z_Malloc ( W_LumpLength(lumpnum), ztag, &lumpcache[llump]);
1058 W_ReadLumpHeader( lumpnum, ptr, 0 ); // read whole lump
1059 // W_ReadLumpHeader (lump, lumpcache[llump], 0); // read whole lump
1060 lump_read = 1; // cache miss, read lump, caller must apply endian fix
1061 }
1062 else
1063 {
1064 //debug_Printf ("cache hit on lump %i\n",lump);
1065 // [WDJ] Do not degrade lump to PU_CACHE while it is in use.
1066 if( ztag == PU_CACHE ) ztag = PU_CACHE_DEFAULT;
1067 Z_ChangeTag (lumpcache[llump], ztag);
1068 lump_read = 0; // cache hit, cache already has endian fixes
1069 }
1070
1071 return lumpcache[llump];
1072 }
1073
1074
1075 // ==========================================================================
1076 // W_CacheLumpName
1077 // ==========================================================================
W_CacheLumpName(const char * name,int ztag)1078 void* W_CacheLumpName ( const char* name, int ztag )
1079 {
1080 return W_CacheLumpNum (W_GetNumForName(name), ztag);
1081 }
1082
1083
1084
1085 // ==========================================================================
1086 // CACHING OF GRAPHIC PATCH RESOURCES
1087 // ==========================================================================
1088
1089 // Graphic 'patches' are loaded, and if necessary, converted into the format
1090 // the most useful for the current rendermode. For software renderer, the
1091 // graphic patches are kept as is. For the hardware renderer, graphic patches
1092 // are 'unpacked', and are kept into the cache in that unpacked format, the
1093 // heap memory cache then act as a 'level 2' cache just after the graphics
1094 // card memory.
1095
1096
1097 // pl : a patch list, maybe offset into a patch list
load_patch_list(load_patch_t * pl)1098 void load_patch_list( load_patch_t * pl )
1099 {
1100 while( pl->patch_owner ) {
1101 // software_render will store a patch allocation.
1102 // hardware render stores a cache ptr.
1103 *(pl->patch_owner) = W_CachePatchName(pl->name, PU_LOCK_SB);
1104 pl++;
1105 }
1106 }
1107
1108 // pl : a patch list, maybe offset into a patch list
release_patch_list(load_patch_t * pl)1109 void release_patch_list( load_patch_t * pl )
1110 {
1111 while( pl->patch_owner ) {
1112 W_release_patch( *(pl->patch_owner) );
1113 pl++;
1114 }
1115 }
1116
1117 // pp : an array of patch_t ptr
1118 // count : number of patches to release
release_patch_array(patch_t ** pp,int count)1119 void release_patch_array( patch_t ** pp, int count )
1120 {
1121 while( count-- ) {
1122 // Hardware render and software render releases are different.
1123 if( *pp )
1124 W_release_patch( *pp );
1125 pp++;
1126 }
1127 }
1128
1129
1130 //
1131 // Cache a patch into heap memory, convert the patch format as necessary
1132 //
1133
1134 // [WDJ] When there is another lump with the same name as a patch, this will
1135 // sometimes get that lump and convert the header as if it was a patch.
1136 // This should only get lumps that are patches.
1137
1138 // Cache the patch with endian conversion
1139 // [WDJ] Only read patches using this function, hardware render too.
1140 // [WDJ] Removed inline because is also called from in hardware/hw_cache.c.
W_CachePatchNum_Endian(lumpnum_t lump,int ztag)1141 void* W_CachePatchNum_Endian ( lumpnum_t lump, int ztag )
1142 {
1143 // __BIG_ENDIAN__ is defined on MAC compilers, not on WIN, nor LINUX
1144 #ifdef __BIG_ENDIAN__
1145 patch_t * patch = W_CacheLumpNum(lump, ztag);
1146 // [WDJ] If newly read patch then fix endian.
1147 if( lump_read )
1148 {
1149 patch->height = (uint16_t)( LE_SWAP16(patch->height) );
1150 patch->width = (uint16_t)( LE_SWAP16(patch->width) );
1151 patch->topoffset = LE_SWAP16(patch->topoffset);
1152 patch->leftoffset = LE_SWAP16(patch->leftoffset);
1153 {
1154 // [WDJ] columnofs[ 0 .. width-1 ]
1155 // The patch structure only shows 8, but there can be many more.
1156 int i = patch->width - 1;
1157 for( ; i>=0; i-- )
1158 patch->columnofs[i] = LE_SWAP32( patch->columnofs[i] );
1159 }
1160 }
1161 return patch;
1162 #else
1163 // [WDJ] Optimized version for little-endian, much faster
1164 return W_CacheLumpNum(lump, ztag);
1165 #endif
1166 }
1167
1168
1169
1170 // Called from many draw functions
W_CachePatchNum(lumpnum_t lumpnum,int ztag)1171 void* W_CachePatchNum ( lumpnum_t lumpnum, int ztag )
1172 {
1173 MipPatch_t* grPatch;
1174
1175 #ifdef HWRENDER
1176 if( ! HWR_patchstore ) {
1177 return W_CachePatchNum_Endian ( lumpnum, ztag );
1178 }
1179
1180 // hardware render
1181 // Patches are stored in HWR patch format.
1182
1183 #ifdef PARANOIA
1184 // check the return value of a previous W_CheckNumForName()
1185 if ( ( ! VALID_LUMP(lumpnum) )
1186 || (LUMPNUM(lumpnum) >= wadfiles[WADFILENUM(lumpnum)]->numlumps) )
1187 I_Error ("W_CachePatchNum: %i >= numlumps", LUMPNUM(lumpnum));
1188 #endif
1189
1190 grPatch = &(wadfiles[WADFILENUM(lumpnum)]->hwrcache[LUMPNUM(lumpnum)]);
1191
1192 if( ! grPatch->mipmap.grInfo.data )
1193 { // first time init grPatch fields
1194 // we need patch w,h,offset,...
1195 patch_t* tmp_patch = W_CachePatchNum_Endian(grPatch->patch_lumpnum, PU_LUMP); // temp use
1196 // default no TF_Opaquetrans
1197 HWR_MakePatch ( tmp_patch, grPatch, &grPatch->mipmap, 0);
1198 Z_Free (tmp_patch);
1199 // HWR_MakePatch makes grInfo.data as PU_HWRCACHE
1200 }
1201
1202 // return MipPatch_t, which can be casted to (patch_t) with valid patch header info
1203 return (void*)grPatch;
1204 #else
1205 // Software renderer only, simplified
1206 return W_CachePatchNum_Endian( lump, ztag );
1207 #endif
1208 }
1209
1210 #ifdef HWRENDER
1211 // [WDJ] Called from hardware render for special mapped sprites
W_CacheMappedPatchNum(lumpnum_t lumpnum,uint32_t drawflags)1212 void* W_CacheMappedPatchNum ( lumpnum_t lumpnum, uint32_t drawflags )
1213 {
1214 MipPatch_t* grPatch;
1215
1216 #ifdef PARANOIA
1217 // check the return value of a previous W_CheckNumForName()
1218 if ( ( ! VALID_LUMP(lumpnum) )
1219 || (LUMPNUM(lumpnum) >= wadfiles[WADFILENUM(lumpnum)]->numlumps) )
1220 I_Error ("W_CacheMappedPatchNum: %i >= numlumps", LUMPNUM(lumpnum));
1221 #endif
1222
1223 grPatch = &(wadfiles[WADFILENUM(lumpnum)]->hwrcache[LUMPNUM(lumpnum)]);
1224
1225 if( ! grPatch->mipmap.grInfo.data )
1226 { // first time init grPatch fields
1227 // we need patch w,h,offset,...
1228 patch_t *tmp_patch = W_CachePatchNum_Endian(grPatch->patch_lumpnum, PU_LUMP); // temp use
1229 // pass TF_Opaquetrans
1230 HWR_MakePatch ( tmp_patch, grPatch, &grPatch->mipmap, drawflags);
1231 Z_Free (tmp_patch);
1232 // HWR_MakePatch makes grInfo.data as PU_HWRCACHE
1233 }
1234
1235 // return MipPatch_t, which can be casted to (patch_t) with valid patch header info
1236 return (void*)grPatch;
1237 }
1238 #endif
1239
1240 // Release patches made with W_CachePatchNum, W_CachePatchName.
W_release_patch(patch_t * patch)1241 void W_release_patch( patch_t * patch )
1242 {
1243 #ifdef HWRENDER
1244 if( HWR_patchstore )
1245 {
1246 // Hardware render: the patches are fake, and are allocated in a large array
1247 MipPatch_t* grPatch = (MipPatch_t*) patch; // sneaky HWR casting
1248 HWR_release_Patch( grPatch, &grPatch->mipmap );
1249 return;
1250 }
1251 #endif
1252
1253 // Software render: the patches were allocated with Z_Malloc
1254 #ifdef PARANOIA
1255 if( ! verify_Z_Malloc(patch))
1256 {
1257 GenPrintf( EMSG_error, "Error W_release_patch: Not a memory block %x\n", *patch);
1258 return;
1259 }
1260 #endif
1261 Z_ChangeTag( patch, PU_UNLOCK_CACHE );
1262 }
1263
1264
1265 // Find patch in LNS_patch namespace
W_CachePatchName(const char * name,int ztag)1266 void* W_CachePatchName ( const char* name, int ztag )
1267 {
1268 int lumpid;
1269 // substitute known name for name not found
1270 lumpid = W_Check_Namespace( name, LNS_patch );
1271 if( ! VALID_LUMP(lumpid) )
1272 {
1273 name = "BRDR_MM";
1274 lumpid = W_Check_Namespace( name, LNS_patch );
1275 if( ! VALID_LUMP(lumpid) )
1276 I_Error ("W_CachePatchName: %s not found!\n", name);
1277 }
1278 return W_CachePatchNum( lumpid, ztag);
1279 }
1280
1281
1282 // convert raw heretic picture to legacy pic_t format
1283 // Used for heretic: TITLE, HELP1, HELP2, ORDER, CREDIT, FINAL1, FINAL2, E2END
1284 // Used for raven demo screen
W_CacheRawAsPic(lumpnum_t lumpnum,int width,int height,int ztag)1285 void* W_CacheRawAsPic( lumpnum_t lumpnum, int width, int height, int ztag)
1286 {
1287 // [WDJ] copy of CacheLumpNum with larger lump allocation,
1288 // read into pic, and no endian fixes
1289 lumpcache_t* lumpcache;
1290 //SoM: 4/8/2000: Don't keep doing operations to the lump variable!
1291 unsigned int llump = LUMPNUM(lumpnum);
1292 unsigned int lfile = WADFILENUM(lumpnum);
1293
1294 #ifdef PARANOIA
1295 // check return value of a previous W_CheckNumForName()
1296 //SoM: 4/8/2000: Do better checking. No more SIGSEGV's!
1297 if( ! VALID_LUMP(lumpnum) )
1298 I_Error ("W_CacheRawAsPic: not VALID_LUMP passed!\n");
1299 if (lfile >= numwadfiles)
1300 I_Error("W_CacheRawAsPic: %i >= numwadfiles(%i)\n", lfile, numwadfiles);
1301 if (llump >= wadfiles[lfile]->numlumps)
1302 I_Error ("W_CacheRawAsPic: %i >= numlumps", llump);
1303 // if(llump < 0) // not possible
1304 // I_Error ("W_CacheRawAsPic: %i < 0!\n", llump);
1305 #endif
1306
1307 lumpcache = wadfiles[lfile]->lumpcache;
1308 if (!lumpcache[llump]) // cache miss
1309 {
1310 // read the lump in
1311
1312 // Allocation is larger than what W_CacheLumpNum does
1313 pic_t* pic = Z_Malloc (W_LumpLength(lumpnum)+sizeof(pic_t),
1314 ztag, &lumpcache[llump]);
1315 // read lump + pic into pic->data (instead of lumpcache)
1316 W_ReadLumpHeader( lumpnum, pic->data, 0 );
1317 // set pic info from caller parameters, (which are literals)
1318 pic->width = width;
1319 pic->height = height;
1320 pic->mode = PALETTE;
1321 }
1322 else
1323 {
1324 // [WDJ] Do not degrade lump to PU_CACHE while it is in use.
1325 if( ztag == PU_CACHE )
1326 ztag = PU_CACHE_DEFAULT;
1327 Z_ChangeTag (lumpcache[llump], ztag);
1328 }
1329
1330 return lumpcache[llump];
1331 }
1332
1333
1334 // Cache and endian convert a pic_t
W_CachePicNum(lumpnum_t lumpnum,int ztag)1335 void* W_CachePicNum( lumpnum_t lumpnum, int ztag )
1336 {
1337 // __BIG_ENDIAN__ is defined on MAC compilers, not on WIN, nor LINUX
1338 #ifdef __BIG_ENDIAN__
1339 pic_t * pt = W_CacheLumpNum ( lumpnum, ztag );
1340 // [WDJ] If newly read pic then fix endian.
1341 if( lump_read )
1342 {
1343 pt->height = (uint16_t)( LE_SWAP16(pt->height) );
1344 pt->width = (uint16_t)( LE_SWAP16(pt->width) );
1345 // pt->reserved = LE_SWAP16(pt->reserved);
1346 }
1347 return pt;
1348 #else
1349 // [WDJ] Optimized version for little-endian, much faster
1350 return W_CacheLumpNum(lumpnum, ztag);
1351 #endif
1352 }
1353
1354 // Cache and endian convert a pic_t
W_CachePicName(const char * name,int tag)1355 void* W_CachePicName( const char* name, int tag )
1356 {
1357 return W_CachePicNum( W_GetNumForName(name), tag);
1358 }
1359
1360
1361 // Search for all DEHACKED lump in all wads and load it.
W_Load_DehackedLumps(int wadnum)1362 void W_Load_DehackedLumps( int wadnum )
1363 {
1364 lumpnum_t clump = 0;
1365
1366 while (1)
1367 {
1368 clump = W_CheckNumForNamePwad("DEHACKED", wadnum, LUMPNUM(clump));
1369 if( ! VALID_LUMP(clump) )
1370 break;
1371 GenPrintf(EMSG_info, "Loading dehacked from %s\n",wadfiles[wadnum]->filename);
1372 DEH_LoadDehackedLump(clump);
1373 clump++;
1374 }
1375 }
1376
1377 // [WDJ] Return a sum unique to a lump, to detect replacements.
1378 // The lumpptr must be to a Z_Malloc lump.
W_lump_checksum(void * lumpptr)1379 uint64_t W_lump_checksum( void* lumpptr )
1380 {
1381 // Work only with the lumpptr given, cannot trust that can get stats
1382 // on the exact same lump, it may be in multiple wads and pwads.
1383 // Very simple checksum over the size of the Z_Malloc block.
1384 int lumpsize = Z_Datasize( lumpptr );
1385 uint64_t checksum = 0;
1386 int i;
1387 for( i=0; i<lumpsize; i++ )
1388 checksum += ((byte*)lumpptr)[i];
1389 return checksum;
1390 }
1391
1392
1393 #if 0
1394 // Makes DOS assumptions
1395 // --------------------------------------------------------------------------
1396 // W_Profile
1397 // --------------------------------------------------------------------------
1398 //
1399 /* --------------------- UNUSED ------------------------
1400 int info[2500][10];
1401 int profilecount;
1402
1403 void W_Profile (void)
1404 {
1405 int i;
1406 memblock_t* block;
1407 void* ptr;
1408 char ch;
1409 FILE* f;
1410 int j;
1411 char name[9];
1412
1413
1414 for (i=0 ; i<numlumps ; i++)
1415 {
1416 ptr = lumpcache[i];
1417 if (!ptr)
1418 {
1419 ch = ' ';
1420 continue;
1421 }
1422 else
1423 {
1424 block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
1425 if (block->memtag < PU_PURGELEVEL)
1426 ch = 'S';
1427 else
1428 ch = 'P';
1429 }
1430 info[i][profilecount] = ch;
1431 }
1432 profilecount++;
1433
1434 f = fopen ("waddump.txt","w");
1435 name[8] = 0;
1436
1437 for (i=0 ; i<numlumps ; i++)
1438 {
1439 memcpy (name,lumpinfo[i].name,8);
1440
1441 for (j=0 ; j<8 ; j++)
1442 if (!name[j])
1443 break;
1444
1445 for ( ; j<8 ; j++)
1446 name[j] = ' ';
1447
1448 fprintf (f,"%s ",name);
1449
1450 for (j=0 ; j<profilecount ; j++)
1451 fprintf (f," %c",info[i][j]);
1452
1453 fprintf (f,"\n");
1454 }
1455 fclose (f);
1456 }
1457
1458 // --------------------------------------------------------------------------
1459 // W_AddFile : the old code kept for reference
1460 // --------------------------------------------------------------------------
1461 // All files are optional, but at least one file must be
1462 // found (PWAD, if all required lumps are present).
1463 // Files with a .wad extension are wadlink files
1464 // with multiple lumps.
1465 // Other files are single lumps with the base filename
1466 // for the lump name.
1467 //
1468
1469 int filelen (int handle)
1470 {
1471 struct stat fileinfo;
1472
1473 if (fstat (handle,&fileinfo) == -1)
1474 I_Error ("Error fstating");
1475
1476 return fileinfo.st_size;
1477 }
1478
1479
1480 int W_AddFile (char *filename)
1481 {
1482 wadinfo_t header;
1483 lumpinfo_t* lump_p;
1484 unsigned i;
1485 int handle;
1486 int length;
1487 int startlump;
1488 filelump_t* fileinfo;
1489 filelump_t singleinfo;
1490 int storehandle;
1491
1492 // open the file and add to directory
1493
1494 // handle reload indicator.
1495 if (filename[0] == '~')
1496 {
1497 filename++;
1498 reload_filename = filename;
1499 reload_lumpnum = numlumps;
1500 }
1501
1502 if ( (handle = open (filename,O_RDONLY | O_BINARY)) == -1)
1503 {
1504 CONS_Printf (" couldn't open %s\n",filename);
1505 return 0;
1506 }
1507
1508 CONS_Printf (" adding %s\n",filename);
1509 startlump = numlumps;
1510
1511 if (strcasecmp (filename+strlen(filename)-3, "wad") )
1512 {
1513 // single lump file
1514 fileinfo = &singleinfo;
1515 singleinfo.filepos = 0;
1516 singleinfo.size = LE_SWAP32(filelen(handle));
1517 FIL_ExtractFileBase (filename, singleinfo.name);
1518 numlumps++;
1519 }
1520 else
1521 {
1522 // WAD file
1523 read (handle, &header, sizeof(header));
1524 if (strncmp(header.identification,"IWAD",4))
1525 {
1526 // Homebrew levels?
1527 if (strncmp(header.identification,"PWAD",4))
1528 {
1529 I_Error ("Wad file %s doesn't have IWAD "
1530 "or PWAD id\n", filename);
1531 }
1532
1533 // ???modifiedgame = true;
1534 }
1535 header.numlumps = LE_SWAP32(header.numlumps);
1536 header.infotableofs = LE_SWAP32(header.infotableofs);
1537 length = header.numlumps*sizeof(filelump_t);
1538 fileinfo = alloca (length);
1539 lseek (handle, header.infotableofs, SEEK_SET);
1540 read (handle, fileinfo, length);
1541 numlumps += header.numlumps;
1542 }
1543
1544
1545 // Fill in lumpinfo
1546 lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
1547
1548 if (!lumpinfo)
1549 I_Error ("Couldn't realloc lumpinfo");
1550
1551 lump_p = &lumpinfo[startlump];
1552
1553 storehandle = reload_filename ? -1 : handle;
1554
1555 for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++)
1556 {
1557 lump_p->handle = storehandle;
1558 lump_p->position = LE_SWAP32(fileinfo->filepos);
1559 lump_p->size = LE_SWAP32(fileinfo->size);
1560 strncpy (lump_p->name, fileinfo->name, 8);
1561 }
1562
1563 if (reload_filename)
1564 close (handle);
1565
1566 return 1;
1567 }
1568 */
1569 #endif
1570