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

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfx.h>
#include <graphics/gfxmacros.h>
#include <graphics/rastport.h>
#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>
#include <libraries/gadtools.h>
#include <hardware/custom.h>
#include <hardware/blit.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include "/includes/struct.h"
#include "/includes/tom_gadget.h"

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

extern	struct	IntuitionBase	*IntuitionBase;
extern	struct	GfxBase		*GfxBase;
extern	struct my_data	*p_info;
extern	struct	appel_proc	*p_data_proc;
struct	RastPort	*rp,*rps;
struct	RastPort	ras2;
struct	BitMap		bitmap;
struct	Screen	*s;
UWORD	width,height;
UWORD	bpr;

#define	WIDTH	320
#define	HEIGHT	320

#define	TRUE	1
#define	FALSE	0

int	max_depth=0;
int	flg_deux=FALSE;
int	flg_un=FALSE;

char	p_ver[]="$VER: Spot v1.1 (24/03/93)";

WORD	areabuffer[25];
struct	AreaInfo	myarea;
struct	TmpRas	tmpras;
char	*p_text_info=
"          Spot    v1.1\n"
"\n"
"This effect show you Spots on your screen\n"
"\n  Lightning the background...\n"
"\n"
"You can select the number of spots,her size\n"
"and speed.\n"
"If SuperDark can open a screen deeper than\n"
"size than the actual one, the shadow option\n"
"is active.\n"
"   by Thomas LANDSPURG \n";

int	bx,by;
int	flg_dblbuff;
	
#define	MAX_NB	10

#define	GID_TAILLE	0
#define	GID_SPEED	1
#define	GID_NOMBRE	2
#define	GID_DBLBUFF	3
#define	GID_SHADOW	4

struct tom_gadget my_gadg[]={
	{"Si_ze",	SLIDER,60,20,100,10,40,20,100,0,0},
	{"_Speed",	SLIDER,60,35,100,10,2,1,10,0,0},
	{"_Number",	SLIDER,60,50,100,10,1,1,5,0,0},
	{"_DoubleBuffer",CHECKBOX,370,20,10,10,FALSE,0,0,0,0},
	{"S_hadow",	SLIDER,255,50,100,10,50,0,90,0,0},
	{0,		END_LISTE,  0,  0,   0, 0, 0,0,0,0,0}
};

int	tx=20;
int	ty=20;
UWORD	flg_clear;
int	val;

long	s2depth;
struct ViewPort      *vp2;
struct	Screen	*s2;
int	num=0;

struct NewScreen newscreen = {
  0,0,0,0,0,0,0,NULL,CUSTOMSCREEN,NULL,(UBYTE *)" ",NULL,NULL
};

struct	RasInfo	ri;
struct	BitMap	b1,b2,*b;
struct ViewPort vp;
struct	View	v,*oldview;
struct RastPort rp1,rp2,*rp;

void	my_text(rp,x,y,p_c)
struct	RastPort	*rp;
int	x,y;
char	*p_c;
{
	if(rp!=0){
		Move(rp,x,y);
		Text(rp,p_c,strlen(p_c));
	}
}
/*************************************************************************/

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

	RandomSeed = RandomSeed * custom . vhposr + 0xE153766F;

	return(RandomSeed % MaxValue);
}

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

void	blit_func()
{

	UWORD	sx,sy,decal,mod;
	ULONG	mask;
	ULONG	offset,code_ret;
	static	WORD	num_plan=0;
	APTR	p_dest;
	UWORD	bltcon0;

  for(num_plan=0;(num_plan<s2depth)||((flg_un==TRUE)&&(num_plan==0));num_plan++){
	WaitBlit();
	code_ret=0;
	sx=(tx+16)&0xfff0;
	sy=ty;
	custom.bltapt=bitmap.Planes[0];	/* Masque */
	offset=(by*bpr+bx/8)&0xFFFE;
	decal=(bx)&0xF;		/* DEcalage sur 16 */
	decal=decal<<12;
	custom.bltadat=0;
	if(flg_un==TRUE){
		p_dest = b->Planes[max_depth-1]+offset;
		if(flg_clear){
			bltcon0=(DEST)|(decal)|(A_TO_D);
		}else{
			bltcon0=(DEST|SRCC|SRCA)|(decal)|(A_OR_C);
		}
	}else{
		custom.bltbpt=rps->BitMap->Planes[num_plan]+offset;
		p_dest = rp->BitMap->Planes[num_plan]+offset;
		if(flg_clear){
			bltcon0=(DEST)|(decal)|(A_TO_D);
		}else{
			bltcon0=(DEST|SRCC|SRCB|SRCA)|(decal)|(ABC|ABNC|NABC|NANBC);
		}
	}
	
	custom.bltcpt= p_dest;
	custom.bltdpt= p_dest;
	custom.bltcon0=bltcon0;
	mod=(bpr/2-sx/16)*2-2;
	custom.bltamod=(WIDTH/16-sx/16)*2-2;
	custom.bltbmod=mod;
	custom.bltcmod=mod;
	custom.bltdmod=mod;
	custom.bltcon1=0;
	decal=(~bx)&0xF;
	decal=decal<<12;
	mask=0xFFFF0000>>decal;
	custom.bltafwm=mask;
	custom.bltalwm=mask>>0xF;
	custom.bltafwm=0xffff;
	custom.bltalwm=0;

	custom.bltsize=(sy<<HSIZEBITS)|(sx/16+1);
   }
}

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

/* Effectue un fading */

UWORD	fade_one_digit(UWORD	n,USHORT	val)
{
	return((n*val/100)&0x00f);
}

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

void	spot()
{
	WORD	x[MAX_NB],y[MAX_NB];
	WORD	sx[MAX_NB],sy[MAX_NB];
	WORD	oldx[MAX_NB],oldy[MAX_NB];
	
	UWORD	mx,my,i,nb;


	if(tx>width*2){
		tx=width/2;
	}
	if(ty>height*2){
		ty=height/2;
	}
	mx=my_gadg[GID_SPEED].value;
	if(mx==0)mx=4;
	my=my_gadg[GID_SPEED].value*height/width;
	if(my==0)my=4;

	nb=((my_gadg[GID_NOMBRE].value-1)%MAX_NB)+1;
	if(nb>MAX_NB)nb=MAX_NB;
	if(nb<1)nb=1;

	for(i=0;i<nb;i++){
		oldx[i]=0;
		oldy[i]=0;
		x[i]=Rand(width-2*tx);
		y[i]=Rand(height-2*ty);

		sx[i]=Rand(mx*2)-mx;
		if(sx[i]==0)sx[i]++;
		sy[i]=Rand(my*2)-my;
		if(sy[i]==0)sy[i]++;
	}
	while(tst_end()==FALSE){

		if(flg_un==TRUE){
			ri.BitMap=b;
			MakeVPort(&v,&vp);
			MrgCop(&v);
			LoadView(&v);
			if(num==2){
				b=&b1;
				num=0;
			}else{
				b=&b2;
			}
			num++;
		}

		WaitTOF();
		flg_clear=TRUE;
		OwnBlitter();
		for(i=0;i<nb;i++){
			if(flg_dblbuff){
				bx=oldx[i];
				by=oldy[i];
				oldx[i]=x[i];
				oldy[i]=y[i];
			}else{
				bx=x[i];
				by=y[i];
			}
			blit_func();
		}
		flg_clear=FALSE;
		for(i=0;i<nb;i++){

			x[i]+=sx[i];
			if(x[i]<=0){
				x[i]=0;
				sx[i]=Rand(mx)+1;
			}else if(x[i]>=width-tx-16){
				x[i]=width-tx-16;
				sx[i]=-Rand(mx)-1;
			}
			y[i]+=sy[i];
			if(y[i]<=0){
				y[i]=0;
				sy[i]=Rand(my)+1;
			}else if(y[i]>=height-ty-1){
				y[i]=height-ty-1;
				sy[i]=-Rand(my)-1;
			}

			bx=x[i];
			by=y[i];
			blit_func();
		}
		DisownBlitter();
	}

}

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

UWORD	plane_avail(ULONG d_id)
{
 UWORD	depth;
 struct ModeNode *ModeNode;
 ModeNode=(struct ModeNode *)p_data_proc->ml->lh_Head;

 depth=0;
 while (ModeNode->mn_Node.ln_Succ){
	if(((ModeNode->DisplayID)&0x8FFF)==(d_id&0x8FFF)){
		depth=ModeNode->MaxDepth;
	}
	ModeNode=(struct ModeNode *)ModeNode->mn_Node.ln_Succ;
 }
 return depth;
}
/*************************************************************************/

void	dark()
{
	int	i,col;
	LONG	mode_id;

	s = NULL;
	s2 = IntuitionBase->FirstScreen;

	vp2 = &s2->ViewPort;
	s2depth = s2->BitMap.Depth;
	flg_un=FALSE;
	newscreen.LeftEdge = s2->LeftEdge;
	newscreen.TopEdge = s2->TopEdge;
	newscreen.Width = s2->Width;
	newscreen.Height = s2->Height;
	newscreen.DetailPen = s2->DetailPen;
	newscreen.BlockPen = s2->BlockPen;
	newscreen.Depth = s2depth;
	newscreen.ViewModes = vp2->Modes;

	width=newscreen.Width;
	height=newscreen.Height;
	rps=&s2->RastPort;

	if(GfxBase->LibNode.lib_Version>=36){
		mode_id=GetVPModeID(vp2);
	}else{
		mode_id=vp2->Modes;
	}

	flg_dblbuff=FALSE;
	max_depth=plane_avail(mode_id);
	if(max_depth <= s2depth){
		if ((s = (struct Screen *)OpenScreen(&newscreen)) == NULL){
			return;
		}
		rp = &s->RastPort;
		bpr=rp->BitMap->BytesPerRow;
		SetRast(rp,0);
  	}else{
		num=0;
		if(my_gadg[GID_DBLBUFF].value==TRUE){
			flg_dblbuff=TRUE;
		}
		val=my_gadg[GID_SHADOW].value;
		if((val<0)||(val>90)){
			val=50;
		}

/*BUG: sous 2.0, vp.Modes ne se fait pas comme ca! */
		oldview=((struct GfxBase *)GfxBase)->ActiView;
        	max_depth=s2depth+1;
		InitView(&v);
		v.ViewPort=&vp;
		InitVPort(&vp);
		vp.Modes=vp2->Modes;

		vp.DWidth=width;
		vp.DHeight=height;
		vp.RasInfo=&ri;
		vp.ColorMap=(struct	ColorMap *)GetColorMap(1<<max_depth);
		InitBitMap(&b1,max_depth,width,height);
		bpr=b1.BytesPerRow;
		for(i=0;i<s2depth;i++){
			b1.Planes[i]=s2->BitMap.Planes[i];
		}
		b1.Planes[max_depth-1]=(PLANEPTR)AllocRaster(width,height);
		b2=b1;
		if(flg_dblbuff){
			b2.Planes[max_depth-1]=(PLANEPTR)AllocRaster(width,height);
			if(b2.Planes[max_depth-1]==0){
				flg_dblbuff=FALSE;
			}
		}
		BltClear(b1.Planes[max_depth-1],height*bpr,0);
		BltClear(b2.Planes[max_depth-1],height*bpr,0);
		InitRastPort(&rp1);
		b=&b1;
		rp1.BitMap=&b1;
		ri.BitMap=&b1;
		ri.RxOffset=0;
		ri.RyOffset=0;
		ri.Next=NULL;

		rp =&rp1;
		flg_un=TRUE;
  	}
	FreeSprite (0);
	GfxBase->SpriteReserved|=1;

	for(i=0;i<(1<<s2depth);i++){
	 UWORD	r,g,b;
	 col=GetRGB4(s2->ViewPort.ColorMap,i);
	 r=(col&0xf00)>>8;
	 g=(col&0x0f0)>>4;
	 b=(col&0x00f);
	 if(flg_un==TRUE){
		SetRGB4(	&vp,i,
				fade_one_digit(r,val),
				fade_one_digit(g,val),
				fade_one_digit(b,val));
		SetRGB4(&vp,i+(1<<s2depth),r,g,b);
	 }else{
		SetRGB4(&(s->ViewPort),i,r,g,b);
	 }
	}

	InitBitMap(&bitmap,1,WIDTH,HEIGHT);
	bitmap.Planes[0]=AllocRaster(WIDTH,HEIGHT);
	if(bitmap.Planes[0]){
		InitRastPort(&ras2);
		ras2.BitMap=&bitmap;

		InitArea(&myarea,areabuffer,10);
		ras2.AreaInfo=&myarea;
		ras2.TmpRas=(struct TmpRas *)InitTmpRas(&tmpras,AllocRaster(WIDTH,HEIGHT),RASSIZE(WIDTH,HEIGHT));
		if(ras2.TmpRas){
			tx=2*my_gadg[GID_TAILLE].value;
			if((tx==0)||(tx>width/2))tx=20;
		
			ty=tx*height/width;
			if((ty==0)||(ty>height/2))ty=20;
			
			SetRast(&ras2,0);
			SetAPen(&ras2,1L);
			{
				LONG	tx2,ty2;
				tx2=tx>>1;
				ty2=ty>>1;
				AreaMove(&ras2,tx2,ty2);
				AreaEllipse(&ras2,tx2,ty2,tx2-1,ty2-1);
				AreaEnd(&ras2);
			}
			WaitBlit();
			FreeRaster(tmpras.RasPtr,WIDTH,HEIGHT);
		}
	}
	spot();

	wait_end();
	if(bitmap.Planes[0])FreeRaster(bitmap.Planes[0],WIDTH,HEIGHT);
	if(flg_un==TRUE){
		FreeRaster(b1.Planes[max_depth-1],width,height);
		if(flg_dblbuff){
			FreeRaster(b2.Planes[max_depth-1],width,height);
		}
		LoadView(oldview);
		FreeColorMap(vp.ColorMap);
		FreeVPortCopLists(&vp);
		FreeCprList(v.LOFCprList);
		DCloseScreen(NULL);
	}else{
		DCloseScreen(s);
	}
}

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

