- Started implementing UDMF support for ZDBSP: Fixed all data structures to hold UDMF data.

SVN r1466 (trunk)
This commit is contained in:
Christoph Oelckers 2009-03-07 20:35:13 +00:00
parent cd38e62b37
commit 9f300f1b06
16 changed files with 1209 additions and 173 deletions

View File

@ -50,7 +50,7 @@ ifeq ($(sse),1)
CFLAGS += -msse2 -mfpmath=sse
endif
OBJS = main.o getopt.o getopt1.o blockmapbuilder.o processor.o view.o wad.o \
OBJS = main.o getopt.o getopt1.o blockmapbuilder.o processor.o processor_udmf.o sc_man.o view.o wad.o \
nodebuild.o nodebuild_events.o nodebuild_extract.o nodebuild_gl.o \
nodebuild_utility.o nodebuild_classify_nosse2.o \
zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/deflate.o zlib/trees.o \

View File

@ -211,7 +211,7 @@ void FBlockmapBuilder::BuildBlockmap ()
BlockLists = new TArray<WORD>[bmapwidth * bmapheight];
for (line = 0; line < Level.NumLines; ++line)
for (line = 0; line < Level.NumLines(); ++line)
{
int x1 = Level.Vertices[Level.Lines[line].v1].x >> FRACBITS;
int y1 = Level.Vertices[Level.Lines[line].v1].y >> FRACBITS;

View File

@ -5,11 +5,19 @@
#pragma once
#endif
#include "tarray.h"
enum
{
BOXTOP, BOXBOTTOM, BOXLEFT, BOXRIGHT
};
struct UDMFKey
{
int key;
int value;
};
struct MapVertex
{
short x, y;
@ -30,6 +38,20 @@ struct MapSideDef
WORD sector;
};
struct IntSideDef
{
// the first 5 values are only used for binary format maps
short textureoffset;
short rowoffset;
char toptexture[8];
char bottomtexture[8];
char midtexture[8];
int sector;
TArray<UDMFKey> props;
};
struct MapLineDef
{
WORD v1;
@ -50,6 +72,18 @@ struct MapLineDef2
WORD sidenum[2];
};
struct IntLineDef
{
DWORD v1;
DWORD v2;
int flags;
int special;
int args[5];
DWORD sidenum[2];
TArray<UDMFKey> props;
};
struct MapSector
{
short floorheight;
@ -61,6 +95,17 @@ struct MapSector
short tag;
};
struct IntSector
{
// none of the sector properties are used by the node builder
// so there's no need to store them in their expanded form for
// UDMF. JUst storing the UDMF keys and leaving the binary fields
// empty is enough
MapSector data;
TArray<UDMFKey> props;
};
struct MapSubsector
{
WORD numlines;
@ -140,19 +185,35 @@ struct MapThing2
char args[5];
};
struct IntThing
{
unsigned short thingid;
fixed_t x; // full precision coordinates for UDMF support
fixed_t y;
// everything else is not needed or has no extended form in UDMF
short z;
short angle;
short type;
short flags;
char special;
char args[5];
TArray<UDMFKey> props;
};
struct FLevel
{
FLevel ();
~FLevel ();
WideVertex *Vertices; int NumVertices;
MapSideDef *Sides; int NumSides;
MapLineDef2 *Lines; int NumLines;
MapSector *Sectors; int NumSectors;
TArray<IntSideDef> Sides;
TArray<IntLineDef> Lines;
TArray<IntSector> Sectors;
TArray<IntThing> Things;
MapSubsectorEx *Subsectors; int NumSubsectors;
MapSeg *Segs; int NumSegs;
MapNodeEx *Nodes; int NumNodes;
MapThing2 *Things; int NumThings;
WORD *Blockmap; int BlockmapSize;
BYTE *Reject; int RejectSize;
@ -164,7 +225,7 @@ struct FLevel
int NumOrgVerts;
WORD *OrgSectorMap; int NumOrgSectors;
DWORD *OrgSectorMap; int NumOrgSectors;
fixed_t MinX, MinY, MaxX, MaxY;
@ -172,6 +233,11 @@ struct FLevel
void RemoveExtraLines ();
void RemoveExtraSides ();
void RemoveExtraSectors ();
int NumSides() const { return Sides.Size(); }
int NumLines() const { return Lines.Size(); }
int NumSectors() const { return Sectors.Size(); }
int NumThings() const { return Things.Size(); }
};
const int BLOCKSIZE = 128;

View File

@ -1,22 +1,22 @@
/*
Routines for extracting usable data from the new BSP tree.
Copyright (C) 2002-2006 Randy Heit
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
Routines for extracting usable data from the new BSP tree.
Copyright (C) 2002-2006 Randy Heit
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <string.h>
#include <stdio.h>
#include <float.h>
@ -320,7 +320,7 @@ DWORD FNodeBuilder::PushGLSeg (TArray<MapSegGLEx> &segs, const FPrivSeg *seg)
if (newseg.linedef != NO_INDEX)
{
MapLineDef2 * ld = &Level.Lines[newseg.linedef];
IntLineDef * ld = &Level.Lines[newseg.linedef];
if (ld->sidenum[0]==ld->sidenum[1])
{
@ -478,7 +478,7 @@ int FNodeBuilder::StripMinisegs (TArray<MapSeg> &segs, int subsector, short bbox
// Just checking the sidedef to determine the side is insufficient.
// When a level is sidedef compressed both sides may well have the same sidedef.
MapLineDef2 * ld = &Level.Lines[newseg.linedef];
IntLineDef * ld = &Level.Lines[newseg.linedef];
if (ld->sidenum[0]==ld->sidenum[1])
{

View File

@ -47,13 +47,13 @@ const fixed_t VERTEX_EPSILON = 6;
void FNodeBuilder::FindUsedVertices (WideVertex *oldverts, int max)
{
int *map = (int *)alloca (max*sizeof(int));
int *map = new int[max];
int i;
FPrivVert newvert;
memset (&map[0], -1, sizeof(int)*max);
for (i = 0; i < Level.NumLines; ++i)
for (i = 0; i < Level.NumLines(); ++i)
{
int v1 = Level.Lines[i].v1;
int v2 = Level.Lines[i].v2;
@ -71,11 +71,12 @@ void FNodeBuilder::FindUsedVertices (WideVertex *oldverts, int max)
map[v2] = VertexMap->SelectVertexExact (newvert);
}
Level.Lines[i].v1 = (WORD)map[v1];
Level.Lines[i].v2 = (WORD)map[v2];
Level.Lines[i].v1 = map[v1];
Level.Lines[i].v2 = map[v2];
}
InitialVertices = Vertices.Size ();
Level.NumOrgVerts = (int)InitialVertices;
delete[] map;
}
// For every sidedef in the map, create a corresponding seg.
@ -84,7 +85,7 @@ void FNodeBuilder::MakeSegsFromSides ()
{
int i, j;
for (i = 0; i < Level.NumLines; ++i)
for (i = 0; i < Level.NumLines(); ++i)
{
if (Level.Lines[i].sidenum[0] != NO_INDEX)
{
@ -110,7 +111,7 @@ void FNodeBuilder::MakeSegsFromSides ()
int FNodeBuilder::CreateSeg (int linenum, int sidenum)
{
FPrivSeg seg;
WORD backside;
DWORD backside;
int segnum;
seg.next = DWORD_MAX;

View File

@ -43,11 +43,7 @@ FLevel::FLevel ()
FLevel::~FLevel ()
{
if (Things) delete[] Things;
if (Lines) delete[] Lines;
if (Vertices) delete[] Vertices;
if (Sides) delete[] Sides;
if (Sectors) delete[] Sectors;
if (Subsectors) delete[] Subsectors;
if (Segs) delete[] Segs;
if (Nodes) delete[] Nodes;
@ -66,14 +62,24 @@ FProcessor::FProcessor (FWadReader &inwad, int lump)
{
printf ("----%s----\n", Wad.LumpName (Lump));
Extended = Wad.MapHasBehavior (lump);
LoadThings ();
LoadVertices ();
LoadLines ();
LoadSides ();
LoadSectors ();
isUDMF = Wad.isUDMF(lump);
if (Level.NumLines == 0 || Level.NumVertices == 0 || Level.NumSides == 0 || Level.NumSectors == 0)
if (isUDMF)
{
Extended = false;
LoadUDMF();
}
else
{
Extended = Wad.MapHasBehavior (lump);
LoadThings ();
LoadVertices ();
LoadLines ();
LoadSides ();
LoadSectors ();
}
if (Level.NumLines() == 0 || Level.NumVertices == 0 || Level.NumSides() == 0 || Level.NumSectors() == 0)
{
printf (" Map is incomplete\n");
}
@ -98,33 +104,52 @@ FProcessor::FProcessor (FWadReader &inwad, int lump)
void FProcessor::LoadThings ()
{
int NumThings;
if (Extended)
{
ReadMapLump<MapThing2> (Wad, "THINGS", Lump, Level.Things, Level.NumThings);
MapThing2 *Things;
ReadMapLump<MapThing2> (Wad, "THINGS", Lump, Things, NumThings);
for (int i = 0; i < Level.NumThings; ++i)
Level.Things.Resize(NumThings);
for (int i = 0; i < NumThings; ++i)
{
Level.Things[i].x = LittleShort(Level.Things[i].x);
Level.Things[i].y = LittleShort(Level.Things[i].y);
Level.Things[i].angle = LittleShort(Level.Things[i].angle);
Level.Things[i].type = LittleShort(Level.Things[i].type);
Level.Things[i].flags = LittleShort(Level.Things[i].flags);
Level.Things[i].thingid = Things[i].thingid;
Level.Things[i].x = LittleShort(Things[i].x) << FRACBITS;
Level.Things[i].y = LittleShort(Things[i].y) << FRACBITS;
Level.Things[i].z = LittleShort(Things[i].z);
Level.Things[i].angle = LittleShort(Things[i].angle);
Level.Things[i].type = LittleShort(Things[i].type);
Level.Things[i].flags = LittleShort(Things[i].flags);
Level.Things[i].special = Things[i].special;
Level.Things[i].args[0] = Things[i].args[0];
Level.Things[i].args[1] = Things[i].args[1];
Level.Things[i].args[2] = Things[i].args[2];
Level.Things[i].args[3] = Things[i].args[3];
Level.Things[i].args[4] = Things[i].args[4];
}
delete[] Things;
}
else
{
MapThing *mt;
ReadMapLump<MapThing> (Wad, "THINGS", Lump, mt, Level.NumThings);
ReadMapLump<MapThing> (Wad, "THINGS", Lump, mt, NumThings);
Level.Things = new MapThing2[Level.NumThings];
memset (Level.Things, 0, sizeof(*Level.Things)*Level.NumThings);
for (int i = 0; i < Level.NumThings; ++i)
Level.Things.Resize(NumThings);
for (int i = 0; i < NumThings; ++i)
{
Level.Things[i].x = LittleShort(mt[i].x);
Level.Things[i].y = LittleShort(mt[i].y);
Level.Things[i].x = LittleShort(mt[i].x) << FRACBITS;
Level.Things[i].y = LittleShort(mt[i].y) << FRACBITS;
Level.Things[i].angle = LittleShort(mt[i].angle);
Level.Things[i].type = LittleShort(mt[i].type);
Level.Things[i].flags = LittleShort(mt[i].flags);
Level.Things[i].z = 0;
Level.Things[i].special = 0;
Level.Things[i].args[0] = 0;
Level.Things[i].args[1] = 0;
Level.Things[i].args[2] = 0;
Level.Things[i].args[3] = 0;
Level.Things[i].args[4] = 0;
}
delete[] mt;
}
@ -132,41 +157,53 @@ void FProcessor::LoadThings ()
void FProcessor::LoadLines ()
{
int NumLines;
if (Extended)
{
ReadMapLump<MapLineDef2> (Wad, "LINEDEFS", Lump, Level.Lines, Level.NumLines);
MapLineDef2 *Lines;
for (int i = 0; i < Level.NumLines; ++i)
ReadMapLump<MapLineDef2> (Wad, "LINEDEFS", Lump, Lines, NumLines);
Level.Lines.Resize(NumLines);
for (int i = 0; i < NumLines; ++i)
{
Level.Lines[i].v1 = LittleShort(Level.Lines[i].v1);
Level.Lines[i].v2 = LittleShort(Level.Lines[i].v2);
Level.Lines[i].flags = LittleShort(Level.Lines[i].flags);
Level.Lines[i].sidenum[0] = LittleShort(Level.Lines[i].sidenum[0]);
Level.Lines[i].sidenum[1] = LittleShort(Level.Lines[i].sidenum[1]);
Level.Lines[i].special = Lines[i].special;
Level.Lines[i].args[0] = Lines[i].args[0];
Level.Lines[i].args[1] = Lines[i].args[1];
Level.Lines[i].args[2] = Lines[i].args[2];
Level.Lines[i].args[3] = Lines[i].args[3];
Level.Lines[i].args[4] = Lines[i].args[4];
Level.Lines[i].v1 = LittleShort(Lines[i].v1);
Level.Lines[i].v2 = LittleShort(Lines[i].v2);
Level.Lines[i].flags = LittleShort(Lines[i].flags);
Level.Lines[i].sidenum[0] = LittleShort(Lines[i].sidenum[0]);
Level.Lines[i].sidenum[1] = LittleShort(Lines[i].sidenum[1]);
if (Level.Lines[i].sidenum[0] == 0xffff) Level.Lines[i].sidenum[0] = NO_INDEX;
if (Level.Lines[i].sidenum[1] == 0xffff) Level.Lines[i].sidenum[1] = NO_INDEX;
}
delete[] Lines;
}
else
{
MapLineDef *ml;
ReadMapLump<MapLineDef> (Wad, "LINEDEFS", Lump, ml, Level.NumLines);
ReadMapLump<MapLineDef> (Wad, "LINEDEFS", Lump, ml, NumLines);
Level.Lines = new MapLineDef2[Level.NumLines];
memset (Level.Lines, 0, sizeof(*Level.Lines)*Level.NumLines);
for (int i = 0; i < Level.NumLines; ++i)
Level.Lines.Resize(NumLines);
for (int i = 0; i < NumLines; ++i)
{
Level.Lines[i].v1 = LittleShort(ml[i].v1);
Level.Lines[i].v2 = LittleShort(ml[i].v2);
Level.Lines[i].flags = LittleShort(ml[i].flags);
Level.Lines[i].sidenum[0] = LittleShort(ml[i].sidenum[0]);
Level.Lines[i].sidenum[1] = LittleShort(ml[i].sidenum[1]);
if (Level.Lines[i].sidenum[0] == 0xffff) Level.Lines[i].sidenum[0] = NO_INDEX;
if (Level.Lines[i].sidenum[1] == 0xffff) Level.Lines[i].sidenum[1] = NO_INDEX;
// Store the special and tag in the args array so we don't lose them
short t = LittleShort(ml[i].special);
Level.Lines[i].args[2] = t & 255;
Level.Lines[i].args[3] = t >> 8;
t = LittleShort(ml[i].tag);
Level.Lines[i].args[0] = t & 255;
Level.Lines[i].args[1] = t >> 8;
Level.Lines[i].special = 0;
Level.Lines[i].args[0] = LittleShort(ml[i].special);
Level.Lines[i].args[1] = LittleShort(ml[i].tag);
}
delete[] ml;
}
@ -188,17 +225,37 @@ void FProcessor::LoadVertices ()
void FProcessor::LoadSides ()
{
ReadMapLump<MapSideDef> (Wad, "SIDEDEFS", Lump, Level.Sides, Level.NumSides);
MapSideDef *Sides;
int NumSides;
ReadMapLump<MapSideDef> (Wad, "SIDEDEFS", Lump, Sides, NumSides);
for (int i = 0; i < Level.NumSides; ++i)
Level.Sides.Resize(NumSides);
for (int i = 0; i < NumSides; ++i)
{
Level.Sides[i].sector = LittleShort(Level.Sides[i].sector);
Level.Sides[i].textureoffset = Sides[i].textureoffset;
Level.Sides[i].rowoffset = Sides[i].rowoffset;
memcpy(Level.Sides[i].toptexture, Sides[i].toptexture, 8);
memcpy(Level.Sides[i].bottomtexture, Sides[i].bottomtexture, 8);
memcpy(Level.Sides[i].midtexture, Sides[i].midtexture, 8);
Level.Sides[i].sector = LittleShort(Sides[i].sector);
if (Level.Sides[i].sector == 0xffff) Level.Sides[i].sector = NO_INDEX;
}
delete [] Sides;
}
void FProcessor::LoadSectors ()
{
ReadMapLump<MapSector> (Wad, "SECTORS", Lump, Level.Sectors, Level.NumSectors);
MapSector *Sectors;
int NumSectors;
ReadMapLump<MapSector> (Wad, "SECTORS", Lump, Sectors, NumSectors);
Level.Sectors.Resize(NumSectors);
for (int i = 0; i < NumSectors; ++i)
{
Level.Sectors[i].data = Sectors[i];
}
}
void FLevel::FindMapBounds ()
@ -229,7 +286,7 @@ void FLevel::RemoveExtraLines ()
// Extra lines are those with 0 length. Collision detection against
// one of those could cause a divide by 0, so it's best to remove them.
for (i = newNumLines = 0; i < NumLines; ++i)
for (i = newNumLines = 0; i < NumLines(); ++i)
{
if (Vertices[Lines[i].v1].x != Vertices[Lines[i].v2].x ||
Vertices[Lines[i].v1].y != Vertices[Lines[i].v2].y)
@ -241,30 +298,31 @@ void FLevel::RemoveExtraLines ()
++newNumLines;
}
}
if (newNumLines < NumLines)
if (newNumLines < NumLines())
{
int diff = NumLines - newNumLines;
int diff = NumLines() - newNumLines;
printf (" Removed %d line%s with 0 length.\n", diff, diff > 1 ? "s" : "");
}
NumLines = newNumLines;
Lines.Resize(newNumLines);
}
void FLevel::RemoveExtraSides ()
{
BYTE *used;
WORD *remap;
int *remap;
int i, newNumSides;
// Extra sides are those that aren't referenced by any lines.
// They just waste space, so get rid of them.
int NumSides = this->NumSides();
used = new BYTE[NumSides];
memset (used, 0, NumSides*sizeof(*used));
remap = new WORD[NumSides];
remap = new int[NumSides];
// Mark all used sides
for (i = 0; i < NumLines; ++i)
for (i = 0; i < NumLines(); ++i)
{
if (Lines[i].sidenum[0] != NO_INDEX)
{
@ -302,10 +360,10 @@ void FLevel::RemoveExtraSides ()
int diff = NumSides - newNumSides;
printf (" Removed %d unused sidedef%s.\n", diff, diff > 1 ? "s" : "");
NumSides = newNumSides;
Sides.Resize(newNumSides);
// Renumber side references in lines
for (i = 0; i < NumLines; ++i)
for (i = 0; i < NumLines(); ++i)
{
if (Lines[i].sidenum[0] != NO_INDEX)
{
@ -317,7 +375,6 @@ void FLevel::RemoveExtraSides ()
}
}
}
delete[] used;
delete[] remap;
}
@ -325,19 +382,19 @@ void FLevel::RemoveExtraSides ()
void FLevel::RemoveExtraSectors ()
{
BYTE *used;
WORD *remap;
DWORD *remap;
int i, newNumSectors;
// Extra sectors are those that aren't referenced by any sides.
// They just waste space, so get rid of them.
NumOrgSectors = NumSectors;
used = new BYTE[NumSectors];
memset (used, 0, NumSectors*sizeof(*used));
remap = new WORD[NumSectors];
NumOrgSectors = NumSectors();
used = new BYTE[NumSectors()];
memset (used, 0, NumSectors()*sizeof(*used));
remap = new DWORD[NumSectors()];
// Mark all used sectors
for (i = 0; i < NumSides; ++i)
for (i = 0; i < NumSides(); ++i)
{
if (Sides[i].sector != NO_INDEX)
{
@ -350,7 +407,7 @@ void FLevel::RemoveExtraSectors ()
}
// Shift out any unused sides
for (i = newNumSectors = 0; i < NumSectors; ++i)
for (i = newNumSectors = 0; i < NumSectors(); ++i)
{
if (used[i])
{
@ -366,13 +423,13 @@ void FLevel::RemoveExtraSectors ()
}
}
if (newNumSectors < NumSectors)
if (newNumSectors < NumSectors())
{
int diff = NumSectors - newNumSectors;
int diff = NumSectors() - newNumSectors;
printf (" Removed %d unused sector%s.\n", diff, diff > 1 ? "s" : "");
// Renumber sector references in sides
for (i = 0; i < NumSides; ++i)
for (i = 0; i < NumSides(); ++i)
{
if (Sides[i].sector != NO_INDEX)
{
@ -380,8 +437,8 @@ void FLevel::RemoveExtraSectors ()
}
}
// Make a reverse map for fixing reject lumps
OrgSectorMap = new WORD[newNumSectors];
for (i = 0; i < NumSectors; ++i)
OrgSectorMap = new DWORD[newNumSectors];
for (i = 0; i < NumSectors(); ++i)
{
if (remap[i] != NO_INDEX)
{
@ -389,7 +446,7 @@ void FLevel::RemoveExtraSectors ()
}
}
NumSectors = newNumSectors;
Sectors.Resize(newNumSectors);
}
delete[] used;
@ -404,7 +461,7 @@ void FProcessor::GetPolySpots ()
// Determine if this is a Hexen map by looking for things of type 3000
// Only Hexen maps use them, and they are the polyobject anchors
for (i = 0; i < Level.NumThings; ++i)
for (i = 0; i < Level.NumThings(); ++i)
{
if (Level.Things[i].type == PO_HEX_ANCHOR_TYPE)
{
@ -412,7 +469,7 @@ void FProcessor::GetPolySpots ()
}
}
if (i < Level.NumThings)
if (i < Level.NumThings())
{
spot1 = PO_HEX_SPAWN_TYPE;
spot2 = PO_HEX_SPAWNCRUSH_TYPE;
@ -425,15 +482,15 @@ void FProcessor::GetPolySpots ()
anchor = PO_ANCHOR_TYPE;
}
for (i = 0; i < Level.NumThings; ++i)
for (i = 0; i < Level.NumThings(); ++i)
{
if (Level.Things[i].type == spot1 ||
Level.Things[i].type == spot2 ||
Level.Things[i].type == anchor)
{
FNodeBuilder::FPolyStart newvert;
newvert.x = Level.Things[i].x << FRACBITS;
newvert.y = Level.Things[i].y << FRACBITS;
newvert.x = Level.Things[i].x;
newvert.y = Level.Things[i].y;
newvert.polynum = Level.Things[i].angle;
if (Level.Things[i].type == anchor)
{
@ -450,24 +507,30 @@ void FProcessor::GetPolySpots ()
void FProcessor::Write (FWadWriter &out)
{
if (Level.NumLines == 0 || Level.NumSides == 0 || Level.NumSectors == 0 || Level.NumVertices == 0)
if (Level.NumLines() == 0 || Level.NumSides() == 0 || Level.NumSectors() == 0 || Level.NumVertices == 0)
{
// Map is empty, so just copy it as-is
out.CopyLump (Wad, Lump);
out.CopyLump (Wad, Wad.FindMapLump ("THINGS", Lump));
out.CopyLump (Wad, Wad.FindMapLump ("LINEDEFS", Lump));
out.CopyLump (Wad, Wad.FindMapLump ("SIDEDEFS", Lump));
out.CopyLump (Wad, Wad.FindMapLump ("VERTEXES", Lump));
out.CreateLabel ("SEGS");
out.CreateLabel ("SSECTORS");
out.CreateLabel ("NODES");
out.CopyLump (Wad, Wad.FindMapLump ("SECTORS", Lump));
out.CreateLabel ("REJECT");
out.CreateLabel ("BLOCKMAP");
if (Extended)
if (!isUDMF)
{
// Map is empty, so just copy it as-is
out.CopyLump (Wad, Lump);
out.CopyLump (Wad, Wad.FindMapLump ("THINGS", Lump));
out.CopyLump (Wad, Wad.FindMapLump ("LINEDEFS", Lump));
out.CopyLump (Wad, Wad.FindMapLump ("SIDEDEFS", Lump));
out.CopyLump (Wad, Wad.FindMapLump ("VERTEXES", Lump));
out.CreateLabel ("SEGS");
out.CreateLabel ("SSECTORS");
out.CreateLabel ("NODES");
out.CopyLump (Wad, Wad.FindMapLump ("SECTORS", Lump));
out.CreateLabel ("REJECT");
out.CreateLabel ("BLOCKMAP");
if (Extended)
{
out.CopyLump (Wad, Wad.FindMapLump ("BEHAVIOR", Lump));
out.CopyLump (Wad, Wad.FindMapLump ("SCRIPTS", Lump));
}
}
else
{
out.CopyLump (Wad, Wad.FindMapLump ("BEHAVIOR", Lump));
out.CopyLump (Wad, Wad.FindMapLump ("SCRIPTS", Lump));
}
return;
}
@ -493,6 +556,9 @@ void FProcessor::Write (FWadWriter &out)
if (BuildNodes)
{
FNodeBuilder *builder = NULL;
// UDMF spec requires GL nodes.
if (isUDMF) BuildGLNodes = true;
try
{
@ -580,7 +646,7 @@ void FProcessor::Write (FWadWriter &out)
Level.Blockmap = new WORD[Level.BlockmapSize];
memcpy (Level.Blockmap, blocks, Level.BlockmapSize*sizeof(WORD));
Level.RejectSize = (Level.NumSectors*Level.NumSectors + 7) / 8;
Level.RejectSize = (Level.NumSectors()*Level.NumSectors() + 7) / 8;
Level.Reject = NULL;
switch (RejectMode)
@ -609,13 +675,13 @@ void FProcessor::Write (FWadWriter &out)
}
Level.RejectSize = 0;
}
else if (Level.NumOrgSectors != Level.NumSectors)
else if (Level.NumOrgSectors != Level.NumSectors())
{
// Some sectors have been removed, so fix the reject.
BYTE *newreject = FixReject (Level.Reject);
delete[] Level.Reject;
Level.Reject = newreject;
Level.RejectSize = (Level.NumSectors * Level.NumSectors + 7) / 8;
Level.RejectSize = (Level.NumSectors() * Level.NumSectors() + 7) / 8;
}
}
}
@ -744,19 +810,19 @@ void FProcessor::Write (FWadWriter &out)
BYTE *FProcessor::FixReject (const BYTE *oldreject)
{
int x, y, ox, oy, pnum, opnum;
int rejectSize = (Level.NumSectors*Level.NumSectors + 7) / 8;
int rejectSize = (Level.NumSectors()*Level.NumSectors() + 7) / 8;
BYTE *newreject = new BYTE[rejectSize];
memset (newreject, 0, rejectSize);
for (y = 0; y < Level.NumSectors; ++y)
for (y = 0; y < Level.NumSectors(); ++y)
{
oy = Level.OrgSectorMap[y];
for (x = 0; x < Level.NumSectors; ++x)
for (x = 0; x < Level.NumSectors(); ++x)
{
ox = Level.OrgSectorMap[x];
pnum = y*Level.NumSectors + x;
opnum = oy*Level.NumSectors + ox;
pnum = y*Level.NumSectors() + x;
opnum = oy*Level.NumSectors() + ox;
if (oldreject[opnum >> 3] & (1 << (opnum & 7)))
{
@ -870,37 +936,39 @@ void FProcessor::WriteLines (FWadWriter &out)
if (Extended)
{
for (i = 0; i < Level.NumLines; ++i)
MapLineDef2 *Lines = new MapLineDef2[Level.NumLines()];
for (i = 0; i < Level.NumLines(); ++i)
{
Level.Lines[i].v1 = LittleShort(Level.Lines[i].v1);
Level.Lines[i].v2 = LittleShort(Level.Lines[i].v2);
Level.Lines[i].flags = LittleShort(Level.Lines[i].flags);
Level.Lines[i].sidenum[0] = LittleShort(Level.Lines[i].sidenum[0]);
Level.Lines[i].sidenum[1] = LittleShort(Level.Lines[i].sidenum[1]);
Lines[i].special = Level.Lines[i].special;
Lines[i].args[0] = Level.Lines[i].args[0];
Lines[i].args[1] = Level.Lines[i].args[1];
Lines[i].args[2] = Level.Lines[i].args[2];
Lines[i].args[3] = Level.Lines[i].args[3];
Lines[i].args[4] = Level.Lines[i].args[4];
Lines[i].v1 = LittleShort(WORD(Level.Lines[i].v1));
Lines[i].v2 = LittleShort(WORD(Level.Lines[i].v2));
Lines[i].flags = LittleShort(WORD(Level.Lines[i].flags));
Lines[i].sidenum[0] = LittleShort(WORD(Level.Lines[i].sidenum[0]));
Lines[i].sidenum[1] = LittleShort(WORD(Level.Lines[i].sidenum[1]));
}
out.WriteLump ("LINEDEFS", Level.Lines, Level.NumLines*sizeof(*Level.Lines));
out.WriteLump ("LINEDEFS", Lines, Level.NumLines()*sizeof(*Lines));
delete[] Lines;
}
else
{
MapLineDef *ld = new MapLineDef[Level.NumLines];
MapLineDef *ld = new MapLineDef[Level.NumLines()];
for (i = 0; i < Level.NumLines; ++i)
for (i = 0; i < Level.NumLines(); ++i)
{
short t;
ld[i].v1 = LittleShort(Level.Lines[i].v1);
ld[i].v2 = LittleShort(Level.Lines[i].v2);
ld[i].flags = LittleShort(Level.Lines[i].flags);
ld[i].sidenum[0] = LittleShort(Level.Lines[i].sidenum[0]);
ld[i].sidenum[1] = LittleShort(Level.Lines[i].sidenum[1]);
t = Level.Lines[i].args[2] + (Level.Lines[i].args[3]<<8);
ld[i].special = LittleShort(t);
t = Level.Lines[i].args[0] + (Level.Lines[i].args[1]<<8);
ld[i].tag = LittleShort(t);
ld[i].v1 = LittleShort(WORD(Level.Lines[i].v1));
ld[i].v2 = LittleShort(WORD(Level.Lines[i].v2));
ld[i].flags = LittleShort(WORD(Level.Lines[i].flags));
ld[i].sidenum[0] = LittleShort(WORD(Level.Lines[i].sidenum[0]));
ld[i].sidenum[1] = LittleShort(WORD(Level.Lines[i].sidenum[1]));
ld[i].special = LittleShort(WORD(Level.Lines[i].args[0]));
ld[i].tag = LittleShort(WORD(Level.Lines[i].args[1]));
}
out.WriteLump ("LINEDEFS", ld, Level.NumLines*sizeof(*ld));
out.WriteLump ("LINEDEFS", ld, Level.NumLines()*sizeof(*ld));
delete[] ld;
}
}
@ -908,17 +976,32 @@ void FProcessor::WriteLines (FWadWriter &out)
void FProcessor::WriteSides (FWadWriter &out)
{
int i;
MapSideDef *Sides = new MapSideDef[Level.NumSides()];
for (i = 0; i < Level.NumSides; ++i)
for (i = 0; i < Level.NumSides(); ++i)
{
Level.Sides[i].sector = LittleShort(Level.Sides[i].sector);
Sides[i].textureoffset = Level.Sides[i].textureoffset;
Sides[i].rowoffset = Level.Sides[i].rowoffset;
memcpy(Sides[i].toptexture, Level.Sides[i].toptexture, 8);
memcpy(Sides[i].bottomtexture, Level.Sides[i].bottomtexture, 8);
memcpy(Sides[i].midtexture, Level.Sides[i].midtexture, 8);
Sides[i].sector = LittleShort(Level.Sides[i].sector);
}
out.WriteLump ("SIDEDEFS", Level.Sides, Level.NumSides*sizeof(*Level.Sides));
out.WriteLump ("SIDEDEFS", Sides, Level.NumSides()*sizeof(*Sides));
delete[] Sides;
}
void FProcessor::WriteSectors (FWadWriter &out)
{
out.WriteLump ("SECTORS", Level.Sectors, Level.NumSectors*sizeof(*Level.Sectors));
int i;
MapSector *Sectors = new MapSector[Level.NumSectors()];
for (i = 0; i < Level.NumSectors(); ++i)
{
Sectors[i] = Level.Sectors[i].data;
}
out.WriteLump ("SECTORS", Sectors, Level.NumSectors()*sizeof(*Sectors));
}
void FProcessor::WriteSegs (FWadWriter &out)

View File

@ -43,6 +43,7 @@ public:
void Write (FWadWriter &out);
private:
void LoadUDMF();
void LoadThings ();
void LoadLines ();
void LoadVertices ();
@ -92,6 +93,7 @@ private:
TArray<FNodeBuilder::FPolyStart> PolyAnchors;
bool Extended;
bool isUDMF;
FWadReader &Wad;
int Lump;

7
processor_udmf.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "processor.h"
void FProcessor::LoadUDMF()
{
}

733
sc_man.cpp Normal file
View File

@ -0,0 +1,733 @@
/*
Reads wad files, builds nodes, and saves new wad files.
Copyright (C) 1996 Raven Software
Copyright (C) 2002-2006 Randy Heit
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// HEADER FILES ------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
#include "sc_man.h"
#ifdef _MSC_VER
#pragma warning(disable:4996)
#endif
// MACROS ------------------------------------------------------------------
#define MAX_STRING_SIZE 4096
#define ASCII_COMMENT (';')
#define CPP_COMMENT ('/')
#define C_COMMENT ('*')
#define ASCII_QUOTE (34)
#define LUMP_SCRIPT 1
#define FILE_ZONE_SCRIPT 2
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void SC_PrepareScript (void);
static void CheckOpen (void);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
char *sc_String;
int sc_StringLen;
int sc_Number;
float sc_Float;
int sc_Line;
bool sc_End;
bool sc_Crossed;
bool sc_StringQuoted;
bool sc_FileScripts = false;
FILE *sc_Out;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static char *ScriptBuffer;
static char *ScriptPtr;
static char *ScriptEndPtr;
static char StringBuffer[MAX_STRING_SIZE];
static bool ScriptOpen = false;
static int ScriptSize;
static bool AlreadyGot = false;
static char *SavedScriptPtr;
static int SavedScriptLine;
static bool CMode;
// CODE --------------------------------------------------------------------
//==========================================================================
//
// SC_OpenFile
//
// Loads a script (from a file). Uses the new/delete memory allocator for
// memory allocation and de-allocation.
//
//==========================================================================
void SC_OpenFile (const char *name)
{
SC_Close ();
FILE * f = fopen(name, "rb");
if (f == NULL)
{
printf("%s: file not found\n", name);
exit(1);
}
fseek(f, 0, SEEK_END);
ScriptSize = ftell(f);
fseek(f, 0, SEEK_SET);
ScriptBuffer = (char*)malloc(ScriptSize);
if (ScriptSize != int(fread(ScriptBuffer, 1, ScriptSize, f)))
{
fclose(f);
printf("%s: unable to read file\n", name);
exit(1);
}
fclose(f);
SC_PrepareScript ();
}
//==========================================================================
//
// SC_PrepareScript
//
// Prepares a script for parsing.
//
//==========================================================================
static void SC_PrepareScript (void)
{
ScriptPtr = ScriptBuffer;
ScriptEndPtr = ScriptPtr + ScriptSize;
sc_Line = 1;
sc_End = false;
ScriptOpen = true;
sc_String = StringBuffer;
AlreadyGot = false;
SavedScriptPtr = NULL;
CMode = false;
}
//==========================================================================
//
// SC_Close
//
//==========================================================================
void SC_Close (void)
{
if (ScriptOpen)
{
if (ScriptBuffer)
{
free(ScriptBuffer);
}
ScriptBuffer = NULL;
ScriptOpen = false;
}
}
//==========================================================================
//
// SC_SavePos
//
// Saves the current script location for restoration later
//
//==========================================================================
void SC_SavePos (void)
{
CheckOpen ();
if (sc_End)
{
SavedScriptPtr = NULL;
}
else
{
SavedScriptPtr = ScriptPtr;
SavedScriptLine = sc_Line;
}
}
//==========================================================================
//
// SC_RestorePos
//
// Restores the previously saved script location
//
//==========================================================================
void SC_RestorePos (void)
{
if (SavedScriptPtr)
{
ScriptPtr = SavedScriptPtr;
sc_Line = SavedScriptLine;
sc_End = false;
AlreadyGot = false;
}
}
//==========================================================================
//
// SC_SetCMode
//
// Enables/disables C mode. In C mode, more characters are considered to
// be whole words than in non-C mode.
//
//==========================================================================
void SC_SetCMode (bool cmode)
{
CMode = cmode;
}
//==========================================================================
//
// SC_GetString
//
//==========================================================================
bool SC_GetString (bool multiline)
{
char *text;
bool foundToken;
CheckOpen();
if (AlreadyGot)
{
AlreadyGot = false;
return true;
}
foundToken = false;
sc_Crossed = false;
sc_StringQuoted = false;
if (ScriptPtr >= ScriptEndPtr)
{
sc_End = true;
return false;
}
while (foundToken == false)
{
while (ScriptPtr < ScriptEndPtr && *ScriptPtr <= ' ')
{
if (*ScriptPtr++ == '\n')
{
sc_Line++;
sc_Crossed = true;
}
}
if (ScriptPtr >= ScriptEndPtr)
{
sc_End = true;
return false;
}
if ((CMode || *ScriptPtr != ASCII_COMMENT) &&
!(ScriptPtr[0] == CPP_COMMENT && ScriptPtr < ScriptEndPtr - 1 &&
(ScriptPtr[1] == CPP_COMMENT || ScriptPtr[1] == C_COMMENT)))
{ // Found a token
foundToken = true;
}
else
{ // Skip comment
if (ScriptPtr[0] == CPP_COMMENT && ScriptPtr[1] == C_COMMENT)
{ // C comment
while (ScriptPtr[0] != C_COMMENT || ScriptPtr[1] != CPP_COMMENT)
{
if (ScriptPtr[0] == '\n')
{
sc_Line++;
sc_Crossed = true;
}
fputc(ScriptPtr[0], sc_Out);
ScriptPtr++;
if (ScriptPtr >= ScriptEndPtr - 1)
{
sc_End = true;
return false;
}
fputs("*/", sc_Out);
}
ScriptPtr += 2;
}
else
{ // C++ comment
while (*ScriptPtr++ != '\n')
{
fputc(ScriptPtr[-1], sc_Out);
if (ScriptPtr >= ScriptEndPtr)
{
sc_End = true;
return false;
}
}
sc_Line++;
sc_Crossed = true;
fputc('\n', sc_Out);
}
}
}
text = sc_String;
if (*ScriptPtr == ASCII_QUOTE)
{ // Quoted string - return string including the quotes
*text++ = *ScriptPtr++;
sc_StringQuoted = true;
while (*ScriptPtr != ASCII_QUOTE)
{
if (multiline && *ScriptPtr == '\n')
{
*text++ = '"';
*text++ = ',';
*text++ = '\n';
*text++ = '\t';
*text++ = '\t';
*text++ = '"';
ScriptPtr++;
continue;
}
else if (*ScriptPtr < ' ')
{
ScriptPtr++;
}
else
{
*text++ = *ScriptPtr++;
}
if (ScriptPtr == ScriptEndPtr
|| text == &sc_String[MAX_STRING_SIZE-1])
{
break;
}
}
*text++ = '"';
ScriptPtr++;
}
else
{ // Normal string
static const char *stopchars;
if (CMode)
{
stopchars = "`~!@#$%^&*(){}[]/=\?+|;:<>,";
// '-' can be its own token, or it can be part of a negative number
if (*ScriptPtr == '-')
{
*text++ = '-';
ScriptPtr++;
if (ScriptPtr < ScriptEndPtr || (*ScriptPtr >= '0' && *ScriptPtr <= '9'))
{
goto grabtoken;
}
goto gottoken;
}
}
else
{
stopchars = "{}|=";
}
if (strchr (stopchars, *ScriptPtr))
{
*text++ = *ScriptPtr++;
}
else
{
grabtoken:
while ((*ScriptPtr > ' ') && (strchr (stopchars, *ScriptPtr) == NULL)
&& (CMode || *ScriptPtr != ASCII_COMMENT)
&& !(ScriptPtr[0] == CPP_COMMENT && (ScriptPtr < ScriptEndPtr - 1) &&
(ScriptPtr[1] == CPP_COMMENT || ScriptPtr[1] == C_COMMENT)))
{
*text++ = *ScriptPtr++;
if (ScriptPtr == ScriptEndPtr
|| text == &sc_String[MAX_STRING_SIZE-1])
{
break;
}
}
}
}
gottoken:
*text = 0;
sc_StringLen = int(text - sc_String);
return true;
}
//==========================================================================
//
// SC_MustGetString
//
//==========================================================================
void SC_MustGetString (void)
{
if (SC_GetString () == false)
{
SC_ScriptError ("Missing string (unexpected end of file).");
}
}
//==========================================================================
//
// SC_MustGetStringName
//
//==========================================================================
void SC_MustGetStringName (const char *name)
{
SC_MustGetString ();
if (SC_Compare (name) == false)
{
SC_ScriptError ("Expected '%s', got '%s'.", name, sc_String);
}
}
//==========================================================================
//
// SC_CheckString
//
// Checks if the next token matches the specified string. Returns true if
// it does. If it doesn't, it ungets it and returns false.
//==========================================================================
bool SC_CheckString (const char *name)
{
if (SC_GetString ())
{
if (SC_Compare (name))
{
return true;
}
SC_UnGet ();
}
return false;
}
//==========================================================================
//
// SC_GetNumber
//
//==========================================================================
bool SC_GetNumber (void)
{
char *stopper;
CheckOpen ();
if (SC_GetString())
{
if (strcmp (sc_String, "MAXINT") == 0)
{
sc_Number = INT_MAX;
}
else
{
sc_Number = strtol (sc_String, &stopper, 0);
if (*stopper != 0)
{
SC_ScriptError ("SC_GetNumber: Bad numeric constant \"%s\".", sc_String);
}
}
sc_Float = (float)sc_Number;
return true;
}
else
{
return false;
}
}
//==========================================================================
//
// SC_MustGetNumber
//
//==========================================================================
void SC_MustGetNumber (void)
{
if (SC_GetNumber() == false)
{
SC_ScriptError ("Missing integer (unexpected end of file).");
}
}
//==========================================================================
//
// SC_CheckNumber
// similar to SC_GetNumber but ungets the token if it isn't a number
// and does not print an error
//
//==========================================================================
bool SC_CheckNumber (void)
{
char *stopper;
//CheckOpen ();
if (SC_GetString())
{
if (strcmp (sc_String, "MAXINT") == 0)
{
sc_Number = INT_MAX;
}
else
{
sc_Number = strtol (sc_String, &stopper, 0);
if (*stopper != 0)
{
SC_UnGet();
return false;
}
}
sc_Float = (float)sc_Number;
return true;
}
else
{
return false;
}
}
//==========================================================================
//
// SC_CheckFloat
// [GRB] Same as SC_CheckNumber, only for floats
//
//==========================================================================
bool SC_CheckFloat (void)
{
char *stopper;
//CheckOpen ();
if (SC_GetString())
{
sc_Float = (float)strtod (sc_String, &stopper);
if (*stopper != 0)
{
SC_UnGet();
return false;
}
return true;
}
else
{
return false;
}
}
//==========================================================================
//
// SC_GetFloat
//
//==========================================================================
bool SC_GetFloat (void)
{
char *stopper;
CheckOpen ();
if (SC_GetString())
{
sc_Float = (float)strtod (sc_String, &stopper);
if (*stopper != 0)
{
SC_ScriptError("SC_GetFloat: Bad numeric constant \"%s\".\n",sc_String);
}
sc_Number = (int)sc_Float;
return true;
}
else
{
return false;
}
}
//==========================================================================
//
// SC_MustGetFloat
//
//==========================================================================
void SC_MustGetFloat (void)
{
if (SC_GetFloat() == false)
{
SC_ScriptError ("Missing floating-point number (unexpected end of file).");
}
}
//==========================================================================
//
// SC_UnGet
//
// Assumes there is a valid string in sc_String.
//
//==========================================================================
void SC_UnGet (void)
{
AlreadyGot = true;
}
//==========================================================================
//
// SC_Check
//
// Returns true if another token is on the current line.
//
//==========================================================================
/*
bool SC_Check(void)
{
char *text;
CheckOpen();
text = ScriptPtr;
if(text >= ScriptEndPtr)
{
return false;
}
while(*text <= 32)
{
if(*text == '\n')
{
return false;
}
text++;
if(text == ScriptEndPtr)
{
return false;
}
}
if(*text == ASCII_COMMENT)
{
return false;
}
return true;
}
*/
//==========================================================================
//
// SC_MatchString
//
// Returns the index of the first match to sc_String from the passed
// array of strings, or -1 if not found.
//
//==========================================================================
int SC_MatchString (const char **strings)
{
int i;
for (i = 0; *strings != NULL; i++)
{
if (SC_Compare (*strings++))
{
return i;
}
}
return -1;
}
//==========================================================================
//
// SC_MustMatchString
//
//==========================================================================
int SC_MustMatchString (const char **strings)
{
int i;
i = SC_MatchString (strings);
if (i == -1)
{
SC_ScriptError (NULL);
}
return i;
}
//==========================================================================
//
// SC_Compare
//
//==========================================================================
bool SC_Compare (const char *text)
{
#ifdef _MSC_VER
return (_stricmp (text, sc_String) == 0);
#else
return (strcasecmp (text, sc_String) == 0);
#endif
}
//==========================================================================
//
// SC_ScriptError
//
//==========================================================================
void SC_ScriptError (const char *message, ...)
{
char composed[2048];
if (message == NULL)
{
message = "Bad syntax.";
}
va_list arglist;
va_start (arglist, message);
vsprintf (composed, message, arglist);
va_end (arglist);
printf ("Script error, line %d:\n%s\n", sc_Line, composed);
exit(1);
}
//==========================================================================
//
// CheckOpen
//
//==========================================================================
static void CheckOpen(void)
{
if (ScriptOpen == false)
{
printf ("SC_ call before SC_Open().\n");
exit(1);
}
}

44
sc_man.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef __SC_MAN_H__
#define __SC_MAN_H__
void SC_Open (const char *name);
void SC_OpenFile (const char *name);
void SC_OpenMem (const char *name, char *buffer, int size);
void SC_OpenLumpNum (int lump, const char *name);
void SC_Close (void);
void SC_SetCMode (bool cmode);
void SC_SetEscape (bool esc);
void SC_SavePos (void);
void SC_RestorePos (void);
bool SC_GetString (bool multiline = false);
void SC_MustGetString (void);
void SC_MustGetStringName (const char *name);
bool SC_CheckString (const char *name);
bool SC_GetNumber (void);
void SC_MustGetNumber (void);
bool SC_CheckNumber (void);
bool SC_CheckFloat (void);
bool SC_GetFloat (void);
void SC_MustGetFloat (void);
void SC_UnGet (void);
//boolean SC_Check(void);
bool SC_Compare (const char *text);
int SC_MatchString (const char **strings);
int SC_MustMatchString (const char **strings);
void SC_ScriptError (const char *message, ...);
void SC_SaveScriptState();
void SC_RestoreScriptState();
extern char *sc_String;
extern int sc_StringLen;
extern int sc_Number;
extern float sc_Float;
extern int sc_Line;
extern bool sc_End;
extern bool sc_Crossed;
extern bool sc_FileScripts;
extern bool sc_StringQuoted;
extern char *sc_ScriptsDir;
extern FILE *sc_Out;
#endif //__SC_MAN_H__

View File

@ -3,7 +3,7 @@
** Templated, automatically resizing array
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit
** Copyright 1998-2007 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@ -37,10 +37,19 @@
#include <stdlib.h>
#include <assert.h>
#include <malloc.h>
#include <new>
template <class T>
#if !defined(_WIN32)
#include <inttypes.h> // for intptr_t
#elif !defined(_MSC_VER)
#include <stdint.h> // for mingw
#endif
// TArray -------------------------------------------------------------------
// T is the type stored in the array.
// TT is the type returned by operator().
template <class T, class TT=T>
class TArray
{
public:
@ -108,10 +117,16 @@ public:
Most = 0;
}
}
// Return a reference to an element
T &operator[] (unsigned int index) const
{
return Array[index];
}
// Returns the value of an element
TT operator() (unsigned int index) const
{
return Array[index];
}
unsigned int Push (const T &item)
{
Grow (1);
@ -133,10 +148,30 @@ public:
if (index < Count)
{
Array[index].~T();
memmove (&Array[index], &Array[index+1], sizeof(T)*(Count - index - 1));
Count--;
if (index < --Count)
{
memmove (&Array[index], &Array[index+1], sizeof(T)*(Count - index));
}
}
}
void Delete (unsigned int index, int deletecount)
{
if (index + deletecount > Count) deletecount = Count - index;
if (deletecount > 0)
{
for(int i = 0; i < deletecount; i++)
{
Array[index + i].~T();
}
Count -= deletecount;
if (index < Count)
{
memmove (&Array[index], &Array[index+deletecount], sizeof(T)*(Count - index));
}
}
}
// Inserts an item into the array, shifting elements as needed
void Insert (unsigned int index, const T &item)
{
@ -217,6 +252,10 @@ public:
Grow (amount);
unsigned int place = Count;
Count += amount;
for (unsigned int i = place; i < Count; ++i)
{
::new((void *)&Array[i]) T;
}
return place;
}
unsigned int Size () const
@ -252,7 +291,7 @@ private:
}
for (unsigned int i = 0; i < Count; ++i)
{
Array[i] = other.Array[i];
::new(&Array[i]) T(other.Array[i]);
}
}
else
@ -281,12 +320,29 @@ private:
}
};
// An array with accessors that automatically grow the
// array as needed. But can still be used as a normal
// TArray if needed. Used by ACS world and global arrays.
// TDeletingArray -----------------------------------------------------------
// An array that deletes its elements when it gets deleted.
template<class T, class TT=T>
class TDeletingArray : public TArray<T, TT>
{
public:
~TDeletingArray<T, TT> ()
{
for (unsigned int i = 0; i < TArray<T,TT>::Size(); ++i)
{
if ((*this)[i] != NULL)
delete (*this)[i];
}
}
};
template <class T>
class TAutoGrowArray : public TArray<T>
// TAutoGrowArray -----------------------------------------------------------
// An array with accessors that automatically grow the array as needed.
// It can still be used as a normal TArray if needed. ACS uses this for
// world and global arrays.
template <class T, class TT=T>
class TAutoGrowArray : public TArray<T, TT>
{
public:
T GetVal (unsigned int index)
@ -299,6 +355,8 @@ public:
}
void SetVal (unsigned int index, T val)
{
if ((int)index < 0) return; // These always result in an out of memory condition.
if (index >= this->Size())
{
this->Resize (index + 1);
@ -307,4 +365,5 @@ public:
}
};
#endif //__TARRAY_H__

View File

@ -576,7 +576,7 @@ static int DesiredSector;
static void DrawLevelReject (HDC dc)
{
int seeFromRow = DesiredSector * Level->NumSectors;
int seeFromRow = DesiredSector * Level->NumSectors();
HPEN oldPen;
HPEN cantSee;
HPEN canSee;
@ -589,7 +589,7 @@ static void DrawLevelReject (HDC dc)
oldPen = (HPEN)SelectObject (dc, canSee);
enum { UNDECIDED, CANT_SEE, CAN_SEE, SEE_FROM } choice, prevchoice = CAN_SEE;
for (int i = 0; i < Level->NumLines; ++i)
for (int i = 0; i < Level->NumLines(); ++i)
{
choice = UNDECIDED;

29
wad.cpp
View File

@ -161,11 +161,27 @@ int FWadReader::FindMapLump (const char *name, int map) const
return -1;
}
bool FWadReader::isUDMF (int index) const
{
index++;
if (strnicmp(Lumps[index].Name, "TEXTMAP", 8) == NULL)
{
// UDMF map
return true;
}
return false;
}
bool FWadReader::IsMap (int index) const
{
int i, j;
if (isUDMF(index)) return true;
index++;
for (i = j = 0; i < 12; ++i)
{
if (strnicmp (Lumps[index+j].Name, MapLumpNames[i], 8) != 0)
@ -279,7 +295,18 @@ int FWadReader::LumpAfterMap (int i) const
{
int j, k;
++i;
if (isUDMF(i))
{
// UDMF map
i += 2;
while (strnicmp(Lumps[i].Name, "ENDMAP", 8) != NULL && i < Header.NumLumps)
{
i++;
}
return i;
}
i++;
for (j = k = 0; j < 12; ++j)
{
if (strnicmp (Lumps[i+k].Name, MapLumpNames[j], 8) != 0)

1
wad.h
View File

@ -32,6 +32,7 @@ public:
~FWadReader ();
bool IsIWAD () const;
bool isUDMF(int lump) const;
int FindLump (const char *name, int index=0) const;
int FindMapLump (const char *name, int map) const;
int FindGLLump (const char *name, int glheader) const;

View File

@ -66,6 +66,7 @@ typedef uint32_t angle_t;
angle_t PointToAngle (fixed_t x, fixed_t y);
static const DWORD NO_MAP_INDEX = 0xffffffff;
static const WORD NO_INDEX = 0xffff;
static const angle_t ANGLE_MAX = 0xffffffff;
static const DWORD DWORD_MAX = 0xffffffff;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="zdbsp_vs2005"
ProjectGUID="{E628034A-AE64-43B5-8CF4-668D07041C35}"
RootNamespace="zdbsp_vs2005"
@ -364,6 +364,14 @@
RelativePath=".\processor.cpp"
>
</File>
<File
RelativePath=".\processor_udmf.cpp"
>
</File>
<File
RelativePath=".\sc_man.cpp"
>
</File>
<File
RelativePath=".\view.cpp"
>
@ -402,6 +410,10 @@
RelativePath=".\resource.h"
>
</File>
<File
RelativePath=".\sc_man.h"
>
</File>
<File
RelativePath=".\tarray.h"
>