// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.
// This file has been modified from Ken Silverman's original release

#include <fcntl.h>
#include <io.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <string.h>
#include <dos.h>
#include "pragmas.h"

#define MAXWADS 4096
#define MAXPOINTS 8192
#define MAXLINES 8192
#define MAXSIDES 8192
#define MAXSECTS 2048
#define MAXTHINGS 4096
#define MAXTEXTS 1024
#define MAXPNAMES 1024
#define MAXTHINGTYPES 3072

#define MAXSECTORS 1024
#define MAXWALLS 8192
#define MAXSPRITES 4096

long asm;
static unsigned short sqrtable[2048];

static char iwadata[MAXWADS][9];
static long inumwads, iwadstart, iwadplc[MAXWADS], iwadlen[MAXWADS];

static char pwadata[MAXWADS][9];
static long pnumwads, pwadstart, pwadplc[MAXWADS], pwadlen[MAXWADS];

static short px[MAXPOINTS], py[MAXPOINTS];

typedef struct
{
	short p1, p2, flags, special, tag;
	short side1, side2;   //If side2 = -1, no left
} linedeftype;
static linedeftype line[MAXLINES];

typedef struct
{
	short xoffset, yoffset;
	char uppertexture[8], lowertexture[8], middletexture[8];
	short sect;
} sidedeftype;
static sidedeftype side[MAXSIDES];
static short sidetoppic[MAXSIDES], sidebotpic[MAXSIDES], sidemidpic[MAXSIDES];

typedef struct
{
	short floorz, ceilingz;
	char floorpic[8], ceilingpic[8];
	short shade, type, tag;
} secttype;
static secttype sect[MAXSECTS];
static short sectspri[MAXSECTS][8];

typedef struct
{
	short x, y, ang, type, options;
} thingtype;
static thingtype thing[MAXTHINGS];

static char textname[MAXTEXTS][9];
static long textoffs[MAXTEXTS];
static short textpname[MAXTEXTS];

static char pname[MAXPNAMES][9];

	//Build map-linking variables
static short picindex[MAXPOINTS], linindex[MAXPOINTS];
static short wx[MAXPOINTS], wy[MAXPOINTS], wx2[MAXPOINTS], wy2[MAXPOINTS];
static short point2[MAXPOINTS], slist[MAXPOINTS], sectorofwall[MAXPOINTS];

typedef struct
{
	short wallptr, wallnum;
	long ceilingz, floorz;
	short ceilingstat, floorstat;
	short ceilingpicnum, ceilingheinum;
	signed char ceilingshade;
	char ceilingpal, ceilingxpanning, ceilingypanning;
	short floorpicnum, floorheinum;
	signed char floorshade;
	char floorpal, floorxpanning, floorypanning;
	char visibility, filler;
	short lotag, hitag, extra;
} sectortype;

typedef struct
{
	long x, y;
	short point2, nextwall, nextsector, cstat;
	short picnum, overpicnum;
	signed char shade;
	char pal, xrepeat, yrepeat, xpanning, ypanning;
	short lotag, hitag, extra;
} walltype;

typedef struct
{
	long x, y, z;
	short cstat, picnum;
	signed char shade;
	char pal, clipdist, filler;
	unsigned char xrepeat, yrepeat;
	signed char xoffset, yoffset;
	short sectnum, statnum;
	short ang, owner, xvel, yvel, zvel;
	short lotag, hitag, extra;
} spritetype;

static sectortype sector[MAXSECTORS];
static walltype wall[MAXWALLS];
static spritetype sprite[MAXSPRITES];

static char tempbuf[16384];
static short tempshort[4096];


	//SCRIPT parsing variables:
static char scriptname[16];
static char filebuf[16384];
static long filhandle, filpos, fileng;

static char definemode = 0, define[16384], *defineptr[4096];
static long defineval[16384], definecnt = 0, numdefines = 0;

static char thingtypemode = 0;
static long thingnum[1024], thingnum2[1024], thingoff[1024], numthings = 0;
static short thingfield[4096];
static char thingop[4096];
static long thingval[4096], thingopnum = 0;

static char texturelookupmode = 0;
static short texturelookup[4096];

static char tagtypemode = 0;
static long tagnum[1024], tagnum2[1024], tagoff[1024], numtags = 0;
static char tagstruct[4096], tagop[4096];
static short tagfield[4096];
static long tagval[4096], tagopnum = 0;

static char sectypemode = 0;
static long secnum[1024], secnum2[1024], secoff[1024], numsecs = 0;
static short secfield[4096];
static char secop[4096];
static long secval[4096], secopnum = 0;

#define THINGLISTNUM 123
static short thinglookup[MAXTHINGTYPES];
typedef struct { short num; char name[8]; } thinglisttype;
static thinglisttype thinglist[THINGLISTNUM] =
{1,"PLAYA1",2,"PLAYA1",3,"PLAYA1",4,"PLAYA1",11,"PLAYA1",14,"",3004,"POSSA1",
84,"SSWVA1",9,"SPOSA1",65,"CPOSA1",3001,"TROOA1",3002,"SARGA1",58,"SARGA1",
3006,"SKULA1",3005,"HEADA1",69,"BOS2A1C1",3003,"BOSSA1",68,"BSPIA1D1",
71,"PAINA1",66,"SKELA1D1",67,"FATTA1",64,"VILEA1D1",7,"SPIDA1D1",16,"CYBRA1",
88,"",89,"",87,"",2005,"CSAWA0",2001,"SHOTA0",82,"SGN2A0",2002,"MGUNA0",
2003,"LAUNA0",2004,"PLASA0",2006,"BFUGA0",2007,"CLIPA0",2008,"SHELA0",
2010,"ROCKA0",2047,"CELLA0",2048,"AMMOA0",2049,"SBOXA0",2046,"BROKA0",
17,"CELPA0",8,"BPAKA0",2011,"STIMA0",2012,"MEDIA0",2014,"BON1A0",
2015,"BON2A0",2018,"ARM1A0",2019,"ARM2A0",83,"MEGAA0",2013,"SOULA0",
2022,"PINVA0",2023,"PSTRA0",2024,"PINSA0",2025,"SUITA0",2026,"PMAPA0",
2045,"PVISA0",5,"BKEYA0",40,"BSKUA0",13,"RKEYA0",38,"RSKUA0",6,"YKEYA0",
39,"YSKUA0",2035,"BAR1A0",72,"KEENA0",48,"ELECA0",30,"COL1A0",32,"COL3A0",
31,"COL2A0",36,"COL5A0",33,"COL4A0",37,"COL6A0",47,"SMITA0",43,"TRE1A0",
54,"TRE2A0",2028,"COLUA0",85,"TLMPA0",86,"TLP2A0",34,"CANDA0",35,"CBRAA0",
44,"TBLUA0",45,"TGRNA0",46,"TREDA0",55,"SMBTA0",56,"SMGTA0",57,"SMRTA0",
70,"FCANA0",41,"CEYEA0",42,"FSKUA0",49,"GOR1A0",63,"GOR1A0",50,"GOR2A0",
59,"GOR2A0",52,"GOR4A0",60,"GOR4A0",51,"GOR5A0",61,"GOR5A0",53,"HDB1A0",
62,"HDB2A0",73,"GOR3A0",74,"GOR3A0",75,"HDB3A0",76,"HDB4A0",77,"HDB5A0",
78,"HDB6A0",25,"POL1A0",26,"BBRNA0",27,"POL4A0",28,"POL2A0",29,"POL3A0",
10,"PLAYW0",12,"PLAYW0",24,"POB1A0",79,"POB2A0",80,"POB2A0",81,"BRS1A0",
15,"PLAYN0",18,"POSSL0",19,"SPOSL0",20,"TROOM0",21,"SARGN0",22,"HEADL0",
23,""};

#pragma aux ksqrtasm =\
	"mov asm, eax",\
	"fild dword ptr asm",\
	"fstp dword ptr asm",\
	"mov bl, byte ptr asm[3]",\
	"sub bl, 63+5",\
	"jge over2048",\
	"xor ebx, ebx",\
	"mov bx, sqrtable[eax*2]",\
	"jmp endksqrtasm",\
	"over2048: lea ecx, [ebx*2]",\
	"shr eax, cl",\
	"mov cl, bl",\
	"xor ebx, ebx",\
	"mov bx, sqrtable[eax*2]",\
	"shl ebx, cl",\
	"endksqrtasm: shr ebx, 10",\
	parm [eax]\
	value [ebx]\
	modify exact [eax ebx ecx]\

main(short argc, char **argv)
{
	char argstring[5][80];
	char iwadfil[80], pwadfil[80], doommap[16], buildmap[16], picstr[16];
	long w, numwads, numtexts, startnumtexts, danumtexts, numpnames;
	long x, y, z, zz, zzz, zzx, zx, cx, cy, gap, p, pp, i, j, k, l, offs;
	long dnumpoints, dnumlines, dnumsides, dnumsectors, dnumthings, good;
	long minx, maxx, miny, maxy, numsectors, numwalls, wadtype;
	long startnumwalls, l1, l2, startpoint2, dapoint2, area;
	long fil, ifil, pfil, x1, y1, x2, y2, startwall, endwall;
	long mapversion, posx, posy, posz, templong, cnt, boardwadindex;
	short ang, cursectnum;

	printf("Wad2Map!                                       Copyright 1995 by Ken Silverman\n");

	if ((argc < 3) || (argc > 5))
	{
		printf("Command line parameters: Wad2Map (PWADName) IWADName MapName (ScriptName)\n");
		printf("   Ex #1: wad2map c:\\doom\\doom.wad e1m1\n");
		printf("   Ex #2: wad2map c:\\doom\\doom.wad e1m1 kenbuild.txt\n");
		printf("   Ex #3: wad2map c:\\doom\\mypwad.wad c:\\doom\\doom.wad e1m1\n");
		printf("   Ex #4: wad2map c:\\doom\\mypwad.wad c:\\doom\\doom.wad e1m1 kenbuild.txt\n");
		exit(0);
	}

	for(i=1;i<argc;i++) strcpy(argstring[i],argv[i]);

	strcpy(iwadfil,argstring[1]);     //"c:\games\doom\doom.wad"
	if (strchr(iwadfil,'.') == 0) strcat(iwadfil,".wad");
	if ((ifil = open(iwadfil,O_BINARY|O_RDWR,S_IREAD)) == -1)
		{ printf("Could not find %s\n",iwadfil); exit(0); }

	read(ifil,&wadtype,4);
	if (wadtype == 0x44415749) wadtype = 0;       //IWAD
	else if (wadtype == 0x44415750) wadtype = 1;  //PWAD
	else { close(ifil); printf("Invalid WAD header\n"); exit(0); }

	strcpy(pwadfil,iwadfil); pfil = ifil;
	if (wadtype == 1)
	{
		strcpy(iwadfil,argstring[2]);
		if (strchr(iwadfil,'.') == 0) strcat(iwadfil,".wad");
		if ((ifil = open(iwadfil,O_BINARY|O_RDWR,S_IREAD)) == -1)
			{ close(pfil); printf("Could not find %s\n",iwadfil); exit(0); }

		read(ifil,&wadtype,4);
		if (wadtype != 0x44415749)        //!= IWAD
		{
			close(ifil); close(pfil);
			printf("Wad a' you think I am?  That ain't no IWAD!\n");
			exit(0);
		}

		strcpy(doommap,argstring[3]);     //"E1M1"
		if (strchr(doommap,'.') != 0) *strchr(doommap,'.') = 0;
		scriptname[0] = 0;
		if (argc == 5)
		{
			strcpy(scriptname,argstring[4]);
			if (strchr(scriptname,'.') == 0) strcat(scriptname,".txt");
		}
	}
	else
	{
		strcpy(doommap,argstring[2]);     //"E1M1"
		if (strchr(doommap,'.') != 0) *strchr(doommap,'.') = 0;
		scriptname[0] = 0;
		if (argc == 4)
		{
			strcpy(scriptname,argstring[3]);
			if (strchr(scriptname,'.') == 0) strcat(scriptname,".txt");
		}
	}

	initksqrt();

	read(ifil,&inumwads,4); read(ifil,&iwadstart,4);
	lseek(ifil,iwadstart,SEEK_SET);
	for(z=0;z<inumwads;z++)
	{
		if ((z&1023) == 0) read(ifil,tempbuf,16384);
		zz = ((z&1023)<<4);
		iwadplc[z] = ((long)tempbuf[zz]) + (((long)tempbuf[zz+1])<<8) + (((long)tempbuf[zz+2])<<16) + (((long)tempbuf[zz+3])<<24);
		zz += 4;
		iwadlen[z] = ((long)tempbuf[zz]) + (((long)tempbuf[zz+1])<<8) + (((long)tempbuf[zz+2])<<16) + (((long)tempbuf[zz+3])<<24);
		zz += 4;
		iwadata[z][0] = tempbuf[zz+0]; iwadata[z][1] = tempbuf[zz+1];
		iwadata[z][2] = tempbuf[zz+2]; iwadata[z][3] = tempbuf[zz+3];
		iwadata[z][4] = tempbuf[zz+4]; iwadata[z][5] = tempbuf[zz+5];
		iwadata[z][6] = tempbuf[zz+6]; iwadata[z][7] = tempbuf[zz+7];
		iwadata[z][8] = 0;
	}

	parsescript();

	for(z=0;z<inumwads;z++) slist[z] = z;

	for(gap=(inumwads>>1);gap>0;gap>>=1)
		for(z=0;z<inumwads-gap;z++)
			for(zz=z;zz>=0;zz-=gap)
			{
				if (stricmp(iwadata[slist[zz]],iwadata[slist[zz+gap]]) <= 0) break;
				i = slist[zz]; slist[zz] = slist[zz+gap]; slist[zz+gap] = i;
			}

	if (ifil != pfil)
	{
		read(pfil,&pnumwads,4);
		read(pfil,&pwadstart,4);
		lseek(pfil,pwadstart,SEEK_SET);
		for(z=0;z<pnumwads;z++)
		{
			if ((z&1023) == 0) read(ifil,tempbuf,16384);
			zz = ((z&1023)<<4);
			pwadplc[z] = ((long)tempbuf[zz]) + (((long)tempbuf[zz+1])<<8) + (((long)tempbuf[zz+2])<<16) + (((long)tempbuf[zz+3])<<24);
			zz += 4;
			pwadlen[z] = ((long)tempbuf[zz]) + (((long)tempbuf[zz+1])<<8) + (((long)tempbuf[zz+2])<<16) + (((long)tempbuf[zz+3])<<24);
			zz += 4;
			pwadata[z][0] = tempbuf[zz+0]; pwadata[z][1] = tempbuf[zz+1];
			pwadata[z][2] = tempbuf[zz+2]; pwadata[z][3] = tempbuf[zz+3];
			pwadata[z][4] = tempbuf[zz+4]; pwadata[z][5] = tempbuf[zz+5];
			pwadata[z][6] = tempbuf[zz+6]; pwadata[z][7] = tempbuf[zz+7];
			pwadata[z][8] = 0;
		}
	}
	else
	{
		pnumwads = inumwads;
		pwadstart = iwadstart;
		for(z=0;z<inumwads;z++)
		{
			pwadplc[z] = iwadplc[z];
			pwadlen[z] = iwadlen[z];
			pwadata[z][0] = iwadata[z][0]; pwadata[z][1] = iwadata[z][1];
			pwadata[z][2] = iwadata[z][2]; pwadata[z][3] = iwadata[z][3];
			pwadata[z][4] = iwadata[z][4]; pwadata[z][5] = iwadata[z][5];
			pwadata[z][6] = iwadata[z][6]; pwadata[z][7] = iwadata[z][7];
			pwadata[z][8] = iwadata[z][8];
		}
	}

	clearbufbyte(FP_OFF(sector),MAXSECTORS*sizeof(sectortype),0L);
	clearbufbyte(FP_OFF(wall),MAXWALLS*sizeof(walltype),0L);
	clearbufbyte(FP_OFF(sprite),MAXSPRITES*sizeof(spritetype),0L);
	for(i=0;i<MAXSECTORS;i++) sector[i].extra = -1;
	for(i=0;i<MAXWALLS;i++) wall[i].extra = -1;
	for(i=0;i<MAXSPRITES;i++) sprite[i].extra = -1;

	if ((w = getwadindex("TEXTURE1")) < 0)
		{ printf("TEXTURE1 not found!\n"); exit(0); }
	lseek(ifil,iwadplc[w],SEEK_SET);
	read(ifil,&numtexts,4);
	read(ifil,textoffs,numtexts*sizeof(long));
	for(z=0;z<numtexts;z++)
	{
		lseek(ifil,iwadplc[w]+textoffs[z],SEEK_SET);
		read(ifil,tempbuf,32);
		textname[z][0] = tempbuf[0]; textname[z][1] = tempbuf[1];
		textname[z][2] = tempbuf[2]; textname[z][3] = tempbuf[3];
		textname[z][4] = tempbuf[4]; textname[z][5] = tempbuf[5];
		textname[z][6] = tempbuf[6]; textname[z][7] = tempbuf[7];
		textname[z][8] = 0;
		textpname[z] = ((long)tempbuf[26]) + (((long)tempbuf[27])<<8);
	}

	if ((w = getwadindex("TEXTURE2")) >= 0)
	{
		lseek(ifil,iwadplc[w],SEEK_SET);
		startnumtexts = numtexts;
		read(ifil,&danumtexts,4); numtexts += danumtexts;
		read(ifil,&textoffs[startnumtexts],(numtexts-startnumtexts)*sizeof(long));
		for(z=startnumtexts;z<numtexts;z++)
		{
			lseek(ifil,iwadplc[w]+textoffs[z],SEEK_SET);
			read(ifil,tempbuf,32);
			textname[z][0] = tempbuf[0]; textname[z][1] = tempbuf[1];
			textname[z][2] = tempbuf[2]; textname[z][3] = tempbuf[3];
			textname[z][4] = tempbuf[4]; textname[z][5] = tempbuf[5];
			textname[z][6] = tempbuf[6]; textname[z][7] = tempbuf[7];
			textname[z][8] = 0;
			textpname[z] = ((long)tempbuf[26]) + (((long)tempbuf[27])<<8);
		}
	}

	if ((w = getwadindex("PNAMES")) < 0)
		{ printf("PNAMES not found!\n"); exit(0); }
	lseek(ifil,iwadplc[w],SEEK_SET);
	read(ifil,&numpnames,4);
	read(ifil,tempbuf,numpnames*8);
	for(z=0;z<numpnames;z++)
	{
		zz = (z<<3);
		pname[z][0] = tempbuf[zz+0]; pname[z][1] = tempbuf[zz+1];
		pname[z][2] = tempbuf[zz+2]; pname[z][3] = tempbuf[zz+3];
		pname[z][4] = tempbuf[zz+4]; pname[z][5] = tempbuf[zz+5];
		pname[z][6] = tempbuf[zz+6]; pname[z][7] = tempbuf[zz+7];
		pname[z][8] = 0;
	}

	if ((w = getwadindex(doommap)) < 0)
		{ printf("Board not found!\n"); exit(0); }
	boardwadindex = w;
	for(w=boardwadindex+10;w>=boardwadindex;w--)
	{
		lseek(pfil,pwadplc[w],SEEK_SET);

		if (stricmp(pwadata[w],"VERTEXES") == 0)
		{
			dnumpoints = (pwadlen[w]>>2);
			read(pfil,tempbuf,pwadlen[w]);
			offs = 0;
			for(z=0;z<dnumpoints;z++)
			{
				px[z] = ((short)tempbuf[offs])+(((short)tempbuf[offs+1])<<8);
				py[z] = -(((short)tempbuf[offs+2])+(((short)tempbuf[offs+3])<<8));
				offs += 4;
			}
		}
		if (stricmp(pwadata[w],"LINEDEFS") == 0)
		{
			dnumlines = pwadlen[w]/sizeof(linedeftype);
			read(pfil,line,sizeof(linedeftype)*dnumlines);
		}
		if (stricmp(pwadata[w],"SIDEDEFS") == 0)
		{
			dnumsides = pwadlen[w]/sizeof(sidedeftype);
			read(pfil,side,pwadlen[w]);
			for(z=0;z<dnumsides;z++)
			{
				for(i=0;i<8;i++) picstr[i] = side[z].uppertexture[i];
				picstr[8] = 0;

				sidetoppic[z] = -1;
				if (picstr[0] != '-')
					for(zx=0;zx<numtexts;zx++)
						if (stricmp(picstr,textname[zx]) == 0)
							{ sidetoppic[z] = getwadindex(pname[textpname[zx]]); break; }

				for(i=0;i<8;i++) picstr[i] = side[z].lowertexture[i];
				picstr[8] = 0;

				sidebotpic[z] = -1;
				if (picstr[0] != '-')
					for(zx=0;zx<numtexts;zx++)
						if (stricmp(picstr,textname[zx]) == 0)
							{ sidebotpic[z] = getwadindex(pname[textpname[zx]]); break; }

				for(i=0;i<8;i++) picstr[i] = side[z].middletexture[i];
				picstr[8] = 0;

				sidemidpic[z] = -1;
				if (picstr[0] != '-')
					for(zx=0;zx<numtexts;zx++)
						if (stricmp(picstr,textname[zx]) == 0)
							{ sidemidpic[z] = getwadindex(pname[textpname[zx]]); break; }
			}
		}
		if (stricmp(pwadata[w],"SECTORS") == 0)
		{
			dnumsectors = pwadlen[w]/sizeof(secttype);
			read(pfil,sect,pwadlen[w]);
			for(z=0;z<dnumsectors;z++)
			{
				for(i=0;i<8;i++) picstr[i] = sect[z].floorpic[i];
				picstr[8] = 0;
				sector[z].floorpicnum = getwadindex(picstr);
		  
				for(i=0;i<8;i++) picstr[i] = sect[z].ceilingpic[i];
				picstr[8] = 0;
				sector[z].ceilingpicnum = getwadindex(picstr);
			}
		}
		if (stricmp(pwadata[w],"THINGS") == 0)
		{
			dnumthings = pwadlen[w]/sizeof(thingtype);
			read(pfil,thing,pwadlen[w]);
		}
	}
	close(ifil);
	if (ifil != pfil) close(pfil);


	minx = 32767; maxx = -32768;
	miny = 32767; maxy = -32768;
	for(z=0;z<dnumpoints;z++)
	{
		x = px[z]; y = py[z];
		if (x < minx) minx = x;
		if (x > maxx) maxx = x;
		if (y < miny) miny = y;
		if (y > maxy) maxy = y;
	}
	cx = (((minx+maxx)>>1)&0xffffffc0);
	cy = (((miny+maxy)>>1)&0xffffffc0);

	numwalls = 0;

	for(z=0;z<dnumsectors;z++)
	{
		startnumwalls = numwalls;
		for(zz=0;zz<dnumlines;zz++)
		{
			if (z == side[line[zz].side1].sect)
			{
				wx[numwalls] = px[line[zz].p1]; wy[numwalls] = py[line[zz].p1];
				wx2[numwalls] = px[line[zz].p2]; wy2[numwalls] = py[line[zz].p2];
				picindex[numwalls] = line[zz].side1; linindex[numwalls++] = zz;
			}
			if ((line[zz].side2 >= 0) && (z == side[line[zz].side2].sect))
			{
				wx[numwalls] = px[line[zz].p2]; wy[numwalls] = py[line[zz].p2];
				wx2[numwalls] = px[line[zz].p1]; wy2[numwalls] = py[line[zz].p1];
				picindex[numwalls] = line[zz].side2; linindex[numwalls++] = zz;
			}
		}

		startpoint2 = startnumwalls;
		for(zz=startnumwalls;zz<numwalls;zz++)
		{
			dapoint2 = -1; x = wx2[zz]; y = wy2[zz];
			j = 0;
			for(zzz=zz+1;zzz<numwalls;zzz++)
				if ((wx[zzz] == x) && (wy[zzz] == y))
				{
					if (j == 0)
					{
						i = wx[zz+1]; wx[zz+1] = wx[zzz]; wx[zzz] = i;
						i = wy[zz+1]; wy[zz+1] = wy[zzz]; wy[zzz] = i;
						i = wx2[zz+1]; wx2[zz+1] = wx2[zzz]; wx2[zzz] = i;
						i = wy2[zz+1]; wy2[zz+1] = wy2[zzz]; wy2[zzz] = i;
						i = picindex[zz+1]; picindex[zz+1] = picindex[zzz]; picindex[zzz] = i;
						i = linindex[zz+1]; linindex[zz+1] = linindex[zzz]; linindex[zzz] = i;
						j = 1;
					}
					else
					{
						j = 1;
						l1 = (x-wx[zz])*(wy2[zz+1]-y) - (y-wy[zz])*(wx2[zz+1]-x);
						l2 = (x-wx[zz])*(wy2[zzz]-y) - (y-wy[zz])*(wx2[zzz]-x);
						if (l1 == 0) j = 2;       //Don't want collinear lines!
						else if ((l1 < 0) && (l2 > 0)) j = 2;
						else if ((wx2[zz+1]-x)*(wy2[zzz]-y) > (wy2[zz+1]-y)*(wx2[zzz]-x)) j = 2;

						if (j == 2)
						{
							i = wx[zz+1]; wx[zz+1] = wx[zzz]; wx[zzz] = i;
							i = wy[zz+1]; wy[zz+1] = wy[zzz]; wy[zzz] = i;
							i = wx2[zz+1]; wx2[zz+1] = wx2[zzz]; wx2[zzz] = i;
							i = wy2[zz+1]; wy2[zz+1] = wy2[zzz]; wy2[zzz] = i;
							i = picindex[zz+1]; picindex[zz+1] = picindex[zzz]; picindex[zzz] = i;
							i = linindex[zz+1]; linindex[zz+1] = linindex[zzz]; linindex[zzz] = i;
						}
					}
					point2[zz] = zz+1;
				}
			if (j == 0) point2[zz] = startpoint2, startpoint2 = zz+1;
		}

		sector[z].wallptr = startnumwalls;
		sector[z].wallnum = numwalls-startnumwalls;
	}

		//Collect sectors
	for(z=0;z<dnumsectors;z++)
	{
		if (stricmp(iwadata[sector[z].ceilingpicnum],"F_SKY1") == 0) sector[z].ceilingstat |= 1;
		if (stricmp(iwadata[sector[z].floorpicnum],"F_SKY1") == 0) sector[z].floorstat |= 1;
		sector[z].ceilingz = -(sect[z].ceilingz<<8);
		sector[z].floorz = -(sect[z].floorz<<8);

		startwall = sector[z].wallptr;
		endwall = startwall + sector[z].wallnum;
		for(zz=startwall;zz<endwall;zz++) sectorofwall[zz] = z;

		j = 28-(sect[z].shade>>3);
		if ((sector[z].ceilingstat&1) == 0) sector[z].ceilingshade = j;
		if ((sector[z].floorstat&1) == 0) sector[z].floorshade = j;
		for(i=startwall;i<endwall;i++) wall[i].shade = j;
	}


	for(i=0;i<MAXTHINGTYPES;i++) thinglookup[i] = -1;

	for(i=0;i<THINGLISTNUM;i++)
		thinglookup[thinglist[i].num] = getwadindex(thinglist[i].name);

	for(i=0;i<MAXTHINGTYPES;i++)
		if (thinglookup[i] == -1)   //Make bad type numbers into cans
			thinglookup[i] = thinglookup[2035];


	for(z=0;z<numwalls;z++) slist[z] = z;

	for(gap=(numwalls>>1);gap>0;gap>>=1)
		for(z=0;z<numwalls-gap;z++)
			for(zz=z;zz>=0;zz-=gap)
			{
				if (wx[slist[zz]] <= wx[slist[zz+gap]]) break;
				i = slist[zz]; slist[zz] = slist[zz+gap]; slist[zz+gap] = i;
			}

	for(z=0;z<numwalls;z++)
	{
		wall[z].x = (((long)wx[z]-cx)<<4);
		wall[z].y = (((long)wy[z]-cy)<<4);
		wall[z].point2 = point2[z];

		wall[z].nextwall = -1;
		wall[z].nextsector = -1;

		x1 = wx[z]; x2 = wx[point2[z]];
		y1 = wy[z]; y2 = wy[point2[z]];

		zz = 0; zzz = 2048;
		do
		{
			if ((zz+zzz < numwalls) && (wx[slist[zz+zzz]] < x2)) zz += zzz;
			zzz >>= 1;
			if ((zz+zzz < numwalls) && (wx[slist[zz+zzz]] < x2)) zz += zzz;
			zzz >>= 1;
		} while (zzz > 0);

		do
		{
			zzx = slist[zz];
			if (wx[zzx] > x2) break;
			if (wy[zzx] == y2)
				if ((wx[point2[zzx]] == x1) && (wy[point2[zzx]] == y1))
				{
					wall[z].nextwall = zzx;
					wall[z].nextsector = sectorofwall[zzx];
					break;
				}
			zz++;
		} while (zz < numwalls);

		if (wall[z].nextwall < 0)
		{
			wall[z].picnum = sidemidpic[picindex[z]];
			wall[z].overpicnum = 0;
		}
		else
		{
			wall[z].picnum = sidetoppic[picindex[z]];
			if (wall[z].picnum <= 0) wall[z].picnum = sidebotpic[picindex[z]];
			if ((wall[z].picnum <= 0) && (wall[z].nextwall >= 0))
			{
				zx = picindex[wall[z].nextwall];
				wall[z].picnum = sidetoppic[zx];
				if (wall[z].picnum <= 0) wall[z].picnum = sidebotpic[zx];
			}
			wall[z].overpicnum = sidemidpic[picindex[z]];
			if (wall[z].overpicnum >= 0) wall[z].cstat |= (1+4+16);
		}
		wall[z].xrepeat = 8;
		wall[z].yrepeat = 8;
		wall[z].xpanning = (char)((-side[picindex[z]].xoffset)&255);
		wall[z].ypanning = (char)(((side[picindex[z]].yoffset<<1))&255);

		if (line[linindex[z]].flags&1) wall[z].cstat |= 1;
		//if (wall[z].nextwall >= 0) wall[z].cstat |= 4;
		//if ((line[linindex[z]].flags&24) && (wall[z].nextwall >= 0))
		//   wall[z].cstat |= 4;
	}

	for(z=0;z<dnumthings;z++)
	{
		sprite[z].x = (((long)thing[z].x-cx)<<4);
		sprite[z].y = (((long)-thing[z].y-cy)<<4);

		sprite[z].sectnum = 0;
		for(zz=0;zz<dnumsectors;zz++)
			if (inside(sprite[z].x,sprite[z].y,(short)zz) != 0)
				{ sprite[z].sectnum = zz; break; }

		sprite[z].z = -(sect[sprite[z].sectnum].floorz<<8);
		sprite[z].clipdist = 32;
		sprite[z].xrepeat = 64;
		sprite[z].yrepeat = 64;
		sprite[z].picnum = thinglookup[thing[z].type];
		sprite[z].ang = ((-((thing[z].ang<<11)/360))&2047);


		for(i=0;i<numthings;i++)
			if ((thing[z].type >= thingnum[i]) && (thing[z].type <= thingnum2[i]))
				for(j=thingoff[i];j<thingoff[i+1];j++)
				{
					k = thingfield[j]; zz = thingval[j];
					switch(thingop[j])
					{
						case 0: setspritefield(z,k,zz); break;
						case 1: setspritefield(z,k,getspritefield(z,k)+zz); break;
						case 2: setspritefield(z,k,getspritefield(z,k)-zz); break;
						case 3: setspritefield(z,k,getspritefield(z,k)|zz); break;
						case 4: setspritefield(z,k,getspritefield(z,k)&zz); break;
						case 5: setspritefield(z,k,getspritefield(z,k)^zz); break;
					}
				}
	}

	for(zx=0;zx<numwalls;zx++)
	{
		z = linindex[zx];
		for(i=0;i<numtags;i++)
		{
			if ((line[z].special < tagnum[i]) || (line[z].special > tagnum2[i])) continue;

			for(j=tagoff[i];j<tagoff[i+1];j++)
			{
				k = (tagfield[j]&127);
				zz = tagval[j]; if (zz == 0x80000000) zz = line[z].tag;
				if (k < 32)
				{
					l = sectorofwall[zx];
					if (wall[zx].nextsector >= 0)
						if ((tagfield[j]&128) ^ (picindex[zx] == line[z].side1))
							l = wall[zx].nextsector;

					zzz = sectspri[l][(tagfield[j]>>8)&7];
					if (zzz < 0)
					{
						zzz = dnumthings++;
						sectspri[l][(tagfield[j]>>8)&7] = zzz;
						zzx = sector[l].wallptr; x1 = wall[zzx].x; y1 = wall[zzx].y;
						zzx = wall[zzx].point2; x2 = wall[zzx].x; y2 = wall[zzx].y;
						sprite[zzz].x = ((x1+x2)>>1) + ksgn(y1-y2);
						sprite[zzz].y = ((y1+y2)>>1) + ksgn(x2-x1);
						sprite[zzz].sectnum = l;
						sprite[zzz].z = sector[l].floorz;
						sprite[zzz].clipdist = 32;
						sprite[zzz].xrepeat = 64;
						sprite[zzz].yrepeat = 64;
					}

					switch(tagop[j])
					{
						case 0: setspritefield(zzz,k,zz); break;
						case 1: setspritefield(zzz,k,getspritefield(zzz,k)+zz); break;
						case 2: setspritefield(zzz,k,getspritefield(zzz,k)-zz); break;
						case 3: setspritefield(zzz,k,getspritefield(zzz,k)|zz); break;
						case 4: setspritefield(zzz,k,getspritefield(zzz,k)&zz); break;
						case 5: setspritefield(zzz,k,getspritefield(zzz,k)^zz); break;
					}
				}
				else if (k < 64)
				{
					l = sectorofwall[zx];
					if (wall[zx].nextsector >= 0)
						if ((tagfield[j]&128) ^ (picindex[zx] == line[z].side1))
							l = wall[zx].nextsector;

					switch(tagop[j])
					{
						case 0: setsectorfield(l,k,zz); break;
						case 1: setsectorfield(l,k,getsectorfield(l,k)+zz); break;
						case 2: setsectorfield(l,k,getsectorfield(l,k)-zz); break;
						case 3: setsectorfield(l,k,getsectorfield(l,k)|zz); break;
						case 4: setsectorfield(l,k,getsectorfield(l,k)&zz); break;
						case 5: setsectorfield(l,k,getsectorfield(l,k)^zz); break;
					}
				}
				else if (k < 96)
				{
					l = zx;
					if (wall[zx].nextwall >= 0)
						if ((tagfield[j]&128) ^ (picindex[zx] == line[z].side1))
							l = wall[zx].nextwall;

					switch(tagop[j])
					{
						case 0: setwallfield(l,k,zz); break;
						case 1: setwallfield(l,k,getwallfield(l,k)+zz); break;
						case 2: setwallfield(l,k,getwallfield(l,k)-zz); break;
						case 3: setwallfield(l,k,getwallfield(l,k)|zz); break;
						case 4: setwallfield(l,k,getwallfield(l,k)&zz); break;
						case 5: setwallfield(l,k,getwallfield(l,k)^zz); break;
					}
				}
			}
		}
	}

	for(l=0;l<dnumsectors;l++)
		for(i=0;i<numsecs;i++)
			if ((sect[l].type >= secnum[i]) && (sect[l].type <= secnum2[i]))
			{
				for(j=secoff[i];j<secoff[i+1];j++)
				{
					k = (secfield[j]&127);
					zz = secval[j]; if (zz == 0x80000000) zz = sect[l].tag;
					if (k < 32)
					{
						zzz = sectspri[l][(secfield[j]>>8)&7];
						if (zzz < 0)
						{
							zzz = dnumthings++;
							sectspri[l][(secfield[j]>>8)&7] = zzz;
							zzx = sector[l].wallptr; x1 = wall[zzx].x; y1 = wall[zzx].y;
							zzx = wall[zzx].point2; x2 = wall[zzx].x; y2 = wall[zzx].y;
							sprite[zzz].x = ((x1+x2)>>1) + ksgn(y1-y2);
							sprite[zzz].y = ((y1+y2)>>1) + ksgn(x2-x1);
							sprite[zzz].sectnum = l;
							sprite[zzz].z = sector[l].floorz;
							sprite[zzz].clipdist = 32;
							sprite[zzz].xrepeat = 64;
							sprite[zzz].yrepeat = 64;
						}

						switch(secop[j])
						{
							case 0: setspritefield(zzz,k,zz); break;
							case 1: setspritefield(zzz,k,getspritefield(zzz,k)+zz); break;
							case 2: setspritefield(zzz,k,getspritefield(zzz,k)-zz); break;
							case 3: setspritefield(zzz,k,getspritefield(zzz,k)|zz); break;
							case 4: setspritefield(zzz,k,getspritefield(zzz,k)&zz); break;
							case 5: setspritefield(zzz,k,getspritefield(zzz,k)^zz); break;
						}
					}
					else if (k < 64)
					{
						switch(secop[j])
						{
							case 0: setsectorfield(l,k,zz); break;
							case 1: setsectorfield(l,k,getsectorfield(l,k)+zz); break;
							case 2: setsectorfield(l,k,getsectorfield(l,k)-zz); break;
							case 3: setsectorfield(l,k,getsectorfield(l,k)|zz); break;
							case 4: setsectorfield(l,k,getsectorfield(l,k)&zz); break;
							case 5: setsectorfield(l,k,getsectorfield(l,k)^zz); break;
						}
					}
				}
			}

	for(z=0;z<dnumsectors;z++)
	{
		sector[z].ceilingpicnum = texturelookup[sector[z].ceilingpicnum];
		sector[z].floorpicnum = texturelookup[sector[z].floorpicnum];
	}
	for(z=0;z<numwalls;z++)
	{
		x = wall[wall[z].point2].x-wall[z].x;
		y = wall[wall[z].point2].y-wall[z].y;
		if ((klabs(x) >= 32768) || (klabs(y) >= 32768))
			wall[z].xrepeat = 255;
		else
		{
			zx = mulscale10(ksqrtasm(x*x+y*y),wall[z].yrepeat);
			wall[z].xrepeat = (char)min(max(zx,1),255);
		}

		wall[z].picnum = texturelookup[wall[z].picnum];
		wall[z].overpicnum = texturelookup[wall[z].overpicnum];
	}

	mapversion = 7; posx = 0; posy = 0; posz = 0; ang = 1536; cursectnum = 0;

		//WATCH OUT THAT FOR DNUMTHINGS BEING HIGHER THAN NUMBER ON DOOM MAP!
	for(i=0;i<dnumthings;i++)
		if (thing[i].type == 1)
		{
			posx = (((long)thing[i].x-cx)<<4);
			posy = (((long)-thing[i].y-cy)<<4);

			cursectnum = 0;
			for(zz=0;zz<dnumsectors;zz++)
				if (inside(posx,posy,(short)zz) != 0)
					{ cursectnum = zz; break; }

			posz = -(sect[cursectnum].floorz<<8) - (32<<8);
			ang = ((-((thing[i].ang<<11)/360))&2047);
			break;
		}

	//getch();

	//setvmode(0x3);

	strcpy(buildmap,doommap);
	if (strchr(buildmap,'.') == 0) strcat(buildmap,".map");
	if ((fil = open(buildmap,O_BINARY|O_TRUNC|O_CREAT|O_WRONLY,S_IWRITE)) == -1)
	{
		printf("Could not write to %s\n",buildmap);
		exit(0);
	}
	write(fil,&mapversion,4);
	write(fil,&posx,4);
	write(fil,&posy,4);
	write(fil,&posz,4);
	write(fil,&ang,2);
	write(fil,&cursectnum,2);
	write(fil,&dnumsectors,2);
	write(fil,sector,sizeof(sectortype)*dnumsectors);
	write(fil,&numwalls,2);
	write(fil,wall,sizeof(walltype)*numwalls);
	write(fil,&dnumthings,2);
	write(fil,sprite,sizeof(spritetype)*dnumthings);
	close(fil);

	printf("Map converted.\n");
}

inside(long x, long y, short sectnum)
{
	walltype *wal;
	long i, x1, y1, x2, y2;
	char cnt;

	cnt = 0;

	wal = &wall[sector[sectnum].wallptr];
	for(i=sector[sectnum].wallnum;i>0;i--)
	{
		y1 = wal->y-y; y2 = wall[wal->point2].y-y;
		if ((y1^y2) < 0)
		{
			x1 = wal->x-x; x2 = wall[wal->point2].x-x;

			if ((x1^x2) < 0)
				cnt ^= (x1*y2<x2*y1)^(y1<y2);
			else if (x1 >= 0)
				cnt ^= 1;
		}
		wal++;
	}
	return(cnt);
}

initksqrt()
{
	unsigned long i, j, num, root;

	for(i=0;i<2048;i++)
	{
		num = (i<<20); root = 128;
		do
		{
			j = root; root = ((num/root+root)>>1);
		} while (klabs(j-root) > 1);
		j = root*root-num;
		while (klabs((j-(root<<1)+1)) < klabs(j)) { j += -(root<<1)+1; root--; }
		while (klabs((j+(root<<1)+1)) < klabs(j)) { j += (root<<1)+1; root++; }
		sqrtable[i] = (unsigned short)root;
	}
}

readbyte()
{
	if (filpos >= fileng) return(-1);
	if ((filpos&16383) == 0) read(filhandle,filebuf,16384);
	filpos++;
	return((long)filebuf[(filpos-1)&16383]);
}

readline()
{
	long i, ch;

	do
	{
		do
		{
			ch = readbyte();
			if (ch < 0) return(0);
		} while ((ch == 13) || (ch == 10));

		i = 0; tempbuf[0] = 0;
		while ((ch != 13) && (ch != 10))
		{
			if (ch < 0) return(0);
			if (ch == ';')
			{
				do
				{
					if (ch < 0) return(0);
					ch = readbyte();
				} while ((ch != 13) && (ch != 10));
				break;
			}
			if ((ch == 32) || (ch == 9)) ch = ',';
			if ((ch != ',') || (i == 0) || (tempbuf[i-1] != ','))
				{ tempbuf[i++] = ch; tempbuf[i] = 0; }
			ch = readbyte();
		}
		if ((i > 0) && (tempbuf[i-1] == ',')) tempbuf[i-1] = 0;
	} while (i <= 0);
	return(i);
}

parsescript()
{
	long i, j, k, l, lasti, breakout, tstart, tend, textnum, frontbackstat;
	long spritenumstat, slen;
	char ch;

	clearbufbyte(FP_OFF(sectspri),MAXSECTS*8*sizeof(short),0xffffffff);

	if (scriptname[0] == 0)
	{
		for(i=0;i<4096;i++) texturelookup[i] = i;
		return;
	}

	if ((filhandle = open(scriptname,O_BINARY|O_RDWR,S_IREAD)) == -1)
	{
		printf("Could not find %s\n",scriptname);
		exit(0);
	}
	filpos = 0; fileng = filelength(filhandle);
	while (readline() != 0)
	{
		i = 0; j = 0; lasti = 0;
		while (1)
		{
			if ((tempbuf[i] == ',') || (tempbuf[i] == 0))
			{
				if (tempbuf[i] == 0) { breakout = 1; }
				else { breakout = 0, tempbuf[i] = 0; }

				if (j == 0)
				{
					if (tempbuf[lasti] == '[')
					{
						definemode = 0;
						thingtypemode = 0;
						texturelookupmode = 0;
						tagtypemode = 0;
						sectypemode = 0;
					}

					if (stricmp(&tempbuf[lasti],"#define") == 0)
						definemode = 1;

					if (thingtypemode == 1)
					{
						thingoff[numthings] = thingopnum;

						k = lasti;
						while ((tempbuf[k] != 0) && (tempbuf[k] != '-')) k++;

						if (tempbuf[k] == '-')
						{
							tempbuf[k] = 0;
							thingnum[numthings] = atol(&tempbuf[lasti]);
							thingnum2[numthings] = atol(&tempbuf[k+1]);
						}
						else
						{
							thingnum[numthings] = atol(&tempbuf[lasti]);
							thingnum2[numthings] = thingnum[numthings];
						}

						numthings++;
					}
					else if (stricmp(&tempbuf[lasti],"[THINGTYPES]") == 0)
						thingtypemode = 1;

					if (texturelookupmode == 1)
					{
						textnum = 0;
						if ((tempbuf[lasti] >= 48) && (tempbuf[lasti] <= 57))
						{
							k = lasti;
							while ((tempbuf[k] != 0) && (tempbuf[k] != '-')) k++;

							if (tempbuf[k] == '-')
							{
								tempbuf[k] = 0;
								tstart = atol(&tempbuf[lasti]);
								tend = atol(&tempbuf[k+1]);
								for(k=tstart;k<=tend;k++)
									tempshort[textnum++] = k;
							}
							else
								tempshort[textnum++] = atol(&tempbuf[lasti]);
						}
						else
						{
							slen = 0;
							while (tempbuf[lasti+slen] != 0)
							{
								ch = tempbuf[lasti+slen];
								if ((ch >= 97) && (ch <= 122)) tempbuf[lasti+slen] -= 32;
								slen++;
							}
							if (slen > 0)
								for(k=inumwads-1;k>=0;k--)
									if ((iwadata[k][slen] == 0) || (iwadata[k][slen] == 32))
										if ((iwadata[k][slen-1] != 0) && (iwadata[k][slen-1] != 32))
										{
											for(l=slen-1;l>=0;l--)
												if (tempbuf[lasti+l] != '?')
												{
													ch = iwadata[k][l];
													if ((ch >= 97) && (ch <= 122)) ch -= 32;
													if (tempbuf[lasti+l] != ch) break;
												}
											if (l < 0) tempshort[textnum++] = k;
										}
						}
					}
					else if (stricmp(&tempbuf[lasti],"[TEXTURELOOKUPS]") == 0)
						texturelookupmode = 1;

					if (tagtypemode == 1)
					{
						tagoff[numtags] = tagopnum;

						k = lasti;
						while ((tempbuf[k] != 0) && (tempbuf[k] != '-')) k++;

						if (tempbuf[k] == '-')
						{
							tempbuf[k] = 0;
							tagnum[numtags] = atol(&tempbuf[lasti]);
							tagnum2[numtags] = atol(&tempbuf[k+1]);
						}
						else
						{
							tagnum[numtags] = atol(&tempbuf[lasti]);
							tagnum2[numtags] = tagnum[numtags];
						}

						numtags++;
					}
					else if (stricmp(&tempbuf[lasti],"[TAGCONVERSIONS]") == 0)
						tagtypemode = 1;

					if (sectypemode == 1)
					{
						secoff[numsecs] = secopnum;

						k = lasti;
						while ((tempbuf[k] != 0) && (tempbuf[k] != '-')) k++;

						if (tempbuf[k] == '-')
						{
							tempbuf[k] = 0;
							secnum[numsecs] = atol(&tempbuf[lasti]);
							secnum2[numsecs] = atol(&tempbuf[k+1]);
						}
						else
						{
							secnum[numsecs] = atol(&tempbuf[lasti]);
							secnum2[numsecs] = secnum[numsecs];
						}
						numsecs++;
					}
					else if (stricmp(&tempbuf[lasti],"[SECTORCONVERSIONS]") == 0)
						sectypemode = 1;

				}
				else if (j > 0)
				{
					if (definemode == 1)
					{
						defineptr[numdefines] = (char *)(&define[definecnt]);
						for(k=lasti;k<i;k++) define[definecnt++] = tempbuf[k];
						define[definecnt++] = 0;
						definemode = 2;
					}
					else if (definemode == 2)
					{
						defineval[numdefines++] = atol(&tempbuf[lasti]);
						definemode = 0;
					}

					if (thingtypemode == 1)
					{
						for(k=lasti;k<i;k++) if (tempbuf[k] == '=') break;
						thingop[thingopnum] = 0;
						if (tempbuf[k-1] == '+') thingop[thingopnum] = 1;
						if (tempbuf[k-1] == '-') thingop[thingopnum] = 2;
						if (tempbuf[k-1] == '|') thingop[thingopnum] = 3;
						if (tempbuf[k-1] == '&') thingop[thingopnum] = 4;
						if (tempbuf[k-1] == '^') thingop[thingopnum] = 5;
						if (thingop[thingopnum] != 0) tempbuf[k-1] = 0;
														 else tempbuf[k] = 0;

						if (stricmp(&tempbuf[lasti],"x") == 0) thingfield[thingopnum] = 0;
						if (stricmp(&tempbuf[lasti],"y") == 0) thingfield[thingopnum] = 1;
						if (stricmp(&tempbuf[lasti],"z") == 0) thingfield[thingopnum] = 2;
						if (stricmp(&tempbuf[lasti],"cstat") == 0) thingfield[thingopnum] = 3;
						if (stricmp(&tempbuf[lasti],"shade") == 0) thingfield[thingopnum] = 4;
						if (stricmp(&tempbuf[lasti],"pal") == 0) thingfield[thingopnum] = 5;
						if (stricmp(&tempbuf[lasti],"clipdist") == 0) thingfield[thingopnum] = 6;
						if (stricmp(&tempbuf[lasti],"xrepeat") == 0) thingfield[thingopnum] = 7;
						if (stricmp(&tempbuf[lasti],"yrepeat") == 0) thingfield[thingopnum] = 8;
						if (stricmp(&tempbuf[lasti],"xoffset") == 0) thingfield[thingopnum] = 9;
						if (stricmp(&tempbuf[lasti],"yoffset") == 0) thingfield[thingopnum] = 10;
						if (stricmp(&tempbuf[lasti],"picnum") == 0) thingfield[thingopnum] = 11;
						if (stricmp(&tempbuf[lasti],"ang") == 0) thingfield[thingopnum] = 12;
						if (stricmp(&tempbuf[lasti],"xvel") == 0) thingfield[thingopnum] = 13;
						if (stricmp(&tempbuf[lasti],"yvel") == 0) thingfield[thingopnum] = 14;
						if (stricmp(&tempbuf[lasti],"zvel") == 0) thingfield[thingopnum] = 15;
						if (stricmp(&tempbuf[lasti],"owner") == 0) thingfield[thingopnum] = 16;
						if (stricmp(&tempbuf[lasti],"sectnum") == 0) thingfield[thingopnum] = 17;
						if (stricmp(&tempbuf[lasti],"statnum") == 0) thingfield[thingopnum] = 18;
						if (stricmp(&tempbuf[lasti],"lotag") == 0) thingfield[thingopnum] = 19;
						if (stricmp(&tempbuf[lasti],"hitag") == 0) thingfield[thingopnum] = 20;
						if (stricmp(&tempbuf[lasti],"extra") == 0) thingfield[thingopnum] = 21;

						if ((tempbuf[k+1] >= 48) && (tempbuf[k+1] <= 57))
							thingval[thingopnum] = atol(&tempbuf[k+1]);
						else
						{
							for(l=0;l<numdefines;l++)
								if (stricmp(defineptr[l],&tempbuf[k+1]) == 0)
									{ thingval[thingopnum] = defineval[l]; break; }
						}

						thingopnum++;
					}

					if ((texturelookupmode == 1) && (j == 1))
					{
						if ((tempbuf[lasti] >= 48) && (tempbuf[lasti] <= 57))
							l = atol(&tempbuf[lasti]);
						else
						{
							for(l=0;l<numdefines;l++)
								if (stricmp(defineptr[l],&tempbuf[lasti]) == 0)
									{ l = defineval[l]; break; }
						}
						for(k=textnum-1;k>=0;k--) texturelookup[tempshort[k]] = l;
					}

					if (tagtypemode == 1)
					{
						for(k=lasti;k<i;k++) if (tempbuf[k] == '=') break;
						tagop[tagopnum] = 0;
						if (tempbuf[k-1] == '+') tagop[tagopnum] = 1;
						if (tempbuf[k-1] == '-') tagop[tagopnum] = 2;
						if (tempbuf[k-1] == '|') tagop[tagopnum] = 3;
						if (tempbuf[k-1] == '&') tagop[tagopnum] = 4;
						if (tempbuf[k-1] == '^') tagop[tagopnum] = 5;
						if (tagop[tagopnum] != 0) tempbuf[k-1] = 0;
														 else tempbuf[k] = 0;

							//Pick off first letter - is it f or b?
						frontbackstat = 0;
						if ((tempbuf[lasti] == 'b') || (tempbuf[lasti] == 'B')) frontbackstat = 1;
						lasti++;

						spritenumstat = 0;
						if ((tempbuf[lasti] >= 48) && (tempbuf[lasti] <= 57))  //1 DIGIT ONLY!
						{
							spritenumstat = tempbuf[lasti]-48;
							lasti++;
						}

						if (stricmp(&tempbuf[lasti],"sprite.x") == 0) tagfield[tagopnum] = 0;
						if (stricmp(&tempbuf[lasti],"sprite.y") == 0) tagfield[tagopnum] = 1;
						if (stricmp(&tempbuf[lasti],"sprite.z") == 0) tagfield[tagopnum] = 2;
						if (stricmp(&tempbuf[lasti],"sprite.cstat") == 0) tagfield[tagopnum] = 3;
						if (stricmp(&tempbuf[lasti],"sprite.shade") == 0) tagfield[tagopnum] = 4;
						if (stricmp(&tempbuf[lasti],"sprite.pal") == 0) tagfield[tagopnum] = 5;
						if (stricmp(&tempbuf[lasti],"sprite.clipdist") == 0) tagfield[tagopnum] = 6;
						if (stricmp(&tempbuf[lasti],"sprite.xrepeat") == 0) tagfield[tagopnum] = 7;
						if (stricmp(&tempbuf[lasti],"sprite.yrepeat") == 0) tagfield[tagopnum] = 8;
						if (stricmp(&tempbuf[lasti],"sprite.xoffset") == 0) tagfield[tagopnum] = 9;
						if (stricmp(&tempbuf[lasti],"sprite.yoffset") == 0) tagfield[tagopnum] = 10;
						if (stricmp(&tempbuf[lasti],"sprite.picnum") == 0) tagfield[tagopnum] = 11;
						if (stricmp(&tempbuf[lasti],"sprite.ang") == 0) tagfield[tagopnum] = 12;
						if (stricmp(&tempbuf[lasti],"sprite.xvel") == 0) tagfield[tagopnum] = 13;
						if (stricmp(&tempbuf[lasti],"sprite.yvel") == 0) tagfield[tagopnum] = 14;
						if (stricmp(&tempbuf[lasti],"sprite.zvel") == 0) tagfield[tagopnum] = 15;
						if (stricmp(&tempbuf[lasti],"sprite.owner") == 0) tagfield[tagopnum] = 16;
						if (stricmp(&tempbuf[lasti],"sprite.sectnum") == 0) tagfield[tagopnum] = 17;
						if (stricmp(&tempbuf[lasti],"sprite.statnum") == 0) tagfield[tagopnum] = 18;
						if (stricmp(&tempbuf[lasti],"sprite.lotag") == 0) tagfield[tagopnum] = 19;
						if (stricmp(&tempbuf[lasti],"sprite.hitag") == 0) tagfield[tagopnum] = 20;
						if (stricmp(&tempbuf[lasti],"sprite.extra") == 0) tagfield[tagopnum] = 21;

						if (stricmp(&tempbuf[lasti],"sector.wallptr") == 0) tagfield[tagopnum] = 32;
						if (stricmp(&tempbuf[lasti],"sector.wallnum") == 0) tagfield[tagopnum] = 33;
						if (stricmp(&tempbuf[lasti],"sector.ceilingpicnum") == 0) tagfield[tagopnum] = 34;
						if (stricmp(&tempbuf[lasti],"sector.floorpicnum") == 0) tagfield[tagopnum] = 35;
						if (stricmp(&tempbuf[lasti],"sector.ceilingheinum") == 0) tagfield[tagopnum] = 36;
						if (stricmp(&tempbuf[lasti],"sector.floorheinum") == 0) tagfield[tagopnum] = 37;
						if (stricmp(&tempbuf[lasti],"sector.ceilingz") == 0) tagfield[tagopnum] = 38;
						if (stricmp(&tempbuf[lasti],"sector.floorz") == 0) tagfield[tagopnum] = 39;
						if (stricmp(&tempbuf[lasti],"sector.ceilingshade") == 0) tagfield[tagopnum] = 40;
						if (stricmp(&tempbuf[lasti],"sector.floorshade") == 0) tagfield[tagopnum] = 41;
						if (stricmp(&tempbuf[lasti],"sector.ceilingxpanning") == 0) tagfield[tagopnum] = 42;
						if (stricmp(&tempbuf[lasti],"sector.floorxpanning") == 0) tagfield[tagopnum] = 43;
						if (stricmp(&tempbuf[lasti],"sector.ceilingypanning") == 0) tagfield[tagopnum] = 44;
						if (stricmp(&tempbuf[lasti],"sector.floorypanning") == 0) tagfield[tagopnum] = 45;
						if (stricmp(&tempbuf[lasti],"sector.ceilingstat") == 0) tagfield[tagopnum] = 46;
						if (stricmp(&tempbuf[lasti],"sector.floorstat") == 0) tagfield[tagopnum] = 47;
						if (stricmp(&tempbuf[lasti],"sector.ceilingpal") == 0) tagfield[tagopnum] = 48;
						if (stricmp(&tempbuf[lasti],"sector.floorpal") == 0) tagfield[tagopnum] = 49;
						if (stricmp(&tempbuf[lasti],"sector.visibility") == 0) tagfield[tagopnum] = 50;
						if (stricmp(&tempbuf[lasti],"sector.lotag") == 0) tagfield[tagopnum] = 51;
						if (stricmp(&tempbuf[lasti],"sector.hitag") == 0) tagfield[tagopnum] = 52;
						if (stricmp(&tempbuf[lasti],"sector.extra") == 0) tagfield[tagopnum] = 53;

						if (stricmp(&tempbuf[lasti],"wall.x") == 0) tagfield[tagopnum] = 64;
						if (stricmp(&tempbuf[lasti],"wall.y") == 0) tagfield[tagopnum] = 65;
						if (stricmp(&tempbuf[lasti],"wall.point2") == 0) tagfield[tagopnum] = 66;
						if (stricmp(&tempbuf[lasti],"wall.nextsector") == 0) tagfield[tagopnum] = 67;
						if (stricmp(&tempbuf[lasti],"wall.nextwall") == 0) tagfield[tagopnum] = 68;
						if (stricmp(&tempbuf[lasti],"wall.picnum") == 0) tagfield[tagopnum] = 69;
						if (stricmp(&tempbuf[lasti],"wall.overpicnum") == 0) tagfield[tagopnum] = 70;
						if (stricmp(&tempbuf[lasti],"wall.shade") == 0) tagfield[tagopnum] = 71;
						if (stricmp(&tempbuf[lasti],"wall.pal") == 0) tagfield[tagopnum] = 72;
						if (stricmp(&tempbuf[lasti],"wall.cstat") == 0) tagfield[tagopnum] = 73;
						if (stricmp(&tempbuf[lasti],"wall.xrepeat") == 0) tagfield[tagopnum] = 74;
						if (stricmp(&tempbuf[lasti],"wall.yrepeat") == 0) tagfield[tagopnum] = 75;
						if (stricmp(&tempbuf[lasti],"wall.xpanning") == 0) tagfield[tagopnum] = 76;
						if (stricmp(&tempbuf[lasti],"wall.ypanning") == 0) tagfield[tagopnum] = 77;
						if (stricmp(&tempbuf[lasti],"wall.lotag") == 0) tagfield[tagopnum] = 78;
						if (stricmp(&tempbuf[lasti],"wall.hitag") == 0) tagfield[tagopnum] = 79;
						if (stricmp(&tempbuf[lasti],"wall.extra") == 0) tagfield[tagopnum] = 80;

						tagfield[tagopnum] += (frontbackstat<<7) + (spritenumstat<<8);

						if ((tempbuf[k+1] >= 48) && (tempbuf[k+1] <= 57))
							tagval[tagopnum] = atol(&tempbuf[k+1]);
						else if (stricmp("tag",&tempbuf[k+1]) == 0)
							tagval[tagopnum] = 0x80000000;
						else
						{
							for(l=0;l<numdefines;l++)
								if (stricmp(defineptr[l],&tempbuf[k+1]) == 0)
									{ tagval[tagopnum] = defineval[l]; break; }
						}

						tagopnum++;
					}

					if (sectypemode == 1)
					{
						for(k=lasti;k<i;k++) if (tempbuf[k] == '=') break;
						secop[secopnum] = 0;
						if (tempbuf[k-1] == '+') secop[secopnum] = 1;
						if (tempbuf[k-1] == '-') secop[secopnum] = 2;
						if (tempbuf[k-1] == '|') secop[secopnum] = 3;
						if (tempbuf[k-1] == '&') secop[secopnum] = 4;
						if (tempbuf[k-1] == '^') secop[secopnum] = 5;
						if (secop[secopnum] != 0) tempbuf[k-1] = 0;
													 else tempbuf[k] = 0;

						spritenumstat = 0;
						if ((tempbuf[lasti] >= 48) && (tempbuf[lasti] <= 57))  //1 DIGIT ONLY!
						{
							spritenumstat = tempbuf[lasti]-48;
							lasti++;
						}

						if (stricmp(&tempbuf[lasti],"sprite.x") == 0) secfield[secopnum] = 0;
						if (stricmp(&tempbuf[lasti],"sprite.y") == 0) secfield[secopnum] = 1;
						if (stricmp(&tempbuf[lasti],"sprite.z") == 0) secfield[secopnum] = 2;
						if (stricmp(&tempbuf[lasti],"sprite.cstat") == 0) secfield[secopnum] = 3;
						if (stricmp(&tempbuf[lasti],"sprite.shade") == 0) secfield[secopnum] = 4;
						if (stricmp(&tempbuf[lasti],"sprite.pal") == 0) secfield[secopnum] = 5;
						if (stricmp(&tempbuf[lasti],"sprite.clipdist") == 0) secfield[secopnum] = 6;
						if (stricmp(&tempbuf[lasti],"sprite.xrepeat") == 0) secfield[secopnum] = 7;
						if (stricmp(&tempbuf[lasti],"sprite.yrepeat") == 0) secfield[secopnum] = 8;
						if (stricmp(&tempbuf[lasti],"sprite.xoffset") == 0) secfield[secopnum] = 9;
						if (stricmp(&tempbuf[lasti],"sprite.yoffset") == 0) secfield[secopnum] = 10;
						if (stricmp(&tempbuf[lasti],"sprite.picnum") == 0) secfield[secopnum] = 11;
						if (stricmp(&tempbuf[lasti],"sprite.ang") == 0) secfield[secopnum] = 12;
						if (stricmp(&tempbuf[lasti],"sprite.xvel") == 0) secfield[secopnum] = 13;
						if (stricmp(&tempbuf[lasti],"sprite.yvel") == 0) secfield[secopnum] = 14;
						if (stricmp(&tempbuf[lasti],"sprite.zvel") == 0) secfield[secopnum] = 15;
						if (stricmp(&tempbuf[lasti],"sprite.owner") == 0) secfield[secopnum] = 16;
						if (stricmp(&tempbuf[lasti],"sprite.sectnum") == 0) secfield[secopnum] = 17;
						if (stricmp(&tempbuf[lasti],"sprite.statnum") == 0) secfield[secopnum] = 18;
						if (stricmp(&tempbuf[lasti],"sprite.lotag") == 0) secfield[secopnum] = 19;
						if (stricmp(&tempbuf[lasti],"sprite.hitag") == 0) secfield[secopnum] = 20;
						if (stricmp(&tempbuf[lasti],"sprite.extra") == 0) secfield[secopnum] = 21;

						if (stricmp(&tempbuf[lasti],"sector.wallptr") == 0) secfield[secopnum] = 32;
						if (stricmp(&tempbuf[lasti],"sector.wallnum") == 0) secfield[secopnum] = 33;
						if (stricmp(&tempbuf[lasti],"sector.ceilingpicnum") == 0) secfield[secopnum] = 34;
						if (stricmp(&tempbuf[lasti],"sector.floorpicnum") == 0) secfield[secopnum] = 35;
						if (stricmp(&tempbuf[lasti],"sector.ceilingheinum") == 0) secfield[secopnum] = 36;
						if (stricmp(&tempbuf[lasti],"sector.floorheinum") == 0) secfield[secopnum] = 37;
						if (stricmp(&tempbuf[lasti],"sector.ceilingz") == 0) secfield[secopnum] = 38;
						if (stricmp(&tempbuf[lasti],"sector.floorz") == 0) secfield[secopnum] = 39;
						if (stricmp(&tempbuf[lasti],"sector.ceilingshade") == 0) secfield[secopnum] = 40;
						if (stricmp(&tempbuf[lasti],"sector.floorshade") == 0) secfield[secopnum] = 41;
						if (stricmp(&tempbuf[lasti],"sector.ceilingxpanning") == 0) secfield[secopnum] = 42;
						if (stricmp(&tempbuf[lasti],"sector.floorxpanning") == 0) secfield[secopnum] = 43;
						if (stricmp(&tempbuf[lasti],"sector.ceilingypanning") == 0) secfield[secopnum] = 44;
						if (stricmp(&tempbuf[lasti],"sector.floorypanning") == 0) secfield[secopnum] = 45;
						if (stricmp(&tempbuf[lasti],"sector.ceilingstat") == 0) secfield[secopnum] = 46;
						if (stricmp(&tempbuf[lasti],"sector.floorstat") == 0) secfield[secopnum] = 47;
						if (stricmp(&tempbuf[lasti],"sector.ceilingpal") == 0) secfield[secopnum] = 48;
						if (stricmp(&tempbuf[lasti],"sector.floorpal") == 0) secfield[secopnum] = 49;
						if (stricmp(&tempbuf[lasti],"sector.visibility") == 0) secfield[secopnum] = 50;
						if (stricmp(&tempbuf[lasti],"sector.lotag") == 0) secfield[secopnum] = 51;
						if (stricmp(&tempbuf[lasti],"sector.hitag") == 0) secfield[secopnum] = 52;
						if (stricmp(&tempbuf[lasti],"sector.extra") == 0) secfield[secopnum] = 53;

						secfield[secopnum] += (spritenumstat<<8);

						if ((tempbuf[k+1] >= 48) && (tempbuf[k+1] <= 57))
							secval[secopnum] = atol(&tempbuf[k+1]);
						else if (stricmp("tag",&tempbuf[k+1]) == 0)
							secval[secopnum] = 0x80000000;
						else
						{
							for(l=0;l<numdefines;l++)
								if (stricmp(defineptr[l],&tempbuf[k+1]) == 0)
									{ secval[secopnum] = defineval[l]; break; }
						}

						secopnum++;
					}

				}
				if (breakout == 1) break;
				lasti = i+1; j++;
			}
			i++;
		}
	}
	thingoff[numthings] = thingopnum;
	tagoff[numtags] = tagopnum;
	secoff[numsecs] = secopnum;
	close(filhandle);
}

getspritefield(long i, long fieldnum)
{
	switch(fieldnum)
	{
		case 0: return((long)sprite[i].x);
		case 1: return((long)sprite[i].y);
		case 2: return((long)sprite[i].z);
		case 3: return((long)sprite[i].cstat);
		case 4: return((long)sprite[i].shade);
		case 5: return((long)sprite[i].pal);
		case 6: return((long)sprite[i].clipdist);
		case 7: return((long)sprite[i].xrepeat);
		case 8: return((long)sprite[i].yrepeat);
		case 9: return((long)sprite[i].xoffset);
		case 10: return((long)sprite[i].yoffset);
		case 11: return((long)sprite[i].picnum);
		case 12: return((long)sprite[i].ang);
		case 13: return((long)sprite[i].xvel);
		case 14: return((long)sprite[i].yvel);
		case 15: return((long)sprite[i].zvel);
		case 16: return((long)sprite[i].owner);
		case 17: return((long)sprite[i].sectnum);
		case 18: return((long)sprite[i].statnum);
		case 19: return((long)sprite[i].lotag);
		case 20: return((long)sprite[i].hitag);
		case 21: return((long)sprite[i].extra);
	}
	return(0);
}

setspritefield(long i, long fieldnum, long newval)
{
	switch(fieldnum)
	{
		case 0: sprite[i].x = newval; break;
		case 1: sprite[i].y = newval; break;
		case 2: sprite[i].z = newval; break;
		case 3: sprite[i].cstat = newval; break;
		case 4: sprite[i].shade = newval; break;
		case 5: sprite[i].pal = newval; break;
		case 6: sprite[i].clipdist = newval; break;
		case 7: sprite[i].xrepeat = newval; break;
		case 8: sprite[i].yrepeat = newval; break;
		case 9: sprite[i].xoffset = newval; break;
		case 10: sprite[i].yoffset = newval; break;
		case 11: sprite[i].picnum = newval; break;
		case 12: sprite[i].ang = newval; break;
		case 13: sprite[i].xvel = newval; break;
		case 14: sprite[i].yvel = newval; break;
		case 15: sprite[i].zvel = newval; break;
		case 16: sprite[i].owner = newval; break;
		case 17: sprite[i].sectnum = newval; break;
		case 18: sprite[i].statnum = newval; break;
		case 19: sprite[i].lotag = newval; break;
		case 20: sprite[i].hitag = newval; break;
		case 21: sprite[i].extra = newval; break;
	}
}

getwallfield(long i, long fieldnum)
{
	switch(fieldnum)
	{
		case 64: return((long)wall[i].x);
		case 65: return((long)wall[i].y);
		case 66: return((long)wall[i].point2);
		case 67: return((long)wall[i].nextsector);
		case 68: return((long)wall[i].nextwall);
		case 69: return((long)wall[i].picnum);
		case 70: return((long)wall[i].overpicnum);
		case 71: return((long)wall[i].shade);
		case 72: return((long)wall[i].pal);
		case 73: return((long)wall[i].cstat);
		case 74: return((long)wall[i].xrepeat);
		case 75: return((long)wall[i].yrepeat);
		case 76: return((long)wall[i].xpanning);
		case 77: return((long)wall[i].ypanning);
		case 78: return((long)wall[i].lotag);
		case 79: return((long)wall[i].hitag);
		case 80: return((long)wall[i].extra);
	}
	return(0);
}

setwallfield(long i, long fieldnum, long newval)
{
	switch(fieldnum)
	{
		case 64: wall[i].x = newval; break;
		case 65: wall[i].y = newval; break;
		case 66: wall[i].point2 = newval; break;
		case 67: wall[i].nextsector = newval; break;
		case 68: wall[i].nextwall = newval; break;
		case 69: wall[i].picnum = newval; break;
		case 70: wall[i].overpicnum = newval; break;
		case 71: wall[i].shade = newval; break;
		case 72: wall[i].pal = newval; break;
		case 73: wall[i].cstat = newval; break;
		case 74: wall[i].xrepeat = newval; break;
		case 75: wall[i].yrepeat = newval; break;
		case 76: wall[i].xpanning = newval; break;
		case 77: wall[i].ypanning = newval; break;
		case 78: wall[i].lotag = newval; break;
		case 79: wall[i].hitag = newval; break;
		case 80: wall[i].extra = newval; break;
	}
}

getsectorfield(long i, long fieldnum)
{
	switch(fieldnum)
	{
		case 32: return((long)sector[i].wallptr);
		case 33: return((long)sector[i].wallnum);
		case 34: return((long)sector[i].ceilingpicnum);
		case 35: return((long)sector[i].floorpicnum);
		case 36: return((long)sector[i].ceilingheinum);
		case 37: return((long)sector[i].floorheinum);
		case 38: return((long)sector[i].ceilingz);
		case 39: return((long)sector[i].floorz);
		case 40: return((long)sector[i].ceilingshade);
		case 41: return((long)sector[i].floorshade);
		case 42: return((long)sector[i].ceilingxpanning);
		case 43: return((long)sector[i].floorxpanning);
		case 44: return((long)sector[i].ceilingypanning);
		case 45: return((long)sector[i].floorypanning);
		case 46: return((long)sector[i].ceilingstat);
		case 47: return((long)sector[i].floorstat);
		case 48: return((long)sector[i].ceilingpal);
		case 49: return((long)sector[i].floorpal);
		case 50: return((long)sector[i].visibility);
		case 51: return((long)sector[i].lotag);
		case 52: return((long)sector[i].hitag);
		case 53: return((long)sector[i].extra);
	}
	return(0);
}

setsectorfield(long i, long fieldnum, long newval)
{
	switch(fieldnum)
	{
		case 32: sector[i].wallptr = newval; break;
		case 33: sector[i].wallnum = newval; break;
		case 34: sector[i].ceilingpicnum = newval; break;
		case 35: sector[i].floorpicnum = newval; break;
		case 36: sector[i].ceilingheinum = newval; break;
		case 37: sector[i].floorheinum = newval; break;
		case 38: sector[i].ceilingz = newval; break;
		case 39: sector[i].floorz = newval; break;
		case 40: sector[i].ceilingshade = newval; break;
		case 41: sector[i].floorshade = newval; break;
		case 42: sector[i].ceilingxpanning = newval; break;
		case 43: sector[i].floorxpanning = newval; break;
		case 44: sector[i].ceilingypanning = newval; break;
		case 45: sector[i].floorypanning = newval; break;
		case 46: sector[i].ceilingstat = newval; break;
		case 47: sector[i].floorstat = newval; break;
		case 48: sector[i].ceilingpal = newval; break;
		case 49: sector[i].floorpal = newval; break;
		case 50: sector[i].visibility = newval; break;
		case 51: sector[i].lotag = newval; break;
		case 52: sector[i].hitag = newval; break;
		case 53: sector[i].extra = newval; break;
	}
}

getwadindex(char *nam)
{
	long i, j;

	i = 0;
	for(j=2048;j>0;j>>=1)
		if (i+j < inumwads)
			if (stricmp(iwadata[slist[i+j]],nam) <= 0) i += j;
	if (stricmp(iwadata[slist[i]],nam) == 0) return(slist[i]);
	return(-1);
}
