/************************************************************

PlayMACk is a simple Macintosh to Amiga sound file conversion
utility.  It differs from other programs in that it will 
recognised a MAC file that has been compressed and decompress
it.

This program is freeware.  It may be used for private use or for
inclusion in commercial software.  My only request is that my
name stay attached to this code for posterity's sake.

Written by Bruce Twambly   25 Aug 1990

************************************************************/

#include "exec/types.h"
#include "stdio.h"
#include "dos.h"
#include "stdlib.h"
#include "string.h"

#define BUFSIZE 8192

int tag_form=0x464f524d;
int tag_8svx=0x38535658;
int tag_vhdr=0x56484452;
int tag_body=0x424f4459;
int tag_hcom=0x48434f4d;
int tag_anno=0x414e4e4f;

FILE *output=NULL;
FILE *input=NULL;
char *buf=NULL;
char *aryptr=NULL;
char *outptr=NULL;

char *anno = "Compressed by PlayMACk- by Bruce Twambly"; 

extern void cleanup();
extern void write_int();
extern void write_word();
extern void write_byte();

struct HcomHead {
	ULONG tag;
	ULONG size;
	ULONG chksum;
	ULONG packtype;
	ULONG packrate;
	UWORD arysize;
}

main(argc,argv)
int argc; 
char *argv[];
{
	struct 	FILEINFO info;
	struct 	HcomHead hh;
	int 	attr=0,error;
	int 	macsize,a;
	char 	infile[40];
	int 	freq = 11000;
	
	printf("PlayMACk v1.0 - Macintosh to Amiga Sound File Conversion\n");
	printf("Copyright %c 1990 by Bruce Twambly\n\n",0xa9);
	
	if (argc<2 || argc>3) {
		printf("Usage: PlayMACk <macsoundfile> [<est smpl/sec>]\n\n");
		exit(1);
	}
	
	strcpy(infile,argv[1]);
	if (argc==3) freq = atoi(argv[2]);

	if (freq <= 0) {
		printf("ERROR: Invalid estimated sample rate.  Check syntax.\n");
		exit(1);
	}
	
	error=dfind(&info,infile,attr);
    if (error!=0 || info.fib_DirEntryType>=0 ) {
		printf("ERROR: Could not find MAC sound file.\n");
		cleanup();
		exit(1);
	}

	printf("Working ... \n\n");
	
	macsize = info.fib_Size;

	if ((input=fopen(infile,"r"))==NULL){
		printf("ERROR: Could not open input file.\n");
		cleanup();
		exit(1);
	}	
	if ((output=fopen(strcat(infile,".8SVX"),"w"))==NULL){
		printf("ERROR: Could not open output file.\n");
		cleanup();
		exit(1);
	}	
	
	if ((buf=malloc(BUFSIZE))== NULL) {
		printf("ERROR: Could not allocate buffer memory.\n");
		cleanup();
		exit(1);
	}
	
	fread((char *) &hh,sizeof(struct HcomHead),1,input);
	if (hh.tag == tag_hcom) macsize=hh.size;	
	
	if ( (macsize%2)!=0 ) {
		printf("Dropping one data byte.  Even lengths required.\n\n");
		macsize -= 1;
	}
	
	write_int(tag_form,output);
	write_int(macsize+88,output);
	write_int(tag_8svx,output);
	write_int(tag_vhdr,output);
	write_int(20,output);
	write_int(macsize,output);
	write_int(0,output);
	write_int(0,output);
	write_word((short)freq,output);
	write_byte(1,output);
	write_byte(0,output);
	write_word(1,output);
	write_word(0,output);
	write_int(tag_anno,output);
	write_int(40,output);
	fwrite(anno,1,40,output);
	write_int(tag_body,output);
	write_int(macsize,output);
	
	if ( hh.tag == tag_hcom ) {
		int 		bufout,bufin;
		int 		loop;
		char 		*table,byteout;
		signed short *nxtwd,index,first;
		ULONG 		smask;
		ULONG 		*inptr;
		BYTE 		*bptr;
		ULONG 		chk;
		struct Aptr { signed short a,b; } *aptr;
		
		printf("Processing compressed MAC sound file ");

		if ((aryptr=malloc(hh.arysize*4))== NULL) {
			printf("Couldn't allocate unpack table memory.\n");
			cleanup();
			exit(1);
		}
		table = aryptr;
	
		if ((outptr=malloc(BUFSIZE))== NULL) {
			printf("Couldn't allocate unpack data memory.\n");
			cleanup();
			exit(1);
		}
		bptr = outptr;

		fread(aryptr,4,hh.arysize,input);
		for (loop=0,aptr=(struct Aptr *) aryptr ; loop<hh.arysize ;
				loop++,aptr++)
			if (aptr->a > 0 ) {
				aptr->a = aptr->a << 2;
				aptr->b = aptr->b << 2;
			}
			
    	fread((char *) &first,sizeof(UWORD),1,input);
	
		*bptr++ = (BYTE)(first&0x00FF);
		bufout=1;
		macsize -= 1;
		chk=0;
		index = 0;
		bufin = fread(buf,1,BUFSIZE,input);
		inptr = (ULONG *) buf;
		printf(".");
		
		while (macsize > 0 ) {
			chk += *inptr;
			smask = 0x80000000;
			while (smask) {
				if ( smask&(*inptr) ) index += 2;
				smask = smask >> 1;
				index = *((signed short *)(table+index));
				nxtwd = (signed short *)(table+index);
				if ( *nxtwd<0 ) {
					first += *(nxtwd+1);
					byteout = (BYTE) first&0x00FF;
					byteout -= 128;
					if (byteout<0) byteout+=256;
					*bptr++ = byteout;
					bufout += 1;
					if (bufout == BUFSIZE) {
						fwrite(outptr,1,bufout,output);
						bufout = 0;
						bptr = outptr;
					}
					index = 0;
					macsize -= 1;
				}						
				if (macsize <= 0 ) break;
			}
			inptr++;
			bufin -= sizeof(ULONG);
			if (bufin <= 0 ) {
				bufin = fread(buf,1,BUFSIZE,input);
				inptr = (ULONG *) buf;
				printf(".");
			}
		}			
		fwrite(outptr,1,bufout,output);
	} else {
		int i,c;
	
		rewind(input);
		c = macsize;
		printf("Processing Uncompressed MAC sound file ");
		while (c>0) {
			a = fread(buf,1,BUFSIZE,input);
			printf(".");
			for (i=0;i<a;i++) {
				buf[i] -= 128;
				if (buf[i]<0) buf[i] += 256;
			}
			fwrite(buf,1,a,output);
			c -= a;
		}
	}

	printf(" Done!\n\nOutput is in file %s\n\n",infile );

	cleanup();

}


void cleanup()
{
	if (output!=NULL) fclose(output);
	if (input!=NULL)  fclose(input);
    if (buf!=NULL)    free(buf);
	if (aryptr!=NULL) free(aryptr);
	if (outptr!=NULL) free(outptr);
}

void write_int(i,f)
int i;
FILE *f;
{
	fwrite((char *)&i,1,4,f);
}

void write_word(w,f)
short w;
FILE *f;
{
	fwrite((char *)&w,1,2,f);
}

void write_byte(b,f)
char b;
FILE *f;
{
	fwrite(&b,1,1,f);
}
