/**************************************************
 *
 * FileID.c
 *
 *    Identify picture/IFF file 
 *      and give info about it.
 *
 *    Copyright(c), 1990 Lloyd B. Eldred
 *
 **************************************************/
#include <stdio.h>
#include <math.h>
 
typedef unsigned char UBYTE;     /* 8 bits unsigned */
typedef unsigned short UWORD;    /* 16 bits unsigned */
typedef short WORD;		 /* 16 bits signed */
typedef long LONG;               /* 32 bits signed */

#define GIF 1
#define IFF 2
#define ANIM 3
#define HIRES 0x8000
#define LACE 0x4
#define HAM 0x800
#define HALFBRITE 0x80

main(argc, argv)
char **argv;
{
	FILE *picfile;
	int type;
	char buf[256],buf2[256],tempotext[10];
	int width,height,color,i,planes;
	UBYTE w1,w2,h1,h2,c;
	int start,start2,start3,camg;
	long vpmode,volume,dt;
	int cfind(char * , int , char * , int);
	UWORD sps,tempo;
	long tempo2;
	WORD numframes;
	unsigned long reltime;
	LONG makelong(char,char,char,char);
	LONG size;
	
	printf(
	"FileID -- File IDentifier. Copyright (c) 1990, Lloyd B. Eldred.\n"
	 );

	       	if (argc != 2) {
		printf("Usage: FileID filename\n");
		exit(2);
	}

	if (argc == 2) {
		if ((picfile = fopen(argv[1], "rb")) == NULL) {
			perror(argv[1]);
			exit(1);
		}
	} 

	/* search for header line */
	for (;;) {
		if (fread(buf, sizeof(buf), 1,picfile) != 1) {
			fprintf(stderr, "Unrecognized filetype\n");
			fclose(picfile);
			exit(3);
		}
		start = cfind(buf,sizeof(buf),"GIF",3);
		if (start != -1){
			type=GIF;
			break;
		}
		
		start = cfind(buf,sizeof(buf),"FORM",4);
		if (start != -1){
			type=IFF;
			break;
		}
		
		start = cfind(buf,sizeof(buf),"CAT ",4);
		if (start != -1){
			type=IFF;
			break;
		}

		start = cfind(buf,sizeof(buf),"LIST",4);
		if (start != -1){
			type=IFF;
			break;
		}


	        
	}
	
	fclose(picfile);

/********************************************************************/
/*                          GIF analysis                            */
/********************************************************************/
	
	if(type == GIF){
		w1 = buf[start+3];
		w2 = buf[start+4];
		h1 = buf[start+5];
		
		printf(" GIF -- Version %c%c%c:",w1,w2,h1);
		if( w1 != '8' || w2 != '7' || h1 != 'a')
			printf(" non recognized version, the following",
			       " are guesses");
		printf("\n");
		if(start != 0)
			printf("Padding encountered at the beginning of",
			       " the file. Some viewers may not like this",
			       " file.\n");
		w1 = buf[start+6];
		w2 = buf[start+7];
		h1 = buf[start+8];
		h2 = buf[start+9];
		c  = buf[start+10];
			
		planes = (int)(c & 0x7) + 1;
		
		color=1;
		
		for(i=0; i<planes ; i++)
		  color = color * 2;
		
		width=w1 + 256 * w2;
		
		height=h1 + 256 * h2;
		
		printf("   Width : %5d\n"
		       "   Height: %5d\n"
		       "   Colors: %5d\n",width,height,color);
		
	}

/********************************************************************/
/*                          IFF analysis                            */
/********************************************************************/

	if(type == IFF){
		printf(" IFF file:");

/* ILBM analysis */

		start3 = cfind(buf,sizeof(buf),"ANIM",4);
		if (start3 != -1){
			printf(" ANIM (Cel Animation)\n");
			type = ANIM;
			start = cfind(buf,sizeof(buf),"ILBM",4);
			if(start != -1 && start < sizeof(buf) + 5){
				w1 = buf[start-4];
				w2 = buf[start-3];
				h1 = buf[start-2];
				h2 = buf[start-1];
				size = makelong(w1,w2,h1,h2);
				if ((picfile = fopen(argv[1], "rb")) 
					== NULL) {
					perror(argv[1]);
					exit(1);
				}
				if(fseek(picfile,(long)(start+size),0)
					== -1){
					printf(" Can't find animation info. (fseek past end of file)\n");
					exit();
				}
			if (fread(buf2, sizeof(buf2), 1,picfile) != 1) {
				fprintf(stderr, 
					" Can't find animation info. (fread past end of file)\n");
				}
				
			}
			start = cfind(buf2,sizeof(buf2),"ANHD",4);
			if(start != -1 && start < sizeof(buf2) - 25){
				w1 = buf2[start+8];
				w2 = buf2[start+9];
				h1 = buf2[start+23];
				h2 = buf2[start+24];
				
				c = buf2[start+25];

				printf("   Compression Mode      :");
				if(w1 == 0) printf(" None\n");
				if(w1 == 1) printf(" XOR ILBM mode\n");
				if(w1 == 2) printf(" Long Delta mode\n");
				if(w1 == 3) printf(" Short Delta mode\n");
				if(w1 == 4) printf(
					" Gen. short/long Delta mode\n");
				if(w1 == 5) printf(
					" Byte Vertical Delta mode\n");
				if(w1 == 'J') printf(
					" Eric Graham's technique\n");
			
				reltime = (unsigned long)
					makelong(w2,h1,h2,c);
				printf("   Frame timing (jiffies): %d\n"
					,reltime);
				printf("   (1 jiffy=1/60 sec)\n");
			}
			else
				printf(
				" Can't find animation information. (Can't find ANHD)\n");
		}
		start = -1;
		if(type != ANIM){
			start = cfind(buf,sizeof(buf),"ILBM",4);
			if(start != -1)
				printf(
				" ILBM (Picture: InterLeaved Bit Map)\n");
			start2 = cfind(buf,sizeof(buf),"ACBM",4);
			if(start2 != -1)
				printf(
				" ACBM (Picture: Amiga Contiguous Bit Map)\n");
		}
			
		if (start != -1 || start2 != -1 || start3 != -1){
			start = cfind(buf,sizeof(buf),"BMHD",4);
			
			if(start == -1){
				printf(" Color information not found\n");
				exit();
			}
			
			
			if(start > (sizeof(buf)-12)){
				printf(
				" Incomplete color information found\n");
				exit();
			}
			w1 = buf[start+8];
			w2 = buf[start+9];
			h1 = buf[start+10];
			h2 = buf[start+11];
			c  = buf[start+16];

			width = (int)w2 + (int)(w1<<8);
			height= (int)h2 + (int)(h1<<8);
						
			planes=(int)c;
			color=1;
			for(i=0; i<planes ; i++)
		  		color = color * 2;
  /* HAM or Extra Half Bright? */
  /* Search for CAMG block */
			camg=0;
			start = cfind(buf,sizeof(buf),"CAMG",4);
							
			if(start != -1) { /* check vpmode flag */
				camg=1;
				w1 = buf[start+8];
				w2 = buf[start+9];
				h1 = buf[start+10];
				h2 = buf[start+11]; 
				vpmode = makelong(w1,w2,h1,h2);

				if(vpmode & HAM) /* HAM flag */
						color = 4096;
			} /* end if(start != -1) */
				 	
			printf("   Width : %5d",width);
			if(camg == 1 && (vpmode & HIRES))
				printf("  Hi-Res");
			printf("\n");
			
			printf("   Height: %5d",height);
			if(camg == 1 && (vpmode & LACE))
				printf("  Interlaced");
			printf("\n");
						
			printf("   Colors: %5d",color);
			if(camg == 1 && (vpmode & HAM))
				printf("  HAM");
			if(camg == 1 && (vpmode & HALFBRITE))
				printf("  Extra-Halfbright");
			printf("\n");
			exit();
			
		} /* end if ILBM */
		
/* check for other IFF file types */

		start = cfind(buf,sizeof(buf),"FTXT",4);
		if (start != -1){
			printf(" FTXT (Formatted Text)\n");
			exit();
		}
		
		start = cfind(buf,sizeof(buf),"SMUS",4);
		if (start != -1){
			printf(" SMUS (Simple MUsical Score)\n");
			start = cfind(buf,sizeof(buf),"SHDR",4);
			if (start == -1 || start > sizeof(buf) - 11){
				printf(" Can't read music info.\n");
				exit();
			}
			w1 = buf[start+8];
			w2 = buf[start+9];
			
			tempo = (UWORD)w2 + (UWORD)(w1<<8);

			tempo2 = ((tempo % 128) * 100000)/128;
			
			tempo /= 128;

			sprintf(tempotext,"%u.%5d",tempo,tempo2);
			for(i = 0; i<9; i++)
				if(tempotext[i] == ' ') tempotext[i] = '0';
						
			h1 = buf[start+10];

			volume = ((int)h1 * 100)/127;

			c = buf[start+11];
			
			printf("   Tempo  (1/4 notes/min): %s\n",tempotext);
			printf("   Volume (percent)      : %d\n",volume);
			printf("   Tracks                : %d\n",(int)c);
			
			exit();
		}
		
		start = cfind(buf,sizeof(buf),"8SVX",4);
		if (start != -1){
			printf(" 8SVX (8-Bit Sample Voice)\n");
			start = cfind(buf,sizeof(buf),"VHDR",4);
			if (start == -1 || start > sizeof(buf)-27){
				printf(" Can't read voice info\n");
				exit();
			}
			w1 = buf[start+20];
			w2 = buf[start+21];
			
			sps = (UWORD)w2 + (UWORD)(w1<<8);
			
			w1 = buf[start+24];
			w2 = buf[start+25];
			h1 = buf[start+26];
			h2 = buf[start+27];
			
			volume = makelong(w1,w2,h1,h2);
			volume = (volume * 100) / 65536;
			printf("   Samples per second: %d\n",sps);
			printf("   Volume (percent)  : %d\n",volume);
			
			exit();
		}

		start = cfind(buf,sizeof(buf),"AIFF",4);
		if (start != -1){
			printf(" AIFF (Apple Audio IFF)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"ANBM",4);
		if (start != -1){
			printf(" ANBM (Animated bitmap -- Deluxe Video)\n");
			start = cfind(buf,sizeof(buf),"FSQN",4);
			if(start == -1 || start > sizeof(buf) - 13 ){
				printf(" Can't read animation info\n");
				exit();
			}
			w1 = buf[start+8];
			w2 = buf[start+9];
			
			numframes = (WORD)w2 + (WORD)(w1<<8);
			
			w1 = buf[start+10];
			w2 = buf[start+11];
			h1 = buf[start+12];
			h2 = buf[start+13];
			
			dt = makelong(w1,w2,h1,h2);
			
			printf("   Number of Frames              : %d\n",
				numframes);
			printf("   Time between frames (jiffies) : %d\n",
				dt);
			printf("   (1 jiffy=1/60 sec)\n");
			
			exit();
		}

		start = cfind(buf,sizeof(buf),"BANK",4);
		if (start != -1){
			printf(" BANK (SoundQuest MIDI data-dump)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"HEAD",4);
		if (start != -1){
			printf(" HEAD (Flow Idea Processor form)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"MIDI",4);
		if (start != -1){
			printf(" MIDI\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"PGTB",4);
		if (start != -1){
			printf(" PGTB (ProGram TraceBack diagnostic dump image)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"SYTH",4);
		if (start != -1){
			printf(" SYTH (SoundQuest Master Librarian file)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"WORD",4);
		if (start != -1){
			printf(" WORD (ProWrite data file)\n");
			exit();
		}
		
		start = cfind(buf,sizeof(buf),"C100",4);
		if (start != -1){
			printf(" C100 (Cloanto Italia, private word processing form)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"PDEF",4);
		if (start != -1){
			printf(" PDEF (Deluxe Print page definition)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"SHAK",4);
		if (start != -1){
			printf(" SHAK (Shakespeare data file)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"VDEO",4);
		if (start != -1){
			printf(" VDEO (Deluxe Video file)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"SAMP",4);
		if (start != -1){
			printf(" SAMP (Sound Sample)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"TDDD",4);
		if (start != -1){
			printf(" TDDD (Turbo Silver file)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"SC3D",4);
		if (start != -1){
			printf(" SC3D (Sculpt 3-D file)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"TEXT",4);
		if (start != -1){
			printf(" TEXT (unformatted ASCII text)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"FNTR",4);
		if (start != -1){
			printf(" FNTR (Raster Font)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"FNTV",4);
		if (start != -1){
			printf(" FNTV (Vector Font)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"GSCR",4);
		if (start != -1){
			printf(" GSCR (General-use musical SCoRe)\n");
			exit();
		}
		
		start = cfind(buf,sizeof(buf),"PICS",4);
		if (start != -1){
			printf(" PICS (Macintosh picture)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"PLBM",4);
		if (start != -1){
			printf(" PLBM (Obsolete)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"USCR",4);
		if (start != -1){
			printf(" USCR (Uhura Sound software musical score)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"UVOX",4);
		if (start != -1){
			printf(" UVOX (Uhura Sound software Macintosh Voice)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"CLIP",4);
		if (start != -1){
			printf(" CLIP (Clipboard data)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"ARC ",4);
		if (start != -1){
			printf(" ARC  (Arcive form)\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"ATXT",4);
		if (start != -1){
			printf(" ATXT\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"PTXT",4);
		if (start != -1){
			printf(" PTXT\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"RGBX",4);
		if (start != -1){
			printf(" RGBX\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"CDAT",4);
		if (start != -1){
			printf(" CDAT\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"MSMP",4);
		if (start != -1){
			printf(" MSMP\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"FIGR",4);
		if (start != -1){
			printf(" FIGR\n");
			exit();
		}

		start = cfind(buf,sizeof(buf),"MOVI",4);
		if (start != -1){
			printf(" MOVI\n");
			exit();
		}

		printf(" Unknown type\n");

	}


	exit();
	
} /* end of main() */

int cfind(buffer,blength,string,slength)
char *buffer;
char *string;
int blength,slength;
{
	int i,start;
	int found;
	
	start = 0;
	
	while(start < (blength-slength)){
		found = 1;
		
		for(i=0;i<slength;i++)
			if(buffer[start+i] != string[i]){
				found = 0;
				break;
			}
		
		if(found == 1) return(start);
		
		start++;
	}
	
	return(-1);  /* string not found */
		
} /* end of cfind() */	

LONG makelong(c1,c2,c3,c4)
char c1,c2,c3,c4;
{
	LONG value;
	
	value = (LONG)c4 + (LONG)(c3<<8) + (LONG)(c2<<16) + (LONG)(c1<<24);
	
	return(value);
	
} /* end of makelong() */ 