/* 
	FM-GRAPHIC EDITOR file loader
*/

#include <stdio.h>
#include <stdlib.h>
#include <egb.h>
#include "tiff.h"

#define II(s)  (short)(*((unsigned char *)&s) * 256 + *((unsigned char *)&s+1))
#define ERR(e) { fmge_err = e ; return -1 ; }

#define ERR_FILE 1
#define ERR_FORM 2

typedef union {
	long p ;
	struct {
		char b,r,g,i ;
	} col ;
} PACK ;

struct {
	short id ;
	short recs ;
	short sx ;
	short sy ;
	short wx ;
	short wy ;
	char mode ;
	char _padding[243] ;
} header ;

int fmge_err ;
int fmge_sx,fmge_sy,fmge_wx,fmge_wy,fmge_mode ;
int xb,bit ;

int gethead( fp )
FILE *fp ;
{
	if( fread( &header, sizeof(header), 1, fp ) == 0 ) ERR(ERR_FILE) ;
	if( header.id != 0x4d46 ) ERR(ERR_FORM) ;
	fmge_sx = II(header.sx) ;
	fmge_sy = II(header.sy) ;
	fmge_wx = II(header.wx) + 1 ; xb = (fmge_wx + 7) / 8 ;
	fmge_wy = II(header.wy) + 1 ;
	fmge_mode = header.mode ;
	return( 0 ) ;
}

void packpixel( sp, dp)
unsigned char *sp ;
long *dp ;
{
	long pix,pm  ;
	unsigned char *cp ;
	register unsigned char mask ;
	register int c,j,i ;

	for( i = 0 ; i < xb ; i++,sp++ ) {
		mask = 0x80 ;
		for( j = 0 ; j < 8 ; j++ ) {
			cp = sp ;
			pix = 0 ;
			pm = 1 << (8 - bit) ;
			for( c = 0 ; c < bit*3 ; c++ ) {
				if( *cp & mask ) 
					pix |= pm ;
				pm <<= 1 ;
				if( c % bit == bit - 1 ) pm <<= 8 - bit ;
				cp += xb ;
			}
			mask >>= 1 ;
			*dp++ = pix ;
		}
	}
}

long *ldbitdat( fp, wx,wy )
FILE *fp ;
int wx,wy ;
{
	int size, y ;
	long *dbp,*bp ;
	unsigned char *sbp ;

	size = wx * wy * 4 + 28 ;
	if( (dbp = (long *)malloc( size )) == 0 ) error("Memory") ;
	if( (sbp = (unsigned char *)malloc( xb * 3 * bit )) == 0 ) 
		error("Memory") ;
	bp = dbp ;
	for( y = 0 ; y < wy ; y++ ) {
		fread(sbp, bit * 3 , xb, fp ) ;
		packpixel( sbp, bp ) ;
		bp += wx ;
	}
	free( sbp ) ;
	return dbp ;
}

sample( work, bp, sx,sy, wx, wy, dwy, mag )
char *work ;
long *bp ;
int sx,sy,wx,wy,dwy,mag ;
{
	long swy,my,pg,pr,pb ;
	short *lb, *lbp ;
	long  *sbp ;
	int x,y,m ;
	char para[16] ;
	PACK bit ;

	lb = (short *)malloc( wx * 2 ) ;
	swy = dwy * mag ;

	DWORD( para + 0 ) = (unsigned int)lb ;
	WORD( para + 4 ) = 0x14 ;
	WORD( para + 6 ) = sx ;
	WORD( para +10 ) = sx + wx - 1 ;

	my = 0 ;
	for( y = 0 ; y < dwy ; y++ ) {
		lbp = lb ;
		sbp = bp ;
		for( x = 0 ; x < wx ; x++ ) {
			pg = pr = pb = 0 ;
			for( m = 0 ; m < mag ; m++ ) {
				bit.p = *(sbp + ((my + m)*wy/swy)*wx ) ;	
				pg += bit.col.g ;
				pr += bit.col.r ;
				pb += bit.col.b ;
			}
			pg = (pg / mag) & 0xF8 ;
			pr = (pr / mag) & 0xF8 ;
			pb = (pb / mag) & 0xF8 ;
			*lbp++ = (pg << 7) + (pr << 2) + (pb >> 3) ;
			sbp++ ;
		}
		my += mag ;
		WORD( para + 8 ) = WORD( para +12 ) = y + sy ;
		EGB_putBlock( work,0,para ) ;
	}
	free( lb ) ;
}

char work[1600] ;
extern int optind ;
extern char *optarg ;

void main( argc,argv ) 
int argc ;
char **argv ;
{
	FILE *fp ;
	long *buf ;
	int mag = 3 ;
	int fwy = 240 ;
	int wf = 1 ;
	int dsy,dwy,c ;
	char name[80] ;

	if( argc < 2 ) usage() ;
	while( ( c = getopt( argc,argv, "s:h:v")) != EOF ) {
		switch( c ) {
		case 's':
			mag = atoi(optarg) ;
			break ;
		case 'h':
			fwy = atoi(optarg) ;
			break ;
		case 'v':
			wf = 0 ;
			break ;
		case '?':
			usage() ;
		}
	}
	if( optind == argc ) usage() ;
	strcpy(name, argv[optind] ) ;
	strcat(name, ".FMG" ) ;
	if( (fp = fopen( name,"rb" )) == NULL ) error( "No File!") ;
	if( gethead( fp ) != 0 ) error( "File Format" ) ;

	if( fmge_mode == 0xFF ) bit = 4 ; else bit = 6 ;

	printf( "Now Loading data of FM-Graphic Editor\n" ) ; 
	buf = ldbitdat( fp, fmge_wx, fmge_wy ) ; 
	fclose( fp ) ;

	EGB_init(work,1536) ;
	EGB_displayPage( work,1,3) ;
	EGB_resolution( work, 0, 10 ) ;
	EGB_displayStart( work, 2, 2, 2 ) ;
	EGB_displayStart( work, 3, 320, 240 ) ;
	dsy = fmge_sy * fwy / 200 ;
	dwy = fmge_wy * fwy / 200 ;
	sample( work, buf, fmge_sx, dsy, fmge_wx, fmge_wy, dwy, mag ) ;
	free(buf) ;
	if( wf ) {
		getchar() ;
		strcpy( name, argv[optind] ) ;
		strcat( name, ".TIF" ) ;
		if(( fp = fopen( name, "wb" )) == NULL ) error( "Write File" ) ;
		setTIFFmode( TIFF_32K ) ;
		mkIFD() ;
		tiff_width = fmge_wx ;
		tiff_length = dwy ;
		putIFD( fp ) ;
		freeIFD() ;
		svram( fp, work, fmge_sx, dsy, fmge_wx, dwy, 16, 0) ;
		fclose( fp ) ;
	}
	getchar();
}

error( msg ) 
char *msg ;
{
	printf( "******** %s Error\n", msg ) ;
	exit( 1 );
}

usage()
{
printf( "USAGE : run386 fmge [-s <smooth>] [-h <height>] [-v] file(.FMG)\n" ) ;
	exit( 1 );
}

