[mod.amiga.sources] Graphics display program for the Amiga.

doc@j.cc.purdue.edu (10/01/86)

From: wecker%cookie.DEC@decwrl.DEC.COM  (DAVE  TANSTAAFL  WECKER)

Doc:	Here is the source for a display program that can be used with the
	image files that follow. I've been working with a Ray Tracing program,
	and finally figured out how to take full advantage of the Amiga's
	HAM (Hold and Modify) mode, yielding 4096 colors on the screen at
	once.

	If people like the pictures, I'll send more (they take from 1 hour
	to several days on a dedicated VAX).

	To use the program, compile and link it (nothing special needed) and
	then type: 

		1> DISPLAY FOO.IMG 

	After the picture completes you can exit by clicking on the (invisible)
	close gadget in the upper left corner. I know the program is (very)
	rough, but I haven't had time to make it pretty.. just functional.

	Please post it and let me know what you think.

	Regards,
	dave

--------------------Program begins below this line--------------------------
/***********************************************************************
 *
 *  DISPLAY package for .img files (DBW encoding)
 *
 *	File format:
 *	    MAXX MAXY MAXCOLORS			    	- header
 *	    256 hex colors in descending usage  	- colortable
 *	    Encoding of pixels: (all printable ASCII)
 *		@ - O	= Absolute color (low four bits) in color table
 *		P - _	= Relative color. Low four bits is new BLUE  value
 *		` - o	= Relative color. Low four bits is new RED   value
 *		p - DEL	= Relative color. Low four bits is new GREEN value
 *		' ' - >	= Repeat introducer (next char - ' ' = repeat count)
 *		?       = Alternate encoding for <DEL>
 *		\r \n	= Ignored (end of line markers) (NOT scan line)
 *
 *	v1.0	860907	DBW
 *
 ***********************************************************************/

#include <stdio.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <functions.h>

extern	char	*fgets();

#undef	NULL
#define	NULL	((void *)0)

#define CHECK(x)	while (line[x] < ' ') {\
	if (fgets(line,128,fp) == NULL) return(-1);\
	x = 0;\
	}

struct	GfxBase		*GfxBase;
struct	IntuitionBase	*IntuitionBase;
struct	RastPort	*rp;
struct	ViewPort	*vp;
struct	Window		*w;
struct	Screen		*screen;
struct	IntuiMessage	*message;
struct	NewScreen	ns = {
    0L,0L,320L,400L,6L,
    0,1,HAM|LACE,
    CUSTOMSCREEN,NULL,
    (UBYTE *)"Display screen",
    NULL,NULL };
struct	NewWindow	nw = {
    0L,0L,320L,400L,0L,1L,
    MOUSEBUTTONS|CLOSEWINDOW,
    ACTIVATE|WINDOWCLOSE|BORDERLESS,
    NULL,NULL,
    (UBYTE *)"Display window",
    NULL,NULL,
    0L,0L,320L,400L,CUSTOMSCREEN };

FILE		*fp = NULL;
unsigned char	line[128];
int		maxx,maxy,maxc;
int		colors[16];
int		cpix,cr,cg,cb,count,pos;

main(argc,argv)
int argc;
char *argv[];
    {
    unsigned long class;
    unsigned short code;
    int	    i,x,y,val,bflg;

    GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
    if (GfxBase == NULL) exit(100);

    IntuitionBase = 
	(struct IntuitionBase *)OpenLibrary("intuition.library",0L);
    if (IntuitionBase == NULL) {
	CloseLibrary(GfxBase);
	exit(200);
	}

    screen = (struct Screen *)OpenScreen(&ns);
    if (screen == NULL) {
	CloseLibrary(IntuitionBase);
	CloseLibrary(GfxBase);
	exit(300);
	}

    nw.Screen = screen;
    w	      = (struct Window *)OpenWindow(&nw);
    if (w == NULL) {
	CloseScreen(screen);
	CloseLibrary(IntuitionBase);
	CloseLibrary(GfxBase);
	exit(400);
	}

    vp = &screen->ViewPort;
    rp = w->RPort;

    /* get the file to read */
    if (argc < 2) fp = stdin;
    else	  fp = fopen(argv[1],"r");

    if (fp == NULL) error("Can't open input file");
    if (fgets(line,128,fp) == NULL) error("Can't read first line");
    if (sscanf(line,"%d %d %d\n",&maxx,&maxy,&maxc) != 3) error("Bad header");
    if (maxc != 256) error("expecting 256 colors");
    for (i = 0; i < 16; i++) {
	if (fgets(line,128,fp) == NULL) error("Can't read colors");
	if (i == 0 &&
	    sscanf(line,"%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
	     &colors[0],&colors[1],&colors[2],&colors[3],&colors[4],&colors[5],
	     &colors[6],&colors[7],&colors[8],&colors[9],&colors[10],&colors[11],
	     &colors[12],&colors[13],&colors[14],&colors[15]) != 16)
		error("Didn't find 16 colors as expected");
	}

    /* now set the color map */
    for (i = 0; i < 16; i++) {
	SetRGB4(vp, (long)i, (long)((colors[i] >> 8) & 0xF),
			     (long)((colors[i] >> 4) & 0xF),
			     (long)((colors[i]     ) & 0xF));
	}

    /* now init the read buffer */
    line[0] = '\n';
    pos	    = 0;
    count   = 0;
    cr	    = 0;
    cg	    = 0;
    cb	    = 0;
    cpix    = '@';
    SetDrMd(rp,JAM1);

    /* Read through the file and display the results */
    bflg = 0;
    for (y = 0; y < maxy; y++) {

	/* check if there was an attempt to abort */
	while ((message=(struct IntuiMessage *)GetMsg(w->UserPort))!=NULL) {
	    class   = message->Class;
	    code    = message->Code;
	    ReplyMsg(message);

	    if (class == CLOSEWINDOW) error(NULL);
	    }

	/* now dump the scan line */
	for (x = 0; x < maxx; x++) {
	    if (getnext() == -1) {
		bflg = 1;
		break;
		}
/*
	    val  = ((cr * 7 + cg * 4 + cb * 2) / 2) + 32;
	    if (val > 126) val = 126;
	    if ((y % 10) == 9 && (x % 4) == 3) printf("%c",(char)val);
*/	    
	    if (x < 320 && y < 400) {
		SetAPen(rp,(long)(cpix & 0x3F));
		WritePixel(rp,(long)x,(long)y);
		}
	    }
	if (bflg == 1) break;
/*
	if ((y % 10) == 9) printf("\n");
*/
	}

    /* wait here until we get a close window message */
    while (1) {
	WaitPort(w->UserPort);
	while ((message=(struct IntuiMessage *)GetMsg(w->UserPort))!=NULL) {
	    class   = message->Class;
	    code    = message->Code;
	    ReplyMsg(message);

	    if (class == CLOSEWINDOW) error(NULL);
	    }
	}
    }

error(msg)
char *msg;
    {
    if (msg) {
	puts("ERROR: ");
	puts(msg);
	puts("\n");
	}
    CloseWindow(w);
    CloseScreen(screen);
    CloseLibrary(IntuitionBase);
    CloseLibrary(GfxBase);
    if (fp != NULL && fp != stdin) fclose(fp);
    if (msg) exit(-1);
    else     exit(0);
    }

getnext() {
    int	scr,crgb;

    /* first see if we're in a repeat count */
    if (count-- > 0) return(0);

    /* now see if we need a new buffer */
    CHECK(pos);

    /* see if we got a repeat count */
    if (line[pos] < '?') {
	count = (line[pos] - ' ') * 94;
	++pos;
	CHECK(pos);
	count += line[pos++] - ' ';
	CHECK(pos);
	}
    else
	count = 1;

    /* now bring the character in */
    cpix = line[pos++];
    if (cpix == '?') cpix = 127;
    if (--count < 0) return(0);

    /* now set up all the associated variables */
    scr = (cpix >> 4) & 3;
    switch (scr) {
	case 0:	crgb = colors[cpix & 0xF];
		cr   = (crgb >> 8) & 0xF;
		cg   = (crgb >> 4) & 0xF;
		cb   = (crgb     ) & 0xF;
		break;
	case 1:	cb   = cpix & 0xF;
		break;
	case 2:	cr   = cpix & 0xF;
		break;
	case 3:	cg   = cpix & 0xF;
		break;
	}
    return(0);
    }