// =============================================================================
// -----------------------------------------------------------------------------
// Program
// -----------------------------------------------------------------------------

#include <stdio.h>
#include <windows.h>
#include "_Kosinski Z80.h"

int main (int ArgNumber, char **ArgList, char **EnvList)

{
	printf ("Tile Converter - by MarkeyJester\n\n");
	if (ArgNumber <= 1)
	{
		printf (" -> Drag and drop Mega Drive art files onto this program\n"
			"    to convert them to SMS tiles and compress them\n"
			"\n"
			"    This tool will automatically find and convert the palette\n"
			"    and mappings correctly\n"
			"\nPress enter key to exit...\n");
		fflush (stdin); getchar ( ); return (0x00);
	}
	char Direct [0x1000];
	int DirLoc;
	for (int ArgCount = 1; ArgCount < ArgNumber; ArgCount++)
	{
		char *FileName = Direct, *SpaceName = NULL, *ExtName = NULL;
		for (int DirLoc = 0; ; )
		{
			char Byte = ArgList [ArgCount] [DirLoc];
			Direct [DirLoc++] = Byte;
			if (Byte == '.' || Byte == 0x00)
			{
				if (Byte == '.' || (Byte == 0x00 && ExtName == NULL))
				{
					ExtName = &Direct [DirLoc];
				}
				if (Byte == 0x00) { break; }
			}
			else if (Byte == ' ')
			{
				SpaceName = &Direct [DirLoc];
			}
			else if (Byte == '\\' || Byte == '/')
			{
				FileName = &Direct [DirLoc];
			}
		}
		printf (" -> %s\n", FileName);

// -----------------------------------------------------------------------------
// Tiles
// -----------------------------------------------------------------------------

		FILE *File = fopen (Direct, "rb");
		if (File == NULL)
		{
			printf ("    Error; could not open the file...\n");
			continue;
		}
		fseek (File, 0x00, SEEK_END);
		int Size = ftell (File);
		char *Memory = (char*) malloc (Size);
		if (Memory == NULL)
		{
			fclose (File);
			printf ("    Error; could not allocate memory for file...\n");
			continue;
		}
		rewind (File);
		int Copy = fread (Memory, sizeof (char), Size, File);
		fclose (File);
		if (Size != Copy)
		{
			free (Memory); Memory = NULL;
			printf ("    Error; fread copied %X instead of %X\n", Copy, Size);
			continue;
		}

	// --- Converting ---

		char Tile [8];
		for (int Loc = 0; Loc < Size; Loc += 4)
		{
			for (int C = 0, B = 0; C < 4; C++)
			{
				Tile [B++] = (Memory [Loc + C] >> 4) & 0x0F;
				Tile [B++] = Memory [Loc + C] & 0x0F;
			}
			for (int C = 0; C < 4; C++)
			{
				char P = 0;
				for (int B = 0; B < 8; B++)
				{
					P = (P << 1) | (Tile [B] >> C) & 1;
				}
				Memory [Loc + C] = P;
			}
		}

	// --- Compress ---

		int Return = KosComp (Memory, Size);
		if (Return != 0)
		{
			free (Memory); Memory = NULL;
			switch (KosComp (Memory, Size))
			{
				case -1: { printf ("    KosSpeComp: Memory allocation error...\n"); } break;
				case -2: { printf ("    KosSpeComp: Input size error...\n"); } break;
			}
			continue;
		}

	// --- Saving ---

		strcpy (ExtName, "ksp");
		if ((File = fopen (Direct, "wb")) == NULL)
		{
			free (Memory); Memory = NULL;
			printf ("    Error; could not save the file\n");
			continue;
		}
		if ((Copy = fwrite (Memory, sizeof (char), Size, File)) != Size)
		{
			fclose (File);
			free (Memory); Memory = NULL;
			printf ("    Error; fwrite copied %X instead of %X\n", Copy, Size);
			continue;
		}
		fclose (File);
		free (Memory); Memory = NULL;

// -----------------------------------------------------------------------------
// Palette
// -----------------------------------------------------------------------------

		strcpy (SpaceName, "Pal.pal");
		ExtName = &SpaceName [4];
		printf ("    %s\n", FileName);

		File = fopen (Direct, "rb");
		if (File == NULL)
		{
			printf ("    Error; could not open the file...\n");
			continue;
		}
		fseek (File, 0x00, SEEK_END);
		Size = ftell (File);
		Memory = (char*) malloc (Size);
		if (Memory == NULL)
		{
			fclose (File);
			printf ("    Error; could not allocate memory for file...\n");
			continue;
		}
		rewind (File);
		Copy = fread (Memory, sizeof (char), Size, File);
		fclose (File);
		if (Size != Copy)
		{
			free (Memory); Memory = NULL;
			printf ("    Error; fread copied %X instead of %X\n", Copy, Size);
			continue;
		}

	// --- Converting ---

		for (int Loc = 0, Pos = 0; Loc < Size; )
		{
			char Col = (Memory [Loc++] << 2) & 0x30;
			Col |= (Memory [Loc] >> 4) & 0x0C;
			Col |= (Memory [Loc++] >> 2) & 0x03;
			Memory [Pos++] = Col;
		}
		Size >>= 1;

	// --- Saving ---

		strcpy (ExtName, "sms.pal");
		if ((File = fopen (Direct, "wb")) == NULL)
		{
			free (Memory); Memory = NULL;
			printf ("    Error; could not save the file\n");
			continue;
		}
		if ((Copy = fwrite (Memory, sizeof (char), Size, File)) != Size)
		{
			fclose (File);
			free (Memory); Memory = NULL;
			printf ("    Error; fwrite copied %X instead of %X\n", Copy, Size);
			continue;
		}
		fclose (File);
		free (Memory); Memory = NULL;



// -----------------------------------------------------------------------------
// Mappings
// -----------------------------------------------------------------------------

		strcpy (SpaceName, "Map.map");
		ExtName = &SpaceName [4];
		printf ("    %s\n", FileName);

		File = fopen (Direct, "rb");
		if (File == NULL)
		{
			printf ("    Error; could not open the file...\n");
			continue;
		}
		fseek (File, 0x00, SEEK_END);
		Size = ftell (File);
		Memory = (char*) malloc (Size);
		if (Memory == NULL)
		{
			fclose (File);
			printf ("    Error; could not allocate memory for file...\n");
			continue;
		}
		rewind (File);
		Copy = fread (Memory, sizeof (char), Size, File);
		fclose (File);
		if (Size != Copy)
		{
			free (Memory); Memory = NULL;
			printf ("    Error; fread copied %X instead of %X\n", Copy, Size);
			continue;
		}

	// --- Converting ---

		for (int Loc = 0; Loc < Size; )
		{
			u_short Tile = Memory [Loc] << 0x08;
			Tile |= (Memory [Loc+1] & 0xFF);
			Tile = (Tile & 0x1FF) | ((Tile & 0x3800) >> 2) | ((Tile & 0x8000) >> 3);
			Memory [Loc++] = Tile;
			Memory [Loc++] = Tile >> 0x08;
		}

	// --- Creating differentials ---

		int SplitSize = ((256/8)*(192/8))*2;
		int MapInitSize = SplitSize;
		char *MapInit = (char*) calloc (MapInitSize, sizeof (char));
		if (MapInit == NULL)
		{
			free (Memory); Memory = NULL;
			printf ("    Error; could not allocate MapInit\n");
			continue;
		}
		int *LogData = NULL; int LogSize = 0, LogPos = 0;
		int Loc;
		for (Loc = 0; Loc < SplitSize; Loc += 2)
		{
			if (	Memory [(SplitSize*0) + Loc + 0] != Memory [(SplitSize*1) + Loc + 0]	||
				Memory [(SplitSize*0) + Loc + 0] != Memory [(SplitSize*2) + Loc + 0]	||
				Memory [(SplitSize*1) + Loc + 0] != Memory [(SplitSize*2) + Loc + 0]	||
				Memory [(SplitSize*0) + Loc + 1] != Memory [(SplitSize*1) + Loc + 1]	||
				Memory [(SplitSize*0) + Loc + 1] != Memory [(SplitSize*2) + Loc + 1]	||
				Memory [(SplitSize*1) + Loc + 1] != Memory [(SplitSize*2) + Loc + 1]	)
			{
				if (LogPos >= LogSize)
				{
					LogSize <<= 1; if (LogSize == 0) { LogSize = 0x10; }
					int *LogNew = (int*) realloc (LogData, LogSize * sizeof (int));
					if (LogNew == NULL)
					{
						break;
					}
					LogData = LogNew;
				}
				LogData [LogPos++] = Loc;
			}
			else
			{
				MapInit [Loc + 0] = Memory [Loc + 0];
				MapInit [Loc + 1] = Memory [Loc + 1];
			}
		}
		if (Loc < SplitSize)
		{
			free (MapInit); MapInit = NULL;
			free (LogData); LogData = NULL;
			free (Memory); Memory = NULL;
			printf ("    Error; could not reallocate log data\n");
			continue;
		}
		LogSize = LogPos;

	// --- Compress ---

		Return = KosComp (MapInit, MapInitSize);
		if (Return != 0)
		{
			free (MapInit); MapInit = NULL;
			free (LogData); LogData = NULL;
			free (Memory); Memory = NULL;
			switch (KosComp (Memory, Size))
			{
				case -1: { printf ("    KosSpeComp: Memory allocation error...\n"); } break;
				case -2: { printf ("    KosSpeComp: Input size error...\n"); } break;
			}
			continue;
		}

	// --- Saving ---

		strcpy (ExtName, "ksp");
		if ((File = fopen (Direct, "wb")) == NULL)
		{
			free (MapInit); MapInit = NULL;
			free (LogData); LogData = NULL;
			free (Memory); Memory = NULL;
			printf ("    Error; could not save the file\n");
			continue;
		}
		if ((Copy = fwrite (MapInit, sizeof (char), MapInitSize, File)) != MapInitSize)
		{
			fclose (File);
			free (MapInit); MapInit = NULL;
			free (LogData); LogData = NULL;
			free (Memory); Memory = NULL;
			printf ("    Error; fwrite copied %X instead of %X\n", Copy, MapInitSize);
			continue;
		}
		fclose (File);
		free (MapInit); MapInit = NULL;

// -----------------------------------------------------------------------------
// Swap mappings...
// -----------------------------------------------------------------------------

		int LogSet = 0, UncSize = 0;
		for (LogPos = 0; LogPos < LogSize; )
		{
			int Start = LogData [LogPos];
			int Slot = Start;
			while (Slot == LogData [LogPos] && LogPos < LogSize)
			{
				Memory [(SplitSize*0) + UncSize] = Memory [(SplitSize*0) + Slot];
				Memory [(SplitSize*1) + UncSize] = Memory [(SplitSize*1) + Slot];
				Memory [(SplitSize*2) + UncSize] = Memory [(SplitSize*2) + Slot];
				UncSize++; Slot++;
				Memory [(SplitSize*0) + UncSize] = Memory [(SplitSize*0) + Slot];
				Memory [(SplitSize*1) + UncSize] = Memory [(SplitSize*1) + Slot];
				Memory [(SplitSize*2) + UncSize] = Memory [(SplitSize*2) + Slot];
				UncSize++; Slot++;
				LogPos++;
			}
			LogData [LogSet++] = ((Start & 0xFFFF) << 0x10) | ((Slot - Start) & 0xFFFF);
		}

	// --- Saving swap mappings ---

			// Top map

		strcpy (&ExtName [-1], " 1.map");
		if ((File = fopen (Direct, "wb")) == NULL)
		{
			free (LogData); LogData = NULL;
			free (Memory); Memory = NULL;
			printf ("    Error; could not save %s\n", FileName);
			continue;
		}
		if ((Copy = fwrite (&Memory [(SplitSize*0)], sizeof (char), UncSize, File)) != UncSize)
		{
			fclose (File);
			free (LogData); LogData = NULL;
			free (Memory); Memory = NULL;
			printf ("    Error; fwrite copied %X instead of %X\n", Copy, UncSize);
			continue;
		}
		fclose (File);

			// Middle map

		strcpy (&ExtName [-1], " 2.map");
		if ((File = fopen (Direct, "wb")) == NULL)
		{
			free (LogData); LogData = NULL;
			free (Memory); Memory = NULL;
			printf ("    Error; could not save %s\n", FileName);
			continue;
		}
		if ((Copy = fwrite (&Memory [(SplitSize*1)], sizeof (char), UncSize, File)) != UncSize)
		{
			fclose (File);
			free (LogData); LogData = NULL;
			free (Memory); Memory = NULL;
			printf ("    Error; fwrite copied %X instead of %X\n", Copy, UncSize);
			continue;
		}
		fclose (File);

			// Bottom map

		strcpy (&ExtName [-1], " 3.map");
		if ((File = fopen (Direct, "wb")) == NULL)
		{
			free (LogData); LogData = NULL;
			free (Memory); Memory = NULL;
			printf ("    Error; could not save %s\n", FileName);
			continue;
		}
		if ((Copy = fwrite (&Memory [(SplitSize*2)], sizeof (char), UncSize, File)) != UncSize)
		{
			fclose (File);
			free (LogData); LogData = NULL;
			free (Memory); Memory = NULL;
			printf ("    Error; fwrite copied %X instead of %X\n", Copy, UncSize);
			continue;
		}
		fclose (File);

		free (Memory); Memory = NULL;

	// --- Saving swap log data ---

		strcpy (&ExtName [-1], ".log");
		if ((File = fopen (Direct, "wb")) == NULL)
		{
			free (LogData); LogData = NULL;
			printf ("    Error; could not save %s\n", FileName);
			continue;
		}
		for (int Loc = 0; Loc < LogSet; Loc++)
		{
		//	fputc (LogData [Loc] >> 0x08, File);	// Size (Don't need upper byte really...)
			fputc (LogData [Loc] >> 0x00, File);

			fputc (LogData [Loc] >> 0x10, File);	// Start positition (little endian)
			fputc (LogData [Loc] >> 0x18, File);
		}
	//	fputc (0x00, File);	// end with size of 0 (Don't need upper byte really...)
		fputc (0x00, File);
		fclose (File);

		free (LogData); LogData = NULL;

	}
	printf ("\nPress enter key to exit...\n");
	fflush (stdin); getchar ( ); return (0x00);
}

// =============================================================================
