#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <proto/exec.h>
#ifdef CPU020
#include <exec/execbase.h>
#endif
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <time.h>
#include <proto/dos.h>
#define HEIGHT 400L
#define DEPTH 6
#define WIDTH 320L
#define rowoffset (WIDTH/8)
#define MODULUS (0x20000L)
#define C 13849
#define A 25173
#define randu2(x) (((seed = seed*A+C))%(x))
#define unmap(x) (randu2(6)+rev_array[(x)])
#ifdef LATTICE
#define PROTOTYPES 1
#endif

#ifndef LATTICE
#define __regargs
#endif

#ifdef DEBUG
int temparray[64];
#endif

/*************************************************
/*
/* This code © 1989 by W. Roger uzun
/* This code is for Lattice 5.0X
/* compile using - lc -v -cf -L -O -w EHBPlasma (for 68000 version)
/* or lc -v -cf -L -m2 -O -dCPU020 -w EHBPlasma (for 68020 version)
/*
/*************************************************/

#define WINDOWSIGNAL (1L<<(wG->UserPort->mp_SigBit))

#define PaletteColorCount 32

short nplanes = DEPTH;
UBYTE *bp[DEPTH];
short ytable[HEIGHT];

struct TextFont *myTextFont;

struct RastPort *rpG;

struct TextAttr TOPAZ80 = {
	(STRPTR)"topaz.font",
	TOPAZ_EIGHTY,0,0
};
struct NewScreen NewScreenStructure = {
	0,0,	/* screen XY origin relative to View */
	320,HEIGHT,	/* screen width and height */
	6,	/* screen depth (number of bitplanes) */
	0,1,	/* detail and block pens */
	LACE+EXTRA_HALFBRITE,	/* display modes for this screen */
	CUSTOMSCREEN,	/* screen type */
	&TOPAZ80,	/* pointer to default screen font */
	"Plasma",	/* screen title */
	NULL,	/* first in list of custom screen gadgets */
	NULL	/* pointer to custom BitMap structure */
};

#define NEWSCREENSTRUCTURE NewScreenStructure

USHORT Palette[] = {
	0x000,	/* color #0 */
	0x01f,	/* color #1 */
	0x03d,	/* color #2 */
	0x05b,	/* color #3 */
	0x079,	/* color #4 */
	0x097,	/* color #5 */
	0x0a5,  /* color #6 */
	0x0b4,  /* color #7 */
	0x0c3,  /* color #8 */
	0x0e1,  /* color #9 */
	0x0f0,  /* color #10 */

	0x01f0,	/* color #11 */
	0x03d0,	/* color #12 */
	0x05b0,	/* color #13 */
	0x0790,	/* color #14 */
	0x0970,	/* color #15 */
	0x0a50,	/* color #16 */
	0x0B40,	/* color #17 */
	0x0c30,	/* color #18 */
	0x0e10,	/* color #19 */
	0x0f00,	/* color #20 */

	0x0f01,	/* color #21 */
	0x0d03,	/* color #22 */
	0x0b05,	/* color #23 */
	0x0907,	/* color #24 */
	0x0709,	/* color #25 */
	0x050a,	/* color #26 */
	0x040b,	/* color #27 */
	0x030c,	/* color #28 */
	0x020d,	/* color #29 */
	0x010e,	/* color #30 */
	0x000f  /* color #31 */
};

#define PALETTE Palette

struct IntuiText IText1 = {
	3,1,JAM1,	/* front and back text pens, drawmode and fill byte */
	0,0,	/* XY origin relative to container TopLeft */
	&TOPAZ80,	/* font pointer or NULL for default */
	"Quit",	/* pointer to text */
	NULL	/* next IntuiText structure */
};

struct MenuItem MenuItem2 = {
	NULL,	/* next MenuItem structure */
	0,8,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
	80,8,	/* hit box width and height */
	ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP,	/* Item flags */
	0,	/* each bit mutually-excludes a same-level Item */
	(APTR)&IText1,	/* Item render  (IntuiText or Image or NULL) */
	NULL,	/* Select render */
	'Q',	/* alternate command-key */
	NULL,	/* SubItem list */
	MENUNULL	/* filled in by Intuition for drag selections */
};

struct IntuiText IText2 = {
	3,1,JAM1,	/* front and back text pens, drawmode and fill byte */
	0,0,	/* XY origin relative to container TopLeft */
	&TOPAZ80,	/* font pointer or NULL for default */
	"About",	/* pointer to text */
	NULL	/* next IntuiText structure */
};

struct MenuItem MenuItem1 = {
	&MenuItem2,	/* next MenuItem structure */
	0,0,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
	80,8,	/* hit box width and height */
	ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP,	/* Item flags */
	0,	/* each bit mutually-excludes a same-level Item */
	(APTR)&IText2,	/* Item render  (IntuiText or Image or NULL) */
	NULL,	/* Select render */
	'A',	/* alternate command-key */
	NULL,	/* SubItem list */
	MENUNULL	/* filled in by Intuition for drag selections */
};

struct Menu Menu1 = {
	NULL,	/* next Menu structure */
	0,0,	/* XY origin of Menu hit box relative to screen TopLeft */
	63,0,	/* Menu hit box width and height */
	MENUENABLED,	/* Menu flags */
	"Project",	/* text of Menu name */
	&MenuItem1	/* MenuItem linked list pointer */
};

#define MenuList1 Menu1

struct NewWindow NewWindowStructure1 = {
	0,0,	/* window XY origin relative to TopLeft of screen */
	320,HEIGHT,	/* window width and height */
	4,8,	/* detail and block pens */
	VANILLAKEY|MENUPICK,	/* IDCMP flags */
	SMART_REFRESH+BACKDROP+BORDERLESS+ACTIVATE,	/* other window flags */
	NULL,	/* first gadget in gadget list */
	NULL,	/* custom CHECKMARK imagery */
	" ",	/* window title */
	NULL,	/* custom screen pointer */
	NULL,	/* custom bitmap */
	5,5,	/* minimum width and height */
	-1,-1,	/* maximum width and height */
	CUSTOMSCREEN	/* destination screen type */
};

SHORT BorderVectors1[] = {
	0,0,
	51,0,
	51,41,
	0,41,
	0,0
};
struct Border Border1 = {
	-1,-1,	/* XY origin relative to container TopLeft */
	3,0,JAM1,	/* front pen, back pen and drawmode */
	5,	/* number of XY vectors */
	BorderVectors1,	/* pointer to XY vectors */
	NULL	/* next border in list */
};

struct IntuiText IText3 = {
	3,0,JAM2,	/* front and back text pens, drawmode and fill byte */
	15,17,	/* XY origin relative to container TopLeft */
	NULL,	/* font pointer or NULL for default */
	"OK",	/* pointer to text */
	NULL	/* next IntuiText structure */
};

struct Gadget Gadget1 = {
	NULL,	/* next gadget */
	65,217,	/* origin XY of hit box relative to window TopLeft */
	50,40,	/* hit box width and height */
	NULL,	/* gadget flags */
	RELVERIFY,	/* activation flags */
	BOOLGADGET,	/* gadget type flags */
	(APTR)&Border1,	/* gadget border or image to be rendered */
	NULL,	/* alternate imagery for selection */
	&IText3,	/* first IntuiText structure */
	NULL,	/* gadget mutual-exclude long word */
	NULL,	/* SpecialInfo structure */
	NULL,	/* user-definable data */
	NULL	/* pointer to user-definable data */
};

#define GadgetList2 Gadget1

struct IntuiText IText5 = {
	3,0,JAM2,	/* front and back text pens, drawmode and fill byte */
	40,114,	/* XY origin relative to container TopLeft */
	NULL,	/* font pointer or NULL for default */
	"By Roger Uzun",	/* pointer to text */
	NULL	/* next IntuiText structure */
};

struct IntuiText IText4a = {
	3,0,JAM2,	/* front and back text pens, drawmode and fill byte */
	16,61,	/* XY origin relative to container TopLeft */
	NULL,	/* font pointer or NULL for default */
	"Press 'C' to Cycle",	/* pointer to text */
	&IText5	/* next IntuiText structure */
};

struct IntuiText IText4 = {
	3,0,JAM2,	/* front and back text pens, drawmode and fill byte */
	6,21,	/* XY origin relative to container TopLeft */
	NULL,	/* font pointer or NULL for default */
	"EHBPlasma Version 1.f",	/* pointer to text */
	&IText4a	/* next IntuiText structure */
};


struct NewWindow NewWindowStructure3 = {
	70,30,	/* window XY origin relative to TopLeft of screen */
	180,280,	/* window width and height */
	0,1,	/* detail and block pens */
	GADGETUP,	/* IDCMP flags */
	SIMPLE_REFRESH+ACTIVATE+NOCAREREFRESH,	/* other window flags */
	&Gadget1,	/* first gadget in gadget list */
	NULL,	/* custom CHECKMARK imagery */
	" ",	/* window title */
	NULL,	/* custom screen pointer */
	NULL,	/* custom bitmap */
	5,5,	/* minimum width and height */
	-1,-1,	/* maximum width and height */
	CUSTOMSCREEN	/* destination screen type */
};


struct Screen *sC;
struct Window *wG;
UWORD done=0;

long maparray[256]={5,1,1,1,1,1,2,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,/* 26 */
		    7,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,/* 43 */
                    33,33,33,33,33,34,34,34,34,34,35,35,35,35,/* 57 */
		    36,36,36,36,37,37,37,37,38,38,38,38,39,39,39,39,/* 73 */
		    40,40,40,40,41,41,41,41,42,42,42,42, /* 85 */

		    11,11,11,11,11,12,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,/* 26 */
		    17,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,/* 43 */
                    43,43,43,43,43,44,44,44,44,44,45,45,45,45,/* 57 */
		    46,46,46,46,47,47,47,47,48,48,48,48,49,49,49,49,/* 73 */
		    50,50,50,50,51,51,51,51,52,52,52,52, /* 85 */

		    21,21,21,21,21,22,22,22,22,22,23,23,23,23,24,24,24,24,25,25,25,25,26,26,26,26,/* 26 */
		    27,27,27,27,27,28,28,28,28,29,29,29,30,30,30,31,31,/* 43 */
                    53,53,53,53,53,54,54,54,54,54,55,55,55,55,/* 57 */
		    56,56,56,56,57,57,57,57,58,58,58,58,59,59,59,59,/* 73 */
		    60,60,60,61,61,61,62,62,62,63,63,63 /* 85 */};
long rev_array[64]={	0,
			1,5,9,13,17,21,25,29,33,38,
			86,90,94,98,102,106,110,114,118,123,
			171,175,179,183,187,191,195,199,203,206,
			208,32,
			44,48,52,56,60,64,68,72,76,83,
			129,133,137,141,145,149,153,157,161,165,
			214,218,222,226,230,234,238,242,246,250,
			250};
	
unsigned short seed = 7;

#ifdef PROTOTYPES

int __regargs ReadPix(long,long);
void __regargs FastPix(long,long,long);
void CycleColors(void);
void __regargs HandleEvent(APTR);
void DoAbout(void);
void DoQuit(void);
void __regargs SubDivide(long,long,long,long);
void __regargs adjust(long,long,long,long,long,long);

#endif


void CycleColors()
{
 ULONG class;
 UWORD d=0,i,temp;
 USHORT tpal[PaletteColorCount];
 struct IntuiMessage *message;

 for(i=0;i<PaletteColorCount;i++)
  tpal[i] = Palette[i];
 while (!d)
  {
   temp = tpal[1];
   for(i=2;i<PaletteColorCount;i++)
    {
     tpal[i-1] = tpal[i];
    }
   tpal[(PaletteColorCount-1)] = temp;
   LoadRGB4(&(sC->ViewPort),tpal,PaletteColorCount);
   Delay(6L);
   if ( (message = (struct IntuiMessage *)
	GetMsg(wG->UserPort) ))
    {
	class = message->Class;
	ReplyMsg((struct Message *)message);
	if (class = VANILLAKEY)
	 d = 1;
    }
  } 
 LoadRGB4(&(sC->ViewPort),Palette,PaletteColorCount);
}

void __regargs adjust(xa,ya,x,y,xb,yb)
long xa,ya,x,y,xb,yb;
{
 long t1,t2;
 int pa,pb,pc,pd;
 register long globalcolor;

 if (ReadPix(x,y))
  return;
 pa = xa;
 pb  =xb;
 pc = ya;
 pd = yb;
 globalcolor = randu2(3) * (abs(pa-pb)+abs(pc-pd));
 t1 = unmap(ReadPix(xa,ya));
 t2 = unmap(ReadPix(xb,yb));
 if (!randu2(2))
  {
   globalcolor = -globalcolor;
  }
 globalcolor = ((t1+t2)>>1)+globalcolor;
 globalcolor &= 0xffL;
 globalcolor = maparray[globalcolor];
 FastPix(x,y,globalcolor);
#ifdef DEBUG
temparray[globalcolor]++;
#endif
}

void __regargs SubDivide(x1,y1,x2,y2)
long x1,y1,x2,y2;
{
 long t1,t2,t3,t4;
 ULONG signals,v;
 struct IntuiMessage *message;
 long x,y,class,code;
 APTR object;
 UWORD d;

 if (((x2-x1)<2L) && ((y2-y1)<2L))
  return;
 if ( (message = (struct IntuiMessage *)
	GetMsg(wG->UserPort) ))
  {
	class = message->Class;
	code = message->Code;
	object = message->IAddress;  /* Gadget */
	ReplyMsg((struct Message *)message);
	if ( class == MENUPICK )	/* MenuItems */
	 HandleEvent((APTR)ItemAddress(&MenuList1,code));
	else if (class = VANILLAKEY)
	 {
          if ((code == 'c')||(code == 'C'))
	   {
	    CycleColors();
	   }
          else
           {
	    d = 0;
	    while(!d)
	     {
	      signals = Wait(WINDOWSIGNAL);
	      if (signals & WINDOWSIGNAL)
	       while ((message = (struct IntuiMessage *)
	              GetMsg(wG->UserPort)))
	        {
	         class = message->Class;
	         ReplyMsg((struct Message *)message);
	         if (class == VANILLAKEY)
	          d = 1;
	        }
	     }
           }
	 }
  }
 if (done)
  return;
 x = (x1+x2)>>1;
 y = (y1+y2)>>1;
 if (!ReadPix(x,y))
  {
   t1 = unmap(ReadPix(x1,y1));
   t2 = unmap(ReadPix(x2,y1));
   t3 = unmap(ReadPix(x2,y2));
   t4 = unmap(ReadPix(x1,y2));
   v = ((t1+t2+t3+t4)>>2);
   v = maparray[v];
   FastPix(x,y,v);
  }
 adjust(x1,y1,x,y1,x2,y1);
 adjust(x2,y1,x2,y,x2,y2);
 adjust(x1,y2,x,y2,x2,y2);
 adjust(x1,y1,x1,y,x1,y2);
 SubDivide(x1,y1,x,y);
 SubDivide(x,y1,x2,y);
 SubDivide(x,y,x2,y2);
 SubDivide(x1,y,x,y2);
}

void DoAbout()
{
 struct IntuiMessage *message;
 struct Window *wG3;

 if (!(wG3 = OpenWindow(&NewWindowStructure3)))
 {
  DisplayBeep(0L);
  return;
 }
 PrintIText(wG3->RPort,&IText4,0L,0L);
 WaitPort(wG3->UserPort);
 while(message = (struct IntuiMessage *)GetMsg(wG3->UserPort))
  ReplyMsg((struct Message *)message);
 CloseWindow(wG3);
}

void __regargs HandleEvent(object)
APTR object;
{
  if (object == (APTR)&MenuItem1) { DoAbout(); return; }
  if (object == (APTR)&MenuItem2) { DoQuit(); return; }
}
#define HANDLEEVENT HandleEvent

/* end of PowerWindows source generation */



void DoQuit()
{
 done = TRUE;
}

/* end of PowerWindows source generation */


void main(void);
void main()
{
 int i;
#ifdef DEBUG
int d;
#endif
	ULONG code;
	ULONG class;
	APTR object;
	ULONG signals;
	struct IntuiMessage *message;	/* the message the IDCMP sends us */

#ifdef CPU020

 struct ExecBase **execbaseptr=(struct ExecBase **)4L;
 UWORD cpuid;
 struct ExecBase *execbase;

 execbase = *execbaseptr;
 cpuid = execbase->AttnFlags;
 if (!(cpuid & AFF_68020))
  {
   exit(0);
  }
#endif

        nplanes = DEPTH - 1;

#ifdef DEBUG
for(d=0;d<64;d++)temparray[d] = 0;
#endif
	if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 33L)))
         {
           exit(0);
         }
	if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 33L)))
         {
           CloseLibrary((struct Library *)IntuitionBase);
           exit(0);
         }
        if (!(myTextFont = OpenFont(&TOPAZ80)))
         {
          CloseLibrary((struct Library *)GfxBase);
          CloseLibrary((struct Library *)IntuitionBase);
          exit(0);
         }
	if (!(sC = OpenScreen(&NewScreenStructure)))
         {
          CloseFont(myTextFont);
          CloseLibrary((struct Library *)GfxBase);
          CloseLibrary((struct Library *)IntuitionBase);
          exit(0);
         }
	LoadRGB4(&(sC->ViewPort),Palette,PaletteColorCount);
	NewWindowStructure3.Screen = NewWindowStructure1.Screen = sC;
	wG = OpenWindow(&NewWindowStructure1);	/* open the window */
	if ( wG == NULL )
	{
	  CloseScreen(sC);
          CloseFont(myTextFont);
          CloseLibrary((struct Library *)GfxBase);
          CloseLibrary((struct Library *)IntuitionBase);
          exit(0);
	}
	rpG = wG->RPort;	/* get a rastport pointer for the window */
	SetFont(rpG,myTextFont);
	SetMenuStrip(wG,&MenuList1);	/* attach any Menu */
        SetDrMd(rpG,JAM1);
        for(i=0;i<DEPTH;i++)
         bp[i] = wG->RPort->BitMap->Planes[i];
        ytable[0] = 0;
	for(i=1;i<HEIGHT;i++)
	 ytable[i] = ytable[i-1] + rowoffset;
        seed = time(0L);
        signals = (randu2(63)) + 1L;
        FastPix(0L,11L,signals);
        signals = (randu2(63)) + 1L;
        FastPix(319L,11L,signals);
        signals = (randu2(63)) + 1L;
        FastPix(319L,HEIGHT-1L,signals);
        signals = (randu2(63)) + 1L;
        FastPix(0L,HEIGHT-1L,signals);
        SubDivide(0L,11L,319L,HEIGHT-1L);
	DisplayBeep(0L);
	while(!done)
	{
		signals = Wait(WINDOWSIGNAL);
		if (signals & WINDOWSIGNAL)
			while( (message = (struct IntuiMessage *)
				GetMsg(wG->UserPort) ) != NULL)
			{
				class = message->Class;
				code = message->Code;
				object = message->IAddress;  /* Gadget */
				ReplyMsg((struct Message *)message);
				if ( class == MENUPICK )	/* MenuItems */
				 HandleEvent((APTR)ItemAddress(&MenuList1,code));
				else if (class = VANILLAKEY)
				 {
			          if ((code == 'c')||(code == 'C'))
				   {
				    CycleColors();
				   }
				 }
			}
	}
        CloseWindow(wG);
        CloseFont(myTextFont);
        CloseScreen(sC);
        CloseLibrary((struct Library *)GfxBase);
        CloseLibrary((struct Library *)IntuitionBase);
#ifdef DEBUG
for(d=0;d<64;d++)printf("temp[%d] = %d\n",d,temparray[d]);
#endif
}
