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