//***********************************
//*			BMP2MAP-Konverter		*
//***********************************
//
// Nutzung und Weitergabe nur unter Einverständnis.!
// Benutzung des Quelltextes ist untersagt!
// Danke.
//

#include "main.h"
#include "bmp2map.h"

void bmp2map()
{
	int x, y, sa, sc, customrect, p;
	time_t timestamp;

	time( &timestamp );

	srand( timestamp );

	system("cls");
	printf("Write Statics? (1=yes,2=WSC,3=Only Items)");
	scanf("%i", &sa);
	printf("Write MapZ-BMP? (1=yes)");
	scanf("%i", &sc);

	printf("Handle Custom Rect? (1=yes)");
	scanf("%i", &customrect);


	if( customrect == 1 )
	{
		printf( "MinX: " );
		scanf( "%i", &MinX );
		printf( "MinY: " );
		scanf( "%i", &MinY );
		printf( "MaxX: " );
		scanf( "%i", &MaxX );
		printf( "MaxY: " );
		scanf( "%i", &MaxY );
	}
	else
	{
		MinX = 0;
		MaxX = XBORDER;
		MinY = 0;
		MaxY = YBORDER;
	}

	printf("---------------------------------------\n");

	printf("SYS|Clear Arrays...\n");
	for(x=MinX; x<MaxX; x++)
		for(y=MinY; y<MaxY; y++)
		{
			Add[x][y]=NULL;
			BMPID[x][y]=0;
			tmp[x][y]=0;
		}

	printf("SYS|Load external Data...\n");
	getConfig();
	getItems();
	getColor();
	getMntn();
	getTiles();
	
	if( sa != 3 )
	{
		loadCoastData();
		loadSmoothData();
		loadSmoothItem();
		loadCliffData();
	}

	printf("SYS|Load karte.bmp and mapz.bmp...\n");
	CacheBMP();

	if( sa != 3 )
	{
		CoastBMP();
	}
	
	printf("SYS|Convert...\n");
	BMP2MUL();

	if( sa != 3 )
	{
		Mountain();
		
		printf("SYS|Create Coast and Crossings...\n");
		for(x=MinX; x<MaxX; x++)
			for(y=MinY; y<MaxY; y++)
			{
				//MakeCoast und SmoothTiles getauscht
				MakeCoast(x, y);
				SmoothTiles(x, y);			
				MakeCliffs(x, y);
				SmoothItem(x, y);
			}
	}

	printf("SYS|Process MapZ...\n");
	ProcessZ();

	printf("Factor for Itemprobabilities: ");
	scanf("%i", &p);
	printf("SYS|Set Items...\n");
	SetItem( p );

	printf("SYS|Load AddFile...\n");
	CheckAddFile();

	if(sa == 1 || sa == 3)
	{
		WriteStatics();
		printf("Write\t%s...\n\t%s...\n",staidx,statics);
	}
	else if(sa == 2)
	{
		WriteStatics2Wsc();
		printf("Write\tstatics.wsc");
	}
	
	if( sa != 3 )
	{
		printf("\t%s...\n",mapmul);
		WriteMUL();
	}

	if(sc)WriteBMP("bmp\\mapz_xxl.bmp",0);
	printf("Done\n");
}




//--------------------------------------------------
//
//--------------------------------------------------
void CacheBMP()
{
	int stuff;
	int x, y, bmpxlen, bmpylen;
	FILE *map0, *map1;
	unsigned char z;

	map0 = fopen("bmp/karte.bmp", "rb");
	map1 = fopen("bmp/mapz.bmp", "rb");

	fseek( map0, 0x12, SEEK_SET );
	fread( &bmpxlen, 4, 1, map0 );
	fread( &bmpylen, 4, 1, map0 );


	fseek( map0, 0x36, SEEK_SET );
	fseek( map1, 0x36, SEEK_SET );

	for(y=bmpylen-1; y>=0; y--)
	for(x=0; x<bmpxlen; x++)
	{
		fread( &BMPID[x][y], 3, 1, map0 );

		//fread( &BMPZ[x][y], 1, 1, map1 );	//r
		fread( &z, 1, 1, map1 );
		BMPZ[x][y] = z - 128;
		fread( &stuff, 2, 1, map1 );		//gb
	}

	fclose(map0);
	fclose(map1);
}



//--------------------------------------------------
//
//--------------------------------------------------
void WriteBMP(char filename[50], int mode)
{
long x, y;
long w;
int a;
FILE *bmp;
	
	printf("\t%s...\n",filename);
	bmp = fopen(filename, "wb");

	//FileHeader schreiben
	w = 19778;					//Anfang
	fwrite(&w, 2, 1, bmp);
	w = 0;						//Umfang der Datei in Byte
	fwrite(&w, 4, 1, bmp);
	w = 0;						//Reserved x2
	fwrite(&w, 2, 2, bmp);
	w = 54;						//Offset
	fwrite(&w, 4, 1, bmp);

	//InfoHeader
	w = 40;						//Infoheadersize
	fwrite(&w, 4, 1, bmp);
	w = XBORDER;				//Width
	fwrite(&w, 4, 1, bmp);
	w = YBORDER;				//Height
	fwrite(&w, 4, 1, bmp);
	w = 1;						//Planes
	fwrite(&w, 2, 1, bmp);
	w = 24;						//ColorBits
	fwrite(&w, 2, 1, bmp);
	w = 0;						//Compression
	fwrite(&w, 4, 1, bmp);
	w = 0;						//ImageSize
	fwrite(&w, 4, 1, bmp);
	w = 3780;					//Res
	fwrite(&w, 4, 1, bmp);
	w = 3780;					//Res
	fwrite(&w, 4, 1, bmp);
	w = 0;						//?
	fwrite(&w, 4, 1, bmp);
	w = 0;						//?
	fwrite(&w, 4, 1, bmp);

	//Schreiben aus dem Cache
	//von links unten nach rechts oben
	for(y=YBORDER-1; y>=0; y--)
	{
		for(x=0; x<XBORDER; x++)
		{
			if(!mode){
				w = ( (MapAlt[x][y]+128) << 16) + ( (MapAlt[x][y]+128) << 8) + ( (MapAlt[x][y]+128) << 0);
				fwrite(&w,3,1,bmp);
			}
			else fwrite(&BMPID[x][y],3,1,bmp);
		}

		//Auf 32-Bit-End-per-Row bringen
		w = 0;
		a = (4-((XBORDER*3)%4))%4;
		fwrite(&w, 1, a, bmp);
	}

	fclose(bmp);
}



//--------------------------------------------------
//
//--------------------------------------------------
void ProcessZ()
{
int x,y;
mntn *neu;

	for(x=MinX; x<MaxX; x++)
		for(y=MinY; y<MaxY; y++)
		{
			neu=a_mntn;
			if(BMPZ[x][y]!=0)
			{
				MapAlt[x][y] += BMPZ[x][y];
				while(neu->next!=NULL)
					{
					if( BMPID[x][y] ==  neu->color ){
						if(neu->check)
						{
							MapAlt[x][y] -= BMPZ[x][y];
							break;
						}
						else if( MapAlt[x][y]>127 && BMPZ[x][y]>0)
							MapAlt[x][y]=RandomNum(120,125);
						break;
						}
					neu=neu->next;
					}
				if( MapAlt[x][y]>127)
				{
					MapAlt[x][y]=RandomNum(120,125);
				}
			}
		}
}



//--------------------------------------------------
//
//--------------------------------------------------
void CheckAddFile()
{
	short id, x, y;
	signed char z;
	int c=0;
	char test[50];

	FILE *afile;

	afile = fopen("addfiles/addfile.dat", "r");

	do
	{
		fscanf(afile, "%s", &test);
		if(strstr(test, "##########")>0) continue;
		id = hstr2num(test);
		fscanf(afile, "%s", &test);
		x = str2num(test);
		fscanf(afile, "%s", &test);
		y = str2num(test);
		fscanf(afile, "%s", &test);
		z = str2num(test);
		fgets(test,10,afile);			//Leerzeile

		if(id>-1)
		{
			MapID[x][y] = id;
			MapAlt[x][y] = z;
			c++;
		}
	}
	while(!feof(afile));

	fclose(afile);

	printf("---------------------------------------\n");
	printf("Tiles changed: %d\n", c);
}



//--------------------------------------------------
//
//--------------------------------------------------
void BMP2MUL()
{
	int x, y;
	liste*neu;
	//rrggbb

	for(x=MinX; x<MaxX; x++)
		for(y=MinY; y<MaxY; y++)
		{	
			MapID[x][y] = 0x00A8;					// setze Default-Texture
			MapAlt[x][y] = -5;
			MapOcc[x][y] = 0;
			
			neu=a_liste;
			while( neu->next!=NULL )
			{
				if(BMPID[x][y] == neu->BMPID)	
				{	
					MapID[x][y] = RandomID(neu->MAPID);
					MapAlt[x][y]= RandomNum(neu->low,neu->high);
					break;
				}
				neu = neu->next;
			}
			neu=b_liste;							// wechseln der Datei
			while( neu->next!=NULL )
			{
				if(BMPID[x][y] == neu->BMPID)	
				{	
					MapID[x][y] = RandomID(neu->MAPID);
					MapAlt[x][y]= RandomNum(neu->low,neu->high);
					break;
				}
				neu = neu->next;
			}
		}
}



//--------------------------------------------------
//
//--------------------------------------------------
void WriteMUL()
{
int blockx, blocky, x, y;
int empty = 0;
int grey = 0x0244;

FILE *map0 = fopen(mapmul,"wb");

	for(blockx=0; blockx<768; blockx++)
	{
		for(blocky=0; blocky<512; blocky++)
		{
			fwrite( &empty, 4, 1, map0 );	//BlockHeader ohne Funktion

			for(y=(8*blocky); y<(8*(blocky+1)); y++)
			{
				for(x=(8*blockx); x<(8*(blockx+1)); x++)
				{
					if(x >= MinX && x < MaxX && y >= MinY && y < MaxY)
					{
						fwrite( &MapID[x][y], 2, 1, map0 );
						if( MapAlt[x][y] > 125 )
						{
							MapAlt[x][y] = RandomNum(120,125);;							
						}
						fwrite( &MapAlt[x][y], 1, 1, map0 );
					}
					else
					{
						fwrite( &grey, 2, 1, map0 );
						fwrite( &empty, 1, 1, map0 );
					}
				}
			}
		}
	}
	fclose(map0);
}



//--------------------------------------------------
//
//--------------------------------------------------
void WriteStatics()
{
int blockx, blocky, x, y, start, length, items;
short color;
signed char x2, y2;
FILE *staidx0;
FILE *statics0;

	staidx0 = fopen(staidx, "wb");
	statics0 = fopen(statics, "wb");

	items = 0;
	start = 0;

	for(blockx=0; blockx<768; blockx++)
	{
		for(blocky=0; blocky<512; blocky++)
		{
			length = 0;
			for(y=(8*blocky); y<(8*(blocky+1)); y++)
			{
				for(x=(8*blockx); x<(8*(blockx+1)); x++)
				{
					color=0;
					x2=x%8;
					y2=y%8;

					if(x < MinX || x >= MaxX || y < MinY || y >= MaxY) continue;
					
					if( Add[x][y]!=NULL )
					{
						fwrite( &Add[x][y]->ID, 2, 1, statics0 );
						fwrite( &x2, 1, 1, statics0 );
						fwrite( &y2, 1, 1, statics0 );
						fwrite( &Add[x][y]->zlev, 1, 1, statics0 );
						fwrite( &Add[x][y]->color, 2, 1, statics0 );		// unknown
						length+=7;
						items++;
						Add[x][y]=Add[x][y]->next;

						while(Add[x][y]->next!=NULL)			// Durchlauf der Itemsliste
						{
							fwrite( &Add[x][y]->ID, 2, 1, statics0 );
							fwrite( &x2, 1, 1, statics0 );
							fwrite( &y2, 1, 1, statics0 );
							fwrite( &Add[x][y]->zlev, 1, 1, statics0 );
							fwrite( &Add[x][y]->color, 2, 1, statics0 );	// unknown
							length+=7;
							items++;
							Add[x][y]=Add[x][y]->next;
						}		
					}
				}
			}
			fwrite( &start, 4, 1, staidx0 );
			start+=length;
			if(length==0) length=0xFFFFFFFF;
			fwrite( &length, 4, 1, staidx0 );
			fwrite( &length, 4, 1, staidx0 );
		}
	}
	fclose(staidx0);
	fclose(statics0);
	printf("Static Items: %i\n", items);
	printf("---------------------------------------\n");
}

void WriteStatics2Wsc()
{
int blockx, blocky, x, y, items, serial;
FILE *wsc;
	
	wsc = fopen("statics.wsc", "wb");

	items = 0;
	serial = 0;

	for(blockx=0; blockx<768; blockx++)
	{
		for(blocky=0; blocky<512; blocky++)
		{
			for(y=(8*blocky); y<(8*(blocky+1)); y++)
			{
				for(x=(8*blockx); x<(8*(blockx+1)); x++)
				{
					if(x < MinX || x >= MaxX || y < MinY || y >= MaxY) continue;
					
					if( Add[x][y]!=NULL )
					{
						fprintf( wsc, "SECTION WORLDITEM %d\n", &serial );
						fprintf( wsc, "SERIAL %d\n", &serial );
						fprintf( wsc, "ID %d\n", &Add[x][y]->ID ); 
						fprintf( wsc, "X %d\n", &x ); 
						fprintf( wsc, "Y %d\n", &y );
						fprintf( wsc, "Z %d\n", &Add[x][y]->zlev );
						fprintf( wsc, "COLOR %d\n", &Add[x][y]->color );
						fprintf( wsc, "\n" );
						items++;
						serial++;
						Add[x][y]=Add[x][y]->next;		
					}
				}
			}
		}
	}
	fclose(wsc);
	printf("Static Items: %i\n", items);
	printf("---------------------------------------\n");
}



//--------------------------------------------------
//
//--------------------------------------------------
int RandomID(int r_cat)
{
	int id = 0x0000;
	cat *neu;
	neu=a_cat;

	while( neu->next!=NULL )
	{
		if( r_cat == neu->cat )
		{
			id=RandomNum(1,neu->anzahl);
			id=neu->id[id-1];
			return id;
		}
		neu = neu->next;
	}
	return 0;
}


//--------------------------------------------------
//
//--------------------------------------------------
int RandomNum(int nLowNum, int nHighNum)
{
	if (nLowNum == nHighNum)
		return nLowNum;
	if (nHighNum - nLowNum + 1)
		return ((rand() % (nHighNum - nLowNum + 1)) + nLowNum);
	else
		return nLowNum;
}



//--------------------------------------------------
//
//--------------------------------------------------
int str2num(char *s) // Convert string to integer
{
	unsigned int i;
	int n=0;
	int neg=0;
	unsigned int length=strlen(s);
	for(i=0;i<length;i++)
	{
		if (s[i]=='-') neg=1;
		n*=10; // Multiply by 10
		if (isdigit(s[i]))
			n=n+(s[i])-48; // Convert char to number from 0 to 9
	}
	if (neg) n=-n;
	return n;
}

int hstr2num(char *s) // Convert hex string to integer
{
	unsigned int i;
	int n=0;
	
	for (i=0;i<strlen(s);i++)
	{
		n*=16;
		if (isdigit(s[i]))
			n=n+(s[i])-48; // Convert char to number from 0 to 9
		if ((s[i]>=65) && (s[i]<=70)) // Uppercase A-F
			n=n+(s[i])-65+10;
		if ((s[i]>=97) && (s[i]<=102)) // Lowercase A-F
			n=n+(s[i])-97+10;
	}
	if (s[0]=='-') n=-n;
	return n;
}

