1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: p_setup.c 1565 2020-12-19 06:21:39Z wesleyjohnson $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Copyright (C) 1998-2016 by DooM Legacy Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 //
20 // $Log: p_setup.c,v $
21 // Revision 1.49 2004/07/27 08:19:37 exl
22 // New fmod, fs functions, bugfix or 2, patrol nodes
23 //
24 // Revision 1.48 2003/06/11 03:38:09 ssntails
25 // THING Z definable in levels by using upper 9 bits
26 //
27 // Revision 1.47 2003/06/11 00:28:49 ssntails
28 // Big Blockmap Support (128kb+ ?)
29 //
30 // Revision 1.46 2003/05/04 02:37:47 sburke
31 // READSHORT now does byte-swapping on big-endian machines.
32 //
33 // Revision 1.45 2002/10/30 23:50:03 bock
34 //
35 // Revision 1.44 2002/09/27 16:40:09 tonyd
36 // First commit of acbot
37 //
38 // Revision 1.43 2002/07/24 19:03:07 ssntails
39 // Added support for things to retain spawned Z position.
40 //
41 // Revision 1.42 2002/07/20 03:24:45 mrousseau
42 // Copy 'side' from SEGS structure to seg_t's copy
43 //
44 // Revision 1.41 2002/01/12 12:41:05 hurdler
45 // Revision 1.40 2002/01/12 02:21:36 stroggonmeth
46 // Revision 1.39 2001/08/19 20:41:03 hurdler
47 //
48 // Revision 1.38 2001/08/13 16:27:44 hurdler
49 // Added translucency to linedef 300 and colormap to 3d-floors
50 //
51 // Revision 1.37 2001/08/12 22:08:40 hurdler
52 // Add alpha value for 3d water
53 //
54 // Revision 1.36 2001/08/12 17:57:15 hurdler
55 // Beter support of sector coloured lighting in hw mode
56 //
57 // Revision 1.35 2001/08/11 15:18:02 hurdler
58 // Add sector colormap in hw mode (first attempt)
59 //
60 // Revision 1.34 2001/08/08 20:34:43 hurdler
61 // Big TANDL update
62 //
63 // Revision 1.33 2001/08/06 23:57:09 stroggonmeth
64 // Removed portal code, improved 3D floors in hardware mode.
65 //
66 // Revision 1.32 2001/07/28 16:18:37 bpereira
67 // Revision 1.31 2001/06/16 08:07:55 bpereira
68 // Revision 1.30 2001/05/27 13:42:48 bpereira
69 //
70 // Revision 1.29 2001/05/14 19:02:58 metzgermeister
71 // * Fixed floor not moving up with player on E3M1
72 // * Fixed crash due to oversized string in screen message ... bad bug!
73 // * Corrected some typos
74 // * fixed sound bug in SDL
75 //
76 // Revision 1.28 2001/04/30 17:19:24 stroggonmeth
77 // HW fix and misc. changes
78 //
79 // Revision 1.27 2001/03/30 17:12:51 bpereira
80 //
81 // Revision 1.26 2001/03/19 21:18:48 metzgermeister
82 // * missing textures in HW mode are replaced by default texture
83 // * fixed crash bug with P_SpawnMissile(.) returning NULL
84 // * deep water trick and other nasty thing work now in HW mode (tested with tnt/map02 eternal/map02)
85 // * added cvar gr_correcttricks
86 //
87 // Revision 1.25 2001/03/13 22:14:19 stroggonmeth
88 // Long time no commit. 3D floors, FraggleScript, portals, ect.
89 //
90 // Revision 1.24 2001/01/25 22:15:43 bpereira
91 // added heretic support
92 //
93 // Revision 1.23 2000/11/04 16:23:43 bpereira
94 // Revision 1.22 2000/11/03 03:27:17 stroggonmeth
95 // Revision 1.21 2000/11/02 19:49:36 bpereira
96 //
97 // Revision 1.20 2000/11/02 17:50:08 stroggonmeth
98 // Big 3Dfloors & FraggleScript commit!!
99 //
100 // Revision 1.19 2000/10/02 18:25:45 bpereira
101 // Revision 1.18 2000/08/31 14:30:56 bpereira
102 //
103 // Revision 1.17 2000/08/11 21:37:17 hurdler
104 // fix win32 compilation problem
105 //
106 // Revision 1.16 2000/08/11 19:10:13 metzgermeister
107 //
108 // Revision 1.15 2000/05/23 15:22:34 stroggonmeth
109 // Not much. A graphic bug fixed.
110 //
111 // Revision 1.14 2000/05/03 23:51:00 stroggonmeth
112 //
113 // Revision 1.13 2000/04/19 15:21:02 hurdler
114 // add SDL midi support
115 //
116 // Revision 1.12 2000/04/18 12:55:39 hurdler
117 // Revision 1.11 2000/04/16 18:38:07 bpereira
118 // Revision 1.10 2000/04/15 22:12:57 stroggonmeth
119 //
120 // Revision 1.9 2000/04/13 23:47:47 stroggonmeth
121 // See logs
122 //
123 // Revision 1.8 2000/04/12 16:01:59 hurdler
124 // ready for T&L code and true static lighting
125 //
126 // Revision 1.7 2000/04/11 19:07:24 stroggonmeth
127 // Finished my logs, fixed a crashing bug.
128 //
129 // Revision 1.6 2000/04/08 11:27:29 hurdler
130 // fix some boom stuffs
131 //
132 // Revision 1.5 2000/04/06 20:40:22 hurdler
133 // Mostly remove warnings under windows
134 //
135 // Revision 1.4 2000/04/04 19:28:43 stroggonmeth
136 // Global colormaps working. Added a new linedef type 272.
137 //
138 // Revision 1.3 2000/04/04 00:32:47 stroggonmeth
139 // Initial Boom compatability plus few misc changes all around.
140 //
141 // Revision 1.2 2000/02/27 00:42:10 hurdler
142 // Revision 1.1.1.1 2000/02/22 20:32:33 hurdler
143 // Initial import into CVS (v1.29 pr3)
144 //
145 //
146 // DESCRIPTION:
147 // Do all the WAD I/O, get map description,
148 // set up initial state and misc. LUTs.
149 //
150 //-----------------------------------------------------------------------------
151
152 #include "doomincl.h"
153 #include "p_local.h"
154 #include "p_tick.h"
155 // think
156 #include "p_setup.h"
157 #include "p_spec.h"
158 #include "p_info.h"
159 #include "g_game.h"
160
161 #include "d_main.h"
162 #include "byteptr.h"
163
164 #include "i_sound.h"
165 // I_PlayCD()..
166 #include "i_system.h"
167 // I_Sleep
168
169 #include "r_data.h"
170 #include "r_things.h"
171 #include "r_sky.h"
172
173 #include "s_sound.h"
174 #include "st_stuff.h"
175 #include "w_wad.h"
176 #include "z_zone.h"
177 #include "r_splats.h"
178 #include "t_array.h"
179 #include "t_func.h"
180 #include "t_script.h"
181
182 #include "hu_stuff.h"
183 #include "console.h"
184
185
186 #ifdef HWRENDER
187 #include "i_video.h"
188 // rendermode
189 #include "hardware/hw_main.h"
190 #include "hardware/hw_light.h"
191 #endif
192
193 #include "b_game.h"
194 // added by AC for acbot
195
196
197 //#define TRACE_BLOCKMAPHEAD
198 //#define DUMP_BLOCKMAP "dmdump"
199
200
201 //
202 // MAP related Lookup tables.
203 // Store VERTEXES, LINEDEFS, SIDEDEFS, etc.
204 //
205 boolean newlevel = false;
206 boolean doom1level = false; // doom 1 level running under doom 2
207
208 int numvertexes;
209 vertex_t* vertexes;
210
211 int numsegs;
212 seg_t* segs;
213
214 int numsectors = 0;
215 sector_t* sectors = NULL;
216
217 int numsubsectors;
218 subsector_t* subsectors;
219
220 int numnodes;
221 node_t* nodes;
222
223 int numlines;
224 line_t* lines;
225
226 int numsides;
227 side_t* sides;
228
229 int nummapthings;
230 mapthing_t* mapthings;
231
232 /*
233 typedef struct mapdata_s {
234 int numvertexes;
235 vertex_t* vertexes;
236 int numsegs;
237 seg_t* segs;
238 int numsectors;
239 sector_t* sectors;
240 int numsubsectors;
241 subsector_t* subsectors;
242 int numnodes;
243 node_t* nodes;
244 int numlines;
245 line_t* lines;
246 int numsides;
247 side_t* sides;
248 } mapdata_t;
249 */
250
251
252 // BLOCKMAP
253 // Created from axis aligned bounding box of the map, a rectangular array of
254 // blocks of size ...
255 // Used to speed up collision detection by spatial subdivision in 2D.
256 //
257 // Blockmap size.
258 unsigned int bmapwidth;
259 unsigned int bmapheight; // size in mapblocks
260
261 uint32_t * blockmapindex; // for large maps, wad is 16bit
262 // offsets in blockmap are from here
263 uint32_t * blockmaphead; // Big blockmap, SSNTails
264
265 // origin of block map
266 // The bottom left corner of the most SW block.
267 fixed_t bmaporgx;
268 fixed_t bmaporgy;
269 // for thing chains
270 mobj_t ** blocklinks;
271
272
273 // REJECT
274 // For fast sight rejection.
275 // Speeds up enemy AI by skipping detailed line-of-sight calculation.
276 // Without special effect, this could be used as a PVS lookup as well.
277 byte * rejectmatrix;
278
279
280 // Maintain single and multi player starting spots.
281 mapthing_t * deathmatchstarts[MAX_DM_STARTS];
282 int numdmstarts;
283 mapthing_t * playerstarts[MAXPLAYERS];
284
285
286 #if 0
287 // [WDJ] Checks from PrBoom.
288
289 // figgi 08/21/00 -- constants and globals for glBsp support
290 #define gNd2 0x32644E67
291 #define gNd3 0x33644E67
292 #define gNd4 0x34644E67
293 #define gNd5 0x35644E67
294 #define ZNOD 0x444F4E5A
295 #define ZGLN 0x4E4C475A
296 #define GL_VERT_OFFSET 4
297
298
299
300 static void P_GetNodesVersion( lumpnum_t lumpnum, lumpnum_t gl_lumpnum )
301 {
302 const void * data;
303
304 data = W_CacheLumpNum(gl_lumpnum+ML_GL_VERTS);
305 if ( (gl_lumpnum > lumpnum) && (forceOldBsp == false) && (compatibility_level >= prboom_2_compatibility) ) {
306 // Check for gNd2, gNd3, gNd4, gNd5
307 if( !strcasecmp( data, "gNd", 3) {
308 nodesVersion = gNd4;
309 I_SoftError("GL Nodes not supported\n");
310 }
311 } else {
312 data = W_CacheLumpNum(lumpnum + ML_NODES);
313 if( !strcasecmp(data, "ZNOD", 4) )
314 I_SoftError("ZDoom nodes not supported");
315
316 data = W_CacheLumpNum(lumpnum + ML_SSECTORS);
317 if( !strcasecmp(data, "ZGLN", 4) )
318 I_SoftError("ZDoom GL nodes not supported");
319 }
320 }
321 #endif
322
323
324
325 //
326 // P_LoadVertexes
327 //
328 static
P_LoadVertexes(lumpnum_t lumpnum)329 void P_LoadVertexes (lumpnum_t lumpnum)
330 {
331 byte* data;
332 mapvertex_t* ml;
333 vertex_t* li;
334 int i;
335
336 // Determine number of lumps:
337 // total lump length / vertex record length.
338 numvertexes = W_LumpLength(lumpnum) / sizeof(mapvertex_t);
339
340 // Allocate zone memory for buffer.
341 vertexes = Z_Malloc (numvertexes*sizeof(vertex_t), PU_LEVEL, NULL);
342
343 // Load data into cache.
344 data = W_CacheLumpNum( lumpnum, PU_STATIC ); // vertex lump temp
345 // [WDJ] Do endian as read from vertex lump temp
346
347 ml = (mapvertex_t *)data;
348 li = vertexes;
349
350 // Copy and convert vertex coordinates,
351 // internal representation as fixed.
352 for (i=0 ; i<numvertexes ; i++, li++, ml++)
353 {
354 // signed
355 li->x = LE_SWAP16(ml->x)<<FRACBITS;
356 li->y = LE_SWAP16(ml->y)<<FRACBITS;
357 }
358
359 // Free buffer memory.
360 Z_Free (data);
361 }
362
363
364 //
365 // Computes the line length in frac units, the glide render needs this
366 //
P_SegLength(seg_t * seg)367 float P_SegLength (seg_t* seg)
368 {
369 double dx,dy;
370
371 // make a vector (start at origin)
372 dx = FIXED_TO_FLOAT(seg->v2->x - seg->v1->x);
373 dy = FIXED_TO_FLOAT(seg->v2->y - seg->v1->y);
374
375 return sqrt(dx*dx+dy*dy)*FRACUNIT;
376 }
377
378
379 //
380 // P_LoadSegs
381 //
382 static
P_LoadSegs(lumpnum_t lumpnum)383 void P_LoadSegs ( lumpnum_t lumpnum )
384 {
385 byte* data;
386 mapseg_t* ml;
387 seg_t* li;
388 line_t* ldef;
389 uint16_t side, linedef;
390 uint16_t vn1, vn2;
391 int i;
392
393 // Load segments, from wad, as generated by nodebuilder.
394 numsegs = W_LumpLength(lumpnum) / sizeof(mapseg_t);
395 segs = Z_Malloc (numsegs*sizeof(seg_t), PU_LEVEL, NULL);
396 memset (segs, 0, numsegs*sizeof(seg_t));
397 data = W_CacheLumpNum (lumpnum, PU_STATIC); // segs lump temp
398 // [WDJ] Do endian as read from segs lump temp
399
400 if( !data || (numsegs < 1))
401 {
402 I_SoftError( "Bad segs data\n" );
403 return;
404 }
405
406 ml = (mapseg_t *)data;
407 li = segs;
408 for (i=0 ; i<numsegs ; i++, li++, ml++)
409 {
410 // [WDJ] Detect buggy wad, bad vertex number
411 // signed
412 vn1 = (uint16_t)LE_SWAP16(ml->v1);
413 vn2 = (uint16_t)LE_SWAP16(ml->v2);
414 if( vn1 > numvertexes || vn2 > numvertexes )
415 {
416 I_SoftError("Seg vertex bad %d,%d\n", vn1,vn2 );
417 // zero both out together, make seg safer (otherwise will cross another line)
418 vn1 = vn2 = 0;
419 }
420 li->v1 = &vertexes[vn1];
421 li->v2 = &vertexes[vn2];
422
423 #ifdef HWRENDER // not win32 only 19990829 by Kin
424 // [WDJ] Initialize irregardless
425 // if (rendermode != render_soft)
426 {
427 // used for the hardware render
428 li->pv1 = li->pv2 = NULL;
429 li->length = P_SegLength (li);
430 //Hurdler: 04/12/2000: for now, only used in hardware mode
431 li->lightmaps = NULL; // list of static lightmap for this seg
432 }
433 #endif
434
435 li->angle = ((uint16_t)( LE_SWAP16(ml->angle) ))<<16;
436 li->offset = (LE_SWAP16(ml->offset))<<16;
437 linedef = (uint16_t)( LE_SWAP16(ml->linedef) );
438 // [WDJ] Detect buggy wad, bad linedef number
439 if( linedef > numlines ) {
440 I_SoftError( "P_LoadSegs, linedef #%i, > numlines %i\n", linedef, numlines );
441 linedef = 0; // default
442 }
443 ldef = &lines[linedef];
444 li->linedef = ldef;
445 side = (uint16_t)( LE_SWAP16(ml->side) );
446 if( side != 0 && side != 1 )
447 {
448 // [WDJ] buggy wad
449 I_SoftError( "P_LoadSegs, bad side index\n");
450 side = 0; // assume was using wrong side
451 }
452 // side1 required to have sidenum != NULL_INDEX
453 if( ldef->sidenum[side] == NULL_INDEX )
454 {
455 // [WDJ] buggy wad
456 I_SoftError( "P_LoadSegs, using missing sidedef\n");
457 side = 0; // assume was using wrong side
458 }
459 li->side = side;
460 li->sidedef = &sides[ldef->sidenum[side]];
461 li->frontsector = sides[ldef->sidenum[side]].sector;
462 if( ldef-> flags & ML_TWOSIDED && (ldef->sidenum[side^1] != NULL_INDEX) )
463 li->backsector = sides[ldef->sidenum[side^1]].sector;
464 else
465 li->backsector = NULL;
466
467 li->numlights = 0;
468 li->rlights = NULL;
469 }
470
471 Z_Free (data);
472 }
473
474
475 //
476 // P_LoadSubsectors
477 //
478 // Called by P_SetupLevel, after LoadLinedefs
479 static
P_LoadSubsectors(lumpnum_t lumpnum)480 void P_LoadSubsectors( lumpnum_t lumpnum )
481 {
482 byte* data;
483 mapsubsector_t* ms;
484 subsector_t* ss;
485 int i;
486
487 // Load subsectors, from wad, as generated by nodebuilder.
488 numsubsectors = W_LumpLength(lumpnum) / sizeof(mapsubsector_t);
489 subsectors = Z_Malloc (numsubsectors*sizeof(subsector_t), PU_LEVEL, NULL);
490 data = W_CacheLumpNum(lumpnum, PU_STATIC); // subsectors lump temp
491 // [WDJ] Do endian as read from subsectors temp lump
492
493 if( !data || (numsubsectors < 1))
494 {
495 I_SoftError( "Bad subsector data\n" );
496 return;
497 }
498
499 ms = (mapsubsector_t *)data;
500 memset (subsectors,0, numsubsectors*sizeof(subsector_t));
501 ss = subsectors;
502
503 for (i=0 ; i<numsubsectors ; i++, ss++, ms++)
504 {
505 ss->numlines = (uint16_t)( LE_SWAP16(ms->numsegs) );
506 ss->firstline = (uint16_t)( LE_SWAP16(ms->firstseg) ); // unsigned
507 // cannot check if valid, segs not loaded yet
508 }
509
510 Z_Free (data);
511 }
512
513
514
515 //
516 // P_LoadSectors
517 //
518
519 // Return the flat size_index.
520 // flatsize : the flat lump size
521 // Called by P_PrecacheLevelFlats at level load time.
522 // Called by V_DrawVidFlatFill, HWR_DrawFlatFill.
P_flatsize_to_index(int flatsize,char * name)523 uint16_t P_flatsize_to_index( int flatsize, char * name )
524 {
525 // Drawing as 64*64 (lumpsize=4096) was the default.
526 // Heretic LAVA flats are 4160, an odd size; use 64*64.
527 // Heretic F_SKY1 flat is 4, an odd size,
528 // but it is a placeholder that is never drawn.
529 if( flatsize >= 2048*2048 ) // 2048x2048 lump
530 return 7;
531 if( flatsize >= 1024*1024 ) // 1024x1024 lump
532 return 6;
533 if( flatsize >= 512*512 ) // 512x512 lump
534 return 5;
535 if( flatsize >= 256*256 ) // 256x256 lump
536 return 4;
537 if( flatsize >= 128*128 ) // 128x128 lump
538 return 3;
539 if( flatsize >= 64*64 ) // 64x64 lump
540 return 2;
541 if( flatsize >= 32*32 ) // 32x32 lump
542 return 1;
543 if( verbose && name )
544 {
545 char buf[10];
546 memcpy( buf, name, 8 ); // no termination on flat name
547 buf[8] = 0;
548 GenPrintf( EMSG_warn, "Flat size not handled, %s, size=%i\n", buf, flatsize );
549 }
550 return 0;
551 }
552
553 //
554 // levelflats
555 //
556 // usually fewer than 25 flats per level
557 #define LEVELFLAT_INC 32
558
559 unsigned int levelflat_max = 0; // num alloc levelflats
560 unsigned int numlevelflats; // actual in use
561 levelflat_t* levelflats;
562
563 //SoM: Other files want this info.
P_PrecacheLevelFlats(void)564 int P_PrecacheLevelFlats( void )
565 {
566 int flatmemory = 0;
567 int i;
568 int lump;
569
570 //SoM: 4/18/2000: New flat code to make use of levelflats.
571 for(i = 0; i < numlevelflats; i++)
572 {
573 lump = levelflats[i].lumpnum;
574 levelflats[i].size_index = P_flatsize_to_index( W_LumpLength(lump), NULL );
575 if(devparm)
576 flatmemory += W_LumpLength(lump);
577 R_GetFlat (lump);
578 }
579 return flatmemory;
580 }
581
582
583 // help function for P_LoadSectors, find a flat in the active wad files,
584 // allocate an id for it, and set the levelflat (to speedup search)
585 //
P_AddLevelFlat(char * flatname)586 int P_AddLevelFlat ( char* flatname )
587 {
588 lump_name_t name8;
589 levelflat_t * lfp;
590 int i;
591
592 numerical_name( flatname, & name8 ); // fast compares
593
594 if( levelflats )
595 {
596 // scan through the already found flats
597 lfp = & levelflats[0];
598 for (i=0; i<numlevelflats; i++)
599 {
600 // Fast numerical name compare.
601 if( *(uint64_t *)lfp->name == name8.namecode )
602 {
603 goto found_level_flat; // return i
604 }
605 lfp ++;
606 }
607 }
608
609 // create new flat entry in levelflats
610 if (devparm)
611 GenPrintf(EMSG_dev, "flat %#03d: %s\n", numlevelflats, name8.s);
612
613 if (numlevelflats>=levelflat_max)
614 {
615 // grow number of levelflats
616 // use Z_Malloc directly because it is usually a small number
617 levelflat_max += LEVELFLAT_INC; // alloc more levelflats
618 levelflat_t* new_levelflats =
619 Z_Malloc (levelflat_max*sizeof(levelflat_t), PU_LEVEL, NULL);
620 // must zero because unanimated are left to defaults
621 memset( &new_levelflats[numlevelflats], 0,
622 (levelflat_max - numlevelflats)*sizeof(levelflat_t) );
623
624 if( levelflats )
625 {
626 memcpy (new_levelflats, levelflats, numlevelflats*sizeof(levelflat_t));
627 Z_Free ( levelflats );
628 }
629 levelflats = new_levelflats;
630 }
631
632 i = numlevelflats;
633 lfp = & levelflats[numlevelflats]; // array moved
634 numlevelflats++;
635
636 // store the name
637 *(uint64_t *)lfp->name = name8.namecode;
638
639 // store the flat lump number
640 lfp->lumpnum = R_FlatNumForName (flatname);
641 lfp->size_index = P_flatsize_to_index( W_LumpLength(lfp->lumpnum), flatname );
642
643 found_level_flat:
644 return i; // level flat id
645 }
646
647
648 // SoM: Do I really need to comment this?
P_FlatNameForNum(int num)649 char * P_FlatNameForNum(int num)
650 {
651 if(num < 0 || num > numlevelflats)
652 I_Error("P_FlatNameForNum: Invalid flatnum\n");
653
654 return Z_Strdup(va("%.8s", levelflats[num].name), PU_STATIC, 0);
655 }
656
657
658 static
P_LoadSectors(lumpnum_t lumpnum)659 void P_LoadSectors( lumpnum_t lumpnum )
660 {
661 byte* data;
662 mapsector_t* ms;
663 sector_t* ss;
664 int i;
665
666 numsectors = W_LumpLength(lumpnum) / sizeof(mapsector_t);
667 sectors = Z_Malloc (numsectors*sizeof(sector_t), PU_LEVEL, NULL);
668 memset (sectors, 0, numsectors*sizeof(sector_t));
669 data = W_CacheLumpNum( lumpnum, PU_STATIC ); // mapsector lump temp
670 // [WDJ] Fix endian as transfer from temp to internal.
671
672 if( !data || (numsectors < 1))
673 {
674 I_SoftError( "Bad sector data\n" );
675 return;
676 }
677
678 // [WDJ] init growing flats array
679 numlevelflats = 0;
680 levelflat_max = 0;
681 levelflats = NULL;
682
683 ms = (mapsector_t *)data; // ms will be ++
684 ss = sectors;
685 for (i=0 ; i<numsectors ; i++, ss++, ms++)
686 {
687 // signed
688 ss->floorheight = LE_SWAP16(ms->floorheight)<<FRACBITS;
689 ss->ceilingheight = LE_SWAP16(ms->ceilingheight)<<FRACBITS;
690
691 //
692 // flats
693 //
694 if( strncasecmp(ms->floorpic,"FWATER",6)==0 ||
695 strncasecmp(ms->floorpic,"FLTWAWA1",8)==0 ||
696 strncasecmp(ms->floorpic,"FLTFLWW1",8)==0 )
697 ss->floortype = FLOOR_WATER;
698 else
699 if( strncasecmp(ms->floorpic,"FLTLAVA1",8)==0 ||
700 strncasecmp(ms->floorpic,"FLATHUH1",8)==0 )
701 ss->floortype = FLOOR_LAVA;
702 else
703 if( strncasecmp(ms->floorpic,"FLTSLUD1",8)==0 )
704 ss->floortype = FLOOR_SLUDGE;
705 else
706 ss->floortype = FLOOR_SOLID;
707
708 ss->floorpic = P_AddLevelFlat (ms->floorpic);
709 ss->ceilingpic = P_AddLevelFlat (ms->ceilingpic);
710
711 ss->lightlevel = (uint16_t)( LE_SWAP16(ms->lightlevel) );
712 // all values are unsigned, but special field is signed short
713 ss->special = (uint16_t)( LE_SWAP16(ms->special) );
714 ss->tag = (uint16_t)( LE_SWAP16(ms->tag) ); // unsigned
715
716 ss->thinglist = NULL;
717 ss->touching_thinglist = NULL; //SoM: 4/7/2000
718
719 ss->stairlock = 0;
720 ss->nextsec = -1;
721 ss->prevsec = -1;
722
723 ss->modelsec = -1; //SoM: 3/17/2000: This causes some real problems
724 // [WDJ] Is now dependent upon model
725 ss->model = SM_normal; //SoM: 3/20/2000, [WDJ] 11/14/2009
726 ss->friction = ORIG_FRICTION; // normal friction
727 ss->movefactor = ORIG_FRICTION_FACTOR;
728 ss->floorlightsec = -1;
729 ss->ceilinglightsec = -1;
730 ss->ffloors = NULL;
731 ss->lightlist = NULL;
732 ss->numlights = 0;
733 ss->attached = NULL;
734 ss->numattached = 0;
735 ss->extra_colormap = NULL;
736 ss->moved = true; // force init of light lists
737 ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0;
738 ss->bottommap = ss->midmap = ss->topmap = -1;
739
740 // ----- for special tricks with HW renderer -----
741 ss->pseudoSector = false;
742 ss->virtualFloor = false;
743 ss->virtualCeiling = false;
744 ss->sectorLines = NULL;
745 ss->stackList = NULL;
746 ss->lineoutLength = -1.0;
747 // ----- end special tricks -----
748
749 }
750
751 Z_Free (data);
752
753 // whoa! there is usually no more than 25 different flats used per level!!
754 //debug_Printf("Load Sectors: %d flats found\n", numlevelflats);
755
756 // set the sky flat num
757 sky_flatnum = P_AddLevelFlat ("F_SKY1");
758
759 // search for animated flats and set up
760 P_Setup_LevelFlatAnims ();
761 }
762
763
764 //
765 // P_LoadNodes
766 //
P_LoadNodes(int lump)767 void P_LoadNodes (int lump)
768 {
769 byte* data;
770 int i;
771 int j;
772 int k;
773 mapnode_t* mn;
774 node_t* no;
775
776 numnodes = W_LumpLength (lump) / sizeof(mapnode_t);
777 nodes = Z_Malloc (numnodes*sizeof(node_t), PU_LEVEL, NULL);
778 data = W_CacheLumpNum (lump,PU_STATIC); // mapnode_t array temp
779 // [WDJ] Fix endian as transfer from temp to internal.
780
781 // No nodes and one subsector is a trivial but legal map.
782 if( (!data || (numnodes < 1)) && (numsubsectors > 1))
783 {
784 I_SoftError( "Bad node data\n" );
785 return;
786 }
787
788 mn = (mapnode_t *)data;
789 no = nodes;
790
791 for (i=0 ; i<numnodes ; i++, no++, mn++)
792 {
793 no->x = LE_SWAP16(mn->x)<<FRACBITS;
794 no->y = LE_SWAP16(mn->y)<<FRACBITS;
795 no->dx = LE_SWAP16(mn->dx)<<FRACBITS;
796 no->dy = LE_SWAP16(mn->dy)<<FRACBITS;
797 for (j=0 ; j<2 ; j++)
798 {
799 no->children[j] = (uint16_t)( LE_SWAP16(mn->children[j]) );
800 for (k=0 ; k<4 ; k++)
801 no->bbox[j][k] = LE_SWAP16(mn->bbox[j][k])<<FRACBITS;
802 }
803 }
804
805 Z_Free (data);
806 }
807
808 //
809 // P_LoadThings
810 //
P_LoadThings(int lump)811 void P_LoadThings (int lump)
812 {
813 // Doom mapthing template (internally we use a modified version)
814 typedef struct
815 {
816 int16_t x, y; ///< coordinates
817 int16_t angle; ///< orientation
818 uint16_t type; ///< DoomEd number
819 uint16_t flags;
820 } doom_mapthing_t;
821
822 int i;
823 mapthing_t* mt;
824 // boolean spawn;
825 byte *data;
826
827 data = W_CacheLumpNum (lump,PU_LEVEL); // temp things lump
828 // [WDJ] Do endian as read from temp things lump
829 nummapthings = W_LumpLength(lump) / sizeof(doom_mapthing_t);
830 mapthings = Z_Malloc(nummapthings * sizeof(mapthing_t), PU_LEVEL, NULL);
831
832 if( !data || (nummapthings < 1))
833 {
834 I_SoftError( "Bad things data\n" );
835 return;
836 }
837
838 //SoM: Because I put a new member into the mapthing_t for use with
839 //fragglescript, the format has changed and things won't load correctly
840 //using the old method.
841
842 doom_mapthing_t *dmt = (doom_mapthing_t *)data;
843 mt = mapthings;
844 for (i=0 ; i<nummapthings ; i++, mt++, dmt++)
845 {
846 // spawn = true;
847
848 // Do spawn all other stuff.
849 // SoM: Do this first so all the mapthing slots are filled!
850 mt->x = LE_SWAP16(dmt->x);
851 mt->y = LE_SWAP16(dmt->y);
852 mt->angle = LE_SWAP16(dmt->angle);
853 mt->type = (uint16_t)( LE_SWAP16(dmt->type) ); // DoomEd number
854 mt->options = (uint16_t)( LE_SWAP16(dmt->flags) ); // bit flags
855 mt->mobj = NULL; //SoM:
856
857 if( gamedesc_id == GDESC_tnt && gamemap == 31)
858 {
859 // Fix TNT MAP31 bug: yellow keycard is multiplayer only
860 // Released a fixed copy of TNT later, but CDROM have this bug.
861 if( mt->type == 6 ) // Yellow keycard
862 mt->options &= ~MTF_MPSPAWN; // Remove multiplayer only flag
863 }
864
865 #if 0
866 // PrBoom does legality checking here.
867 // May need this for special thing detection and engine setup.
868 P_Setup_Mapthing(mt);
869 #endif
870
871 P_SpawnMapthing (mt);
872 }
873
874 Z_Free(data);
875 }
876
877
878 //
879 // P_LoadLineDefs
880 // Also counts secret lines for intermissions.
881 //
P_LoadLineDefs(int lump)882 void P_LoadLineDefs (int lump)
883 {
884 byte* data;
885 int i;
886 maplinedef_t* mld;
887 line_t* ld;
888 vertex_t* v1;
889 vertex_t* v2;
890
891 numlines = W_LumpLength (lump) / sizeof(maplinedef_t);
892 lines = Z_Malloc (numlines*sizeof(line_t), PU_LEVEL, NULL);
893 memset (lines, 0, numlines*sizeof(line_t));
894 data = W_CacheLumpNum (lump,PU_STATIC); // temp linedefs array
895 // [WDJ] Fix endian as transfer from lump temp to internal.
896
897 if( !data || (numlines < 1))
898 {
899 I_SoftError( "Bad linedefs data\n" );
900 return;
901 }
902
903 mld = (maplinedef_t *)data;
904 ld = lines;
905 for (i=0 ; i<numlines ; i++, mld++, ld++)
906 {
907 ld->flags = (uint16_t)( LE_SWAP16(mld->flags) ); // bit flags
908 ld->special = (uint16_t)( LE_SWAP16(mld->special) );
909 ld->tag = (uint16_t)( LE_SWAP16(mld->tag) );
910 v1 = ld->v1 = &vertexes[ (uint16_t) LE_SWAP16(mld->v1) ];
911 v2 = ld->v2 = &vertexes[ (uint16_t) LE_SWAP16(mld->v2) ];
912 ld->dx = v2->x - v1->x;
913 ld->dy = v2->y - v1->y;
914
915 if (!ld->dx)
916 ld->slopetype = ST_VERTICAL;
917 else if (!ld->dy)
918 ld->slopetype = ST_HORIZONTAL;
919 else
920 {
921 if (FixedDiv (ld->dy , ld->dx) > 0)
922 ld->slopetype = ST_POSITIVE;
923 else
924 ld->slopetype = ST_NEGATIVE;
925 }
926
927 if (v1->x < v2->x)
928 {
929 ld->bbox[BOXLEFT] = v1->x;
930 ld->bbox[BOXRIGHT] = v2->x;
931 }
932 else
933 {
934 ld->bbox[BOXLEFT] = v2->x;
935 ld->bbox[BOXRIGHT] = v1->x;
936 }
937
938 if (v1->y < v2->y)
939 {
940 ld->bbox[BOXBOTTOM] = v1->y;
941 ld->bbox[BOXTOP] = v2->y;
942 }
943 else
944 {
945 ld->bbox[BOXBOTTOM] = v2->y;
946 ld->bbox[BOXTOP] = v1->y;
947 }
948
949 // Set soundorg in P_GroupLines
950
951 // NULL_INDEX = no sidedef
952 ld->sidenum[0] = (uint16_t)( LE_SWAP16(mld->sidenum[0]) );
953 ld->sidenum[1] = (uint16_t)( LE_SWAP16(mld->sidenum[1]) );
954
955 // [WDJ] detect common wad errors and make playable, similar to prboom
956 if( ld->sidenum[0] == NULL_INDEX )
957 {
958 // linedef is required to always have valid sidedef1
959 I_SoftError( "Linedef %i is missing sidedef1\n", i );
960 ld->sidenum[0] = 0; // arbitrary valid sidedef
961 }
962 else if ( ld->sidenum[0] >= numsides )
963 {
964 I_SoftError( "Linedef %i has sidedef1 bad index\n", i );
965 ld->sidenum[0] = 0; // arbitrary valid sidedef
966 }
967 if( ld->sidenum[1] == NULL_INDEX )
968 {
969 if( ld->flags & ML_TWOSIDED )
970 {
971 // two-sided linedef is required to always have valid sidedef2
972 I_SoftError( "Linedef %i is missing sidedef2\n", i );
973 // fix one or the other
974 // ld->sidenum[1] = 0; // arbitrary valid sidedef
975 ld->flags &= ~ML_TWOSIDED;
976 }
977 }
978 else if ( ld->sidenum[1] >= numsides )
979 {
980 I_SoftError( "Linedef %i has sidedef2 bad index\n", i );
981 ld->sidenum[1] = 0; // arbitrary valid sidedef
982 }
983
984
985 // special linedef has special sidedef1
986 if (ld->sidenum[0] != NULL_INDEX && ld->special)
987 sides[ld->sidenum[0]].linedef_special = ld->special;
988 }
989
990 Z_Free (data);
991 }
992
993
P_LoadLineDefs2()994 void P_LoadLineDefs2()
995 {
996 int i;
997 line_t* ld = lines;
998 for(i = 0; i < numlines; i++, ld++)
999 {
1000 if (ld->sidenum[0] != NULL_INDEX)
1001 ld->frontsector = sides[ld->sidenum[0]].sector;
1002 else
1003 ld->frontsector = 0;
1004
1005 if (ld->sidenum[1] != NULL_INDEX)
1006 ld->backsector = sides[ld->sidenum[1]].sector;
1007 else
1008 ld->backsector = 0;
1009
1010 // special linedef setup after sidedefs are loaded
1011 switch( ld->special )
1012 {
1013 case 260: // Boom transparency
1014 // sidedef1 of master linedef has the transparency map
1015 // Similar effect to Boom, no alternatives
1016 {
1017 int eff = ld->translu_eff; // TRANSLU_med, or TRANSLU_ext + lumpid
1018 short tag = ld->tag;
1019 // uint16_t tag = ld->tag; // change when lines[] changes
1020 if( tag )
1021 {
1022 // Same tagged linedef get it too (both sidedefs).
1023 int li;
1024 for( li=numlines-1; li>=0; li-- )
1025 {
1026 if( lines[li].tag == tag )
1027 lines[li].translu_eff = eff;
1028 // Cannot use special because Boom allows tagged lines
1029 // to have the transparent effect simultaneously with
1030 // other linedef effects.
1031 }
1032 }
1033 }
1034 }
1035 }
1036 }
1037
1038 #if 0
1039 // See two part load of sidedefs, with special texture interpretation
1040 //
1041 // P_LoadSideDefs
1042 //
1043 void P_LoadSideDefs (int lump)
1044 {
1045 byte* data;
1046 int i;
1047 mapsidedef_t* msd;
1048 side_t* sd;
1049
1050 numsides = W_LumpLength (lump) / sizeof(mapsidedef_t);
1051 sides = Z_Malloc (numsides*sizeof(side_t), PU_LEVEL, NULL);
1052 memset (sides, 0, numsides*sizeof(side_t));
1053 data = W_CacheLumpNum (lump,PU_STATIC); // sidedefs temp lump
1054 // [WDJ] Do endian as read from temp sidedefs lump
1055
1056 msd = (mapsidedef_t *)data;
1057 sd = sides;
1058 for (i=0 ; i<numsides ; i++, msd++, sd++)
1059 {
1060 sd->textureoffset = LE_SWAP16(msd->textureoffset)<<FRACBITS;
1061 sd->rowoffset = LE_SWAP16(msd->rowoffset)<<FRACBITS;
1062 // 0= no-texture, never -1
1063 sd->toptexture = R_TextureNumForName(msd->toptexture);
1064 sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
1065 sd->midtexture = R_TextureNumForName(msd->midtexture);
1066
1067 sd->sector = §ors[ (uint16_t)( LE_SWAP16(msd->sector) )];
1068 }
1069
1070 Z_Free (data);
1071 }
1072 #endif
1073
1074 static
Report_sidedef_bad_sector(int sdnum,int secnum)1075 void Report_sidedef_bad_sector( int sdnum, int secnum )
1076 {
1077 int li;
1078
1079 // When WAD has not been cleaned, some editors leave sidedefs around
1080 // with sector_num=65535.
1081 if( (! verbose) && (secnum == 65535) ) return;
1082
1083 for( li=numlines-1; li>=0; li-- )
1084 {
1085 if( lines[li].sidenum[0] == sdnum
1086 || lines[li].sidenum[1] == sdnum )
1087 {
1088 // found parent linedef
1089 I_SoftError( "SideDef %i has bad sector number %i, used by line %i\n",
1090 sdnum, secnum, li );
1091 return;
1092 }
1093 }
1094 I_SoftError( "SideDef %i has bad sector number %i, UNUSED\n", sdnum, secnum );
1095 }
1096
1097
1098 // Two part load of sidedefs
1099 // [WDJ] Do endian conversion in part2
P_LoadSideDefs(int lump)1100 void P_LoadSideDefs (int lump)
1101 {
1102 numsides = W_LumpLength(lump) / sizeof(mapsidedef_t);
1103 sides = Z_Malloc(numsides*sizeof(side_t), PU_LEVEL, NULL);
1104 memset(sides, 0, numsides*sizeof(side_t));
1105 }
1106
1107 // SoM: 3/22/2000: Delay loading texture names until after loaded linedefs.
1108
1109 // Interpret Linedef specials in sidedefs,
1110 // after other supporting data has been loaded.
P_LoadSideDefs2(int lump)1111 void P_LoadSideDefs2(int lump)
1112 {
1113 mapsidedef_t * msdlump = W_CacheLumpNum(lump, PU_IN_USE); // sidedefs lump
1114 // [WDJ] Do endian as read from temp sidedefs lump
1115 int sdnum;
1116 int num, eff;
1117
1118 for (sdnum=0; sdnum<numsides; sdnum++)
1119 {
1120 register mapsidedef_t *msd = & msdlump[sdnum]; // map sidedef
1121 register side_t *sd = & sides[sdnum];
1122 register sector_t *sec;
1123
1124 sd->textureoffset = LE_SWAP16(msd->textureoffset)<<FRACBITS;
1125 sd->rowoffset = LE_SWAP16(msd->rowoffset)<<FRACBITS;
1126
1127 // Refined to allow special linedef colormap (in texture name) to instead
1128 // be a wall texture (wall texture name instead of colormap name)
1129 // using the normal colormap.
1130 // Check if valid texture first, on failure check if valid colormap,
1131 // because we have func that can check texture without error.
1132
1133 uint16_t secnum = (uint16_t)( LE_SWAP16(msd->sector) );
1134 // [WDJ] Check for buggy wad, like prboom
1135 if( secnum >= numsectors )
1136 {
1137 Report_sidedef_bad_sector( sdnum, secnum );
1138 secnum = 0; // arbitrary use of sector 0
1139 }
1140 sd->sector = sec = §ors[secnum];
1141
1142 // original linedef types are 1..141, higher values are extensions
1143 switch (sd->linedef_special)
1144 {
1145 case 242: // Boom deep water, sidedef1 texture is colormap
1146 case 280: //SoM: 3/22/2000: Legacy water type.
1147 // Sets topmap,midmap,bottommap colormaps, in the tagged sectors.
1148 // Uses the model sector lightlevel underwater, and over ceiling.
1149 // [WDJ] There is no good reason for HWRENDER to block recording the
1150 // colormaps if the worse that the hardware renderer does is ignore them.
1151 {
1152 num = R_CheckTextureNumForName(msd->toptexture);
1153 if(num == -1) // if not texture
1154 {
1155 // must be colormap
1156 sec->topmap = R_ColormapNumForName(msd->toptexture);
1157 num = 0;
1158 }
1159 sd->toptexture = num; // never set to -1
1160
1161 num = R_CheckTextureNumForName(msd->midtexture);
1162 if(num == -1)
1163 {
1164 sec->midmap = R_ColormapNumForName(msd->midtexture);
1165 num = 0;
1166 }
1167 sd->midtexture = num; // never set to -1
1168
1169
1170 num = R_CheckTextureNumForName(msd->bottomtexture);
1171 if(num == -1)
1172 {
1173 sec->bottommap = R_ColormapNumForName(msd->bottomtexture);
1174 num = 0;
1175 }
1176 sd->bottomtexture = num; // never set to -1
1177 }
1178 break; // [WDJ] no fall through
1179
1180 case 282: //SoM: 4/4/2000: Just colormap transfer
1181 // Set the colormap of all tagged sectors.
1182
1183 // SoM: R_Create_Colormap will only create a colormap in software mode...
1184 // [WDJ] Expanded to hardware mode too.
1185 {
1186 if(msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#')
1187 {
1188 // generate colormap from sidedef1 texture text strings
1189 sec->midmap = R_Create_Colormap_str(msd->toptexture, msd->midtexture, msd->bottomtexture);
1190 sd->toptexture = sd->bottomtexture = 0;
1191 sec->extra_colormap = &extra_colormaps[sec->midmap];
1192 }
1193 else
1194 {
1195 // textures never set to -1
1196 if((num = R_CheckTextureNumForName(msd->toptexture)) == -1)
1197 sd->toptexture = 0;
1198 else
1199 sd->toptexture = num;
1200 if((num = R_CheckTextureNumForName(msd->midtexture)) == -1)
1201 sd->midtexture = 0;
1202 else
1203 sd->midtexture = num;
1204 if((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1)
1205 sd->bottomtexture = 0;
1206 else
1207 sd->bottomtexture = num;
1208 }
1209 }
1210 break; // [WDJ] no fall through
1211 // case 282, if(render_soft), was falling through,
1212 // but as 260 has same tests, the damage was benign
1213
1214
1215 case 260: // Boom transparency
1216 // When tag=0: this sidedef middle texture is made translucent using TRANMAP.
1217 // When tag!=0: all same tagged linedef have their middle texture
1218 // made translucent using sidedef1.
1219 // If this sidedef middle texture is a TRANMAP, size=64K, then it
1220 // is used for the transluceny.
1221 // This always affects both sidedefs.
1222 // never set to -1, 0=no_texture
1223 // Do not mangle special because Boom allows tagged lines
1224 // to have the transparent effect simultaneously with
1225 // other linedef effects.
1226 eff = TRANSLU_med; // default TRANMAP
1227 sd->midtexture = 0; // default, no texture
1228 // texture name = "TRANMAP" means use TRANSLU_med
1229 if( strncasecmp("TRANMAP", msd->midtexture, 8) != 0 )
1230 {
1231 // From Boom, any lump can be transparency map if it is right size
1232 lumpnum_t spec_num = W_CheckNumForName( msd->midtexture );
1233 if( VALID_LUMP( spec_num ) && W_LumpLength(spec_num) == 65536 )
1234 {
1235 int translu_map_num = R_setup_translu_store( spec_num );
1236 eff = TRANSLU_ext + translu_map_num;
1237 // LoadLineDefs2 will propagate it to other linedefs
1238 }
1239 else
1240 {
1241 // Not lump name or not right size
1242 // midtexture is texture
1243 num = R_CheckTextureNumForName(msd->midtexture);
1244 sd->midtexture = (num == -1) ? 0 : num;
1245 }
1246 }
1247 {
1248 // Find parent linedef and update, otherwise would have to use
1249 // some field to pass translu_eff back up to it.
1250 int li;
1251 for( li=numlines-1; li>=0; li-- )
1252 {
1253 if( lines[li].sidenum[0] == sdnum ) // found parent linedef
1254 {
1255 lines[li].translu_eff = eff;
1256 break;
1257 }
1258 }
1259 }
1260
1261 num = R_CheckTextureNumForName(msd->toptexture);
1262 sd->toptexture = (num == -1) ? 0 : num;
1263
1264 num = R_CheckTextureNumForName(msd->bottomtexture);
1265 sd->bottomtexture = (num == -1) ? 0 : num;
1266 break;
1267 /* case 260: // killough 4/11/98: apply translucency to 2s normal texture
1268 sd->midtexture = strncasecmp("TRANMAP", msd->midtexture, 8) ?
1269 ( ! VALID_LUMP(sd->special = W_CheckNumForName(msd->midtexture)) )
1270 ||
1271 W_LumpLength(sd->special) != 65536 ?
1272 sd->special=0, R_TextureNumForName(msd->midtexture) :
1273 (sd->special++, 0) : (sd->special=0);
1274 sd->toptexture = R_TextureNumForName(msd->toptexture);
1275 sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
1276 break;*/ //This code is replaced.. I need to fix this though
1277
1278
1279 //Hurdler: added for alpha value with translucent 3D-floors/water
1280 case 300: // Legacy solid translucent 3D floor in tagged
1281 case 301: // Legacy translucent 3D water in tagged
1282 case 302: // Legacy 3D fog in tagged
1283 case 304: // Legacy opaque fluid (because of inside)
1284 // 3Dfloor slab uses model sector ceiling and floor, heights and flats.
1285 // Upper texture encodes the translucent alpha: #nnn => 0..255
1286 // Uses model sector colormap and lightlevel
1287 // Interpret texture name string as decimal alpha and fogwater effect
1288 sd->toptexture = R_Create_FW_effect( sd->linedef_special,
1289 msd->toptexture );
1290 sd->bottomtexture = 0;
1291 sd->midtexture = R_TextureNumForName(msd->midtexture); // side texture
1292 break;
1293
1294 default: // normal cases
1295 // SoM: Lots of people are sick of texture errors.
1296 // Hurdler: see r_data.c for my suggestion
1297 // [WDJ] 0=no-texture, texture not found returns default texture.
1298 // Textures never set to -1, so these texture num are safe to use as array index.
1299 sd->midtexture = R_TextureNumForName(msd->midtexture);
1300 sd->toptexture = R_TextureNumForName(msd->toptexture);
1301 sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
1302 break;
1303 }
1304 }
1305 Z_Free (msdlump);
1306 }
1307
1308
1309
1310
1311 //
1312 // P_LoadBlockMap
1313 //
1314 // Read wad blockmap using int16_t wadblockmaplump[].
1315 // Expand from 16bit wad to internal 32bit blockmap.
P_LoadBlockMap(int lump)1316 void P_LoadBlockMap (int lump)
1317 {
1318 int count = W_LumpLength(lump)/2; // number of 16 bit blockmap entries
1319 uint16_t * wadblockmaplump = W_CacheLumpNum (lump, PU_LEVEL); // blockmap lump temp
1320 uint32_t firstlist, lastlist; // blockmap block list bounds
1321 uint32_t overflow_corr = 0;
1322 uint32_t bme;
1323 uint32_t max_bme = 0; // for detecting overflow wrap
1324 #ifdef TRACE_BLOCKMAPHEAD
1325 uint32_t head_bmi = 0;
1326 #endif
1327 int blockmap_errors = 0;
1328 int i;
1329
1330 #ifdef DUMP_BLOCKMAP
1331 char dbmfn[MAX_WADPATH]; // DUMP_BLOCKMAP file name
1332 snprintf( dbmfn, MAX_WADPATH-1, "%s_M%i", DUMP_BLOCKMAP, gamemap );
1333 FILE * dbmfp = fopen( dbmfn, "w" );
1334 #endif
1335
1336 // [WDJ] when zennode has not been run, this code will corrupt Zone memory.
1337 // It assumes a minimum size blockmap.
1338 if( count < 5 )
1339 I_Error( "Missing blockmap, node builder has not been run.\n" );
1340
1341 // [WDJ] Do endian as read from blockmap lump temp
1342 blockmaphead = Z_Malloc(sizeof(*blockmaphead) * count, PU_LEVEL, NULL);
1343
1344 // killough 3/1/98: Expand wad blockmap into larger internal one,
1345 // by treating all offsets except -1 as unsigned and zero-extending
1346 // them. This potentially doubles the size of blockmaps allowed,
1347 // because Doom originally considered the offsets as always signed.
1348 // [WDJ] They are unsigned in Unofficial Doom Spec.
1349
1350 blockmaphead[0] = LE_SWAP16(wadblockmaplump[0]); // map orgin_x
1351 blockmaphead[1] = LE_SWAP16(wadblockmaplump[1]); // map orgin_y
1352 blockmaphead[2] = (uint16_t)( LE_SWAP16(wadblockmaplump[2]) ); // number columns (x size)
1353 blockmaphead[3] = (uint16_t)( LE_SWAP16(wadblockmaplump[3]) ); // number rows (y size)
1354
1355 bmaporgx = blockmaphead[0]<<FRACBITS;
1356 bmaporgy = blockmaphead[1]<<FRACBITS;
1357 bmapwidth = blockmaphead[2];
1358 bmapheight = blockmaphead[3];
1359 blockmapindex = & blockmaphead[4];
1360 firstlist = 4 + (bmapwidth*bmapheight);
1361 lastlist = count - 1;
1362
1363 #ifdef TRACE_BLOCKMAPHEAD
1364 GenPrintf(EMSG_warn,"Blockmap: width=%i, height=%i, org=(%4X.%4X,%4X.%4X), firstlist=%i, count=%i\n",
1365 bmapwidth, bmapheight, (bmaporgx>>16), (bmaporgx&0xFFFF), (bmaporgy>>16), (bmaporgy&0xFFFF), firstlist, count );
1366 #endif
1367 #ifdef DUMP_BLOCKMAP
1368 fprintf( dbmfp, "Map: %i\n", gamemap );
1369 fprintf( dbmfp, "Blockmap: width=%i, height=%i, org=(%4X.%4X,%4X.%4X), firstlist=%X (%i), lastlist=%X\n",
1370 bmapwidth, bmapheight, (bmaporgx>>16), (bmaporgx&0xFFFF), (bmaporgy>>16), (bmaporgy&0xFFFF), firstlist, firstlist, lastlist );
1371 if( lastlist > 0xFFFF )
1372 fprintf( dbmfp, "Large Blockmap: overflow +%i\n", lastlist >> 16 );
1373 #endif
1374
1375 if( firstlist >= lastlist || bmapwidth < 1 || bmapwidth > 0xFFF0 || bmapheight < 1 || bmapheight > 0xFFF0 )
1376 I_Error( "Blockmap corrupt, must run node builder on wad.\n" );
1377
1378 // read blockmap index array
1379 for (i=4 ; i<firstlist ; i++) // for all entries in wad offset index
1380 {
1381 // [WDJ] LE_SWAP16 returns a 16 bit signed value on a big-endian machine,
1382 // so must make it unsigned, otherwise it can get sign extended.
1383 // Found by Michael Bauerle.
1384 bme = (uint16_t)( LE_SWAP16(wadblockmaplump[i]) ); // offset
1385 #ifdef DUMP_BLOCKMAP
1386 fprintf( dbmfp,"#%6X %6X\n", i, bme );
1387 #endif
1388
1389 if( bme == firstlist )
1390 {
1391 // Use the first list. Zennode compress will put a common empty list as first list.
1392 goto save_blockmap;
1393 }
1394
1395 // upon overflow, the bme will wrap to low values
1396 if ( (bme < firstlist) // too small to be valid
1397 && (bme < 0x2000) && ((max_bme & 0xFFFF) > 0xE000)) // wrapped
1398 {
1399 // first or repeated overflow
1400 uint32_t overflow_corr_n = overflow_corr + 0x00010000;
1401 if( overflow_corr_n >= lastlist )
1402 {
1403 GenPrintf(EMSG_warn,"Blockmap offset[%i]: Overflow 0x%X, exceeds lastlist=0x%X\n", i, overflow_corr_n, lastlist );
1404 #ifdef DUMP_BLOCKMAP
1405 fprintf( dbmfp,"Blockmap offset[%i]: Overflow 0x%X, exceeds lastlist=0x%X\n", i, overflow_corr_n, lastlist );
1406 #endif
1407 }
1408 else
1409 {
1410 // within lump bounds
1411 overflow_corr = overflow_corr_n;
1412 GenPrintf(EMSG_warn,"Blockmap offset[%i...]: Overflow correct 0x%X\n", i, overflow_corr );
1413 #ifdef DUMP_BLOCKMAP
1414 fprintf( dbmfp,"Blockmap offset[%X...]: Overflow correct 0x%X\n", i, overflow_corr );
1415 #endif
1416 }
1417 }
1418
1419 if( overflow_corr == 0 ) // normal blockmap entry
1420 {
1421 goto save_blockmap;
1422 }
1423
1424 // Blockmap is loaded before linedefs, so cannot verify blockmap by checking linedefs.
1425 // if( overflow_corr )
1426 {
1427 // correct for overflow
1428 uint32_t bmec = bme + overflow_corr;
1429 uint32_t bmi = blockmaphead[i-1];
1430 byte have_corrected = 0;
1431
1432 #ifdef DUMP_BLOCKMAP
1433 fprintf( dbmfp, " Overflow: prev blockmaphead[%X]=%X, max_bme=%X, corrected bmec=%X\n", i-1, bmi, max_bme, bmec );
1434 #endif
1435
1436 if( bmec <= lastlist )
1437 {
1438 uint32_t wbmec = (uint16_t)( LE_SWAP16(wadblockmaplump[bmec]) );
1439 uint32_t wbm3 = (bmec > 0)? (uint16_t)( LE_SWAP16(wadblockmaplump[bmec-1]) ) : 0xFFFF;
1440 #ifdef DUMP_BLOCKMAP
1441 fprintf( dbmfp, " Check list head: wadblockmap[bmec-1]=%X wadblockmap[bmec]=%X\n", wbm3, wbmec );
1442 #endif
1443 if( (wbm3 == 0xFFFF) && (wbmec == 0) ) // valid start list
1444 {
1445 // Valid blockmap list.
1446 // Note: zennode will compress, scattering the entries.
1447 #ifdef DUMP_BLOCKMAP
1448 fprintf( dbmfp, " Valid List: %X\n", bmec );
1449 #endif
1450 bme = bmec; // accept corrected blockmap list head
1451 goto save_blockmap;
1452 }
1453 }
1454
1455 // not accepted above
1456 {
1457 // Test index in previous overflow_corr groups.
1458 // This happens when zennode compresses the blockmap by reusing exisiting linedef lists.
1459 // Assert: overflow_corr < lastlist
1460 uint32_t bmec2;
1461 for( bmec2 = bme; bmec2 < overflow_corr; bmec2 += 0x10000 ) // all previous overflow_corr
1462 {
1463 uint32_t wbmec = (uint16_t)( LE_SWAP16(wadblockmaplump[bmec2]) );
1464 uint32_t wbm3 = (bmec2 > 0)? (uint16_t)( LE_SWAP16(wadblockmaplump[bmec2-1]) ) : 0xFFFF;
1465 if( (wbm3 == 0xFFFF) && (wbmec == 0) ) // valid start list
1466 {
1467 // Because node builder did not make a new entry, it must be this existing entry.
1468 #ifdef DUMP_BLOCKMAP
1469 fprintf( dbmfp, " Found list entry at: bmec=%X\n", bmec2 );
1470 #endif
1471 bme = bmec2;
1472 goto save_blockmap;
1473 }
1474 }
1475 }
1476
1477 // not accepted above
1478 GenPrintf( EMSG_warn, "Blockmap offset not a list head: bme=%X bmec=%X\n", bme, bmec );
1479 GenPrintf( EMSG_warn, " prev blockmaphead[%i]=%X\n", i-1, blockmaphead[i-1] );
1480 #ifdef DUMP_BLOCKMAP
1481 fprintf( dbmfp, "Blockmap offset not a list head: bme=%X bmec=%X\n", bme, bmec );
1482 fprintf( dbmfp, " prev blockmaphead[%i]=%X\n", i-1, blockmaphead[i-1] );
1483 #endif
1484
1485 // FIXME: Replace this with something that is more likely to find a usable blockmap list.
1486 // Meantime, this dumps some of the blockmap list, for diagnosis.
1487 {
1488 // Search for next blockmap list head, desperate last fix.
1489 // This assumes there is something wrong with our blockmap list decoding.
1490 uint32_t wbm1 = (uint16_t)( LE_SWAP16(wadblockmaplump[bmi]) ); // prev
1491 uint32_t list_head = 0;
1492 #ifdef TRACE_BLOCKMAPHEAD
1493 uint32_t headcnt = 0;
1494 #endif
1495 byte fatal_error_bme = 0;
1496
1497 list_head = blockmaphead[i-1];
1498 for( bmi = blockmaphead[i-1]+1; bmi <= lastlist; bmi++ )
1499 {
1500 uint32_t wbm2 = (uint16_t)( LE_SWAP16(wadblockmaplump[bmi]) );
1501 if(wbm2 > (0xFFFF/2))
1502 {
1503 // Blockmap list entry suspicious large
1504 GenPrintf( EMSG_warn, "Blockmap list entry suspicious large: %X\n", wbm2 );
1505 #ifdef DUMP_BLOCKMAP
1506 fprintf( dbmfp, "Blockmap list entry suspicious large: %X\n", wbm2 );
1507 #endif
1508 }
1509
1510 if(wbm1 == 0xFFFF) // prev was end-of-list
1511 {
1512 if( wbm2 == 0 )
1513 {
1514 // Head of list
1515 list_head = bmi;
1516
1517 #ifdef TRACE_BLOCKMAPHEAD
1518 if( (headcnt < 1) || ((headcnt < 8) && (bmi > head_bmi)) || (((bmi - bme)&0xFF) == 0) )
1519 {
1520 GenPrintf( EMSG_warn, "Found blockmaphead: wadblockmaplump[%X] bme_diff=%X\n", bmi, (bmi - bme));
1521 #ifdef DUMP_BLOCKMAP
1522 fprintf( dbmfp, "Found blockmaphead: wadblockmaplump[%X] bme_diff=%X\n", bmi, (bmi - bme));
1523 #endif
1524 if( bmi > head_bmi ) head_bmi = bmi;
1525 }
1526
1527 headcnt++;
1528 #endif
1529
1530 if( ! have_corrected )
1531 {
1532 GenPrintf( EMSG_warn, "Using next blockmaphead: wadblockmaplump[%X] bme_diff=%X\n", bmi, (bmi - bme));
1533 #ifdef DUMP_BLOCKMAP
1534 fprintf( dbmfp, "Using next blockmaphead: wadblockmaplump[%X] bme_diff=%X\n", bmi, (bmi - bme));
1535 #endif
1536 have_corrected = 1;
1537 bmec = bmi;
1538 break;
1539 }
1540 }
1541 else
1542 {
1543 // After 0xFFFF must be 0.
1544 GenPrintf( EMSG_warn, "Corrupt blockmaphead: wadblockmaplump[%X] = %X\n", bmi, wbm2 );
1545 #ifdef DUMP_BLOCKMAP
1546 fprintf( dbmfp, "Corrupt blockmaphead: wadblockmaplump[%X] = %X\n", bmi, wbm2 );
1547 #endif
1548 blockmap_errors++;
1549 fatal_error_bme = 1;
1550 }
1551 }
1552 else if( wbm2 == 0xFFFF )
1553 {
1554 // End of blockmap list
1555 GenPrintf( EMSG_warn, " list_length=%X\n", (bmi - list_head));
1556 #ifdef DUMP_BLOCKMAP
1557 fprintf( dbmfp, " list_length=%X\n", (bmi - list_head));
1558 #endif
1559 }
1560 else if( wbm1 == 0 )
1561 {
1562 // first entry of list
1563 }
1564
1565 wbm1 = wbm2;
1566 }
1567
1568 #ifdef TRACE_BLOCKMAPHEAD
1569 if( headcnt > 1 )
1570 {
1571 GenPrintf( EMSG_debug, "Found %i possible blockmaphead.\n", headcnt );
1572 #ifdef DUMP_BLOCKMAP
1573 fprintf( dbmfp, "Found %i possible blockmaphead.\n", headcnt );
1574 #endif
1575 }
1576 #endif
1577
1578 if( fatal_error_bme || ( ! have_corrected ))
1579 {
1580 goto fake_it;
1581 }
1582
1583 bme = bmec;
1584 }
1585 }
1586
1587
1588 save_blockmap:
1589 if ( bme > lastlist )
1590 {
1591 #ifdef DUMP_BLOCKMAP
1592 fprintf( dbmfp, "Blockmap offset[%i]= %X, exceeds bounds.\n", i, bme);
1593 #endif
1594 I_SoftError("Blockmap offset[%i]= %X, exceeds bounds.\n", i, bme);
1595 goto fake_it;
1596 }
1597 if ( bme < firstlist
1598 || ((uint16_t)(LE_SWAP16(wadblockmaplump[bme]))) != 0 ) // not start list
1599 {
1600 #ifdef DUMP_BLOCKMAP
1601 fprintf( dbmfp, "Bad blockmap offset[%i]= %X.\n", i, bme);
1602 #endif
1603 I_SoftError("Bad blockmap offset[%i]= %X.\n", i, bme);
1604 goto fake_it;
1605 }
1606
1607 store_it:
1608 blockmaphead[i] = bme;
1609 if( bme > max_bme ) max_bme = bme; // detecting wrap
1610 continue;
1611
1612 fake_it:
1613 // put something reasonable, so rest of map can be played.
1614 // This does not work if i=0, but in that case there is no blockmap at all,
1615 // and it will error out anyway.
1616 bme = blockmaphead[i-1];
1617 goto store_it;
1618 }
1619
1620 if( blockmap_errors > 32 )
1621 {
1622 I_Error("Too many blockmap errors.\n");
1623 }
1624
1625
1626 #ifdef DUMP_BLOCKMAP
1627 fprintf( dbmfp, "Linedef lists:\n" );
1628 #endif
1629
1630 // read blockmap linedef lists
1631 for (i=firstlist ; i<count ; i++) // for all lists in lump
1632 {
1633 // killough 3/1/98
1634 // Unsigned except for -1, which will be read as 0xFFFF.
1635 // [WDJ] LE_SWAP16 is signed on big-endian machines, so convert to prevent errors.
1636 uint16_t bme = (uint16_t)( LE_SWAP16(wadblockmaplump[i]) );
1637 blockmaphead[i] = (bme == 0xffff)? ((uint32_t) -1) : ((uint32_t) bme);
1638 #ifdef DUMP_BLOCKMAP
1639 fprintf( dbmfp, "#%6X %6X\n", i, bme );
1640 #endif
1641 }
1642
1643 Z_Free(wadblockmaplump);
1644
1645
1646 // clear out mobj chains
1647 unsigned int bm_size = sizeof(*blocklinks) * bmapwidth * bmapheight;
1648 blocklinks = Z_Malloc (bm_size, PU_LEVEL, NULL);
1649 memset (blocklinks, 0, bm_size);
1650 /* Original
1651 blockmaplump = W_CacheLumpNum (lump,PU_LEVEL);
1652 blockmap = blockmaplump+4;
1653 count = W_LumpLength (lump)/2;
1654
1655 for (i=0 ; i<count ; i++)
1656 blockmaplump[i] = LE_SWAP16(blockmaplump[i]);
1657
1658 bmaporgx = blockmaplump[0]<<FRACBITS;
1659 bmaporgy = blockmaplump[1]<<FRACBITS;
1660 bmapwidth = blockmaplump[2];
1661 bmapheight = blockmaplump[3];
1662 }
1663
1664 // clear out mobj chains
1665 count = sizeof(*blocklinks)*bmapwidth*bmapheight;
1666 blocklinks = Z_Malloc (count, PU_LEVEL, NULL);
1667 memset (blocklinks, 0, count);
1668 */
1669 #ifdef DUMP_BLOCKMAP
1670 fclose(dbmfp);
1671 #endif
1672 }
1673
1674
1675
1676 //
1677 // P_GroupLines
1678 // Builds sector line lists and subsector sector numbers.
1679 // Finds block bounding boxes for sectors.
1680 //
P_GroupLines(void)1681 void P_GroupLines (void)
1682 {
1683 line_t** linebuffer; // to build line list
1684 line_t* li;
1685 sector_t* sector;
1686 subsector_t* ss;
1687 seg_t* seg;
1688 fixed_t bbox[4];
1689 int block;
1690 int total;
1691 int i, j;
1692
1693 // look up sector number for each subsector
1694 ss = subsectors;
1695 for (i=0 ; i<numsubsectors ; i++, ss++)
1696 {
1697 // [WDJ] Detct buggy wad
1698 if( ss->firstline > numsegs )
1699 {
1700 I_Error( "P_GroupLines: subsector firstline %i > numsegs %i\n",
1701 ss->firstline, numsegs );
1702 }
1703 seg = &segs[ss->firstline]; // first seg of the subsector
1704 if( seg->sidedef )
1705 {
1706 // normal
1707 ss->sector = seg->sidedef->sector;
1708 }
1709 else
1710 {
1711 // [WDJ] prboom can play Europe.wad, but Legacy segfaults, cannot have that.
1712 // buggy wad, try to recover
1713 I_SoftError( "P_GroupLines, subsector without sidedef1 sector\n");
1714 // find one good reference in all the segs, like in prboom does
1715 for(j=0; j < ss->numlines; j++ )
1716 {
1717 if( seg->sidedef )
1718 {
1719 ss->sector = seg->sidedef->sector;
1720 GenPrintf(EMSG_error, " found sector in seg #%d\n", j );
1721 goto continue_subsectors;
1722 }
1723 seg++; // step through segs from firstline
1724 }
1725 // subsector has no sector
1726 I_SoftError( "P_GroupLines, subsector defaulted to sector[0]\n");
1727 // [WDJ] arbitrarily use sector[0], because these usually are not visible.
1728 ss->sector = & sectors[0];
1729 }
1730 continue_subsectors:
1731 continue;
1732 }
1733
1734 // count number of lines in each sector
1735 li = lines;
1736 total = 0;
1737 for (i=0 ; i<numlines ; i++, li++) // for each line
1738 {
1739 // [WDJ] some wads ( like blowup.wad, and zdoom formats)
1740 // have missing frontsector, but other ports (like prboom) cope
1741 if( li->frontsector )
1742 {
1743 total++;
1744 li->frontsector->linecount++;
1745 }
1746 else
1747 {
1748 I_SoftError( "P_GroupLines, linedef #%d missing frontsector\n", i );
1749 }
1750
1751 if (li->backsector && li->backsector != li->frontsector)
1752 {
1753 li->backsector->linecount++;
1754 total++;
1755 }
1756 }
1757
1758 // build line tables for each sector
1759 // One allocation for all, each sector using a segment of the list
1760 linebuffer = Z_Malloc(total*sizeof(line_t *), PU_LEVEL, NULL);
1761 sector = sectors; // §ors[0]
1762 for (i=0 ; i<numsectors ; i++, sector++)
1763 {
1764 // for each sector
1765 M_ClearBox (bbox);
1766 sector->linelist = linebuffer; // the next segment
1767 li = lines; // &lines[0]
1768 for (j=0 ; j<numlines ; j++, li++)
1769 {
1770 // for each line
1771 // check if it has this sector as a side
1772 if (li->frontsector == sector || li->backsector == sector)
1773 {
1774 *linebuffer++ = li; // add it to this segment
1775 M_AddToBox (bbox, li->v1->x, li->v1->y);
1776 M_AddToBox (bbox, li->v2->x, li->v2->y);
1777 }
1778 }
1779 // check that added lines in this segment equal the sector linecount
1780 if (linebuffer - sector->linelist != sector->linecount)
1781 I_Error ("P_GroupLines: miscounted");
1782
1783 // set the degenmobj_t to the middle of the bounding box
1784 sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2;
1785 sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2;
1786
1787 // adjust bounding box to map blocks
1788 block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT;
1789 block = block >= bmapheight ? bmapheight-1 : block;
1790 sector->blockbox[BOXTOP]=block;
1791
1792 block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT;
1793 block = block < 0 ? 0 : block;
1794 sector->blockbox[BOXBOTTOM]=block;
1795
1796 block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT;
1797 block = block >= bmapwidth ? bmapwidth-1 : block;
1798 sector->blockbox[BOXRIGHT]=block;
1799
1800 block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT;
1801 block = block < 0 ? 0 : block;
1802 sector->blockbox[BOXLEFT]=block;
1803 }
1804
1805 }
1806
1807
1808 // SoM: 6/27: Don't restrict maps to MAPxx/ExMx any more!
1809 char *levellumps[] =
1810 {
1811 "label", // ML_LABEL, A separator, name, ExMx or MAPxx
1812 "THINGS", // ML_THINGS, Monsters, items..
1813 "LINEDEFS", // ML_LINEDEFS, LineDefs, from editing
1814 "SIDEDEFS", // ML_SIDEDEFS, SideDefs, from editing
1815 "VERTEXES", // ML_VERTEXES, Vertices, edited and BSP splits generated
1816 "SEGS", // ML_SEGS, LineSegs, from LineDefs split by BSP
1817 "SSECTORS", // ML_SSECTORS, SubSectors, list of LineSegs
1818 "NODES", // ML_NODES, BSP nodes
1819 "SECTORS", // ML_SECTORS, Sectors, from editing
1820 "REJECT", // ML_REJECT, LUT, sector-sector visibility
1821 "BLOCKMAP", // ML_BLOCKMAP LUT, motion clipping, walls/grid element
1822 "BEHAVIOR", // ML_BEHAVIOR Hexen
1823 };
1824
1825
1826 #if 0
1827 // Unused
1828 //
1829 // Checks for the normal level header lumps.
1830 // lump : the header lump
1831 static
1832 boolean P_CheckHeaderLumps(int lump)
1833 {
1834 int i;
1835 int filen, lumpn;
1836
1837 filen = WADFILENUM(lump);
1838 if( filen > numwadfiles ) goto fail;
1839
1840 int numlump = wadfiles[filen]->numlups;
1841 lumpinfo_t * lump_p = wadfiles[filen]->lumpinfo;
1842
1843 lumpn = LUMPNUM(lump);
1844
1845 for(i=ML_THINGS; i<=ML_BLOCKMAP; i++)
1846 {
1847 int li = lumpn + i;
1848 if( li > numlump ) goto fail;
1849 if( strncmp( lump_p[li].name, levellumps[i], 8) ) goto fail;
1850 }
1851 return true;
1852
1853 fail:
1854 return false;
1855 }
1856 #endif
1857
1858
1859 // Checks a lump and returns whether or not it is a level header lump.
1860 // ml : a specific lump type or 0 to search all
1861 static
P_CheckLumpName(int lump,int ml)1862 int P_CheckLumpName(int lump, int ml)
1863 {
1864 int ml2;
1865 int filen, lumpn;
1866
1867 filen = WADFILENUM(lump);
1868 if( filen > numwadfiles )
1869 goto fail;
1870
1871 lumpn = LUMPNUM(lump);
1872 if( lumpn > wadfiles[filen]->numlumps )
1873 goto fail;
1874
1875 lumpinfo_t * lump_p = wadfiles[filen]->lumpinfo;
1876 const char * lump_name = lump_p[lumpn].name;
1877
1878 ml2 = ml;
1879 if( ml == 0)
1880 { // search
1881 ml = ML_THINGS;
1882 ml2 = ML_BEHAVIOR;
1883 }
1884
1885 for( ; ml<=ml2; ml++)
1886 {
1887 if( strncmp( lump_name, levellumps[ml], 8) == 0 )
1888 return ml;
1889 }
1890 fail:
1891 return -1;
1892 }
1893
1894
1895 //
1896 // Setup sky texture to use for the level, actually moved the code
1897 // from G_DoLoadLevel() which had nothing to do there.
1898 //
1899 // - in future, each level may use a different sky.
1900 //
1901 // The sky texture to be used instead of the F_SKY1 dummy.
P_Setup_LevelSky(void)1902 void P_Setup_LevelSky (void)
1903 {
1904 char * sn = "SKY1";
1905 char skytexname[12];
1906
1907 // DOOM determines the sky texture to be used
1908 // depending on the current episode, and the game version.
1909
1910 if(*info_skyname)
1911 sn = info_skyname;
1912 else
1913 if (gamemode == doom2_commercial) // includes doom2, plut, tnt
1914 // || (gamemode == pack_tnt) he ! is not a mode is a episode !
1915 // || ( gamemode == pack_plut )
1916 {
1917 if (gamemap < 12)
1918 sn = "SKY1";
1919 else
1920 if (gamemap < 21)
1921 sn = "SKY2";
1922 else
1923 sn = "SKY3";
1924 }
1925 else
1926 if ( (gamemode==ultdoom_retail) ||
1927 (gamemode==doom_registered) )
1928 {
1929 if (gameepisode<1 || gameepisode>4) // useful??
1930 gameepisode = 1;
1931
1932 sprintf (skytexname,"SKY%d",gameepisode);
1933 sn = & skytexname[0];
1934 }
1935 else // who knows?
1936 if (gamemode==heretic)
1937 {
1938 static char *skyLumpNames[5] = {
1939 "SKY1", "SKY2", "SKY3", "SKY1", "SKY3" };
1940
1941 if(gameepisode > 0 && gameepisode <= 5)
1942 sn = skyLumpNames[gameepisode-1];
1943 }
1944
1945 sky_texture = R_TextureNumForName ( sn );
1946 // scale up the old skies, if needed
1947 R_Setup_SkyDraw ();
1948 }
1949
1950
1951 //
1952 // P_SetupLevel
1953 //
1954 // Load the level from an existing lump or from a external wad !
1955 // Purge all previous PU_LEVEL memory.
1956 lumpnum_t level_lumpnum = 0; // for info and comparative savegame
1957 char* level_mapname = NULL; // to savegame and info
1958
1959 // to_episode : change to episode num
1960 // to_map : change to map number
1961 // to_skill : change to skill
1962 // map_wadname : map command, load wad file
P_SetupLevel(int to_episode,int to_map,skill_e to_skill,char * map_wadname)1963 boolean P_SetupLevel (int to_episode,
1964 int to_map,
1965 skill_e to_skill,
1966 char* map_wadname) // for wad files
1967 {
1968 const char *errstr;
1969 char *sl_mapname = NULL;
1970 int i;
1971
1972 GenPrintf( (verbose? (EMSG_ver|EMSG_now) : (EMSG_console|EMSG_now)),
1973 "Setup Level\n" );
1974
1975 //Initialize Boom sector node list.
1976 P_Init_Secnode();
1977
1978 // Clear existing level variables and reclaim memory.
1979 totalkills = totalitems = totalsecret = wminfo.maxfrags = 0;
1980 wminfo.partime = 180;
1981 for (i=0 ; i<MAXPLAYERS ; i++)
1982 {
1983 players[i].killcount = players[i].secretcount
1984 = players[i].itemcount = 0;
1985 players[i].mo = NULL; // will be freed with PU_LEVEL
1986 #ifdef CLIENTPREDICTION2
1987 players[i].spirit = NULL;
1988 #endif
1989 }
1990
1991 // Initial height of PointOfView
1992 // will be set by player think.
1993 players[consoleplayer].viewz = 1;
1994
1995 P_Release_PicAnims();
1996
1997 // [WDJ] 7/2010 Free allocated memory in sectors before PU_LEVEL purge
1998 for (i=0 ; i<numsectors ; i++)
1999 {
2000 sector_t * sp = §ors[i];
2001 if( sp )
2002 {
2003 if( sp->attached ) // from realloc in P_AddFakeFloor
2004 {
2005 free( sp->attached );
2006 sp->attached = NULL;
2007 }
2008 }
2009 }
2010
2011 I_Sleep( 100 ); // give menu sound a chance to finish
2012 // Make sure all sounds are stopped before Z_FreeTags.
2013 // This will kill the last menu pistol sound too.
2014 S_Stop_LevelSound();
2015
2016 #if 0 // UNUSED
2017 if (debugfile)
2018 {
2019 Z_FreeTags (PU_LEVEL, 255); // all purge tags
2020 Z_FileDumpHeap (debugfile);
2021 }
2022 #endif
2023
2024 Z_FreeTags (PU_LEVEL, PU_PURGELEVEL-1);
2025
2026 // [WDJ] all temp lumps are unlocked, to be freed unless they are accessed first
2027 Z_ChangeTags_To (PU_LUMP, PU_CACHE);
2028 Z_ChangeTags_To (PU_IN_USE, PU_CACHE); // for any missed otherwise
2029
2030 #ifdef WALLSPLATS
2031 // clear the splats from previous level
2032 R_Clear_LevelSplats ();
2033 #endif
2034 P_Clear_Extra_Mapthing(); // remove FS mapthings
2035
2036 script_camera_on = false;
2037 HU_Clear_Tips();
2038
2039 if (camera.chase)
2040 camera.mo = NULL;
2041
2042 // UNUSED W_Profile ();
2043
2044 P_Init_Thinkers ();
2045
2046 // Loading new level map.
2047
2048 #ifdef WADFILE_RELOAD
2049 // if working with a devlopment map, reload it
2050 W_Reload ();
2051 #endif
2052
2053 // Load the map from existing game resource or external wad file.
2054 if (map_wadname && map_wadname[0] )
2055 {
2056 // External wad file load.
2057 level_id_t level_id;
2058
2059 if (!P_AddWadFile (map_wadname, &level_id) ||
2060 level_id.mapname==NULL) // no maps were found
2061 {
2062 // go back to title screen if no map is loaded
2063 errstr = "No Maps";
2064 goto load_reject;
2065 }
2066
2067 // From the added wad, returned by P_AddWadFile().
2068 to_episode = gameepisode = level_id.episode;
2069 to_map = gamemap = level_id.map;
2070 sl_mapname = level_id.mapname; // mapname from P_AddWadFile
2071 }
2072 else
2073 {
2074 // Existing game map
2075 sl_mapname = G_BuildMapName(to_episode,to_map);
2076 }
2077
2078 // Determine this level map name for savegame and info next level.
2079 if(level_mapname) Z_Free(level_mapname);
2080 level_mapname = Z_Strdup(sl_mapname, PU_STATIC, 0); // MAP01 or E1M1, etc.
2081 level_lumpnum = W_GetNumForName(sl_mapname);
2082
2083 leveltime = 0;
2084
2085 // textures are needed first
2086 // R_Load_Textures ();
2087 // R_Flush_Texture_Cache();
2088
2089 R_Clear_FW_effect(); // clear and init of fog store
2090 R_Clear_Colormaps(); // colormap ZMalloc cleared by Z_FreeTags(PU_LEVEL, PU_PURGELEVEL-1)
2091
2092 #ifdef FRAGGLESCRIPT
2093 // load level lump info(level name etc)
2094 // Dependent upon level_mapname, level_lumpnum.
2095 P_Load_LevelInfo();
2096 #endif
2097
2098 //SoM: We've loaded the music lump, start the music.
2099 S_Start_LevelSound();
2100
2101 //faB: now part of level loading since in future each level may have
2102 // its own anim texture sequences, switches etc.
2103 P_Init_SwitchList ();
2104 P_Init_PicAnims ();
2105 P_Init_Lava ();
2106 P_Setup_LevelSky ();
2107
2108 // SoM: WOO HOO!
2109 // SoM: DOH!
2110 //R_Init_Portals ();
2111
2112 // [WDJ] Check on Hexen-format maps, idea from PrBoom.
2113 if( P_CheckLumpName( level_lumpnum+ML_BEHAVIOR, ML_BEHAVIOR ) == ML_BEHAVIOR )
2114 {
2115 errstr = "Hexen format not supported";
2116 goto load_reject;
2117 }
2118
2119 // note: most of this ordering is important
2120 P_LoadBlockMap (level_lumpnum+ML_BLOCKMAP);
2121 P_LoadVertexes (level_lumpnum+ML_VERTEXES);
2122 P_LoadSectors (level_lumpnum+ML_SECTORS);
2123 P_LoadSideDefs (level_lumpnum+ML_SIDEDEFS);
2124
2125 P_LoadLineDefs (level_lumpnum+ML_LINEDEFS);
2126 P_LoadSideDefs2(level_lumpnum+ML_SIDEDEFS);
2127 P_LoadLineDefs2();
2128 P_LoadSubsectors (level_lumpnum+ML_SSECTORS);
2129 P_LoadNodes (level_lumpnum+ML_NODES);
2130 P_LoadSegs (level_lumpnum+ML_SEGS);
2131 rejectmatrix = W_CacheLumpNum (level_lumpnum+ML_REJECT,PU_LEVEL);
2132 P_GroupLines ();
2133
2134 #ifdef HWRENDER
2135 if( rendermode != render_soft )
2136 {
2137 HWR_SetupLevel();
2138 }
2139 #endif
2140
2141 bodyqueslot = 0;
2142
2143 numdmstarts = 0;
2144 // added 25-4-98 : reset the players starts
2145 //SoM: Set pointers to NULL
2146 for(i=0;i<MAXPLAYERS;i++)
2147 playerstarts[i] = NULL;
2148
2149 P_Init_AmbientSound ();
2150 P_Init_Monsters ();
2151 P_OpenWeapons ();
2152 P_LoadThings (level_lumpnum+ML_THINGS);
2153 P_CloseWeapons ();
2154
2155 // set up world state
2156 P_SpawnSpecials ();
2157 P_Init_BrainTarget();
2158
2159 //BP: spawnplayers after all structures are inititialized
2160 for (i=0 ; i<MAXPLAYERS ; i++)
2161 {
2162 if (playeringame[i])
2163 {
2164 if( deathmatch )
2165 {
2166 G_DoReborn(i);
2167 }
2168 else if( EV_legacy >= 128 )
2169 {
2170 G_CoopSpawnPlayer(i);
2171 }
2172 }
2173 #ifdef DOGS
2174 else if( extra_dog_count < cv_mbf_dogs.EV )
2175 {
2176 G_SpawnExtraDog( playerstarts[i] );
2177 }
2178 #endif
2179 }
2180
2181 // clear special respawning que
2182 iquehead = iquetail = 0;
2183
2184 // build subsector connect matrix
2185 // UNUSED P_ConnectSubsectors ();
2186
2187 #ifdef CDMUS
2188 //Fab:19-07-98:start cd music for this level (note: can be remapped)
2189 if (gamemode==doom2_commercial)
2190 I_PlayCD (to_map, true); // Doom2, 32 maps
2191 else
2192 I_PlayCD ((to_episode-1)*9+ to_map, true); // Doom1, 9maps per episode
2193 #endif
2194
2195 // preload graphics
2196 #ifdef HWRENDER
2197 if( rendermode != render_soft )
2198 {
2199 HWR_Preload_Graphics();
2200 }
2201 #endif
2202
2203 if (precache)
2204 R_PrecacheLevel ();
2205
2206
2207 #ifdef FRAGGLESCRIPT
2208 T_Init_FSArrayList(); // Setup FS array list
2209 T_PreprocessScripts(); // preprocess FraggleScript scripts
2210 #endif
2211
2212 script_camera_on = false;
2213
2214 B_Init_Nodes(); //added by AC for acbot
2215
2216 //debug_Printf("P_SetupLevel: %d vertexs %d segs %d subsector\n",numvertexes,numsegs,numsubsectors);
2217 return true;
2218
2219 load_reject:
2220 // If want error messages to be seen, need a delay, or else the screen will be redrawn.
2221 GenPrintf( EMSG_hud|EMSG_now, "%s: %s\n", errstr, level_mapname );
2222 I_Sleep(4000);
2223 I_SoftError("%s: %s\n", errstr, level_mapname);
2224 return false;
2225 }
2226
2227
2228 static void P_process_wadfile( int wadfilenum, /*OUT*/ level_id_t * firstmap_out );
2229
2230 // Add a wadfile to the active wad files,
2231 // replace sounds, musics, patches, textures, sprites and maps
2232 //
2233 // wadfilename : filename of wad to be loaded
2234 // firstmap_out : /*OUT*/ info about the first level map
2235 // Called by Command_Addfile, CL_Load_ServerFiles.
P_AddWadFile(char * wadfilename,level_id_t * firstmap_out)2236 boolean P_AddWadFile (char* wadfilename, /*OUT*/ level_id_t * firstmap_out )
2237 {
2238 int wadfilenum;
2239
2240 if( firstmap_out )
2241 firstmap_out->mapname = NULL;
2242
2243 wadfilenum = W_Load_WadFile( wadfilename );
2244 if( wadfilenum == -1 )
2245 {
2246 GenPrintf(EMSG_warn, "could not load wad file %s\n", wadfilename);
2247 return false;
2248 }
2249
2250 #ifdef ZIPWAD
2251 wadfile_t * wadfile = wadfiles[wadfilenum];
2252 if( wadfile->classify == FC_zip )
2253 {
2254 // A zip file
2255 int num = wadfile->archive_num_wadfile;
2256 while( num-- )
2257 {
2258 // all wadfile in archive follow it in sequence
2259 wadfilenum ++;
2260 P_process_wadfile( wadfilenum, /*OUT*/ firstmap_out );
2261 }
2262 return true;
2263 }
2264 #endif
2265
2266 P_process_wadfile( wadfilenum, /*OUT*/ firstmap_out );
2267 return true;
2268 }
2269
2270
2271 // wadfilenum : from W_Load_WadFile (eventually need it for making a lumpnum)
2272 // firstmap_out : see P_SetupLevel
2273 static
P_process_wadfile(int wadfilenum,level_id_t * firstmap_out)2274 void P_process_wadfile( int wadfilenum, /*OUT*/ level_id_t * firstmap_out )
2275 {
2276 wadfile_t * wadfile;
2277 lumpinfo_t * lumpinfo;
2278 char* name;
2279 int first_map_replaced, map_num;
2280 int i,j;
2281 int replace_cnt;
2282
2283 //
2284 // search for sound replacements
2285 //
2286 wadfile = wadfiles[wadfilenum];
2287 lumpinfo = wadfile->lumpinfo;
2288 if( lumpinfo == NULL )
2289 return;
2290
2291 replace_cnt = 0;
2292 for (i=0; i<wadfile->numlumps; i++,lumpinfo++)
2293 {
2294 name = lumpinfo->name;
2295 if (name[0]=='D' && name[1]=='S')
2296 {
2297 for (j=1 ; j<NUMSFX ; j++)
2298 {
2299 if ( S_sfx[j].name &&
2300 !S_sfx[j].link &&
2301 !strncasecmp(S_sfx[j].name,name+2,6) )
2302 {
2303 // the sound will be reloaded when needed,
2304 // since sfx->data will be NULL
2305 if (devparm)
2306 GenPrintf(EMSG_dev, "Sound %.8s replaced\n", name);
2307
2308 S_FreeSfx (&S_sfx[j]);
2309
2310 replace_cnt++;
2311 }
2312 }
2313 }
2314 }
2315 if (!devparm && replace_cnt)
2316 GenPrintf(EMSG_dev, "%d sounds replaced\n", replace_cnt);
2317
2318 //
2319 // search for music replacements
2320 //
2321 lumpinfo = wadfile->lumpinfo;
2322 replace_cnt = 0;
2323 for (i=0; i<wadfile->numlumps; i++,lumpinfo++)
2324 {
2325 name = lumpinfo->name;
2326 if (name[0]=='D' && name[1]=='_')
2327 {
2328 if (devparm)
2329 GenPrintf(EMSG_dev, "Music %.8s replaced\n", name);
2330 replace_cnt++;
2331 }
2332 }
2333 if (!devparm && replace_cnt)
2334 GenPrintf(EMSG_dev, "%d musics replaced\n", replace_cnt);
2335
2336 //
2337 // search for sprite replacements
2338 //
2339 R_AddSpriteDefs (sprnames, numwadfiles-1);
2340
2341 // [WDJ] This previously would try to detect texture changes.
2342 // But any change of patch or texture will invalidate the current
2343 // cached textures, so the only safe thing to do is rebuild them all.
2344 // This fixes bad textures on netgames, and after Map command.
2345 R_Flush_Texture_Cache(); // clear all previous
2346 R_Load_Textures(); // reload all textures
2347
2348 //
2349 // look for skins
2350 //
2351 R_AddSkins (wadfilenum); //faB: wadfile index in wadfiles[]
2352
2353 //
2354 // search for maps
2355 //
2356 lumpinfo = wadfile->lumpinfo;
2357 first_map_replaced = INT_MAX; // invalid
2358 for (i=0; i<wadfile->numlumps; i++,lumpinfo++)
2359 {
2360 name = lumpinfo->name;
2361 // map_num format: Episode: 8 bits, map: 8 bits
2362 // which allows test for lowest in one operation.
2363 map_num = 0; // invalid
2364 if (gamemode==doom2_commercial) // Doom2
2365 {
2366 if( name[0]=='M'
2367 && name[1]=='A'
2368 && name[2]=='P' )
2369 {
2370 map_num = (name[3]-'0')*10 + (name[4]-'0');
2371 GenPrintf(EMSG_info, "Map %d\n", map_num);
2372 }
2373 }
2374 else
2375 {
2376 if ( name[0]=='E'
2377 && ((unsigned)name[1]-'0')<='9' // a digit
2378 && name[2]=='M'
2379 && ((unsigned)name[3]-'0')<='9'
2380 && name[4]==0 )
2381 {
2382 map_num = ((name[1]-'0')<<8) + (name[3]-'0');
2383 GenPrintf(EMSG_info, "Episode %d map %d\n", name[1]-'0',
2384 name[3]-'0');
2385 }
2386 }
2387 // The lowest numbered map is the first map. No map 0.
2388 if ( (map_num > 0) && (map_num < first_map_replaced) )
2389 {
2390 first_map_replaced = map_num;
2391 if(firstmap_out) /* OUT */
2392 {
2393 firstmap_out->mapname = name;
2394 firstmap_out->episode = map_num >> 8;
2395 firstmap_out->map = map_num & 0xFF;
2396 }
2397 }
2398 }
2399
2400 if ( first_map_replaced >= 0xFFFF ) // invalid
2401 GenPrintf(EMSG_info, "No maps added\n");
2402
2403 // reload status bar (warning should have valid player !)
2404 if( gamestate == GS_LEVEL )
2405 ST_Start();
2406 }
2407