//
// Level Converter
//
// Converts thing types from 1.09.4 to 1.1
//
// By A.J. Freda
//
// Modified from Graue's "Heightedit"
// and uses Graue's "LumpMod" utility.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//#define STARPOSTS_ONLY

#define TABLE_SIZE 16384
int conversion[TABLE_SIZE]; // Conversion table.
FILE *lvlconvfile;

static inline void InitializeThingConversionTable(void)
{
	memset(conversion, 0, sizeof(conversion));

	// Player starts
	conversion[1] = 1;
	conversion[2] = 2;
	conversion[3] = 3;
	conversion[4] = 4;
	conversion[4001] = 5;
	conversion[4002] = 6;
	conversion[4003] = 7;
	conversion[4004] = 8;
	conversion[4005] = 9;
	conversion[4006] = 10;
	conversion[4007] = 11;
	conversion[4008] = 12;
	conversion[4009] = 13;
	conversion[4010] = 14;
	conversion[4011] = 15;
	conversion[4012] = 16;
	conversion[4013] = 17;
	conversion[4014] = 18;
	conversion[4015] = 19;
	conversion[4016] = 20;
	conversion[4017] = 21;
	conversion[4018] = 22;
	conversion[4019] = 23;
	conversion[4020] = 24;
	conversion[4021] = 25;
	conversion[4022] = 26;
	conversion[4023] = 27;
	conversion[4024] = 28;
	conversion[4025] = 29;
	conversion[4026] = 30;
	conversion[4027] = 31;
	conversion[4028] = 32;
	conversion[11] = 33;
	conversion[87] = 34;
	conversion[89] = 35;

	// Enemies
	conversion[3004] = 100;
	conversion[9] = 101;
	conversion[58] = 102;
	conversion[5005] = 103;
	conversion[5006] = 104;
	conversion[3005] = 105;
	conversion[22] = 106;
	conversion[21] = 107;
	conversion[71] = 108;
	conversion[56] = 109;
	conversion[2004] = 110;
	conversion[42] = 111;

	// Bosses
	conversion[16] = 200;
	conversion[2008] = 201;
	conversion[17] = 290;
	conversion[2049] = 291;

	// Collectibles
	conversion[2014] = 300;
	conversion[69] = 301;
	conversion[3003] = 302;
	conversion[80] = 303;
	conversion[26] = 304;
	conversion[54] = 305;
	conversion[31] = 310;
	conversion[34] = 311;
	conversion[2013] = 312;
	conversion[420] = 313;
	conversion[421] = 314;
	conversion[422] = 315;
	conversion[423] = 316;
	conversion[424] = 317;
	conversion[425] = 318;
	conversion[426] = 319;
	conversion[64] = 320;
	conversion[3002] = 320;
	conversion[3001] = 320;

	// Boxes
	conversion[2011] = 400;
	conversion[2012] = 400;
	conversion[48] = 402;
	conversion[2002] = 403;
	conversion[2018] = 404;
	conversion[35] = 405;
	conversion[2028] = 406;
	conversion[25] = 407;
	conversion[2022] = 408;
	conversion[41] = 409;
	conversion[2005] = 410;
	conversion[78] = 411;
	conversion[3000] = 412;

	// Interactive Objects
	conversion[33] = 500;
	conversion[86] = 501;
	conversion[3006] = 502;
//	conversion[?] = 520;
	conversion[23] = 521;
	conversion[67] = 522;
	conversion[68] = 523;
	conversion[32] = 540;
	conversion[30] = 541;
	conversion[28] = 550;
	conversion[79] = 551;
	conversion[5004] = 552;
	conversion[65] = 553;
	conversion[66] = 554;
	conversion[2015] = 555;
	conversion[38] = 556;
	conversion[20] = 557;
	conversion[39] = 558;

	// Special Placement Patterns
	conversion[84] = 600;
	conversion[44] = 601;
	conversion[76] = 602;
	conversion[77] = 603;
	conversion[47] = 604;
	conversion[2007] = 605;
	conversion[2048] = 606;
	conversion[2010] = 607;
	conversion[2046] = 608;
	conversion[2047] = 609;

	// Powerup Indicators/Environmental Effects/Miscellany
	conversion[2026] = 700;
	conversion[2024] = 701;
	conversion[2023] = 702;
	conversion[2045] = 703;
	conversion[83] = 704;
	conversion[2019] = 705;
	conversion[2025] = 706;
	conversion[27] = 707;
	conversion[14] = 708;
	conversion[43] = 709;
	conversion[8] = 750;
	conversion[5003] = 751;
	conversion[5007] = 752;
	conversion[18] = 753;
	conversion[5001] = 754;
	conversion[5002] = 755;
	conversion[2003] = 756;

	// Greenflower Scenery
	conversion[36] = 800;
	conversion[70] = 801;
	conversion[73] = 802;
	conversion[74] = 804;
	conversion[75] = 805;

	// Techno Hill Scenery
	conversion[2035] = 900;
	conversion[2006] = 901;

	// Deep Sea Scenery
	conversion[81] = 1000;

	// Castle Eggman Scenery
	conversion[49] = 1100;
	conversion[24] = 1101;
	conversion[52] = 1102;
	conversion[2001] = 1103;

	// NiGHTS Items
	conversion[72] = 1700;
	conversion[61] = 1701;
	conversion[46] = 1702;
	conversion[60] = 1703;
	conversion[82] = 1704;
	conversion[57] = 1705;
	conversion[37] = 1706;
	conversion[3007] = 1707;
	conversion[3008] = 1708;
	conversion[3009] = 1709;
	conversion[40] = 1710;

	// Mario Items
	conversion[10005] = 1800;
	conversion[10000] = 1801;
	conversion[10001] = 1802;
	conversion[50] = 1803;
	conversion[10] = 1804;
	conversion[29] = 1805;
	conversion[19] = 1806;
	conversion[12] = 1807;
	conversion[10002] = 1808;
	conversion[10003] = 1809;
	conversion[10004] = 1810;

	// Christmas Items
	conversion[5] = 1850;
	conversion[13] = 1851;
	conversion[6] = 1852;
}

static inline void InitializeSectorConversionTable(void)
{
	memset(conversion, 0, sizeof(conversion));

	// Player starts
	conversion[690] = -1;
	conversion[691] = -1;
	conversion[692] = -1;
	conversion[693] = -1;
	conversion[694] = -1;
	conversion[695] = -1;
	conversion[696] = -1;
	conversion[697] = -1;
	conversion[698] = -1;
	conversion[699] = -1;
	conversion[700] = -1;
	conversion[701] = -1;
	conversion[702] = -1;
	conversion[703] = -1;
	conversion[704] = -1;
	conversion[705] = -1;
	conversion[706] = -1;
	conversion[707] = -1;
	conversion[708] = -1;
	conversion[709] = -1;
	conversion[710] = -1;
	conversion[711] = -1;
	conversion[981] = -1;
	conversion[986] = -1;
	conversion[8] = -1;
	conversion[17] = -1;
	conversion[519] = 3 + (512 << 8);
	conversion[984] = 2 + (512 << 8);

	// Section 1
	conversion[11] = 1;
	conversion[983] = 2;
	conversion[7] = 3;
	conversion[18] = 4;
	conversion[4] = 5;
	conversion[16] = 6;
	conversion[5] = 7;
	conversion[10] = 8;
	conversion[978] = 9;
	conversion[980] = 10;
	conversion[9] = 11;
	conversion[6] = 12;
	conversion[992] = 13;
	conversion[996] = 14;
	conversion[14] = 15;

	// Section 2
	conversion[971] = 1 << 4;
	conversion[972] = 2 << 4;
	conversion[973] = 3 << 4;
	conversion[974] = 4 << 4;
	conversion[975] = 5 << 4;
	conversion[967] = 6 << 4;
	conversion[968] = 7 << 4;
	conversion[970] = 8 << 4;
	conversion[666] = 9 << 4;
	conversion[990] = 10 << 4;
	conversion[991] = 11 << 4;

	// Section 3
	conversion[256] = 1 << 8;
	conversion[512] = 2 << 8;
	conversion[768] = 3 << 8;
	conversion[985] = 4 << 8;
	conversion[976] = 5 << 8;
	conversion[977] = 6 << 8;
	conversion[1500] = 7 << 8;
	conversion[1501] = 8 << 8;
	conversion[1502] = 9 << 8;
	conversion[1503] = 10 << 8;
	conversion[1504] = 11 << 8;
	conversion[1505] = 12 << 8;
	conversion[1506] = 13 << 8;
	conversion[1507] = 14 << 8;
	conversion[1508] = 15 << 8;

	// Section 4
	conversion[993] = 1 << 12;
	conversion[33] = 2 << 12;
	conversion[982] = 2 << 12;
	conversion[987] = 2 << 12;
	conversion[995] = 2 << 12;
	conversion[988] = 3 << 12;
	conversion[989] = 4 << 12;
	conversion[997] = 5 << 12;
	conversion[969] = 6 << 12;
	conversion[979] = 7 << 12;
	conversion[998] = 8 << 12;
	conversion[999] = 9 << 12;
	conversion[994] = 10 << 12;
}

static inline void InitializeLinedefConversionTable(void)
{
	memset(conversion, 0, sizeof(conversion));

	// Old Water Removed
	conversion[14] = -1;

	// Level Parameters/Misc:
	conversion[64] = 1;
	conversion[71] = 2;
	conversion[18] = 3;
	conversion[65] = 4;
	conversion[63] = 5;
	conversion[73] = 6;
	conversion[66] = 7;

	// Level-Load Effects:
	conversion[26] = 50;
	conversion[24] = 51;
	conversion[88] = 52;
	conversion[2] = 53;
	conversion[3] = 54;
	conversion[4] = 55;
	conversion[6] = 56;
	conversion[7] = 57;
	conversion[8] = 58;
	conversion[232] = 59;
	conversion[233] = 60;
	conversion[43] = 61;
	conversion[50] = 62;
	conversion[242] = 63;

	// Floor-Over-Floors:
	conversion[25] = 100;
	conversion[33] = 101;
	conversion[44] = 102;
	conversion[69] = 103;
	conversion[51] = 104;
	conversion[57] = 105;
	conversion[48] = 120;
	conversion[45] = 121;
	conversion[75] = 122;
	conversion[74] = 123;
	conversion[59] = 140;
	conversion[81] = 141;
	conversion[77] = 142;
	conversion[38] = 150;
	conversion[68] = 151;
	conversion[72] = 152;
	conversion[34] = 160;
	conversion[36] = 170;
	conversion[35] = 171;
	conversion[79] = 172;
	conversion[80] = 173;
	conversion[82] = 174;
	conversion[83] = 175;
	conversion[39] = 176;
	conversion[1] = 177;
	conversion[37] = 178;
	conversion[42] = 179;
	conversion[40] = 180;
	conversion[89] = 190;
	conversion[90] = 191;
	conversion[91] = 192;
	conversion[94] = 193;
	conversion[92] = 194;
	conversion[93] = 195;
	conversion[49] = 200;
	conversion[47] = 201;
	conversion[46] = 202;
	conversion[62] = 220;
	conversion[52] = 221;
	conversion[67] = 222;
	conversion[58] = 223;
	conversion[41] = 250;
	conversion[54] = 251;
	conversion[76] = 252;
	conversion[86] = 253;
	conversion[55] = 254;
	conversion[78] = 255;
	conversion[84] = 256;
	conversion[56] = 257;
	conversion[53] = 258;
	conversion[87] = 259;

	// Linedef Executor Triggers:
	conversion[96] = 300;
	conversion[97] = 301;
	conversion[98] = 302;
	conversion[95] = 303;
	conversion[99] = 304;
	conversion[19] = 305;
	conversion[20] = 306;
	conversion[21] = 307;
	conversion[9] = 308;
	conversion[10] = 309;
	conversion[11] = 310;
	conversion[12] = 311;
	conversion[13] = 312;
	conversion[15] = 313;

	// Linedef Executor Options:
	conversion[101] = 400;
	conversion[102] = 401;
	conversion[103] = 402;
	conversion[106] = 403;
	conversion[107] = 404;
	conversion[108] = 405;
	conversion[109] = 406;
	conversion[110] = 407;
	conversion[111] = 408;
	conversion[112] = 409;
	conversion[114] = 410;
	conversion[116] = 411;
	conversion[104] = 412;
	conversion[105] = 413;
	conversion[115] = 414;
	conversion[113] = 415;
	conversion[119] = 416;
	conversion[120] = 417;
	conversion[117] = 420;
	conversion[118] = 421;
	conversion[121] = 422;
	conversion[123] = 423;
	conversion[124] = 424;
	conversion[125] = 425;
	conversion[122] = 426;
	conversion[126] = 427;
	conversion[127] = 428;

	// Scrollers/Pushers
	conversion[100] = 500;
	conversion[85] = 501;
	conversion[254] = 502;
	conversion[218] = 503;
	conversion[249] = 504;
	conversion[255] = 505;
	conversion[251] = 510;
	conversion[215] = 511;
	conversion[246] = 512;
	conversion[250] = 513;
	conversion[214] = 514;
	conversion[245] = 515;
	conversion[252] = 520;
	conversion[216] = 521;
	conversion[247] = 522;
	conversion[203] = 523;
	conversion[205] = 524;
	conversion[201] = 525;
	conversion[253] = 530;
	conversion[217] = 531;
	conversion[248] = 532;
	conversion[202] = 533;
	conversion[204] = 534;
	conversion[200] = 535;
	conversion[223] = 540;
	conversion[224] = 541;
	conversion[229] = 542;
	conversion[230] = 543;
	conversion[225] = 544;
	conversion[227] = 545;
	conversion[228] = 546;
	conversion[226] = 547;

	// Lighting
	conversion[213] = 600;
	
	conversion[5] = 601;
	conversion[60] = 602;
	conversion[61] = 603;
	conversion[16] = 606;

	// Translucency
	conversion[284] = 900;
	conversion[285] = 901;
	conversion[286] = 902;
	conversion[287] = 903;
	conversion[288] = 904;
	conversion[283] = 905;

	// Extended numbers
	conversion[281] = conversion[25];
	conversion[289] = conversion[33];
	conversion[282] = conversion[26];
}

#ifndef _WIN32
#include <ctype.h>
static inline const char* _strupr(char *n)
{
	const char *m = n;
        while (*n != '\0')
        {
                *n = toupper(*n);
                n++;
        }
        return m;
}
#define strupr _strupr
#endif

static inline int ConvertStarposts(char *argv[])
{
	char syscmd[100];
	InitializeThingConversionTable();

	sprintf(syscmd, "lumpmod %s extract -s MAP%s THINGS lvlconv.tmp",
		argv[1], strupr(argv[2]));
	system(syscmd);

	lvlconvfile = fopen("lvlconv.tmp", "r+b");
	if(lvlconvfile == NULL) {
		puts("Failed to open lvlconv.tmp.");
		return EXIT_FAILURE;
	}
	for(;;) {
		int c;
		short x, y, angle, type, options;

		fseek(lvlconvfile, 1, SEEK_CUR);
		fseek(lvlconvfile, -1, SEEK_CUR);

		c = fgetc(lvlconvfile);
		if(c == EOF) break;

		fseek(lvlconvfile, -1, SEEK_CUR);
		if(fread(&x, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CANNOT READ THE X");
			return EXIT_FAILURE;
		}
		if(fread(&y, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE Y");
			return EXIT_FAILURE;
		}
		if(fread(&angle, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE ANGLE");
			return EXIT_FAILURE;
		}
		if(fread(&type, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE TYPE");
			return EXIT_FAILURE;
		}
		if(fread(&options, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE FLAGS");
			return EXIT_FAILURE;
		}

		fseek(lvlconvfile, -6, SEEK_CUR);

		/* CHECK FOR MATCH */
		if(type == 502)
		{
			int numpost = options & 31;
			angle %= 360;
			angle += numpost * 360;
			options = 0;
		}

		if(fwrite(&angle, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CANNOT WRITE THE ANGLE");
			return EXIT_FAILURE;
		}

		if(fwrite(&type, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CANNOT WRITE THE TYPE");
			return EXIT_FAILURE;
		}

		if (fwrite(&options, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CANNOT WRITE THE FLAGS");
			return EXIT_FAILURE;
		}
	}
	fclose(lvlconvfile);
	puts("DONE, Man!.. Inserting into WAD.\n");
	sprintf(syscmd, "lumpmod %s update -s MAP%s THINGS lvlconv.tmp",
		argv[1], strupr(argv[2]));
	system(syscmd);
	remove("lvlconv.tmp");
	return 1;
}

static inline int ConvertThings(char *argv[])
{
	char syscmd[100];
	InitializeThingConversionTable();

	printf("NOTE: Skill settings not supported in 1.1. All of your objects\nhave been converted to appear regardless of skill level.\n");

	sprintf(syscmd, "lumpmod %s extract -s MAP%s THINGS lvlconv.tmp",
		argv[1], strupr(argv[2]));
	system(syscmd);

	lvlconvfile = fopen("lvlconv.tmp", "r+b");
	if(lvlconvfile == NULL) {
		puts("Failed to open lvlconv.tmp.");
		return EXIT_FAILURE;
	}
	for(;;) {
		int c;
		short x, y, angle, type, options;

		fseek(lvlconvfile, 1, SEEK_CUR);
		fseek(lvlconvfile, -1, SEEK_CUR);

		c = fgetc(lvlconvfile);
		if(c == EOF) break;

		fseek(lvlconvfile, -1, SEEK_CUR);
		if(fread(&x, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CANNOT READ THE X");
			return EXIT_FAILURE;
		}
		if(fread(&y, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE Y");
			return EXIT_FAILURE;
		}
		if(fread(&angle, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE ANGLE");
			return EXIT_FAILURE;
		}
		if(fread(&type, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE TYPE");
			return EXIT_FAILURE;
		}
		if(fread(&options, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE FLAGS");
			return EXIT_FAILURE;
		}

		fseek(lvlconvfile, -6, SEEK_CUR);

		/* CHECK FOR MATCH */
		if(type != 32000 && type != 32001) // !@#$%^ Doom Builder...
		{
			if(type < TABLE_SIZE && conversion[type] < 0)
				printf("\nThing type %d no longer supported. You will have to manually change this.", type);
			else if(type < TABLE_SIZE && conversion[type] != 0)
				type = conversion[type];
			else
				printf("\nUnknown thing type %d!", type);

			if (type != 502 && type != 1700 && type != 1701 && type != 1702 && type != 1703 && type != 1704 && type != 1705)
			{
				if (options == 1 || options == 4)
				{
					printf("\nThing type %d on Easy or Hard only, renamed to thing type 4242.", type);
					type = 4242;
				}

				options &= ~7; // Strip skill settings
			}
		}

		if (type == 502)
		{
			int numpost = options & 31;
			angle %= 360;
			angle += numpost * 360;
			options = 0;
		}

		if(fwrite(&angle, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CANNOT WRITE THE ANGLE");
			return EXIT_FAILURE;
		}

		if(fwrite(&type, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CANNOT WRITE THE TYPE");
			return EXIT_FAILURE;
		}

		if (fwrite(&options, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CANNOT WRITE THE FLAGS");
			return EXIT_FAILURE;
		}
	}
	fclose(lvlconvfile);
	puts("DONE, Man!.. Inserting into WAD.\n");
	sprintf(syscmd, "lumpmod %s update -s MAP%s THINGS lvlconv.tmp",
		argv[1], strupr(argv[2]));
	system(syscmd);
	remove("lvlconv.tmp");
	return 1;
}

static void ConvertFlat(char *garbage)
{
		/* CHECK FOR MATCH */
		if(!memcmp(garbage, "FLOOR0_3\0\0\0\0", 8))
			strncpy(garbage, "GFZFLR01\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLOOR0_6\0\0\0", 8))
			strncpy(garbage, "GFZFLR02\0\0\0", 8);
		else if(!memcmp(garbage, "CEIL3_3\0\0\0\0\0", 8) || !memcmp(garbage, "GATE1\0\0\0\0\0\0", 8))
			strncpy(garbage, "GFZFLR03\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "CEIL3_4\0\0\0\0\0", 8))
			strncpy(garbage, "GFZFLR04\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLOOR1_1\0\0\0\0\0", 8))
			strncpy(garbage, "GFZFLR05\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLOOR1_7\0\0\0\0\0", 8))
			strncpy(garbage, "GFZFLR06\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLOOR5_3\0\0\0\0\0", 8))
			strncpy(garbage, "GFZFLR07\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "OLDROCK\0\0\0\0\0\0", 8))
			strncpy(garbage, "GFZFLR08\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "SFLR5_0\0\0\0\0\0", 8))
			strncpy(garbage, "GFZFLR09\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "SFLR6_1\0\0\0\0\0", 8)
			|| !memcmp(garbage, "SFLR6_4\0\0\0\0\0", 8)
			|| !memcmp(garbage, "SFLR7_1\0\0\0\0\0", 8)
			|| !memcmp(garbage, "SFLR7_4\0\0\0\0\0", 8))
		{
			printf("Flat pic %s no longer supported. Use GFZFLR09 with\r\nlinedef special #7 to achieve same effect.\r\nFlat converted to GFZFLR09 for your convenience.\r\n", garbage);
			strncpy(garbage, "GFZFLR09\0\0\0\0\0\0", 8);
		}
		else if(!memcmp(garbage, "DEM1_4\0\0\0\0\0\0", 8))
			strncpy(garbage, "GFZFLR10\0\0\0\0", 8);

		else if(!memcmp(garbage, "FLOOR3_3\0\0\0\0\0", 8))
			strncpy(garbage, "THZFLR30\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLOOR4_5\0\0\0\0\0", 8))
			strncpy(garbage, "THZFLR31\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "OTHZW1\0\0\0\0\0", 8))
			strncpy(garbage, "THZFLR32\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "OTHZW2\0\0\0\0\0", 8))
			strncpy(garbage, "THZFLR33\0\0\0\0\0\0\0", 8);

		else if(!memcmp(garbage, "BLOOD1\0\0", 8))
			strncpy(garbage, "LITER1\0\0", 8);
		else if(!memcmp(garbage, "BLOOD2\0\0", 8))
			strncpy(garbage, "LITER2\0\0", 8);
		else if(!memcmp(garbage, "BLOOD3\0\0", 8))
			strncpy(garbage, "LITER3\0\0", 8);

		else if(!memcmp(garbage, "BLUE1\0\0\0", 8))
			strncpy(garbage, "LITEB1\0\0", 8);
		else if(!memcmp(garbage, "BLUE2\0\0\0", 8))
			strncpy(garbage, "LITEB2\0\0", 8);
		else if(!memcmp(garbage, "BLUE3\0\0\0", 8))
			strncpy(garbage, "LITEB3\0\0", 8);

		else if(!memcmp(garbage, "GREY1\0\0\0", 8))
			strncpy(garbage, "LITEN1\0\0", 8);
		else if(!memcmp(garbage, "GREY2\0\0\0", 8))
			strncpy(garbage, "LITEN2\0\0", 8);
		else if(!memcmp(garbage, "GREY3\0\0\0", 8))
			strncpy(garbage, "LITEN3\0\0", 8);

		else if(!memcmp(garbage, "NUKAGE1\0\0\0", 8))
			strncpy(garbage, "LITEY1\0\0", 8);
		else if(!memcmp(garbage, "NUKAGE2\0\0\0", 8))
			strncpy(garbage, "LITEY2\0\0", 8);
		else if(!memcmp(garbage, "NUKAGE3\0\0\0", 8))
			strncpy(garbage, "LITEY3\0\0", 8);

		else if(!memcmp(garbage, "CEIL1_3\0\0\0\0\0", 8))
			strncpy(garbage, "CEZFLR09\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "CEIL1_1\0\0\0\0\0", 8))
			strncpy(garbage, "CEZFLR10\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "CEIL1_2\0\0\0\0\0", 8))
			strncpy(garbage, "CEZFLR11\0\0\0\0\0\0\0", 8);

		else if(!memcmp(garbage, "CONS1_1\0\0\0\0\0", 8))
			strncpy(garbage, "SFLR07\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "CONS1_5\0\0\0\0\0", 8))
			strncpy(garbage, "SFLR08\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "CONS1_7\0\0\0\0\0", 8))
			strncpy(garbage, "SFLR09\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLOOR0_5\0\0\0\0\0", 8))
			strncpy(garbage, "SFLR10\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLOOR0_7\0\0\0\0\0", 8))
			strncpy(garbage, "SFLR11\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLOOR1_6\0\0\0\0\0", 8))
			strncpy(garbage, "SFLR12\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "SLIME01\0\0\0\0\0", 8))
			strncpy(garbage, "SFLR13\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "SLIME02\0\0\0\0\0", 8))
			strncpy(garbage, "SFLR14\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "SLIME03\0\0\0\0\0", 8))
			strncpy(garbage, "SFLR15\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "SLIME04\0\0\0\0\0", 8))
			strncpy(garbage, "SFLR12\0\0\0\0\0\0\0", 8);

		else if(!memcmp(garbage, "DCFLR1\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR01\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DCCEIL1\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR02\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DCPAVE\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR03\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DCMANHO\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR04\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DCTEX1\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR05\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DCTEX2\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR06\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DCTEX3\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR07\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DCTEX4\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR08\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DCWHITE\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR09\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DCYELLOW\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR10\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DENTFLR\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR11\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DENTMETL\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR12\0\0\0\0\0\0\0", 8); // Intentionally
		else if(!memcmp(garbage, "FLAT14\0\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR12\0\0\0\0\0", 8); // The same!
		else if(!memcmp(garbage, "MFLR8_1\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR13\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "STEP2\0\0\0\0\0", 8))
			strncpy(garbage, "DCZFLR14\0\0\0\0\0", 8);


		else if(!memcmp(garbage, "DEEPSEA2\0\0\0\0\0", 8))
			strncpy(garbage, "DSZFLR04\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DEEPSEA3\0\0\0\0\0", 8))
			strncpy(garbage, "DSZFLR05\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "DEEPSEA4\0\0\0\0\0", 8))
			strncpy(garbage, "DSZFLR06\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLOOR4_6\0\0\0\0\0", 8))
			strncpy(garbage, "DSZFLR07\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "SLIME14\0\0\0\0\0", 8))
			strncpy(garbage, "DSZFLR08\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "SLIME15\0\0\0\0\0", 8))
			strncpy(garbage, "DSZFLR09\0\0\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "SLIME16\0\0\0\0\0", 8))
			strncpy(garbage, "DSZFLR10\0\0\0\0\0\0\0", 8);

		else if(!memcmp(garbage, "ERROCK\0\0\0\0\0\0", 8))
			strncpy(garbage, "ERZFLR01\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLAT18\0\0\0\0\0\0", 8))
			strncpy(garbage, "ERZFLR02\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLAT20\0\0\0\0\0\0", 8))
			strncpy(garbage, "ERZFLR03\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLAT22\0\0\0\0\0\0", 8))
			strncpy(garbage, "ERZFLR04\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLAT23\0\0\0\0\0\0", 8))
			strncpy(garbage, "ERZFLR05\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLAT5_4\0\0\0\0", 8))
			strncpy(garbage, "ERZFLR06\0\0\0\0\0", 8);

		else if(!memcmp(garbage, "FLAT10\0\0\0\0\0\0", 8))
			strncpy(garbage, "REDFLR\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "FLAT5\0\0\0\0\0\0", 8))
			strncpy(garbage, "ORGFLR\0\0\0\0\0", 8);

		else if(!memcmp(garbage, "MFLR8_2\0\0\0\0\0\0", 8))
			strncpy(garbage, "GREYFLR\0\0\0\0\0", 8);
		else if(!memcmp(garbage, "MFLR8_4\0\0\0\0\0\0", 8))
			strncpy(garbage, "GREYFLR\0\0\0\0\0", 8);
}

static inline int ConvertSectors(char *argv[])
{
	char syscmd[100];
	InitializeSectorConversionTable();

	sprintf(syscmd, "lumpmod %s extract -s MAP%s SECTORS lvlconv.tmp",
		argv[1], strupr(argv[2]));
	system(syscmd);

	lvlconvfile = fopen("lvlconv.tmp", "r+b");
	if(lvlconvfile == NULL) {
		puts("Failed to open lvlconv.tmp.");
		return EXIT_FAILURE;
	}
	for(;;) {
		int c;
		char garbage[11];
		short type;

		c = fgetc(lvlconvfile);
		if(c == EOF) break;

		fseek(lvlconvfile, -1, SEEK_CUR);
		if(fread(&garbage, sizeof(short)*2, 1, lvlconvfile) < 1) {
			puts("I CANNOT READ THE DATA BEFORE SECTOR FLATS");
			return EXIT_FAILURE;
		}

		// Read floor flat first.
		if(fread(&garbage, 8, 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE SECTOR FLOOR FLAT");
			return EXIT_FAILURE;
		}

		fseek(lvlconvfile, -8, SEEK_CUR);

		garbage[8] = 0;

		ConvertFlat(garbage);

		if(fwrite(&garbage, 8, 1, lvlconvfile) < 1) {
			puts("I CANNOT WRITE THE FLOOR FLAT");
			return EXIT_FAILURE;
		}

		fseek(lvlconvfile, 0, SEEK_CUR);

		memset(garbage, 0, sizeof(garbage));

		// Now do ceiling flat.
		if(fread(&garbage, 8, 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE SECTOR CEILING FLAT");
			return EXIT_FAILURE;
		}

		fseek(lvlconvfile, -8, SEEK_CUR);

		garbage[8] = 0;
		ConvertFlat(garbage);

		if(fwrite(&garbage, 8, 1, lvlconvfile) < 1) {
			puts("I CANNOT WRITE THE CEILING FLAT");
			return EXIT_FAILURE;
		}

		// Skip lightlevel
		fseek(lvlconvfile, 1 * sizeof(short), SEEK_CUR);

		// Now do sector special.
		if(fread(&type, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE SECTOR SPECIAL");
			return EXIT_FAILURE;
		}

		fseek(lvlconvfile, -1 * (int)sizeof(short), SEEK_CUR);

		/* CHECK FOR MATCH */
		if(conversion[type] < 0)
			printf("\nSector type %d no longer supported. You will have to manually change this.", type);
		else if(conversion[type] != 0)
			type = conversion[type];
		else if (type != 0)
			printf("\nUnknown sector type %d!", type);

		if(fwrite(&type, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CANNOT WRITE THE TYPE");
			return EXIT_FAILURE;
		}

		/* skip 1 short of TOTAL CRAP */
		fseek(lvlconvfile, 1 * sizeof(short), SEEK_CUR);
	}
	fclose(lvlconvfile);
	puts("DONE, Man!.. Inserting back into WAD.\n");
	sprintf(syscmd, "lumpmod %s update -s MAP%s SECTORS lvlconv.tmp",
		argv[1], strupr(argv[2]));
	system(syscmd);
	remove("lvlconv.tmp");
	return 1;
}

static inline int ConvertLinedefs(char *argv[])
{
	char syscmd[100];
	InitializeLinedefConversionTable();

	sprintf(syscmd, "lumpmod %s extract -s MAP%s LINEDEFS lvlconv.tmp",
		argv[1], strupr(argv[2]));
	system(syscmd);

	lvlconvfile = fopen("lvlconv.tmp", "r+b");
	if(lvlconvfile == NULL) {
		puts("Failed to open lvlconv.tmp.");
		return EXIT_FAILURE;
	}
	for(;;) {
		int c;
		short garbage[3], type;

		c = fgetc(lvlconvfile);
		if(c == EOF) break;

		fseek(lvlconvfile, -1, SEEK_CUR);
		if(fread(&garbage, sizeof(short)*3, 1, lvlconvfile) < 1) {
			puts("I CANNOT READ THE DATA BEFORE THE LINEDEF SPECIAL");
			return EXIT_FAILURE;
		}
		if(fread(&type, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CAN'T READ THE LINEDEF TYPE");
			return EXIT_FAILURE;
		}

		fseek(lvlconvfile, -1 * (int)sizeof(short), SEEK_CUR);

		/* CHECK FOR MATCH */
		if(conversion[type] < 0)
			printf("\nLinedef type %d no longer supported. You will have to manually change this.", type);
		else if(conversion[type] != 0)
		{
			if(type == 65)
				printf("\nThis level contains a speed pad linedef. You will have to flip the direction of the line for it to work properly.");

			type = conversion[type];
		}
		else if (type != 0)
			printf("\nUnknown linedef type %d!", type);

		if(fwrite(&type, sizeof(short), 1, lvlconvfile) < 1) {
			puts("I CANNOT WRITE THE TYPE");
			return EXIT_FAILURE;
		}

		/* skip 3 shorts of TOTAL CRAP */
		fseek(lvlconvfile, 3 * sizeof(short), SEEK_CUR);
	}
	fclose(lvlconvfile);
	puts("DONE, Man!.. Inserting back into WAD.\n");
	sprintf(syscmd, "lumpmod %s update -s MAP%s LINEDEFS lvlconv.tmp",
		argv[1], strupr(argv[2]));
	system(syscmd);
	remove("lvlconv.tmp");
	return 1;
}

int main(int argc, char *argv[]) {
	if(argc != 3) {
		puts("Usage: lvlconv [filename] [mapnumber]");
		puts("Example: lvlconv wadfile.wad 01");
		return EXIT_FAILURE; /* YOU FAIL IT! */
	}

	if(strlen(argv[2]) != 2 || strlen(argv[1]) > 32) {
		puts("nonono you screwed it up");
		return EXIT_FAILURE; /* YOU LIKEWISE FAIL IT! */
	}
#ifdef STARPOSTS_ONLY
	ConvertStarposts(argv);
#else
	puts("\nConverting Things...");
	ConvertThings(argv);
	puts("\nConverting Sectors...");
	ConvertSectors(argv);
	puts("\nConverting Linedefs...");
	ConvertLinedefs(argv);
#endif

	puts("\nOkay, DONE!! Enjoy the NEWLY MODIFIED WAD FILE!!! HAVE A GOOD DAY!");
	return EXIT_SUCCESS; /* YOU SUCCEED AT IT! :) */
}