home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MegaDoom Adventures
/
PMWMEGADOOM.iso
/
doom
/
creators
/
ibsp101s
/
savebsp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-10
|
19KB
|
809 lines
/* savebsp.m */
#include "idbsp.h"
/*
id secstore_i;
id mapvertexstore_i;
id subsecstore_i;
id maplinestore_i;
id nodestore_i;
id mapthingstore_i;
id ldefstore_i;
id sdefstore_i;
*/
STORAGE *secstore_i;
STORAGE *mapvertexstore_i;
STORAGE *subsecstore_i;
STORAGE *maplinestore_i;
STORAGE *nodestore_i;
STORAGE *mapthingstore_i;
STORAGE *ldefstore_i;
STORAGE *sdefstore_i;
/*
===============================================================================
the output functions byte swap and write lumps
===============================================================================
*/
/*
================
=
= WriteStorage
=
================
*/
/*void WriteStorage (char *name, id store, int esize) */
void WriteStorage(char *name, STORAGE * store, int esize)
{
int count,
len;
/* count = [store count]; */
count = store -> count;
len = esize * count;
/* [wad_i addName: name data:[store elementAt:0] size:len]; */
addName(name, store -> data, len);
printf("%s (%i): %i\n", name, count, len);
}
/*
=================
=
= OutputSectors
=
=================
*/
void OutputSectors(void)
{
int i,
count;
mapsector_t *p;
/*
count = [secstore_i count];
p = [secstore_i elementAt:0];
*/
count = secstore_i -> count;
p = secstore_i -> data;
/*
for (i=0 ; i<count ; i++, p++)
{
p->floorheight = SHORT(p->floorheight);
p->ceilingheight = SHORT(p->ceilingheight);
p->lightlevel = SHORT(p->lightlevel);
p->special = SHORT(p->special);
p->tag = SHORT(p->tag);
}
*/
WriteStorage("sectors", secstore_i, sizeof(mapsector_t));
}
/*
=================
=
= OutputSegs
=
=================
*/
void OutputSegs(void)
{
int i,
count;
mapseg_t *p;
/*
count = [maplinestore_i count];
p = [maplinestore_i elementAt:0];
*/
count = maplinestore_i -> count;
p = maplinestore_i -> data;
/*
for (i=0 ; i<count ; i++, p++)
{
p->v1 = SHORT(p->v1);
p->v2 = SHORT(p->v2);
p->angle = SHORT(p->angle);
p->linedef = SHORT(p->linedef);
p->side = SHORT(p->side);
p->offset = SHORT(p->offset);
}
*/
WriteStorage("segs", maplinestore_i, sizeof(mapseg_t));
}
/*
=================
=
= OutputSubsectors
=
=================
*/
void OutputSubsectors(void)
{
int i,
count;
mapsubsector_t *p;
/*
count = [subsecstore_i count];
p = [subsecstore_i elementAt:0];
*/
count = subsecstore_i -> count;
p = subsecstore_i -> data;
/*
for (i=0 ; i<count ; i++, p++)
{
p->numsegs = SHORT(p->numsegs);
p->firstseg = SHORT(p->firstseg);
}
*/
WriteStorage("ssectors", subsecstore_i, sizeof(mapsubsector_t));
}
/*
=================
=
= OutputVertexes
=
=================
*/
void OutputVertexes(void)
{
int i,
count;
mapvertex_t *p;
/*
count = [mapvertexstore_i count];
p = [mapvertexstore_i elementAt:0];
*/
count = mapvertexstore_i -> count;
p = mapvertexstore_i -> data;
/*
for (i=0 ; i<count ; i++, p++)
{
p->x = SHORT(p->x);
p->y = SHORT(p->y);
}
*/
WriteStorage("vertexes", mapvertexstore_i, sizeof(mapvertex_t));
}
/*
=================
=
= OutputThings
=
=================
*/
void OutputThings(void)
{
int i,
count;
mapthing_t *p;
/*
count = [mapthingstore_i count];
p = [mapthingstore_i elementAt:0];
*/
count = mapthingstore_i -> count;
p = mapthingstore_i -> data;
/*
for (i=0 ; i<count ; i++, p++)
{
p->x = SHORT(p->x);
p->y = SHORT(p->y);
p->angle = SHORT(p->angle);
p->type = SHORT(p->type);
p->options = SHORT(p->options);
}
*/
WriteStorage("things", mapthingstore_i, sizeof(mapthing_t));
}
/*
=================
=
= OutputLineDefs
=
=================
*/
void OutputLineDefs(void)
{
int i,
count;
maplinedef_t *p;
/*
count = [ldefstore_i count];
p = [ldefstore_i elementAt:0];
*/
count = ldefstore_i -> count;
p = ldefstore_i -> data;
#if 0
for (i = 0; i < count; i++, p++)
{
p -> v1 = SHORT(p -> v1);
p -> v2 = SHORT(p -> v2);
/* some ancient version of DoomEd left ML_MAPPED flags in some of the levels */
p -> flags = SHORT(p -> flags & ~ML_MAPPED);
p -> special = SHORT(p -> special);
p -> tag = SHORT(p -> tag);
p -> sidenum[0] = SHORT(p -> sidenum[0]);
p -> sidenum[1] = SHORT(p -> sidenum[1]);
}
#endif
WriteStorage("linedefs", ldefstore_i, sizeof(maplinedef_t));
}
/*
=================
=
= OutputSideDefs
=
=================
*/
void OutputSideDefs(void)
{
int i,
count;
mapsidedef_t *p;
/*
count = [sdefstore_i count];
p = [sdefstore_i elementAt:0];
*/
count = sdefstore_i -> count;
p = sdefstore_i -> data;
/*
for (i=0 ; i<count ; i++, p++)
{
p->textureoffset = SHORT(p->textureoffset);
p->rowoffset = SHORT(p->rowoffset);
p->sector = SHORT(p->sector);
}
*/
WriteStorage("sidedefs", sdefstore_i, sizeof(mapsidedef_t));
}
/*
=================
=
= OutputNodes
=
=================
*/
void OutputNodes(void)
{
int i,
j,
count;
mapnode_t *p;
/*
count = [nodestore_i count];
p = [nodestore_i elementAt:0];
*/
count = nodestore_i -> count;
p = nodestore_i -> data;
/*
for (i=0 ; i<count ; i++, p++)
{
for (j=0 ; j<sizeof(mapnode_t)/2 ; j++)
((short *)p)[j] = SHORT(((short *)p)[j]);
}
*/
WriteStorage("nodes", nodestore_i, sizeof(mapnode_t));
}
/*
===============================================================================
PROCESSING
===============================================================================
*/
/*
=================
=
= UniqueVertex
=
= Returns the vertex number, adding a new vertex if needed
=================
*/
int UniqueVertex(int x, int y)
{
int i,
count;
mapvertex_t mv,
*mvp;
mv.x = x;
mv.y = y;
/* see if an identical vertex already exists */
/*
count = [mapvertexstore_i count];
mvp = [mapvertexstore_i elementAt:0];
*/
count = mapvertexstore_i -> count;
mvp = mapvertexstore_i -> data;
for (i = 0; i < count; i++, mvp++)
if (mvp -> x == mv.x && mvp -> y == mv.y)
return i;
/* [mapvertexstore_i addElement: &mv]; */
memcpy((mapvertex_t *) mapvertexstore_i -> data + mapvertexstore_i -> count, &mv,
sizeof(mapvertex_t));
mapvertexstore_i -> count += 1;
mapvertexstore_i -> data = (mapvertex_t *) realloc(mapvertexstore_i -> data,
sizeof(mapvertex_t) * (mapvertexstore_i -> count + 1));
return count;
}
/*
=============================================================================
*/
float bbox[4];
/*
=================
=
= AddPointToBBox
=
=================
*/
void AddPointToBBox(NXPoint * pt)
{
if (pt -> x < bbox[BOXLEFT])
bbox[BOXLEFT] = pt -> x;
if (pt -> x > bbox[BOXRIGHT])
bbox[BOXRIGHT] = pt -> x;
if (pt -> y > bbox[BOXTOP])
bbox[BOXTOP] = pt -> y;
if (pt -> y < bbox[BOXBOTTOM])
bbox[BOXBOTTOM] = pt -> y;
}
/*
=================
=
= ProcessLines
=
= Adds the lines in a subsector to the mapline storage
=================
*/
/* void ProcessLines (id store_i) */
void ProcessLines(STORAGE * store_i)
{
int i,
count;
line_t *wline;
mapseg_t line;
short angle;
float fangle;
bbox[BOXLEFT] = INT_MAX;
bbox[BOXRIGHT] = INT_MIN;
bbox[BOXTOP] = INT_MIN;
bbox[BOXBOTTOM] = INT_MAX;
/* count = [store_i count]; */
count = store_i -> count;
for (i = 0; i < count; i++)
{
/* wline = [store_i elementAt: i]; */
wline = (line_t *) store_i -> data + i;
if (wline -> grouped)
printf("ERROR: line regrouped\n");
wline -> grouped = true;
memset(&line, 0, sizeof(line));
AddPointToBBox(&wline -> p1);
AddPointToBBox(&wline -> p2);
line.v1 = UniqueVertex(wline -> p1.x, wline -> p1.y);
line.v2 = UniqueVertex(wline -> p2.x, wline -> p2.y);
line.linedef = wline -> linedef;
line.side = wline -> side;
line.offset = wline -> offset;
fangle = atan2(wline -> p2.y - wline -> p1.y, wline -> p2.x - wline -> p1.x);
angle = (short)(fangle / (PI * 2) * 0x10000);
line.angle = angle;
/* [maplinestore_i addElement: &line]; */
memcpy((mapseg_t *) maplinestore_i -> data + maplinestore_i -> count, &line,
sizeof(line));
maplinestore_i -> count += 1;
maplinestore_i -> data = (mapseg_t *) realloc(maplinestore_i -> data,
sizeof(mapseg_t) * (maplinestore_i -> count + 1));
}
}
/*
=================
=
= ProcessSubsector
=
=================
*/
/* int ProcessSubsector (id wmaplinestore_i) */
int ProcessSubsector(STORAGE * wmaplinestore_i)
{
int count;
worldline_t *linedef;
line_t *wline;
mapsubsector_t sub;
memset(&sub, 0, sizeof(sub));
/* count = [wmaplinestore_i count]; */
count = wmaplinestore_i -> count;
if (count < 1)
Error("ProcessSubsector: count = %i", count);
/* wline = [wmaplinestore_i elementAt: 0]; */
wline = wmaplinestore_i -> data;
/* linedef = [linestore_i elementAt: wline->linedef]; */
linedef = (worldline_t *) linestore_i -> data + wline -> linedef;
sub.numsegs = count;
/* sub.firstseg = [maplinestore_i count]; */
sub.firstseg = maplinestore_i -> count;
ProcessLines(wmaplinestore_i);
/* add the new subsector
[subsecstore_i addElement: &sub];
*/
memcpy((mapsubsector_t *) subsecstore_i -> data + subsecstore_i -> count, &sub,
sizeof(mapsubsector_t));
subsecstore_i -> count += 1;
subsecstore_i -> data = (mapsubsector_t *) realloc(subsecstore_i -> data,
sizeof(mapsubsector_t) * (subsecstore_i -> count + 1));
/* return [subsecstore_i count]-1; */
return subsecstore_i -> count - 1;
}
/*
=================
=
= ProcessNode
=
=================
*/
int ProcessNode(bspnode_t * node, short *totalbox)
{
short subbox[2][4];
int i,
r;
mapnode_t mnode;
memset(&mnode, 0, sizeof(mnode));
if (node -> lines_i) /* NF_SUBSECTOR flags a subsector */
{
r = ProcessSubsector(node -> lines_i);
for (i = 0; i < 4; i++)
totalbox[i] = bbox[i];
return r | NF_SUBSECTOR;
}
mnode.x = node -> divline.pt.x;
mnode.y = node -> divline.pt.y;
mnode.dx = node -> divline.dx;
mnode.dy = node -> divline.dy;
r = ProcessNode(node -> side[0], subbox[0]);
mnode.children[0] = r;
for (i = 0; i < 4; i++)
mnode.bbox[0][i] = subbox[0][i];
r = ProcessNode(node -> side[1], subbox[1]);
mnode.children[1] = r;
for (i = 0; i < 4; i++)
mnode.bbox[1][i] = subbox[1][i];
totalbox[BOXLEFT] = MIN(subbox[0][BOXLEFT], subbox[1][BOXLEFT]);
totalbox[BOXTOP] = MAX(subbox[0][BOXTOP], subbox[1][BOXTOP]);
totalbox[BOXRIGHT] = MAX(subbox[0][BOXRIGHT], subbox[1][BOXRIGHT]);
totalbox[BOXBOTTOM] = MIN(subbox[0][BOXBOTTOM], subbox[1][BOXBOTTOM]);
/* [nodestore_i addElement: &mnode]; */
memcpy((mapnode_t *) nodestore_i -> data + nodestore_i -> count, &mnode, sizeof(mapnode_t));
nodestore_i -> count += 1;
nodestore_i -> data = (mapnode_t *) realloc(nodestore_i -> data,
sizeof(mapnode_t) * (nodestore_i -> count + 1));
/* return [nodestore_i count] - 1; */
return nodestore_i -> count - 1;
}
/*
=================
=
= ProcessNodes
=
= Recursively builds the nodes, subsectors, and line lists,
= then writes the lumps
=================
*/
void ProcessNodes(void)
{
short worldbounds[4];
/*
subsecstore_i = [[Storage alloc]
initCount: 0
elementSize: sizeof(mapsubsector_t)
description: NULL];
maplinestore_i = [[Storage alloc]
initCount: 0
elementSize: sizeof(mapseg_t)
description: NULL];
nodestore_i = [[Storage alloc]
initCount: 0
elementSize: sizeof(mapnode_t)
description: NULL];
*/
subsecstore_i = (STORAGE *) SafeMalloc(sizeof(STORAGE));
subsecstore_i -> data = (mapsubsector_t *) SafeMalloc(sizeof(mapsubsector_t));
subsecstore_i -> count = 0;
subsecstore_i -> size = sizeof(mapsubsector_t);
maplinestore_i = (STORAGE *) SafeMalloc(sizeof(STORAGE));
maplinestore_i -> data = (mapseg_t *) SafeMalloc(sizeof(mapseg_t));
maplinestore_i -> count = 0;
maplinestore_i -> size = sizeof(mapseg_t);
nodestore_i = (STORAGE *) SafeMalloc(sizeof(STORAGE));
nodestore_i -> data = (mapnode_t *) SafeMalloc(sizeof(mapnode_t));
nodestore_i -> count = 0;
nodestore_i -> size = sizeof(mapnode_t);
ProcessNode(startnode, worldbounds);
}
/*
=================
=
= ProcessThings
=
=================
*/
void ProcessThings(void)
{
worldthing_t *wt;
mapthing_t mt;
int count;
/*
mapthingstore_i = [[Storage alloc]
initCount: 0
elementSize: sizeof(mapthing_t)
description: NULL];
*/
mapthingstore_i = (STORAGE *) SafeMalloc(sizeof(STORAGE));
mapthingstore_i -> data = (mapthing_t *) SafeMalloc(sizeof(mapthing_t));
mapthingstore_i -> count = 0;
mapthingstore_i -> size = sizeof(mapthing_t);
/*
count = [thingstore_i count];
wt = [thingstore_i elementAt: 0];
*/
count = thingstore_i -> count;
wt = thingstore_i -> data;
while (count--)
{
memset(&mt, 0, sizeof(mt));
mt.x = wt -> origin.x;
mt.y = wt -> origin.y;
mt.angle = wt -> angle;
mt.type = wt -> type;
mt.options = wt -> options;
/* [mapthingstore_i addElement: &mt]; */
memcpy((mapthing_t *) mapthingstore_i -> data + mapthingstore_i -> count, &mt,
sizeof(mapthing_t));
mapthingstore_i -> count += 1;
mapthingstore_i -> data = (mapthing_t *) realloc(mapthingstore_i -> data,
sizeof(mapthing_t) * (mapthingstore_i -> count + 1));
wt++;
}
}
/*
=============================================================================
*/
/*
==================
=
= ProcessSidedef
=
==================
*/
int ProcessSidedef(worldside_t * ws)
{
mapsidedef_t ms;
ms.textureoffset = ws -> firstcollumn;
ms.rowoffset = ws -> firstrow;
memcpy(ms.toptexture, ws -> toptexture, 8);
memcpy(ms.bottomtexture, ws -> bottomtexture, 8);
memcpy(ms.midtexture, ws -> midtexture, 8);
ms.sector = ws -> sector;
/* [sdefstore_i addElement: &ms]; */
memcpy((mapsidedef_t *) sdefstore_i -> data + sdefstore_i -> count, &ms, sizeof(mapsidedef_t));
sdefstore_i -> count += 1;
sdefstore_i -> data = (mapsidedef_t *) realloc(sdefstore_i -> data,
sizeof(mapsidedef_t) * (sdefstore_i -> count + 1));
/* return [sdefstore_i count]-1; */
return sdefstore_i -> count - 1;
}
/*
==================
=
= ProcessLineSideDefs
=
= Must be called after BuildSectors
==================
*/
void ProcessLineSideDefs(void)
{
int i,
count;
maplinedef_t ld;
worldline_t *wl;
/*
mapvertexstore_i = [[Storage alloc]
initCount: 0
elementSize: sizeof(mapvertex_t)
description: NULL];
ldefstore_i = [[Storage alloc]
initCount: 0
elementSize: sizeof(maplinedef_t)
description: NULL];
sdefstore_i = [[Storage alloc]
initCount: 0
elementSize: sizeof(mapsidedef_t)
description: NULL];
*/
mapvertexstore_i = (STORAGE *) SafeMalloc(sizeof(STORAGE));
mapvertexstore_i -> data = (mapvertex_t *) SafeMalloc(sizeof(mapvertex_t));
mapvertexstore_i -> count = 0;
mapvertexstore_i -> size = sizeof(mapvertex_t);
ldefstore_i = (STORAGE *) SafeMalloc(sizeof(STORAGE));
ldefstore_i -> data = (maplinedef_t *) SafeMalloc(sizeof(maplinedef_t));
ldefstore_i -> count = 0;
ldefstore_i -> size = sizeof(maplinedef_t);
sdefstore_i = (STORAGE *) SafeMalloc(sizeof(STORAGE));
sdefstore_i -> data = (mapsidedef_t *) SafeMalloc(sizeof(mapsidedef_t));
sdefstore_i -> count = 0;
sdefstore_i -> size = sizeof(mapsidedef_t);
/*
count = [linestore_i count];
wl = [linestore_i elementAt:0];
*/
count = linestore_i -> count;
wl = linestore_i -> data;
for (i = 0; i < count; i++, wl++)
{
ld.v1 = UniqueVertex(wl -> p1.x, wl -> p1.y);
ld.v2 = UniqueVertex(wl -> p2.x, wl -> p2.y);
ld.flags = wl -> flags;
ld.special = wl -> special;
ld.tag = wl -> tag;
ld.sidenum[0] = ProcessSidedef(&wl -> side[0]);
if (wl -> flags & ML_TWOSIDED)
ld.sidenum[1] = ProcessSidedef(&wl -> side[1]);
else
ld.sidenum[1] = -1;
/* [ldefstore_i addElement: &ld]; */
memcpy((maplinedef_t *) ldefstore_i -> data + ldefstore_i -> count, &ld, sizeof(maplinedef_t));
ldefstore_i -> count += 1;
ldefstore_i -> data = (maplinedef_t *) realloc(ldefstore_i -> data,
sizeof(maplinedef_t) * (ldefstore_i -> count + 1));
}
}
/*
=============================================================================
*/
/*
==================
=
= SaveDoomMap
=
==================
*/
void SaveDoomMap(void)
{
printf("\nBuildSectordefs\n");
BuildSectordefs();
printf("ProcessThings\n");
ProcessThings();
printf("ProcessLineSideDefs\n");
ProcessLineSideDefs();
printf("ProcessNodes\n");
ProcessNodes();
printf("ProcessSectors\n");
ProcessSectors();
printf("\nProcessConnections\n");
ProcessConnections();
/* all processing is complete, write everything out */
OutputThings();
OutputLineDefs();
OutputSideDefs();
OutputVertexes();
OutputSegs();
OutputSubsectors();
OutputNodes();
OutputSectors();
OutputConnections();
}