/*
	graphics.c

	display routines for 16 grey scales dithered to simulate 255.
						mcr
*/

#include <graphics/gfxbase.h>
#include <graphics/display.h>
#include <intuition/intuition.h>
#include <stdio.h>
#include "macros.h"

struct	GfxBase		*GfxBase;	/* Export the library pointers */
struct	IntuitionBase	*IntuitionBase;
struct	RastPort	*rp;		/* Graphics structures           */
struct	ViewPort	*vp;
struct	Window		*w;		/* Intuition structures        */ 
struct	Screen		*screen;

struct	NewScreen	ns = {
	0, 0,				/* start position                */
	640, 400, 4,			/* width, height, depth          */
	15, 0,				/* detail pen, block pen         */
	HIRES|INTERLACE,		/* ViewModes			 */
	CUSTOMSCREEN,			/* screen type                   */
	NULL,				/* font to use                   */
	NULL,				/* default title for screen      */
	NULL				/* pointer to additional gadgets */
};

struct NewWindow nw = {
	0, 0,				/* start position                */
	640, 400,			/* width, height                 */
	15, 0,				/* detail pen, block pen         */
	NULL,				/* IDCMP flags                   */
	BORDERLESS,			/* window flags                  */
	NULL,				/* pointer to first user gadget  */
	NULL,				/* pointer to user checkmark     */
	NULL,				/* window title                  */
	NULL,				/* pointer to screen (set below) */
	NULL,				/* pointer to superbitmap        */
	0, 0, 640, 386,			/* ignored since not sizeable    */
	CUSTOMSCREEN			/* type of screen desired        */
};

int	xoff, yoff;

gfx_open()
{
	if( !(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library", 0) ) ) {
		gfx_close();
		return(0);
	}

	if ( !( IntuitionBase = (struct IntuitionBase *)
		OpenLibrary("intuition.library", 0) )
	 ) {
		gfx_close();
		return(0);
	}
	if ( !( screen = (struct Screen *)
		OpenScreen(&ns) )
	) { 
		gfx_close();
		return(0);
	}

	nw.Screen = screen;                /* Open window in our new screen */
	if ( !( w = (struct Window *)
		OpenWindow(&nw) )
	) {
		gfx_close();
		return(0);
	}

	vp = &screen->ViewPort;             /* Set colors in screen's VP    */
	rp = w->RPort;                      /* Render into the window's RP  */

	/* Set the color registers ( cut down on ugly greens )	*/
	SetRGB4(vp, 00, 00, 00, 00);
	SetRGB4(vp, 01, 01, 00, 01);    
	SetRGB4(vp, 02, 02, 01, 02);   
	SetRGB4(vp, 03, 03, 02, 03);
	SetRGB4(vp, 04, 04, 03, 04);
	SetRGB4(vp, 05, 05, 04, 05);
	SetRGB4(vp, 06, 06, 05, 06);
	SetRGB4(vp, 07, 07, 06, 07);
	SetRGB4(vp, 08, 08, 07, 08);
	SetRGB4(vp, 09, 09, 08, 09);
	SetRGB4(vp, 10, 10, 09, 10);
	SetRGB4(vp, 11, 11, 10, 11);
	SetRGB4(vp, 12, 12, 11, 12);
	SetRGB4(vp, 13, 13, 12, 13);
	SetRGB4(vp, 14, 14, 13, 14);
	SetRGB4(vp, 15, 15, 14, 15);

	return( 1 );
}

gfx_close()
{
	if (w)
		CloseWindow(w);

	if (screen)
		CloseScreen(screen);

	if (IntuitionBase)
		CloseLibrary(IntuitionBase);

	if (GfxBase)
		CloseLibrary(GfxBase);
}

struct	Screen	*gfx_screen()
{
	return( screen );
}

do_pixel(x, y, col)
register	int	x, y, col;
{
	SetAPen(rp, dither(x, y, col) );
	WritePixel(rp, x, y );
}


#define DITHSIZE	3
/* 4 x 4 dithering matrix */
static	int	matrix[DITHSIZE+1][DITHSIZE+1] = {
	{  0,  8,  2, 10 },
	{ 12,  4, 14,  6 },
	{  3, 11,  1,  9 },
	{ 15,  7, 13,  5 }
};

/*
	dithering by area access to matrix by using
	the MOD function on the x and y coordinates
*/
dither(x, y, level) /* dithering function */
register	int	x, y, level;
{
	register	int	base;

	base = level >> 4;

	if ( (base == 0x0F) || (level < 8) )
		return(base);

	/*
	 * skew every second line over by half a grid to get a brick-layer's
	 * pattern, rather than a straight grid.  The human eye is too good
	 * at seeing straight lines when the points in the grid line up.
	 */
	x += (y & 8) >> 1;

	if ( (level & 0x0f) < matrix [x%DITHSIZE] [y%DITHSIZE] )
		return(base);

	return(base+1);
}
