#include <exec/types.h>
#include <exec/memory.h>

#include <intuition/intuition.h>
#include <dos/dos.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/alib_protos.h>

extern	ULONG	Depth, Mode;
UWORD	Colors5[] = {	0x0F20, 0x0E30, 0x0C50, 0x0B60, 0x0980, 0x0890, 0x06B0, 0x05C0, 0x03E0, 0x02F0, 0x00F2,
	0x00E3, 0x00C5, 0x00B6, 0x0098, 0x006B, 0x005C, 0x003E, 0x002F, 0x020F, 0x030E, 0x050C,	0x060B, 0x0809,
	0x0908, 0x0B06, 0x0C05, 0x0E03, 0x0F02, 0x0F00 }, Colors4[] = {	0x0E03, 0x0B06, 0x0909, 0x060B, 0x030E,
	0x003E, 0x006B, 0x0099, 0x00B6, 0x00E3, 0x03E0,	0x06B0, 0x0990, 0x0B60, 0x0E30 }, Colors3[] = {	0x0E00,
	0x0770, 0x00E0, 0x0077, 0x000E, 0x0707 }, Colors2[] = {	0x0E00, 0x00E0, 0x000E }, Colors1[] = { 0x0FFF },
	*Table[5], Range[] = { 32, 32, 32, 22, 14, 8, 4, 2 }, *Cell, Hei, Wid;

VOID CycleColors( struct Screen *Scr, ULONG Depth )
{
static	ULONG	pos = 0;
	ULONG	i, j = 0, Colors = ( 1L << Depth ) - 1;

	SetRGB4(&( Scr->ViewPort ), 0, 0, 0, 0 );
	for( i = pos; j < Colors; i = ++i % Colors )
		SetRGB4(&( Scr->ViewPort ), ++j, ( Table[Depth-1][i] & 0x0F00 ) >> 8,
			( Table[Depth-1][i] & 0x00F0 ) >> 4, Table[Depth-1][i] & 0x000F);

	pos = ++pos % Colors;
}

#define SetCell( l, c, val ) *( Cell + ( l * Wid + c )) = val;
#define ValCell( l, c ) ( *( Cell + ( l * Wid + c )))

void set( UWORD l, UWORD c, UWORD size, LONG value, struct RastPort *Rast )
{
	UWORD rang;

	rang = Range[size];
	value = value + RangeRand( rang ) - ( rang + 1 ) / 2;
	if( value < 1 ) value = 1;
	SetCell( l, c, value );
	SetAPen( Rast, value );
	WritePixel( Rast, c, l );
}

void grow( struct RastPort *Rast )
{
	UWORD l, c, i, step, nextStep, l1, l2, c1, c2;

	SetCell( 0, 0, 0 );
	step = 256;
	for( i = 0; i < 8; i++ ) {
		nextStep = step / 2;
		for( l = 0; ( l < Hei )&&( !( SetSignal( 0, 0 ) & SIGBREAKF_CTRL_C )); l += step ) {
			l1 = ( l + nextStep ) % Hei;
			l2 = ( l + step ) % Hei;
			for( c = 0; c < Wid; c += step ) {
				c1 = ( c + nextStep ) % Wid;
				c2 = ( c + step ) % Wid;
				set( l, c1, i, ( ValCell( l, c ) + ValCell( l, c2 ) + 1 ) / 2, Rast );
				set( l1, c, i, ( ValCell( l, c ) + ValCell( l2, c ) + 1 ) / 2, Rast );
				set( l1, c1, i, ( ValCell( l, c ) + ValCell( l, c2 ) + ValCell( l2, c ) + 
					ValCell( l2, c2 ) + 2 ) / 4, Rast );
			}
		}
		step = nextStep;
	}
}

VOID blank( VOID )
{
	struct	Screen	*Scr;
		LONG	i;

	if( Scr = OpenScreenTags( NULL, SA_Depth, Depth, SA_Overscan, OSCAN_STANDARD, SA_DisplayID, Mode, SA_Quiet,
		TRUE, SA_Behind, TRUE, TAG_DONE )) {

		Wid = Scr->Width;
		Hei = Scr->Height;

		CycleColors( Scr, Depth );
		BlankMousePointer();
		ScreenToFront( Scr );

		if( Cell = AllocVec( Wid * Hei * sizeof( WORD ), MEMF_CLEAR )) {

			while(!( SetSignal( 0L, 0L ) & SIGBREAKF_CTRL_C )){

				SetRast(&( Scr->RastPort ), 0 );
				grow(&( Scr->RastPort ));

				for( i = 0; ( i < 200 )&&(!( SetSignal( 0L, 0L ) & SIGBREAKF_CTRL_C )); i++ ) {
					WaitTOF();
					WaitTOF();
					CycleColors( Scr, Depth );
				}
			}
			FreeVec( Cell );
	 	}
		SetSignal( 0L, SIGBREAKF_CTRL_C );
		UnblankMousePointer();
		CloseScreen( Scr );
	}
}
