~ubuntu-branches/ubuntu/quantal/glbsp/quantal

« back to all changes in this revision

Viewing changes to src/level.c

  • Committer: Bazaar Package Importer
  • Author(s): Darren Salt
  • Date: 2008-01-30 13:33:49 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080130133349-kgojg33vyiu8xbvp
Tags: 2.24-1
* New upstream release.
* Bumped the lib soname and the library package name due to one silly
  little binary incompatibility caused by changes in an exported struct.
  (Safe; nothing else currently in the archive has ever used libglbsp2.)
* Removed my patches since they're all applied upstream.
* Updated the list of documentation files.
* Build-time changes:
  - Switched from dh_movefiles to dh_install.
  - Updated my makefile to cope with upstream changes.
  - Corrected for debian-rules-ignores-make-clean-error.
  - Corrected for substvar-source-version-is-deprecated.
  - Link libglbsp, rather than glbsp, with libm and libz.
* Fixed shlibdeps. (Closes: #460387)
* Bumped standards version to 3.7.3 (no other changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//------------------------------------------------------------------------
 
2
// LEVEL : Level structure read/write functions.
 
3
//------------------------------------------------------------------------
 
4
//
 
5
//  GL-Friendly Node Builder (C) 2000-2007 Andrew Apted
 
6
//
 
7
//  Based on 'BSP 2.3' by Colin Reed, Lee Killough and others.
 
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
//
 
21
//  ZDBSP format support based on code (C) 2002,2003 Randy Heit
 
22
// 
 
23
//------------------------------------------------------------------------
 
24
 
 
25
#include "system.h"
 
26
 
 
27
#include <stdio.h>
 
28
#include <stdlib.h>
 
29
#include <string.h>
 
30
#include <stdarg.h>
 
31
#include <ctype.h>
 
32
#include <math.h>
 
33
#include <limits.h>
 
34
#include <assert.h>
 
35
 
 
36
#include "analyze.h"
 
37
#include "blockmap.h"
 
38
#include "level.h"
 
39
#include "node.h"
 
40
#include "reject.h"
 
41
#include "seg.h"
 
42
#include "structs.h"
 
43
#include "util.h"
 
44
#include "wad.h"
 
45
 
 
46
 
 
47
#define DEBUG_LOAD      0
 
48
#define DEBUG_BSP       0
 
49
 
 
50
#define ALLOC_BLKNUM  1024
 
51
 
 
52
 
 
53
// per-level variables
 
54
 
 
55
boolean_g lev_doing_normal;
 
56
boolean_g lev_doing_hexen;
 
57
 
 
58
static boolean_g lev_force_v3;
 
59
static boolean_g lev_force_v5;
 
60
 
 
61
 
 
62
#define LEVELARRAY(TYPE, BASEVAR, NUMVAR)  \
 
63
    TYPE ** BASEVAR = NULL;  \
 
64
    int NUMVAR = 0;
 
65
 
 
66
 
 
67
LEVELARRAY(vertex_t,  lev_vertices,   num_vertices)
 
68
LEVELARRAY(linedef_t, lev_linedefs,   num_linedefs)
 
69
LEVELARRAY(sidedef_t, lev_sidedefs,   num_sidedefs)
 
70
LEVELARRAY(sector_t,  lev_sectors,    num_sectors)
 
71
LEVELARRAY(thing_t,   lev_things,     num_things)
 
72
 
 
73
static LEVELARRAY(seg_t,     segs,       num_segs)
 
74
static LEVELARRAY(subsec_t,  subsecs,    num_subsecs)
 
75
static LEVELARRAY(node_t,    nodes,      num_nodes)
 
76
static LEVELARRAY(node_t,    stale_nodes,num_stale_nodes)
 
77
static LEVELARRAY(wall_tip_t,wall_tips,  num_wall_tips)
 
78
 
 
79
 
 
80
int num_normal_vert = 0;
 
81
int num_gl_vert = 0;
 
82
int num_complete_seg = 0;
 
83
 
 
84
 
 
85
/* ----- allocation routines ---------------------------- */
 
86
 
 
87
#define ALLIGATOR(TYPE, BASEVAR, NUMVAR)  \
 
88
{  \
 
89
  if ((NUMVAR % ALLOC_BLKNUM) == 0)  \
 
90
  {  \
 
91
    BASEVAR = UtilRealloc(BASEVAR, (NUMVAR + ALLOC_BLKNUM) *   \
 
92
        sizeof(TYPE *));  \
 
93
  }  \
 
94
  BASEVAR[NUMVAR] = (TYPE *) UtilCalloc(sizeof(TYPE));  \
 
95
  NUMVAR += 1;  \
 
96
  return BASEVAR[NUMVAR - 1];  \
 
97
}
 
98
 
 
99
 
 
100
vertex_t *NewVertex(void)
 
101
  ALLIGATOR(vertex_t, lev_vertices, num_vertices)
 
102
 
 
103
linedef_t *NewLinedef(void)
 
104
  ALLIGATOR(linedef_t, lev_linedefs, num_linedefs)
 
105
 
 
106
sidedef_t *NewSidedef(void)
 
107
  ALLIGATOR(sidedef_t, lev_sidedefs, num_sidedefs)
 
108
 
 
109
sector_t *NewSector(void)
 
110
  ALLIGATOR(sector_t, lev_sectors, num_sectors)
 
111
 
 
112
thing_t *NewThing(void)
 
113
  ALLIGATOR(thing_t, lev_things, num_things)
 
114
 
 
115
seg_t *NewSeg(void)
 
116
  ALLIGATOR(seg_t, segs, num_segs)
 
117
 
 
118
subsec_t *NewSubsec(void)
 
119
  ALLIGATOR(subsec_t, subsecs, num_subsecs)
 
120
 
 
121
node_t *NewNode(void)
 
122
  ALLIGATOR(node_t, nodes, num_nodes)
 
123
 
 
124
node_t *NewStaleNode(void)
 
125
  ALLIGATOR(node_t, stale_nodes, num_stale_nodes)
 
126
 
 
127
wall_tip_t *NewWallTip(void)
 
128
  ALLIGATOR(wall_tip_t, wall_tips, num_wall_tips)
 
129
 
 
130
 
 
131
/* ----- free routines ---------------------------- */
 
132
 
 
133
#define FREEMASON(TYPE, BASEVAR, NUMVAR)  \
 
134
{  \
 
135
  int i;  \
 
136
  for (i=0; i < NUMVAR; i++)  \
 
137
    UtilFree(BASEVAR[i]);  \
 
138
  if (BASEVAR)  \
 
139
    UtilFree(BASEVAR);  \
 
140
  BASEVAR = NULL; NUMVAR = 0;  \
 
141
}
 
142
 
 
143
 
 
144
void FreeVertices(void)
 
145
  FREEMASON(vertex_t, lev_vertices, num_vertices)
 
146
 
 
147
void FreeLinedefs(void)
 
148
  FREEMASON(linedef_t, lev_linedefs, num_linedefs)
 
149
 
 
150
void FreeSidedefs(void)
 
151
  FREEMASON(sidedef_t, lev_sidedefs, num_sidedefs)
 
152
 
 
153
void FreeSectors(void)
 
154
  FREEMASON(sector_t, lev_sectors, num_sectors)
 
155
 
 
156
void FreeThings(void)
 
157
  FREEMASON(thing_t, lev_things, num_things)
 
158
 
 
159
void FreeSegs(void)
 
160
  FREEMASON(seg_t, segs, num_segs)
 
161
 
 
162
void FreeSubsecs(void)
 
163
  FREEMASON(subsec_t, subsecs, num_subsecs)
 
164
 
 
165
void FreeNodes(void)
 
166
  FREEMASON(node_t, nodes, num_nodes)
 
167
 
 
168
void FreeStaleNodes(void)
 
169
  FREEMASON(node_t, stale_nodes, num_stale_nodes)
 
170
 
 
171
void FreeWallTips(void)
 
172
  FREEMASON(wall_tip_t, wall_tips, num_wall_tips)
 
173
 
 
174
 
 
175
/* ----- lookup routines ------------------------------ */
 
176
 
 
177
#define LOOKERUPPER(BASEVAR, NUMVAR, NAMESTR)  \
 
178
{  \
 
179
  if (index < 0 || index >= NUMVAR)  \
 
180
    FatalError("No such %s number #%d", NAMESTR, index);  \
 
181
    \
 
182
  return BASEVAR[index];  \
 
183
}
 
184
 
 
185
vertex_t *LookupVertex(int index)
 
186
  LOOKERUPPER(lev_vertices, num_vertices, "vertex")
 
187
 
 
188
linedef_t *LookupLinedef(int index)
 
189
  LOOKERUPPER(lev_linedefs, num_linedefs, "linedef")
 
190
  
 
191
sidedef_t *LookupSidedef(int index)
 
192
  LOOKERUPPER(lev_sidedefs, num_sidedefs, "sidedef")
 
193
  
 
194
sector_t *LookupSector(int index)
 
195
  LOOKERUPPER(lev_sectors, num_sectors, "sector")
 
196
  
 
197
thing_t *LookupThing(int index)
 
198
  LOOKERUPPER(lev_things, num_things, "thing")
 
199
  
 
200
seg_t *LookupSeg(int index)
 
201
  LOOKERUPPER(segs, num_segs, "seg")
 
202
  
 
203
subsec_t *LookupSubsec(int index)
 
204
  LOOKERUPPER(subsecs, num_subsecs, "subsector")
 
205
  
 
206
node_t *LookupNode(int index)
 
207
  LOOKERUPPER(nodes, num_nodes, "node")
 
208
 
 
209
node_t *LookupStaleNode(int index)
 
210
  LOOKERUPPER(stale_nodes, num_stale_nodes, "stale_node")
 
211
 
 
212
 
 
213
/* ----- reading routines ------------------------------ */
 
214
 
 
215
 
 
216
//
 
217
// CheckForNormalNodes
 
218
//
 
219
int CheckForNormalNodes(void)
 
220
{
 
221
  lump_t *lump;
 
222
  
 
223
  /* Note: an empty NODES lump can be valid */
 
224
  if (FindLevelLump("NODES") == NULL)
 
225
    return FALSE;
 
226
 
 
227
  lump = FindLevelLump("SEGS");
 
228
  
 
229
  if (! lump || lump->length == 0 || CheckLevelLumpZero(lump))
 
230
    return FALSE;
 
231
 
 
232
  lump = FindLevelLump("SSECTORS");
 
233
  
 
234
  if (! lump || lump->length == 0 || CheckLevelLumpZero(lump))
 
235
    return FALSE;
 
236
 
 
237
  return TRUE;
 
238
}
 
239
 
 
240
//
 
241
// GetVertices
 
242
//
 
243
void GetVertices(void)
 
244
{
 
245
  int i, count=-1;
 
246
  raw_vertex_t *raw;
 
247
  lump_t *lump = FindLevelLump("VERTEXES");
 
248
 
 
249
  if (lump)
 
250
    count = lump->length / sizeof(raw_vertex_t);
 
251
 
 
252
  DisplayTicker();
 
253
 
 
254
# if DEBUG_LOAD
 
255
  PrintDebug("GetVertices: num = %d\n", count);
 
256
# endif
 
257
 
 
258
  if (!lump || count == 0)
 
259
    FatalError("Couldn't find any Vertices");
 
260
 
 
261
  raw = (raw_vertex_t *) lump->data;
 
262
 
 
263
  for (i=0; i < count; i++, raw++)
 
264
  {
 
265
    vertex_t *vert = NewVertex();
 
266
 
 
267
    vert->x = (float_g) SINT16(raw->x);
 
268
    vert->y = (float_g) SINT16(raw->y);
 
269
 
 
270
    vert->index = i;
 
271
  }
 
272
 
 
273
  num_normal_vert = num_vertices;
 
274
  num_gl_vert = 0;
 
275
  num_complete_seg = 0;
 
276
}
 
277
 
 
278
//
 
279
// GetSectors
 
280
//
 
281
void GetSectors(void)
 
282
{
 
283
  int i, count=-1;
 
284
  raw_sector_t *raw;
 
285
  lump_t *lump = FindLevelLump("SECTORS");
 
286
 
 
287
  if (lump)
 
288
    count = lump->length / sizeof(raw_sector_t);
 
289
 
 
290
  if (!lump || count == 0)
 
291
    FatalError("Couldn't find any Sectors");
 
292
 
 
293
  DisplayTicker();
 
294
 
 
295
# if DEBUG_LOAD
 
296
  PrintDebug("GetSectors: num = %d\n", count);
 
297
# endif
 
298
 
 
299
  raw = (raw_sector_t *) lump->data;
 
300
 
 
301
  for (i=0; i < count; i++, raw++)
 
302
  {
 
303
    sector_t *sector = NewSector();
 
304
 
 
305
    sector->floor_h = SINT16(raw->floor_h);
 
306
    sector->ceil_h  = SINT16(raw->ceil_h);
 
307
 
 
308
    memcpy(sector->floor_tex, raw->floor_tex, sizeof(sector->floor_tex));
 
309
    memcpy(sector->ceil_tex,  raw->ceil_tex,  sizeof(sector->ceil_tex));
 
310
 
 
311
    sector->light = UINT16(raw->light);
 
312
    sector->special = UINT16(raw->special);
 
313
    sector->tag = SINT16(raw->tag);
 
314
 
 
315
    sector->coalesce = (sector->tag >= 900 && sector->tag < 1000) ?
 
316
        TRUE : FALSE;
 
317
 
 
318
    /* sector indices never change */
 
319
    sector->index = i;
 
320
 
 
321
    sector->warned_facing = -1;
 
322
 
 
323
    /* Note: rej_* fields are handled completely in reject.c */
 
324
  }
 
325
}
 
326
 
 
327
//
 
328
// GetThings
 
329
//
 
330
void GetThings(void)
 
331
{
 
332
  int i, count=-1;
 
333
  raw_thing_t *raw;
 
334
  lump_t *lump = FindLevelLump("THINGS");
 
335
 
 
336
  if (lump)
 
337
    count = lump->length / sizeof(raw_thing_t);
 
338
 
 
339
  if (!lump || count == 0)
 
340
  {
 
341
    // Note: no error if no things exist, even though technically a map
 
342
    // will be unplayable without the player starts.
 
343
    PrintWarn("Couldn't find any Things!\n");
 
344
    return;
 
345
  }
 
346
 
 
347
  DisplayTicker();
 
348
 
 
349
# if DEBUG_LOAD
 
350
  PrintDebug("GetThings: num = %d\n", count);
 
351
# endif
 
352
 
 
353
  raw = (raw_thing_t *) lump->data;
 
354
 
 
355
  for (i=0; i < count; i++, raw++)
 
356
  {
 
357
    thing_t *thing = NewThing();
 
358
 
 
359
    thing->x = SINT16(raw->x);
 
360
    thing->y = SINT16(raw->y);
 
361
 
 
362
    thing->type = UINT16(raw->type);
 
363
    thing->options = UINT16(raw->options);
 
364
 
 
365
    thing->index = i;
 
366
  }
 
367
}
 
368
 
 
369
//
 
370
// GetThingsHexen
 
371
//
 
372
void GetThingsHexen(void)
 
373
{
 
374
  int i, count=-1;
 
375
  raw_hexen_thing_t *raw;
 
376
  lump_t *lump = FindLevelLump("THINGS");
 
377
 
 
378
  if (lump)
 
379
    count = lump->length / sizeof(raw_hexen_thing_t);
 
380
 
 
381
  if (!lump || count == 0)
 
382
  {
 
383
    // Note: no error if no things exist, even though technically a map
 
384
    // will be unplayable without the player starts.
 
385
    PrintWarn("Couldn't find any Things!\n");
 
386
    return;
 
387
  }
 
388
 
 
389
  DisplayTicker();
 
390
 
 
391
# if DEBUG_LOAD
 
392
  PrintDebug("GetThingsHexen: num = %d\n", count);
 
393
# endif
 
394
 
 
395
  raw = (raw_hexen_thing_t *) lump->data;
 
396
 
 
397
  for (i=0; i < count; i++, raw++)
 
398
  {
 
399
    thing_t *thing = NewThing();
 
400
 
 
401
    thing->x = SINT16(raw->x);
 
402
    thing->y = SINT16(raw->y);
 
403
 
 
404
    thing->type = UINT16(raw->type);
 
405
    thing->options = UINT16(raw->options);
 
406
 
 
407
    thing->index = i;
 
408
  }
 
409
}
 
410
 
 
411
//
 
412
// GetSidedefs
 
413
//
 
414
void GetSidedefs(void)
 
415
{
 
416
  int i, count=-1;
 
417
  raw_sidedef_t *raw;
 
418
  lump_t *lump = FindLevelLump("SIDEDEFS");
 
419
 
 
420
  if (lump)
 
421
    count = lump->length / sizeof(raw_sidedef_t);
 
422
 
 
423
  if (!lump || count == 0)
 
424
    FatalError("Couldn't find any Sidedefs");
 
425
 
 
426
  DisplayTicker();
 
427
 
 
428
# if DEBUG_LOAD
 
429
  PrintDebug("GetSidedefs: num = %d\n", count);
 
430
# endif
 
431
 
 
432
  raw = (raw_sidedef_t *) lump->data;
 
433
 
 
434
  for (i=0; i < count; i++, raw++)
 
435
  {
 
436
    sidedef_t *side = NewSidedef();
 
437
 
 
438
    side->sector = (SINT16(raw->sector) == -1) ? NULL :
 
439
        LookupSector(UINT16(raw->sector));
 
440
 
 
441
    if (side->sector)
 
442
      side->sector->ref_count++;
 
443
 
 
444
    side->x_offset = SINT16(raw->x_offset);
 
445
    side->y_offset = SINT16(raw->y_offset);
 
446
 
 
447
    memcpy(side->upper_tex, raw->upper_tex, sizeof(side->upper_tex));
 
448
    memcpy(side->lower_tex, raw->lower_tex, sizeof(side->lower_tex));
 
449
    memcpy(side->mid_tex,   raw->mid_tex,   sizeof(side->mid_tex));
 
450
 
 
451
    /* sidedef indices never change */
 
452
    side->index = i;
 
453
  }
 
454
}
 
455
 
 
456
static INLINE_G sidedef_t *SafeLookupSidedef(uint16_g num)
 
457
{
 
458
  if (num == 0xFFFF)
 
459
    return NULL;
 
460
 
 
461
  if ((int)num >= num_sidedefs && (sint16_g)(num) < 0)
 
462
    return NULL;
 
463
 
 
464
  return LookupSidedef(num);
 
465
}
 
466
 
 
467
//
 
468
// GetLinedefs
 
469
//
 
470
void GetLinedefs(void)
 
471
{
 
472
  int i, count=-1;
 
473
  raw_linedef_t *raw;
 
474
  lump_t *lump = FindLevelLump("LINEDEFS");
 
475
 
 
476
  if (lump)
 
477
    count = lump->length / sizeof(raw_linedef_t);
 
478
 
 
479
  if (!lump || count == 0)
 
480
    FatalError("Couldn't find any Linedefs");
 
481
 
 
482
  DisplayTicker();
 
483
 
 
484
# if DEBUG_LOAD
 
485
  PrintDebug("GetLinedefs: num = %d\n", count);
 
486
# endif
 
487
 
 
488
  raw = (raw_linedef_t *) lump->data;
 
489
 
 
490
  for (i=0; i < count; i++, raw++)
 
491
  {
 
492
    linedef_t *line;
 
493
 
 
494
    vertex_t *start = LookupVertex(UINT16(raw->start));
 
495
    vertex_t *end   = LookupVertex(UINT16(raw->end));
 
496
 
 
497
    start->ref_count++;
 
498
    end->ref_count++;
 
499
 
 
500
    line = NewLinedef();
 
501
 
 
502
    line->start = start;
 
503
    line->end   = end;
 
504
 
 
505
    /* check for zero-length line */
 
506
    line->zero_len = (fabs(start->x - end->x) < DIST_EPSILON) && 
 
507
        (fabs(start->y - end->y) < DIST_EPSILON);
 
508
 
 
509
    line->flags = UINT16(raw->flags);
 
510
    line->type = UINT16(raw->type);
 
511
    line->tag  = SINT16(raw->tag);
 
512
 
 
513
    line->two_sided = (line->flags & LINEFLAG_TWO_SIDED) ? TRUE : FALSE;
 
514
    line->is_precious = (line->tag >= 900 && line->tag < 1000) ? 
 
515
        TRUE : FALSE;
 
516
 
 
517
    line->right = SafeLookupSidedef(UINT16(raw->sidedef1));
 
518
    line->left  = SafeLookupSidedef(UINT16(raw->sidedef2));
 
519
 
 
520
    if (line->right)
 
521
    {
 
522
      line->right->ref_count++;
 
523
      line->right->on_special |= (line->type > 0) ? 1 : 0;
 
524
    }
 
525
 
 
526
    if (line->left)
 
527
    {
 
528
      line->left->ref_count++;
 
529
      line->left->on_special |= (line->type > 0) ? 1 : 0;
 
530
    }
 
531
 
 
532
    line->self_ref = (line->left && line->right &&
 
533
        (line->left->sector == line->right->sector));
 
534
 
 
535
    line->index = i;
 
536
  }
 
537
}
 
538
 
 
539
//
 
540
// GetLinedefsHexen
 
541
//
 
542
void GetLinedefsHexen(void)
 
543
{
 
544
  int i, j, count=-1;
 
545
  raw_hexen_linedef_t *raw;
 
546
  lump_t *lump = FindLevelLump("LINEDEFS");
 
547
 
 
548
  if (lump)
 
549
    count = lump->length / sizeof(raw_hexen_linedef_t);
 
550
 
 
551
  if (!lump || count == 0)
 
552
    FatalError("Couldn't find any Linedefs");
 
553
 
 
554
  DisplayTicker();
 
555
 
 
556
# if DEBUG_LOAD
 
557
  PrintDebug("GetLinedefsHexen: num = %d\n", count);
 
558
# endif
 
559
 
 
560
  raw = (raw_hexen_linedef_t *) lump->data;
 
561
 
 
562
  for (i=0; i < count; i++, raw++)
 
563
  {
 
564
    linedef_t *line;
 
565
 
 
566
    vertex_t *start = LookupVertex(UINT16(raw->start));
 
567
    vertex_t *end   = LookupVertex(UINT16(raw->end));
 
568
 
 
569
    start->ref_count++;
 
570
    end->ref_count++;
 
571
 
 
572
    line = NewLinedef();
 
573
 
 
574
    line->start = start;
 
575
    line->end   = end;
 
576
 
 
577
    // check for zero-length line
 
578
    line->zero_len = (fabs(start->x - end->x) < DIST_EPSILON) && 
 
579
        (fabs(start->y - end->y) < DIST_EPSILON);
 
580
 
 
581
    line->flags = UINT16(raw->flags);
 
582
    line->type = UINT8(raw->type);
 
583
    line->tag  = 0;
 
584
 
 
585
    /* read specials */
 
586
    for (j=0; j < 5; j++)
 
587
      line->specials[j] = UINT8(raw->specials[j]);
 
588
 
 
589
    // -JL- Added missing twosided flag handling that caused a broken reject
 
590
    line->two_sided = (line->flags & LINEFLAG_TWO_SIDED) ? TRUE : FALSE;
 
591
 
 
592
    line->right = SafeLookupSidedef(UINT16(raw->sidedef1));
 
593
    line->left  = SafeLookupSidedef(UINT16(raw->sidedef2));
 
594
 
 
595
    // -JL- Added missing sidedef handling that caused all sidedefs to be pruned
 
596
    if (line->right)
 
597
    {
 
598
      line->right->ref_count++;
 
599
      line->right->on_special |= (line->type > 0) ? 1 : 0;
 
600
    }
 
601
 
 
602
    if (line->left)
 
603
    {
 
604
      line->left->ref_count++;
 
605
      line->left->on_special |= (line->type > 0) ? 1 : 0;
 
606
    }
 
607
 
 
608
    line->self_ref = (line->left && line->right &&
 
609
        (line->left->sector == line->right->sector));
 
610
 
 
611
    line->index = i;
 
612
  }
 
613
}
 
614
 
 
615
//
 
616
// GetStaleNodes
 
617
//
 
618
void GetStaleNodes(void)
 
619
{
 
620
  int i, count=-1;
 
621
  raw_node_t *raw;
 
622
  lump_t *lump = FindLevelLump("NODES");
 
623
 
 
624
  if (lump)
 
625
    count = lump->length / sizeof(raw_node_t);
 
626
 
 
627
  if (!lump || count < 5)
 
628
    return;
 
629
 
 
630
  DisplayTicker();
 
631
 
 
632
# if DEBUG_LOAD
 
633
  PrintDebug("GetStaleNodes: num = %d\n", count);
 
634
# endif
 
635
 
 
636
  raw = (raw_node_t *) lump->data;
 
637
 
 
638
  /* must allocate all the nodes beforehand, since they contain
 
639
   * internal references to each other.
 
640
   */
 
641
  for (i=0; i < count; i++)
 
642
  {
 
643
    NewStaleNode();
 
644
  }
 
645
 
 
646
  for (i=0; i < count; i++, raw++)
 
647
  {
 
648
    node_t *nd = LookupStaleNode(i);
 
649
 
 
650
    nd->x  = SINT16(raw->x);
 
651
    nd->y  = SINT16(raw->y);
 
652
    nd->dx = SINT16(raw->dx);
 
653
    nd->dy = SINT16(raw->dy);
 
654
 
 
655
    nd->index = i;
 
656
    
 
657
    /* Note: we ignore the subsector references */
 
658
     
 
659
    if ((UINT16(raw->right) & 0x8000U) == 0)
 
660
    {
 
661
      nd->r.node = LookupStaleNode(UINT16(raw->right));
 
662
    }
 
663
 
 
664
    if ((UINT16(raw->left) & 0x8000U) == 0)
 
665
    {
 
666
      nd->l.node = LookupStaleNode(UINT16(raw->left));
 
667
    }
 
668
 
 
669
    /* we also ignore the bounding boxes -- not needed */
 
670
  }
 
671
}
 
672
 
 
673
 
 
674
static INLINE_G int TransformSegDist(const seg_t *seg)
 
675
{
 
676
  float_g sx = seg->side ? seg->linedef->end->x : seg->linedef->start->x;
 
677
  float_g sy = seg->side ? seg->linedef->end->y : seg->linedef->start->y;
 
678
 
 
679
  return (int) ceil(UtilComputeDist(seg->start->x - sx, seg->start->y - sy));
 
680
}
 
681
 
 
682
static INLINE_G int TransformAngle(angle_g angle)
 
683
{
 
684
  int result;
 
685
  
 
686
  result = (int)(angle * 65536.0 / 360.0);
 
687
  
 
688
  if (result < 0)
 
689
    result += 65536;
 
690
 
 
691
  return (result & 0xFFFF);
 
692
}
 
693
 
 
694
static int SegCompare(const void *p1, const void *p2)
 
695
{
 
696
  const seg_t *A = ((const seg_t **) p1)[0];
 
697
  const seg_t *B = ((const seg_t **) p2)[0];
 
698
 
 
699
  if (A->index < 0)
 
700
    InternalError("Seg %p never reached a subsector !", A);
 
701
 
 
702
  if (B->index < 0)
 
703
    InternalError("Seg %p never reached a subsector !", B);
 
704
 
 
705
  return (A->index - B->index);
 
706
}
 
707
 
 
708
 
 
709
/* ----- writing routines ------------------------------ */
 
710
 
 
711
static const uint8_g *lev_v2_magic = (uint8_g *) "gNd2";
 
712
static const uint8_g *lev_v3_magic = (uint8_g *) "gNd3";
 
713
static const uint8_g *lev_v5_magic = (uint8_g *) "gNd5";
 
714
 
 
715
void PutVertices(char *name, int do_gl)
 
716
{
 
717
  int count, i;
 
718
  lump_t *lump;
 
719
 
 
720
  DisplayTicker();
 
721
 
 
722
  if (do_gl)
 
723
    lump = CreateGLLump(name);
 
724
  else
 
725
    lump = CreateLevelLump(name);
 
726
 
 
727
  for (i=0, count=0; i < num_vertices; i++)
 
728
  {
 
729
    raw_vertex_t raw;
 
730
    vertex_t *vert = lev_vertices[i];
 
731
 
 
732
    if ((do_gl ? 1 : 0) != ((vert->index & IS_GL_VERTEX) ? 1 : 0))
 
733
    {
 
734
      continue;
 
735
    }
 
736
 
 
737
    raw.x = SINT16(I_ROUND(vert->x));
 
738
    raw.y = SINT16(I_ROUND(vert->y));
 
739
 
 
740
    AppendLevelLump(lump, &raw, sizeof(raw));
 
741
 
 
742
    count++;
 
743
  }
 
744
 
 
745
  if (count != (do_gl ? num_gl_vert : num_normal_vert))
 
746
    InternalError("PutVertices miscounted (%d != %d)", count,
 
747
      do_gl ? num_gl_vert : num_normal_vert);
 
748
 
 
749
  if (lev_doing_normal && ! do_gl && count > 65534)
 
750
    MarkHardFailure(LIMIT_VERTEXES);
 
751
  else if (count > 32767)
 
752
    MarkSoftFailure(do_gl ? LIMIT_GL_VERT : LIMIT_VERTEXES);
 
753
}
 
754
 
 
755
void PutV2Vertices(int do_v5)
 
756
{
 
757
  int count, i;
 
758
  lump_t *lump;
 
759
 
 
760
  DisplayTicker();
 
761
 
 
762
  lump = CreateGLLump("GL_VERT");
 
763
 
 
764
  if (do_v5)
 
765
      AppendLevelLump(lump, lev_v5_magic, 4);
 
766
  else
 
767
      AppendLevelLump(lump, lev_v2_magic, 4);
 
768
 
 
769
  for (i=0, count=0; i < num_vertices; i++)
 
770
  {
 
771
    raw_v2_vertex_t raw;
 
772
    vertex_t *vert = lev_vertices[i];
 
773
 
 
774
    if (! (vert->index & IS_GL_VERTEX))
 
775
      continue;
 
776
 
 
777
    raw.x = SINT32((int)(vert->x * 65536.0));
 
778
    raw.y = SINT32((int)(vert->y * 65536.0));
 
779
 
 
780
    AppendLevelLump(lump, &raw, sizeof(raw));
 
781
 
 
782
    count++;
 
783
  }
 
784
 
 
785
  if (count != num_gl_vert)
 
786
    InternalError("PutV2Vertices miscounted (%d != %d)", count,
 
787
      num_gl_vert);
 
788
 
 
789
  if (count > 32767)
 
790
    MarkSoftFailure(LIMIT_GL_VERT);
 
791
}
 
792
 
 
793
void PutSectors(void)
 
794
{
 
795
  int i;
 
796
  lump_t *lump = CreateLevelLump("SECTORS");
 
797
 
 
798
  DisplayTicker();
 
799
 
 
800
  for (i=0; i < num_sectors; i++)
 
801
  {
 
802
    raw_sector_t raw;
 
803
    sector_t *sector = lev_sectors[i];
 
804
 
 
805
    raw.floor_h = SINT16(sector->floor_h);
 
806
    raw.ceil_h  = SINT16(sector->ceil_h);
 
807
 
 
808
    memcpy(raw.floor_tex, sector->floor_tex, sizeof(raw.floor_tex));
 
809
    memcpy(raw.ceil_tex,  sector->ceil_tex,  sizeof(raw.ceil_tex));
 
810
 
 
811
    raw.light = UINT16(sector->light);
 
812
    raw.special = UINT16(sector->special);
 
813
    raw.tag   = SINT16(sector->tag);
 
814
 
 
815
    AppendLevelLump(lump, &raw, sizeof(raw));
 
816
  }
 
817
 
 
818
  if (num_sectors > 65534)
 
819
    MarkHardFailure(LIMIT_SECTORS);
 
820
  else if (num_sectors > 32767)
 
821
    MarkSoftFailure(LIMIT_SECTORS);
 
822
}
 
823
 
 
824
void PutSidedefs(void)
 
825
{
 
826
  int i;
 
827
  lump_t *lump = CreateLevelLump("SIDEDEFS");
 
828
 
 
829
  DisplayTicker();
 
830
 
 
831
  for (i=0; i < num_sidedefs; i++)
 
832
  {
 
833
    raw_sidedef_t raw;
 
834
    sidedef_t *side = lev_sidedefs[i];
 
835
 
 
836
    raw.sector = (side->sector == NULL) ? SINT16(-1) :
 
837
        UINT16(side->sector->index);
 
838
 
 
839
    raw.x_offset = SINT16(side->x_offset);
 
840
    raw.y_offset = SINT16(side->y_offset);
 
841
 
 
842
    memcpy(raw.upper_tex, side->upper_tex, sizeof(raw.upper_tex));
 
843
    memcpy(raw.lower_tex, side->lower_tex, sizeof(raw.lower_tex));
 
844
    memcpy(raw.mid_tex,   side->mid_tex,   sizeof(raw.mid_tex));
 
845
 
 
846
    AppendLevelLump(lump, &raw, sizeof(raw));
 
847
  }
 
848
 
 
849
  if (num_sidedefs > 65534)
 
850
    MarkHardFailure(LIMIT_SIDEDEFS);
 
851
  else if (num_sidedefs > 32767)
 
852
    MarkSoftFailure(LIMIT_SIDEDEFS);
 
853
}
 
854
 
 
855
void PutLinedefs(void)
 
856
{
 
857
  int i;
 
858
  lump_t *lump = CreateLevelLump("LINEDEFS");
 
859
 
 
860
  DisplayTicker();
 
861
 
 
862
  for (i=0; i < num_linedefs; i++)
 
863
  {
 
864
    raw_linedef_t raw;
 
865
    linedef_t *line = lev_linedefs[i];
 
866
 
 
867
    raw.start = UINT16(line->start->index);
 
868
    raw.end   = UINT16(line->end->index);
 
869
 
 
870
    raw.flags = UINT16(line->flags);
 
871
    raw.type  = UINT16(line->type);
 
872
    raw.tag   = SINT16(line->tag);
 
873
 
 
874
    raw.sidedef1 = line->right ? UINT16(line->right->index) : 0xFFFF;
 
875
    raw.sidedef2 = line->left  ? UINT16(line->left->index)  : 0xFFFF;
 
876
 
 
877
    AppendLevelLump(lump, &raw, sizeof(raw));
 
878
  }
 
879
 
 
880
  if (num_linedefs > 65534)
 
881
    MarkHardFailure(LIMIT_LINEDEFS);
 
882
  else if (num_linedefs > 32767)
 
883
    MarkSoftFailure(LIMIT_LINEDEFS);
 
884
}
 
885
 
 
886
void PutLinedefsHexen(void)
 
887
{
 
888
  int i, j;
 
889
  lump_t *lump = CreateLevelLump("LINEDEFS");
 
890
 
 
891
  DisplayTicker();
 
892
 
 
893
  for (i=0; i < num_linedefs; i++)
 
894
  {
 
895
    raw_hexen_linedef_t raw;
 
896
    linedef_t *line = lev_linedefs[i];
 
897
 
 
898
    raw.start = UINT16(line->start->index);
 
899
    raw.end   = UINT16(line->end->index);
 
900
 
 
901
    raw.flags = UINT16(line->flags);
 
902
    raw.type  = UINT8(line->type);
 
903
 
 
904
    // write specials
 
905
    for (j=0; j < 5; j++)
 
906
      raw.specials[j] = UINT8(line->specials[j]);
 
907
 
 
908
    raw.sidedef1 = line->right ? UINT16(line->right->index) : 0xFFFF;
 
909
    raw.sidedef2 = line->left  ? UINT16(line->left->index)  : 0xFFFF;
 
910
 
 
911
    AppendLevelLump(lump, &raw, sizeof(raw));
 
912
  }
 
913
 
 
914
  if (num_linedefs > 65534)
 
915
    MarkHardFailure(LIMIT_LINEDEFS);
 
916
  else if (num_linedefs > 32767)
 
917
    MarkSoftFailure(LIMIT_LINEDEFS);
 
918
}
 
919
 
 
920
static INLINE_G uint16_g VertexIndex16Bit(const vertex_t *v)
 
921
{
 
922
  if (v->index & IS_GL_VERTEX)
 
923
    return (uint16_g) ((v->index & ~IS_GL_VERTEX) | 0x8000U);
 
924
 
 
925
  return (uint16_g) v->index;
 
926
}
 
927
 
 
928
static INLINE_G uint32_g VertexIndex32BitV5(const vertex_t *v)
 
929
{
 
930
  if (v->index & IS_GL_VERTEX)
 
931
    return (uint32_g) ((v->index & ~IS_GL_VERTEX) | 0x80000000U);
 
932
 
 
933
  return (uint32_g) v->index;
 
934
}
 
935
 
 
936
void PutSegs(void)
 
937
{
 
938
  int i, count;
 
939
  lump_t *lump = CreateLevelLump("SEGS");
 
940
 
 
941
  DisplayTicker();
 
942
 
 
943
  // sort segs into ascending index
 
944
  qsort(segs, num_segs, sizeof(seg_t *), SegCompare);
 
945
 
 
946
  for (i=0, count=0; i < num_segs; i++)
 
947
  {
 
948
    raw_seg_t raw;
 
949
    seg_t *seg = segs[i];
 
950
 
 
951
    // ignore minisegs and degenerate segs
 
952
    if (! seg->linedef || seg->degenerate)
 
953
      continue;
 
954
 
 
955
    raw.start   = UINT16(VertexIndex16Bit(seg->start));
 
956
    raw.end     = UINT16(VertexIndex16Bit(seg->end));
 
957
    raw.angle   = UINT16(TransformAngle(seg->p_angle));
 
958
    raw.linedef = UINT16(seg->linedef->index);
 
959
    raw.flip    = UINT16(seg->side);
 
960
    raw.dist    = UINT16(TransformSegDist(seg));
 
961
 
 
962
    AppendLevelLump(lump, &raw, sizeof(raw));
 
963
 
 
964
    count++;
 
965
 
 
966
#   if DEBUG_BSP
 
967
    PrintDebug("PUT SEG: %04X  Vert %04X->%04X  Line %04X %s  "
 
968
        "Angle %04X  (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", seg->index,
 
969
        UINT16(raw.start), UINT16(raw.end), UINT16(raw.linedef), 
 
970
        seg->side ? "L" : "R", UINT16(raw.angle), 
 
971
        seg->start->x, seg->start->y, seg->end->x, seg->end->y);
 
972
#   endif
 
973
  }
 
974
 
 
975
  if (count != num_complete_seg)
 
976
    InternalError("PutSegs miscounted (%d != %d)", count,
 
977
      num_complete_seg);
 
978
 
 
979
  if (count > 65534)
 
980
    MarkHardFailure(LIMIT_SEGS);
 
981
  else if (count > 32767)
 
982
    MarkSoftFailure(LIMIT_SEGS);
 
983
}
 
984
 
 
985
void PutGLSegs(void)
 
986
{
 
987
  int i, count;
 
988
  lump_t *lump = CreateGLLump("GL_SEGS");
 
989
 
 
990
  DisplayTicker();
 
991
 
 
992
  // sort segs into ascending index
 
993
  qsort(segs, num_segs, sizeof(seg_t *), SegCompare);
 
994
 
 
995
  for (i=0, count=0; i < num_segs; i++)
 
996
  {
 
997
    raw_gl_seg_t raw;
 
998
    seg_t *seg = segs[i];
 
999
 
 
1000
    // ignore degenerate segs
 
1001
    if (seg->degenerate)
 
1002
      continue;
 
1003
 
 
1004
    raw.start = UINT16(VertexIndex16Bit(seg->start));
 
1005
    raw.end   = UINT16(VertexIndex16Bit(seg->end));
 
1006
    raw.side  = UINT16(seg->side);
 
1007
 
 
1008
    if (seg->linedef)
 
1009
      raw.linedef = UINT16(seg->linedef->index);
 
1010
    else
 
1011
      raw.linedef = UINT16(0xFFFF);
 
1012
 
 
1013
    if (seg->partner)
 
1014
      raw.partner = UINT16(seg->partner->index);
 
1015
    else
 
1016
      raw.partner = UINT16(0xFFFF);
 
1017
 
 
1018
    AppendLevelLump(lump, &raw, sizeof(raw));
 
1019
 
 
1020
    count++;
 
1021
 
 
1022
#   if DEBUG_BSP
 
1023
    PrintDebug("PUT GL SEG: %04X  Line %04X %s  Partner %04X  "
 
1024
      "(%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", seg->index, UINT16(raw.linedef), 
 
1025
      seg->side ? "L" : "R", UINT16(raw.partner),
 
1026
      seg->start->x, seg->start->y, seg->end->x, seg->end->y);
 
1027
#   endif
 
1028
  }
 
1029
 
 
1030
  if (count != num_complete_seg)
 
1031
    InternalError("PutGLSegs miscounted (%d != %d)", count,
 
1032
      num_complete_seg);
 
1033
 
 
1034
  if (count > 65534)
 
1035
    InternalError("PutGLSegs with %d (> 65534) segs", count);
 
1036
  else if (count > 32767)
 
1037
    MarkSoftFailure(LIMIT_GL_SEGS);
 
1038
}
 
1039
 
 
1040
void PutV3Segs(int do_v5)
 
1041
{
 
1042
  int i, count;
 
1043
  lump_t *lump = CreateGLLump("GL_SEGS");
 
1044
 
 
1045
  if (! do_v5)
 
1046
      AppendLevelLump(lump, lev_v3_magic, 4);
 
1047
 
 
1048
  DisplayTicker();
 
1049
 
 
1050
  // sort segs into ascending index
 
1051
  qsort(segs, num_segs, sizeof(seg_t *), SegCompare);
 
1052
 
 
1053
  for (i=0, count=0; i < num_segs; i++)
 
1054
  {
 
1055
    raw_v3_seg_t raw;
 
1056
    seg_t *seg = segs[i];
 
1057
 
 
1058
    // ignore degenerate segs
 
1059
    if (seg->degenerate)
 
1060
      continue;
 
1061
 
 
1062
    if (do_v5)
 
1063
    {
 
1064
      raw.start = UINT32(VertexIndex32BitV5(seg->start));
 
1065
      raw.end   = UINT32(VertexIndex32BitV5(seg->end));
 
1066
    }
 
1067
    else
 
1068
    {
 
1069
      raw.start = UINT32(seg->start->index);
 
1070
      raw.end   = UINT32(seg->end->index);
 
1071
    }
 
1072
 
 
1073
    raw.side  = UINT16(seg->side);
 
1074
 
 
1075
    if (seg->linedef)
 
1076
      raw.linedef = UINT16(seg->linedef->index);
 
1077
    else
 
1078
      raw.linedef = UINT16(0xFFFF);
 
1079
 
 
1080
    if (seg->partner)
 
1081
      raw.partner = UINT32(seg->partner->index);
 
1082
    else
 
1083
      raw.partner = UINT32(0xFFFFFFFF);
 
1084
 
 
1085
    AppendLevelLump(lump, &raw, sizeof(raw));
 
1086
 
 
1087
    count++;
 
1088
 
 
1089
#   if DEBUG_BSP
 
1090
    PrintDebug("PUT V3 SEG: %06X  Line %04X %s  Partner %06X  "
 
1091
      "(%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", seg->index, UINT16(raw.linedef), 
 
1092
      seg->side ? "L" : "R", UINT32(raw.partner),
 
1093
      seg->start->x, seg->start->y, seg->end->x, seg->end->y);
 
1094
#   endif
 
1095
  }
 
1096
 
 
1097
  if (count != num_complete_seg)
 
1098
    InternalError("PutGLSegs miscounted (%d != %d)", count,
 
1099
      num_complete_seg);
 
1100
}
 
1101
 
 
1102
void PutSubsecs(char *name, int do_gl)
 
1103
{
 
1104
  int i;
 
1105
  lump_t *lump;
 
1106
 
 
1107
  DisplayTicker();
 
1108
 
 
1109
  if (do_gl)
 
1110
    lump = CreateGLLump(name);
 
1111
  else
 
1112
    lump = CreateLevelLump(name);
 
1113
 
 
1114
  for (i=0; i < num_subsecs; i++)
 
1115
  {
 
1116
    raw_subsec_t raw;
 
1117
    subsec_t *sub = subsecs[i];
 
1118
 
 
1119
    raw.first = UINT16(sub->seg_list->index);
 
1120
    raw.num   = UINT16(sub->seg_count);
 
1121
 
 
1122
    AppendLevelLump(lump, &raw, sizeof(raw));
 
1123
 
 
1124
#   if DEBUG_BSP
 
1125
    PrintDebug("PUT SUBSEC %04X  First %04X  Num %04X\n",
 
1126
      sub->index, UINT16(raw.first), UINT16(raw.num));
 
1127
#   endif
 
1128
  }
 
1129
 
 
1130
  if (num_subsecs > 32767)
 
1131
    MarkHardFailure(do_gl ? LIMIT_GL_SSECT : LIMIT_SSECTORS);
 
1132
}
 
1133
 
 
1134
void PutV3Subsecs(int do_v5)
 
1135
{
 
1136
  int i;
 
1137
  lump_t *lump;
 
1138
 
 
1139
  DisplayTicker();
 
1140
 
 
1141
  lump = CreateGLLump("GL_SSECT");
 
1142
 
 
1143
  if (! do_v5)
 
1144
      AppendLevelLump(lump, lev_v3_magic, 4);
 
1145
 
 
1146
  for (i=0; i < num_subsecs; i++)
 
1147
  {
 
1148
    raw_v3_subsec_t raw;
 
1149
    subsec_t *sub = subsecs[i];
 
1150
 
 
1151
    raw.first = UINT32(sub->seg_list->index);
 
1152
    raw.num   = UINT32(sub->seg_count);
 
1153
 
 
1154
    AppendLevelLump(lump, &raw, sizeof(raw));
 
1155
 
 
1156
#   if DEBUG_BSP
 
1157
    PrintDebug("PUT V3 SUBSEC %06X  First %06X  Num %06X\n",
 
1158
      sub->index, UINT32(raw.first), UINT32(raw.num));
 
1159
#   endif
 
1160
  }
 
1161
 
 
1162
  if (!do_v5 && num_subsecs > 32767)
 
1163
    MarkHardFailure(LIMIT_GL_SSECT);
 
1164
}
 
1165
 
 
1166
static int node_cur_index;
 
1167
 
 
1168
static void PutOneNode(node_t *node, lump_t *lump)
 
1169
{
 
1170
  raw_node_t raw;
 
1171
 
 
1172
  if (node->r.node)
 
1173
    PutOneNode(node->r.node, lump);
 
1174
 
 
1175
  if (node->l.node)
 
1176
    PutOneNode(node->l.node, lump);
 
1177
 
 
1178
  node->index = node_cur_index++;
 
1179
 
 
1180
  raw.x  = SINT16(node->x);
 
1181
  raw.y  = SINT16(node->y);
 
1182
  raw.dx = SINT16(node->dx / (node->too_long ? 2 : 1));
 
1183
  raw.dy = SINT16(node->dy / (node->too_long ? 2 : 1));
 
1184
 
 
1185
  raw.b1.minx = SINT16(node->r.bounds.minx);
 
1186
  raw.b1.miny = SINT16(node->r.bounds.miny);
 
1187
  raw.b1.maxx = SINT16(node->r.bounds.maxx);
 
1188
  raw.b1.maxy = SINT16(node->r.bounds.maxy);
 
1189
 
 
1190
  raw.b2.minx = SINT16(node->l.bounds.minx);
 
1191
  raw.b2.miny = SINT16(node->l.bounds.miny);
 
1192
  raw.b2.maxx = SINT16(node->l.bounds.maxx);
 
1193
  raw.b2.maxy = SINT16(node->l.bounds.maxy);
 
1194
 
 
1195
  if (node->r.node)
 
1196
    raw.right = UINT16(node->r.node->index);
 
1197
  else if (node->r.subsec)
 
1198
    raw.right = UINT16(node->r.subsec->index | 0x8000);
 
1199
  else
 
1200
    InternalError("Bad right child in node %d", node->index);
 
1201
 
 
1202
  if (node->l.node)
 
1203
    raw.left = UINT16(node->l.node->index);
 
1204
  else if (node->l.subsec)
 
1205
    raw.left = UINT16(node->l.subsec->index | 0x8000);
 
1206
  else
 
1207
    InternalError("Bad left child in node %d", node->index);
 
1208
 
 
1209
  AppendLevelLump(lump, &raw, sizeof(raw));
 
1210
 
 
1211
# if DEBUG_BSP
 
1212
  PrintDebug("PUT NODE %04X  Left %04X  Right %04X  "
 
1213
    "(%d,%d) -> (%d,%d)\n", node->index, UINT16(raw.left),
 
1214
    UINT16(raw.right), node->x, node->y,
 
1215
    node->x + node->dx, node->y + node->dy);
 
1216
# endif
 
1217
}
 
1218
 
 
1219
static void PutOneV5Node(node_t *node, lump_t *lump)
 
1220
{
 
1221
  raw_v5_node_t raw;
 
1222
 
 
1223
  if (node->r.node)
 
1224
    PutOneV5Node(node->r.node, lump);
 
1225
 
 
1226
  if (node->l.node)
 
1227
    PutOneV5Node(node->l.node, lump);
 
1228
 
 
1229
  node->index = node_cur_index++;
 
1230
 
 
1231
  raw.x  = SINT16(node->x);
 
1232
  raw.y  = SINT16(node->y);
 
1233
  raw.dx = SINT16(node->dx / (node->too_long ? 2 : 1));
 
1234
  raw.dy = SINT16(node->dy / (node->too_long ? 2 : 1));
 
1235
 
 
1236
  raw.b1.minx = SINT16(node->r.bounds.minx);
 
1237
  raw.b1.miny = SINT16(node->r.bounds.miny);
 
1238
  raw.b1.maxx = SINT16(node->r.bounds.maxx);
 
1239
  raw.b1.maxy = SINT16(node->r.bounds.maxy);
 
1240
 
 
1241
  raw.b2.minx = SINT16(node->l.bounds.minx);
 
1242
  raw.b2.miny = SINT16(node->l.bounds.miny);
 
1243
  raw.b2.maxx = SINT16(node->l.bounds.maxx);
 
1244
  raw.b2.maxy = SINT16(node->l.bounds.maxy);
 
1245
 
 
1246
  if (node->r.node)
 
1247
    raw.right = UINT32(node->r.node->index);
 
1248
  else if (node->r.subsec)
 
1249
    raw.right = UINT32(node->r.subsec->index | 0x80000000U);
 
1250
  else
 
1251
    InternalError("Bad right child in V5 node %d", node->index);
 
1252
 
 
1253
  if (node->l.node)
 
1254
    raw.left = UINT32(node->l.node->index);
 
1255
  else if (node->l.subsec)
 
1256
    raw.left = UINT32(node->l.subsec->index | 0x80000000U);
 
1257
  else
 
1258
    InternalError("Bad left child in V5 node %d", node->index);
 
1259
 
 
1260
  AppendLevelLump(lump, &raw, sizeof(raw));
 
1261
 
 
1262
# if DEBUG_BSP
 
1263
  PrintDebug("PUT V5 NODE %08X  Left %08X  Right %08X  "
 
1264
    "(%d,%d) -> (%d,%d)\n", node->index, UINT32(raw.left),
 
1265
    UINT32(raw.right), node->x, node->y,
 
1266
    node->x + node->dx, node->y + node->dy);
 
1267
# endif
 
1268
}
 
1269
 
 
1270
void PutNodes(char *name, int do_gl, int do_v5, node_t *root)
 
1271
{
 
1272
  lump_t *lump;
 
1273
 
 
1274
  DisplayTicker();
 
1275
 
 
1276
  if (do_gl)
 
1277
    lump = CreateGLLump(name);
 
1278
  else
 
1279
    lump = CreateLevelLump(name);
 
1280
 
 
1281
  node_cur_index = 0;
 
1282
 
 
1283
  if (root)
 
1284
  {
 
1285
    if (do_v5)
 
1286
      PutOneV5Node(root, lump);
 
1287
    else
 
1288
      PutOneNode(root, lump);
 
1289
  }
 
1290
 
 
1291
  if (node_cur_index != num_nodes)
 
1292
    InternalError("PutNodes miscounted (%d != %d)",
 
1293
      node_cur_index, num_nodes);
 
1294
 
 
1295
  if (!do_v5 && node_cur_index > 32767)
 
1296
    MarkHardFailure(LIMIT_NODES);
 
1297
}
 
1298
 
 
1299
 
 
1300
/* ----- ZDBSP format writing --------------------------- */
 
1301
 
 
1302
static const uint8_g *lev_ZD_magic = (uint8_g *) "ZNOD";
 
1303
 
 
1304
void PutZVertices(void)
 
1305
{
 
1306
  int count, i;
 
1307
 
 
1308
  uint32_g orgverts = UINT32(num_normal_vert);
 
1309
  uint32_g newverts = UINT32(num_gl_vert);
 
1310
 
 
1311
  ZLibAppendLump(&orgverts, 4);
 
1312
  ZLibAppendLump(&newverts, 4);
 
1313
 
 
1314
  DisplayTicker();
 
1315
 
 
1316
  for (i=0, count=0; i < num_vertices; i++)
 
1317
  {
 
1318
    raw_v2_vertex_t raw;
 
1319
    vertex_t *vert = lev_vertices[i];
 
1320
 
 
1321
    if (! (vert->index & IS_GL_VERTEX))
 
1322
      continue;
 
1323
 
 
1324
    raw.x = SINT32((int)(vert->x * 65536.0));
 
1325
    raw.y = SINT32((int)(vert->y * 65536.0));
 
1326
 
 
1327
    ZLibAppendLump(&raw, sizeof(raw));
 
1328
 
 
1329
    count++;
 
1330
  }
 
1331
 
 
1332
  if (count != num_gl_vert)
 
1333
    InternalError("PutZVertices miscounted (%d != %d)",
 
1334
        count, num_gl_vert);
 
1335
}
 
1336
 
 
1337
void PutZSubsecs(void)
 
1338
{
 
1339
  int i;
 
1340
  int count;
 
1341
  uint32_g raw_num = UINT32(num_subsecs);
 
1342
 
 
1343
  int cur_seg_index = 0;
 
1344
 
 
1345
  ZLibAppendLump(&raw_num, 4);
 
1346
  DisplayTicker();
 
1347
 
 
1348
  for (i=0; i < num_subsecs; i++)
 
1349
  {
 
1350
    subsec_t *sub = subsecs[i];
 
1351
    seg_t *seg;
 
1352
 
 
1353
    raw_num = UINT32(sub->seg_count);
 
1354
 
 
1355
    ZLibAppendLump(&raw_num, 4);
 
1356
 
 
1357
    // sanity check the seg index values
 
1358
    count = 0;
 
1359
    for (seg = sub->seg_list; seg; seg = seg->next, cur_seg_index++)
 
1360
    {
 
1361
      // ignore minisegs and degenerate segs
 
1362
      if (! seg->linedef || seg->degenerate)
 
1363
        continue;
 
1364
 
 
1365
      if (cur_seg_index != seg->index)
 
1366
        InternalError("PutZSubsecs: seg index mismatch in sub %d (%d != %d)\n",
 
1367
            i, cur_seg_index, seg->index);
 
1368
      
 
1369
      count++;
 
1370
    }
 
1371
 
 
1372
    if (count != sub->seg_count)
 
1373
      InternalError("PutZSubsecs: miscounted segs in sub %d (%d != %d)\n",
 
1374
          i, count, sub->seg_count);
 
1375
  }
 
1376
 
 
1377
  if (cur_seg_index != num_complete_seg)
 
1378
    InternalError("PutZSubsecs miscounted segs (%d != %d)",
 
1379
        cur_seg_index, num_complete_seg);
 
1380
}
 
1381
 
 
1382
void PutZSegs(void)
 
1383
{
 
1384
  int i, count;
 
1385
  uint32_g raw_num = UINT32(num_complete_seg);
 
1386
 
 
1387
  ZLibAppendLump(&raw_num, 4);
 
1388
  DisplayTicker();
 
1389
 
 
1390
  for (i=0, count=0; i < num_segs; i++)
 
1391
  {
 
1392
    seg_t *seg = segs[i];
 
1393
 
 
1394
    // ignore minisegs and degenerate segs
 
1395
    if (! seg->linedef || seg->degenerate)
 
1396
      continue;
 
1397
 
 
1398
    if (count != seg->index)
 
1399
      InternalError("PutZSegs: seg index mismatch (%d != %d)\n",
 
1400
          count, seg->index);
 
1401
 
 
1402
    {
 
1403
      uint32_g v1 = UINT32(VertexIndex32BitV5(seg->start));
 
1404
      uint32_g v2 = UINT32(VertexIndex32BitV5(seg->end));
 
1405
 
 
1406
      uint16_g line = UINT16(seg->linedef->index);
 
1407
      uint8_g  side = seg->side;
 
1408
 
 
1409
      ZLibAppendLump(&v1,   4);
 
1410
      ZLibAppendLump(&v2,   4);
 
1411
      ZLibAppendLump(&line, 2);
 
1412
      ZLibAppendLump(&side, 1);
 
1413
    }
 
1414
 
 
1415
    count++;
 
1416
  }
 
1417
 
 
1418
  if (count != num_complete_seg)
 
1419
    InternalError("PutZSegs miscounted (%d != %d)",
 
1420
        count, num_complete_seg);
 
1421
}
 
1422
 
 
1423
static void PutOneZNode(node_t *node)
 
1424
{
 
1425
  raw_v5_node_t raw;
 
1426
 
 
1427
  if (node->r.node)
 
1428
    PutOneZNode(node->r.node);
 
1429
 
 
1430
  if (node->l.node)
 
1431
    PutOneZNode(node->l.node);
 
1432
 
 
1433
  node->index = node_cur_index++;
 
1434
 
 
1435
  raw.x  = SINT16(node->x);
 
1436
  raw.y  = SINT16(node->y);
 
1437
  raw.dx = SINT16(node->dx / (node->too_long ? 2 : 1));
 
1438
  raw.dy = SINT16(node->dy / (node->too_long ? 2 : 1));
 
1439
 
 
1440
  ZLibAppendLump(&raw.x,  2);
 
1441
  ZLibAppendLump(&raw.y,  2);
 
1442
  ZLibAppendLump(&raw.dx, 2);
 
1443
  ZLibAppendLump(&raw.dy, 2);
 
1444
 
 
1445
  raw.b1.minx = SINT16(node->r.bounds.minx);
 
1446
  raw.b1.miny = SINT16(node->r.bounds.miny);
 
1447
  raw.b1.maxx = SINT16(node->r.bounds.maxx);
 
1448
  raw.b1.maxy = SINT16(node->r.bounds.maxy);
 
1449
 
 
1450
  raw.b2.minx = SINT16(node->l.bounds.minx);
 
1451
  raw.b2.miny = SINT16(node->l.bounds.miny);
 
1452
  raw.b2.maxx = SINT16(node->l.bounds.maxx);
 
1453
  raw.b2.maxy = SINT16(node->l.bounds.maxy);
 
1454
 
 
1455
  ZLibAppendLump(&raw.b1, sizeof(raw.b1));
 
1456
  ZLibAppendLump(&raw.b2, sizeof(raw.b2));
 
1457
 
 
1458
  if (node->r.node)
 
1459
    raw.right = UINT32(node->r.node->index);
 
1460
  else if (node->r.subsec)
 
1461
    raw.right = UINT32(node->r.subsec->index | 0x80000000U);
 
1462
  else
 
1463
    InternalError("Bad right child in V5 node %d", node->index);
 
1464
 
 
1465
  if (node->l.node)
 
1466
    raw.left = UINT32(node->l.node->index);
 
1467
  else if (node->l.subsec)
 
1468
    raw.left = UINT32(node->l.subsec->index | 0x80000000U);
 
1469
  else
 
1470
    InternalError("Bad left child in V5 node %d", node->index);
 
1471
 
 
1472
  ZLibAppendLump(&raw.right, 4);
 
1473
  ZLibAppendLump(&raw.left,  4);
 
1474
 
 
1475
# if DEBUG_BSP
 
1476
  PrintDebug("PUT Z NODE %08X  Left %08X  Right %08X  "
 
1477
    "(%d,%d) -> (%d,%d)\n", node->index, UINT32(raw.left),
 
1478
    UINT32(raw.right), node->x, node->y,
 
1479
    node->x + node->dx, node->y + node->dy);
 
1480
# endif
 
1481
}
 
1482
 
 
1483
void PutZNodes(node_t *root)
 
1484
{
 
1485
  uint32_g raw_num = UINT32(num_nodes);
 
1486
 
 
1487
  ZLibAppendLump(&raw_num, 4);
 
1488
  DisplayTicker();
 
1489
 
 
1490
  node_cur_index = 0;
 
1491
 
 
1492
  if (root)
 
1493
    PutOneZNode(root);
 
1494
 
 
1495
  if (node_cur_index != num_nodes)
 
1496
    InternalError("PutZNodes miscounted (%d != %d)",
 
1497
      node_cur_index, num_nodes);
 
1498
}
 
1499
 
 
1500
void SaveZDFormat(node_t *root_node)
 
1501
{
 
1502
  lump_t *lump;
 
1503
 
 
1504
  // leave SEGS and SSECTORS empty
 
1505
  CreateLevelLump("SEGS");
 
1506
  CreateLevelLump("SSECTORS");
 
1507
 
 
1508
  lump = CreateLevelLump("NODES");
 
1509
 
 
1510
  AppendLevelLump(lump, lev_ZD_magic, 4);
 
1511
 
 
1512
  ZLibBeginLump(lump);
 
1513
 
 
1514
  PutZVertices();
 
1515
  PutZSubsecs();
 
1516
  PutZSegs();
 
1517
  PutZNodes(root_node);
 
1518
 
 
1519
  ZLibFinishLump();
 
1520
}
 
1521
 
 
1522
 
 
1523
/* ----- whole-level routines --------------------------- */
 
1524
 
 
1525
//
 
1526
// LoadLevel
 
1527
//
 
1528
void LoadLevel(void)
 
1529
{
 
1530
  char *message;
 
1531
 
 
1532
  const char *level_name = GetLevelName();
 
1533
 
 
1534
  boolean_g normal_exists = CheckForNormalNodes();
 
1535
 
 
1536
  lev_doing_normal = !cur_info->gwa_mode && (cur_info->force_normal || 
 
1537
    (!cur_info->no_normal && !normal_exists));
 
1538
 
 
1539
  // -JL- Identify Hexen mode by presence of BEHAVIOR lump
 
1540
  lev_doing_hexen = (FindLevelLump("BEHAVIOR") != NULL);
 
1541
 
 
1542
  if (lev_doing_normal)
 
1543
    message = UtilFormat("Building normal and GL nodes on %s%s",
 
1544
        level_name, lev_doing_hexen ? " (Hexen)" : "");
 
1545
  else
 
1546
    message = UtilFormat("Building GL nodes on %s%s",
 
1547
        level_name, lev_doing_hexen ? " (Hexen)" : "");
 
1548
 
 
1549
  lev_doing_hexen |= cur_info->force_hexen;
 
1550
 
 
1551
  DisplaySetBarText(1, message);
 
1552
 
 
1553
  PrintVerbose("\n\n");
 
1554
  PrintMsg("%s\n", message);
 
1555
  PrintVerbose("\n");
 
1556
 
 
1557
  UtilFree(message);
 
1558
 
 
1559
  GetVertices();
 
1560
  GetSectors();
 
1561
  GetSidedefs();
 
1562
 
 
1563
  if (lev_doing_hexen)
 
1564
  {
 
1565
    GetLinedefsHexen();
 
1566
    GetThingsHexen();
 
1567
  }
 
1568
  else
 
1569
  {
 
1570
    GetLinedefs();
 
1571
    GetThings();
 
1572
  }
 
1573
 
 
1574
  PrintVerbose("Loaded %d vertices, %d sectors, %d sides, %d lines, %d things\n", 
 
1575
      num_vertices, num_sectors, num_sidedefs, num_linedefs, num_things);
 
1576
 
 
1577
  if (cur_info->fast && !lev_doing_normal &&
 
1578
      normal_exists && num_sectors > 5 && num_linedefs > 100)
 
1579
  {
 
1580
    PrintVerbose("Using original nodes to speed things up\n");
 
1581
    GetStaleNodes();
 
1582
  }
 
1583
 
 
1584
  if (lev_doing_normal)
 
1585
  {
 
1586
    // NOTE: order here is critical
 
1587
 
 
1588
    if (cur_info->pack_sides)
 
1589
      DetectDuplicateSidedefs();
 
1590
 
 
1591
    if (cur_info->merge_vert)
 
1592
      DetectDuplicateVertices();
 
1593
 
 
1594
    if (!cur_info->no_prune)
 
1595
      PruneLinedefs();
 
1596
 
 
1597
    // always prune vertices (ignore -noprune), otherwise all the
 
1598
    // unused vertices from seg splits would keep accumulating.
 
1599
    PruneVertices();
 
1600
 
 
1601
    if (!cur_info->no_prune)
 
1602
      PruneSidedefs();
 
1603
 
 
1604
    if (cur_info->prune_sect)
 
1605
      PruneSectors();
 
1606
  }
 
1607
 
 
1608
  CalculateWallTips();
 
1609
 
 
1610
  if (lev_doing_hexen)
 
1611
  {
 
1612
    // -JL- Find sectors containing polyobjs
 
1613
    DetectPolyobjSectors();
 
1614
  }
 
1615
 
 
1616
  DetectOverlappingLines();
 
1617
 
 
1618
  if (cur_info->window_fx)
 
1619
    DetectWindowEffects();
 
1620
}
 
1621
 
 
1622
//
 
1623
// FreeLevel
 
1624
//
 
1625
void FreeLevel(void)
 
1626
{
 
1627
  FreeVertices();
 
1628
  FreeSidedefs();
 
1629
  FreeLinedefs();
 
1630
  FreeSectors();
 
1631
  FreeThings();
 
1632
  FreeSegs();
 
1633
  FreeSubsecs();
 
1634
  FreeNodes();
 
1635
  FreeStaleNodes();
 
1636
  FreeWallTips();
 
1637
}
 
1638
 
 
1639
//
 
1640
// PutGLOptions
 
1641
//
 
1642
void PutGLOptions(void)
 
1643
{
 
1644
  char option_buf[128];
 
1645
 
 
1646
  sprintf(option_buf, "-v%d -factor %d", cur_info->spec_version, cur_info->factor);
 
1647
 
 
1648
  if (cur_info->fast         ) strcat(option_buf, " -f");
 
1649
  if (cur_info->force_normal ) strcat(option_buf, " -n");
 
1650
  if (cur_info->merge_vert   ) strcat(option_buf, " -m");
 
1651
  if (cur_info->pack_sides   ) strcat(option_buf, " -p");
 
1652
  if (cur_info->prune_sect   ) strcat(option_buf, " -u");
 
1653
  if (cur_info->skip_self_ref) strcat(option_buf, " -s");
 
1654
  if (cur_info->window_fx    ) strcat(option_buf, " -y");
 
1655
 
 
1656
  if (cur_info->no_normal) strcat(option_buf, " -xn");
 
1657
  if (cur_info->no_reject) strcat(option_buf, " -xr");
 
1658
  if (cur_info->no_prune ) strcat(option_buf, " -xu");
 
1659
 
 
1660
  AddGLTextLine("OPTIONS", option_buf);
 
1661
}
 
1662
 
 
1663
//
 
1664
// PutGLChecksum
 
1665
//
 
1666
void PutGLChecksum(void)
 
1667
{
 
1668
  uint32_g crc;
 
1669
  lump_t *lump;
 
1670
  char num_buf[64];
 
1671
 
 
1672
  Adler32_Begin(&crc);
 
1673
 
 
1674
  lump = FindLevelLump("VERTEXES");
 
1675
 
 
1676
  if (lump && lump->length > 0)
 
1677
    Adler32_AddBlock(&crc, lump->data, lump->length);
 
1678
 
 
1679
  lump = FindLevelLump("LINEDEFS");
 
1680
 
 
1681
  if (lump && lump->length > 0)
 
1682
    Adler32_AddBlock(&crc, lump->data, lump->length);
 
1683
 
 
1684
  Adler32_Finish(&crc);
 
1685
 
 
1686
  sprintf(num_buf, "0x%08x", crc);
 
1687
 
 
1688
  AddGLTextLine("CHECKSUM", num_buf);
 
1689
}
 
1690
 
 
1691
//
 
1692
// SaveLevel
 
1693
//
 
1694
void SaveLevel(node_t *root_node)
 
1695
{
 
1696
  lev_force_v3 = (cur_info->spec_version == 3) ? TRUE : FALSE;
 
1697
  lev_force_v5 = (cur_info->spec_version == 5) ? TRUE : FALSE;
 
1698
  
 
1699
  // Note: RoundOffBspTree will convert the GL vertices in segs to
 
1700
  // their normal counterparts (pointer change: use normal_dup).
 
1701
 
 
1702
  if (cur_info->spec_version == 1)
 
1703
    RoundOffBspTree(root_node);
 
1704
 
 
1705
  // GL Nodes
 
1706
  {
 
1707
    if (num_normal_vert > 32767 || num_gl_vert > 32767)
 
1708
    {
 
1709
      if (cur_info->spec_version < 3)
 
1710
      {
 
1711
        lev_force_v5 = TRUE;
 
1712
        MarkV5Switch(LIMIT_VERTEXES | LIMIT_GL_SEGS);
 
1713
      }
 
1714
    }
 
1715
 
 
1716
    if (num_segs > 65534)
 
1717
    {
 
1718
      if (cur_info->spec_version < 3)
 
1719
      {
 
1720
        lev_force_v5 = TRUE;
 
1721
        MarkV5Switch(LIMIT_GL_SSECT | LIMIT_GL_SEGS);
 
1722
      }
 
1723
    }
 
1724
 
 
1725
    if (num_nodes > 32767)
 
1726
    {
 
1727
      if (cur_info->spec_version < 5)
 
1728
      {
 
1729
        lev_force_v5 = TRUE;
 
1730
        MarkV5Switch(LIMIT_GL_NODES);
 
1731
      }
 
1732
    }
 
1733
 
 
1734
    if (cur_info->spec_version == 1)
 
1735
      PutVertices("GL_VERT", TRUE);
 
1736
    else
 
1737
      PutV2Vertices(lev_force_v5);
 
1738
 
 
1739
    if (lev_force_v3 || lev_force_v5)
 
1740
      PutV3Segs(lev_force_v5);
 
1741
    else
 
1742
      PutGLSegs();
 
1743
 
 
1744
    if (lev_force_v3 || lev_force_v5)
 
1745
      PutV3Subsecs(lev_force_v5);
 
1746
    else
 
1747
      PutSubsecs("GL_SSECT", TRUE);
 
1748
 
 
1749
    PutNodes("GL_NODES", TRUE, lev_force_v5, root_node);
 
1750
 
 
1751
    // -JL- Add empty PVS lump
 
1752
    CreateGLLump("GL_PVS");
 
1753
  }
 
1754
 
 
1755
  if (lev_doing_normal)
 
1756
  {
 
1757
    if (cur_info->spec_version != 1)
 
1758
      RoundOffBspTree(root_node);
 
1759
 
 
1760
    NormaliseBspTree(root_node);
 
1761
 
 
1762
    PutVertices("VERTEXES", FALSE);
 
1763
    PutSectors();
 
1764
    PutSidedefs();
 
1765
 
 
1766
    if (lev_doing_hexen)
 
1767
      PutLinedefsHexen();
 
1768
    else
 
1769
      PutLinedefs();
 
1770
 
 
1771
    if (lev_force_v5)
 
1772
    {
 
1773
      // don't report a problem when -v5 was explicitly given
 
1774
      if (cur_info->spec_version < 5)
 
1775
        MarkZDSwitch();
 
1776
 
 
1777
      SaveZDFormat(root_node);
 
1778
    }
 
1779
    else
 
1780
    {
 
1781
      PutSegs();
 
1782
      PutSubsecs("SSECTORS", FALSE);
 
1783
      PutNodes("NODES", FALSE, FALSE, root_node);
 
1784
    }
 
1785
 
 
1786
    // -JL- Don't touch blockmap and reject if not doing normal nodes
 
1787
    PutBlockmap();
 
1788
 
 
1789
    if (!cur_info->no_reject || !FindLevelLump("REJECT"))
 
1790
      PutReject();
 
1791
  }
 
1792
 
 
1793
  // keyword support (v5.0 of the specs)
 
1794
  AddGLTextLine("BUILDER", "glBSP " GLBSP_VER);
 
1795
  PutGLOptions();
 
1796
  {
 
1797
    char *time_str = UtilTimeString();
 
1798
 
 
1799
    if (time_str)
 
1800
    {
 
1801
      AddGLTextLine("TIME", time_str);
 
1802
      UtilFree(time_str);
 
1803
    }
 
1804
  }
 
1805
 
 
1806
  // this must be done _after_ the normal nodes have been built,
 
1807
  // so that we use the new VERTEXES lump in the checksum.
 
1808
  PutGLChecksum();
 
1809
}
 
1810