Rev 298 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
298 | serge | 1 | // Emacs style mode select -*- C++ -*- |
2 | //----------------------------------------------------------------------------- |
||
3 | // |
||
4 | // $Id:$ |
||
5 | // |
||
6 | // Copyright (C) 1993-1996 by id Software, Inc. |
||
7 | // |
||
8 | // This source is available for distribution and/or modification |
||
9 | // only under the terms of the DOOM Source Code License as |
||
10 | // published by id Software. All rights reserved. |
||
11 | // |
||
12 | // The source is distributed in the hope that it will be useful, |
||
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License |
||
15 | // for more details. |
||
16 | // |
||
17 | // $Log:$ |
||
18 | // |
||
19 | // DESCRIPTION: |
||
20 | // Handles WAD file header, directory, lump I/O. |
||
21 | // |
||
22 | //----------------------------------------------------------------------------- |
||
23 | |||
24 | |||
25 | static const char |
||
26 | rcsid[] = "$Id: w_wad.c,v 1.5 1997/02/03 16:47:57 b1 Exp $"; |
||
27 | |||
28 | |||
29 | #include |
||
30 | #include |
||
31 | #include |
||
32 | #include |
||
33 | |||
34 | #include "m_swap.h" |
||
35 | #include "doomtype.h" |
||
36 | #include "i_system.h" |
||
37 | #include "z_zone.h" |
||
38 | #include "w_wad.h" |
||
39 | |||
40 | #include |
||
41 | |||
42 | |||
43 | // |
||
44 | // GLOBALS |
||
45 | // |
||
46 | |||
47 | // Location of each lump on disk. |
||
48 | lumpinfo_t* lumpinfo; |
||
49 | int numlumps; |
||
50 | |||
51 | void** lumpcache; |
||
52 | |||
53 | |||
54 | int filelength (FILE *handle) |
||
55 | { |
||
56 | unsigned long pos, size; |
||
57 | |||
58 | pos = ftell(handle); |
||
59 | fseek(handle, 0, SEEK_END); |
||
60 | size = ftell(handle); |
||
61 | fseek(handle, pos, SEEK_SET); |
||
62 | return (int)size; |
||
63 | } |
||
64 | |||
65 | |||
66 | void |
||
67 | ExtractFileBase |
||
68 | ( char* path, |
||
69 | char* dest ) |
||
70 | { |
||
71 | char* src; |
||
72 | int length; |
||
73 | |||
74 | src = path + strlen(path) - 1; |
||
75 | |||
76 | // back up until a \ or the start |
||
77 | while (src != path |
||
78 | && *(src-1) != '\\' |
||
79 | && *(src-1) != '/') |
||
80 | { |
||
81 | src--; |
||
82 | } |
||
83 | |||
84 | // copy up to eight characters |
||
85 | memset (dest,0,8); |
||
86 | length = 0; |
||
87 | |||
88 | while (*src && *src != '.') |
||
89 | { |
||
90 | if (++length == 9) |
||
91 | I_Error ("Filename base of %s >8 chars",path); |
||
92 | |||
93 | *dest++ = toupper((int)*src++); |
||
94 | } |
||
95 | } |
||
96 | |||
97 | |||
98 | |||
99 | |||
100 | |||
101 | // |
||
102 | // LUMP BASED ROUTINES. |
||
103 | // |
||
104 | |||
105 | // |
||
106 | // W_AddFile |
||
107 | // All files are optional, but at least one file must be |
||
108 | // found (PWAD, if all required lumps are present). |
||
109 | // Files with a .wad extension are wadlink files |
||
110 | // with multiple lumps. |
||
111 | // Other files are single lumps with the base filename |
||
112 | // for the lump name. |
||
113 | // |
||
114 | // If filename starts with a tilde, the file is handled |
||
115 | // specially to allow map reloads. |
||
116 | // But: the reload feature is a fragile hack... |
||
117 | |||
118 | #ifdef __BEOS__ |
||
119 | #ifdef __GNUC__ |
||
120 | extern void *alloca(int); |
||
121 | #else |
||
122 | #include |
||
123 | #endif |
||
124 | #endif /* __BEOS__ */ |
||
125 | |||
126 | int reloadlump; |
||
127 | char* reloadname; |
||
128 | |||
129 | |||
130 | void W_AddFile (char *filename) |
||
131 | { |
||
132 | wadinfo_t header; |
||
133 | lumpinfo_t* lump_p; |
||
134 | unsigned i; |
||
135 | FILE *handle; |
||
136 | int length; |
||
137 | int startlump; |
||
138 | filelump_t* fileinfo; |
||
139 | filelump_t singleinfo; |
||
140 | int storehandle; |
||
141 | |||
142 | // open the file and add to directory |
||
143 | |||
144 | // handle reload indicator. |
||
145 | if (filename[0] == '~') |
||
146 | { |
||
147 | filename++; |
||
148 | reloadname = filename; |
||
149 | reloadlump = numlumps; |
||
150 | } |
||
151 | |||
152 | if ( (handle = fopen (filename,"rb")) == NULL) |
||
153 | { |
||
154 | printf (" couldn't open %s\n",filename); |
||
155 | return; |
||
156 | } |
||
157 | |||
158 | printf (" adding %s\n",filename); |
||
159 | startlump = numlumps; |
||
160 | |||
161 | if (I_strncasecmp (filename+strlen(filename)-3 , "wad", 3 ) ) |
||
162 | { |
||
163 | // single lump file |
||
164 | fileinfo = &singleinfo; |
||
165 | singleinfo.filepos = 0; |
||
166 | singleinfo.size = LONG(filelength(handle)); |
||
167 | ExtractFileBase (filename, singleinfo.name); |
||
168 | numlumps++; |
||
169 | } |
||
170 | else |
||
171 | { |
||
172 | //WAD file |
||
173 | printf("f1 at %x,%u\n",&header,handle); |
||
174 | fread (&header, 1, sizeof(header), handle); |
||
175 | printf("f2\n"); |
||
176 | if (strncmp(header.identification,"IWAD",4)) |
||
177 | { |
||
178 | printf("No IWAD id\n"); |
||
179 | // Homebrew levels? |
||
180 | if (strncmp(header.identification,"PWAD",4)) |
||
181 | { |
||
182 | I_Error ("Wad file %s doesn't have IWAD " |
||
183 | "or PWAD id\n", filename); |
||
184 | } |
||
185 | // printf("WAD magic OK\n"); |
||
186 | // ???modifiedgame = true; |
||
187 | } |
||
188 | printf("after checking hdr\n"); |
||
189 | header.numlumps = LONG(header.numlumps); |
||
190 | printf("%u lumps in WAD\n",header.numlumps); |
||
191 | header.infotableofs = LONG(header.infotableofs); |
||
192 | printf("infor table at %x\n",header.infotableofs); |
||
193 | length = header.numlumps*sizeof(filelump_t); |
||
194 | printf("length %u\n",length); |
||
195 | fileinfo = alloca(length); |
||
196 | |||
197 | printf("seeking to info table\n"); |
||
198 | fseek (handle, header.infotableofs, SEEK_SET); |
||
199 | printf("f3\n"); |
||
200 | fread (fileinfo, 1, length, handle); |
||
201 | printf("f4\n"); |
||
202 | numlumps += header.numlumps; |
||
203 | } |
||
204 | |||
205 | |||
206 | // Fill in lumpinfo |
||
207 | lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t)); |
||
208 | |||
209 | if (!lumpinfo) |
||
210 | I_Error ("Couldn't realloc lumpinfo"); |
||
211 | |||
212 | lump_p = &lumpinfo[startlump]; |
||
213 | |||
214 | storehandle = reloadname ? -1 : (int)handle; |
||
215 | |||
216 | for (i=startlump ; i |
||
217 | { |
||
218 | lump_p->handle = storehandle; |
||
219 | lump_p->position = LONG(fileinfo->filepos); |
||
220 | lump_p->size = LONG(fileinfo->size); |
||
221 | strncpy (lump_p->name, fileinfo->name, 8); |
||
222 | } |
||
223 | |||
224 | if (reloadname) |
||
225 | fclose (handle); |
||
226 | } |
||
227 | |||
228 | |||
229 | |||
230 | |||
231 | // |
||
232 | // W_Reload |
||
233 | // Flushes any of the reloadable lumps in memory |
||
234 | // and reloads the directory. |
||
235 | // |
||
236 | void W_Reload (void) |
||
237 | { |
||
238 | wadinfo_t header; |
||
239 | int lumpcount; |
||
240 | lumpinfo_t* lump_p; |
||
241 | unsigned i; |
||
242 | FILE *handle; |
||
243 | int length; |
||
244 | filelump_t* fileinfo; |
||
245 | |||
246 | if (!reloadname) |
||
247 | return; |
||
248 | |||
249 | if ( (handle = fopen (reloadname,"rb")) == NULL) |
||
250 | I_Error ("W_Reload: couldn't open %s",reloadname); |
||
251 | |||
252 | printf("f5\n"); |
||
253 | fread (&header, 1, sizeof(header), handle); |
||
254 | printf("f6\n"); |
||
255 | lumpcount = LONG(header.numlumps); |
||
256 | header.infotableofs = LONG(header.infotableofs); |
||
257 | length = lumpcount*sizeof(filelump_t); |
||
258 | fileinfo = malloc (length); |
||
259 | fseek (handle, header.infotableofs, SEEK_SET); |
||
260 | printf("f7\n"); |
||
261 | fread (fileinfo, 1, length, handle); |
||
262 | printf("f8\n"); |
||
263 | |||
264 | // Fill in lumpinfo |
||
265 | lump_p = &lumpinfo[reloadlump]; |
||
266 | |||
267 | for (i=reloadlump ; |
||
268 | i |
||
269 | i++,lump_p++, fileinfo++) |
||
270 | { |
||
271 | if (lumpcache[i]) |
||
272 | Z_Free (lumpcache[i]); |
||
273 | |||
274 | lump_p->position = LONG(fileinfo->filepos); |
||
275 | lump_p->size = LONG(fileinfo->size); |
||
276 | } |
||
277 | |||
278 | fclose (handle); |
||
279 | } |
||
280 | |||
281 | |||
282 | |||
283 | // |
||
284 | // W_InitMultipleFiles |
||
285 | // Pass a null terminated list of files to use. |
||
286 | // All files are optional, but at least one file |
||
287 | // must be found. |
||
288 | // Files with a .wad extension are idlink files |
||
289 | // with multiple lumps. |
||
290 | // Other files are single lumps with the base filename |
||
291 | // for the lump name. |
||
292 | // Lump names can appear multiple times. |
||
293 | // The name searcher looks backwards, so a later file |
||
294 | // does override all earlier ones. |
||
295 | // |
||
296 | void W_InitMultipleFiles (char** filenames) |
||
297 | { |
||
298 | int size; |
||
299 | |||
300 | // open all the files, load headers, and count lumps |
||
301 | numlumps = 0; |
||
302 | |||
303 | // will be realloced as lumps are added |
||
304 | lumpinfo = malloc(1); |
||
305 | |||
306 | for ( ; *filenames ; filenames++) |
||
307 | W_AddFile (*filenames); |
||
308 | |||
309 | if (!numlumps) |
||
310 | I_Error ("W_InitFiles: no files found"); |
||
311 | |||
312 | // set up caching |
||
313 | size = numlumps * sizeof(*lumpcache); |
||
314 | lumpcache = malloc (size); |
||
315 | |||
316 | if (!lumpcache) |
||
317 | I_Error ("Couldn't allocate lumpcache"); |
||
318 | |||
319 | memset (lumpcache,0, size); |
||
320 | } |
||
321 | |||
322 | |||
323 | |||
324 | |||
325 | // |
||
326 | // W_InitFile |
||
327 | // Just initialize from a single file. |
||
328 | // |
||
329 | void W_InitFile (char* filename) |
||
330 | { |
||
331 | char* names[2]; |
||
332 | |||
333 | names[0] = filename; |
||
334 | names[1] = NULL; |
||
335 | W_InitMultipleFiles (names); |
||
336 | } |
||
337 | |||
338 | |||
339 | |||
340 | // |
||
341 | // W_NumLumps |
||
342 | // |
||
343 | int W_NumLumps (void) |
||
344 | { |
||
345 | return numlumps; |
||
346 | } |
||
347 | |||
348 | |||
349 | |||
350 | // |
||
351 | // W_CheckNumForName |
||
352 | // Returns -1 if name not found. |
||
353 | // |
||
354 | |||
355 | int W_CheckNumForName (char* name) |
||
356 | { |
||
357 | union { |
||
358 | char s[9]; |
||
359 | int x[2]; |
||
360 | |||
361 | } name8; |
||
362 | |||
363 | int v1; |
||
364 | int v2; |
||
365 | lumpinfo_t* lump_p; |
||
366 | |||
367 | // make the name into two integers for easy compares |
||
368 | strncpy (name8.s,name,8); |
||
369 | |||
370 | // in case the name was a fill 8 chars |
||
371 | name8.s[8] = 0; |
||
372 | |||
373 | // case insensitive |
||
374 | strupr (name8.s); |
||
375 | |||
376 | v1 = name8.x[0]; |
||
377 | v2 = name8.x[1]; |
||
378 | |||
379 | |||
380 | // scan backwards so patch lump files take precedence |
||
381 | lump_p = lumpinfo + numlumps; |
||
382 | |||
383 | while (lump_p-- != lumpinfo) |
||
384 | { |
||
385 | if ( *(int *)lump_p->name == v1 |
||
386 | && *(int *)&lump_p->name[4] == v2) |
||
387 | { |
||
388 | return lump_p - lumpinfo; |
||
389 | } |
||
390 | } |
||
391 | |||
392 | // TFB. Not found. |
||
393 | return -1; |
||
394 | } |
||
395 | |||
396 | |||
397 | |||
398 | |||
399 | // |
||
400 | // W_GetNumForName |
||
401 | // Calls W_CheckNumForName, but bombs out if not found. |
||
402 | // |
||
403 | int W_GetNumForName (char* name) |
||
404 | { |
||
405 | int i; |
||
406 | |||
407 | i = W_CheckNumForName (name); |
||
408 | |||
409 | if (i == -1) |
||
410 | I_Error ("W_GetNumForName: %s not found!", name); |
||
411 | |||
412 | return i; |
||
413 | } |
||
414 | |||
415 | |||
416 | // |
||
417 | // W_LumpLength |
||
418 | // Returns the buffer size needed to load the given lump. |
||
419 | // |
||
420 | int W_LumpLength (int lump) |
||
421 | { |
||
422 | if (lump >= numlumps) |
||
423 | I_Error ("W_LumpLength: %i >= numlumps",lump); |
||
424 | |||
425 | return lumpinfo[lump].size; |
||
426 | } |
||
427 | |||
428 | |||
429 | |||
430 | // |
||
431 | // W_ReadLump |
||
432 | // Loads the lump into the given buffer, |
||
433 | // which must be >= W_LumpLength(). |
||
434 | // |
||
435 | void |
||
436 | W_ReadLump |
||
437 | ( int lump, |
||
438 | void* dest ) |
||
439 | { |
||
440 | int c; |
||
441 | lumpinfo_t* l; |
||
442 | FILE *handle; |
||
443 | |||
444 | if (lump >= numlumps) |
||
445 | I_Error ("W_ReadLump: %i >= numlumps",lump); |
||
446 | |||
447 | l = lumpinfo+lump; |
||
448 | |||
449 | // ??? I_BeginRead (); |
||
450 | |||
451 | if (l->handle == -1) |
||
452 | { |
||
453 | // reloadable file, so use open / read / close |
||
454 | if ( (handle = fopen (reloadname,"rb")) == NULL) |
||
455 | I_Error ("W_ReadLump: couldn't open %s",reloadname); |
||
456 | } |
||
457 | else |
||
458 | handle = (FILE *)l->handle; |
||
459 | |||
460 | fseek (handle, l->position, SEEK_SET); |
||
461 | c = fread (dest, 1, l->size, handle); |
||
462 | if (c < l->size) |
||
463 | I_Error ("W_ReadLump: only read %i of %i on lump %i", |
||
464 | c,l->size,lump); |
||
465 | |||
466 | if (l->handle == -1) |
||
467 | fclose (handle); |
||
468 | |||
469 | // ??? I_EndRead (); |
||
470 | } |
||
471 | |||
472 | |||
473 | |||
474 | |||
475 | // |
||
476 | // W_CacheLumpNum |
||
477 | // |
||
478 | void* |
||
479 | W_CacheLumpNum |
||
480 | ( int lump, |
||
481 | int tag ) |
||
482 | { |
||
483 | byte* ptr; |
||
484 | |||
485 | if ((unsigned)lump >= numlumps) |
||
486 | I_Error ("W_CacheLumpNum: %i >= numlumps",lump); |
||
487 | |||
488 | if (!lumpcache[lump]) |
||
489 | { |
||
490 | // read the lump in |
||
491 | |||
492 | //printf ("cache miss on lump %i\n",lump); |
||
493 | ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]); |
||
494 | W_ReadLump (lump, lumpcache[lump]); |
||
495 | } |
||
496 | else |
||
497 | { |
||
498 | //printf ("cache hit on lump %i\n",lump); |
||
499 | Z_ChangeTag (lumpcache[lump],tag); |
||
500 | } |
||
501 | |||
502 | return lumpcache[lump]; |
||
503 | } |
||
504 | |||
505 | |||
506 | |||
507 | // |
||
508 | // W_CacheLumpName |
||
509 | // |
||
510 | void* |
||
511 | W_CacheLumpName |
||
512 | ( char* name, |
||
513 | int tag ) |
||
514 | { |
||
515 | return W_CacheLumpNum (W_GetNumForName(name), tag); |
||
516 | } |
||
517 | |||
300 | serge | 518 | #if 0 |
298 | serge | 519 | |
520 | // |
||
521 | // W_Profile |
||
522 | // |
||
523 | int info[2500][10]; |
||
524 | int profilecount; |
||
525 | |||
526 | void W_Profile (void) |
||
527 | { |
||
528 | int i; |
||
529 | memblock_t* block; |
||
530 | void* ptr; |
||
531 | char ch; |
||
532 | FILE* f; |
||
533 | int j; |
||
534 | char name[9]; |
||
535 | |||
536 | |||
537 | for (i=0 ; i |
||
538 | { |
||
539 | ptr = lumpcache[i]; |
||
540 | if (!ptr) |
||
541 | { |
||
542 | ch = ' '; |
||
543 | continue; |
||
544 | } |
||
545 | else |
||
546 | { |
||
547 | block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); |
||
548 | if (block->tag < PU_PURGELEVEL) |
||
549 | ch = 'S'; |
||
550 | else |
||
551 | ch = 'P'; |
||
552 | } |
||
553 | info[i][profilecount] = ch; |
||
554 | } |
||
555 | profilecount++; |
||
556 | |||
557 | f = fopen ("waddump.txt","w"); |
||
558 | name[8] = 0; |
||
559 | |||
560 | for (i=0 ; i |
||
561 | { |
||
562 | memcpy (name,lumpinfo[i].name,8); |
||
563 | |||
564 | for (j=0 ; j<8 ; j++) |
||
565 | if (!name[j]) |
||
566 | break; |
||
567 | |||
568 | for ( ; j<8 ; j++) |
||
569 | name[j] = ' '; |
||
570 | |||
300 | serge | 571 | printf ("%s ",name); |
298 | serge | 572 | |
573 | for (j=0 ; j |
||
574 | fprintf (f," %c",info[i][j]); |
||
575 | |||
300 | serge | 576 | printf ("\n"); |
298 | serge | 577 | } |
578 | fclose (f); |
||
579 | } |
||
580 | |||
300 | serge | 581 | #endif8>8>>> |