
#include "glover.h"

// 4K-Aligned stuff for effects.c (padded out to go beyond 4k)
// (In a separate file, coz bits of effects.c relied on
// This whole file JUST fits into 4k (see GLOVER.MAP)



// these are masked with &60 000000, so semi becomes zero, as required
// (they also need shifting down, coz the transp mode is in the 16...23 byte)

int Print3DSpriteG(SPRITEX *spr,VERT *vect,SHORT scale, unsigned long *colours);

void Draw_Debris()
{
	DEBRISSTR *deb;
	VERT vect;
	unsigned int colour;
	int r,g,b;


// this time, we can whistle through the list, coz none of 'em are going to vanish
	for(deb = active_debris; deb; deb = deb->next)
	{
		vect.vx = deb->pos.vx >> 12;
		vect.vy = deb->pos.vy >> 12;
		vect.vz = deb->pos.vz >> 12;

		switch(deb->type)
		{

			case DEBRIS_BLUESTAR:
				Print3DSprite(bstarbase + (deb->timer >> 1),	&vect,400, P3DS_SEMI | 0x808080);
				break;

			case DEBRIS_POINTS:
			{
				static unsigned long colours[6 * 4] =
				{
					0x008080,0x008080,0x001080,0x001080,	// 10	yel
					0x008000,0x008000,0x808000,0x808000,	// 20	grn
					0x206080,0x206080,0x108080,0x108080,	// 50 orange
					0x808000,0x808000,0x800000,0x800000,	// 100 blu
					0x802070,0x802070,0x200080,0x200080,	// 500 pink
					0x008080,0x008080,0xc0c0c0,0xc0c0c0		// x2
				};

/*
				if(deb->timer < 10)
				{
					sprctrl.r = sprctrl.g = sprctrl.b = 128;
				}
				else
				{
// 10...20 -> 128...0
					sprctrl.r = sprctrl.g = sprctrl.b = ((20 - deb->timer) * 128 / 10);
				}

				sprctrl.semitrans = SEMITRANS_ADD;
				Print3DSprite(
					garibscorebase + deb->value,
					deb->pos.vx>>12,(deb->pos.vy>>12) - (deb->timer << 2),deb->pos.vz>>12,
					350 + 20 * deb->timer,350 + 20 * deb->timer);
*/
//				sprctrl.semitrans = SEMITRANS_NONE;
/*
				switch(deb->value)
				{
				case 1:
					colour = 0x008000;
					break;
				case 2:
					colour = 0x286440;
					break;
				case 3:
					colour = 0x808000;
					break;
				case 4:
					colour = 0x804070;
					break;
				case 5:
					colour = 0x008000;
					break;


				default:
					colour = 0x008080;
					break;
				}
*/
				if(deb->value == 5)
				{
					vect.vy -= (deb->timer << 1);
				}
				else
				{
					vect.vy -= (deb->timer << 2);
				}

				Print3DSpriteG(
					garibscorebase + deb->value,
					&vect,
					170 + 10 * deb->timer, &colours[deb->value<<2]);

				break;
			}

			case DEBRIS_LIFEGLOW:
				if(deb->timer < 5)
				{
					colour = 0x808080 | P3DS_ADD;
				}
				else
				{
// 10...20 -> 128...0
					colour = 0x10101 * ((10 - deb->timer) * 128 / 5) + P3DS_ADD;
				}

				Print3DSprite(
					glowbase + deb->timer,
					&vect,
					256,
					colour);
				break;


			case DEBRIS_RINGSTAR:
				if(deb->timer < 6)
				{
//					sprctrl.r = sprctrl.g = sprctrl.b = 128;
					colour = 0x808080;
				}
				else
				{
// 10...20 -> 128...0
					colour = (0x10101 * ((12 - deb->timer) * 128 / 6) ) | P3DS_ADD;
				}

				{
//					VECTOR tvec;
//					tvec = deb->pos;
					vect.vx = (deb->pos.vx + deb->timer * (rsin(deb->value) <<2)) >> 12;
					vect.vz = (deb->pos.vz + deb->timer * (rcos(deb->value) <<2)) >> 12;
					vect.vy = (deb->pos.vy - 10 * rsin(deb->timer * 2048 / 12)) >> 12;

//					Print3DSprite(starbase,&vect,256,colour);
					Print3DSprite(starbase,&vect,128,colour);
				}
				break;


			case DEBRIS_STUNSTAR:
				colour = (0x10101 * ((12 - deb->timer) * 128 / 12)) | P3DS_ADD;
//				Print3DSprite(starbase,&vect,256 - 10 * deb->timer, colour);
				Print3DSprite(starbase,&vect,128 - 5 * deb->timer, colour);
				break;


			case DEBRIS_WISP:
				if(deb->timer < 4)
				{
					colour = 0x404040 | P3DS_ADD;
				}
				else
				{
// 10...20 -> 128...0
					colour = (0x101010 * ((7 - deb->timer) * 64 / 3)) | P3DS_ADD;
				}
				{
					Print3DSprite(wispbase + deb->timer,&vect,256,colour);
				}
				break;

			case DEBRIS_SPELLDUST:
//				sprctrl.semitrans = SEMITRANS_ADD;
//				sprctrl.r = sprctrl.g = sprctrl.b = 64;	// the decay's built into the sprite

//				colour = 0x404040 | P3DS_ADD;
//				Print3DSprite(SPR_fardbase + (deb->timer >> 1),&vect,512,colour);
				colour = 0x808080 | P3DS_ADD;
				Print3DSprite(SPR_fardsbase + (deb->timer >> 1),&vect,256,colour);
				colour = 0x808080 | P3DS_SUB;
				Print3DSprite(SPR_fardabase + (deb->timer >> 1),&vect,256,colour);

				break;


			case DEBRIS_SPELLFLASH:
			{
				int size;
				size = 2050 - 2048 * deb->timer/10;

	// manual non 50-50 alpha...
	// 2nd, add in the foreground
				Print3DSprite(
					SPR_fairbase,
					&vect,
					size,
					deb->value | P3DS_ADD);
	// 1st, dim down the background
				Print3DSprite(
					SPR_fairbase,
					&vect,
					size, 0x404040 | P3DS_SUB);
				break;
			}

			case DEBRIS_FLAME:
				{
					VECTOR tvec;
					if(deb->value != -1)
					{
						vect.vx = (deb->pos.vx + deb->timer * (rsin(deb->value) <<2)) >> 12;
						vect.vz = (deb->pos.vz + deb->timer * (rcos(deb->value) <<2)) >>12;
					}

					Print3DSprite(
						(SPR_firebbase + deb->timer * 8/30),
						&vect,
//						512,0xc0c0c0 | P3DS_SEMI);
						256,0xc0c0c0 | P3DS_SEMI);
				}
				break;
			case DEBRIS_FASTFLAME:
				{
					VECTOR tvec;
					Print3DSprite(
						(SPR_firebbase + deb->timer * 8/15),
						&vect,
//						deb->value,0xc0c0c0 | P3DS_SEMI);
						deb->value>>1,0xc0c0c0 | P3DS_SEMI);
				}
				break;

			case DEBRIS_AIMBLOB:
			{
				int bri;
				sprctrl.semitrans = SEMITRANS_ADD;

				bri = (20 - deb->timer) * 64/20;

	// manual non 50-50 alpha...
	// 2nd, add in the foreground
				r = ((deb->value      ) & 0xff) * bri/64;
				g = ((deb->value >>  8) & 0xff) * bri/64;
				b = ((deb->value >> 16) & 0xff) * bri/64;

				Print3DSprite(
					SPR_fairbase,
					&vect,
					256, (r) | (g<<8) | (b << 16) | P3DS_ADD);

	// 1st, dim down the background
				Print3DSprite(
					SPR_fairbase,
					&vect,
					256, (0x10101 * (bri * 3/2)) | P3DS_SUB);

				break;
			}

			case DEBRIS_DUST:
			{
				Print3DSprite(
					SPR_smokebase + deb->timer,
					&vect,
					256,deb->value | P3DS_ADD);
//					512,deb->value | P3DS_ADD);
				break;
			}



			case DEBRIS_PORTALPUFF:
			case DEBRIS_PORTALPUFF2:
			{
				int size;
				int bri;

				if(deb->type == DEBRIS_PORTALPUFF)	// || deb->type == DEBRIS_HOOPHOVER)
					size = 256;
				else
					size = 64;

				if(deb->timer < 6)
				{
					bri = 64;
					size = size * (deb->timer+4)/10;
					colour = deb->value;
				}
				else
				{
// 10...20 -> 128...0
					bri = (12 - deb->timer) * 64 / 6;
					r = deb->value & 0xff;
					g = (deb->value>>8) & 0xff;
					b = (deb->value>>16) & 0xff;

					r = ((12 - deb->timer) * r / 6);
					g = ((12 - deb->timer) * g / 6);
					b = ((12 - deb->timer) * b / 6);
					colour = (r) | (g<< 8) | (b<<16);
				}


// manual non 50-50 alpha...
// 2nd, add in the foreground

				Print3DSprite(
					SPR_puffbase,
					&vect,
					size,colour | P3DS_ADD);

// 1st, dim down the background

				Print3DSprite(
					SPR_puffbase,
					&vect,
					size,(bri * 0x10101) | P3DS_SUB);
//					12,(bri * 0x10101) | P3DS_SUB);

				break;
			}

			case DEBRIS_ROBOTHOVER:
			case DEBRIS_HOOPHOVER:
			{
				int bri;
				int size;

				if(deb->type == DEBRIS_ROBOTHOVER)
				{
					size = 1024;
				}
				else
					size = 256;


				if(deb->timer < 3)
				{
					bri = deb->timer * 64/3;
					colour = deb->value;
					r = deb->value & 0xff;
					g = (deb->value>>8) & 0xff;
					b = (deb->value>>16) & 0xff;

					r = deb->timer * r / 3;
					g = deb->timer * g / 3;
					b = deb->timer * b / 3;
					colour = (r) | (g<< 8) | (b<<16);
				}
				else if(deb->timer < 6)
				{
					bri = 64;
					colour = deb->value;
				}
				else
				{
// 10...20 -> 128...0
					bri = (12 - deb->timer) * 64 / 6;
					r = deb->value & 0xff;
					g = (deb->value>>8) & 0xff;
					b = (deb->value>>16) & 0xff;

					r = ((12 - deb->timer) * r / 6);
					g = ((12 - deb->timer) * g / 6);
					b = ((12 - deb->timer) * b / 6);
					colour = (r) | (g<< 8) | (b<<16);
				}


// manual non 50-50 alpha...
// 2nd, add in the foreground

				Print3DSprite(
					SPR_puffbase,
					&vect,
					size,colour | P3DS_ADD);

// 1st, dim down the background

				Print3DSprite(
					SPR_puffbase,
					&vect,
					size,(bri * 0x10101) | P3DS_SUB);

				break;
			}


			case DEBRIS_STINGEXPLODE:
			{

	// manual non 50-50 alpha...
	// 2nd, add in the foreground
				Print3DSprite(
					SPR_smokebase + deb->timer,
					&vect,
					1024,
					deb->value | P3DS_ADD);
	// 1st, dim down the background
				Print3DSprite(
					SPR_smokebase + deb->timer,
					&vect,
					1024, 0x404040 | P3DS_SUB);
				break;
			}
			case DEBRIS_SMOKE:
				{
					Print3DSprite(
						(SPR_smokebase + deb->timer * 7/30),
						&vect,
						deb->value,0x404040 | P3DS_SUB);
				}
				break;


			case DEBRIS_TRACY_HEART:
			{
				int bri;


				if(deb->timer < 3)
				{
					bri = deb->timer * 127/3;
				}
				else
				{
					bri = (20-deb->timer) * 127 / 17;
				}

				Print3DAlphaSprite(tracy_heart_sprite,&vect,256, 0x60505050);

/*
// manual non 50-50 alpha...
// 2nd, add in the foreground

				Print3DSprite(
					tracy_heart_sprite,
					&vect,
					256,bri * 0x10101 | P3DS_ADD);

// 1st, dim down the background
// (ummm - we want to use the masking palette, dude!)

				Print3DSprite(
					tracy_heart_sprite,
					&vect,
					256,(bri * 0x10101) | P3DS_SUB);
*/
				break;
			}

		
			case DEBRIS_OPEC_HOVER:
			{
				Print3DSprite(
					(SPR_smokebase + deb->timer * 7/10),
					&vect,
					deb->value,0x404040 | P3DS_ADD);
			}
			break;

			case DEBRIS_CANNON:
				{
					Print3DSprite(
						(SPR_smokebase + deb->timer * 7/30),
						&vect,
						deb->value,0x404040 | P3DS_ADD);
				}
				break;


// yellow animated sparky blobby bits
			case DEBRIS_FRANKLECCY:
				if(deb->timer < 6)
				{
					colour = 0x008080 | P3DS_ADD;
				}
				else
				{
// 10...20 -> 128...0
					colour = (0x00101 * ((12 - deb->timer) * 128 / 6) ) | P3DS_ADD;
				}

				vect.vx = (deb->pos.vx + deb->timer * (rsin(deb->value) <<1)) >> 12;
				vect.vz = (deb->pos.vz + deb->timer * (rcos(deb->value) <<1)) >> 12;
				vect.vy = (deb->pos.vy - 10 * rsin(deb->timer * 2048 / 12)) >> 12;

				Print3DSprite(SPR_fairbase,&vect,400,colour);

				if(deb->timer < 6)
				{
					colour = 0x404040 | P3DS_SUB;
				}
				else
				{
// 10...20 -> 128...0
					colour = (0x10101 * ((12 - deb->timer) * 64 / 6) ) | P3DS_SUB;
				}
				Print3DSprite(SPR_fairbase,&vect,400,colour);

				break;


			case DEBRIS_FRANKLECCY2:
				if(deb->timer < 6)
				{
					colour = 0x808000 | P3DS_ADD;
				}
				else
				{
// 10...20 -> 128...0
					colour = (0x10100 * ((12 - deb->timer) * 128 / 6) ) | P3DS_ADD;
				}

				vect.vx = (deb->pos.vx + deb->timer * (rsin(deb->value) <<1)) >> 12;
				vect.vz = (deb->pos.vz + deb->timer * (rcos(deb->value) <<1)) >> 12;
				vect.vy = (deb->pos.vy - 10 * rsin(deb->timer * 2048 / 12)) >> 12;

				Print3DSprite(SPR_fairbase,&vect,400,colour);

				if(deb->timer < 6)
				{
					colour = 0x404040 | P3DS_SUB;
				}
				else
				{
// 10...20 -> 128...0
					colour = (0x10101 * ((12 - deb->timer) * 64 / 6) ) | P3DS_SUB;
				}
				Print3DSprite(SPR_fairbase,&vect,400,colour);

				break;



		}
	}
	sprctrl.r = sprctrl.g = sprctrl.b = 128;
	sprctrl.semitrans = 0;
}

void	Draw_Garibs()
{
	GARIBPOS *gar;
	int k;
	VERT vect;

	gar = &garibpositions[0];
	for (k=0;k<numberofgaribs;k++, gar++)
	{
		gar_frame += 4;
//		if(gar_frame >= cardbase+13)
//			gar_frame -=13;
		if(gar_frame >= cardbase+12)
			gar_frame -=12;

		if((gar->flags & (GARIBFLAG_DISPLAY + GARIBFLAG_COLLECTED)) == GARIBFLAG_DISPLAY)
		{
			vect.vx = gar->x;
			vect.vy = gar->y;
			vect.vz = gar->z;
			switch(gar->type)
			{
				case NORMAL_GARIB:
				case GENERATED_GARIB:
					if(Print3DSprite(gar_frame,&vect,GARIB_DRAW_SIZE, 0x00808080))
					{
						SVECTOR v;
						v.vx = gar->x;
						v.vy = gar->shadowheight;
						v.vz = gar->z;

						Draw_RawShadow(&v, 5, 0x303030,-1);
					}
					break;

				case EXTRA_LIFE:
				case GENERATED_LIFE:
					if(Print3DSprite(extralifebase+(activeframe & 7),&vect,ELIFE_DRAW_SIZE, 0x00808080))
					{
						SVECTOR v;
						v.vx = gar->x;
						v.vy = gar->shadowheight;
						v.vz = gar->z;

						Draw_RawShadow(&v, 5, 0x303030,-1);
					}
					break;

				case SUPER_GARIB:
				default:
					break;
			}
		}
	}
}

void pickupDrawSpells()
{
	int i;
	SPELLSTR *spell;
	int f;
	VERT vect;

	for(i = 0, spell = & spells[0]; i < MAX_SPELLS; i++, spell++)
	{
		if(spell->timer)
		{
			f = activeframe & 7;
			if (f > 3)
				f = 7 - f;

			vect.vx = spell->pos.vx>>12;
			vect.vy = spell->pos.vy>>12;
			vect.vz = spell->pos.vz>>12;
// manual non 50-50 alpha...

// 2nd, add in the foreground

			Print3DSprite(
				SPR_fairbase + f,
				&vect,
				512,spell->headcolour | P3DS_ADD);
// 1st, dim down the background
			Print3DSprite(
				SPR_fairbase + f,
				&vect,
				512,0x404040 | P3DS_SUB);
		}
	}

	sprctrl.semitrans = 0;
	sprctrl.r = sprctrl.g = sprctrl.b = 128;
}

/*
typedef struct {
	u_long	tag;
	u_char	r0, g0, b0, code;
	short	x0, 	y0;
	u_char	u0, v0;	u_short	clut;
	short	x1,	y1;
	u_char	u1, v1;	u_short	tpage;
	short	x2,	y2;
	u_char	u2, v2;	u_short	pad1;
	short	x3,	y3;
	u_char	u3, v3;	u_short	pad2;
} POLY_FT4;
*/



int Print3DSprite(SPRITEX *spr,VERT *vect,SHORT scale, unsigned long colour)
{
	POLY_FT4 *si;
	LONG spritez;

	LONG		width;
	LONG		height;
	LONG distancescale;
	GsOTA 	*otptr;

//	if (TOOMANYPOLYS(4*MAXPACKETSIZE,"Print3DSprite"))return 0;

	si = (POLY_FT4 *) GsOUT_PACKET_P; 


// scary scaling-and-transform-in-one-go code from the Action Man people...
	width = (spr->w);
	gte_SetLDDQB(0);			// clear offset control reg (C2_DQB)
	gte_ldv0(vect)	;//vert);
	gte_SetLDDQA(width);		// shove sprite width into control reg (C2_DQA)
	gte_rtps();				// do the rtps
	gte_stsxy(&si->x0);	//scrxy);		// get screen x and y
	gte_stszotz(&spritez);	//depth);		// get order table z
// end of scaling-and-transform


// tbd - make this ditch according to on-screen SIZE
// limit to "max poly depth", and we can ditch the "MAXDEPTH" "and" below...

	if(spritez < 20) return 0;
//	if (spritez>1000)return 0; //about half the length of atlantis1


	if(spritez > lscapeFogStartZ>>2)
		return 0;
	if(spritez > MAXOTZ)
		spritez = MAXOTZ-50;



	gte_stopz(&distancescale);		// get scaled width of sprite
	distancescale >>= 16;

	width = (distancescale * scale) >> 8;

	if(width < 3)
		return 0;	// better max-distance check

 	si->x1=si->x3=si->x0+width;
 	si->x0=si->x2=si->x0-width;
   	if (si->x1<-256) return 0;
   	if (si->x0>256) return 0;

	if(spr->w == spr->h)
		height = width;	//(distancescale * scale) >> 8;
	else
		height = width * spr->h / spr->w;

	si->y2=si->y3=si->y0+height;
	si->y1=si->y0=si->y0-height;
   	if (si->y2< -128) return 0;
   	if (si->y0> 128) return 0;


	*(ULONG*)&si->u0=*(ULONG*)&((SPRITEX*)spr)->u0;	// u0,v0, and clut info
	*(ULONG*)&si->u2=*(ULONG*)&((SPRITEX*)spr)->u2;	// plus pad1
	*(ULONG*)&si->u3=*(ULONG*)&((SPRITEX*)spr)->u3;	// plus pad2

	if( ! (colour & 0xF0000000) )
	{
		*(ULONG*)&si->u1=*(ULONG*)&((SPRITEX*)spr)->u1;	// u1,v1, and tpage info
		*(ULONG*)&si->r0 = colour | (GPU_COM_TF4<<24);
	}
	else
	{
		*(ULONG*)&si->u1=(*(ULONG*)&((SPRITEX*)spr)->u1) | ((colour >> 8) & 0x00600000);
		*(ULONG*)&si->r0 = (colour & 0xffffff) | ((GPU_COM_TF4+2)<<24);
	}

	otptr=(GsOTA *)(PolyList->org+spritez);
//	otptr=(GsOTA*)(PolyList->org+( spritez >> (PolyList->shift) ));

	PUTPACKETINTABLE(si,otptr,POLYTF4_LEN);
	INCPOLYSDRAWN;
	si++;
	GsOUT_PACKET_P=(PACKET*)si;
	return 1;
}


int Print3DSpriteG(SPRITEX *spr,VERT *vect,SHORT scale, unsigned long *colours)
{
	POLY_GT4 *si;
	LONG spritez;

	LONG		width;
	LONG		height;
	LONG distancescale;
	GsOTA 	*otptr;

//	if (TOOMANYPOLYS(4*MAXPACKETSIZE,"Print3DSprite"))return 0;

	si = (POLY_GT4 *) GsOUT_PACKET_P; 


// scary scaling-and-transform-in-one-go code from the Action Man people...
	width = (spr->w);
	gte_SetLDDQB(0);			// clear offset control reg (C2_DQB)
	gte_ldv0(vect)	;//vert);
	gte_SetLDDQA(width);		// shove sprite width into control reg (C2_DQA)
	gte_rtps();				// do the rtps
	gte_stsxy(&si->x0);	//scrxy);		// get screen x and y
	gte_stszotz(&spritez);	//depth);		// get order table z
// end of scaling-and-transform


// tbd - make this ditch according to on-screen SIZE
// limit to "max poly depth", and we can ditch the "MAXDEPTH" "and" below...

	if(spritez < 20) return 0;
//	if (spritez>1000)return 0; //about half the length of atlantis1


	if(spritez > lscapeFogStartZ>>2)
		return 0;
	if(spritez > MAXOTZ)
		spritez = MAXOTZ-50;



	gte_stopz(&distancescale);		// get scaled width of sprite
	distancescale >>= 16;

	width = (distancescale * scale) >> 8;

	if(width < 3)
		return 0;	// better max-distance check

 	si->x1=si->x3=si->x0+width;
 	si->x0=si->x2=si->x0-width;
   	if (si->x1<-256) return 0;
   	if (si->x0>256) return 0;

	if(spr->w == spr->h)
		height = width;	//(distancescale * scale) >> 8;
	else
		height = width * spr->h / spr->w;

	si->y2=si->y3=si->y0+height;
	si->y1=si->y0=si->y0-height;
   	if (si->y2< -128) return 0;
   	if (si->y0> 128) return 0;


	*(ULONG*)&si->u0=*(ULONG*)&((SPRITEX*)spr)->u0;	// u0,v0, and clut info
	*(ULONG*)&si->u2=*(ULONG*)&((SPRITEX*)spr)->u2;	// plus pad1
	*(ULONG*)&si->u3=*(ULONG*)&((SPRITEX*)spr)->u3;	// plus pad2

	if( ! (colours[0] & 0xF0000000) )
	{
		*(ULONG*)&si->u1=*(ULONG*)&((SPRITEX*)spr)->u1;	// u1,v1, and tpage info
		*(ULONG*)&si->r0 = colours[0] | (GPU_COM_TG4<<24);
	}
	else
	{
		*(ULONG*)&si->u1=(*(ULONG*)&((SPRITEX*)spr)->u1) | ((colours[0] >> 8) & 0x00600000);
		*(ULONG*)&si->r0 = (colours[0] & 0xffffff) | ((GPU_COM_TG4+2)<<24);
	}
	*(ULONG*)&si->r1 = colours[1];
	*(ULONG*)&si->r2 = colours[2];
	*(ULONG*)&si->r3 = colours[3];

	otptr=(GsOTA *)(PolyList->org+spritez);
//	otptr=(GsOTA*)(PolyList->org+( spritez >> (PolyList->shift) ));

	PUTPACKETINTABLE(si,otptr,POLYTG4_LEN);
	INCPOLYSDRAWN;
	si++;
	GsOUT_PACKET_P=(PACKET*)si;
	return 1;
}

// high word of colour = alpha value
// note - alpha is used purely to damp down the screen values
// the texture value isn't damped down here.
int Print3DAlphaSprite(SPRITEX *spr,VERT *vect,SHORT scale, unsigned long colour)
{
	POLY_FT4 *si;
	LONG spritez;

	LONG		width;
	LONG		height;
	LONG distancescale;
	GsOTA 	*otptr;
//	int r,g,b,alp;
	int alp;

//	if (TOOMANYPOLYS(4*MAXPACKETSIZE,"Print3DSprite"))return 0;

//	ASSERT(spr->flags & NCOLOURKEY);

	si = (POLY_FT4 *) GsOUT_PACKET_P; 


// scary scaling-and-transform-in-one-go code from the Action Man people...
	width = (spr->w);
	gte_SetLDDQB(0);			// clear offset control reg (C2_DQB)
	gte_ldv0(vect)	;//vert);
	gte_SetLDDQA(width);		// shove sprite width into control reg (C2_DQA)
	gte_rtps();				// do the rtps
	gte_stsxy(&si->x0);	//scrxy);		// get screen x and y
	gte_stszotz(&spritez);	//depth);		// get order table z
// end of scaling-and-transform


// tbd - make this ditch according to on-screen SIZE
// limit to "max poly depth", and we can ditch the "MAXDEPTH" "and" below...

	if(spritez < 20) return 0;
//	if (spritez>1000)return 0; //about half the length of atlantis1


	if(spritez > lscapeFogStartZ>>2)
		return 0;
	if(spritez > MAXOTZ)
		spritez = MAXOTZ-50;



	gte_stopz(&distancescale);		// get scaled width of sprite
	distancescale >>= 16;

	width = (distancescale * scale) >> 8;

	if(width < 3)
		return 0;	// better max-distance check

 	si->x1=si->x3=si->x0+width;
 	si->x0=si->x2=si->x0-width;
   	if (si->x1<-256) return 0;
   	if (si->x0>256) return 0;

	if(spr->w == spr->h)
		height = width;	//(distancescale * scale) >> 8;
	else
		height = width * spr->h / spr->w;

	si->y2=si->y3=si->y0+height;
	si->y1=si->y0=si->y0-height;
   	if (si->y2< -128) return 0;
   	if (si->y0> 128) return 0;



	alp = (colour>>24) & 0xff;
//	r = (colour    ) & 0xff;
//	g = (colour>> 8) & 0xff;
//	b = (colour>>16) & 0xff;
//	r = (r * alp) >> 8;
//	g = (g * alp) >> 8;
//	b = (b * alp) >> 8;


	*(ULONG*)&si->u0=*(ULONG*)&((SPRITEX*)spr)->u0;	// u0,v0, and clut info
	*(ULONG*)&si->u2=*(ULONG*)&((SPRITEX*)spr)->u2;	// plus pad1
	*(ULONG*)&si->u3=*(ULONG*)&((SPRITEX*)spr)->u3;	// plus pad2
	*(ULONG*)&si->u1=(*(ULONG*)&((SPRITEX*)spr)->u1) | ((SEMITRANS_ADD-1) << (16+5));

	*(ULONG*)&si->r0 = (colour & 0xffffff) | ((GPU_COM_TF4+2)<<24);
//	*(ULONG*)&si->r0 = (r) | (g<<8) | (b<<16) | ((GPU_COM_TF4+2)<<24);

	otptr=(GsOTA *)(PolyList->org+spritez);
//	otptr=(GsOTA*)(PolyList->org+( spritez >> (PolyList->shift) ));

	PUTPACKETINTABLE(si,otptr,POLYTF4_LEN);
	INCPOLYSDRAWN;


	si[1] = si[0];
	si++;

	si->r0=alp;
	si->g0=alp;
	si->b0=alp;
	si->tpage = spr->tpage |((SEMITRANS_SUB-1)<<5);

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

	si++;

	GsOUT_PACKET_P=(PACKET*)si;
	return 1;
}






// let's assume xz-flat alignment for now...
void Draw_RawShadow(SVECTOR *vec, LONG radius, ULONG colour, LONG spritezn)
{
	LONG spritez[4];
//	LONG spritezn;
	VERT vect[4];
	POLY_FT4 *si;
	GsOTA 	*otptr;

	if (TOOMANYPOLYS(4*MAXPACKETSIZE,"Draw_RawShadow"))return;
// 0 1
// 2 3

	vect[0].vx = vec->vx - radius;
	vect[0].vz = vec->vz - radius;
	vect[1].vx = vec->vx - radius;
	vect[1].vz = vec->vz + radius;

	vect[2].vx = vec->vx + radius;
	vect[2].vz = vec->vz - radius;
	vect[3].vx = vec->vx + radius;
	vect[3].vz = vec->vz + radius;

	vect[0].vy = vect[1].vy = vect[2].vy = vect[3].vy = vec->vy;

	si = (POLY_FT4 *) GsOUT_PACKET_P;

// 	*(ULONG*)&si->r0=sprctrl.r|(sprctrl.g<<8)|(sprctrl.b<<16)|(GPU_COM_TF4<<24);
 	*(ULONG*)&si->r0=colour|(GPU_COM_TF4<<24);

	*(ULONG*)&si->u0=*(ULONG*)&(shadbase)->u0;
	*(ULONG*)&si->u1=*(ULONG*)&(shadbase)->u1;
	*(ULONG*)&si->u2=*(ULONG*)&(shadbase)->u2;
	*(ULONG*)&si->u3=*(ULONG*)&(shadbase)->u3;


	gte_ldv3c(&vect[0].vx);
	gte_rtpt();
	gte_stsxy3_ft4((ULONG*)si);
	gte_stsz3c(&spritez[0]);
	
	gte_ldv0(&vect[3].vx);
	gte_rtps();
	gte_stsxy(&si->x3);
	gte_stsz(&spritez[3]);

	if(spritezn == -1)
	{
		spritezn = spritez[0];
		if(spritez[1]<spritezn) spritezn = spritez[1];
		if(spritez[2]<spritezn) spritezn = spritez[2];
		if(spritez[3]<spritezn) spritezn = spritez[3];
		spritezn >>= 2;
//	spritezn -= 1;	// 16's ok...? as is 12, 8
	}
	si->clut = shadbase->clut;
	si->tpage = shadbase->tpage|((SEMITRANS_SUB-1)<<5);
	si->code=GPU_COM_TF4+2;

	if(spritezn > 1024 * radius / 5)
	{
//		DB("beyond 1023*r/5... spritezn = %d, r = %d\n",spritezn,radius);
		return;
	}
	if(spritezn > MAXOTZ)
	{
//		DB("beyond otz\n");

		return;
	}

	if(spritezn < 0)
		return;

// shadows need to be plotted after the lscape they're on, but before the object they're the shadow of
// (flying objects, where things can go between the obj & its shadow, complicate matters somewhat)

	//otptr=(GsOTA*)(PolyList->org+( (spritezn & MAXDEPTH) >> (PolyList->shift) ));
	otptr=(GsOTA*)(PolyList->org+spritezn);

	PUTPACKETINTABLE(si,otptr,POLYTF4_LEN);

	INCPOLYSDRAWN;
	si++;							//incr. packet building address by sizeof POLY_FT4
	GsOUT_PACKET_P=(PACKET*)si;		 	//return new packet building address
}
