#include <exec/types.h>
#include <exec/memory.h>

#include <intuition/intuition.h>

#include <dos/dos.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/alib_protos.h>

#include "Star.h"
#include "//defs.h"
#include "/main.h"

#define	DE	200
#define	de	1000

#define WRITEPIXEL( r, x, y ) { if(( x >= 0 )&&( x < Wid )&&( y >= 0 )&&( y < Hei )) WritePixel( r, x, y ); }

struct ModulePrefs
{
	LONG Mode;
	LONG Stars;
	LONG Speed;
};

struct pt_3d
{
	LONG x;
	LONG y;
	LONG z;
	LONG speed;
};

struct pt_2d
{
	LONG x;
	LONG y;
};

extern struct ModulePrefs nP;

struct pt_3d *tab_pt_3d;
struct pt_2d *tab_old;

#define BLANKMOUSE
#include "/utility.c"

void new_star( struct pt_3d *p, LONG speed )
{
	p->x = 1500 - ( LONG )RangeRand( 3000 );
	p->y = 1000 - ( LONG )RangeRand( 2000 );
	p->z = 1000 + ( LONG )RangeRand( 2000 );
	p->speed = ( LONG )RangeRand( 10 ) + speed;
}

LONG Blank( VOID *Prefs )
{
	struct ModulePrefs *mP;
	struct RastPort *Rast;
	struct Screen *Scr;
	struct pt_3d *p;
	struct pt_2d *p2;
	LONG ToFrontCount = 0, Wid, Hei, i, x, y, Stars, Speed, RetVal = OK;
	
	if( StarWnd )
		mP = &nP;
	else
		mP = ( struct ModulePrefs * )Prefs;
	
	Stars = mP->Stars;
	Speed = mP->Speed;
	
	tab_pt_3d = AllocVec( Stars * sizeof( struct pt_3d ), MEMF_CLEAR );
	tab_old = AllocVec( Stars * sizeof( struct pt_2d ), MEMF_CLEAR );
	Scr = OpenScreenTags( 0L, SA_Depth, 2, SA_Overscan, OSCAN_STANDARD,
						 SA_DisplayID, mP->Mode, SA_Quiet, TRUE, SA_Behind, TRUE, TAG_DONE );
	
	if( tab_pt_3d && tab_old && Scr )
	{
		Wid = Scr->Width;
		Hei = Scr->Height;
		
		Rast = &( Scr->RastPort );
		SetRast( Rast, 0 );
		for( i = 0; i < 4; i++ )
			SetRGB4(&( Scr->ViewPort ), i, 4 * i, 4 * i, 4 * i );
		
		for( i = 0; i < Stars; i++ )
		{
			new_star( &tab_pt_3d[i], Speed );
			tab_old[i].x = 0;
			tab_old[i].y = 0;
		}
		
		BlankMousePointer( Scr );
		ScreenToFront( Scr );
		
		while( RetVal == OK )
		{
			WaitTOF();

			if(!( ++ToFrontCount % 60 ))
				ScreenToFront( Scr );
			
			p2 = tab_old;
			p = tab_pt_3d;
			for( i = 0; i < Stars; i++ )
			{
				x = p2->x;
				y = p2->y;
				
				SetAPen( Rast, 0 );
				if( p->z > 1000 )
				{
					WRITEPIXEL( Rast, x, y );
				}
				else
				{
					if( p->z > 200 )
					{
						WRITEPIXEL( Rast, x, y );
						WRITEPIXEL( Rast, x+1, y );
					}
					else
					{
						WRITEPIXEL( Rast, x, y );
						WRITEPIXEL( Rast, x+1, y );
						WRITEPIXEL( Rast, x, y+1 );
						WRITEPIXEL( Rast, x+1, y+1 );
					}
				}
				p->z -= p->speed;
				if( p->z <= -de )
					new_star( p, Speed );
				
				x = Wid/2 + ( DE * p->x ) / ( p->z + de );
				y = Hei/2 + ( DE * p->y ) / ( p->z + de );
				
				if(( x < 0 )||( x >= Wid )||( y < 0 )||( y >= Hei ))
				{
					new_star( p, Speed );
					p2->x = 0;
					p2->y = 0;
				}
				else
				{
					p2->x = x;
					p2->y = y;
					if( p->z > 2000 )
					{
						SetAPen( Rast, 1 );
						WRITEPIXEL( Rast, x, y );
					}
					else
					{
						if( p->z > 1500 )
						{
							SetAPen( Rast, 2 );
							WRITEPIXEL( Rast, x, y );
						}
						else
						{
							if( p->z > 1000 )
							{
								SetAPen( Rast, 3 );
								WRITEPIXEL( Rast, x, y );
							}
							else
							{
								if( p->z > 200 )
								{
									SetAPen( Rast, 3 );
									WRITEPIXEL( Rast, x, y );
									WRITEPIXEL( Rast, x+1, y );
								}
								else
								{
									SetAPen( Rast, 3 );
									WRITEPIXEL( Rast, x, y );
									WRITEPIXEL( Rast, x+1, y );
									WRITEPIXEL( Rast, x, y+1 );
									WRITEPIXEL( Rast, x+1, y+1 );
								}
							}
						}
					}
				}
				p2++;
				p++;
			}
			if(!( ToFrontCount % 5 ))
				RetVal = ContinueBlanking();
		}
		UnblankMousePointer();
	}
	else
		RetVal = FAILED;

	if( Scr )
		CloseScreen( Scr );
	if( tab_pt_3d )
		FreeVec( tab_pt_3d );
	if( tab_old )
		FreeVec( tab_old );

	return RetVal;
}
