  /* Fichier clock.dark.c				*/
/* Module appele par le programme principal	*/
/* pour effectuer un effet defini..appele par	*/
/* loadseg					*/
#include	<exec/types.h>
#include	<exec/ports.h>
#include	<graphics/display.h>
#include	<graphics/gfxbase.h>
#include	<intuition/intuition.h>
#include	<hardware/custom.h>
#include	<math.h>
#include	"/includes/struct.h"
#include	"/includes/tom_gadget.h"

#define	WIDTH	640
#define	HEIGHT	256
#define	SGN(x)	((x)<0?-1:1)
#define	ABS(x)	((x)<0?(-(x)):(x))

char	buffer[100];
extern	struct my_data	*p_info;
extern	char	*pr_buff;
extern	struct	GfxBase	*GfxBase;

char	*p_text_info="Fracblank\nBased on a Program From ???\nAdapted and Modified!\n";

#define reg register
extern	void __asm MultiPlot(reg __a0 struct Screen *,reg __d0 WORD, reg __d1 WORD,reg __d2 WORD);
extern	void __asm MonoPlot(	reg __a0 PLANEPTR,
				reg __d0 WORD,
				reg __d1 WORD,
				reg __d2 WORD,
				reg __d3 WORD,
				reg __d4 WORD);

char	*p_modes[]={"Monochrome","Static Colors","Dynamic Colors",0};
char	*p_type[]={"RealPlane","CosmicFlame","RandoM",0};
int	duree=10;

struct	tom_gadget	my_gadg[]={
	{"_Mode",	CYCLE,     60,  20,200,12, 0,0,0,0,(char *)p_modes},
	{"T_empo",	SLIDER,    60,  40,200,12, 0,10,100,0,NULL},
	{"T_ype",	MX,    	   170, 55,100,20, 3,10,100,0,(char *)p_type},
	{0,		END_LISTE,  0,  0,   0, 0, 0,0,0,0,0}};

struct NewScreen NewBlankerScreen ={
	0,0,
	WIDTH,HEIGHT,
	4,0,1,MODE_640,CUSTOMSCREEN,
	NULL,NULL,NULL,NULL};

ULONG	count_col,count;

#ifndef custom
#define custom (*(struct Custom *)0xDFF000)
#endif	/* custom */

struct Screen		*BlankScreen;


	/* sin -45° = cos -45° (saves precious calculation time). */

#define deg45	(-0.707106781)
enum	{	COLOUR_MONO,COLOUR_STATIC,COLOUR_CYCLE};

	/* Rainbow colour table. */

UWORD			 Table[75];

	/* No colours at all. */

UWORD			 Black[32];
	/* The colours of a rainbow (well, with a bit of imagination, just
	 * 32 colours in this rainbow for now).
	 */

UWORD Rainbow[32] =
{
	0x0000,0x0F00,0x0F30,0x0F50,
	0x0F70,0x0F90,0x0FB0,0x0FD0,
	0x0FF0,0x0DF0,0x0BF0,0x09F0,
	0x07F0,0x05F0,0x03F0,0x00F0,
	0x00D1,0x00B3,0x0095,0x0077,
	0x0059,0x003B,0x001D,0x000F,
	0x010F,0x030F,0x050F,0x070F,
	0x090F,0x0B0F,0x0D0F,0x0F0F
};
	/* Some kind of a semaphore to tell the blank task to stop drawing. */

BYTE			 StopDrawing	= FALSE;

	/* Cosmic flame fractal parameters. */

#define MAXFLAMELEVEL	20
#define MAXTOTALPOINTS	20000

	/* Declarations for cosmic flame blanker code. */

float			 Flame[2][3][2];
WORD			 FlameLevel,
			 FlameAlternateForm,
			 FlameModulo;
UWORD			 FlameColourTable[32];
BYTE			 FlameWheel,
			 FlameColour;
PLANEPTR		 FlamePlane;
ULONG			 FlamePoints;


	/* Random(ULONG MaxValue):
	 *
	 *	Simple random number generation routine.
	 */

ULONG __regargs
Random(ULONG MaxValue)
{
	STATIC ULONG RandomSeed = 0xDEAD0123;

	RandomSeed = RandomSeed * custom . vhposr + 0xE153766F;

	return(RandomSeed % MaxValue);
}

void	my_printf(rp,x,y,texte)
struct RastPort	*rp;
int	x,y;
char	*texte;
{
	SetAPen(rp,1);
	Move(rp,x,y);
	Text(rp,texte,strlen(texte));
}
void	new_param(float	*a,float	*b,float	*c,float	*mag)
{
	*a = (float)(Random(700) + 5) / 100.0;
	*b = (float)(Random(190) + 5) / 100.0;
	*c = (float)(Random( 90) + 5) / 100.0;

	*mag = (float)(1 << (Random(6) + 2)) * deg45;
}

	/* RealPlane():
	 *
	 *	Draw real plane fractals.
	 */

VOID
RealPlane()
{
	STATIC BYTE Wheel = 0;
	UBYTE	flg_end;
	UWORD	Count = 0;
	UWORD	Colours[32],OffsetX = BlankScreen -> Width >> 1,OffsetY = BlankScreen -> Height >> 1;
	float	x,y,yy,a,b,c,sx,sy,mag;
	int	count_bis;
	struct RastPort	*RPort;
	WORD		 i,NewBit = 0;
	BYTE		 Colour = 1,Plus = 1;

	x=0;
	y=0;
	count_bis=100;

	/* Provide starting numbers for the fractal
	 * parameters.
	 */
	new_param(&a,&b,&c,&mag);

	Colours[0] = 0;
	flg_end=tst_end();
	/* Are we running in monochrome mode? */

	if(my_gadg[0].value == COLOUR_MONO)
	{
		UWORD		Modulo	= BlankScreen -> RastPort . BitMap -> BytesPerRow;
		PLANEPTR	Plane	= BlankScreen -> RastPort . BitMap -> Planes[0];

			/* Set up the screen colour table. */

		Colours[1] = Table[Wheel];
		LoadRGB4(&BlankScreen -> ViewPort,Colours,2);

			/* Go into fractal generation loop. */

		while(flg_end==FALSE){

				/* The original formula looks like
				 * this:
				 *                                    ½
				 *    x = y - SIGN(x) × ABS(b × x - c)
				 *    y = a - x
				 *
				 * I have split the calculation into
				 * several steps to save time and
				 * variables.
				 */

			yy = a - x;

			if(x < 0)
				x = y + sqrt(fabs(b * x - c));
			else
				x = y - sqrt(fabs(b * x - c));

			y = yy;

				/* The resulting image appears to have
				 * been rotated by 45°, so we'll
				 * rotate the pixel coordinates by -45°
				 *
				 *    x =  x × cos(alpha) + y × sin(alpha)
				 *    y = -x × sin(alpha) + y × cos(alpha)
				 *
				 * We also magnify the image (i.e. the
				 * distribution of pixels) in the following
				 * lines.
				 */

			sx = 2*mag * ( x + y);
			sy = mag * (-x + y);

				/* If the pixel happens to reside within
				 * the boundaries of the screen, draw it.
				 */

			MonoPlot(Plane,(WORD)(sx) + OffsetX,(WORD)(sy) + OffsetY,Modulo,BlankScreen -> Width,BlankScreen -> Height);
			count_bis--;
			if(count_bis==0){

				count_bis=100;
				flg_end=tst_end();
				Count++;
				if(Count%10){

					Colours[1] = Table[Wheel];
					LoadRGB4(&BlankScreen -> ViewPort,Colours,2);
					Wheel = (Wheel + 1) % 75;
				}
				/* Change the pattern? */
				if(Count%duree==0){
					flg_end=TRUE;
				}
			}
		}
	}else{
		RPort = &BlankScreen -> RastPort;

		for(i = 1 ; i < 32 ; i++)
			Colours[i] = Table[(Wheel + i) % 75];

		if(my_gadg[0].value == COLOUR_CYCLE)
			LoadRGB4(&BlankScreen -> ViewPort,Colours,32);
		else
			LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);

		Wheel = (Wheel + 1) % 75;


		while(flg_end==FALSE){
			flg_end=tst_end();
			yy = a - x;

			if(x < 0){
				x = y + sqrt(fabs(b * x - c));
			}else{
				x = y - sqrt(fabs(b * x - c));
			}
			y = yy;

			sx = mag * 2.0 * ( x + y);
			sy = mag * 1.0 * (-x + y);
			MultiPlot(BlankScreen,(WORD)(sx) + OffsetX,(WORD)(sy) + OffsetY,Colour | NewBit);

			count_bis--;
			if(count_bis==0){
				count_bis=100;
				/* Oh well, it's not that easy to
				 * produce decent colour values for
				 * the pixels to be rendered.
				 *
				 * The following statement will change
				 * the current drawing pen after exactly
				 * 1200 pixels have been rendered and will
				 * pick a new colour between 1 and 31.
				 */
			   Count++;

			   if(Count%12==0)
			   {
				if(NewBit)
				{
					NewBit = 0;

					Colour += Plus;

					if(!Colour)
					{
						Plus	= 1;
						Colour	= 2;
					}
					else
					{
						if(Colour == 32)
						{
							Plus	= -1;
							Colour	= 30;
						}
					}
				}
				else
					NewBit = 0x20;
			    }
  			    if(Count%6==0){
				for(i = 1 ; i < 32 ; i++)
					Colours[i] = Table[(Wheel + i) % 75];

				if(my_gadg[0].value == COLOUR_CYCLE)
					LoadRGB4(&BlankScreen -> ViewPort,Colours,32);

				Wheel = (Wheel + 1) % 75;
			   }
			   if(Count%duree==0){
				flg_end=TRUE;
			   }
			}
		}
	}
}

	/* RecurseMono(float x,float y,WORD Level):
	 *
	 *	Cosmic flame calculation routine (monochrome).
	 */

BYTE
RecurseMono(float x,float y,WORD Level)
{

	if(count==0){
		return(FALSE);
	}
	if(tst_end()!=FALSE){
		StopDrawing	= TRUE;
	}
	if(StopDrawing)
	{
		FlameLevel	= 0;
		StopDrawing	= FALSE;

		return(FALSE);
	}

		/* ^E tells the blanker to rotate the
		 * colours.
		 */
	count--;
	count_col--;
	if(count_col==0)
	{
		count_col=200;

		FlameColourTable[1] = Table[FlameWheel];

		LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,2);

		FlameWheel = (FlameWheel + 1) % 75;
	}
	if(Level >= MAXFLAMELEVEL)
	{
		if((FlamePoints++) > MAXTOTALPOINTS)
			return(FALSE);
		else
			MonoPlot(FlamePlane,(WORD)((BlankScreen -> Width >> 1) * (x + 1.0)),(WORD)((BlankScreen -> Height >> 1) * (y + 1.0)),FlameModulo,BlankScreen -> Width,BlankScreen -> Height);
	}
	else
	{
		float	nx,ny;
		WORD	i;

		for(i = 0 ; i < 2 ; i++)
		{
			nx = Flame[0][0][i] * x + Flame[0][1][i] * y + Flame[0][2][i];
			ny = Flame[1][0][i] * x + Flame[1][1][i] * y + Flame[1][2][i];

			if(i < FlameAlternateForm)
			{
				nx = sin(nx);
				ny = sin(ny);
			}

			if(!StopDrawing)
			{
				if(!RecurseMono(nx,ny,Level + 1))
					return(FALSE);
			}
			else
				return(FALSE);
		}
	}

	return(TRUE);
}

	/* RecurseColour(float x,float y,WORD Level):
	 *
	 *	Cosmic flame calculation routine (colour).
	 */

BYTE
RecurseColour(float x,float y,WORD Level)
{
	if(count==0){
		return(FALSE);
	}
	if(tst_end()!=FALSE){
		StopDrawing	= TRUE;
	}
		/* Are we to shut down? */

	if(StopDrawing)
	{
		FlameLevel	= 0;
		StopDrawing	= FALSE;

		return(FALSE);
	}

		/* ^E tells the blanker to rotate the
		 * colours.
		 */
	count--;
	count_col--;
	if(count_col==0)
	{
		count_col=200;
		if(my_gadg[0].value == COLOUR_CYCLE)
		{
			WORD i;

			for(i = 1 ; i < 32 ; i++)
				FlameColourTable[i] = Table[(FlameWheel + i) % 75];

			LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,32);

			FlameWheel = (FlameWheel + 1) % 75;
		}
	}
	if(Level >= MAXFLAMELEVEL)
	{
		if((FlamePoints++) > MAXTOTALPOINTS)
			return(FALSE);
		else
			MultiPlot(BlankScreen,(WORD)((BlankScreen -> Width >> 1) * (x + 1.0)),(WORD)((BlankScreen -> Height >> 1) * (y + 1.0)),FlameColour + 1);
	}
	else
	{
		float	nx,ny;
		WORD	i;

		for(i = 0 ; i < 2 ; i++)
		{
			nx = Flame[0][0][i] * x + Flame[0][1][i] * y + Flame[0][2][i];
			ny = Flame[1][0][i] * x + Flame[1][1][i] * y + Flame[1][2][i];

			if(i < FlameAlternateForm)
			{
				nx = sin(nx);
				ny = sin(ny);
			}

			if(!StopDrawing)
			{
				if(!RecurseColour(nx,ny,Level + 1))
					return(FALSE);
			}
			else
				return(FALSE);
		}
	}

	return(TRUE);
}

	/* CosmicFlame():
	 *
	 *	The cosmic flame screen blanker.
	 *
	 *	xlock.c - X11 client to lock a display and show a screen saver.
	 *
	 *	Copyright (c) 1988-91 by Patrick J. Naughton.
	 *
	 *	Permission to use, copy, modify, and distribute this software and its
	 *	documentation for any purpose and without fee is hereby granted,
	 *	provided that the above copyright notice appear in all copies and that
	 *	both that copyright notice and this permission notice appear in
	 *	supporting documentation.
	 */

VOID
CosmicFlame()
{
	WORD i,j,k;

	count_col=20;
	count=duree*200;

		/* Monochrome mode? */

	if(my_gadg[0].value == COLOUR_MONO)
	{
		BYTE Alternate = FALSE;

			/* Initialize defaults. */

		FlameModulo	= BlankScreen -> RastPort . BitMap -> BytesPerRow;
		FlamePlane	= BlankScreen -> RastPort . BitMap -> Planes[0];

		FlameWheel	= 0;

			/* Set up the screen colour table. */

		FlameColourTable[0] = 0;
		FlameColourTable[1] = Table[FlameWheel];

		LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,2);

		FlameLevel	= 0;

			/* Go into fractal generation loop. */
		while((tst_end()==FALSE)&&(count!=0)){
			if(!((FlameLevel++) % 20))
			{
				LoadRGB4(&BlankScreen -> ViewPort,Black,2);

				SetRast(&BlankScreen -> RastPort,0);

				LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,2);

				Alternate = !Alternate;
			}

			if(Alternate)
				FlameAlternateForm = 0;
			else
				FlameAlternateForm = Random(2) + 2;

			for(k = 0 ; k < 2 ; k++)
			{
				for(i = 0 ; i < 2 ; i++)
				{
					for(j = 0; j < 3; j++)
						Flame[i][j][k] = ((float)Random(1024)) / 512.0 - 1.0;
				}
			}

			FlamePoints = 0;

			RecurseMono(0.0,0.0,0);
		}
	}
	else
	{
		BYTE Alternate = FALSE,Plus;

		FlameWheel = Random(75);

		FlameColourTable[0] = 0x000;

		for(i = 1 ; i < 32 ; i++)
			FlameColourTable[i] = Table[(FlameWheel + i) % 75];

		if(my_gadg[0].value == COLOUR_CYCLE)
			LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,32);
		else
			LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);

		FlameWheel	= (FlameWheel + 1) % 75;

		FlameColour	= Random(63);
		Plus		= 1;

		FlameLevel	= 0;

			/* Go into fractal generation loop. */

		while((tst_end()==FALSE)&&(count!=0)){
			if(!((FlameLevel++) % 20))
			{
				LoadRGB4(&BlankScreen -> ViewPort,Black,32);

				SetRast(&BlankScreen -> RastPort,0);

				if(my_gadg[0].value == COLOUR_CYCLE)
					LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,32);
				else
					LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);

				Alternate = !Alternate;
			}
			else
			{
				if(FlameColour == 62)
					Plus = -1;

				if(FlameColour == 0)
					Plus = 1;

				FlameColour += Plus;
			}

			if(Alternate)
				FlameAlternateForm = 0;
			else
				FlameAlternateForm = Random(2) + 2;

			for(k = 0 ; k < 2 ; k++)
			{
				for(i = 0 ; i < 2 ; i++)
				{
					for(j = 0; j < 3; j++)
						Flame[i][j][k] = ((float)Random(1024)) / 512.0 - 1.0;
				}
			}

			FlamePoints = 0;

			RecurseColour(0.0,0.0,0);
		}
	}
}

/* Put here your own code */
/* But don't remember     */

void	__saveds	dark()
{
	int	num;

	duree=my_gadg[1].value*20;

	BlankScreen=(struct Screen *)OpenScreen(&NewBlankerScreen);
	SetRast (&BlankScreen->RastPort,0);
	if(BlankScreen!=0){
		FreeSprite (0);
		GfxBase->SpriteReserved|=1;
		do{
			/* Mode aleatoire ? */
			if(my_gadg[2].value==2){
				num=rand()%2;
			}else{
				num=my_gadg[2].value;
			}
			SetRast(&BlankScreen->RastPort,0);
			StopDrawing=FALSE;
			switch(num){
				case 0:
					RealPlane();
					break;
				case 1:
					CosmicFlame();
					break;
				default:
					break;
			}
		}while(tst_end()==FALSE);
		CloseScreen(BlankScreen);
	}

}
void	proc_init()
{

	WORD	i,c = 0,r = 15,g = 0,b = 0;

		/* Create a table of rainbow colours. */

	for(i = 0 ; i < 16 ; i++)
		Table[c++] = (r << 8) | ((g++) << 4) | b;

	g = 15;
	r--;

	for(i = 0 ; i < 15 ; i++)
		Table[c++] = ((r--) << 8) | (g << 4) | b;

	r = 0;
	g--;
	b++;

	for(i = 0 ; i < 15 ; i++)
		Table[c++] = (r << 8) | ((g--) << 4) | (b++);

	g = 0;
	b = 15;
	r++;

	for(i = 0 ; i < 15 ; i++)
		Table[c++] = ((r++) << 8) | (g << 4) | b;

	r = 15;
	b--;

	for(i = 0 ; i < 14 ; i++)
		Table[c++] = (r << 8) | (g << 4) | (b--);

}

void	proc_save()
{
}
void	proc_end()
{
}
