diff options
Diffstat (limited to 'apps/plugins/doom/w_wad.c')
-rw-r--r-- | apps/plugins/doom/w_wad.c | 683 |
1 files changed, 683 insertions, 0 deletions
diff --git a/apps/plugins/doom/w_wad.c b/apps/plugins/doom/w_wad.c new file mode 100644 index 0000000000..4bd3807191 --- /dev/null +++ b/apps/plugins/doom/w_wad.c | |||
@@ -0,0 +1,683 @@ | |||
1 | /* Emacs style mode select -*- C++ -*- | ||
2 | *----------------------------------------------------------------------------- | ||
3 | * | ||
4 | * | ||
5 | * PrBoom a Doom port merged with LxDoom and LSDLDoom | ||
6 | * based on BOOM, a modified and improved DOOM engine | ||
7 | * Copyright (C) 1999 by | ||
8 | * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman | ||
9 | * Copyright (C) 1999-2000 by | ||
10 | * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
25 | * 02111-1307, USA. | ||
26 | * | ||
27 | * DESCRIPTION: | ||
28 | * Handles WAD file header, directory, lump I/O. | ||
29 | * | ||
30 | *----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #include "doomstat.h" | ||
34 | #include "doomtype.h" | ||
35 | |||
36 | #ifdef __GNUG__ | ||
37 | #pragma implementation "w_wad.h" | ||
38 | #endif | ||
39 | #include "w_wad.h" | ||
40 | #include "m_swap.h" | ||
41 | #include "i_system.h" | ||
42 | |||
43 | #include "rockmacros.h" | ||
44 | // | ||
45 | // GLOBALS | ||
46 | // | ||
47 | |||
48 | // Location of each lump on disk. | ||
49 | lumpinfo_t *lumpinfo IBSS_ATTR; | ||
50 | int numlumps IBSS_ATTR; // killough | ||
51 | void **lumpcache IBSS_ATTR; // killough | ||
52 | #ifdef TIMEDIAG | ||
53 | static int *locktic; // cph | ||
54 | |||
55 | static void W_ReportLocks(void) | ||
56 | { | ||
57 | int i; | ||
58 | lprintf(LO_DEBUG, "W_ReportLocks:\nLump Size Locks Tics\n"); | ||
59 | for (i=0; i<numlumps; i++) { | ||
60 | if (lumpinfo[i].locks) | ||
61 | printf("%8.8s %6u %2d %6d\n", lumpinfo[i].name, | ||
62 | W_LumpLength(i), lumpinfo[i].locks, gametic - locktic[i]); | ||
63 | } | ||
64 | } | ||
65 | #endif | ||
66 | |||
67 | #ifdef HEAPDUMP | ||
68 | void W_PrintLump(FILE* fp, void* p) { | ||
69 | int i; | ||
70 | for (i=0; i<numlumps; i++) | ||
71 | if (lumpcache[i] == p) { | ||
72 | fdprintf(fp, " %8.8s %6u %2d %6d", lumpinfo[i].name, | ||
73 | W_LumpLength(i), lumpinfo[i].locks, gametic - locktic[i]); | ||
74 | return; | ||
75 | } | ||
76 | fprintf(fp, " not found"); | ||
77 | } | ||
78 | #endif | ||
79 | |||
80 | |||
81 | |||
82 | static int W_Filelength(int handle) | ||
83 | { | ||
84 | /* | ||
85 | struct stat fileinfo; | ||
86 | if (fstat(handle,&fileinfo) == -1) | ||
87 | I_Error("W_Filelength: Error fstating"); | ||
88 | return fileinfo.st_size; | ||
89 | */ | ||
90 | return filesize(handle); | ||
91 | } | ||
92 | |||
93 | void ExtractFileBase (const char *path, char *dest) | ||
94 | { | ||
95 | const char *src = path + strlen(path) - 1; | ||
96 | int length; | ||
97 | |||
98 | // back up until a \ or the start | ||
99 | while (src != path && src[-1] != ':' // killough 3/22/98: allow c:filename | ||
100 | && *(src-1) != '\\' | ||
101 | && *(src-1) != '/') | ||
102 | src--; | ||
103 | |||
104 | // copy up to eight characters | ||
105 | memset(dest,0,8); | ||
106 | length = 0; | ||
107 | |||
108 | while (*src && *src != '.' && ++length<9) | ||
109 | *dest++ = toupper(*src++); | ||
110 | /* cph - length check removed, just truncate at 8 chars. | ||
111 | * If there are 8 or more chars, we'll copy 8, and no zero termination | ||
112 | */ | ||
113 | } | ||
114 | |||
115 | // | ||
116 | // 1/18/98 killough: adds a default extension to a path | ||
117 | // Note: Backslashes are treated specially, for MS-DOS. | ||
118 | // | ||
119 | |||
120 | char *AddDefaultExtension(char *path, const char *ext) | ||
121 | { | ||
122 | char *p = path; | ||
123 | while (*p++); | ||
124 | while (p-->path && *p!='/' && *p!='\\') | ||
125 | if (*p=='.') | ||
126 | return path; | ||
127 | if (*ext!='.') | ||
128 | strcat(path,"."); | ||
129 | return strcat(path,ext); | ||
130 | } | ||
131 | |||
132 | // | ||
133 | // LUMP BASED ROUTINES. | ||
134 | // | ||
135 | |||
136 | // | ||
137 | // W_AddFile | ||
138 | // All files are optional, but at least one file must be | ||
139 | // found (PWAD, if all required lumps are present). | ||
140 | // Files with a .wad extension are wadlink files | ||
141 | // with multiple lumps. | ||
142 | // Other files are single lumps with the base filename | ||
143 | // for the lump name. | ||
144 | // | ||
145 | // Reload hack removed by Lee Killough | ||
146 | // CPhipps - source is an enum | ||
147 | // | ||
148 | |||
149 | static void W_AddFile(const char *filename, wad_source_t source) | ||
150 | // killough 1/31/98: static, const | ||
151 | { | ||
152 | wadinfo_t header; | ||
153 | lumpinfo_t* lump_p; | ||
154 | unsigned i; | ||
155 | int handle; | ||
156 | int length; | ||
157 | int startlump; | ||
158 | filelump_t *fileinfo, *fileinfo2free=NULL; //killough | ||
159 | filelump_t singleinfo; | ||
160 | |||
161 | // open the file and add to directory | ||
162 | |||
163 | handle = open(filename,O_RDONLY); | ||
164 | |||
165 | #ifdef HAVE_NET | ||
166 | if (handle == -1 && D_NetGetWad(filename)) // CPhipps | ||
167 | handle = open(filename,O_RDONLY); | ||
168 | #endif | ||
169 | |||
170 | if (handle == -1) | ||
171 | { | ||
172 | if ( strlen(filename)<=4 || // add error check -- killough | ||
173 | (strcasecmp(filename+strlen(filename)-4 , ".lmp" ) && | ||
174 | strcasecmp(filename+strlen(filename)-4 , ".gwa" ) ) | ||
175 | ) | ||
176 | I_Error("W_AddFile: couldn't open %s",filename); | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | //jff 8/3/98 use logical output routine | ||
181 | printf (" adding %s\n",filename); | ||
182 | startlump = numlumps; | ||
183 | |||
184 | if ( strlen(filename)<=4 || | ||
185 | ( | ||
186 | strcasecmp(filename+strlen(filename)-4,".wad") && | ||
187 | strcasecmp(filename+strlen(filename)-4,".gwa") | ||
188 | ) | ||
189 | ) | ||
190 | { | ||
191 | // single lump file | ||
192 | fileinfo = &singleinfo; | ||
193 | singleinfo.filepos = 0; | ||
194 | singleinfo.size = LONG(W_Filelength(handle)); | ||
195 | ExtractFileBase(filename, singleinfo.name); | ||
196 | numlumps++; | ||
197 | } | ||
198 | else | ||
199 | { | ||
200 | // WAD file | ||
201 | read(handle, &header, sizeof(header)); | ||
202 | if (strncmp(header.identification,"IWAD",4) && | ||
203 | strncmp(header.identification,"PWAD",4)) | ||
204 | I_Error("W_AddFile: Wad file %s doesn't have IWAD or PWAD id", filename); | ||
205 | header.numlumps = LONG(header.numlumps); | ||
206 | header.infotableofs = LONG(header.infotableofs); | ||
207 | length = header.numlumps*sizeof(filelump_t); | ||
208 | fileinfo2free = fileinfo = malloc(length); // killough | ||
209 | lseek(handle, header.infotableofs, SEEK_SET); | ||
210 | read(handle, fileinfo, length); | ||
211 | numlumps += header.numlumps; | ||
212 | } | ||
213 | |||
214 | // Fill in lumpinfo | ||
215 | lumpinfo = realloc(lumpinfo, numlumps*sizeof(lumpinfo_t)); | ||
216 | |||
217 | lump_p = &lumpinfo[startlump]; | ||
218 | for (i=startlump ; (int)i<numlumps ; i++,lump_p++, fileinfo++) | ||
219 | { | ||
220 | lump_p->handle = handle; // killough 4/25/98 | ||
221 | lump_p->position = LONG(fileinfo->filepos); | ||
222 | lump_p->size = LONG(fileinfo->size); | ||
223 | #ifndef NO_PREDEFINED_LUMPS | ||
224 | lump_p->data = NULL; // killough 1/31/98 | ||
225 | #endif | ||
226 | lump_p->namespace = ns_global; // killough 4/17/98 | ||
227 | strncpy (lump_p->name, fileinfo->name, 8); | ||
228 | lump_p->source = source; // Ty 08/29/98 | ||
229 | lump_p->locks = 0; // CPhipps - initialise locks | ||
230 | } | ||
231 | |||
232 | free(fileinfo2free); // killough | ||
233 | } | ||
234 | |||
235 | // jff 1/23/98 Create routines to reorder the master directory | ||
236 | // putting all flats into one marked block, and all sprites into another. | ||
237 | // This will allow loading of sprites and flats from a PWAD with no | ||
238 | // other changes to code, particularly fast hashes of the lumps. | ||
239 | // | ||
240 | // killough 1/24/98 modified routines to be a little faster and smaller | ||
241 | |||
242 | static int IsMarker(const char *marker, const char *name) | ||
243 | { | ||
244 | return !strncasecmp(name, marker, 8) || | ||
245 | (*name == *marker && !strncasecmp(name+1, marker, 7)); | ||
246 | } | ||
247 | |||
248 | // killough 4/17/98: add namespace tags | ||
249 | |||
250 | static void W_CoalesceMarkedResource(const char *start_marker, | ||
251 | const char *end_marker, int namespace) | ||
252 | { | ||
253 | lumpinfo_t *marked = malloc(sizeof(*marked) * numlumps); | ||
254 | size_t i, num_marked = 0, num_unmarked = 0; | ||
255 | int is_marked = 0, mark_end = 0; | ||
256 | lumpinfo_t *lump = lumpinfo; | ||
257 | |||
258 | for (i=numlumps; i--; lump++) | ||
259 | if (IsMarker(start_marker, lump->name)) // start marker found | ||
260 | { // If this is the first start marker, add start marker to marked lumps | ||
261 | if (!num_marked) | ||
262 | { | ||
263 | strncpy(marked->name, start_marker, 8); | ||
264 | marked->size = 0; // killough 3/20/98: force size to be 0 | ||
265 | marked->namespace = ns_global; // killough 4/17/98 | ||
266 | num_marked = 1; | ||
267 | } | ||
268 | is_marked = 1; // start marking lumps | ||
269 | } | ||
270 | else | ||
271 | if (IsMarker(end_marker, lump->name)) // end marker found | ||
272 | { | ||
273 | mark_end = 1; // add end marker below | ||
274 | is_marked = 0; // stop marking lumps | ||
275 | } | ||
276 | else | ||
277 | if (is_marked) // if we are marking lumps, | ||
278 | { // move lump to marked list | ||
279 | marked[num_marked] = *lump; | ||
280 | marked[num_marked++].namespace = namespace; // killough 4/17/98 | ||
281 | } | ||
282 | else | ||
283 | lumpinfo[num_unmarked++] = *lump; // else move down THIS list | ||
284 | |||
285 | // Append marked list to end of unmarked list | ||
286 | memcpy(lumpinfo + num_unmarked, marked, num_marked * sizeof(*marked)); | ||
287 | |||
288 | free(marked); // free marked list | ||
289 | |||
290 | numlumps = num_unmarked + num_marked; // new total number of lumps | ||
291 | |||
292 | if (mark_end) // add end marker | ||
293 | { | ||
294 | lumpinfo[numlumps].size = 0; // killough 3/20/98: force size to be 0 | ||
295 | lumpinfo[numlumps].namespace = ns_global; // killough 4/17/98 | ||
296 | strncpy(lumpinfo[numlumps++].name, end_marker, 8); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | // Hash function used for lump names. | ||
301 | // Must be mod'ed with table size. | ||
302 | // Can be used for any 8-character names. | ||
303 | // by Lee Killough | ||
304 | |||
305 | unsigned W_LumpNameHash(const char *s) | ||
306 | { | ||
307 | unsigned hash; | ||
308 | (void) ((hash = toupper(s[0]), s[1]) && | ||
309 | (hash = hash*3+toupper(s[1]), s[2]) && | ||
310 | (hash = hash*2+toupper(s[2]), s[3]) && | ||
311 | (hash = hash*2+toupper(s[3]), s[4]) && | ||
312 | (hash = hash*2+toupper(s[4]), s[5]) && | ||
313 | (hash = hash*2+toupper(s[5]), s[6]) && | ||
314 | (hash = hash*2+toupper(s[6]), | ||
315 | hash = hash*2+toupper(s[7])) | ||
316 | ); | ||
317 | return hash; | ||
318 | } | ||
319 | |||
320 | // | ||
321 | // W_CheckNumForName | ||
322 | // Returns -1 if name not found. | ||
323 | // | ||
324 | // Rewritten by Lee Killough to use hash table for performance. Significantly | ||
325 | // cuts down on time -- increases Doom performance over 300%. This is the | ||
326 | // single most important optimization of the original Doom sources, because | ||
327 | // lump name lookup is used so often, and the original Doom used a sequential | ||
328 | // search. For large wads with > 1000 lumps this meant an average of over | ||
329 | // 500 were probed during every search. Now the average is under 2 probes per | ||
330 | // search. There is no significant benefit to packing the names into longwords | ||
331 | // with this new hashing algorithm, because the work to do the packing is | ||
332 | // just as much work as simply doing the string comparisons with the new | ||
333 | // algorithm, which minimizes the expected number of comparisons to under 2. | ||
334 | // | ||
335 | // killough 4/17/98: add namespace parameter to prevent collisions | ||
336 | // between different resources such as flats, sprites, colormaps | ||
337 | // | ||
338 | |||
339 | int (W_CheckNumForName)(register const char *name, register int namespace) | ||
340 | { | ||
341 | // Hash function maps the name to one of possibly numlump chains. | ||
342 | // It has been tuned so that the average chain length never exceeds 2. | ||
343 | |||
344 | int i; | ||
345 | |||
346 | if (!lumpinfo) | ||
347 | return -1; | ||
348 | |||
349 | i = lumpinfo[W_LumpNameHash(name) % (unsigned) numlumps].index; | ||
350 | |||
351 | // We search along the chain until end, looking for case-insensitive | ||
352 | // matches which also match a namespace tag. Separate hash tables are | ||
353 | // not used for each namespace, because the performance benefit is not | ||
354 | // worth the overhead, considering namespace collisions are rare in | ||
355 | // Doom wads. | ||
356 | |||
357 | while (i >= 0 && (strncasecmp(lumpinfo[i].name, name, 8) || | ||
358 | lumpinfo[i].namespace != (unsigned)namespace)) | ||
359 | i = lumpinfo[i].next; | ||
360 | |||
361 | // Return the matching lump, or -1 if none found. | ||
362 | |||
363 | return i; | ||
364 | } | ||
365 | |||
366 | // | ||
367 | // killough 1/31/98: Initialize lump hash table | ||
368 | // | ||
369 | |||
370 | static void W_InitLumpHash(void) | ||
371 | { | ||
372 | int i; | ||
373 | |||
374 | for (i=0; i<numlumps; i++) | ||
375 | lumpinfo[i].index = -1; // mark slots empty | ||
376 | |||
377 | // Insert nodes to the beginning of each chain, in first-to-last | ||
378 | // lump order, so that the last lump of a given name appears first | ||
379 | // in any chain, observing pwad ordering rules. killough | ||
380 | |||
381 | for (i=0; i<numlumps; i++) | ||
382 | { // hash function: | ||
383 | int j = W_LumpNameHash(lumpinfo[i].name) % (unsigned) numlumps; | ||
384 | lumpinfo[i].next = lumpinfo[j].index; // Prepend to list | ||
385 | lumpinfo[j].index = i; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | // End of lump hashing -- killough 1/31/98 | ||
390 | |||
391 | |||
392 | |||
393 | // W_GetNumForName | ||
394 | // Calls W_CheckNumForName, but bombs out if not found. | ||
395 | // | ||
396 | int W_GetNumForName (const char* name) // killough -- const added | ||
397 | { | ||
398 | int i = W_CheckNumForName (name); | ||
399 | if (i == -1) | ||
400 | I_Error("W_GetNumForName: %s not found", name); | ||
401 | return i; | ||
402 | } | ||
403 | |||
404 | // W_Init | ||
405 | // Loads each of the files in the wadfiles array. | ||
406 | // All files are optional, but at least one file | ||
407 | // must be found. | ||
408 | // Files with a .wad extension are idlink files | ||
409 | // with multiple lumps. | ||
410 | // Other files are single lumps with the base filename | ||
411 | // for the lump name. | ||
412 | // Lump names can appear multiple times. | ||
413 | // The name searcher looks backwards, so a later file | ||
414 | // does override all earlier ones. | ||
415 | // | ||
416 | // CPhipps - modified to use the new wadfiles array | ||
417 | // | ||
418 | struct wadfile_info *wadfiles=NULL; | ||
419 | |||
420 | size_t numwadfiles = 0; // CPhipps - size of the wadfiles array (dynamic, no limit) | ||
421 | |||
422 | void W_Init(void) | ||
423 | { | ||
424 | #ifndef NO_PREDEFINED_LUMPS | ||
425 | // killough 1/31/98: add predefined lumps first | ||
426 | |||
427 | numlumps = num_predefined_lumps; | ||
428 | |||
429 | // lumpinfo will be realloced as lumps are added | ||
430 | lumpinfo = malloc(numlumps*sizeof(*lumpinfo)); | ||
431 | |||
432 | memcpy(lumpinfo, predefined_lumps, numlumps*sizeof(*lumpinfo)); | ||
433 | // Ty 08/29/98 - add source flag to the predefined lumps | ||
434 | { | ||
435 | int i; | ||
436 | for (i=0;i<numlumps;i++) | ||
437 | lumpinfo[i].source = source_pre; | ||
438 | } | ||
439 | #else | ||
440 | // CPhipps - start with nothing | ||
441 | |||
442 | numlumps = 0; lumpinfo = malloc(0); | ||
443 | #endif | ||
444 | |||
445 | { // CPhipps - new wadfiles array used | ||
446 | // open all the files, load headers, and count lumps | ||
447 | int i; | ||
448 | for (i=0; (size_t)i<numwadfiles; i++) | ||
449 | W_AddFile(wadfiles[i].name, wadfiles[i].src); | ||
450 | } | ||
451 | if (!numlumps) | ||
452 | I_Error ("W_Init: No files found"); | ||
453 | |||
454 | //jff 1/23/98 | ||
455 | // get all the sprites and flats into one marked block each | ||
456 | // killough 1/24/98: change interface to use M_START/M_END explicitly | ||
457 | // killough 4/17/98: Add namespace tags to each entry | ||
458 | |||
459 | W_CoalesceMarkedResource("S_START", "S_END", ns_sprites); | ||
460 | W_CoalesceMarkedResource("F_START", "F_END", ns_flats); | ||
461 | |||
462 | // killough 4/4/98: add colormap markers | ||
463 | W_CoalesceMarkedResource("C_START", "C_END", ns_colormaps); | ||
464 | |||
465 | // set up caching | ||
466 | lumpcache = calloc(sizeof *lumpcache, numlumps); // killough | ||
467 | |||
468 | if (!lumpcache) | ||
469 | I_Error ("W_Init: Couldn't allocate lumpcache"); | ||
470 | |||
471 | // killough 1/31/98: initialize lump hash table | ||
472 | W_InitLumpHash(); | ||
473 | |||
474 | #ifdef TIMEDIAG | ||
475 | // cph - allocate space for lock time diagnostics | ||
476 | locktic = malloc(sizeof(*locktic)*numlumps); | ||
477 | atexit(W_ReportLocks); | ||
478 | #endif | ||
479 | } | ||
480 | |||
481 | // | ||
482 | // W_LumpLength | ||
483 | // Returns the buffer size needed to load the given lump. | ||
484 | // | ||
485 | int W_LumpLength (int lump) | ||
486 | { | ||
487 | if (lump >= numlumps) | ||
488 | I_Error ("W_LumpLength: %i >= numlumps",lump); | ||
489 | return lumpinfo[lump].size; | ||
490 | } | ||
491 | |||
492 | // | ||
493 | // W_ReadLump | ||
494 | // Loads the lump into the given buffer, | ||
495 | // which must be >= W_LumpLength(). | ||
496 | // | ||
497 | |||
498 | void W_ReadLump(int lump, void *dest) | ||
499 | { | ||
500 | lumpinfo_t *l = lumpinfo + lump; | ||
501 | |||
502 | #ifdef RANGECHECK | ||
503 | if (lump >= numlumps) | ||
504 | I_Error ("W_ReadLump: %i >= numlumps",lump); | ||
505 | #endif | ||
506 | |||
507 | #ifndef NO_PREDEFINED_LUMPS | ||
508 | if (l->data) // killough 1/31/98: predefined lump data | ||
509 | memcpy(dest, l->data, l->size); | ||
510 | else | ||
511 | #endif | ||
512 | { | ||
513 | int c; | ||
514 | |||
515 | // killough 1/31/98: Reload hack (-wart) removed | ||
516 | |||
517 | lseek(l->handle, l->position, SEEK_SET); | ||
518 | c = read(l->handle, dest, l->size); | ||
519 | if (c < l->size) | ||
520 | I_Error("W_ReadLump: only read %i of %i on lump %i", c, l->size, lump); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | // | ||
525 | // W_CacheLumpNum | ||
526 | /* | ||
527 | * killough 4/25/98: simplified | ||
528 | * CPhipps - modified for new lump locking scheme | ||
529 | * returns a const* | ||
530 | */ | ||
531 | |||
532 | void * (W_CacheLumpNum)(int lump, unsigned short locks) | ||
533 | { | ||
534 | #ifdef RANGECHECK | ||
535 | if ((unsigned)lump >= (unsigned)numlumps) | ||
536 | I_Error ("W_CacheLumpNum: %i >= numlumps",lump); | ||
537 | #endif | ||
538 | |||
539 | if (!lumpcache[lump]) // read the lump in | ||
540 | W_ReadLump(lump, Z_Malloc(W_LumpLength(lump), PU_CACHE, &lumpcache[lump])); | ||
541 | |||
542 | /* cph - if wasn't locked but now is, tell z_zone to hold it */ | ||
543 | if (!lumpinfo[lump].locks && locks) { | ||
544 | Z_ChangeTag(lumpcache[lump],PU_STATIC); | ||
545 | #ifdef TIMEDIAG | ||
546 | locktic[lump] = gametic; | ||
547 | #endif | ||
548 | } | ||
549 | lumpinfo[lump].locks += locks; | ||
550 | |||
551 | #ifdef SIMPLECHECKS | ||
552 | if (!((lumpinfo[lump].locks+1) & 0xf)) | ||
553 | printf("W_CacheLumpNum: High lock on %s (%d)\n", | ||
554 | lumpinfo[lump].name, lumpinfo[lump].locks); | ||
555 | #endif | ||
556 | |||
557 | // CPhipps - if not locked, can't give you a pointer | ||
558 | return (locks ? lumpcache[lump] : NULL); | ||
559 | } | ||
560 | |||
561 | /* cph - | ||
562 | * W_CacheLumpNumPadded | ||
563 | * | ||
564 | * Caches a lump and pads the memory following it. | ||
565 | * The thing returned is *only* guaranteed to be padded if | ||
566 | * the lump isn't already cached (otherwise, you get whatever is | ||
567 | * currently cached, which if it was cached by a previous call | ||
568 | * to this will also be padded) | ||
569 | */ | ||
570 | |||
571 | void * W_CacheLumpNumPadded(int lump, size_t len, unsigned char pad) | ||
572 | { | ||
573 | const int locks = 1; | ||
574 | #ifdef RANGECHECK | ||
575 | if ((unsigned)lump >= (unsigned)numlumps) | ||
576 | I_Error ("W_CacheLumpNum: %i >= numlumps",lump); | ||
577 | #endif | ||
578 | |||
579 | if (!lumpcache[lump]) { /* read the lump in */ | ||
580 | size_t lumplen = W_LumpLength(lump); | ||
581 | unsigned char* p; | ||
582 | W_ReadLump(lump, p = Z_Malloc(len, PU_CACHE, &lumpcache[lump])); | ||
583 | memset(p+lumplen, pad, len-lumplen); | ||
584 | } | ||
585 | |||
586 | /* cph - if wasn't locked but now is, tell z_zone to hold it */ | ||
587 | if (!lumpinfo[lump].locks && locks) { | ||
588 | Z_ChangeTag(lumpcache[lump],PU_STATIC); | ||
589 | #ifdef TIMEDIAG | ||
590 | locktic[lump] = gametic; | ||
591 | #endif | ||
592 | } | ||
593 | lumpinfo[lump].locks += locks; | ||
594 | |||
595 | #ifdef SIMPLECHECKS | ||
596 | if (!((lumpinfo[lump].locks+1) & 0xf)) | ||
597 | printf("W_CacheLumpNum: High lock on %s (%d)\n", | ||
598 | lumpinfo[lump].name, lumpinfo[lump].locks); | ||
599 | #endif | ||
600 | |||
601 | return lumpcache[lump]; | ||
602 | } | ||
603 | |||
604 | // | ||
605 | // W_UnlockLumpNum | ||
606 | // | ||
607 | // CPhipps - this changes (should reduce) the number of locks on a lump | ||
608 | |||
609 | void (W_UnlockLumpNum)(int lump, signed short unlocks) | ||
610 | { | ||
611 | #ifdef SIMPLECHECKS | ||
612 | if ((signed short)lumpinfo[lump].locks < unlocks) | ||
613 | printf("W_UnlockLumpNum: Excess unlocks on %s (%d-%d)\n", | ||
614 | lumpinfo[lump].name, lumpinfo[lump].locks, unlocks); | ||
615 | #endif | ||
616 | lumpinfo[lump].locks -= unlocks; | ||
617 | // cph - Note: must only tell z_zone to make purgeable if currently locked, | ||
618 | // else it might already have been purged | ||
619 | if (unlocks && !lumpinfo[lump].locks) | ||
620 | Z_ChangeTag(lumpcache[lump], PU_CACHE); | ||
621 | } | ||
622 | |||
623 | // W_CacheLumpName macroized in w_wad.h -- killough | ||
624 | |||
625 | #ifndef NO_PREDEFINED_LUMPS | ||
626 | // WritePredefinedLumpWad | ||
627 | // Args: Filename - string with filename to write to | ||
628 | // Returns: void | ||
629 | // | ||
630 | // If the user puts a -dumplumps switch on the command line, we will | ||
631 | // write all those predefined lumps above out into a pwad. User | ||
632 | // supplies the pwad name. | ||
633 | // | ||
634 | // killough 4/22/98: make endian-independent, remove tab chars | ||
635 | void WritePredefinedLumpWad(const char *filename) | ||
636 | { | ||
637 | int handle; // for file open | ||
638 | char filenam[256]; // we may have to add ".wad" to the name they pass | ||
639 | |||
640 | if (!filename || !*filename) // check for null pointer or empty name | ||
641 | return; // early return | ||
642 | |||
643 | AddDefaultExtension(strcpy(filenam, filename), ".wad"); | ||
644 | |||
645 | // The following code writes a PWAD from the predefined lumps array | ||
646 | // How to write a PWAD will not be explained here. | ||
647 | #ifdef _MSC_VER // proff: In Visual C open is defined a bit different | ||
648 | if ( (handle = open (filenam, O_RDWR | O_CREAT | O_BINARY, _S_IWRITE|_S_IREAD)) != -1) | ||
649 | #else | ||
650 | if ( (handle = open (filenam, O_RDWR | O_CREAT | O_BINARY, S_IWUSR|S_IRUSR)) != -1) | ||
651 | #endif | ||
652 | { | ||
653 | wadinfo_t header = {"PWAD"}; | ||
654 | size_t filepos = sizeof(wadinfo_t) + num_predefined_lumps * sizeof(filelump_t); | ||
655 | int i; | ||
656 | |||
657 | header.numlumps = LONG(num_predefined_lumps); | ||
658 | header.infotableofs = LONG(sizeof(header)); | ||
659 | |||
660 | // write header | ||
661 | write(handle, &header, sizeof(header)); | ||
662 | |||
663 | // write directory | ||
664 | for (i=0;(size_t)i<num_predefined_lumps;i++) | ||
665 | { | ||
666 | filelump_t fileinfo = {0}; | ||
667 | fileinfo.filepos = LONG(filepos); | ||
668 | fileinfo.size = LONG(predefined_lumps[i].size); | ||
669 | strncpy(fileinfo.name, predefined_lumps[i].name, 8); | ||
670 | write(handle, &fileinfo, sizeof(fileinfo)); | ||
671 | filepos += predefined_lumps[i].size; | ||
672 | } | ||
673 | |||
674 | // write lumps | ||
675 | for (i=0;(size_t)i<num_predefined_lumps;i++) | ||
676 | write(handle, predefined_lumps[i].data, predefined_lumps[i].size); | ||
677 | |||
678 | close(handle); | ||
679 | I_Error("WritePredefinedLumpWad: Predefined lumps wad, %s written", filename); | ||
680 | } | ||
681 | I_Error("WritePredefinedLumpWad: Can't open predefined lumps wad %s for output", filename); | ||
682 | } | ||
683 | #endif | ||