Rev 333 | 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 | } |
342 | serge | 154 | |
155 | printf("open file %s\n\r",filename); |
||
333 | serge | 156 | |
298 | serge | 157 | if ( (handle = fopen (filename,"rb")) == NULL) |
158 | { |
||
333 | serge | 159 | printf (" couldn't open %s\n",filename); |
160 | return; |
||
298 | serge | 161 | } |
162 | |||
333 | serge | 163 | printf (" adding %s\n\r",filename); |
298 | serge | 164 | startlump = numlumps; |
333 | serge | 165 | |
166 | if (strnicmp (filename+strlen(filename)-3 , "wad", 3 ) ) |
||
298 | serge | 167 | { |
333 | serge | 168 | // single lump file |
169 | fileinfo = &singleinfo; |
||
170 | singleinfo.filepos = 0; |
||
171 | singleinfo.size = FileSize(handle); |
||
172 | ExtractFileBase (filename, singleinfo.name); |
||
173 | numlumps++; |
||
298 | serge | 174 | } |
175 | else |
||
176 | { |
||
333 | serge | 177 | //WAD file |
178 | fread (&header, 1, sizeof(header), handle); |
||
179 | |||
180 | if (strncmp(header.identification,"IWAD",4)) |
||
181 | { |
||
182 | printf("No IWAD id\n"); |
||
183 | // Homebrew levels? |
||
184 | if (strncmp(header.identification,"PWAD",4)) |
||
185 | { |
||
186 | I_Error ("Wad file %s doesn't have IWAD " |
||
187 | "or PWAD id\n", filename); |
||
188 | } |
||
189 | printf("WAD magic OK\n"); |
||
190 | // ???modifiedgame = true; |
||
191 | } |
||
192 | header.numlumps = LONG(header.numlumps); |
||
193 | |||
194 | header.infotableofs = LONG(header.infotableofs); |
||
195 | |||
196 | length = header.numlumps*sizeof(filelump_t); |
||
197 | |||
198 | fileinfo = alloca(length); |
||
199 | |||
200 | fseek (handle, header.infotableofs, SEEK_SET); |
||
201 | fread (fileinfo, 1, length, handle); |
||
202 | numlumps += header.numlumps; |
||
298 | serge | 203 | } |
204 | |||
205 | |||
206 | // Fill in lumpinfo |
||
207 | lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t)); |
||
208 | |||
209 | if (!lumpinfo) |
||
333 | serge | 210 | I_Error ("Couldn't realloc lumpinfo"); |
298 | serge | 211 | |
212 | lump_p = &lumpinfo[startlump]; |
||
333 | serge | 213 | |
298 | serge | 214 | storehandle = reloadname ? -1 : (int)handle; |
333 | serge | 215 | |
298 | serge | 216 | for (i=startlump ; i |
217 | { |
||
333 | serge | 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); |
||
298 | serge | 222 | } |
333 | serge | 223 | |
298 | serge | 224 | if (reloadname) |
333 | serge | 225 | fclose (handle); |
298 | serge | 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 | { |
||
333 | serge | 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 | |||
298 | serge | 246 | if (!reloadname) |
333 | serge | 247 | return; |
248 | |||
298 | serge | 249 | if ( (handle = fopen (reloadname,"rb")) == NULL) |
333 | serge | 250 | I_Error ("W_Reload: couldn't open %s",reloadname); |
298 | serge | 251 | |
252 | fread (&header, 1, sizeof(header), handle); |
||
333 | serge | 253 | |
298 | serge | 254 | lumpcount = LONG(header.numlumps); |
255 | header.infotableofs = LONG(header.infotableofs); |
||
256 | length = lumpcount*sizeof(filelump_t); |
||
257 | fileinfo = malloc (length); |
||
258 | fseek (handle, header.infotableofs, SEEK_SET); |
||
259 | fread (fileinfo, 1, length, handle); |
||
260 | |||
261 | // Fill in lumpinfo |
||
262 | lump_p = &lumpinfo[reloadlump]; |
||
333 | serge | 263 | |
298 | serge | 264 | for (i=reloadlump ; |
333 | serge | 265 | i |
266 | i++,lump_p++, fileinfo++) |
||
298 | serge | 267 | { |
333 | serge | 268 | if (lumpcache[i]) |
269 | Z_Free (lumpcache[i]); |
||
298 | serge | 270 | |
333 | serge | 271 | lump_p->position = LONG(fileinfo->filepos); |
272 | lump_p->size = LONG(fileinfo->size); |
||
298 | serge | 273 | } |
333 | serge | 274 | |
298 | serge | 275 | fclose (handle); |
276 | } |
||
277 | |||
278 | // |
||
279 | // W_InitMultipleFiles |
||
280 | // Pass a null terminated list of files to use. |
||
281 | // All files are optional, but at least one file |
||
282 | // must be found. |
||
283 | // Files with a .wad extension are idlink files |
||
284 | // with multiple lumps. |
||
285 | // Other files are single lumps with the base filename |
||
286 | // for the lump name. |
||
287 | // Lump names can appear multiple times. |
||
288 | // The name searcher looks backwards, so a later file |
||
289 | // does override all earlier ones. |
||
290 | // |
||
291 | void W_InitMultipleFiles (char** filenames) |
||
333 | serge | 292 | { |
293 | int size; |
||
298 | serge | 294 | |
295 | // open all the files, load headers, and count lumps |
||
296 | numlumps = 0; |
||
297 | |||
298 | // will be realloced as lumps are added |
||
333 | serge | 299 | lumpinfo = malloc(16384); |
298 | serge | 300 | |
301 | for ( ; *filenames ; filenames++) |
||
333 | serge | 302 | W_AddFile (*filenames); |
298 | serge | 303 | |
304 | if (!numlumps) |
||
333 | serge | 305 | I_Error ("W_InitFiles: no files found"); |
298 | serge | 306 | |
307 | // set up caching |
||
308 | size = numlumps * sizeof(*lumpcache); |
||
309 | lumpcache = malloc (size); |
||
310 | |||
311 | if (!lumpcache) |
||
333 | serge | 312 | I_Error ("Couldn't allocate lumpcache"); |
298 | serge | 313 | |
314 | memset (lumpcache,0, size); |
||
315 | } |
||
316 | |||
317 | |||
318 | |||
319 | |||
320 | // |
||
321 | // W_InitFile |
||
322 | // Just initialize from a single file. |
||
323 | // |
||
324 | void W_InitFile (char* filename) |
||
325 | { |
||
333 | serge | 326 | char* names[2]; |
298 | serge | 327 | |
328 | names[0] = filename; |
||
329 | names[1] = NULL; |
||
330 | W_InitMultipleFiles (names); |
||
331 | } |
||
332 | |||
333 | |||
334 | |||
335 | // |
||
336 | // W_NumLumps |
||
337 | // |
||
338 | int W_NumLumps (void) |
||
339 | { |
||
340 | return numlumps; |
||
341 | } |
||
342 | |||
343 | |||
344 | |||
345 | // |
||
346 | // W_CheckNumForName |
||
347 | // Returns -1 if name not found. |
||
348 | // |
||
349 | |||
350 | int W_CheckNumForName (char* name) |
||
351 | { |
||
352 | union { |
||
333 | serge | 353 | char s[9]; |
354 | int x[2]; |
||
355 | |||
298 | serge | 356 | } name8; |
357 | |||
333 | serge | 358 | int v1; |
359 | int v2; |
||
360 | lumpinfo_t* lump_p; |
||
298 | serge | 361 | |
362 | // make the name into two integers for easy compares |
||
363 | strncpy (name8.s,name,8); |
||
364 | |||
365 | // in case the name was a fill 8 chars |
||
366 | name8.s[8] = 0; |
||
367 | |||
368 | // case insensitive |
||
333 | serge | 369 | strupr (name8.s); |
298 | serge | 370 | |
371 | v1 = name8.x[0]; |
||
372 | v2 = name8.x[1]; |
||
373 | |||
374 | |||
375 | // scan backwards so patch lump files take precedence |
||
376 | lump_p = lumpinfo + numlumps; |
||
377 | |||
378 | while (lump_p-- != lumpinfo) |
||
379 | { |
||
333 | serge | 380 | if ( *(int *)lump_p->name == v1 |
381 | && *(int *)&lump_p->name[4] == v2) |
||
382 | { |
||
383 | return lump_p - lumpinfo; |
||
384 | } |
||
298 | serge | 385 | } |
386 | |||
387 | // TFB. Not found. |
||
388 | return -1; |
||
389 | } |
||
390 | |||
391 | |||
392 | |||
393 | |||
394 | // |
||
395 | // W_GetNumForName |
||
396 | // Calls W_CheckNumForName, but bombs out if not found. |
||
397 | // |
||
398 | int W_GetNumForName (char* name) |
||
399 | { |
||
333 | serge | 400 | int i; |
298 | serge | 401 | |
402 | i = W_CheckNumForName (name); |
||
403 | |||
404 | if (i == -1) |
||
405 | I_Error ("W_GetNumForName: %s not found!", name); |
||
406 | |||
407 | return i; |
||
408 | } |
||
409 | |||
410 | |||
411 | // |
||
412 | // W_LumpLength |
||
413 | // Returns the buffer size needed to load the given lump. |
||
414 | // |
||
415 | int W_LumpLength (int lump) |
||
416 | { |
||
417 | if (lump >= numlumps) |
||
333 | serge | 418 | I_Error ("W_LumpLength: %i >= numlumps",lump); |
298 | serge | 419 | |
420 | return lumpinfo[lump].size; |
||
421 | } |
||
422 | |||
423 | |||
424 | |||
425 | // |
||
426 | // W_ReadLump |
||
427 | // Loads the lump into the given buffer, |
||
428 | // which must be >= W_LumpLength(). |
||
429 | // |
||
430 | void |
||
431 | W_ReadLump |
||
333 | serge | 432 | ( int lump, |
433 | void* dest ) |
||
298 | serge | 434 | { |
333 | serge | 435 | int c; |
436 | lumpinfo_t* l; |
||
437 | FILE *handle; |
||
438 | size_t bytes; |
||
439 | |||
298 | serge | 440 | if (lump >= numlumps) |
333 | serge | 441 | I_Error ("W_ReadLump: %i >= numlumps",lump); |
298 | serge | 442 | |
443 | l = lumpinfo+lump; |
||
333 | serge | 444 | |
298 | serge | 445 | // ??? I_BeginRead (); |
333 | serge | 446 | |
298 | serge | 447 | if (l->handle == -1) |
448 | { |
||
333 | serge | 449 | // reloadable file, so use open / read / close |
450 | if ( (handle = fopen (reloadname,"rb")) == NULL) |
||
451 | I_Error ("W_ReadLump: couldn't open %s",reloadname); |
||
298 | serge | 452 | } |
453 | else |
||
333 | serge | 454 | handle = (FILE *)l->handle; |
455 | |||
298 | serge | 456 | fseek (handle, l->position, SEEK_SET); |
457 | c = fread (dest, 1, l->size, handle); |
||
458 | if (c < l->size) |
||
333 | serge | 459 | I_Error ("W_ReadLump: only read %i of %i on lump %i", |
460 | c,l->size,lump); |
||
298 | serge | 461 | |
462 | if (l->handle == -1) |
||
333 | serge | 463 | fclose (handle); |
464 | |||
298 | serge | 465 | // ??? I_EndRead (); |
466 | } |
||
467 | |||
468 | |||
469 | |||
470 | |||
471 | // |
||
472 | // W_CacheLumpNum |
||
473 | // |
||
474 | void* |
||
475 | W_CacheLumpNum |
||
333 | serge | 476 | ( int lump, |
477 | int tag ) |
||
298 | serge | 478 | { |
333 | serge | 479 | byte* ptr; |
298 | serge | 480 | |
333 | serge | 481 | if ((unsigned)lump >= (unsigned)numlumps) |
482 | I_Error ("W_CacheLumpNum: %i >= numlumps",lump); |
||
483 | |||
298 | serge | 484 | if (!lumpcache[lump]) |
485 | { |
||
333 | serge | 486 | // read the lump in |
487 | |||
488 | //printf ("cache miss on lump %i\n",lump); |
||
489 | ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]); |
||
490 | W_ReadLump (lump, lumpcache[lump]); |
||
298 | serge | 491 | } |
492 | else |
||
493 | { |
||
333 | serge | 494 | //printf ("cache hit on lump %i\n",lump); |
495 | Z_ChangeTag (lumpcache[lump],tag); |
||
298 | serge | 496 | } |
333 | serge | 497 | |
298 | serge | 498 | return lumpcache[lump]; |
499 | } |
||
500 | |||
501 | |||
502 | |||
503 | // |
||
504 | // W_CacheLumpName |
||
505 | // |
||
506 | void* |
||
507 | W_CacheLumpName |
||
333 | serge | 508 | ( char* name, |
509 | int tag ) |
||
298 | serge | 510 | { |
511 | return W_CacheLumpNum (W_GetNumForName(name), tag); |
||
512 | } |
||
513 | |||
300 | serge | 514 | #if 0 |
298 | serge | 515 | |
516 | // |
||
517 | // W_Profile |
||
518 | // |
||
333 | serge | 519 | int info[2500][10]; |
520 | int profilecount; |
||
298 | serge | 521 | |
522 | void W_Profile (void) |
||
523 | { |
||
333 | serge | 524 | int i; |
525 | memblock_t* block; |
||
526 | void* ptr; |
||
527 | char ch; |
||
528 | FILE* f; |
||
529 | int j; |
||
530 | char name[9]; |
||
531 | |||
532 | |||
298 | serge | 533 | for (i=0 ; i |
333 | serge | 534 | { |
535 | ptr = lumpcache[i]; |
||
536 | if (!ptr) |
||
537 | { |
||
538 | ch = ' '; |
||
539 | continue; |
||
540 | } |
||
541 | else |
||
542 | { |
||
543 | block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); |
||
544 | if (block->tag < PU_PURGELEVEL) |
||
545 | ch = 'S'; |
||
546 | else |
||
547 | ch = 'P'; |
||
548 | } |
||
549 | info[i][profilecount] = ch; |
||
298 | serge | 550 | } |
551 | profilecount++; |
||
333 | serge | 552 | |
298 | serge | 553 | f = fopen ("waddump.txt","w"); |
554 | name[8] = 0; |
||
555 | |||
556 | for (i=0 ; i |
||
557 | { |
||
333 | serge | 558 | memcpy (name,lumpinfo[i].name,8); |
298 | serge | 559 | |
333 | serge | 560 | for (j=0 ; j<8 ; j++) |
561 | if (!name[j]) |
||
562 | break; |
||
298 | serge | 563 | |
333 | serge | 564 | for ( ; j<8 ; j++) |
565 | name[j] = ' '; |
||
298 | serge | 566 | |
333 | serge | 567 | //printf ("%s ",name); |
298 | serge | 568 | |
333 | serge | 569 | for (j=0 ; j |
570 | fprintf (f," %c",info[i][j]); |
||
298 | serge | 571 | |
333 | serge | 572 | //printf ("\n"); |
298 | serge | 573 | } |
574 | fclose (f); |
||
575 | } |
||
576 | |||
300 | serge | 577 | #endif8>8>>> |
333 | serge | 578 |