/************************************************/
/*  COMVIEW 1.01 - C64 Doodle/Koala pic viewer  */
/*----------------------------------------------*/
/*  By:  Paul Grebenc, July 2, 1990             */
/*  Written using Lattice C V5.02               */
/*----------------------------------------------*/
/*  Program displays C64 Doodle and Koala Paint */
/*  format picture files on the Amiga.          */
/************************************************/

#define INTUITION_REV 0
#define GRAPHICS_REV 0

#include <exec/types.h>
#include <intuition/intuition.h>
#include <dos.h>
#include <stdio.h>
#include <graphics/display.h>

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

struct Screen *Scrn;
struct Window *Wind;
struct IntuiMessage *Mesg;

int count,loop,inloop;
int x,y;
int color,hires,colormem[1000],loscreen[1000],hiscreen[1000];
ULONG flags,MessageClass;
VOID OpenAll(),help(),doodle(),koala();
FILE *fp;

main(argc,argv)
int argc;
char *argv[];
{
	/* ======Examine command line arguments====== */
	
	if(argc!=3)	/* Usage:  COMVIEW mode filename (3 args) */
	{
		help();
		exit(FALSE);
	}
	if((argv[1][0]!='d')&&(argv[1][0]!='k'))	/* Valid mode? */
	{
		help();
		exit(FALSE);
	}
	
			
	OpenAll();		/* Open Libraries */

	
	/* ======Open a screen to display Doodle picture in====== */

	if((Scrn=(struct Screen *)make_screen(0,320,200,4,0x00,0x01,
		NULL,NULL)) == NULL)
	{
		CloseLibrary(IntuitionBase);
		CloseLibrary(GfxBase);
		printf("Unable to open screen!\n");
		exit(FALSE);
	}

	
	/* ======Set colors for Commodore 64 palette====== */
	
	SetRGB4(&Scrn->ViewPort,0,0,0,0);	/* Black */
	SetRGB4(&Scrn->ViewPort,1,15,15,15);	/* White */
	SetRGB4(&Scrn->ViewPort,2,13,2,0);	/* Red */
	SetRGB4(&Scrn->ViewPort,3,0,13,14);	/* Cyan */
	SetRGB4(&Scrn->ViewPort,4,14,0,14);	/* Purple */
	SetRGB4(&Scrn->ViewPort,5,0,13,6);	/* Green */
	SetRGB4(&Scrn->ViewPort,6,4,0,14);	/* Blue */
	SetRGB4(&Scrn->ViewPort,7,14,14,4);	/* Yellow */
	SetRGB4(&Scrn->ViewPort,8,12,7,0);	/* Orange */
	SetRGB4(&Scrn->ViewPort,9,9,7,0);	/* Brown */
	SetRGB4(&Scrn->ViewPort,10,14,8,5);	/* Lt Red */
	SetRGB4(&Scrn->ViewPort,11,6,6,6);	/* Dk Grey */
	SetRGB4(&Scrn->ViewPort,12,9,9,9);	/* Md Grey */
	SetRGB4(&Scrn->ViewPort,13,10,15,10);	/* Lt Green */
	SetRGB4(&Scrn->ViewPort,14,8,7,15);	/* Lt Blue */
	SetRGB4(&Scrn->ViewPort,15,11,11,11);	/* Lt Grey */
	
	
	/* ======Open the window for the display of picture====== */
	
	flags=ACTIVATE|WINDOWDEPTH|WINDOWCLOSE|SMART_REFRESH|BORDERLESS;
	
	if((Wind=(struct Window *)make_window(0,0,320,200,NULL,flags,
		CLOSEWINDOW,00,00,Scrn,NULL))==NULL)
	{
		CloseScreen(Scrn);
		CloseLibrary(IntuitionBase);
		CloseLibrary(GfxBase);
		printf("Could not open window!\n");
		exit(FALSE);
	}
	
	SetRast(Wind->RPort,00);	/* Screen to black */

	
	/* ======Open the file to read in doodle picture====== */
	
	fp = fopen(argv[2],"r");
	if (fp==NULL)
	{
		CloseWindow(Wind);
		CloseScreen(Scrn);
		CloseLibrary(IntuitionBase);
		CloseLibrary(GfxBase);
		printf("Could not open file!\n");
		exit(FALSE);
	}

	
	/* ======Which format of display to we branch off to====== */
	
	if(argv[1][0]=='d')	/* Which format do we show? */
	{
		doodle();	/* 'd' Doodle, 'k' Koala    */
	}
	else
	{
		koala();
	}


	fclose(fp);	/* Close the file! */


	/* ======Routine to wait for the user to close the window====== */

	for( ; ; )
	{
		if((Mesg=(struct IntuiMessage *)
			GetMsg(Wind->UserPort))==NULL)
		{
			Wait(1 << Wind->UserPort->mp_SigBit);
			continue;
		}
		MessageClass = Mesg->Class;
		ReplyMsg(Mesg);
		if(MessageClass == CLOSEWINDOW)
		{
			CloseWindow(Wind);
			CloseScreen(Scrn);
			CloseLibrary(IntuitionBase);
			CloseLibrary(GfxBase);
			exit(TRUE);
		}
	}
}



/* ======Help display for those less fortunate than us====== */

VOID help()
{
		printf("\nCOMVIEW 1.01, C64 picture viewer - ©1990 Paul Grebenc\n");
		printf("\nUsage:  COMVIEW mode filename\n");
		printf(" Mode:  'd' Doodle picture - 'k' Koala picture\n\n");
}



/* ======Display a Doodle picture file with file pointer (fp)====== */

VOID doodle()
{	
	hires = getc(fp);	/* See if this is a Doodle file or not! */
	color = getc(fp);
	if((hires != 0x00) || (color != 0x5c))	/*Address of Doodle file*/
	{
		CloseWindow(Wind);
		CloseScreen(Scrn);
		CloseLibrary(IntuitionBase);
		CloseLibrary(GfxBase);
		fclose(fp);
		printf("\nThat file is not a Doodle picture!\n");
		printf("\nUsage:  COMVIEW mode filename\n\n");
		exit(FALSE);
	}
	
	fseek(fp,2,0);  /* Beginning of color data in Doodle file */
	
	for(count=0; count<1000; count++)
	{
		color = getc(fp);	/* Get a byte of color.  Lower */
					/* nibble is background color. */
		colormem[count]=((color & 240) >> 4); /* For hires color */
		
		y=(count/40);	/* Find x,y for this 8 x 8 block */
		x=( (count - (40 * y) ) * 8 );
		y = y * 8;
		
		SetAPen(Wind->RPort,color);	/* Change color */
		SetDrMd(Wind->RPort,JAM1);	/* Set draw mode */
		RectFill(Wind->RPort,x,y,x+7,y+7);	/* Fill Block */
	}
	
	fseek(fp,1026,0);  /* Beginning of hires data in Doodle file */
	
	for(count=0; count<1000; count++)
	{
		y=(count/40);		/* Find base for first block */
		x=((count-(40*y))*8);	/* of hi-res graphics        */
		y=y*8;
		
		SetAPen(Wind->RPort,colormem[count]); /* Set color */
		
		for(loop=0; loop<8; loop++)
		{
			hires = getc(fp);	/* Byte of hires picture */

			if(hires & 128)
				WritePixel(Wind->RPort,x,y+loop);
			if(hires & 64)
				WritePixel(Wind->RPort,x+1,y+loop);
			if(hires & 32)
				WritePixel(Wind->RPort,x+2,y+loop);
			if(hires & 16)
				WritePixel(Wind->RPort,x+3,y+loop);
			if(hires & 8)
				WritePixel(Wind->RPort,x+4,y+loop);
			if(hires & 4)
				WritePixel(Wind->RPort,x+5,y+loop);
			if(hires & 2)
				WritePixel(Wind->RPort,x+6,y+loop);
			if(hires & 1)
				WritePixel(Wind->RPort,x+7,y+loop);
		}
	}
}



/* ======Display a Koala picture file with file pointer (fp)====== */

VOID koala()
{
	hires = getc(fp);    /* See if this is a Koala file or not! */
	color = getc(fp);
	if((hires != 0x00) || (color != 0x60)) /* Address of Koala file */
	{
		CloseWindow(Wind);
		CloseScreen(Scrn);
		CloseLibrary(IntuitionBase);
		CloseLibrary(GfxBase);
		fclose(fp);
		printf("\nThat file is not a Koala picture!\n");
		printf("\nUsage:  COMVIEW mode filename\n\n");
		exit(FALSE);
	}

	fseek(fp,10002,0);	/* This is where background color is */
	color = getc(fp);
	SetRast(Wind->RPort,color);	/* Set background color */
	
	/* ======Read in our color data now for use in drawing====== */
	
	fseek(fp,8002,0);	/* Beginning of screen memory in Koala */
	for(count=0; count<1000; count++)
	{
		color = getc(fp);	/* Get byte of screen */
		hiscreen[count] = ((color & 240) >> 4);	/* pattern 01 */
		loscreen[count] = (color & 15);		/* patterm 10 */
	}
	for(count=0; count<1000; count++)  /* Color memory comes next */
	{
		color = getc(fp);
		colormem[count] = (color & 15);		/* pattern 11 */
	}
	
	fseek(fp,2,0);	/* Back to beginning of hires data */
	
	SetDrMd(Wind->RPort,JAM1);	/* Drawmode */
	
	for(count=0; count<1000; count++)
	{
		y=count/40;	/* Find base for first block of hires */
		x=((count-(40*y))*8);
		y=y*8;
		
		for(loop=0; loop<8; loop++)
		{
			hires = getc(fp);  /* Byte of hires picture */
			
			for(inloop=6; inloop>=0; inloop-=2)
			{
				if((hires & 3) == 1)
				{
					SetAPen(Wind->RPort,hiscreen[count]);
					RectFill(Wind->RPort,x+inloop,y+loop,x+inloop+1,y+loop);
				}	
				else if((hires & 3) == 2)
				{
					SetAPen(Wind->RPort,loscreen[count]);
					RectFill(Wind->RPort,x+inloop,y+loop,x+inloop+1,y+loop);
				}
				else if((hires & 3) == 3)
				{
					SetAPen(Wind->RPort,colormem[count]);
					RectFill(Wind->RPort,x+inloop,y+loop,x+inloop+1,y+loop);
				}
				hires = (hires >> 2);
			}
		}
	}
}


/* Open_All() sets up the intuition environment for the user. */

VOID OpenAll()
{
	IntuitionBase=(struct IntuitionBase *)
		OpenLibrary("intuition.library",INTUITION_REV);
	if(IntuitionBase==NULL)
		exit(FALSE);
		
	GfxBase=(struct GfxBase *)
		OpenLibrary("graphics.library",GRAPHICS_REV);
	if(GfxBase==NULL)
		exit(FALSE);		
}


/* make_screen() will open a screen with the supplied characteristics. */
		 
make_screen(y,w,h,d,color0,color1,mode,name)
SHORT y,w,h,d;
UBYTE color0,color1,*name;
USHORT mode;
{
	struct NewScreen NewScreen;
	
	NewScreen.LeftEdge=0;		/* initialize a NewScreen object */
	NewScreen.TopEdge=y;
	NewScreen.Width=w;
	NewScreen.Height=h;
	NewScreen.Depth=d;
	NewScreen.DetailPen=color0;
	NewScreen.BlockPen=color1;
	NewScreen.ViewModes=mode;
	NewScreen.Type=CUSTOMSCREEN;
	NewScreen.Font=NULL;
	NewScreen.DefaultTitle=name;
	NewScreen.Gadgets=NULL;
	NewScreen.CustomBitMap=NULL;
	
	return(OpenScreen(&NewScreen));	/* return the address of screen */
}


/* make_window() will open a window in the specified screen and with the
		indicated characteristics. */

make_window(x,y,w,h,name,flags,iflags,color0,color1,screen,firstgadget)
SHORT x,y,w,h;
UBYTE *name,color0,color1;
ULONG flags;
USHORT iflags;
struct Screen *screen;
struct Gadget *firstgadget;
{
	struct NewWindow NewWindow;
	
	NewWindow.LeftEdge=x;	/* initialize a NewWindow object */
	NewWindow.TopEdge=y;
	NewWindow.Width=w;
	NewWindow.Height=h;
	NewWindow.DetailPen=color0;
	NewWindow.BlockPen=color1;
	NewWindow.Title=name;
	NewWindow.Flags=flags;
	NewWindow.IDCMPFlags=iflags|CLOSEWINDOW|VANILLAKEY;
	if(screen==NULL)
	{
		NewWindow.Type=WBENCHSCREEN;
		NewWindow.Screen=NULL;
	}
	else
	{
		NewWindow.Type=CUSTOMSCREEN;
		NewWindow.Screen=screen;
	}
	NewWindow.FirstGadget=firstgadget;
	NewWindow.CheckMark=NULL;
	NewWindow.BitMap=NULL;
	NewWindow.MinWidth=0;
	NewWindow.MinHeight=0;
	NewWindow.MaxWidth=0;
	NewWindow.MaxHeight=0;
	
	return(OpenWindow(&NewWindow)); /*return address of the window */
}
