/***************************************************************
	CAR RACE II    character data archiver  version 1.01
					[ Mar.27, 1989 ]
 ***************************************************************/

#include	<stdio.h>

#define		unchar		unsigned char
#define		FSIZE		1024*32
#define		DSIZE		2048
#define		ERROR		-1
#define		COMPLETE	0

int	chrlen[6] = { 6,9,12,20,24,40 } ;
int	chralc[6][40] = {
		{ 0,1,2,3,4,5 },
		{ 0,1,2,6,7,3,4,5,8 },
		{ 0,1,2,3,8,9,4,5,6,7,10,11 },
		{ 0,1,2,3,4,10,11,12,13,14,5,6,7,8,9,15,16,17,18,19 },
		{ 0,1,2,3,4,5,12,13,14,15,16,17,
		  6,7,8,9,10,11,18,19,20,21,22,23 },
		{ 0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23,
		  8,9,10,11,12,13,14,15,24,25,26,27,28,29,30,31,
		  32,33,34,35,36,37,38,39 }
	} ;

char	chrbuf[DSIZE][32] ;


main( argc,argv )
int	argc ;
char	**argv ;
{
	FILE	*tp,*wp ;
	char	head[128] ;

	printf( "CAR RACE II  character data archiver  ver 1.01\n" ) ;
	if ( argc < 4 ) {
		puts( "usage: chrar <table> <destination> <char file ...>\n" ) ;
		exit( 1 ) ;
	}
	if ( readchar( argc-3,argv+3,chrbuf[0] ) == ERROR ) {
		exit( 1 ) ;
	}
	if (( tp = fopen( *(argv+1),"r" )) == NULL ) {
		perror( *(argv+1)) ;
		exit( 1 ) ;
	}
	if (( wp = fopen( *(argv+2),"w" )) == NULL ) {
		perror( *(argv+2)) ;
		exit( 1 ) ;
	}
	while ( fgets( head,127,tp ) != NULL ) {
		if ( head[0] == '#' )
			archive( (int)(head[1]-'0'),tp,wp ) ;
	}
	fclose( tp ) ;
	fclose( wp ) ;
}

/*******  archive main  ******************************************/

archive( mo,tp,wp )
int	mo ;
FILE	*tp,*wp ;
{
	char	buf[32] ;
	int	chrnum[40] ;
	int	i,len,num,*pnt ;

	len = chrlen[mo] ;
	pnt = chrnum ;
	for ( i=0 ; i<len ; i++ ) {
		*pnt++ = getnum( tp ) ;
	}
	pnt = chralc[mo] ;
	for ( i=0 ; i<len ; i++ ) {
		if (( num = chrnum[*pnt++] ) < 0x8000 ) {
			fwrite( chrbuf[num],sizeof(char),32,wp ) ;
		} else {
			num &= 0x7fff ;
			flip( chrbuf[num],buf,32 ) ;
			fwrite( buf,sizeof(char),32,wp ) ;
		}
	}
}

/*******  flip character  *****************************************/

flip( dat,buf,len )
unchar	*dat,*buf ;
int	len ;
{
	int	nn,mm,i ;

	while ( len-- > 0 ) {
		nn = *dat++ ;
		for ( mm=i=0 ; i<8 ; i++ ) {
			mm = ( mm << 1 ) + ( nn % 2 ) ;
			nn >>= 1 ;
		}
		*buf++ = mm ;
	}
}

/*******  get number from table file  *****************************/

getnum( fp )
FILE	*fp ;
{
	int	cc,nn,i ;

	do {
		if (( cc = fgetc( fp )) == EOF )  return ( 0 ) ;
	} while ( cc<'0' || ('9'<cc && cc<'A') || 'F'<cc ) ;

	if (( nn = cc - '0' ) > 9 )  nn = cc - 'A' + 10 ;

	for ( i=0 ; i<3 ; i++ ) {
		cc = fgetc( fp ) ;
		if ((cc -= '0') > 9 ) cc -= 7 ;
		nn = nn * 16 + cc ;
	}
	return ( nn ) ;
}
	
/*******  read character data  ***********************************/

readchar( argc,argv,buf )
int	argc ;
char	**argv,*buf ;
{
	FILE	*fp ;
	int	cnt = 0 ;

	while ( argc-- ) {
		if ( cnt+1024 > DSIZE ) {
			printf( "too many file\n" ) ;
			return ( ERROR ) ;
		}
		if (( fp = fopen( *(argv++),"r" )) == NULL ) {
			perror( *(argv-1)) ;
			return ( ERROR ) ;
		}
		if ( fread( buf,sizeof(char),FSIZE,fp ) != FSIZE ) {
			printf( "%s: not character file\n",*(argv-1)) ;
			fclose( fp ) ;
			return ( ERROR ) ;
		}
		fclose( fp ) ;
		buf += FSIZE ;
		cnt += 1024 ;
	}
	return ( COMPLETE ) ;
}
