]> icculus.org git repositories - theoddone33/hheretic.git/blob - base/w_wad.c
Redo makefile, delete oss driver, fix some c99 errors, default to clang
[theoddone33/hheretic.git] / base / w_wad.c
1 // W_wad.c
2
3 #ifdef NeXT
4 #include <libc.h>
5 #include <ctype.h>
6
7 #else
8 // next doesn't need a binary flag in open call
9 #define O_BINARY        0
10
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <fcntl.h>
15 #include <sys/stat.h>
16 #include <ctype.h>
17 #include <unistd.h>
18 #endif
19
20 #include "doomdef.h"
21
22 //===============
23 //   TYPES
24 //===============
25
26
27 typedef struct
28 {
29         char            identification[4];              // should be IWAD
30         int                     numlumps;
31         int                     infotableofs;
32 } wadinfo_t;
33
34
35 typedef struct
36 {
37         int                     filepos;
38         int                     size;
39         char            name[8];
40 } filelump_t;
41
42
43 //=============
44 // GLOBALS
45 //=============
46
47 lumpinfo_t      *lumpinfo;              // location of each lump on disk
48 int                     numlumps;
49
50 void            **lumpcache;
51
52
53 //===================
54
55
56 #define strcmpi strcasecmp
57
58 void strupr (char *s)
59 {
60     while (*s)
61     {
62         *s = toupper(*s);
63         s++;
64     }
65 }
66
67 /*
68 ================
69 =
70 = filelength
71 =
72 ================
73 */
74
75 int filelength (int handle)
76 {
77     struct stat fileinfo;
78     
79     if (fstat (handle,&fileinfo) == -1)
80         I_Error ("Error fstating");
81
82     return fileinfo.st_size;
83 }
84
85
86
87 void ExtractFileBase (char *path, char *dest)
88 {
89         char    *src;
90         int             length;
91
92         src = path + strlen(path) - 1;
93
94 //
95 // back up until a \ or the start
96 //
97         while (src != path && *(src-1) != '\\' && *(src-1) != '/')
98                 src--;
99
100 //
101 // copy up to eight characters
102 //
103         memset (dest,0,8);
104         length = 0;
105         while (*src && *src != '.')
106         {
107                 if (++length == 9)
108                         I_Error ("Filename base of %s >8 chars",path);
109                 *dest++ = toupper((int)*src++);
110         }
111 }
112
113 /*
114 ============================================================================
115
116                                                 LUMP BASED ROUTINES
117
118 ============================================================================
119 */
120
121 /*
122 ====================
123 =
124 = W_AddFile
125 =
126 = All files are optional, but at least one file must be found
127 = Files with a .wad extension are wadlink files with multiple lumps
128 = Other files are single lumps with the base filename for the lump name
129 =
130 ====================
131 */
132
133 void W_AddFile (char *filename)
134 {
135         wadinfo_t               header;
136         lumpinfo_t              *lump_p;
137         unsigned                i;
138         int                             handle, length;
139         int                             startlump;
140         filelump_t              *fileinfo, singleinfo;
141         
142 //
143 // open the file and add to directory
144 //      
145         if ( (handle = open (filename,O_RDONLY | O_BINARY)) == -1)
146                 return;
147
148         startlump = numlumps;
149         
150         if (strcmpi (filename+strlen(filename)-3 , "wad" ) )
151         {
152         // single lump file
153                 fileinfo = &singleinfo;
154                 singleinfo.filepos = 0;
155                 singleinfo.size = LONG(filelength(handle));
156                 ExtractFileBase (filename, singleinfo.name);
157                 numlumps++;
158         }
159         else 
160         {
161         // WAD file
162                 read (handle, &header, sizeof(header));
163                 if (strncmp(header.identification,"IWAD",4))
164                 {
165                         if (strncmp(header.identification,"PWAD",4))
166                                 I_Error ("Wad file %s doesn't have IWAD or PWAD id\n"
167                                 ,filename);
168                 }
169                 header.numlumps = LONG(header.numlumps);
170                 header.infotableofs = LONG(header.infotableofs);
171                 length = header.numlumps*sizeof(filelump_t);
172                 fileinfo = alloca (length);
173                 lseek (handle, header.infotableofs, SEEK_SET);
174                 read (handle, fileinfo, length);
175                 numlumps += header.numlumps;
176         }
177
178 //
179 // Fill in lumpinfo
180 //
181         lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
182         if (!lumpinfo)
183                 I_Error ("Couldn't realloc lumpinfo");
184         lump_p = &lumpinfo[startlump];
185         
186         for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++)
187         {
188                 lump_p->handle = handle;
189                 lump_p->position = LONG(fileinfo->filepos);
190                 lump_p->size = LONG(fileinfo->size);
191                 strncpy (lump_p->name, fileinfo->name, 8);
192         }
193 }
194
195
196
197
198
199 /*
200 ====================
201 =
202 = W_InitMultipleFiles
203 =
204 = Pass a null terminated list of files to use.
205 =
206 = All files are optional, but at least one file must be found
207 =
208 = Files with a .wad extension are idlink files with multiple lumps
209 =
210 = Other files are single lumps with the base filename for the lump name
211 =
212 = Lump names can appear multiple times. The name searcher looks backwards,
213 = so a later file can override an earlier one.
214 =
215 ====================
216 */
217
218 void W_InitMultipleFiles (char **filenames)
219 {       
220         int             size;
221         
222 //
223 // open all the files, load headers, and count lumps
224 //
225         numlumps = 0;
226         lumpinfo = malloc(1);   // will be realloced as lumps are added
227
228         for ( ; *filenames ; filenames++)
229                 W_AddFile (*filenames);
230
231         if (!numlumps)
232                 I_Error ("W_InitFiles: no files found");
233                 
234 //
235 // set up caching
236 //
237         size = numlumps * sizeof(*lumpcache);
238         lumpcache = malloc (size);
239         if (!lumpcache)
240                 I_Error ("Couldn't allocate lumpcache");
241         memset (lumpcache,0, size);
242 }
243
244
245
246 /*
247 ====================
248 =
249 = W_InitFile
250 =
251 = Just initialize from a single file
252 =
253 ====================
254 */
255
256 void W_InitFile (char *filename)
257 {
258         char    *names[2];
259
260         names[0] = filename;
261         names[1] = NULL;
262         W_InitMultipleFiles (names);
263 }
264
265
266
267 /*
268 ====================
269 =
270 = W_NumLumps
271 =
272 ====================
273 */
274
275 int     W_NumLumps (void)
276 {
277         return numlumps;
278 }
279
280
281
282 /*
283 ====================
284 =
285 = W_CheckNumForName
286 =
287 = Returns -1 if name not found
288 =
289 ====================
290 */
291
292 int     W_CheckNumForName (char *name)
293 {
294         char    name8[9];
295         int             v1,v2;
296         lumpinfo_t      *lump_p;
297
298 // make the name into two integers for easy compares
299
300         strncpy (name8,name,8);
301         name8[8] = 0;                   // in case the name was a fill 8 chars
302         strupr (name8);                 // case insensitive
303
304         v1 = *(int *)name8;
305         v2 = *(int *)&name8[4];
306
307
308 // scan backwards so patch lump files take precedence
309
310         lump_p = lumpinfo + numlumps;
311
312         while (lump_p-- != lumpinfo)
313         {
314                 if(*(int *)lump_p->name == v1 && *(int *)&lump_p->name[4] == v2)
315                 {
316                         return lump_p-lumpinfo;
317                 }
318         }
319         return -1;
320 }
321
322
323 /*
324 ====================
325 =
326 = W_GetNumForName
327 =
328 = Calls W_CheckNumForName, but bombs out if not found
329 =
330 ====================
331 */
332
333 int     W_GetNumForName (char *name)
334 {
335         int     i;
336
337         i = W_CheckNumForName (name);
338         if (i != -1)
339                 return i;
340
341         I_Error ("W_GetNumForName: %s not found!",name);
342         return -1;
343 }
344
345
346 /*
347 ====================
348 =
349 = W_LumpLength
350 =
351 = Returns the buffer size needed to load the given lump
352 =
353 ====================
354 */
355
356 int W_LumpLength (int lump)
357 {
358         if (lump >= numlumps)
359                 I_Error ("W_LumpLength: %i >= numlumps",lump);
360         return lumpinfo[lump].size;
361 }
362
363
364 /*
365 ====================
366 =
367 = W_ReadLump
368 =
369 = Loads the lump into the given buffer, which must be >= W_LumpLength()
370 =
371 ====================
372 */
373
374 void W_ReadLump (int lump, void *dest)
375 {
376         int                     c;
377         lumpinfo_t      *l;
378         
379         if (lump >= numlumps)
380                 I_Error ("W_ReadLump: %i >= numlumps",lump);
381         l = lumpinfo+lump;
382         
383         
384         lseek (l->handle, l->position, SEEK_SET);
385         c = read (l->handle, dest, l->size);
386         if (c < l->size)
387                 I_Error ("W_ReadLump: only read %i of %i on lump %i",c,l->size,lump);   
388 }
389
390
391
392 /*
393 ====================
394 =
395 = W_CacheLumpNum
396 =
397 ====================
398 */
399
400 void    *W_CacheLumpNum (int lump, int tag)
401 {
402 byte *ptr;
403
404         if ((unsigned)lump >= numlumps)
405                 I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
406                 
407         if (!lumpcache[lump])
408         {       // read the lump in
409 //printf ("cache miss on lump %i\n",lump);
410                 ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
411                 W_ReadLump (lump, lumpcache[lump]);
412         }
413         else
414         {
415 //printf ("cache hit on lump %i\n",lump);
416                 Z_ChangeTag (lumpcache[lump],tag);
417         }
418         
419         return lumpcache[lump];
420 }
421
422
423 /*
424 ====================
425 =
426 = W_CacheLumpName
427 =
428 ====================
429 */
430
431 void    *W_CacheLumpName (char *name, int tag)
432 {
433         return W_CacheLumpNum (W_GetNumForName(name), tag);
434 }
435
436
437 /*
438 ====================
439 =
440 = W_Profile
441 =
442 ====================
443 */
444
445 // Ripped out for Heretic
446 /*
447 int     info[2500][10];
448 int     profilecount;
449
450 void W_Profile (void)
451 {
452         int             i;
453         memblock_t      *block;
454         void    *ptr;
455         char    ch;
456         FILE    *f;
457         int             j;
458         char    name[9];
459         
460         
461         for (i=0 ; i<numlumps ; i++)
462         {       
463                 ptr = lumpcache[i];
464                 if (!ptr)
465                 {
466                         ch = ' ';
467                         continue;
468                 }
469                 else
470                 {
471                         block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
472                         if (block->tag < PU_PURGELEVEL)
473                                 ch = 'S';
474                         else
475                                 ch = 'P';
476                 }
477                 info[i][profilecount] = ch;
478         }
479         profilecount++;
480         
481         f = fopen ("waddump.txt","w");
482         name[8] = 0;
483         for (i=0 ; i<numlumps ; i++)
484         {
485                 memcpy (name,lumpinfo[i].name,8);
486                 for (j=0 ; j<8 ; j++)
487                         if (!name[j])
488                                 break;
489                 for ( ; j<8 ; j++)
490                         name[j] = ' ';
491                 fprintf (f,"%s ",name);
492                 for (j=0 ; j<profilecount ; j++)
493                         fprintf (f,"    %c",info[i][j]);
494                 fprintf (f,"\n");
495         }
496         fclose (f);
497 }
498 */
499
500 void W_Shutdown (void)
501 {
502         free (lumpinfo);
503         free (lumpcache);
504 }