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 = &sectors[ (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 = &sectors[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;  // &sectors[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 = &sectors[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