/* :ts=4
*
*	simple.c -- a simple debox picture displayer
*
*	William A. Ware							9007.20
*
*****************************************************************************
*   This information is CONFIDENTIAL and PROPRIETARY						*
*   Copyright (C) 1990, Silent Software Incorporated.						*
*   All Rights Reserved.													*
****************************************************************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <graphics/gfxbase.h>
#include <graphics/view.h>
#include "debox.h"
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include "deboxproto.h"


struct GfxBase *GfxBase;
struct Library *DeBoxBase;

BPTR				outfile;	/* for stdout outputs */

BPTR		  		file;
struct CompHeader	header;
UBYTE				*indata;		/* the body of the data */
LONG				insize;			/* the size of the body */
struct BMInfo 		*bmi;			/* info on the bitmap */
struct BitMap 		*bm;
UBYTE				*mask;
LONG				planesize;
struct View	  		*view;
struct View			*oldview;


void cleanexit( int rv, char *exitmsg )
{
	if (rv != 0) 
	{
		if (outfile)
		{
			Write( outfile, exitmsg, strlen(exitmsg) );
			Write( outfile, "\n", 1);
		}
	}
	if (oldview) LoadView(oldview);
	if (view)	 DeleteView((struct SuperView *)view);
	if (mask)	 FreeMem( mask, planesize );
	if (bm)		 FreeBitMap(bm);
	if (bmi)	 FreeBMInfo(bmi);
	if (indata)	 FreeMem(indata,insize);
	if (file)	 Close(file);
	if (DeBoxBase)	CloseLibrary(DeBoxBase);
	if (GfxBase) 	CloseLibrary(GfxBase);
	
	exit(rv);
}


main(int argc,char **argv)
{
	LONG i;
		/* Picture Information */

	outfile = Output();
	if (argc != 2) 
		cleanexit(5,"Usage: simple <file>");
	
	/* Open Libraries -- Gfx and Debox */
	if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",1L)))
		cleanexit(10,"Unable to open graphics.library.");
	if (!(DeBoxBase = OpenLibrary("debox.library",0L)))
		cleanexit(10,"Unable to open debox.library.");
	
	if (!(file = Open(argv[1],MODE_OLDFILE))) 	
		cleanexit(5,"Unable to open input file.");

		/* First read a header into a buffer */
	if (Read(file,(char *)&header,COMPHEADER_SIZE) != COMPHEADER_SIZE)
		cleanexit(5,"Unable to read header.");
	
		/* This is not really required.  It just a check to see if the
		 * data is for the proper version.  */
	if (HeaderSize( &header ) != COMPHEADER_SIZE) 
		cleanexit(5,"Header Version inccorrect.");

		/* Another Check -- This time for a picture. (not required, it is
		 * safe not to check ) */
	if (header.ci_Type != DEBOXTYPE_PIC)
		cleanexit(5,"File not a debox picture.");

		/* NEW - header.ci_CSize will be the correct size */
	insize = header.ci_CSize;

		/* Allocate and load */
	if (!(indata = AllocMem( insize, MEMF_PUBLIC )))
		cleanexit(5,"Unable to allocate memory for the file.");
	if (Read(file,(char *)indata,insize) != insize )
		cleanexit(5,"Unable to read the file into memory.");

		/* Now the picture is ready to be decompressed.  First however
		 * the information on the bitmap needs to be retrieved.
		 * If this routine fails then the file is not a sbox - picture file 
		 * or it is a corrupted picture file.
		 */
	if (!(bmi = DecompBMInfo( NULL,&header, indata ))) 
		cleanexit(5,"Error in data.");
		
		/* Now the bitmap and view port can be made with this information */
	
	if (!(bm = AllocBitMap(bmi->bmi_Depth,bmi->bmi_Width,bmi->bmi_Height)))
		cleanexit(5,"Unable to allocate a bitmap.");
	
		/* If there is a mask - need an extra plane. */
	planesize = bm->Rows * bm->BytesPerRow;
	if (bmi->bmi_Flags & BMIF_HAS_MASK)
	{
		if (!(mask = AllocMem( planesize, MEMF_CHIP )))
			cleanexit( 5,"Unable to allocat memory for mask.");
	}
	
		/* CREATE THE VIEW - Allocated also (thats what the NULL is for) */
	if (!(view=(struct View *)CreateView(NULL,bm,bmi->bmi_Width,
										bmi->bmi_Height,bmi->bmi_Modes)))
		cleanexit(5,"Unable to allocate view structures.");

			/* Load the Color Map if availible */
	if (bmi->bmi_ColorMap)
		LoadRGB4(view->ViewPort,bmi->bmi_ColorMap,bmi->bmi_NumColors);

			/* Now I am going to decompress the bitmap. */
	if (DecompBitMap(&header,indata,bm,mask) < 0)
		cleanexit(5,"Error in data.");

			/* SAVE the old view and load the new view */
	oldview = GfxBase -> ActiView;	
	LoadView( view );
	
	if (bmi->bmi_ColorMap && bmi->bmi_RangeInfo)
	{
		/* I Have a colormap and some ranges - Do some Color cycling */
		
		/* I Could put this into a Vertical Interrupt - Since I Just want
		   to cycle the colors I am just do a simple loop */
		for(i=0;i<240;i++)
		{
			WaitTOF();
				/* 16666 - is the micro seconds for 60 frames a second.
				 *         The PAL value would be 20000 for 50 fps. */
			if (CycleColors( bmi, (LONG)16666 ))
				LoadRGB4(view->ViewPort,bmi->bmi_ColorMap,bmi->bmi_NumColors);
				/* If CycleRanges() Returns != 0 then The colortable has
				   changed */
		}
	}
	else
	{	/* No Ranges or colormap - Just sit for 4 seconds */
		Delay(240L);
	}

		/* If There is a mask Show it, to prove that it is there */
	if (mask)
	{
		int i;
		CopyMem(mask,bm->Planes[0],planesize);
		for(i=1;i<bm->Depth;i++) MemSet(bm->Planes[i],0,planesize);
		SetRGB4( view->ViewPort, 0, 0,0,0 );
		SetRGB4( view->ViewPort, 1, 0xf,0xf,0xf );
		Delay(120L);
	}
	
	cleanexit( 0, NULL );
}
