
// Custom_Dyn
// The non-optimal general case psi-plotter. Includes the object-not-skinned version
// Removed from islpsi.c, because we're using "*4, possibly cached" vertex numbers

#include "global.h"
#include "custom.h"


#ifndef _WINDOWS


#define GETX(n)( ((SHORTXY *)( (int)(tfv) +(n) ))->x )
#define GETY(n)( ((SHORTXY *)( (int)(tfv) +(n) ))->y )
#define GETV(n)(  *(u_long *)( (int)(tfv) +(n) ) )
#define GETD(n)(  *(u_long *)( (int)(tfd) +(n) ) )
#define GETN(n)( ((VERT *)( (int)(tfn) +(n<<1) )) )



void customPsiDrawSortedPrimitives_Full(int depth,long *tfv)
{
	register PACKET*		packet = currentDisplayPage->primPtr;
//	register long			*tfv = transformedVertices;
	VERT 					*tfn = transformedNormals;
	register TMD_P_GT4I		*opcd;
	int						primsleft;
	ULONG					*sorts = sortedIndex;
	register long			t1;
	register long			t2;
	unsigned long *ot = currentDisplayPage->ot+depth;
	int						gteH;
	PSIMODELCTRL	*modctrl = &PSImodelctrl;
	int lightmode = modctrl->lighting;

	gte_ReadGeomScreen(&gteH);

	opcd = 0;
 
	for(primsleft = sortCount; primsleft; primsleft--)
	{

		while(opcd==0)
		{
			(int)opcd = *(sorts++);
		}

		switch (opcd->cd & (0xff-2))
		{

/*-----------------------------------------------------------------------------------------------------------------*/
// Was rmvd
#define si ((POLY_FT3*)packet)
#define op ((TMD_P_FT3I*)opcd)

			case GPU_COM_TF3:
				INCPOLYCOUNT(MODEL_POLYS);

#ifdef _WINDOWS
				BEGINPRIM(si, POLY_FT3);
#else
				addPrimLen(ot,si,FT3_PRIMLEN,t1);
#endif

				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices
			
//				*(u_long *)  (&si->u0) = *(u_long *) (&op->tu0);		// Texture coords
//				*(u_long *)  (&si->u1) = *(u_long *) (&op->tu1);

				t1 = *(u_long *) (&op->tu0);
				t2 = *(u_long *) (&op->tu1);
				*(u_long *)  (&si->u0) = t1;
				*(u_long *)  (&si->u1) = t2;
				
				*(u_long *)  (&si->u2) = *(u_long *) (&op->tu2);

				
				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb(&op->r0);
						gte_ldv0(GETN(op->v0));
						gte_nccs();
						gte_strgb(&si->r0);
						break;
					case DIRECTIONONLY:
						gte_ldv0(GETN(op->v0));
						gte_ncs();
						gte_strgb(&si->r0);
						break;
					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *) (&si->r0) = *(u_long *) (&op->r0);
		 		}

#ifdef _WINDOWS
			ENDPRIM(si, depth, POLY_FT3);
#endif


				si->code = op->cd;
				op = op->next;
				si++;
				break;
#undef si
#undef op

/*-----------------------------------------------------------------------------------------------------------------*/
// Was rmvd
#define si ((POLY_FT4*)packet)
#define op ((TMD_P_FT4I*)opcd)
				
				case GPU_COM_TF4:
				INCPOLYCOUNT(MODEL_POLYS);

#ifdef _WINDOWS
				BEGINPRIM(si, POLY_FT4);
#else
				addPrimLen(ot,si,FT4_PRIMLEN,t1);
#endif
   			
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices

				t1 = *(u_long *) (&op->tu0);
				t2 = *(u_long *) (&op->tu1);
				*(u_long *)  (&si->u0) = t1;
				*(u_long *)  (&si->u1) = t2;
				
//				*(u_long *)  (&si->u0) = *(u_long *) (&op->tu0);		// Texture coords
//				*(u_long *)  (&si->u1) = *(u_long *) (&op->tu1);

				gte_stsxy3_ft4(si);

				*(u_long *)  (&si->x3) = *(u_long *) (&GETV(op->v3));
				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb(&op->r0);
						gte_ldv0(GETN(op->v0));
						gte_nccs();			
						gte_strgb(&si->r0);
						break;
					case DIRECTIONONLY:
						gte_ldv0(GETN(op->v0));
						gte_ncs();			
						gte_strgb(&si->r0);
						break;
					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *) (&si->r0) = *(u_long *) (&op->r0);		// 9 cycles here
				}
				*(u_long *)  (&si->u2) = *(u_long *) (&op->tu2);
				*(u_long *)  (&si->u3) = *(u_long *) (&op->tu3);

				setPolyFT4(si);
				si->code = op->cd;

#ifdef _WINDOWS
			ENDPRIM(si, depth, POLY_FT4);
#endif
				op = op->next;
				si++;
				break;
#undef si
#undef op

/*-----------------------------------------------------------------------------------------------------------------*/
// Okay, I've been optimising the GT3 to hell & gone...
// (The others, I'll do if & when we need 'em)
#define si ((POLY_GT3*)packet)
#define op ((TMD_P_GT3I*)opcd)

			case GPU_COM_TG3:
				INCPOLYCOUNT(MODEL_POLYS);
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices
				
				t1 = *(u_long *) (&op->tu0);
				gte_stsxy3_gt3(si);	// 3 swc2's
				t2 = *(u_long *) (&op->tu1);

				*(u_long *)  (&si->u0) = t1;
				*(u_long *)  (&si->u1) = t2;

#ifdef _WINDOWS
				BEGINPRIM(si, POLY_GT3);
#else
				addPrimLen(ot,si,GT3_PRIMLEN,t2);
#endif

				t1 = *(u_long *) (&op->tu2);

				*(u_long *)  (&si->u2) = t1;


				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb3(&op->r0, &op->r1, &op->r2);
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_ncct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						break;
					case DIRECTIONONLY:
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_nct();			
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						break;
					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r1) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r2) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *)  (&si->r0) = *(u_long *) (&op->r0);
						*(u_long *)  (&si->r1) = *(u_long *) (&op->r1);
						*(u_long *)  (&si->r2) = *(u_long *) (&op->r2);
				}
				si->code = op->cd;	// top bit of rgb0
				op = op->next;

#ifdef _WINDOWS
			ENDPRIM(si, depth, POLY_GT3);
#endif
				si++;

				break;
#undef si
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/

#define si ((POLY_GT4*)packet)
#define op opcd

			case GPU_COM_TG4:
				INCPOLYCOUNT(MODEL_POLYS);

#ifdef _WINDOWS
				BEGINPRIM(si, POLY_GT4);
#else
				addPrimLen(ot,si,GT4_PRIMLEN,t1);
#endif

				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices

				t1 = *(u_long *) (&op->tu0);
				t2 = *(u_long *) (&op->tu1);
				*(u_long *)  (&si->u0) = t1;
				*(u_long *)  (&si->u1) = t2;
					
				gte_stsxy3_gt4(si);

				t1 = *(u_long *) (&op->tu2);
				t2 = *(u_long *) (&op->tu3);
				*(u_long *)  (&si->u2) = t1;
				*(u_long *)  (&si->u3) = t2;
										
				*(u_long *)  (&si->x3) = *(u_long *) (&GETV(op->v3));
				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb3(&op->r0, &op->r1, &op->r2);
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_ncct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);

						gte_ldrgb(&op->r3);
						gte_ldv0(GETN(op->v3));
						gte_nccs();			// NormalColorCol
						gte_strgb(&si->r3);
						break;
					case DIRECTIONONLY:
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_nct();			
						gte_strgb3(&si->r0, &si->r1, &si->r2);

						gte_ldv0(GETN(op->v3));
						gte_ncs();			// NormalColorCol
						gte_strgb(&si->r3);
						break;
					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r1) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r2) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r3) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *)  (&si->r0) = *(u_long *) (&op->r0);
						*(u_long *)  (&si->r1) = *(u_long *) (&op->r1);
						*(u_long *)  (&si->r2) = *(u_long *) (&op->r2);
						*(u_long *)  (&si->r3) = *(u_long *) (&op->r3);
				}


				si->code = op->cd;
				(int)op = op->next;
#ifdef _WINDOWS
			ENDPRIM(si, depth, POLY_GT4);
#endif
				si++;
				break;

#undef si
#undef op

/*-----------------------------------------------------------------------------------------------------------------*/
// was rmvd
#define si ((POLY_FT4*)packet)
#define op ((TMD_P_FT4I*)opcd)

			case GPU_COM_TF4SPR :
				INCPOLYCOUNT(MODEL_POLYS);
				{
/*
				int			width, height;





				BEGINPRIM(si, POLY_FT4);

//	We can't use the "quick" scaling method in skinned objects, since we don't know which
//	bone the sprite is attached to, hence we can't rtps the vertex and get the scaled width/height,
//	so we have to do the scaling based on the distance ourselves.

				width = ((op->v2 * gteH) / tfd[op->v0]) / 2;
				height = ((op->v3 * gteH) / tfd[op->v0]) / 4;













 				*(u_long *)&si->r0 = *(u_long *)&op->r0;			// Texture coords / colors
				*(u_long *)&si->u0 = *(u_long *)&op->tu0;
				*(u_long *)&si->u1 = *(u_long *)&op->tu1;
				*(u_long *)&si->u2 = *(u_long *)&op->tu2;
				*(u_long *)&si->u3 = *(u_long *)&op->tu3;

				si->x1 = si->x3 = ((DVECTOR *)tfv)[op->v0].vx + width;
				si->x0 = si->x2 = ((DVECTOR *)tfv)[op->v0].vx - width;
				si->y2 = si->y3 = ((DVECTOR *)tfv)[op->v0].vy + height;
				si->y0 = si->y1 = ((DVECTOR *)tfv)[op->v0].vy - height;
				


				setPolyFT4(si);

				si->code = op->cd | modctrl->semitrans;

 				ENDPRIM(si, depth, POLY_FT4);
				op = op->next;
				}
*/


			}
//			si++;
			break;

#undef si
#undef op

/*-----------------------------------------------------------------------------------------------------------------*/
// was rmvd
#define si ((POLY_G4*)packet)
#define op ((TMD_P_FG4I*)opcd)
			case GPU_COM_G4:
			case GPU_COM_F4:
				INCPOLYCOUNT(MODEL_POLYS);

#ifdef _WINDOWS
				BEGINPRIM(si, POLY_G3);
#else
				addPrimLen(ot,si,G4_PRIMLEN,t1);
#endif
   			
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices

				*(u_long *)  (&si->x3) = *(u_long *) (&GETV(op->v3));
 
				
				gte_stsxy3_g4(si);

				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb3(&op->r0, &op->r1, &op->r2);
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_ncct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						
						gte_ldrgb(&op->r3);
						gte_ldv0(GETN(op->v3));
						gte_nccs();			// NormalColorCol
						gte_strgb(&si->r3);
						break;
					case DIRECTIONONLY:
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_nct();			
						gte_strgb3(&si->r0, &si->r1, &si->r2);

						gte_ldv0(GETN(op->v3));
						gte_ncs();			// NormalColorCol
						gte_strgb(&si->r3);
						break;

					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r1) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r2) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r3) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *)  (&si->r0) = *(u_long *) (&op->r0);
						*(u_long *)  (&si->r1) = *(u_long *) (&op->r1);
						*(u_long *)  (&si->r2) = *(u_long *) (&op->r2);
						*(u_long *)  (&si->r3) = *(u_long *) (&op->r3);
				}
				setPolyG4(si);
				si->code = op->cd;
#ifdef _WINDOWS
			ENDPRIM(si, depth, POLY_G4);
#endif
				op = op->next;
				si++;
				break;
#undef si
#undef op

/*-----------------------------------------------------------------------------------------------------------------*/

// At the moment, Ginger's crest is untextured
// (ummm, why?)
#define si ((POLY_G3*)packet)
#define op ((TMD_P_FG3I*)opcd)
			
			case GPU_COM_G3:
			case GPU_COM_F3:

				INCPOLYCOUNT(MODEL_POLYS);

				addPrimLen(ot,si,G3_PRIMLEN,t1);
 			
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices

//				*(u_long *)  (&si->r0) = *(u_long *) (&op->r0);
				t1 = *((u_long *) (&op->r0));
				
				gte_stsxy3_g3(si);


				*(u_long *)  (&si->r0) = t1;

				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb3(&op->r0, &op->r1, &op->r2);
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_ncct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						break;
					case DIRECTIONONLY:
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_nct();			
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						break;
					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r1) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r2) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *)  (&si->r1) = *(u_long *) (&op->r1);
						*(u_long *)  (&si->r2) = *(u_long *) (&op->r2);
				}

				setPolyG3(si);
				si->code = op->cd;
#ifdef _WINDOWS
			ENDPRIM(si, depth, POLY_G3);
#endif
				op = op->next;
				si++;
				break;
#undef si
#undef op

/*-----------------------------------------------------------------------------------------------------------------*/
		default:
			printf("prim %d\n",opcd->cd);
			break;
		}
	}
	currentDisplayPage->primPtr = packet;
}




/**************************************************************************
	FUNCTION:	PSIDrawPrimitives
	PURPOSE:	add list of polys into ot
	PARAMETERS:	ot (at depth)
	RETURNS:	
**************************************************************************/

void psiDrawPrimitives_NOT_THIS_ONE(int depth,long *tfv, long *tfd)
{
	register PACKET*		packet;
//	register long *tfv = transformedVertices;
//	register long *tfd = transformedDepths;
	register TMD_P_GT4I	*opcd;
	long	 clipflag;
	PSIMODELCTRL	*modctrl = &PSImodelctrl;
	VERT	*vp = modctrl->VertTop;
	int prims,primsleft,lightmode;
	USHORT *sorts;
	VERT 	*tfn = transformedNormals;
	int		gteH;
	
	gte_ReadGeomScreen(&gteH);





	prims = (int)modctrl->PrimTop;
	sorts = modctrl->SortOffs;
	primsleft = modctrl->PrimLeft;
	lightmode = modctrl->lighting;

	while(primsleft)
	{
		
		opcd = (TMD_P_GT4I*)( prims + (*sorts++<<3) );
		switch (opcd->cd & (0xff-2))
		{
/*-----------------------------------------------------------------------------------------------------------------*/
#define si ((POLY_FT3*)packet)
#define op ((TMD_P_FT3I*)opcd)
		case GPU_COM_TF3:
			INCPOLYCOUNT(MODEL_POLYS);
			if((GETD(op->v2) > modctrl->nearclip) && (GETD(op->v2) < modctrl->farclip))
			{
				BEGINPRIM(si, POLY_FT3);

				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices
			
				*(u_long *)  (&si->u0) = *(u_long *) (&op->tu0);		// Texture coords
			
				gte_nclip_b();	// takes 8 cycles


				*(u_long *)  (&si->u2) = *(u_long *) (&op->tu2);

	 			gte_stopz(&clipflag);
			
				if ( !(op->dummy & psiDOUBLESIDED) && (clipflag >= 0) )
					break;									// Back face culling

				*(u_long *)  (&si->u1) = *(u_long *) (&op->tu1);
				gte_stsxy3_ft3(si);
			
				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb(&op->r0);
						gte_ldv0(GETN(op->v0));
						gte_nccs();			
						gte_strgb(&si->r0);
						break;
					case DIRECTIONONLY:
						gte_ldv0(GETN(op->v0));
						gte_ncs();			
						gte_strgb(&si->r0);
						break;

					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *) (&si->r0) = *(u_long *) (&op->r0);		// 9 cycles here
		 		}
				setPolyFT3(si);
				si->code = op->cd | modctrl->semitrans;

 				ENDPRIM(si, depth & 1023, POLY_FT3);
				modctrl->polysdrawn++;
			}
			break;
#undef si
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
#define si ((POLY_FT4*)packet)
#define op ((TMD_P_FT4I*)opcd)
		case GPU_COM_TF4:
			INCPOLYCOUNT(MODEL_POLYS);
			if((GETD(op->v2) > modctrl->nearclip) && (GETD(op->v2) < modctrl->farclip))
			{
				BEGINPRIM(si, POLY_FT4);
   			
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices
			
				*(u_long *)  (&si->u0) = *(u_long *) (&op->tu0);		// Texture coords

				gte_nclip_b();	// takes 8 cycles
		
				*(u_long *)  (&si->u1) = *(u_long *) (&op->tu1);

				gte_stopz(&clipflag);

				if ( !(op->dummy & psiDOUBLESIDED) && (clipflag >= 0) )
					break;	// Back face culling
				
				gte_stsxy3_ft4(si);

				*(u_long *)  (&si->x3) = *(u_long *) (&GETV(op->v3));

				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb(&op->r0);
						gte_ldv0(GETN(op->v0));
						gte_nccs();			
						gte_strgb(&si->r0);
						break;
					case DIRECTIONONLY:
						gte_ldv0(GETN(op->v0));
						gte_ncs();			
						gte_strgb(&si->r0);
						break;
					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *) (&si->r0) = *(u_long *) (&op->r0);		// 9 cycles here
				}
				*(u_long *)  (&si->u2) = *(u_long *) (&op->tu2);
				*(u_long *)  (&si->u3) = *(u_long *) (&op->tu3);

				setPolyFT4(si);
				si->code = op->cd | modctrl->semitrans;
				
				modctrl->polysdrawn++;
 			
 				ENDPRIM(si, depth & 1023, POLY_FT4);
			}
			break;
#undef si
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
#define si ((POLY_GT3*)packet)
#define op ((TMD_P_GT3I*)opcd)
		case GPU_COM_TG3:
			INCPOLYCOUNT(MODEL_POLYS);
			if((GETD(op->v2) > modctrl->nearclip) && (GETD(op->v2) < modctrl->farclip))	
			{
				BEGINPRIM(si, POLY_GT3);

				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices
				
				*(u_long *)  (&si->u0) = *(u_long *) (&op->tu0);		// Texture coords

				gte_nclip_b();	// takes 8 cycles
				
				*(u_long *)  (&si->u2) = *(u_long *) (&op->tu2);
					
				gte_stopz(&clipflag);
				
				if (!(op->dummy & psiDOUBLESIDED) && (clipflag >= 0) )
					break;								// Back face culling

				gte_stsxy3_gt3(si);
			

				*(u_long *)  (&si->u1) = *(u_long *) (&op->tu1);

				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb3(&op->r0, &op->r1, &op->r2);
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_ncct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						break;
					case DIRECTIONONLY:
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_nct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						break;
					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r1) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r2) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *)  (&si->r0) = *(u_long *) (&op->r0);
						*(u_long *)  (&si->r1) = *(u_long *) (&op->r1);
						*(u_long *)  (&si->r2) = *(u_long *) (&op->r2);
				}
				setPolyGT3(si);
				si->code = op->cd | modctrl->semitrans;
			
				modctrl->polysdrawn++;

				ENDPRIM(si, depth & 1023, POLY_GT3);
			}
			break;
 		
#undef si
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
#define si ((POLY_GT4*)packet)
#define op opcd
		case GPU_COM_TG4:
			INCPOLYCOUNT(MODEL_POLYS);
			if((GETD(op->v2) > modctrl->nearclip) && (GETD(op->v2) < modctrl->farclip))
			{
				BEGINPRIM(si, POLY_GT4);

				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices
				
				*(u_long *)  (&si->u0) = *(u_long *) (&op->tu0);		// Texture coords
			
				gte_nclip_b();	// takes 8 cycles
		
				*(u_long *)  (&si->u1) = *(u_long *) (&op->tu1);
					
				gte_stopz(&clipflag);
				
				if (!(op->dummy & psiDOUBLESIDED) && (clipflag >= 0) ) break;			// Back face culling

				gte_stsxy3_gt4(si);
				
						
				*(u_long *)  (&si->u2) = *(u_long *) (&op->tu2);
				*(u_long *)  (&si->u3) = *(u_long *) (&op->tu3);


				*(u_long *)  (&si->x3) = *(u_long *) (&GETV(op->v3));
		
		
				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb3(&op->r0, &op->r1, &op->r2);
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_ncct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						
						gte_ldrgb(&op->r3);
						gte_ldv0(GETN(op->v3));
						gte_nccs();			// NormalColorCol
						gte_strgb(&si->r3);
						break;
					case DIRECTIONONLY:
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_nct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);

						gte_ldv0(GETN(op->v3));
						gte_ncs();			
						gte_strgb(&si->r3);
						break;
					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r1) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r2) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r3) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *)  (&si->r0) = *(u_long *) (&op->r0);
						*(u_long *)  (&si->r1) = *(u_long *) (&op->r1);
						*(u_long *)  (&si->r2) = *(u_long *) (&op->r2);
						*(u_long *)  (&si->r3) = *(u_long *) (&op->r3);
				}
		
				modctrl->polysdrawn++;
			
				setPolyGT4(si);
				si->code = op->cd | modctrl->semitrans;
				ENDPRIM(si, depth & 1023, POLY_GT4);
			}
			break;
#undef si
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
#define si ((POLY_FT4*)packet)
#define op ((TMD_P_FT4I*)opcd)
		case GPU_COM_TF4SPR :
			INCPOLYCOUNT(MODEL_POLYS);
			if((GETD(op->v0) > modctrl->nearclip) && (GETD(op->v0) < modctrl->farclip))
			{
				int			width, height;

				BEGINPRIM(si, POLY_FT4);
/*
	We can't use the "quick" scaling method in skinned objects, since we don't know which
	bone the sprite is attached to, hence we can't rtps the vertex and get the scaled width/height,
	so we have to do the scaling based on the distance ourselves.
*/
				width = ((op->v2 * gteH) / GETD(op->v0)) / 2;
				height = ((op->v3 * gteH) / GETD(op->v0)) / 4;

 				*(u_long *)&si->r0 = *(u_long *)&op->r0;			// Texture coords / colors
				*(u_long *)&si->u0 = *(u_long *)&op->tu0;
				*(u_long *)&si->u1 = *(u_long *)&op->tu1;
				*(u_long *)&si->u2 = *(u_long *)&op->tu2;
				*(u_long *)&si->u3 = *(u_long *)&op->tu3;

				si->x1 = si->x3 = ((DVECTOR *)tfv)[op->v0].vx + width;
				si->x0 = si->x2 = ((DVECTOR *)tfv)[op->v0].vx - width;
				si->y2 = si->y3 = ((DVECTOR *)tfv)[op->v0].vy + height;
				si->y0 = si->y1 = ((DVECTOR *)tfv)[op->v0].vy - height;
				
				setPolyFT4(si);
				si->code = op->cd | modctrl->semitrans;
 				ENDPRIM(si, depth & 1023, POLY_FT4);
			}
			break;
#undef si
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
#define si ((POLY_G4*)packet)
#define op ((TMD_P_FG4I*)opcd)
		case GPU_COM_G4:
		case GPU_COM_F4:
			INCPOLYCOUNT(MODEL_POLYS);
			if((GETD(op->v2) > modctrl->nearclip) && (GETD(op->v2) < modctrl->farclip))
			{
				BEGINPRIM(si, POLY_G4);
   			
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices

				*(u_long *)  (&si->x3) = *(u_long *) (&tfv[op->v3]);
 
 				gte_nclip_b();	// takes 8 cycles
		

				gte_stopz(&clipflag);

				// Back face culling
				if ( !(op->dummy & psiDOUBLESIDED) && (clipflag >= 0) ) break;									// Back face culling
				
				gte_stsxy3_g4(si);


				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb3(&op->r0, &op->r1, &op->r2);
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_ncct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						
						gte_ldrgb(&op->r3);
						gte_ldv0(GETN(op->v3));
						gte_nccs();			// NormalColorCol
						gte_strgb(&si->r3);
						break;
					case DIRECTIONONLY:
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_nct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);

						gte_ldv0(GETN(op->v3));
						gte_ncs();			
						gte_strgb(&si->r3);
						break;
					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r1) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r2) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r3) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *)  (&si->r0) = *(u_long *) (&op->r0);
						*(u_long *)  (&si->r1) = *(u_long *) (&op->r1);
						*(u_long *)  (&si->r2) = *(u_long *) (&op->r2);
						*(u_long *)  (&si->r3) = *(u_long *) (&op->r3);
				}

				setPolyG4(si);
				si->code = op->cd | modctrl->semitrans;

				modctrl->polysdrawn++;

				ENDPRIM(si, depth & 1023, POLY_G4);
			}
			break;
#undef si
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
#define si ((POLY_G3*)packet)
#define op ((TMD_P_FG3I*)opcd)
			
		case GPU_COM_G3:
		case GPU_COM_F3:
			INCPOLYCOUNT(MODEL_POLYS);
			if((GETD(op->v2) > modctrl->nearclip) && (GETD(op->v2) < modctrl->farclip))
			{
				BEGINPRIM(si, POLY_G3);
   			
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices

 
				*(u_long *)  (&si->r0) = *(u_long *) (&op->r0);
 				gte_nclip_b();	// takes 8 cycles
		

				gte_stopz(&clipflag);

	//			if (clipflag >= 0) break; 								// Back face culling
				if ( !(op->dummy & psiDOUBLESIDED) && (clipflag >= 0) ) break;									// Back face culling
				
				gte_stsxy3_g3(si);


				switch (lightmode)
				{
					case DIRECTIONAL:
						gte_ldrgb3(&op->r0, &op->r1, &op->r2);
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_ncct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						break;
					case DIRECTIONONLY:
						gte_ldv3(GETN(op->v0), GETN(op->v1), GETN(op->v2));
						gte_nct();
						gte_strgb3(&si->r0, &si->r1, &si->r2);
						break;
					case COLOURIZE:
						*(u_long *)  (&si->r0) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r1) = *(u_long *) (&modctrl->col);
						*(u_long *)  (&si->r2) = *(u_long *) (&modctrl->col);
						break;
					default:
						*(u_long *)  (&si->r1) = *(u_long *) (&op->r1);
						*(u_long *)  (&si->r2) = *(u_long *) (&op->r2);
				}


				modctrl->polysdrawn++;

				setPolyG3(si);
				si->code = op->cd | modctrl->semitrans;

				ENDPRIM(si, depth & 1023, POLY_G3);
			}
			break;
#undef si
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
			default:
				break;
		}
		primsleft--;
	}
}



#endif