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