/*
	name:	iff.c

	Iff 24-bit color picture support
	--------------------------------

	These routines enable image output in 24-bit iff ILBM format,
	and iff input (2-256 colormapped images + 24-bit images).

	I may have made some overkill here, by adding 68000 assembler
	code for the planar2chunky routines (they are really hard to
	get fast, and can be quite annoying sometimes). It should work
	on any 68k system (Amiga, Mac, HP300/68k...?)


    This source-code is part of the RayLab 1.1 package, and it is provided
    for your compiling pleasure.  You may use it, change it, re-compile it
    etc., as long as nobody else but you receive the changes/compilations
    that you have made!

    You may not use any part(s) of this source-code for your own productions
    without the permission from the author of RayLab. Please read the legal
    information found in the users documentation for RayLab for more details.

*/


#include  <stdlib.h>
#include  <string.h>

#include  "defs.h"
#include  "extern.h"

#define iff_header_size 90
#define max_comp_count 128


typedef unsigned long  ULONG;
typedef unsigned short UWORD;
typedef unsigned char  UBYTE;

typedef struct ilbminfo {	/* (non-standard, for internal use only) */
	UWORD	Width;
	UWORD	Height;
	ULONG	BodySize;
	UBYTE	Planes;
	UBYTE	Compression;
	UWORD	Colors;
	COLOR24	ColorMap[256];
} ILBM_INFO;


/* Global (for iff.c) variables */

	unsigned char iffdata[parraysize*3];
	unsigned char iffplanes[parraysize*3];
	unsigned char iffpacked[parraysize*3+(parraysize*3)/16];	/* In case of overflow */
	long	bodysize;

	unsigned char iff_header[iff_header_size] = {
		'F','O','R','M',		/* "FORM" */
		0x00,0x00,0x00,0x00,		/* Iff file size (Motorola longword) */
		'I','L','B','M',		/* "ILBM" */
		'B','M','H','D',		/* "BMHD" */
		0x00,0x00,0x00,0x14,		/* BMHD size (20 bytes) */
		0x00,0x00,0x00,0x00,		/* Width, Heigth (Motorola words) */
		0x00,0x00,0x00,0x00,
		0x18,0x00,0x01,0x00,		/* 24 bitplanes, enable "byterun1" compression */
		0x00,0x00,0x2c,0x2c,
		0x00,0x00,0x00,0x00,		/* Width, Heigth (Motorola words) */
		'A','N','N','O',		/* "ANNO" */
		0x00,0x00,0x00,0x22,		/* ANNO size (34 bytes) */
		/* "RayLab 1.1 © 1996 Marcus Geelnard" */
		'R','a','y','L','a','b',' ','1','.','1',' ',0xa9,
		' ','1','9','9','6',' ','M','a','r','c','u','s',
		' ','G','e','e','l','n','a','r','d',0x00,
		'B','O','D','Y',		/* "BODY" */
		0x00,0x00,0x00,0x00		/* BODY size (Motorola longword) */
	};

	ILBM_INFO HeaderInfo;



/* ---------------------------------------------------------------------
	WriteIffHeader()
   --------------------------------------------------------------------- */

void WriteIffHeader(FILE *f, long width, long height)
{
	long	xres,yres;
	double	yresd;

	bodysize=0L;

	iff_header[20]=iff_header[36]=(char)(width>>8);	/* Set initial width and height */
	iff_header[21]=iff_header[37]=(char)(width&0xff);
	iff_header[22]=iff_header[38]=(char)0;
	iff_header[23]=iff_header[39]=(char)0;

	if(width<368)      xres=44;			/* Set reslution, based on  */
	else if(width>736) xres=11;			/* the width/height and the */
	else               xres=22;			/* camera-aspect.           */
	yresd=(double)(xres*width)*Camera.Aspect.y/((double)height*Camera.Aspect.x);
	yres=(int)yresd;
	if(fmod(yresd,1.0)>=0.5) yres++;
	iff_header[34]=(unsigned char)xres;
	iff_header[35]=(unsigned char)yres;

	(void) fwrite(iff_header,sizeof(unsigned char),(size_t)iff_header_size,f);
}


/* ---------------------------------------------------------------------
	WriteIffLine()
   --------------------------------------------------------------------- */

void WriteIffLine(FILE *f, long width)
{
	long	linesize;

	IffChunkyToPlanar(width);			/* The iff ILBM format uses planar (interleaved) image data */
	linesize=IffCompressPlanar(width);		/* ...and a simple, non-destructive compression-method. */
	bodysize+=linesize;
	(void) fwrite(iffpacked,sizeof(unsigned char),(size_t)linesize,f);
}


/* ---------------------------------------------------------------------
	CleanupIff()
   --------------------------------------------------------------------- */

void CleanupIff(FILE *f)
{
	register long	formsize;
	
	formsize=bodysize+iff_header_size-4;	/* Total file-size, excluding the word "FORM" */

	(void) fseek(f,4L,SEEK_SET);
	WriteMotLongWord(f,formsize);
	(void) fseek(f,iff_header_size-4L,SEEK_SET);
	WriteMotLongWord(f,bodysize);
	(void) fseek(f,22L,SEEK_SET);
	WriteMotShortWord(f,RenderedLines);	/* Write amount of rendered lines (works for interrupted pics) */
	(void) fseek(f,38L,SEEK_SET);
	WriteMotShortWord(f,RenderedLines);
}


/* ---------------------------------------------------------------------
	ReadIffHeader()
   --------------------------------------------------------------------- */

void ReadIffHeader(FILE *f, long *width, long *height)
{
	int	i,FoundCHUNK;
	ULONG	LongWord,csize;

	*width=-1L; *height=-1L;
	FoundCHUNK=FALSE;

	(void) fseek(f,0L,SEEK_SET);
	if(ReadMotLongWord(f)==0x464f524dL) {			/* Look for "FORM" */
	    (void) fseek(f,8L,SEEK_SET);
	    if(ReadMotLongWord(f)==0x494c424dL) {		/* Look for "ILBM" */
		csize=FindChunk(f,(char *)"BMHD");		/* Look for "BMHD" */
		if(csize>0L) FoundCHUNK=TRUE;
		if(FoundCHUNK==TRUE) {
		    HeaderInfo.Width=(UWORD)ReadMotShortWord(f);
		    HeaderInfo.Height=(UWORD)ReadMotShortWord(f);
		    (void) fseek(f,4L,SEEK_CUR);
		    HeaderInfo.Planes=(UBYTE)fgetc(f);
		    (void) fseek(f,1L,SEEK_CUR);
		    HeaderInfo.Compression=(UBYTE)fgetc(f);
		}
		else fprintf(textoutput,"\nError: Could not find BMHD section in iff file.\n");
	    }
	    else fprintf(textoutput,"\nError: Not an ILBM iff file.\n");
	}
	else fprintf(textoutput,"\nError: Not an iff file.\n");

	if(FoundCHUNK==TRUE) {
	    if(HeaderInfo.Planes==24) {
		HeaderInfo.Colors=0;
		FoundCHUNK=TRUE;
	    }
	    else {
		HeaderInfo.Colors=(UWORD)(1<<(int)HeaderInfo.Planes);
		(void) fseek(f,12L,SEEK_SET);
		FoundCHUNK=FALSE;
		csize=FindChunk(f,(char *)"CMAP");		/* Look for "CMAP" */
		if(csize>0L) FoundCHUNK=TRUE;
		if(FoundCHUNK==TRUE) {
		    LongWord=csize/3;
		    if(((HeaderInfo.Planes==6)&&(LongWord<=32))||((HeaderInfo.Planes==8)&&(LongWord<=64))) {
			fprintf(textoutput,"\nError: Amount of colors does not match amount of bitplanes in iff file (HAM?)\n");
			FoundCHUNK=FALSE;
		    }
		    else {
			for(i=0;i<256;i++) {			/* Init color-map */
			    if(i<LongWord) {
				HeaderInfo.ColorMap[i].r=(UBYTE)fgetc(f);
				HeaderInfo.ColorMap[i].g=(UBYTE)fgetc(f);
				HeaderInfo.ColorMap[i].b=(UBYTE)fgetc(f);
			    }
			    else {
				HeaderInfo.ColorMap[i].r=(UBYTE)0;
				HeaderInfo.ColorMap[i].g=(UBYTE)0;
				HeaderInfo.ColorMap[i].b=(UBYTE)0;
			    }
			}
		    }
		}
		else fprintf(textoutput,"\nError: Could not find color-map in iff file.\n");
	    }
	    if(FoundCHUNK==TRUE) {
		(void) fseek(f,12L,SEEK_SET);
		FoundCHUNK=FALSE;
		csize=FindChunk(f,(char *)"BODY");		/* Look for "BODY" */
		if(csize>0L) {
		    FoundCHUNK=TRUE;
		    HeaderInfo.BodySize=csize;
		}
		if(FoundCHUNK==TRUE) {
		    *width=(long)HeaderInfo.Width;
		    *height=(long)HeaderInfo.Height;
		}
		else fprintf(textoutput,"\nError:  Could not find BODY (image data) in iff file.\n");
	    }
	}
}


/* ---------------------------------------------------------------------
	ReadIffImage()
   --------------------------------------------------------------------- */

short ReadIffImage(int *ImageNum, FILE *f, long width, long height)
{
	int	i;
	short	ImageType;
	IMAGE24	*Img24;
	IMAGE8	*Img8;
	unsigned char *IFFBody,*ImgBody;
	long	IFFBodyOffset;

	ImageType=IMG_NONE;
	*ImageNum=0;


	/* 24-bit image */

	if(HeaderInfo.Planes==(UBYTE)24) {
	    if(Num24Images<maximages) {
		Img24=(IMAGE24 *)malloc(sizeof(IMAGE24));
		if(Img24!=NULL) {
		    Img24->XSize=width; Img24->YSize=height;
		    Img24->Interpolate=INTPOL_NONE;
		    Img24->Maptype=MAP_PLANAR;
		    Img24->Tile=TILE_TRUE;
		    Img24->Body=(unsigned char *)malloc((size_t)(3*width*height));
		    if(Img24->Body!=NULL) {
			IFFBody=(unsigned char *)malloc((size_t)HeaderInfo.BodySize);
			if(IFFBody!=NULL) {
			    (void) fread(IFFBody,(size_t)HeaderInfo.BodySize,(size_t)1,f);
			    ImgBody=Img24->Body;
			    IFFBodyOffset=0L; i=0;
			    while((IFFBodyOffset<HeaderInfo.BodySize)&&(i<height)) {
				IFFBodyOffset+=IffDeCompressPlanar(&IFFBody[IFFBodyOffset],width,24);
				IffPlanarToChunky(ImgBody,width,24);
				ImgBody=&ImgBody[width*3];
				i++;
			    }
			    *ImageNum=(short)Num24Images;
			    Img24Array[Num24Images]=Img24;
			    Num24Images++;
			    ImageType=IMG_24BIT;
			    free(IFFBody);
			}
			else {
			    fprintf(textoutput,"\nError: Could not allocate memory for iff body\n");
			    free(Img24->Body); free(Img24);
			    ImageType=IMG_NONE;
			}
		    }
		    else {
			fprintf(textoutput,"\nError: Could not allocate memory for image data\n");
			free(Img24);
			ImageType=IMG_NONE;
		    }
		}
		else {
		    fprintf(textoutput,"\nError: Could not allocate memory for image\n");
		    ImageType=IMG_NONE;
		}
	    }
	    else {
		fprintf(textoutput,"\nError: maximum amount of 24-bit images exceeded\n");
	    }
	}


	/* 8-bit color-mapped image */

	else {
	    if(Num8Images<maximages) {
		Img8=(IMAGE8 *)malloc(sizeof(IMAGE8));
		if(Img8!=NULL) {
		    Img8->XSize=width; Img8->YSize=height;
		    Img8->Interpolate=INTPOL_NONE;
		    Img8->Maptype=MAP_PLANAR;
		    Img8->Tile=TILE_TRUE;
		    Img8->Body=(unsigned char *)malloc((size_t)(width*height));
		    if(Img8->Body!=NULL) {
			IFFBody=(unsigned char *)malloc((size_t)HeaderInfo.BodySize);
			if(IFFBody!=NULL) {
			    for(i=0;i<256;i++) {
				Img8->Colormap[i].r=(double)HeaderInfo.ColorMap[i].r/255.0;
				Img8->Colormap[i].g=(double)HeaderInfo.ColorMap[i].g/255.0;
				Img8->Colormap[i].b=(double)HeaderInfo.ColorMap[i].b/255.0;
			    }
			    (void) fread(IFFBody,(size_t)HeaderInfo.BodySize,(size_t)1,f);
			    ImgBody=Img8->Body;
			    IFFBodyOffset=0L; i=0;
			    while((IFFBodyOffset<HeaderInfo.BodySize)&&(i<height)) {
				IFFBodyOffset+=IffDeCompressPlanar(&IFFBody[IFFBodyOffset],width,(int)HeaderInfo.Planes);
				IffPlanarToChunky(ImgBody,width,(int)HeaderInfo.Planes);
				ImgBody=&ImgBody[width];
				i++;
			    }
			    *ImageNum=(short)Num8Images;
			    Img8Array[Num8Images]=Img8;
			    Num8Images++;
			    ImageType=IMG_8BIT;
			    free(IFFBody);
			}
			else {
			    fprintf(textoutput,"\nError: Could not allocate memory for iff body\n");
			    free(Img8->Body); free(Img8);
			    ImageType=IMG_NONE;
			}
		    }
		    else {
			fprintf(textoutput,"\nError: Could not allocate memory for image data\n");
			free(Img8);
			ImageType=IMG_NONE;
		    }
		}
		else {
		    fprintf(textoutput,"\nError: Could not allocate memory for image\n");
		    ImageType=IMG_NONE;
		}
	    }
	    else {
		fprintf(textoutput,"\nError: maximum amount of color-mapped images exceeded\n");
	    }
	}


	return(ImageType);
}


/* ---------------------------------------------------------------------
	IffChunkyToPlanar()
   --------------------------------------------------------------------- */

void IffChunkyToPlanar(long width)
{
	unsigned char planebuff[24], *pb, *pixels, *planes;
	register long	bytes, i, j, k ,l;
	register unsigned char a;
	long	count;
	
	pixels=iffdata;
	for(i=0;i<width;i++) {
	    *pixels++=pixelarray[i].r;
	    *pixels++=pixelarray[i].g;
	    *pixels++=pixelarray[i].b;
	};

	pixels=iffdata;
	bytes=(width>>3)&0x7ffffffeL;	/* bytes = amount of bytes per bitplane-line */
	if((width&0x0f)!=0) bytes+=2;

	count=0;
	for(l=0;l<bytes;l++) {
	    for(i=0;i<8;i++){
		pb=planebuff;
		for(j=0;j<3;j++) {	/* Three bytes per pixel (r,g,b) */
		    if(count<width) a=*pixels++;
		    else a=0;
		    for(k=0;k<8;k++) {
			*pb++=(*pb<<1)|(a&0x01); a=a>>1;
		    }
		}
		count++;
	    }
	    pb=planebuff;
	    planes=&iffplanes[l];	/* Next eight pixels */
	    for(i=0;i<24;i++) {
		*planes=*pb++;
		planes+=bytes;		/* Next bitplane */
	    }
	}

}


/* ---------------------------------------------------------------------
	IffCompressPlanar()
   --------------------------------------------------------------------- */

long IffCompressPlanar(long width)
{
	unsigned char *src, *src2;
	signed char *dest;
	register unsigned char oldbyte;
	register long	srcleft, destsize, count, i, j;
	long	srcsize;

	src=iffplanes; dest=iffpacked;

	srcsize=(width>>3)&0x7ffffffeL;
	if((width&0x0f)!=0) srcsize+=2;
	destsize=0L;

	for(i=0;i<24;i++) {
	    srcleft=srcsize;
	    while(srcleft>0) {
		src2=src;
		count=1L; oldbyte=*src++;
		while(((srcleft-count)>0)&&(count<max_comp_count)&&(oldbyte==*src)) {
		    count++; src++;
		}
		if(count>2) {			/* More than two lookalikes? */
		    *dest++=(signed char)-(count-1L);
		    *dest++=oldbyte;
		    destsize+=2;
		}
		else {				/* Ok, copy source straight off until we find lookalikes */
		    while(((srcleft-count)>0)&&(count<max_comp_count)&&((oldbyte!=*src)||(count<3))) {
			count++; oldbyte=*src; src++;
		    }
		    if((oldbyte==*src)&&((srcleft-count)>0)&&(count<max_comp_count)) {
			count-=1L; src--;
		    }
		    *dest++=(char)(count-1L);
		    for(j=0;j<count;j++) {
			*dest++=*src2++;
		    }
		    destsize+=(1+count);
		}
		srcleft-=count;
	    }
	}

	return(destsize);
}


/* ---------------------------------------------------------------------
	IffDeCompressPlanar()
   --------------------------------------------------------------------- */

long IffDeCompressPlanar(unsigned char *Data, long width, int planes)
{
	unsigned char *source,*destination,a;
	long	destsize,retvalue;
	int	i,j,ctrl;

	retvalue=0L;

	source=Data;
	destination=iffplanes;
	destsize=(width>>3)&0x7ffffffeL;	/* >>3 <=> /8 */
	if((width&0x0f)!=0) destsize+=2;
	destsize*=(long)planes;

	if(HeaderInfo.Compression==(UBYTE)0) {
	    for(i=0;i<destsize;i++) *destination++=*source++;
	    retvalue=destsize;
	}
	else {
	    i=0;
	    while(i<destsize) {
		ctrl=(int)*source++;
		retvalue++; j=0;
		if((ctrl&0x0080)!=0) {			/* Fill */
		    ctrl=257-ctrl;
		    a=*source++;
		    retvalue++;
		    while((j<ctrl)&&(i<destsize)) {
			*destination++=a;
			i++; j++;
		    }
		}
		else {					/* Copy */
		    ctrl++;
		    while((j<ctrl)&&(i<destsize)) {
			*destination++=*source++;
			i++; j++;
		    }
		    retvalue+=j;
		}
	    }
	}

	return(retvalue);
}


/* ---------------------------------------------------------------------
	IffPlanarToChunky()
   --------------------------------------------------------------------- */

void IffPlanarToChunky(unsigned char *Chunky, long width, int planes)
{
	unsigned char *source[24],*srctmp,*destination,a;
	int	i,j,k,l,bplsize,count;

	bplsize=(width>>3)&0x7ffffffeL;
	if((width&0x0f)!=0) bplsize+=2;

	destination=Chunky;
	for(i=0;i<planes;i++)  source[i]=&iffplanes[i*bplsize];

	count=0;
#if !(defined(__GNUC__) && defined(__mc68000__))
	if(planes<=8) {
#else
	if(planes<8) {
#endif
	    for(i=0;i<bplsize;i++) {
		for(j=7;j>=0;j--) {
		    if(count<width) {
			a=0;
			for(l=planes-1;l>=0;l--) {
			    srctmp=source[l];
			    a=(a<<1)|((srctmp[i]>>j)&0x01);
			}
			*destination++=a;
		    }
		    count++;
		}
	    }
	}

#if defined(__GNUC__) && defined(__mc68000__)
	else if(planes==8) {

/* The assembler routine is slow, but yet faster than the _SLOW_ C routine!
   This is the 8-bit routine, which uses all 15 general purpose 32-bit regs
   of the 68000 (I could use some more), which reduces the memory-accesses
   to 1.5 accesses/pixel, as compared to 99 accesses/pixel for the 24-bit
   routine.
   If you feel like optimizing for other processors than the MC68000, be my
   guest. */

    __asm__ ("
	movem.l	d0-d7/a0-a6,-(sp)
	move.l	%0,-(sp)	/* Save desitnation(s) on stack */
	move.l	%1,a1		/* a1 = destination */
	move.l	%2,a4		/* a4 = width */

	moveq	#0,d6		/* Byte-offset from first byte in each plane */
pixel_loop8:
	move.l	(sp),a0		/* a0 = source[] */
	move.l	(a0)+,a3
	move.l	(a3,d6.w),d0
	move.l	(a0)+,a3
	move.l	(a3,d6.w),d1
	move.l	(a0)+,a3
	move.l	(a3,d6.w),d2
	move.l	(a0)+,a3
	move.l	(a3,d6.w),d3
	move.l	(a0)+,a3
	move.l	(a3,d6.w),d4
	move.l	(a0)+,a3
	move.l	(a3,d6.w),d5
	move.l	(a0)+,a3
	move.l	(a3,d6.w),a5
	move.l	(a0),a3
	move.l	(a3,d6.w),a6
	move.l	#32,a0
bit_loop8:
	add.l	d0,d0
	roxr.b	#1,d7
	add.l	d1,d1
	roxr.b	#1,d7
	add.l	d2,d2
	roxr.b	#1,d7
	add.l	d3,d3
	roxr.b	#1,d7
	add.l	d4,d4
	roxr.b	#1,d7
	add.l	d5,d5
	roxr.b	#1,d7
	exg	d0,a5
	exg	d1,a6
	add.l	d0,d0
	roxr.b	#1,d7
	add.l	d1,d1
	roxr.b	#1,d7
	subq.l	#1,a4
	cmp.l	#0,a4
	ble.s	done8
	move.b	d7,(a1)+
	exg	d0,a5
	exg	d1,a6
	subq.l	#1,a0
	cmp.l	#0,a0
	bgt	bit_loop8
	addq.l	#4,d6
	bra	pixel_loop8

done8:	addq.l	#4,sp
	movem.l	(sp)+,d0-d7/a0-a6

    " : /* no output */
      : "a" (source),		/* 0 */
        "a" (destination),	/* 1 */
        "d" (width),		/* 2 */
        "d" (planes)		/* 3 */
      /* no clobbering, all used registers saved on the stack */
    );

	}
#endif

	else {

#if !(defined(__GNUC__) && defined(__mc68000__))
	    for(i=0;i<bplsize;i++) {
		for(j=7;j>=0;j--) {
		    if(count<width) {
			for(k=0;k<3;k++) {
			    a=0;
			    for(l=7;l>=0;l--) {
				srctmp=source[(k<<3)+l];
				a=(a<<1)|((srctmp[i]>>j)&0x01);
			    }
			    *destination++=a;
			}
		    }
		    count++;
		}
	    }
#else

/* The assembler routine is slow, but yet faster than the _SLOW_ C routine!
   This is the 24-bit routine, which is a quite heavy one.
   If you feel like optimizing for other processors than the MC68000, be my
   guest (planar2chunky requires quite some concentration, and too many
   memory-accesses using this method - any ideas?)! */

    __asm__ ("
	movem.l	d0-d1/d3-d7/a0-a3,-(sp)
	move.l	%2,d7		/* d7 = width */
	move.l	%0,a0		/* a0 = source[] */
	move.l	%1,a1		/* a1 = destination */

	moveq	#0,d3		/* Byte-offset from first byte in each plane */
	moveq	#8,d4
	subq.w	#1,d7
pixel_loop24:
	move.l	a0,a2
	moveq	#3-1,d6
bit1_loop24:
	moveq	#8-1,d5
bit2_loop24:
	move.l	(a2)+,a3
	lea	(a3,d3.w),a3
	move.b	(a3),d0
	add.b	d0,(a3)
	roxr.b	#1,d1
	dbf	d5,bit2_loop24
	move.b	d1,(a1)+
	dbf	d6,bit1_loop24
	subq.l	#1,d4
	bgt	not_new_byte24
	moveq	#8,d4
	addq.l	#1,d3
not_new_byte24:
	dbf	d7,pixel_loop24

	movem.l	(sp)+,d0-d1/d3-d7/a0-a3

    " : /* no output */
      : "a" (source),		/* 0 */
        "a" (destination),	/* 1 */
        "d" (width)		/* 2 */
      /* no clobbering, all used registers saved on the stack */
    );
#endif

	}


}


/* ---------------------------------------------------------------------
	FindChunk()
   --------------------------------------------------------------------- */

long FindChunk(FILE *f,char *cname)
{
	char	cfound[5];
	long	csize;
	int	i,a,EndOfFile,FoundChunk;

	EndOfFile = FoundChunk = FALSE;

	(void) fseek(f,(size_t)12,SEEK_SET);
	while((EndOfFile == FALSE)&&(FoundChunk == FALSE)) {
	    for(i=0;i<4;i++) {
		if(EndOfFile == FALSE) {
		    a = fgetc(f);
		    if(a == EOF) EndOfFile = TRUE;
		    else cfound[i] = (char)a;
		}
	    }
	    if(EndOfFile == FALSE) {
		cfound[4] = (char)0;
		csize = ReadMotLongWord(f);
		if(strcmp(cfound,cname) == 0) FoundChunk = TRUE;
		else (void) fseek(f,(size_t)csize,SEEK_CUR);
	    }
	}
	if(FoundChunk == FALSE) csize = -1L;

	return(csize);
}


/* ---------------------------------------------------------------------
   This is just a compability issue;
   32-bit longwords should have MSB first, then bits 23-16,
   followed by bits 15-8, and last LSB (Motorola style)
   --------------------------------------------------------------------- */

void WriteMotLongWord(FILE *f, long lw)
{
	int	i;

	for(i=0;i<4;i++) {
	    fputc((int)((lw>>24)&0xff),f);
	    lw=lw<<8;
	}
}

void WriteMotShortWord(FILE *f, long lw)
{
	int	i;

	lw=lw<<16;
	for(i=0;i<2;i++) {
	    fputc((int)((lw>>24)&0xff),f);
	    lw=lw<<8;
	}
}

long ReadMotLongWord(FILE *f)
{
	long	lw;
	int	i;

	lw=0L;
	for(i=0;i<4;i++) {
	    lw=(lw<<8)|(long)(fgetc(f)&0xff);
	}

	return(lw);
}

long ReadMotShortWord(FILE *f)
{
	long	lw;

	lw=0L;
	lw=(long)(fgetc(f))&0xff;
	lw=(lw<<8)|(long)(fgetc(f)&0xff);

	return(lw);
}
