/************************************************************************************
	GLOVER PSX	(c) 1998-9 ISL

	overlay.c:	 	General overlay handling

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

#include "glover.h"

SPRCTRL sprctrl;
USHORT overlayAlphaClut = 0;

void spriteReset(void)
{
	sprctrl.overrideclut = 0;
	sprctrl.scalex = 4096;
	sprctrl.scaley = 4096;

	SETRGBC(sprctrl.r,128,128,128,0);
	//sprctrl.r=128;
	//sprctrl.g=128;
	//sprctrl.b=128;
	sprctrl.shaded=FALSE;
	sprctrl.center = 0;
	sprctrl.flipx = 0;
	sprctrl.flipy = 0;
	sprctrl.forceZ = 128;
	sprctrl.tempvram = 0;
	sprctrl.zbufspr = 0;
	sprctrl.attribute = 0;
	sprctrl.noclip = 0;
	sprctrl.nofade = 0;
	sprctrl.rotate=0;
	sprctrl.stretch=1;
	sprctrl.true_alpha = 255;
}

void spritePrint(SPRITEX *spr,SHORT x,SHORT y,USHORT zbuf)
{
	ULONG 	w,h;
	LONG u,v;
	//ULONG flag=0;
	POLY_FT4 *polyFT4=(POLY_FT4*)GsOUT_PACKET_P;
	POLY_GT4 *polyGT4=(POLY_GT4*)GsOUT_PACKET_P;
	GsOTA *otptr;
	UBYTE tmp;
	LONG		width;
	LONG		height;
	SHORT centerx,centery;
	LONG sin,cos;
	ULONG flag=0;
	int scaleX;

	ASSERT(spr);

	if(sprctrl.true_alpha==0)
		return;

	if(TOOMANYPOLYS(sizeof(POLY_FT4),"spritePrint"))
		return;

	w=spr->w;

	if(spr->tpage&128)
	{
		if(w==128)
		{
			flag=1;
		} //256;
	}
	else
	{
		if(w==256)
		{
			flag=1;
		}
	}
	
	if (w==0)
	{
		w=256;
		flag=1;
	} //256;

	h=spr->h; //if (h==0)h=256;

	if(sprctrl.shaded)
	{
		*(ULONG*)&polyGT4->u0=*(ULONG*)&spr->u0;
		*(ULONG*)&polyGT4->u1=*(ULONG*)&spr->u1;
		*(ULONG*)&polyGT4->u2=*(ULONG*)&spr->u2;
		*(ULONG*)&polyGT4->u3=*(ULONG*)&spr->u3;
	}
	else
	{
		*(ULONG*)&polyFT4->u0=*(ULONG*)&spr->u0;
		*(ULONG*)&polyFT4->u1=*(ULONG*)&spr->u1;
		*(ULONG*)&polyFT4->u2=*(ULONG*)&spr->u2;
		*(ULONG*)&polyFT4->u3=*(ULONG*)&spr->u3;
	}

	if(sprctrl.stretch)
		scaleX=sprctrl.scalex*sprctrl.stretch;
	else
		scaleX=sprctrl.scalex;

	w=((w*scaleX)/4096);
	h=((h*sprctrl.scaley)/4096);

	if(sprctrl.shaded)
	{
		polyGT4->x0=x;
		polyGT4->y0=y;
		polyGT4->x1=x+w;
		polyGT4->y1=y;
		polyGT4->x2=x;
		polyGT4->y2=y+h;
		polyGT4->x3=x+w;
		polyGT4->y3=y+h;
	}
	else
	{
		polyFT4->x0=x;
		polyFT4->y0=y;
		polyFT4->x1=x+w;
		polyFT4->y1=y;
		polyFT4->x2=x;
		polyFT4->y2=y+h;
		polyFT4->x3=x+w;
		polyFT4->y3=y+h;
	}

	u=(spr->u*scaleX)/4096;
	v=(spr->v*sprctrl.scaley)/4096;

	if(sprctrl.shaded)
	{
		polyGT4->x0+=u;
		polyGT4->y0+=v;
		polyGT4->x1+=u;
		polyGT4->y1+=v;
		polyGT4->x2+=u;
		polyGT4->y2+=v;
		polyGT4->x3+=u;
		polyGT4->y3+=v;
	}
	else
	{
		polyFT4->x0+=u;
		polyFT4->y0+=v;
		polyFT4->x1+=u;
		polyFT4->y1+=v;
		polyFT4->x2+=u;
		polyFT4->y2+=v;
		polyFT4->x3+=u;
		polyFT4->y3+=v;
	}

	if(flag!=1)
	{
		if(scaleX<=4096)
		{
			if(sprctrl.shaded)
			{
				polyGT4->u1++;
				polyGT4->u3++;
			}
			else
			{
				polyFT4->u1++;
				polyFT4->u3++;
			}
		}
	}

	if(sprctrl.scaley<=4096)
	{
		if(sprctrl.shaded)
		{
			polyGT4->v2++;
			polyGT4->v3++;
		}
		else
		{
			polyFT4->v2++;
			polyFT4->v3++;
		}

	}

	if(sprctrl.flipx)
	{
		if(sprctrl.shaded)
		{
			tmp=polyGT4->u0;polyGT4->u0=polyGT4->u1-1;polyGT4->u1=tmp-1;
			tmp=polyGT4->u2;polyGT4->u2=polyGT4->u3-1;polyGT4->u3=tmp-1;
		}
		else
		{
			tmp=polyFT4->u0;polyFT4->u0=polyFT4->u1-1;polyFT4->u1=tmp-1;
			tmp=polyFT4->u2;polyFT4->u2=polyFT4->u3-1;polyFT4->u3=tmp-1;
		}
	}	

	if(sprctrl.flipy)
	{
		if(sprctrl.shaded)
		{
			tmp=polyGT4->v0;polyGT4->v0=polyGT4->v2-1;polyGT4->v2=tmp-1;
			tmp=polyGT4->v1;polyGT4->v1=polyGT4->v3-1;polyGT4->v3=tmp-1;
		}
		else
		{
			tmp=polyFT4->v0;polyFT4->v0=polyFT4->v2-1;polyFT4->v2=tmp-1;
			tmp=polyFT4->v1;polyFT4->v1=polyFT4->v3-1;polyFT4->v3=tmp-1;
		}
	}	

	if(sprctrl.rotate!=0)
	{
		width=polyFT4->x3-polyFT4->x0;		
		height=polyFT4->y3-polyFT4->y0;		
		centerx=polyFT4->x0+width/2;
		centery=polyFT4->y0+height/2;
		width=width/2;
		sin=rsin(sprctrl.rotate+3072);
		cos=rcos(sprctrl.rotate+3072);

		polyFT4->x0=centerx+(cos*height+sin*width)/(4096);
		polyFT4->y0=centery+(cos*width-sin*height)/(4096*2);

		polyFT4->x1=centerx+(-sin*width+cos*height)/(4096);
		polyFT4->y1=centery+(-sin*height-cos*width)/(4096*2);

		polyFT4->x3=centerx+(-cos*height-sin*width)/(4096);
		polyFT4->y3=centery+(-cos*width+sin*height)/(4096*2);

		polyFT4->x2=centerx+(sin*width-cos*height)/(4096);
		polyFT4->y2=centery+(sin*height+cos*width)/(4096*2);
	}

	if(sprctrl.shaded)
	{
		*(ULONG*)&polyGT4->r0=*(ULONG*)&sprctrl.r;
		*(ULONG*)&polyGT4->r1=*(ULONG*)&sprctrl.r;
		*(ULONG*)&polyGT4->r2=*(ULONG*)&sprctrl.r1;
		*(ULONG*)&polyGT4->r3=*(ULONG*)&sprctrl.r1;
		polyGT4->code=GPU_COM_TG4;//<<24)+(sprctrl.b<<16)+(sprctrl.g<<8)+(sprctrl.r);

  		polyGT4->tpage=spr->tpage;
		if(sprctrl.semitrans)
		{
			polyGT4->code|=2;		//does all semi trans modes
			polyGT4->tpage|=((sprctrl.semitrans-1)<<5);
		}

		if(sprctrl.overrideclut!=0)
			polyGT4->clut=sprctrl.overrideclut; 
	
	  	otptr=(GsOTA*)(PolyList->org+1+((zbuf & MAXDEPTH)>>(PolyList->shift)));
   		PUTPACKETINTABLE(polyGT4,otptr,POLYTG4_LEN);
		
		GsOUT_PACKET_P +=sizeof(POLY_GT4);
	}
	else
	{
		if(sprctrl.true_alpha == 255)
		{
			*(ULONG*)&polyFT4->r0=*(ULONG*)&sprctrl.r;
			polyFT4->code=GPU_COM_TF4;//<<24)+(sprctrl.b<<16)+(sprctrl.g<<8)+(sprctrl.r);

  			polyFT4->tpage=spr->tpage;
			if(sprctrl.semitrans)
			{
				polyFT4->code|=2;		//does all semi trans modes
				polyFT4->tpage|=((sprctrl.semitrans-1)<<5);
			}

			if(sprctrl.overrideclut!=0)
				polyFT4->clut=sprctrl.overrideclut; 
		
	  		otptr=(GsOTA*)(PolyList->org+1+((zbuf & MAXDEPTH)>>(PolyList->shift)));
   			PUTPACKETINTABLE(polyFT4,otptr,POLYTF4_LEN);
			
			GsOUT_PACKET_P +=sizeof(POLY_FT4);
		}
		else
		{
//			int temp = sprctrl.true_alpha;
//			sprctrl.true_alpha = 255;
// true alpha:- 2nd, plot the sprite in additive, with rgb scaled to the alpha value
			polyFT4->r0=(sprctrl.r * sprctrl.true_alpha)>>8;
			polyFT4->g0=(sprctrl.g * sprctrl.true_alpha)>>8;
			polyFT4->b0=(sprctrl.b * sprctrl.true_alpha)>>8;
			polyFT4->code=GPU_COM_TF4 | 2;
  			polyFT4->tpage=spr->tpage | ((SEMITRANS_ADD-1)<<5);

			if(sprctrl.overrideclut!=0)
				polyFT4->clut=sprctrl.overrideclut; 
		
	  		otptr=(GsOTA*)(PolyList->org+1+((zbuf & MAXDEPTH)>>(PolyList->shift)));
   			PUTPACKETINTABLE(polyFT4,otptr,POLYTF4_LEN);
			
			GsOUT_PACKET_P +=sizeof(POLY_FT4);
// true alpha:- 1st, plot the sprite in subtractive, using darkness proportional to the alpha value
// Requires a CLUT that is (transparent zero, 127-white everywhere else)
// (or, for lighting effects, a clut which is grey-scaled for an alpha-map, but that shoud be done as a special case where needed)

			polyFT4[1] = polyFT4[0];
			polyFT4++;

			polyFT4->r0=sprctrl.true_alpha;
			polyFT4->g0=sprctrl.true_alpha;
			polyFT4->b0=sprctrl.true_alpha;
			polyFT4->tpage = spr->tpage |((SEMITRANS_SUB-1)<<5);

			polyFT4->clut = overlayAlphaClut;
   			PUTPACKETINTABLE(polyFT4,otptr,POLYTF4_LEN);	// same ot-ptr

			GsOUT_PACKET_P +=sizeof(POLY_FT4);

//			sprctrl.true_alpha = temp;

		}
	}

   	if((spr->flags bAND (NSPLIT))!=0)
		spritePrint(spr+1,x,y,zbuf);

	// NB - For the dictionary definition of recursion, see recursion.
}

OVERLAYLIST overlayList;

void overlayFindFrames(OVERLAY *pOverlay, char *sStr)
{
	int f;
	char sFName[16];
	pOverlay->frameList=(FRAMELIST *)MALLOC(sizeof(FRAMELIST), sStr);
	for(f=1; f<MAX_OVERLAY_FRAMES; f++)
	{
		sprintf(sFName, "%s%02d", sStr, f);
		DB("Frame '%s'\n", sFName);
		pOverlay->frameList->texture[f-1]=textureFindInAllBanks(sFName);
		if(!(pOverlay->frameList->texture[f-1]))
			break;
	}

	pOverlay->frameList->numFrames=f-1;
	pOverlay->frameList->currentFrame=0;
}

/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void overlaySetup(OVERLAY *overlay, SPRITEX *texture, int xPos, int yPos, int zPos, int attrib)
{

	//NFindTexture(&overlay->texture, UpdateCRC(name), NO);
	overlay->texture=texture;
	overlay->frameList = NULL;
	overlay->scaleX = overlay->scaleY = 4096;
	overlay->xPos = xPos;
	overlay->yPos = yPos;
	overlay->zPos = zPos;
	overlayInitialise(overlay);
	overlay->a = 255;
	overlay->active=TRUE;

}

/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void overlaySetupAndAdd(OVERLAY *overlay, SPRITEX *texture, int xPos, int yPos, int zPos, int attrib)
{
	overlaySetup(overlay,texture,xPos,yPos,zPos,attrib);
	overlayAdd(overlay);
}

/*	--------------------------------------------------------------------------------
	Function 	: SetupOverlay
	Purpose 	: sets up most of the common elements that are always needed to be initialised
	Parameters 	: OVERLAY *
	Returns 	: none
	Info 		:
*/
void overlayInitialise(OVERLAY *overlay)
{
	overlay->r = overlay->g = overlay->b = 255;
	overlay->a = 255;	//127;
}

/*	--------------------------------------------------------------------------------
	Function 	: InitOverlayList()
	Purpose 	: duh!
	Parameters 	: none
	Returns 	: none
	Info 		:
*/
void overlayInitialiseList(void)
{
	static USHORT ref_palette[16] =
	{0x8000,0x4210,0x4210,0x4210,	// rgb = 127
	 0x4210,0x4210,0x4210,0x4210,
	 0x4210,0x4210,0x4210,0x4210,
	 0x4210,0x4210,0x4210,0x4210
	};

	overlayList.head.next = overlayList.head.prev = &overlayList.head;
	overlayList.numEntries = 0;
	if(!overlayAlphaClut)
	{
		overlayAlphaClut = textureAddCLUT16(&ref_palette[0]);
	}
}

void overlaySub(OVERLAY *overlay)
{
	if(overlay->next == NULL)
		return;


	if(overlay->frameList)
	{
		FREE(overlay->frameList);
		overlay->frameList = NULL;
	}

	//FREE(&overlay->bitmap);

	overlay->prev->next = overlay->next;
	overlay->next->prev = overlay->prev;

	overlay->next = NULL;
	overlayList.numEntries--;
}

/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void overlayAdd(OVERLAY *overlay)
{
	OVERLAY *ptr;
	int i = 0;

	//if(overlay->next == NULL)
	{
		for(ptr = overlayList.head.next;ptr != &overlayList.head;ptr = ptr->next)
		{
			if(ptr == NULL)
				printf("oo la la\n");
			i++;
			if(ptr->zPos < overlay->zPos)
			{
				break;
			}
		}
		overlay->next = ptr;
		overlay->prev = ptr->prev;
		ptr->prev->next = overlay;
		ptr->prev = overlay;
		overlayList.numEntries++;
	}
}

void overlayClearAll(void)
{
	OVERLAY *overlay,*overlay2;

	for(overlay = overlayList.head.next;overlay != &overlayList.head;overlay = overlay2)
	{
		overlay2 = overlay->next;
		overlaySub(overlay);
	}

	//overlayInitialiseList();
}

/*	--------------------------------------------------------------------------------
	Function 	: PrintOverlays()
	Purpose 	: 
	Parameters 	: none
	Returns 	: none
	Info 		:
*/
void overlayPrintAll(void)
{
	OVERLAY *overlay;

	sprctrl.stretch=2;

	if(overlayList.numEntries)
	{
		for(overlay = overlayList.head.next;overlay != &overlayList.head;overlay = overlay->next)
		{
			if(overlay->active)
				overlayPrint(overlay);	
		}
	}

// tidy up anything we've changed so others don't need to check it all the time
	sprctrl.scalex=4096;
	sprctrl.scaley=4096;
	SETRGBC(sprctrl.r,128,128,128,0);
}


void overlayPrint(OVERLAY *overlay)
{
	SPRITEX *pSprite;

	if(overlay->a==0)
		return;

	if(overlay->frameList)		//is it an animating overlay?
	{
		pSprite = overlay->frameList->texture[overlay->currentFrame];
		//overlay->sprite.bitmap->buf = pOv->data;	
	
//		if(dispFrameCount & 1)
			overlay->currentFrame++;
	
		if(overlay->currentFrame >= overlay->frameList->numFrames)
			overlay->currentFrame = 0;
	}
	else
		pSprite=overlay->texture;

	//printf("Printing sprite %p at %d,%d ...\n", pSprite, overlay->xPos, overlay->yPos);
	sprctrl.scalex=(overlay->scaleX);//*5192)/4096;
	sprctrl.scaley=overlay->scaleY;
	sprctrl.stretch=0;

	sprctrl.r=overlay->r/2;
	sprctrl.g=overlay->g/2;
	sprctrl.b=overlay->b/2;

//	sprctrl.semitrans=(overlay->a<128)?1:0;
	sprctrl.semitrans = SEMITRANS_NONE;
	sprctrl.true_alpha = overlay->a;

	spritePrint(pSprite, overlay->xPos-256, overlay->yPos-128, 0);

	sprctrl.true_alpha = 255;

//	sprctrl.semitrans=0;
}

