;/*
sc RESOPT IGNORE=73 DATA=NEAR NMINC UCHAR CONSTLIB STREQ STRMERGE NOSTKCHK NOSTDIO OPTIMIZE OPTTIME Mandelbrot.c
slink from lib:c.o mandelbrot.o to //Clients/Mandelbrot LIB /lib/client.lib LIB:scm.lib LIB:sc.lib LIB:amiga.lib SC SD NOICONS STRIPDEBUG
delete mandelbrot.o
quit

 Mandelbrot 1.5  (Client for BServer)

 Copyright © 1994-1995 Luca Viola & Stefano Reksten of 3AM - The Three Amigos!!!
 All rights reserved.

 Reworked and compiled for MathIeee as Massimo Capanni asked.
*/

#include <exec/types.h>
#include <exec/execbase.h>
#include <intuition/intuition.h>

#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/mathieeesingbas.h>
#include <math.h>

#include "/include/client.h"

char *ver = "$VER: Mandelbrot 1.5 "__AMIGADATE__;

#define	RISX		240
#define	RISY		240
#define	PLANES		4
#define	MAXITER		32
#define	COLORS		(1 << PLANES)

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *MathIeeeDoubBasBase;

struct DisplayIDInformation *dinfo;

struct Screen *scr;
struct RastPort *rport;
struct ViewPort vport;
ULONG *table;

int MaxTopAdd, MaxLeftAdd, RisX, RisY, MaxIters;

#define Mul IEEESPMul
#define Add IEEESPAdd
#define Div IEEESPDiv
#define Sub IEEESPSub
#define Cmp IEEESPCmp
#define Flt IEEESPFlt

void DrawMandel( void )
{
float quadsize;
float temp, xr, yr, sqxr, sqyr, d, vx, vy,
       x1real, y1imm, x2real, y2imm, gapx, gapy;
long loop, x, y, risx, risy;
BOOL stillBlanking = TRUE;
ULONG secs, mics;
UWORD TopAdd, LeftAdd;

risx=RisX;
risy=RisY;

while( stillBlanking )
	{
	CurrentTime( &secs, &mics );
	TopAdd = (secs + (mics>>4)) % MaxTopAdd;
	LeftAdd = mics % MaxLeftAdd;

	quadsize = Mul( 3.4F, (float)drand48() );
	x1real = Mul( (float)-2.2, (float)drand48() );
	x2real = Add( x1real, quadsize );
	y1imm = Add( (float)-1.7, (float)drand48() );
	y2imm = Add( y1imm, quadsize );

	gapx = Div( Sub( x2real, x1real ), Flt( risx ) );
	gapy = Div( Sub( y1imm, y2imm ), Flt( risy ) );
	vy = y2imm;

	for ( y = 0; y < RisY; y++ )
		{
		vy = Add( vy, gapy );
		vx = x1real;
		for( x = 0; x < RisX && stillBlanking; x++ )
			{
			vx = Add( vx, gapx );
			xr = 0; yr = 0;
			loop = 0;

			do
				{
				loop++;
                sqxr = Mul( xr, xr );
				sqyr = Mul( yr, yr );
				temp = Add( Sub( sqxr, sqyr ), vx );
				yr = Add( Mul( Add( xr, xr ), yr ) , vy );
				xr = temp;
				d = Add( sqxr, sqyr );
				if ( Cmp( d, 4.0F ) == 1 )
					{
					SetAPen( &(scr->RastPort), loop%COLORS+1 );
					WritePixel( &(scr->RastPort), x + LeftAdd, y + TopAdd );
				  	loop=MaxIters;
					}
				stillBlanking = STILL_BLANKING;
				}
			while(loop!=MaxIters && stillBlanking );

			if ( stillBlanking && ( Cmp( d, 4.0F ) == -1 ) )
				{
				SetAPen( &(scr->RastPort), 0 );
				WritePixel( &(scr->RastPort), x + LeftAdd, y + TopAdd );
				}
			}
		}
	}
}


void Mandel( void )
{
UBYTE n, brightness = GETBRIGHTNESS(dinfo);
ULONG displayID = DISPLAYID(dinfo);
UWORD rwidth, rheight;
struct Rectangle *rect = GETTXTOSCANRECT(dinfo);

rwidth = RECTANGLEWIDTH(rect);
rheight = RECTANGLEHEIGHT(rect);

if ( rwidth < RisX )
	{
	RisX = rwidth; MaxLeftAdd = 0;
	}
else
	MaxLeftAdd = rwidth - RisX;

if ( rheight < RisY )
	{
	RisY = rheight; MaxTopAdd = 0;
	}
else
	MaxTopAdd = rheight - RisY;


if ( !CheckAA() )
	{
	if ( displayID & SUPERHIRES )
		{
		displayID &= ~SUPERHIRES;
		displayID |= HIRES;
		rwidth >>= 1;
		}
	}

if ( scr = (struct Screen *)OpenScreenTags( NULL,
		SA_DisplayID, displayID,
		SA_Width, rwidth,
		SA_Height, rheight,
		SA_Depth, PLANES,
		SA_Quiet, TRUE,
		SA_Overscan, OSCAN_TEXT,
		TAG_DONE ) )
	{
	rport = &scr->RastPort;
	vport = scr->ViewPort;
	SetRGB4( &vport, 0, 0, 0, 0 );
	for ( n = 1; n < 1<<PLANES; n++ )
		SetRGB4( &vport, n, n * brightness/100, n * brightness/100, (16-n) * brightness / 100 );

	SpritesOff();

	DrawMandel();

	SpritesOn();
	CloseScreen( scr );
	}
else
	SendClientMsg( ACTION_FAILED );
}


void __main( void )
{
ULONG secs, mics;

if ( IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library", 37L ) )
	{
	if ( GfxBase = (struct GfxBase *)OpenLibrary( "graphics.library", 37L ) )
		{
		if ( MathIeeeSingBasBase = OpenLibrary( "mathieeesingbas.library", 37L ) )
			{
			if ( dinfo = OpenCommunication() )
				{
				if ( !GetArgInt( dinfo->di_Args, "XRES", &RisX ) )
					RisX = RISX;
				if ( !GetArgInt( dinfo->di_Args, "YRES", &RisY ) )
					RisY = RISY;
				if ( !GetArgInt( dinfo->di_Args, "MAXITERS", &MaxIters ) )
					MaxIters = MAXITER;

				CurrentTime( &secs, &mics );
				srand48( secs );
				Mandel();
				CloseCommunication( dinfo );
				}
			CloseLibrary( MathIeeeSingBasBase );
			}
		CloseLibrary( (struct Library *)GfxBase );
		}
	CloseLibrary( (struct Library *)IntuitionBase );
	}
}
