;/*
if not exists WorldData.o
	sc DATA=FAR WorldData.c
endif
sc RESOPT IGNORE=73 DATA=FAR NMINC UCHAR CONSTLIB STREQ STRMERGE NOSTKCHK NOSTDIO OPTIMIZE OPTSIZE World.c
slink from LIB:c.o WorldData.o World.o to ///Clients/World LIB LIB:sc.lib LIB:amiga.lib //lib/client.lib SC NOICONS STRIPDEBUG
quit

 World 1.2  (Client for BServer)

 Copyright © 1995 by Stefano Reksten of 3AM - The Three Amigos!!!
 All rights reserved.
*/

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

#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#include "//include/client.h"
#include "//include/bitmap/bitmap.h"
#include "//include/bitmap/bitmap_pragmas.h"

extern UBYTE w_cmap[16][3];

extern UWORD w01_imgdata[], w02_imgdata[], w03_imgdata[],
             w04_imgdata[], w05_imgdata[], w06_imgdata[],
             w07_imgdata[], w08_imgdata[], w09_imgdata[],
             w10_imgdata[], w11_imgdata[], w12_imgdata[],
             w13_imgdata[], w14_imgdata[], w15_imgdata[],
             w16_imgdata[], w17_imgdata[], w18_imgdata[],
             w19_imgdata[], w20_imgdata[], w21_imgdata[],
             w22_imgdata[], w23_imgdata[], w24_imgdata[],
             w_mask[];

#define IMGW 64
#define IMGH 64

#define BITPLSIZE ((((IMGW+15)>>4)<<1)*IMGH)

char *ver = "$VER: World 1.2 "__AMIGADATE__;

UWORD *wframes[24] = {
             w01_imgdata, w02_imgdata, w03_imgdata,
             w04_imgdata, w05_imgdata, w06_imgdata,
             w07_imgdata, w08_imgdata, w09_imgdata,
             w10_imgdata, w11_imgdata, w12_imgdata,
             w13_imgdata, w14_imgdata, w15_imgdata,
             w16_imgdata, w17_imgdata, w18_imgdata,
             w19_imgdata, w20_imgdata, w21_imgdata,
             w22_imgdata, w23_imgdata, w24_imgdata };

UBYTE *mem_ptr;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *BitMapBase;
struct DisplayIDInformation *dinfo;
BOOL blanking = TRUE, customscreen;

extern ULONG RangeSeed;
struct Screen *scr;
struct BitMap *Worldsbm, *storebm, *shadowbm, *scalebm;
WORD x, y, dirx, diry,
     blitx, blity, sizex, sizey, y_gap;
UBYTE scaleX = 0, scaleY = 0;
struct BitMapScaleInfo bsi;
UBYTE depth, frame;
struct RastPort *rp;
PLANEPTR mask;
int frameno;


void MoveWorld( void )
{
x += dirx * (1<<scaleX);
if ( x < -((IMGW<<scaleX)>>1) )
	{
	x = -((IMGW<<scaleX)>>1);
	dirx = RangeRand( 2 ) + 1;
	}
if ( x >= scr->Width - 1 - (IMGW>>1) )
	{
	x = scr->Width - 1 - (IMGW>>1);
	dirx = - RangeRand( 2 ) - 1;
	}

y += diry * (1<<scaleY);
if ( y < -((IMGH<<scaleY)>>1) )
	{
	y = -((IMGH<<scaleY)>>1);
	diry = RangeRand( 2 ) + 1;
	}
if ( y >= scr->Height - 1 - (IMGH>>1) )
	{
	y = scr->Height - 1 - (IMGH>>1);
	diry = - RangeRand( 2 ) - 1;
	}
}


BOOL CreateFrames( void )
{
BOOL success = FALSE;

if ( Worldsbm = AllocVec( sizeof(struct BitMap), MEMF_ANY|MEMF_CLEAR ) )
	{
	InitBitMap( Worldsbm, depth + 1, IMGW, IMGH );
	Worldsbm->Planes[0] = mem_ptr;
	Worldsbm->Planes[1] = mem_ptr + BITPLSIZE;
	Worldsbm->Planes[2] = mem_ptr + 2 * BITPLSIZE;
	Worldsbm->Planes[3] = mem_ptr + 3 * BITPLSIZE;
	Worldsbm->Planes[depth] = mem_ptr + 4 * BITPLSIZE;

	if ( shadowbm = CreateBitMap( IMGW << scaleX, IMGH << scaleY, depth + 1 ) )
		{
		if ( scalebm = CreateBitMap( IMGW << scaleX, IMGH << scaleY, depth + 1 ) )
			{
			mask = scalebm->Planes[depth];

			bsi.bsi_SrcLeftEdge = 0;
			bsi.bsi_SrcTopEdge = 0;
			bsi.bsi_DestTopEdge = 0;
			bsi.bsi_DestLeftEdge = 0;
			bsi.bsi_HorDen = 1;
			bsi.bsi_VertDen = 1;
			bsi.bsi_TempBitMap = shadowbm;
			bsi.bsi_HorNum = 1 << scaleX;
			bsi.bsi_VertNum = 1 << scaleY;
			bsi.bsi_Flags = NULL;
			bsi.bsi_SrcBitMap = Worldsbm;
			bsi.bsi_DestBitMap = scalebm;
			bsi.bsi_Width = IMGW;
			bsi.bsi_Height = IMGH;

			Decrunch30( Worldsbm->Planes[depth], w_mask );

			success = TRUE;
			}
		if ( !success ) DisposeBitMap( shadowbm );
		}
	if ( !success ) FreeVec( Worldsbm );
	}

return success;
}


void GetDirection( void )
{
dirx = diry = 0;

while ( ( dirx == 0 ) || ( diry == 0 ) )
	{
	dirx = RangeRand( 5 ) - 2;
	diry = RangeRand( 5 ) - 2;
	}
}


void Blank( void )
{
register int n, ticks = 0;
ULONG mode;
BOOL success = FALSE;
UBYTE brightness = GETBRIGHTNESS(dinfo);

if ( !customscreen && CheckAA() && IntuitionBase->FirstScreen->RastPort.BitMap->Depth < 7 )
	scr = GetDeeperFrontmostScreen( brightness, 4 );
else
	{
	scaleX = scaleY = 0;
	if ( scr = OpenScreenTags( NULL,
		SA_DisplayID, DISPLAYID(dinfo),
		SA_Depth, 4,
		SA_Quiet, TRUE,
		TAG_END ) )
		SetRGB4( &scr->ViewPort, 0, 0, 0, 0 );
	}

if ( scr )
	{
	depth = scr->RastPort.BitMap->Depth;
	if ( depth <= 7 )
		{
		mode = scr->ViewPort.Modes;
		if ( mode & SUPERHIRES )
			{
			if ( mode & LACE )
				{ scaleX = 1; scaleY = 0; }
			else
				{ scaleX = 2; scaleY = 0; }
			}
		else if ( mode & HIRES )
			{
			if ( mode & LACE )
				{ scaleX = 1; scaleY = 1; }
			else
				{ scaleX = 1; scaleY = 0; }
			}
		else if ( mode & LACE )
			{ scaleX = 0; scaleY = 1; }

		if ( storebm = CreateBitMap( scr->Width, scr->Height, depth ) )
			{
			BltBitMap( scr->RastPort.BitMap, 0, 0,
				storebm, 0, 0,
				scr->Width, scr->Height, 0xC0, 0xFF, NULL );

			if ( CreateFrames() )
				{
				if ( rp = AllocVec( sizeof(struct RastPort), MEMF_ANY|MEMF_CLEAR ) )
					{
					success = TRUE;

					InitRastPort( rp );
					rp->BitMap = shadowbm;

					SpritesOff();

					for ( n = 1; n < 16; n++ )
						SetRGB4( &scr->ViewPort, n, w_cmap[n][0]*brightness/100, w_cmap[n][1]*brightness/100, w_cmap[n][2]*brightness/100 );

					x = RangeRand( scr->Width - 1 - (IMGW << scaleX) );
					y = RangeRand( scr->Height - 1 - (IMGH << scaleY) );
					GetDirection();

					while( STILL_BLANKING )
						{
						if ( !(bsi.bsi_Flags + scaleX + scaleY) && ++ticks < 5 )
							WaitTOF();
						else
							{
							ticks = 0;

							MoveWorld();

							if ( x < 0 )
								{ blitx = -x; sizex = (IMGW<<scaleX) + x; }
							else if ( x > scr->Width - 1 - (IMGW<<scaleX) )
								{ blitx = 0; sizex = scr->Width - x; }
							else
								{ blitx = 0; sizex = IMGW<<scaleX; }

							if ( y < 0 )
								{ blity = -y; sizey = (IMGH<<scaleY) + y; }
							else if ( y > scr->Height - 1 - (IMGH<<scaleY) )
								{ blity = 0; sizey = scr->Height - y; }
							else
								{ blity = 0; sizey = IMGH<<scaleY; }

							Decrunch30( mem_ptr, wframes[frameno] );
							frameno = ++frameno % 24;
							ScaleBitMap( &bsi );

							BltBitMap( storebm, x < 0 ? 0 : ( x >= scr->Width ? scr->Width - 1 - x : x ), y < 0 ? 0 : ( y >= scr->Height ? scr->Height - 1 - y : y ),
								shadowbm, 0, 0,
								IMGW << scaleX, IMGH << scaleY, 0xC0, 0xFF, NULL );

							BltMaskBitMapRastPort( scalebm, blitx, blity,
								rp, 0, 0, sizex, sizey, (ABC|ABNC|ANBC), mask );

							WaitTOF();
							BltBitMap( shadowbm, 0, 0,
								scr->RastPort.BitMap, x < 0 ? 0 : ( x >= scr->Width ? scr->Width - 1 - x : x ), y < 0 ? 0 : ( y >= scr->Height ? scr->Height - 1 - y : y ),
								x < 0 ? IMGW << scaleX : sizex, y < 0 ? IMGH << scaleY : sizey, 0xC0, 0xFF, NULL );
							}
						}
					SpritesOn();

					FreeVec( rp );
					}
				DisposeBitMap( scalebm );
				DisposeBitMap( shadowbm );
				FreeVec( Worldsbm );
				}
			DisposeBitMap( storebm );
			}
		}
	CloseScreen( scr );
	}

if ( !success )
	SendClientMsg( ACTION_FAILED );
}


void __main( void )
{
if ( IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library", 37L ) )
	{
	if ( GfxBase = (struct GfxBase *)OpenLibrary( "graphics.library", 37L ) )
		{
		if ( BitMapBase = OpenLibrary( "bitmap.library", 0L ) )
			{
			if ( mem_ptr = AllocVec( 5 * BITPLSIZE, MEMF_CHIP ) )
				{
				if ( dinfo = OpenCommunication() )
					{
					if ( Check4String( dinfo->di_Args, "CUSTOMSCREEN" ) )
						customscreen = TRUE;
					else
						customscreen = FALSE;

					CurrentTime( &RangeSeed, &RangeSeed );
					Blank();
					CloseCommunication( dinfo );
					}
				FreeVec( mem_ptr );
				}
			CloseLibrary( BitMapBase );
			}
		CloseLibrary( (struct Library *)GfxBase );
		}
	CloseLibrary( (struct Library *)IntuitionBase );
	}
}
