/* 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 ; ifloorheight = 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 ; iv1 = 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 ; inumsegs = 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 ; ix = 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 ; ix = 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 ; iv1 = 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 ; itextureoffset = 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 ; icount; mvp = mapvertexstore_i->data; for (i=0 ; ix == 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 ; idata + 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 ; ip1.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 (); }