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

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


/* In den folgenden Strukturen wird die Farbtabelle für die Übersichtskarte im PMP-File */
/* gespeichert. Das erste Array wird durch die Terrainnummern indiziert und liefert die */
/* Farbnummer dieses Terrains in der Übersichtskarte.                                   */
/* Das zweite Array enthält die 4 Bitplanes. Sie müssen zu Programmbeginn mit 0 initial-*/
/* isiert werden.                                                                       */

UBYTE Terrain_Color[101] = {
10, 6, 14, 1, 5, 5, 5, 9, 9, 9, 
9, 13, 13, 13, 11, 11, 11, 11, 11, 11, 
11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 
8, 0, 0, 0, 0, 1, 1, 1, 1, 14, 
14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 10, 10, 8, 8, 8, 8, 
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
8, 8, 8, 8, 15, 15, 15, 15, 15, 15, 
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 
15, 15, 15, 0, 0, 0, 0, 10, 11, 11, 
11 
};

#define SIZE_OF_BITPLANE 10000
UBYTE Bitmaps[4][SIZE_OF_BITPLANE];


/* Das folgende Array enthält die Daten fürs COM-File. Da dieses File bisher nicht     */
/* entschlüsselt ist, habe ich das größte COM-File (31) als DATAs übernommen und       */
/* speichere diese mit dem neu erzeugten File zusammen ab. Versuche haben gezeigt, daß */
/* dieses Vorgehen unkritisch ist (bisher jedenfalls).                                 */ 
UBYTE Com_Datas[] = {
0x5f, 0x05, 0x00, 0x02, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x21, 0x02, 0x00, 0x32, 0x02, 0x00, 0x44, 
0x00, 0x00, 0x3c, 0x05, 0x00, 0x40, 0x00, 0x00, 0x46, 0x02, 0x00, 0x04, 0x00, 0x00, 0x50, 0x05, 
0x00, 0x02, 0x00, 0x00, 0x28, 0x02, 0x02, 0x44, 0x00, 0x00, 0x5a, 0x05, 0x00, 0x02, 0x00, 0x00, 
0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, 0x00, 0x10, 0x00, 0x00, 0x5a, 0x05, 0x00, 0x20, 
0x01, 0x00, 0x55, 0x05, 0x00, 0x20, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 
0x00, 0x02, 0x00, 0x00, 0x64, 0x05, 0x03, 0x00, 0x00, 0x00, 0x46, 0x05, 0x01, 0x00, 0x00, 0x00, 
0x46, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, 0x00, 0x40, 0x00, 0x00, 
0x28, 0x02, 0x00, 0x44, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x05, 0x00, 0x00, 
0x00, 0x00, 0x00 };



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


typedef struct{
	UBYTE	Token;		/* Codierung: 	0 = EOF erreicht,
										1 = Kein Token mehr in dieser Zeile,
										2 = Doppelpunkt,
										3 = Semikolon (Kommentar),
										4 = Slash (Terrain/Unit Trennung),
										5 = USHORT,
										6 = UBYTE,
										7 = Besitzer,
										8 = Index,
										9 = Aldinium,
										10 = Inhalt
										11 = HQ, 12 = FA, 13 = DE, 14 = TR,
										15 = Falsches Token gefunden -> ERROR     */
	USHORT	Zahl;		/* Nur bei entsprechendem Token belegt */
} Token_Type;



/* Die folgenden Variablen dienen der Speicherung einer Zeile des Eingabefiles. Sie   */
/* werden nur vom Scanner, bzw im Fehlerfall vom Hauptprogramm zur Ausgabe benutzt.   */
#define BUFF_SIZE 500
char buffer[BUFF_SIZE] = "";
int	buffer_pos = 0;






/***************************************************************************************/
/* Errechnet die Position eines Kartenfeldes in einer der Bitplanes aus dem *.PMP File */
/* aufgrund der Position in der Übersichtskarte (!).                                   */
/* Liefert den Byteoffset, der zur Position des ersten Bytes der Bitplane addiert      */
/* werden muß, um auf das Byte zu kommen, das das gewünschte Feld enthält, sowie darin */
/* die Nummer des Bits beginnend bei 0.                                                */
/* Erwartet außerdem die Anzahl Bytes pro Zeile in einer Bitplane.                     */
/***************************************************************************************/
void GetBitPosition( 	USHORT x,
						USHORT y, 
						USHORT Bytes_per_Line,
						USHORT *Bitposition, 
						USHORT *Byteposition )
{

	*Byteposition = (y * Bytes_per_Line) + (x / 8 );
	*Bitposition = 7 - (x % 8);
};













/**************************************************************************************/
/* Scannerfunction. liefert bei Aufruf das nächste Token zurück.Ist der Buffer leer,  */
/* liest sie automatisch die nächste Zeile ein.                                       */
/**************************************************************************************/
void Scanner( 	FILE	*eingabe,
				Token_Type	*Token )
{
	/* Diese Variable buffert eine ganze Zeile des Quellfiles für den Scanner */
	static int	buffer_size = -1;
	static char	c = 0;
	ULONG  		l;


	/* buffer_pos auf das erste non-white-space Zeichen stellen. Dabei wird der Buffer bei */
	/* Bedarf wieder neu gefüllt, bzw das Token 0 zurückgeliefert,wenn FEOF erreicht.      */	
	while( buffer[ buffer_pos ] <= ' ' )
	{
		if( feof( eingabe ))
		{
			Token->Token = 0;
			return;
		};
		if( buffer[ buffer_pos ] == 0 )
		{
			/* Wenn Buffer leer, neue Zeile einlesen und Groß- in Kleinbuchstaben konvertieren */
			while( c < ' ' )
			{
				fread( &c, 1, 1, eingabe );
				if( feof( eingabe ))
				{
					Token->Token = 0;
					return;
				};
			};

			/* c enthält den ersten gültigen Character */
			buffer_size = buffer_pos = 0;
			while( (c >= ' ') && (!feof(eingabe)) )
			{
				buffer[ buffer_size++ ] = c;
				fread( &c, 1, 1, eingabe );
			};

			buffer[ buffer_size ] = 0;
			strlwr( buffer );
		}else{
			buffer_pos++;
		};
	};

	/* Wenn buffer_pos jetzt auf ein 0-Character zeigt, ist die Zeile zu Ende */
	if( buffer[ buffer_pos ] == 0 )
	{
		Token->Token = 1;
		return;
	};


	/* ----------------- Nun wird nach den möglichen Token gesucht ----------------- */

	/* Kommentartoken */
	if( buffer[ buffer_pos ] == ';' )
	{
		Token->Token = 3;
		buffer_pos = buffer_size;
		return;
	};
	
	/* Doppelpunkttoken */
	if( buffer[ buffer_pos ] == ':' )
	{
		Token->Token = 2;
		buffer_pos++;
		return;
	};

	/* Slashtoken */
	if( buffer[ buffer_pos ] == '/' )
	{
		Token->Token = 4;
		buffer_pos++;
		return;
	};
	
	/* HQ */
	if( (buffer[ buffer_pos ] == 'h') && (buffer[ buffer_pos+1 ] == 'q') )
	{
		Token->Token = 11;
		buffer_pos += 2;
		return;
	};

	/* Fabrik */
	if( (buffer[ buffer_pos ] == 'f') && (buffer[ buffer_pos+1 ] == 'a') )
	{
		Token->Token = 12;
		buffer_pos += 2;
		return;
	};

	/* Depot */
	if( (buffer[ buffer_pos ] == 'd') && (buffer[ buffer_pos+1 ] == 'e') )
	{
		Token->Token = 13;
		buffer_pos += 2;
		return;
	};

	/* Transporter */
	if( (buffer[ buffer_pos ] == 't') && (buffer[ buffer_pos+1 ] == 'r') )
	{
		Token->Token = 14;
		buffer_pos += 2;
		return;
	};

	/* "besitzer" */
	if( strncmp( &buffer[buffer_pos], "besitzer", 8 ) == 0 )
	{
		Token->Token = 7;
		buffer_pos += 8;
		return;
	};

	/* "index" */
	if( strncmp( &buffer[buffer_pos], "index", 5 ) == 0 )
	{
		Token->Token = 8;
		buffer_pos += 5;
		return;
	};

	/* "aldinium" */
	if( strncmp( &buffer[buffer_pos], "aldinium", 8 ) == 0 )
	{
		Token->Token = 9;
		buffer_pos += 8;
		return;
	};

	/* "inhalt" */
	if( strncmp( &buffer[buffer_pos], "inhalt", 6 ) == 0 )
	{
		Token->Token = 10;
		buffer_pos += 6;
		return;
	};


	/* Zahl */
	if( (l = strspn( &buffer[ buffer_pos ], "0123456789abcdef" )) > 0 )
	{
		int		i = 0;

		l = l + buffer_pos;

		Token->Zahl = 0;
		
		/* Aufbau der Zahl aus den Hexziffern */
		while( buffer_pos < l )
		{
			Token->Zahl *= 16;
			if( (buffer[ buffer_pos ] >= '0' ) && (buffer[ buffer_pos ] <= '9' ) )
				Token->Zahl += (buffer[ buffer_pos ] - '0' );
			else
				Token->Zahl += (buffer[ buffer_pos ] - 'a' + 10 );
			buffer_pos++;
		};


		if( Token->Zahl > 255 )
			Token->Token = 5;
		else
			Token->Token = 6;
		return;
	};


	/* An dieser Stelle steht fest, das buffer_pos auf ein unbekanntes Token zeigt */
	Token->Token = 15;
	buffer_pos++;

};









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

	int 	i;


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

	
	/* Variablen zum parsen des Quelltextes */
	Token_Type	Token;
	int			Zustand;
	SHP_Type 	shp_eintrag = {0,0,0,0,0,0,0,0,0,0,0,0};
	USHORT		us, aktuelle_Zeile = 0, aktuelle_Spalte = 0, unit_geschrieben = 0,
				Bit_Position, Byte_Position1, Byte_Position2;
	UBYTE		ub, Bitmuster, shp_counter = 0;


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


	for( i=0; i<SIZE_OF_BITPLANE; i++ )
		Bitmaps[0][i] = Bitmaps[1][i] = Bitmaps[2][i] = Bitmaps[3][i] = 0;


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

		exit( 20 );
	};
		
		

	printf("\n\n\n\n");
	printf("BATTLE ISLE Level Compiler    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 */

	i = 0;
	while( Dateiname[i] = (argv[2])[i]  )
		i++;

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

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


	strcat( Dateiname, "FIN" );

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

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


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

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


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

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


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




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

	printf("Alle Dateien sind geöffnet.\n");

	/* Zuerst wird in der SHP-Datei der Header mit 0-Bytes vollgeschrieben, sowie Platz im */
	/* PMP-File für das Password geschaffen.                                               */
	ub = 0;
	for( i=0; i<28; i++ )
		fwrite(&ub, 1, 1, shp );

	fprintf( pmp, "        " ); /* Leerer Platz für Password */



	/* Ab hier stehen die benötigten Dateien bereit. Der folgende Teil realisiert den Parser */
	/* sowie die benötigten Ausgabefunktionen. Er stellt einen endlichen Automaten dar.      */
	
	Zustand = 1;

	do{
		Scanner( eingabe, &Token );

		switch( Zustand )
		{
		case 0:
				/* Felerzustand */
				Token.Token = 0;
				printf("\n\nSchwerer Fehler !\n");
				printf("%s\n", buffer );
				for(i=0; i<buffer_pos-1; i++ )
					printf("-");
				printf("^\n\n\n");
				break;

		/* Die folgenden Zustände bearbeiten den Header der Datei */

		case 1:
				/* Anfang */
				if(	Token.Token == 2 )
					/* : gelesen */
					Zustand = 2;
				else
					if( Token.Token != 3 )
						/* kein Kommentar? dann Fehler */
						Zustand = 0;
				break;

		case 2:
				/* Erwartet wird die Spaltenzahl */
				if( Token.Token == 6 )
				{
					Hex_Spalten = Token.Zahl;
					fwrite( &Token.Zahl, 2, 1, fin );
					if( Token.Zahl <= 64 )
					{
						Zustand = 3;
					}else{
						printf("Zu viele Spalten (maximal 64!)!\n");
						Zustand = 0;
					};
				}else
					Zustand = 0;
				break;

		case 3:
				/* Anfang für Zeilenzahl */
				if(	Token.Token == 2 )
					/* : gelesen */
					Zustand = 4;
				else
					if( Token.Token != 3 )
						/* kein Kommentar? dann Fehler */
						Zustand = 0;
				break;

		case 4:
				/* Erwartet wird die Zeilenzahl */
				if( Token.Token == 6 )
				{
					Hex_Zeilen = Token.Zahl;
					fwrite( &Token.Zahl, 2, 1, fin );

					if( Token.Zahl <= 64 )
					{
						Zustand = 5;
					}else{
						printf("Zu viele Zeilen! Maximum = 64!\n");
						Zustand = 0;
					};
				
					/* Nun werden die restlichen Daten für das PMP-File berechnet und geschrieben */
					
					/* Unbekannter Wert */
					us = 0x0F0F;
					fwrite( &us, 2, 1, pmp );

					/* Anzahl Bytes pro Bitplane */
					Bytes_per_Line = (Hex_Spalten * 2) / 8;
					Bytes_per_Bitplane = Bytes_per_Line * Hex_Zeilen*2;
					us = Bytes_per_Bitplane + 24;
					fwrite( &us , 2, 1, pmp );

					/* 3 Unbekannte Werte */
					us = 0;
					fwrite( &us, 2, 1, pmp );
					fwrite( &us, 2, 1, pmp );
					fwrite( &us, 2, 1, pmp );

					/* Anzahl 16-Bit Blöcke pro Zeile */
					us = (Hex_Spalten*2) / 16;
					fwrite( &us, 2, 1, pmp );

					/* Anzahl Spalten und Zeilen des Bildes, nicht der Karte */					
					us = Hex_Spalten*2;
					fwrite( &us, 2, 1, pmp );
					us = Hex_Zeilen*2;
					fwrite( &us, 2, 1, pmp );


					/* Nun wird der Rest des Files bis zum Beginn der ersten Bitplane */
					/* mit FF aufgefüllt.                                             */
					ub = 0xFF;
					us = Bytes_per_Bitplane + 24;
					for( i=24; i<us; i++ )
						fwrite( &ub, 1, 1, pmp );

					printf("Zeilen: %hd      Spalten: %hd\n", Hex_Zeilen, Hex_Spalten );

				}else
					Zustand = 0;
				break;


		/* Jetzt müssen die Kartenzeilen folgen */

		case 5:
				/* Erwartet wird der Zeilenanfang, ein Doppelpunkt */
				if(	Token.Token == 2 )
					/* : gelesen */
					Zustand = 6;
				else
					if( Token.Token != 3 )
						/* kein Kommentar? dann Fehler */
						Zustand = 0;
				break;
		case 6:
				/* Erwartet wird die Zeilennummer */
				if( Token.Token == 6 )
				{
					Zustand = 7;
				}else{
					/* Ein spezieller Fehler ist, daß zuwenig Zeilen gelesen wurden */
					if( (Token.Token >=11) && (Token.Token <=14))
						printf("Zuwenig Zeilen im Kartenfile!\n");
					Zustand = 0;

				};
				break;
		case 7:
				/* Erwartet wird der Doppelpunkt, der der Zeilennummer folgt */
				if(	Token.Token == 2 )
				{
					/* : gelesen */
					aktuelle_Zeile++;
					if( aktuelle_Zeile > Hex_Zeilen )
					{
						printf("Zuviele Zeilen!\n");
						Zustand = 0;
					}else
						Zustand = 8;
				}else
					Zustand = 0;
				break;

		case 8:
				/* Hier wird die erste Terrainnummer erwartet */
				if( Token.Token == 6 )
				{
					/* Eintrag ins FIN-File */
					ub = (UBYTE) Token.Zahl;
					fwrite( &ub, 1, 1, fin );

					aktuelle_Spalte = 1;

					/* Ermitteln der Farbe des Terrains für die Übersichtskarte */
					GetBitPosition( (aktuelle_Spalte-1) * 2, (aktuelle_Zeile-1) * 2, Bytes_per_Line, &Bit_Position, &Byte_Position1 );
					GetBitPosition( (aktuelle_Spalte-1) * 2, (aktuelle_Zeile-1) * 2 + 1, Bytes_per_Line, &Bit_Position, &Byte_Position2 );
					ub = Terrain_Color[ Token.Zahl ];
					Bitmuster = (1<<Bit_Position) | (1<<(Bit_Position-1));

					for( i=3; i>=0; i-- )
					{
						if( (ub % 2) == 1 )
						{
							Bitmaps [i][ Byte_Position1 ] |= Bitmuster;
							Bitmaps [i][ Byte_Position2 ] |= Bitmuster;
						};
						ub /= 2;
					};

					if( Token.Zahl <= 100 )
					{
						Zustand = 9;
					}else{
						printf("Falscher Terraincode!\n");
						Zustand = 0;
					};
				}else{
					Zustand = 0;
				};
				break;
			
		case 9:
				/* Hier wird eine laufende Terrainnummer erwartet oder ein / der die  */
				/* Unitnummer einleitet.Ein : bedeutet, das bereits die nächste Zeile */
				/* oder die erste Inventory-Zeile des SHP-Files gelesen wurde.        */

				if( Token.Token == 6 )
				{
					if( !unit_geschrieben )
					{
						/* Das vorhergehende Terrain hat noch keine Unit. Da jetzt wieder */
						/* ein Terrain gelesen wird, muß erst noch für das vorherige      */
						/* Terrain ein 0xFF als Unit ins FIN-File geschrieben werden.     */
						ub = 0xFF;
						fwrite( &ub, 1, 1, fin );
					};

					/* Eintrag des neuen Terrains ins FIN-File */
					ub = (UBYTE) Token.Zahl;
					fwrite( &ub, 1, 1, fin );
					
					aktuelle_Spalte++;

					/* Ermitteln der Farbe des Terrains für die Übersichtskarte */
					GetBitPosition( (aktuelle_Spalte-1) * 2, (aktuelle_Zeile-1) * 2, Bytes_per_Line, &Bit_Position, &Byte_Position1 );
					GetBitPosition( (aktuelle_Spalte-1) * 2, (aktuelle_Zeile-1) * 2 + 1, Bytes_per_Line, &Bit_Position, &Byte_Position2 );
					ub = Terrain_Color[ Token.Zahl ];
					Bitmuster = (1<<Bit_Position) | (1<<(Bit_Position-1));

					for( i=3; i>=0; i-- )
					{
						if( (ub % 2) == 1 )
						{
							Bitmaps [i][ Byte_Position1 ] |= Bitmuster;
							Bitmaps [i][ Byte_Position2 ] |= Bitmuster;
						};
						ub /= 2;
					};

					if( aktuelle_Spalte > Hex_Spalten )
					{
						printf("Zuviele Spalten !\n");
						Zustand = 0;
					}else{
						if( Token.Zahl <= 100 )
						{
							Zustand = 9;
						}else{
							printf("Falscher Terraincode!\n");
							Zustand = 0;
						};
					};
				}else{
					if( Token.Token == 4 )
					{	
						/* / bedeutet Unit */
						Zustand = 10;
					}else{
						if( Token.Token == 2 )
						{
							if( !unit_geschrieben )
							{
								/* Das vorhergehende Terrain hat noch keine Unit. Da jetzt 	 */
								/* die Zeile zu Ende ist, muß erst noch für das vorherige    */
								/* Terrain ein 0xFF als Unit ins FIN-File geschrieben werden */
								ub = 0xFF;
								fwrite( &ub, 1, 1, fin );
							};

							/* Doppelpunkt ist entweder die nächste Zeile oder das HQ */
							if( aktuelle_Zeile+1 > Hex_Zeilen )
							{
								printf("Alle Kartenzeilen eingelesen.\n");
								Zustand = 11;	/* HQ einlesen */
							}else{
								/* Nächste Zeile lesen. Zuvor aber noch testen, ob überhaupt  */
								/* genügend Spalten eingelesen wurden.                        */

								if( aktuelle_Spalte < Hex_Spalten )
								{
									printf("Zuwenig Spalten !\n");
									Zustand = 0;
								}else{
									Zustand = 6;	/* nächste Zeile lesen */
								};
							};

						}else{
							/* Hier muß es wohl ein Fehler sein */
							Zustand = 0;
						};

				    };
				};
				unit_geschrieben = 0;
				break;
			
		case 10:
				/* Hier muß die Unitnumer eingelesen werden */
				if( Token.Token == 6 )
				{
					/* Eintrag ins FIN-File */
					ub = (UBYTE) Token.Zahl;
					fwrite( &ub, 1, 1, fin );
				
					/* Weiter beim Terrainlesen */
					unit_geschrieben = 1;
					if( Token.Zahl <= 52 )
					{
						Zustand = 9;
					}else{
						printf("Falscher Unitcode!\n");
						Zustand = 0;
					};
				}else{
					Zustand = 0;
				};

				break;



	/* Ab hier werden die Einträge für das COM-File aufbereitet */

		case 11:
				/* Hier wird der Typcode des Eintrages erwartet */
				if( (Token.Token >=11) && (Token.Token <=14) )
				{
					shp_eintrag.Typ = Token.Token - 11;
					Zustand = 12;
				}else{
					if( Token.Token != 3 )
					{
						/* Doch kein COM-Eintrag */
						printf("Zuviele Zeilen oder falscher COM-Code !\n");
						Zustand = 0;
					};
				};
				break;

		case 12:
				/* Der Doppelpunkt nach dem COM-Code muß folgen */
				if( Token.Token == 2 )
				{
					Zustand = 13;
				}else{
					Zustand = 0;
				};
				break;

		case 13:
				/* "Besitzer" wird erwartet */
				if( Token.Token == 7 )
				{
					Zustand = 14;
				}else{
					Zustand = 0;
				};
				break;

		case 14:
				/* : nach "Besitzer" wird erwartet */
				if( Token.Token == 2 )
				{
					Zustand = 15;
				}else{
					Zustand = 0;
				};
				break;

		case 15:
				/* Angabe des Besitzers wird erwartet */
				if( Token.Token == 6 )
				{
					shp_eintrag.Besitzer = Token.Zahl;
					Zustand = 16;
				}else{
					Zustand = 0;
				};
				break;

		case 16:
				/* "Index" wird erwartet */
				if( Token.Token == 8 )
				{
					Zustand = 17;
				}else{
					Zustand = 0;
				};
				break;

		case 17:
				/* : nach "Index" wird erwartet */
				if( Token.Token == 2 )
				{
					Zustand = 18;
				}else{
					Zustand = 0;
				};
				break;

		case 18:
				/* Angabe des Index wird erwartet */
				if( Token.Token == 6 )
				{
					shp_eintrag.Index = Token.Zahl;
					Zustand = 19;
				}else{
					Zustand = 0;
				};
				break;

		case 19:
				/* "Aldinium" wird erwartet */
				if( Token.Token == 9 )
				{
					Zustand = 20;
				}else{
					Zustand = 0;
				};
				break;

		case 20:
				/* : nach "Aldinium" wird erwartet */
				if( Token.Token == 2 )
				{
					Zustand = 21;
				}else{
					Zustand = 0;
				};
				break;

		case 21:
				/* Angabe des Aldiniums wird erwartet */
				if( Token.Token == 6 )
				{
					shp_eintrag.Aldinium = Token.Zahl;
					Zustand = 22;
				}else{
					Zustand = 0;
				};
				break;

		case 22:
				/* "Inhalt" wird erwartet */
				if( Token.Token == 10 )
				{
					Zustand = 23;
				}else{
					Zustand = 0;
				};
				break;

		case 23:
				/* : nach "Inhalt" wird erwartet */
				if( Token.Token == 2 )
				{
					Zustand = 24;
				}else{
					Zustand = 0;
				};
				break;

		case 24:
				/* Es müssen jetzt 7 Inhaltsbytes folgen, die noch für die spezielle    */
				/* Art der Codierung im COM-File vorbereitet werden müssen.             */
				if( Token.Token == 6 )
				{
					shp_eintrag.Inhalt[0] = (Token.Zahl == 0xFF) ? (0xFF):(Token.Zahl / 2);
					Zustand = 25;
				}else{
					Zustand = 0;
				};
				break;
		case 25:
				if( Token.Token == 6 )
				{
					shp_eintrag.Inhalt[1] = (Token.Zahl == 0xFF) ? (0xFF):(Token.Zahl / 2);
					Zustand = 26;
				}else{
					Zustand = 0;
				};
				break;
		case 26:
				if( Token.Token == 6 )
				{
					shp_eintrag.Inhalt[2] = (Token.Zahl == 0xFF) ? (0xFF):(Token.Zahl / 2);
					Zustand = 27;
				}else{
					Zustand = 0;
				};
				break;
		case 27:
				if( Token.Token == 6 )
				{
					shp_eintrag.Inhalt[3] = (Token.Zahl == 0xFF) ? (0xFF):(Token.Zahl / 2);
					Zustand = 28;
				}else{
					Zustand = 0;
				};
				break;
		case 28:
				if( Token.Token == 6 )
				{
					shp_eintrag.Inhalt[4] = (Token.Zahl == 0xFF) ? (0xFF):(Token.Zahl / 2);
					Zustand = 29;
				}else{
					Zustand = 0;
				};
				break;
		case 29:
				if( Token.Token == 6 )
				{
					shp_eintrag.Inhalt[5] = (Token.Zahl == 0xFF) ? (0xFF):(Token.Zahl / 2);
					Zustand = 30;
				}else{
					Zustand = 0;
				};
				break;
		case 30:
				if( Token.Token == 6 )
				{
					shp_eintrag.Inhalt[6] = (Token.Zahl == 0xFF) ? (0xFF):(Token.Zahl / 2);

					/* Nun wird der Eintrag geschrieben */
					fwrite( &shp_eintrag, sizeof( SHP_Type ), 1, shp );
					shp_counter++;
					Zustand = 31;
				}else{
					Zustand = 0;
				};
				break;

		case 31:
				/* Hier wird auf den Doppelpunkt der nächsten Zeile gewartet, bzw ein in der */
				/* alten Zeile folgender Kommentar überlesen. Falls im Verlauf des Wartens   */
				/* ein EOF auftaucht. Wird in den Endzustand übergegangen.                   */
				if( Token.Token == 2)
				{
					Zustand = 11;
				}else{
					if( Token.Token == 0 )
					{
						Zustand = 1000;
					}else{
						if( Token.Token != 3 )
						{
							Zustand = 0;
						};
					};
				};
				break;


		};

	}while( Token.Token != 0 );


	/* Jetzt werden die Bitplanes ins PMP-File geschrieben */
	fwrite( &Bitmaps[0][0], Bytes_per_Bitplane, 1, pmp );
	fwrite( &Bitmaps[1][0], Bytes_per_Bitplane, 1, pmp );
	fwrite( &Bitmaps[2][0], Bytes_per_Bitplane, 1, pmp );
	fwrite( &Bitmaps[3][0], Bytes_per_Bitplane, 1, pmp );

	/* Nun muß noch eine leere Bitplane angehängt werden */
	for( i=0; i<SIZE_OF_BITPLANE; i++ )
		Bitmaps[0][i] = 0;

	fwrite( &Bitmaps[0][0], SIZE_OF_BITPLANE, 1, pmp );



	/* Nun wird noch die Anzahl der shp-Eintrage ins File geschrieben */
	fseek( shp, 27, 0 );
	fwrite( &shp_counter, 1, 1, shp ); 


	/* Schließlich wird das COM-File erzeugt */
	fwrite( Com_Datas, 163, 1, com );






	fclose( fin );
	fclose( shp );
	fclose( pmp );
	fclose( com );
	fclose( eingabe );

	if( Zustand != 0 )
		printf("Alles klar, Mann! Jetzt puste diesen gelben Hunden die Ärsche aus dem Wasser!\n");
}
