/*
	IDBSP.C - version 1.0 (06/03/94)
	(c) 1994 Ron Rossbach (ej070@cleveland.freenet.edu)

	This program is a mostly direct port of id's BSP compiler to MS-DOS.  In the
	words of John Carmack - "This code was written and evolved ... so it's
	probably not the cleanest thing in the world."  Program was compiled with
	DJGPP v1.11 (that's "DJ's port of GCC" version 1.11, which means GCC v2.5.7)

	Inquiries, comments, etc. are always welcome at the above address.

	Use and distribution of this code permitted according to the terms of the
	GNU General Public License.  Please give credit where credit is due (namely
	to id for releasing the code in the first place!)

	Please do not use this code to develop modified levels for the shareware
	version of DOOM.
*/

#include "idbsp.h"

WADFILE	wad_i;

void BSPMain(FILE *pDWD,boolean overwrite);

int main(int argc, char **argv)
{
	char szDWDName[81], szWADName[81];
	FILE *pDWD;
	boolean overwrite;

	printf("** IDBSP - id's node builder for DOOM, version 1.0 **"
	"\nDOS port (c) 1994 Ron Rossbach (ej070@cleveland.freenet.edu)"
	"\n\nDOOM is a registered trademark of id Software, Inc."
	"\n\nid will not provide technical support for this program."
	"\n\nSee the accompanying README for terms of use, distribution, etc.");

	if (argc < 2 || argc > 3)
		{
		printf("\n\nUsage: \"idbsp dwdfile [wadfile]\""
		"\nDefault is TMP.WAD if wadfile not specified");
		Error("\nExiting....");
		}

	strcpy(szDWDName, argv[1]);

	if (argc == 3)
		strcpy(szWADName, argv[2]);
	else
		strcpy(szWADName,"tmp.wad");

	printf("\nDWD File: %s\nWAD File: %s\n", szDWDName, szWADName);

	if ((pDWD = fopen(szDWDName, "r")) == NULL)
	{
		printf("\nCannot open DWD file");
		return 0;
	}

	if ((wad_i.handle = fopen(szWADName, "rb+")) == NULL)
		{
		wad_i.handle = fopen(szWADName, "wb");
		if (wad_i.handle == NULL)
			Error("\nCannot open WAD file %s",szWADName);
		overwrite = true;
		}
	else
		{
		printf("\n\nWAD file %s already exists.  Overwrite? (y/n): ", szWADName);
		if (toupper(getchar()) == 'Y')
			{
			overwrite = true;
			fclose(wad_i.handle);
			wad_i.handle = fopen(szWADName, "wb");
			}
		else
			overwrite = false;
		}

	wad_i.pathname = (char *)SafeMalloc(strlen(szWADName) + 1);

	if (wad_i.pathname == NULL)
	{
		printf("\nERROR: wad_i.pathname: malloc");
		fclose(pDWD);
		fclose(wad_i.handle);
		return 0;
	}

	strcpy(wad_i.pathname, szWADName);

	BSPMain(pDWD, overwrite);

	fclose(pDWD);
	fclose(wad_i.handle);

	return 0;
}


void BSPMain(FILE *pDWD, boolean overwrite)
{
	int version, episode, level;
	long size;
	char tmp[81],tmpname[81],dirname[9];

	printf("\noverwrite = %d\n",overwrite);
	if (overwrite)
		initNew();
	else
		initFromFile();

	if (!fscanf (pDWD, "WorldServer version %d\n", &version) || version != 4)
		Error ("LoadDoomMap: not a version 4 doom map");

	printf ( "Loading version 4 doom map\n");

	while (fgets(tmp, 81, pDWD) != NULL)
		{
		if (sscanf(tmp,"level:E%dM%d",&episode,&level) == 2)
			{
					/* Handle Map Level */
			sprintf(tmp,"E%dM%d",episode,level);
			printf("\nBuilding Map Level %s",tmp);
			addName(tmp,0,0);
			printf("\nLoading DWD file.....");
			LoadDoomMap(pDWD);
			printf("\nBuilding BSP....");
			DrawMap();
			BuildBSP();
			printf("\nSaving WAD file.....");
			SaveDoomMap();
			SaveBlocks();
			/* Free storage */
			FreeGlobalStorage();
			}
					/* Handle other resources */
		if (sscanf(tmp,"%s :%d",dirname,&size) == 2)
			{
			strcpy(tmp,dirname);
			strcpy(tmpname,tmp);
			strcat(tmpname,".lmp");
			printf("\nAdding resource %s",tmpname);
			AddFromFile(tmp, size, tmpname);
			}
		}

	printf("\nWriting directory.....");
	writeDirectory();

	return;
}

void AddFromFile(char *resname, int size, char *fname)
{
	void *p;
	FILE *f;

	p = (void *)SafeMalloc(size);
	if ((f=fopen(fname,"rb")) == NULL)
		Error("\nAddFromFile: could not open file %s\n", fname);

	fread(p, size, 1, f);
	addName(resname, p, size);
	fclose(f);
	free(p);
}

void FreeGlobalStorage(void)
{
 /*	free(segstore_i->data); */
	free(linestore_i->data);
	free(thingstore_i->data);
	free(secstore_i->data);
	free(mapvertexstore_i->data);
	free(subsecstore_i->data);
	free(maplinestore_i->data);
	free(nodestore_i->data);
	free(mapthingstore_i->data);
	free(ldefstore_i->data);
	free(sdefstore_i->data);
/*	free(secdefstore_i->data); */
/*	free(bchains); */
/*	free(blines); */
/*	free(segstore_i); */
	free(linestore_i);
	free(thingstore_i);
	free(secstore_i);
	free(mapvertexstore_i);
	free(subsecstore_i);
	free(maplinestore_i);
	free(nodestore_i);
	free(mapthingstore_i);
	free(ldefstore_i);
	free(sdefstore_i);
/*	free(secdefstore_i); */
}

void progress(void)
{
	char *s="/-\\|/-\\|";
	static unsigned char pcnt=0;

	if((pcnt&15) == 0)
		{
		printf("%c\b",s[((pcnt)/16)&7]);
		fflush(stdout);
		}
	pcnt++;
}

void Error (char *error, ...)
{
	va_list argptr;
	va_start (argptr,error);
	vprintf (error,argptr);
	va_end (argptr);
	printf ("\n");
	exit (1);
}

void *SafeMalloc(unsigned size)
{
	void *ret = (void *)malloc(size);
	if (!ret)
		Error("\nSafeMalloc: Failed to allocate %u bytes",size);

	return ret;
}

void *SafeCalloc(unsigned num, unsigned size)
{
	void *ret = (void *)calloc(num,size);
	if (!ret)
		Error("\nSafeCalloc: Failed to allocate %u of %u bytes",num,size);

	return ret;
}

#ifdef __BIG_ENDIAN__
short   LittleShort (short l)
{
	byte    b1,b2;
	b1 = l&255;
	b2 = (l>>8)&255;
	return (b1<<8) + b2;
}

short   BigShort (short l)
{
	return l;
}

long    LittleLong (long l)
{
	byte    b1,b2,b3,b4;
	b1 = l&255;
	b2 = (l>>8)&255;
	b3 = (l>>16)&255;
	b4 = (l>>24)&255;
	return ((long)b1<<24) + ((long)b2<<16) + ((long)b3<<8) + b4;
}

long    BigLong (long l)
{
	return l;
}

#else

short   BigShort (short l)
{
	byte    b1,b2;
	b1 = l&255;
	b2 = (l>>8)&255;
	return (b1<<8) + b2;
}

short   LittleShort (short l)
{
	return l;
}

long    BigLong (long l)
{
	byte    b1,b2,b3,b4;
	b1 = l&255;
	b2 = (l>>8)&255;
	b3 = (l>>16)&255;
	b4 = (l>>24)&255;
	return ((long)b1<<24) + ((long)b2<<16) + ((long)b3<<8) + b4;
}

long    LittleLong (long l)
{
	return l;
}

#endif

