 /* Fichier effect.dark.c				*/
/* Module appele par le programme principal	*/
/* pour effectuer un effet defini..appele par	*/
/* loadseg					*/

#include <time.h>
#include <math.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/rastport.h>
#include <graphics/displayinfo.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include "/includes/struct.h"
#include "/includes/tom_gadget.h"

char	p_ver[]="$VER: Effects v1.1 (28/02/93)";

char	*p_text_info="   effects V1.1\n\n   by Thomas landspurg\n\nThere is 3 effects:\n- One effect based on the interferences\n- Another one based on a old article from\n  the Scientific America (effect Dragon)\n  Basicly, there is some things to see with\n  chaos theory!\n- The last one also based on this article,but\n  give another effect. Fracblanck is also\n  based on this effect.\n\n Just choose the effect you want..\n";

struct	Screen		*s;
struct	RastPort	*rp;

#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);

WORD	(*call_func)(WORD,float);
UWORD	my_mod;

#define	WIDTH	320
#define	HEIGHT	256
UWORD	width,height,nb_col;
extern	struct	GfxBase	*GfxBase;
float	teta;

int	max_color=10;
UWORD  *ScreenColors;
#define	NB_COL	12
UWORD	CMap[NB_COL+1]={
    0x00f, 0x8f8, 0xff0, 0xe50, 0xf00,
    0x0ff, 0x356, 0xf06, 0x00f, 0x0ff,
    0xfff, 0xf00, 0xff0
};


int	duree;
struct NewScreen   Screen = {
    0, 0, WIDTH,HEIGHT, 5,0,1,NULL,CUSTOMSCREEN,NULL,NULL,NULL,NULL};

UBYTE         *TypeLabels[] = {
	"interferences",
	"dragon",
	"Frac Effect",
/*	"keftales",*/
	"Random",
	0l };


struct tom_gadget my_gadg[]={
	{"Ty_pe",	MX,	167,14,17,40,0, 0,0,0,(char *)TypeLabels},
	{"T_empo",	SLIDER,	100,60,100,10,100,50,100,0,0},
	{"_Resolution",	SCREEN,	100,80,100,12,0, 0,0,0,0},
	{0,		END_LISTE,  0,  0,   0, 0, 0,0,0,0,0}
};
static  unsigned        int     seed;


unsigned        int     my_rand()
{
        
        seed=25173*seed+138490;
        return(seed);
}

void	rotate()
{
	static	unsigned	int	compt=0;
	unsigned	int	n,i;

	n=compt;
	for(i=1;i<nb_col;i++){
		n=n%max_color;
		SetRGB4(	&s->ViewPort,i,
				(ScreenColors[n+1]&0xf00)>>8,
				(ScreenColors[n+1]&0x0f0)>>4,
				(ScreenColors[n+1]&0x00f));
		n++;
	}
	compt++;
}
/************************************************************ interferances */
void	interferences()
{
	int	i,x,y,factor,col;

	factor=my_rand()%20+1;
	for(y=-height/2+1;(y<=0)&&(tst_end()==FALSE);y++){
		for(x=-width/2+1;x<=0;x++){
			col=((x*x+y*y)/factor)%(my_mod)+1;
			MultiPlot(s,(WORD)(width/2-1+x),(WORD)(height/2-1+y),col);
			MultiPlot(s,(WORD)(width/2-1-x),(WORD)(height/2-1+y),col);
			MultiPlot(s,(WORD)(width/2-1+x),(WORD)(height/2-1-y),col);
			MultiPlot(s,(WORD)(width/2-1-x),(WORD)(height/2-1-y),col);

		}
		rotate();
	
	}
	for(i=0;(i<100)&&(tst_end()==FALSE);i++){
		Delay(2);
		WaitTOF();
		rotate();
	}
}

WORD	func1(UWORD	r,float	teta)
{
	return(((WORD)(teta*31/(2*PI)))%(my_mod)+1);
}
WORD	func2(UWORD	r,float	teta)
{
	return(((WORD)(20*teta+r/2))%(my_mod)+1);
}

/************************************************************ keftales */
void	keftales()
{
	int	i,x,y,factor,col;
	UWORD	r;
	factor=my_rand()%20+1;
	for(y=-height/2+1;(y<=0)&&(tst_end()==FALSE);y++){
		for(x=-width/2+1;x<=0;x++){
			r=sqrt((double)(x*x+y*y));
			if(y!=0){
				teta=atan((float)(y)/(float)(x));
			}else	teta=0;
			if(x<0)teta+=PI;
			teta+=PI;
/*
			if((x+y)!=0){
				col=(10*(WORD)sqrt(abs(x+y))*(WORD)(10*sin(((float)(x-y))/10)))%(my_mod)+1;
			}
*/
			col=call_func(r,teta);
			MultiPlot(s,(WORD)(width/2-1+x),(WORD)(height/2-1+y),col);
			col=call_func(r,PI-teta);
			MultiPlot(s,(WORD)(width/2-1-x),(WORD)(height/2-1+y),col);
			col=call_func(r,-teta);
			MultiPlot(s,(WORD)(width/2-1+x),(WORD)(height/2-1-y),col);
			col=call_func(r,teta+PI);
			MultiPlot(s,(WORD)(width/2-1-x),(WORD)(height/2-1-y),col);
		}
		rotate();
	
	}
	for(i=0;(i<100)&&(tst_end()==FALSE);i++){
		Delay(2);
		WaitTOF();
		rotate();
	}
}

/************************************************************ carre */
/* suite de point quit provoaue des effets sympas */

void	carre()
{
	int	i,flg_end;
	float	xx,yy,x,y;
	float	a,t;
	PLANEPTR	plane;
	UWORD	Modulo;

	plane=rp->BitMap->Planes[0];
	Modulo=rp->BitMap->BytesPerRow;
	t=(float)(my_rand()%100+10);
	a=PI-t/5000;
	SetRast(rp,0);
	SetRGB4(&s->ViewPort,1,0xf,0xf,0xf);
	SetAPen(rp,1);
	x=y=0;
	flg_end=FALSE;
	for(i=0;(i<duree)&&(flg_end==FALSE);i++){
		if(i%100==0){
			flg_end=tst_end();
		}
		xx=y-sin(x);
		yy=a-x;
		MonoPlot(	plane,
				width/2+(int)(2.0*x),
				height/2+(int)(2.0*y),
				Modulo,
				width,height
				);
/*
		WritePixel(rp,width/2+(int)(2.0*x),height/2+(int)(2.0*y));
*/
		x=xx;
		y=yy;
	}
	SetRast(rp,0);
}
#define	SGN(x)	((x)<0?-1:1)
#define	ABS(x)	((x)<0?(-(x)):(x))

float	one_param()
{
	return ((float)((my_rand()%1000)/10-50.0));
}

/************************************************************ effet_sun */

void	effet_sun()
{
	float	x,y,xx,yy,a,b,c;
	int	i,xe,ye,flg_end;
	UWORD	duree2;

	flg_end=FALSE;
	SetRast(rp,0);
	x=0;y=0;

	a=(float)one_param();
	do{
		b=(float)one_param();
	}while(b==0.0);
	c=(float)one_param();
	duree2=duree*4;
	for(i=0;(i<duree2)&&(flg_end==FALSE);i++){
		if(i%100==0){
			flg_end=tst_end();
			if(i%1000==0){
				rotate();
			}
		}
		xx=y-SGN(x)*sqrt(ABS(b*x-c));
		yy=a-x;
		xe=width/2+(int)(1.0*x);
		ye=height/2+(int)(1.0*y);
		if((xe>=0)&&(xe<width)&&(ye>=0)&&(ye<height)){
			MultiPlot(s,(WORD)(xe),(WORD)(ye),(ReadPixel(rp,xe,ye)+1)%(my_mod)+1);
		}
		x=xx;
		y=yy;
	}
	SetRast(rp,0);
}


/***************************************************************************/

UWORD	fade_one_digit(USHORT	n,USHORT	j,UWORD mask)
{
	register	UWORD	s,d;
	s=CMap[n]&mask;
	d=CMap[n+1]&mask;
	return(((s+(d-s)*j*NB_COL/max_color))&mask);
}

/***************************************************************************/

void	dark()
{
  int	effet,i,n,j;
  struct	tom_gadget	*pg;

  /* With WB2.0 or higher, we use facilities of the intuition lib. */
  /* to open screen (overscan...)			           */
  pg=&my_gadg[2];
  if((GfxBase->LibNode.lib_Version>=37)&&(pg->d3!=0)){
	
	 s=OpenScreenTags(NULL,
			   SA_Width,(ULONG)pg->d1,
			   SA_Height,(ULONG)pg->d2,
                           SA_Depth,(ULONG)pg->d3,
			   SA_Overscan,(ULONG)pg->value,
                           SA_DisplayID,(ULONG)pg->p_data,
                           SA_Quiet,TRUE,TAG_DONE);
   }else{
   	 s = OpenScreen( &Screen );
   }
   if ( s != 0){
	FreeSprite (0);
	GfxBase->SpriteReserved|=1;
	rp = &(s->RastPort);
	width=s->Width;
	height=s->Height;
	nb_col=1<<rp->BitMap->Depth;


	/****************************************************************/
	/* We create a color map, with transitions, in the range of all */
	/* the availables colors					 */
	/****************************************************************/

	if(nb_col>NB_COL*4){
		max_color=nb_col;
	}else{
		max_color=nb_col*4;
	}
	ScreenColors=(UWORD *)AllocMem(sizeof(UWORD)*(max_color),MEMF_CLEAR);
	if(ScreenColors){
		/* We create a fading ColorMap, with transition....*/
		n=0;
		j=0;
		for(i=1;i<max_color;i++){

			ScreenColors[i]= fade_one_digit(n,j,0xF00)
					|fade_one_digit(n,j,0X0f0)
					|fade_one_digit(n,j,0X00F);

			j++;
			if(j>=(max_color/NB_COL)){
				j=0;
				n++;
		}
	  }
	  ScreenColors[0]=0;
	}
	LoadRGB4(&s->ViewPort,ScreenColors,nb_col);
	SetRast(rp,0);
	while(tst_end()==FALSE){
		if(my_gadg[0].value==3){
			effet=my_rand()%3;
		}else{
			effet=my_gadg[0].value;
		}
		duree=my_gadg[1].value*100;
		my_mod=nb_col-1;
		switch(effet){
			case 0:	
				interferences();
				break;
			case 1:	
				carre();
				break;
			case 2:	
				effet_sun();
				break;
			default:
			case 3:	
				call_func=&func2;
				keftales();
				break;
		}
	}
	if(ScreenColors)FreeMem(ScreenColors,sizeof(UWORD)*(max_color));
	DCloseScreen(s);
      }
}

void	proc_init()
{
        seed=VBeamPos();
}

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

