[net.micro.amiga] This is the correct AMIGA version of DISPLAY.C

wecker@cookie.dec.com (DAVE TANSTAAFL WECKER) (10/16/86)

/***********************************************************************
 *
 *  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);
    }