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