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


/*
int	argc = 4;
char	*(argv[6]) = {"dummy", "dh0:spiele/battleisle/map", "31", "dh0:temp/Temp.txt" };
*/


/* Dient zur Speicherung von Koordinaten von Gebäuden bzw. Units, deren   */
/* Inhalte später noch ausgegeben werden.                                 */
typedef struct{
	USHORT	x, y;
} Punkt;



/* Dient zum Einlesen eines SHP-Eintrages für HQs, Depots usw. */
typedef struct{
	UBYTE	Besitzer, Typ, Index;
	UBYTE	Aldinium, pad;
	UBYTE	Inhalt[7];
} SHP_Type;




/*****************************************************************************/
/* Diese Function ist die vom der systeminternen Funktion QSORT benötigte    */
/* Vergleichsprozedur.                                                       */
/*****************************************************************************/
int	shp_compare( const SHP_Type	*e1,
				 const SHP_Type	*e2)
{
	if( e1->Index < e2->Index )
		return(-1);
	if( e1->Index == e2->Index )
		return(0);
	if( e1->Index > e2->Index )
		return(1);
};




void main( int argc, char *(argv[]) )
{

	int 	i=0, x, y, j;


	/* Variablen für Dateizugriff */
	char Dateiname[100];
	FILE *fin, *shp, *ausgabe;
	UBYTE terrain, unit, Nof_shp_entries;

	SHP_Type 	shp_eintrag, shp_feld[100];



	/* Ausmaße der Karte */
	USHORT	Hex_Zeilen, Hex_Spalten;





	/* Speicherung der Gebäude mit ihren Koordinaten. Die Reihenfolge der     */
	/* Einträge korrespondiert mit der laufenden Nummer im SHP-File.          */
	
	Punkt Hq[2];
	USHORT Hq_Zaehler = 0, hqz =0;

	Punkt Factory[100];
	USHORT Factory_Zaehler=0;

	Punkt Depot[100];
	USHORT Depot_Zaehler=0;

	Punkt Transporter[100];
	USHORT Transporter_Zaehler = 0;





	/* Auswertung der Argumente */
	
	if( argc != 4 )
	{
		printf("AUFRUF:\nBI_Decompiler <Datendirectory> <Levelnummer> <Zieldatei>\n");

		exit( 20 );
	};
		
		

	printf("\n\n\n\n");
	printf("BATTLE ISLE Level Decompiler    Version 1.0\n");
	printf("Copyright 1991 by Pius_XII  & Panorama Computer Club Duisburg\n");
	printf("Dieses Programm und alle dazugehörigen Daten dürfen frei kopiert werden.\n");
	printf("Für mehr Informationen könnt ihr unsere Mailbox anrufen:02065/74199\n");
	printf("\n\n");




	/* Synthetisieren der Dateinamen und öffnen der Dateien */

	while( Dateiname[i] = (argv[1])[i]  )
		i++;

	if( Dateiname[i-1] != '/' )
	{
		Dateiname[i++] = '/';
		Dateiname[i] = 0;
	};

	strcat( Dateiname, argv[2] );
	i += 2;
	Dateiname[i++] = '.';
	Dateiname[i] = 0;


	strcat( Dateiname, "FIN" );

	if( !(fin = fopen( Dateiname, "r" )))
	{
		printf("Error beim öffnen von %s !\n", Dateiname );
		exit(20);
	};

	Dateiname[i] = 0;
	strcat( Dateiname, "SHP" );

	if( !(shp = fopen( Dateiname, "r" )))
	{
		printf("Error beim öffnen von %s !\n", Dateiname );
		fclose( fin );
		exit(20);
	};



	if( !(ausgabe = fopen( argv[3], "w" )))
	{
		printf("Error beim öffnen von %s !\n", argv[3] );
		fclose( fin );
		fclose( shp );
		exit(20);
	};




	/* Ab hier stehen die benötigten Dateien bereit */




	/* Einlesen der Kartenausmaße und Ausgabe ins Zielfile */
	fread( &Hex_Spalten, 2, 1, fin );
	fprintf( ausgabe, ":%02hX ;Spalten\n", Hex_Spalten );

	fread( &Hex_Zeilen, 2, 1, fin );
	fprintf( ausgabe, ":%02hX ;Zeilen\n", Hex_Zeilen );

	fprintf( ausgabe, "\n\n\n");





	/* Bearbeiten der Karte */

	fprintf( ausgabe, ";  ");
	for( x=0; x<Hex_Spalten; x++ )
		fprintf( ausgabe, " -%02hX- ",x );
	fprintf( ausgabe, "\n\n");


	for(y=0; y<Hex_Zeilen; y++ )
	{
		/* Äußere Schleife indiziert die Zeilen */

		fprintf( ausgabe, ":%02hX: ",y);
	
		for( x=0; x<Hex_Spalten; x++ )
		{

			/* Innere Schleife indiziert die Spalten einer jeden Zeile */

			/* Einlesen von Terrain und Unit */
			fread( &terrain, 1, 1, fin );
			fread( &unit, 1, 1, fin );





			/* Sonderbehandlung der Factories, Depots und Hqs */
			if( (terrain == 44) || (terrain == 46) || (terrain == 94 ) )
			{
				Factory[ Factory_Zaehler ].x = x;
				Factory[ Factory_Zaehler ].y = y;
				Factory_Zaehler++;

			}else{

				if( (terrain == 32) || (terrain == 93) || (terrain == 96 ) )
				{
					Depot[ Depot_Zaehler ].x = x;
					Depot[ Depot_Zaehler ].y = y;
					Depot_Zaehler++;

				}else{

					if( (terrain == 47) || (terrain == 95) )
					{
						Hq[ Hq_Zaehler ].x = x;
						Hq[ Hq_Zaehler ].y = y;
						Hq_Zaehler++;

					};
				};
			};







			/* Sonderbehandlung für Transportfahrzeuge */
			if( (unit == 12) || (unit == 13) ||
				(unit == 24) || (unit == 25) ||
				(unit == 28) || (unit == 29) ||
				(unit == 30) || (unit == 31) ||
				(unit == 38) || (unit == 39) ||
				(unit == 46) || (unit == 47)    )
			{
				Transporter[ Transporter_Zaehler ].x = x;
				Transporter[ Transporter_Zaehler ].y = y;
				Transporter_Zaehler++;

			};
			



			if( unit != 255 )
				fprintf( ausgabe, "%02hX/%02hX ", terrain, unit );
			else
				fprintf( ausgabe, "%02hX    ", terrain );


		};

		fprintf( ausgabe, "\n");



	};

	fprintf( ausgabe, "\n\n\n");


	/* Nun erfolgt das Einlesen des SHP-Files */


	fseek( shp, 27, 0 );
	fread( &Nof_shp_entries, 1, 1, shp );


	for( i=0; i<Nof_shp_entries; i++ )
		fread( &shp_feld[i], sizeof (SHP_Type), 1, shp );




	/* Die Einträge werden nun nach aufsteigenden Index-Komponenten sortiert, */
	/* wobei der Zusammenhang einer Gruppe (z.B. HQ) erhalten bleibt.         */

	i=j=2; /* HQs brauchen nicht sortiert zu werden */

	while( i<Nof_shp_entries )
	{
		/* Einstellen von j auf den letzten Eintrag des Typs von Eintrag i */
		while( (j<Nof_shp_entries) && (shp_feld[i].Typ == shp_feld[j].Typ) )
			j++;
		j--;

		if( i<j )
			qsort( &shp_feld[i], j-i+1, sizeof( SHP_Type ), shp_compare );

		j++;
		i=j;

	};






	for( i=0; i<Nof_shp_entries; i++ )
	{

		memcpy( &shp_eintrag, &shp_feld[i], sizeof (SHP_Type));



		/* Anpassen der Speicherweise der SHP-Files an die Unittabelle */

		if( shp_eintrag.Besitzer == 0 )
		{
			/* Rot */
			for( j=0; j<7; j++ )
				if( shp_eintrag.Inhalt[j] != 255 )
					shp_eintrag.Inhalt[j] *= 2;
		}else{
			/* Gelb */
			for( j=0; j<7; j++ )
				if( shp_eintrag.Inhalt[j] != 255 )
					shp_eintrag.Inhalt[j] = shp_eintrag.Inhalt[j]*2 + 1;
		};


		
		switch (shp_eintrag.Typ)
		{

		case 0 :	/* Hauptquartier */

					fprintf( ausgabe, ":HQ:  Besitzer: %1hX   Index: %02hX   Aldinium: %02hX  Inhalt: %02hX %02hX %02hX %02hX %02hX %02hX %02hX ;   X/Y-Position: %02hX/%02hX\n", shp_eintrag.Besitzer, shp_eintrag.Index, 
								shp_eintrag.Aldinium, shp_eintrag.Inhalt[0], shp_eintrag.Inhalt[1], shp_eintrag.Inhalt[2], shp_eintrag.Inhalt[3], shp_eintrag.Inhalt[4], shp_eintrag.Inhalt[5], shp_eintrag.Inhalt[6], 
								Hq[shp_eintrag.Index].x, Hq[shp_eintrag.Index].y ); 
					break;

		case 1 :	/* Factory */
					fprintf( ausgabe, ":FA:  Besitzer: %1hX   Index: %02hX   Aldinium: %02hX  Inhalt: %02hX %02hX %02hX %02hX %02hX %02hX %02hX ;   X/Y-Position: %02hX/%02hX\n", shp_eintrag.Besitzer, shp_eintrag.Index, 
								shp_eintrag.Aldinium, shp_eintrag.Inhalt[0], shp_eintrag.Inhalt[1], shp_eintrag.Inhalt[2], shp_eintrag.Inhalt[3], shp_eintrag.Inhalt[4], shp_eintrag.Inhalt[5], shp_eintrag.Inhalt[6], 
								Factory[shp_eintrag.Index].x, Factory[shp_eintrag.Index].y ); 
					break;

		case 2 :	/* Depot */
					fprintf( ausgabe, ":DE:  Besitzer: %1hX   Index: %02hX   Aldinium: %02hX  Inhalt: %02hX %02hX %02hX %02hX %02hX %02hX %02hX ;   X/Y-Position: %02hX/%02hX\n", shp_eintrag.Besitzer, shp_eintrag.Index, 
								shp_eintrag.Aldinium, shp_eintrag.Inhalt[0], shp_eintrag.Inhalt[1], shp_eintrag.Inhalt[2], shp_eintrag.Inhalt[3], shp_eintrag.Inhalt[4], shp_eintrag.Inhalt[5], shp_eintrag.Inhalt[6], 
								Depot[shp_eintrag.Index].x, Depot[shp_eintrag.Index].y ); 
					break;

		case 3 :	/* Transporter */
					fprintf( ausgabe, ":TR:  Besitzer: %1hX   Index: %02hX   Aldinium: %02hX  Inhalt: %02hX %02hX %02hX %02hX %02hX %02hX %02hX ;   X/Y-Position: %02hX/%02hX\n", shp_eintrag.Besitzer, shp_eintrag.Index, 
								shp_eintrag.Aldinium, shp_eintrag.Inhalt[0], shp_eintrag.Inhalt[1], shp_eintrag.Inhalt[2], shp_eintrag.Inhalt[3], shp_eintrag.Inhalt[4], shp_eintrag.Inhalt[5], shp_eintrag.Inhalt[6], 
								Transporter[shp_eintrag.Index].x, Transporter[shp_eintrag.Index].y ); 

					break;

		};



	};



	fclose( fin );
	fclose( shp );
	fclose( ausgabe );

	printf("Alles klar!\n");

}
