/*
			===== IDBSP - id Software's BSP builder for DOOM ====
	DOS port (c) 1994 Ron Rossbach (ej070@cleveland.freenet.edu)

	File IDBSP.H
		Main header file for the IDBSP program

	Revisions:

		1)	Changed the worldside_t typedef to include a pointer to the sector
				the SIDEDEF helps to enclose, rather than including a complete (and
				redundant) copy of the sector information. (v1.1)

		2)	Changed the sectordef_t typedef to include a field to indicate if
				the sector has been referenced in the final SECTORS resource for the
				PWAD.	This helps prevent duplicate entries in the SECTORS resource.
				(v1.1)

		3)	Move all typedefs from .C modules into this header file.  Include
				prototypes for all functions in all modules.  (v1.1)
*/

#ifndef __IDBSP__
#define __IDBSP__

#define MAX(a,b) ( (a) > (b) ) ? (a) : (b)
#define MIN(a,b) ( (a) < (b) ) ? (a) : (b)

/*
	typedef to replace "storage" object from id' original Objective-C source
*/
typedef struct
{
	int		count;
	int 	size;
	void 	*data;
} STORAGE;

#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <limits.h>
#include <float.h>
#include "doomdata.h"
#include "wadfile.h"

/*
	The following macros (SHORT and LONG) were used in id's original source,
	in various incarnations, to provide byte-swapping when needed for saving
	WAD files across difference machine architectures (big- vs. little-endian)
	We don't need them, since we're staying within a single architecture.
	Definitions are commented-out for posterity.
*/
/*
#define SHORT(x)        NXSwapLittleShortToHost((short)x)
#define LONG(x)         NXSwapLittleLongToHost((long)x)
*/
/*
#define SHORT(x) LittleShort((short)x)
#define LONG(x)  LittleLong((long)x)
*/
/*
#define SHORT(x) BigShort((short)x)
#define LONG(x) BigLong((long)x)
*/
/*
#define SHORT(x) (short)(x)
#define LONG(x) (long)(x)
*/

#define PI   					3.141592657
#define MAXVERTEX   	8192
#define MAXTOUCHSECS  16
#define MAXSECTORS    2048
#define MAXSUBSECTORS 2048

/*
	The following typedefs replace types originally supplied by the NextStep
	application	development kits.....NXIntPoint is used only in the THING
	typedef.
	In id's original source, THINGS were read with floats for origin, and
	aligned on 16x16 grids before being stored in the WAD with ints for origin.
	We dispense with the alignment, so don't bother reading THINGS with
	floats for origin.
*/
typedef struct
{
	float 	x;
	float 	y;
} NXPoint;

typedef struct
{
	int 	x;
	int 	y;
} NXIntPoint;

typedef struct
{
	float 	width;
	float 	height;
} NXSize;

typedef struct
{
	NXPoint origin;
	NXSize 	size;
} NXRect;

/*
	The following types are id's "world types"; i.e. formats for storing map
	data interally, for calculations.  Map data stored in the following types
	is converted to WAD file types prior to being written to the WAD.
*/

typedef struct
{
	int 		floorheight, ceilingheight;
	char  	floorflat[9], ceilingflat[9];
	int     lightlevel;
	int     special, tag;
/*	boolean	sectoronlist;	 */		/* Added in v1.1 to help sector handling */
} sectordef_t;

typedef struct
{
	int			firstrow;
	int     firstcollumn;
	char    toptexture[9];
	char    bottomtexture[9];
	char    midtexture[9];
/*sectordef_t     sectordef;  */     /* on the viewers ("right") side */
	sectordef_t		*sectordef;		/* Changed in v1.1 to help sector handling */
	int     			sector;       /* only used when saving doom map */
} worldside_t;

typedef struct
{
	NXPoint     	p1, p2;
	int       		special, tag;
	int         	flags;
	worldside_t   side[2];
} worldline_t;

#define ML_BLOCKMOVE    1
#define ML_TWOSIDED     4   /* backside will not be present at all 	*/
														/* if not two sided 										*/

typedef struct
{
/*				NXPoint         origin; */
	NXIntPoint 	origin;		 /* Added in v1.1 to remove THING alignment */
	int         angle;
	int         type;
	int         options;
	int         area;
} worldthing_t;


/*
	The following types are used during BSP calculation
*/

typedef struct
{
	NXPoint pt;
	float   dx,dy;
}	divline_t;

typedef struct bspstruct_s
{
/* id lines_i; */
	STORAGE 		*lines_i;				/* if non NULL, the node is 		*/
	divline_t   divline;        /* terminal and has no children */
	float       bbox[4];
	struct  		bspstruct_s             *side[2];
} bspnode_t;


typedef struct
{
	NXPoint 	p1, p2;
	int       linedef, side, offset;
	boolean   grouped;                 /* internal error check */
} line_t;

/*
	The following typedefs are originally from the SAVECNCT.C module, which
	handled the REJECT resource building....
*/
enum {si_north, si_east, si_south, si_west};

typedef struct
{
	int		x,y;
} bpoint_t;

typedef struct
{
	int		xl, xh, yl, yh;
} bbox_t;

typedef struct
{
	bpoint_t	p1, p2;
} bline_t;

typedef struct
{
	int			numpoints;
	bbox_t		bounds;
	bpoint_t	*points;
} bchain_t;

typedef struct
{
	int		x,y;
	int		dx,dy;
} bdivline_t;

/*
	The following section contains functions prototypes and global data
	declarations for each program module....
*/

/*
	Module IDBSP.C
*/
extern  WADFILE		wad_i;
extern 	boolean 	wadin, fullreject, preservebug, uniquesector, radius,
                  duplines, trace;
extern 	float 		pos_radius;
extern  int       sectopt;

void 		AddFromFile(char *resname, int size, char *fname);
void 		FreeGlobalStorage(void);
void 		DWDMain(FILE *pDWD);
void 		WADMain(FILE *pWAD);
void 		Error (char *error, ...);
void 		*SafeMalloc(unsigned size);
void 		*SafeCalloc(unsigned num, unsigned size);
void		*SafeRealloc(void *p, unsigned size);

/*
	Module DOOMLOAD.C
*/
extern  STORAGE 		*linestore_i, *thingstore_i;
extern  sectordef_t *sectorlist;
extern 	int 				sectorlistcount;

typedef struct
{
	float   left, right, top, bottom;
} fbbox_t;

void 					LoadDoomMap(FILE *file);
void 					LoadWADMap(FILE *file, lumpinfo_t *lumps);
void 					ReadWADLine(FILE *f, worldline_t *wl, mapvertex_t *verts,
													mapsidedef_t *sides);
void 					ReadWADThing(FILE *f, worldthing_t *t);
void 					ReadWADSector(FILE *f, sectordef_t *s);
worldline_t 	*ReadLine(FILE *file, worldline_t *line);
void 					ReadSector(FILE *file, sectordef_t *s);
worldthing_t 	*ReadThing(FILE *file, worldthing_t *thing);
void 					BBoxFromPoints(fbbox_t *box, NXPoint *p1, NXPoint *p2);
boolean 			LineOverlaid(worldline_t *line);

/*
	Module DRAWING.C
*/
extern  STORAGE		*window_i, *view_i;
extern  float   	scale;
extern  NXRect  	worldbounds;

void 		EraseWindow(void);
void 		DrawMap(void);
void 		DrawLineStore(STORAGE *lines_i);
void 		DrawDivLine (divline_t *div);
void 		DrawLineDef (maplinedef_t *ld);
void 		IDRectFromPoints(NXRect *rect, NXPoint const *p1, NXPoint const *p2 );
void 		IDEnclosePoint(NXRect *rect, NXPoint const *point);
void 		BoundLineStore(STORAGE *lines_i,NXRect *r);

/*
	Module BUILDBSP.C
*/
extern  int    			cuts;         /* number of new lines generated by BSP */
																	/* process 															*/
extern  bspnode_t   *startnode;

void 			BuildBSP(void);
void    	DivlineFromWorldline(divline_t *d, line_t *w);
int     	PointOnSide(NXPoint *p, divline_t *l);
int 			sign(float i);
boolean 	LineOnSide(line_t *wl, divline_t *bl);
float 		InterceptVector(divline_t *v2, divline_t *v1);
float 		round(float x);
line_t  	*CutLine(line_t *wl, divline_t *bl);
int 			EvaluateSplit(STORAGE *lines_i, line_t *spliton, int bestgrade);
int     	PointOnSide(NXPoint *p, divline_t *l);
bspnode_t *BSPList(STORAGE *lines_i);
void 			MakeSegs(void);
void 			ExecuteSplit(STORAGE *lines_i, line_t *spliton, STORAGE *frontlist_i,
												STORAGE *backlist_i);

/*
	Module SAVEBSP.C
*/
extern  STORAGE 	*secstore_i;
extern  STORAGE 	*mapvertexstore_i;
extern  STORAGE 	*subsecstore_i;
extern  STORAGE 	*maplinestore_i;
extern  STORAGE 	*nodestore_i;
extern  STORAGE 	*mapthingstore_i;
extern  STORAGE 	*ldefstore_i;
extern  STORAGE 	*sdefstore_i;

void		SaveDoomMap(void);
void 		WriteStorage(char *name, STORAGE *store, int esize);
void 		OutputSectors(void);
void 		OutputSegs(void);
void 		OutputSubsectors(void);
void 		OutputVertexes(void);
void 		OutputThings(void);
void 		OutputLineDefs(void);
void 		OutputSideDefs(void);
void 		OutputNodes(void);
int 		UniqueVertex(int x, int y);
void 		AddPointToBBox(NXPoint *pt);
void 		ProcessLines(STORAGE *store_i);
int 		ProcessSubsector(STORAGE *wmaplinestore_i);
int 		ProcessNode(bspnode_t *node, short *totalbox);
void 		ProcessNodes(void);
void 		ProcessThings(void);
int 		ProcessSidedef(worldside_t *ws);
void 		ProcessLineSideDefs(void);

/*
	Module SAVEBLCK.C
*/
void			SaveBlocks(void);
boolean 	LineContact (worldline_t *wl);
void 			GenerateBlockList(int x, int y);

/*
	Module SAVESCTR.C
*/
extern	STORAGE		*sectorsavelist; 	/* Added for check for mem overwrite bug */

void		ProcessSectors(void);
void 		BuildSectordefs(void);
void 		RecursiveGroupSubsector(int ssnum);
void 		AddSubsectorToVertex(int subnum, int vertex);
int 		UniqueSector(sectordef_t *def);

/*
	Module SAVECNCT.C
*/
void 		ProcessConnections(void);
void 		OutputConnections(void);
void 		ClearBBox(bbox_t *box);
void 		AddToBBox(bbox_t *box, int x, int y);
int			BPointOnSide(bpoint_t *pt, bdivline_t *l);
void 		DrawBBox(bbox_t *box);
void 		DrawDivline(bdivline_t *li);
void 		DrawBChain(bchain_t *ch);
boolean DoesChainBlock(bchain_t *chain);
void 		BuildConnections(void);
void 		BuildBlockingChains(void);

#endif	/* __IDBSP__	*/

