/***************************************************************
    OBJ character data compress for CAR RACE  version 1.20
		    Programmed by Y.Nishida
					[ May.21, 1990 ]
 ***************************************************************/

#include	<stdio.h>

#define		unchar		unsigned char
#define		DSIZE		768
#define		ERROR		-1
#define		COMPLETE	0
#define		CONT		0
#define		END		1

struct	data {
		int	size ;		/*  bit size of character	*/
		int	leng ;		/*  length of data		*/
		int	code ;		/*  character code ( buffer )	*/
		int	cnum ;		/*  character number ( VRAM )	*/ 
		int	flag ;		/*  terminator flag		*/
	} ;

struct	data header[34] = {
		{ 4,  7, 0x006, 0x06, CONT },
		{ 4,  7, 0x016, 0x16, CONT },
		{ 3,  3, 0x00d, 0x0d, CONT },
		{ 3, 35, 0x01d, 0x1d, CONT },
		{ 3, 36, 0x040, 0x40, CONT },
		{ 3,  4, 0x070, 0x70, CONT },
		{ 2, 12, 0x064, 0x64, CONT },
		{ 2, 56, 0x074, 0x74, CONT },
		{ 2, 12, 0x0b0, 0xb0, CONT },
		{ 1,  4, 0x0ac, 0xac, CONT },
		{ 1, 36, 0x0bc, 0xbc,  END },	
		{ 2, 32, 0x0e0, 0xe0,  END },
		{ 2, 32, 0x100, 0xe0,  END },
		{ 2, 32, 0x120, 0xe0,  END },
		{ 2, 32, 0x140, 0xe0,  END },
		{ 2, 32, 0x160, 0xe0,  END },
		{ 2, 32, 0x180, 0xe0,  END },
		{ 2, 32, 0x1a0, 0xe0,  END },
		{ 2, 32, 0x1c0, 0xe0,  END },
		{ 2, 32, 0x1e0, 0xe0,  END },
		{ 2, 32, 0x200, 0xe0,  END },
		{ 2, 32, 0x220, 0xe0,  END },
		{ 2, 32, 0x240, 0xe0,  END },
		{ 2, 32, 0x260, 0xe0,  END },
		{ 2, 32, 0x280, 0xe0,  END },
		{ 2, 32, 0x2A0, 0xe0,  END },
		{ 3,  6, 0x2C0, 0x60, CONT },
		{ 3,  6, 0x2C8, 0x66, CONT },
		{ 3,  6, 0x2D0, 0x70, CONT },
		{ 3,  6, 0x2D8, 0x76, CONT },
		{ 3, 12, 0x2E0, 0x80, CONT },
		{ 3, 12, 0x2F0, 0x90,  END },
		{ 4,  2, 0x2C6, 0x66, CONT },
		{ 4,  2, 0x2D6, 0x76,  END }
	} ;


unchar	chrbuf[DSIZE][32] ;		/* character data buffer	*/
int	chrcnt  = 0 ;			/* total character 		*/
int	bincnt  = 0 ;			/* binary counter		*/

main( argc,argv )
int	argc ;
char	**argv ;
{
	FILE	*fp ;
	void	make_data() ;

	puts( "\nOBJ character data compress for CAR RACE  version 1.20" ) ;
	if ( argc != 4 ) {
		puts( "Usage: mkspchr <OBJ file> <MAP file> <READY file>" ) ;
		exit( 1 ) ;
	}
	if ( read_char( *++argv,0x000,0x0e0 ) == ERROR ) {
		printf( "%s :can not found OBJ character file\n", *argv ) ;
		exit( 1 ) ;
	}
	if ( read_char( *++argv,0x0e0,0x1e0 ) == ERROR ) {
		printf( "%s :can not found MAP character file\n", *argv ) ;
		exit( 1 ) ;
	}
	if ( read_char( *++argv,0x2c0,0x040 ) == ERROR ) {
		printf( "%s :can not found READY character file\n", *argv ) ;
		exit( 1 ) ;
	}
	if (( fp = fopen( "OBJECT.CHR","w" )) == NULL ) {
		puts( "OBJECT.CHR :file can not create" ) ;
		exit( 1 ) ;
	}
	make_data( fp ) ;
	fclose( fp ) ;

	printf( "\nTotal %4d ( $%04X ) character",      chrcnt,chrcnt ) ;
	printf( "\n      %4d ( $%04X ) bytes write.\n", bincnt,bincnt ) ;
	exit( 0 ) ;
}

/****************************************************************/
/*	make data						*/
/****************************************************************/

void make_data( fp )
FILE	*fp ;
{
	struct data	*dat ;
	int		cnt ;

	putchar( '\n' ) ;
	for ( dat=header,cnt=0 ; cnt<34 ; dat++,cnt++ ) {
		printf( "Offset = $%04X   character code = $%03X   data length = %2d\n",
				 bincnt,dat->code,dat->leng ) ;

		switch ( dat->size ) {
			case 1: bincnt += make1( fp, dat->code, dat->cnum, dat->leng ) ;	break ;
			case 2: bincnt += make2( fp, dat->code, dat->cnum, dat->leng ) ;	break ;
			case 3: bincnt += make3( fp, dat->code, dat->cnum, dat->leng ) ;	break ;
			case 4: bincnt += make4( fp, dat->code, dat->cnum, dat->leng ) ;	break ;
		}
		if ( dat->flag == END ) {
			fputc( 0x00,fp ) ;	/*  write end code	*/
			bincnt++ ;
		}
		chrcnt += dat->leng ;
	}
}

/******* make character data ( 1 bit )  **************************/

int make1( fp,code,cnum,leng )
FILE	*fp ;
int	code,cnum,leng ;
{
	int	ct = 0 ;

	fputc( leng | 0x40, fp ) ;		/*  write flag and  data length		*/
	fputc( cnum, fp ) ;			/*  write character code		*/

	while ( leng-- ) {
		ct += wthalf( &chrbuf[code++][17],fp ) ;
	}
	return ( ct+2 ) ;
}

/******* make character data ( 2 bit )  **************************/

int make2( fp,code,cnum,leng )
FILE	*fp ;
int	code,cnum,leng ;
{
	int	ct = 0 ;

	fputc( leng | 0x80, fp ) ;		/*  write flag and  data length		*/
	fputc( cnum,fp ) ;			/*  write character code		*/

	while ( leng-- ) {
		ct += fwrite( chrbuf[code++],sizeof(char),16,fp ) ;
	}
	return ( ct+2 ) ;
}

/******* make character data ( 3 bit )  **************************/

int make3( fp,code,cnum,leng )
FILE	*fp ;
int	code,cnum,leng ;
{
	int	ct = 0 ;

	fputc( leng | 0xc0, fp ) ;		/*  write flag and  data length		*/
	fputc( cnum,fp ) ;			/*  write character code		*/

	while ( leng-- ) {
		ct += fwrite( chrbuf[code],sizeof(char),16,fp ) ;
		ct += wthalf( &chrbuf[code++][16],fp ) ;
	}
	return ( ct+2 ) ;
}

/******* make character data ( 4 bit )  **************************/

int make4( fp,code,cnum,leng )
FILE	*fp ;
int	code,cnum,leng ;
{
	int	ct = 0 ;

	fputc( leng,fp ) ;		/*  write flag and  data length		*/
	fputc( cnum,fp ) ;		/*  write character code		*/

	while ( leng-- ) {
		ct += fwrite( chrbuf[code++],sizeof(char),32,fp ) ;
	}
	return ( ct+2 ) ;
}

/******* write half of word *************************************/

int wthalf( buff,fp )
char	*buff ;
FILE	*fp ;
{
	int	ct ;

	for ( ct=0 ; ct<8 ; buff+=2,ct++ ) {
		fputc( *buff,fp ) ;
	}
	return ( 8 ) ;
}

/****************************************************************/
/*	read character data					*/
/****************************************************************/

int read_char( fname,code,size )
char	*fname ;
int	code,size ;
{
	FILE	*fp ;

	if (( fp = fopen( fname,"r" )) == NULL )
		return ( ERROR ) ;

	printf( "read file \"%s\"\n", fname ) ;
	if ( fread( chrbuf[code],sizeof(char),size*32,fp ) != size*32 ) {
		return ( ERROR ) ;
	}
	fclose( fp ) ;
	return ( COMPLETE ) ;
}
