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