/*
   WAD_DWD.C
   (c) 1994 Ron Rossbach (ej070@cleveland.freenet.edu)

   This program converts an ordinary WAD file into a slightly extended version
   of a DWD file.  The DWD file can then be used as input to IDBSP

   Use and distribution of this code permitted according to the terms of the GNU
   General Public License.

   version 1.0.1 by Antony Suter <antony@werple.apana.org.au>
      these fixes and modification (c) 1994 by Antony Suter
 */

#include "wad_dwd.h"

/*
   ===============
   =
   = main
   =
   ===============
 */
int                 main(int argc, char *argv[])
{
	char                dwd_name[81];
	char                wad_name[81];
	char                tmp[9];
	FILE               *dwd,
	                   *wad;
	int                 i;
	long                numthings,
	                    numvertexes,
	                    numlines,
	                    numsides,
	                    numsectors;
	int                 episode,
	                    level;
	mapvertex_t        *vertexes = NULL;
	mapsidedef_t       *sidedefs = NULL;
	maplinedef_t       *linedefs = NULL;
	mapsector_t        *sectors = NULL;
	mapthing_t         *things = NULL;
	lumpinfo_t         *lumps = NULL;
	wadinfo_t           wadheader;

	printf("** WAD_DWD - a WAD->DWD converter for DOOM - version 1.0.1 **"
		"\n(c) 1994 Ron Rossbach (ej070@cleveland.freenet.edu)"
		"\nThis compilation by Antony Suter <antony@werple.apana.org.au>"
		"\n\nDOOM is a registered trademark of id Software, Inc."
		"\n\nSee the accompanying README for terms of use, distribution, etc.");

	if (argc < 2 || argc > 3)
		{
		printf("\n\nUsage: \"wad_dwd wadfile [dwdfile]\""
			"\nTMP.DWD is the default if dwdfile is not specified.");
		Error("\nExiting....");
		}

	strcpy(wad_name, argv[1]);

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

	if ((wad = fopen(wad_name, "rb")) == NULL)
		Error("Cannot open WAD file");

	if ((dwd = fopen(dwd_name, "w")) == NULL)
		{
		fclose(wad);
		Error("Cannot open DWD file");
		}

	/*
	   Read the WAD header
	 */
	fread(&wadheader, sizeof(wadinfo_t), 1, wad);
	fseek(wad, wadheader.infotableofs, SEEK_SET);

	printf("\n\nWAD file: %s\nDWD file: %s\n", wad_name, dwd_name);

	/*
	   Read the WAD directory
	 */
	lumps = ReadWAD(wad, wadheader.numlumps, sizeof(lumpinfo_t));

	/*
	   Process directory entries
	 */
	WriteHeader(dwd);
	for (i = 0; i < wadheader.numlumps; i++)
		{
		strncpy(tmp, lumps[i].name, 8);
		tmp[8] = '\0';

		if (strlen(tmp) <= 0)
			continue;

		/* Handle map levels */
		if (sscanf(tmp, "E%dM%d", &episode, &level) == 2)
			{
			printf("\nWriting Level: %s", tmp);
			things = (mapthing_t *) ReadStorage(wad, &lumps[++i], &numthings, sizeof(mapthing_t));
			linedefs = (maplinedef_t *) ReadStorage(wad, &lumps[++i], &numlines, sizeof(maplinedef_t));
			sidedefs = (mapsidedef_t *) ReadStorage(wad, &lumps[++i], &numsides, sizeof(mapsidedef_t));
			vertexes = (mapvertex_t *) ReadStorage(wad, &lumps[++i], &numvertexes, sizeof(mapvertex_t));
			i += 4;
			sectors = (mapsector_t *) ReadStorage(wad, &lumps[i], &numsectors, sizeof(mapsector_t));
			i += 2;
			fprintf(dwd, "\nlevel:E%dM%d\n", episode, level);
			WriteLines(dwd, numlines, linedefs, vertexes, sidedefs, sectors);
			WriteThings(dwd, numthings, things);
			free(vertexes);
			free(sidedefs);
			free(linedefs);
			free(sectors);
			}
		/* Other Resources */
		else
			{
			printf("\nWriting Resource: %s", tmp);
			fprintf(dwd, "\n%s :%d\n", tmp, lumps[i].size);
			ExtractResource(wad, &lumps[i]);
			}
		}

	free(lumps);
	fclose(wad);
	fclose(dwd);

	printf("\n");

	return 0;
}

/*
   ===============
   =
   = progress
   =
   = provides some visual feedback for the user....
   =
   ===============
 */
void                progress(void)
{
	char               *s = "/-\\|/-\\|";
	static unsigned char pcnt = 0;

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

/*
   ====================
   =
   = Error
   =
   = Displays an error message and exits program
   =
   ====================
 */
void                Error(char *error,...)
{
	va_list             argptr;

	va_start(argptr, error);
	vprintf(error, argptr);
	va_end(argptr);
	printf("\n");
	exit(1);
}


void               *SafeCalloc(unsigned num, size_t size)
{
	void               *ret = (void *)calloc(num, size);

	if (!ret)
		Error("\nSafeCalloc: Failed to allocate %u of %u bytes", num, size);

	return ret;
}
