
// 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"
#include "timer.h"


#ifndef _WINDOWS
#ifdef INCLUDE_OLD_VERSION_RENDERER


#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:	
**************************************************************************/
#ifndef DREAMCAST

void psiDrawPrimitives(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--;
	}
}

// Dreamcast, Windows, and old_version_renderer defines
#endif
#endif
#endif


/*-----------------------------------------------------------------------------------------------------------------*/
// A load of stuff copied here because it's only called from the old-version renderer
// (And hence should be kept in the overlay)
/*-----------------------------------------------------------------------------------------------------------------*/

// Multiply all the verts up by four...
// (note that accessing transformed normals will still need a *2)
void customPsiFixupPrims(PSIMODEL *psiModel)
{
	TextureType *sprt;
	int p,a;
	char *primitive;
	UBYTE s;

	//int ix; //temp

	p = psiModel->noofPrims;
	primitive = (char*)psiModel->primOffset;

	while (p)
	{
		
		s = ((TMD_P_GT4I*)primitive)->cd;	// code
		switch (s &(0xff-2))
		{

			case GPU_COM_G3:
			case GPU_COM_F3:	
				a = sizeof(TMD_P_FG3I );
#ifndef _WINDOWS
			 	((TMD_P_FG3I*)primitive)->v0 *= 4;
			 	((TMD_P_FG3I*)primitive)->v1 *= 4;
			 	((TMD_P_FG3I*)primitive)->v2 *= 4;
#endif
				break;

			case GPU_COM_G4:
			case GPU_COM_F4:	
				a = sizeof(TMD_P_FG4I );
#ifndef _WINDOWS
			 	((TMD_P_FG4I*)primitive)->v0 *= 4;
			 	((TMD_P_FG4I*)primitive)->v1 *= 4;
			 	((TMD_P_FG4I*)primitive)->v2 *= 4;
			 	((TMD_P_FG4I*)primitive)->v3 *= 4;
#endif
				break;

			case GPU_COM_TF3:	
				a = sizeof(TMD_P_FT3I );
#ifndef _WINDOWS
			 	((TMD_P_FT3I*)primitive)->v0 *= 4;
			 	((TMD_P_FT3I*)primitive)->v1 *= 4;
			 	((TMD_P_FT3I*)primitive)->v2 *= 4;
#endif
				break;

			case GPU_COM_TF4SPR:
			case GPU_COM_TF4:	
				a = sizeof(TMD_P_FT4I );
#ifndef _WINDOWS
			 	((TMD_P_FT4I*)primitive)->v0 *= 4;
			 	((TMD_P_FT4I*)primitive)->v1 *= 4;
			 	((TMD_P_FT4I*)primitive)->v2 *= 4;
			 	((TMD_P_FT4I*)primitive)->v3 *= 4;
#endif
				break;

			case GPU_COM_TG3:	
				a = sizeof(TMD_P_GT3I );
#ifndef _WINDOWS
			 	((TMD_P_GT3I*)primitive)->dummy &= 1;	// only use the double-sided bit
			 	((TMD_P_GT3I*)primitive)->v0 *= 4;
			 	((TMD_P_GT3I*)primitive)->v1 *= 4;
			 	((TMD_P_GT3I*)primitive)->v2 *= 4;
#endif
				break;

			case GPU_COM_TG4:	
				a = sizeof(TMD_P_GT4I );
#ifndef _WINDOWS
			 	((TMD_P_GT4I*)primitive)->dummy &= 1;	// only use the double-sided bit
			 	((TMD_P_GT4I*)primitive)->v0 *= 4;
			 	((TMD_P_GT4I*)primitive)->v1 *= 4;
			 	((TMD_P_GT4I*)primitive)->v2 *= 4;
			 	((TMD_P_GT4I*)primitive)->v3 *= 4;
#endif
				break;


			default:	
				a = 0;
				utilPrintf("FATAL: don't know that kind of prim...($%x)\n",s);
				
				for (;;);
				break;

		}
		primitive += a;
		p--;
	}
}

#ifndef _WINDOWS
long psiCRCName(char *psiName)
{
	int i,j,slen;
	char str[64];

	utilUpperStr(psiName);
	
	for (i = 0; i < 63; i ++)
	{
		str[i] = psiName[i];
		if ( (psiName[i] == 0) || (psiName[i] == 32) || (psiName[i] == '.') )
			break;
	}
	str[i] = 0;
	slen = i - 1;

	for (i = slen; i >= 0; i --)
	{
		if ( ((str[i] < 'A') || (str[i] > 'Z')) &&
			 ((str[i] < '0') || (str[i] > '9')) )		 break;
	}

	if (i >= 0)
	{
		j = i + 1;
		for (i = 0; i < slen; i ++)
		{
		 str[i] = str[i + j];
		}
	}
	
	return utilStr2CRC(&str[0]);
}
#endif

PSIMODEL *psiCheck(char *psiName)
{
	int i,crc;

	crc = psiCRCName(psiName);

	for (i = 0; i < psiModelListLen; i ++)
	{
		if ( psiModelListCRC[i] == crc )
			return psiModelList[i];
	}

	return NULL;
}


#ifndef _WINDOWS
PSIMODEL *psiLoad(char *psiName)
{
	char *addr;
	//PSIMESH *mesh;
	int lastfilelength;//,i;
	PSIMODEL *psiModel;


	if (sizeof(PSIMODEL) != 192)
		utilPrintf("\nWARNING: PSIMODEL structure length invalid (%d != 192)\n\n",sizeof(PSIMODEL));
	

	psiModel = psiCheck(psiName);		// already loaded ?
	if (psiModel!=NULL)
	{
		//utilPrintf("Already loaded file %s\n",psiName);
		//psiDisplay(psiModel);
		return psiModel;

	}

	PSIname = psiName;

	if (psiModelListLen>=MAXMODELS) 
	{
		utilPrintf("jees ! how many models do you expect me to load ?\n"); 
		return 0; 
	}


	//psiName = psiConstructName(psiName);
	addr = (void *)fileLoad(psiName, &lastfilelength);
	
	psiModel = psiFixup(addr);

	customPsiFixupPrims(psiModel);
	return psiModel;

}
#endif

#ifndef DREAMCAST
void psiFixupPrims(PSIMODEL *psiModel)
{
	TextureType *sprt;
	int p,a;
	char *primitive;
	UBYTE s;

	//int ix; //temp

		p = psiModel->noofPrims;
		primitive = (char*)psiModel->primOffset;

		while (p)
		{
			
			s = ((TMD_P_GT4I*)primitive)->cd;	// code
			switch (s &(0xff-2))
			{

				case GPU_COM_G3:
				case GPU_COM_F3:	
					a = sizeof(TMD_P_FG3I );
			 		((TMD_P_FG3I*)primitive)->in=(sizeof(TMD_P_FG3I)/4)-1;	//ilen
					((TMD_P_FG3I*)primitive)->out=0xc; 						//olen   
					
					if (((TMD_P_FG3I*)primitive)->dummy & psiTRANSPAR )
						((TMD_P_FG3I*)primitive)->cd |=2;
					
					//((TMD_P_FG3I*)primitive)->dummy &= psiDOUBLESIDED; 
					F3count++;							  
					break;

				case GPU_COM_G4:
				case GPU_COM_F4:	
					a = sizeof(TMD_P_FG4I );
					((TMD_P_FG4I*)primitive)->in=(sizeof(TMD_P_FG4I)/4)-1;	//ilen
		 			((TMD_P_FG4I*)primitive)->out=0x8; 						//olen   
					
					if (((TMD_P_FG4I*)primitive)->dummy & psiTRANSPAR )
						((TMD_P_FG4I*)primitive)->cd |=2;
					
					//((TMD_P_FG4I*)primitive)->dummy &= psiDOUBLESIDED; 
					
					F4count++;
					break;

				case GPU_COM_TF3:	
					a = sizeof(TMD_P_FT3I );
					sprt = PageTexture( ((TMD_P_FT3I*)primitive)->clut ); // clut = texture index number
					// I've had to add this for the PC version to avoid crashes..
#ifdef _WINDOWS
					if (!sprt)
						break;
#endif
					
					if (((TMD_P_FT3I*)primitive)->tpage) 
						((TMD_P_FT3I*)primitive)->cd |= 2;
					
					((TMD_P_FT3I*)primitive)->tpage |= sprt->tpage;
					((TMD_P_FT3I*)primitive)->clut = sprt->clut;

					((TMD_P_FT3I*)primitive)->in=(sizeof(TMD_P_FT3I)/4)-1;	//ilen
		 			((TMD_P_FT3I*)primitive)->out=0x7; 						//olen   
					((TMD_P_FT3I*)primitive)->tu0 += sprt->x;
					((TMD_P_FT3I*)primitive)->tu1 += sprt->x;
					((TMD_P_FT3I*)primitive)->tu2 += sprt->x;

					((TMD_P_FT3I*)primitive)->tv0 += sprt->y;
					((TMD_P_FT3I*)primitive)->tv1 += sprt->y;
					((TMD_P_FT3I*)primitive)->tv2 += sprt->y;

					TF3count++;
					//((TMD_P_FG4I*)primitive)->dummy &= psiDOUBLESIDED; 
					break;

				case GPU_COM_TF4SPR:
				case GPU_COM_TF4:	
					a = sizeof(TMD_P_FT4I );
					sprt = PageTexture( ((TMD_P_FT4I*)primitive)->clut ); // clut= texture index number
					// I've had to add this for the PC version to avoid crashes..
#ifdef _WINDOWS
					if (!sprt)
						break;
#endif

					if (((TMD_P_FT4I*)primitive)->tpage) 
						((TMD_P_FT4I*)primitive)->cd |= 2;
						
					((TMD_P_FT4I*)primitive)->tpage |= sprt->tpage;
					((TMD_P_FT4I*)primitive)->clut = sprt->clut;

					((TMD_P_FT4I*)primitive)->in=(sizeof(TMD_P_FT4I)/4)-1;	//ilen
		 			((TMD_P_FT4I*)primitive)->out=0x9; 						//olen   

					((TMD_P_FT4I*)primitive)->tu0 += sprt->x;
					((TMD_P_FT4I*)primitive)->tu1 += sprt->x;
					((TMD_P_FT4I*)primitive)->tu2 += sprt->x;
					((TMD_P_FT4I*)primitive)->tu3 += sprt->x;

					((TMD_P_FT4I*)primitive)->tv0 += sprt->y;
					((TMD_P_FT4I*)primitive)->tv1 += sprt->y;
					((TMD_P_FT4I*)primitive)->tv2 += sprt->y;
					((TMD_P_FT4I*)primitive)->tv3 += sprt->y;

					TF4count++;
					//((TMD_P_FG4I*)primitive)->dummy &= psiDOUBLESIDED; 
					break;

				case GPU_COM_TG3:	
					a = sizeof(TMD_P_GT3I );
					sprt = PageTexture( ((TMD_P_GT3I*)primitive)->clut ); // clut= texture index number


					// I've had to add this for the PC version to avoid crashes..
#ifdef _WINDOWS
					if (!sprt)
						break;
#endif
					
					if (((TMD_P_GT3I*)primitive)->tpage) 
						((TMD_P_GT3I*)primitive)->cd |= 2;
									
					((TMD_P_GT3I*)primitive)->tpage |= sprt->tpage;
					((TMD_P_GT3I*)primitive)->clut = sprt->clut;

					((TMD_P_GT3I*)primitive)->in=(sizeof(TMD_P_GT3I)/4)-1;	//ilen
		 			((TMD_P_GT3I*)primitive)->out=0x9; 						//olen   

					((TMD_P_GT3I*)primitive)->tu0 += sprt->x;
					((TMD_P_GT3I*)primitive)->tu1 += sprt->x;
					((TMD_P_GT3I*)primitive)->tu2 += sprt->x;

					((TMD_P_GT3I*)primitive)->tv0 += sprt->y;
					((TMD_P_GT3I*)primitive)->tv1 += sprt->y;
					((TMD_P_GT3I*)primitive)->tv2 += sprt->y;

					TG3count++;
					break;

				case GPU_COM_TG4:	
					a = sizeof(TMD_P_GT4I );
					sprt = PageTexture( ((TMD_P_GT4I*)primitive)->clut ); // clut= texture index number
					// I've had to add this for the PC version to avoid crashes..
#ifdef _WINDOWS
					if (!sprt)
						break;
#endif

					if (((TMD_P_GT4I*)primitive)->tpage) 
						((TMD_P_GT4I*)primitive)->cd |= 2;
						
					((TMD_P_GT4I*)primitive)->tpage |= sprt->tpage;
					((TMD_P_GT4I*)primitive)->clut = sprt->clut;

					((TMD_P_GT4I*)primitive)->in=(sizeof(TMD_P_GT4I)/4)-1;	//ilen
		 			((TMD_P_GT4I*)primitive)->out=0xc; 						//olen   

					((TMD_P_GT4I*)primitive)->tu0 += sprt->x;
					((TMD_P_GT4I*)primitive)->tu1 += sprt->x;
					((TMD_P_GT4I*)primitive)->tu2 += sprt->x;
					((TMD_P_GT4I*)primitive)->tu3 += sprt->x;

					((TMD_P_GT4I*)primitive)->tv0 += sprt->y;
					((TMD_P_GT4I*)primitive)->tv1 += sprt->y;
					((TMD_P_GT4I*)primitive)->tv2 += sprt->y;
					((TMD_P_GT4I*)primitive)->tv3 += sprt->y;
									
					TG4count++;

					break;


				default:	
					a = 0;
					utilPrintf("FATAL: don't know that kind of prim...($%x)\n",s);
					
					for (;;);
					break;

			}
			primitive += a;
			p--;
		}
}
#endif


#ifndef DREAMCAST


/**************************************************************************
	FUNCTION:	PSISortPrims
	PURPOSE:	create link list table for model's polys
	PARAMETERS:	
	RETURNS:	
**************************************************************************/

// If this rou's running out of registers, it may be worth
// allocating ourselves some scratchpad space
#ifndef _WINDOWS
void customPsiSortPrimitives(long *tfv, long *tfd)
{
#ifndef DREAMCAST

#ifndef _WINDOWS
	register long clipflag asm("$20");
#else
	register long clipflag;
#endif
//	register long *tfd asm("$19");
//	register long *tfv  asm("$18");
	register TMD_P_GT4I	*opcd;
	int				*sl;
	int localSortCount;

	long deep;
	int primsleft;
	int localMinDepth = minDepth;

	clipflag = 0;

	(TMD_P_GT3I*)sl = &sortedIndex[0];

	primsleft = PSImodelctrl.PrimLeft;
	opcd = (TMD_P_GT4I*)(PSImodelctrl.PrimTop);

	localSortCount = sortCount;

//	tfv =transformedVertices;
//	tfd =transformedDepths;

	while(primsleft)
	{
		switch (opcd->cd & (0xff - 2))
		{
/*-----------------------------------------------------------------------------------------------------------------*/
#define op ((TMD_P_FT3I*)opcd)
			case GPU_COM_TF3:
						
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices

				gte_nclip();	// takes 8 cycles
				
				deep = (GETD(op->v2) - localMinDepth);

				gte_stopz_cpu(clipflag);
					
				if ((clipflag < 0))	// || (op->dummy))
				{
//					op->next = sl[deep];
//					sl[deep] = (int)op;
//					localSortCount ++;
				}
				op ++;
				break;

#undef op			
/*-----------------------------------------------------------------------------------------------------------------*/
#define op ((TMD_P_FT4I*)opcd)
			case GPU_COM_TF4:
			
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices

				gte_nclip();	// takes 8 cycles
				
				deep = (GETD(op->v2) - localMinDepth);

				gte_stopz_cpu(clipflag);
				
				if ((clipflag < 0))	// || (op->dummy))
				{
//					op->next = sl[deep];
//					sl[deep] = (int)op;
//					localSortCount ++;
				}
				op ++;
				break;
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
#define op ((TMD_P_GT3I*)opcd)
			case GPU_COM_TG3:
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices

				gte_nclip();	// takes 8 cycles

				deep = (GETD(op->v2) - localMinDepth);	// fill in that 8-cycle gap

				gte_stopz_cpu(clipflag);
					
				if ((clipflag < 0) || (op->dummy))
				{
					op->next = sl[deep];
					sl[deep] = (int)op;
					localSortCount ++;
				}
				
				op ++;
				break;
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
#define op opcd
			case GPU_COM_TG4:

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

				gte_nclip();	// takes 8 cycles

				deep = (GETD(op->v2) - localMinDepth);
			
				gte_stopz_cpu(clipflag);
						
				if ((clipflag < 0) || (op->dummy))
				{
					op->next = sl[deep];
					sl[deep] = (int)op;
					localSortCount ++;
				}

				op ++;
				break;
#undef op

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

#define op ((TMD_P_FT4I*)opcd)
			case GPU_COM_TF4SPR :
			
				deep = (GETD(op->v0) - localMinDepth);

//				op->next = sl[deep];
//				sl[deep] = (int)op;
//				localSortCount++;

				op++;
				break;
#undef op

/*-----------------------------------------------------------------------------------------------------------------*/
#define op ((TMD_P_FG4I*)opcd)
			case GPU_COM_G4:
			case GPU_COM_F4:
   		
				gte_ldsxy3(GETV(op->v0), GETV(op->v1), GETV(op->v2));		// Load 1st three vertices

				gte_nclip();	// takes 8 cycles

				deep = (GETD(op->v2) - localMinDepth);

				gte_stopz_cpu(clipflag);
				
					
				if ((clipflag<0))	// || (op->dummy))
				{
					op->next = sl[deep];
					sl[deep] = (int)op;
					localSortCount ++;
				}
				op ++;
				break;
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
#define op ((TMD_P_FG3I*)opcd)
			case GPU_COM_G3:
			case GPU_COM_F3:

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

				gte_nclip();	// takes 8 cycles

				deep = (GETD(op->v2) - localMinDepth);

				gte_stopz_cpu(clipflag);
				
				if ((clipflag < 0))	// || (op->dummy))
				{
					op->next = sl[deep];
					sl[deep] = (int)op;
					localSortCount ++;
				}
				op ++;
				break;
#undef op
/*-----------------------------------------------------------------------------------------------------------------*/
			default:
				break;
		}
		primsleft --;
	}
	sortCount = localSortCount;
#endif
}

#endif

/*
void *psiRegisterDrawFunction(void (*drawHandler)(int))
{
	void *olddraw = (void *)customDrawFunction;
	customDrawFunction = drawHandler;
	return olddraw;
}
*/

// Moved here from "custom.c".
// Note - this  is now a code overlay, debug only (from the model viewer)
void oldPsiRenderer(PSIDATA *psiData)
{
	long		*tfvbase;
	long		*tfdbase;
	register long		*tfv;
	register long		*tfd;
	register PSIOBJECT	*world;
	PSIMODELCTRL		*modctrl = &PSImodelctrl;
	LONG				depth;
	LONG				s = modctrl->sorttable;
	int					loop, obs, i;
	VERT				*tfn;

	world = psiData->object;
	obs = psiData->numObjects;

	// transform all the vertices (by heirarchy)
	// tfv == one long list of transformed vertices


	tfn = transformedNormals - 1;



	tfTotal = 0;
	for (loop = 0; loop < obs; loop++)
	{
		world = (PSIOBJECT*)psiData->objectTable[loop];
		tfTotal += world->meshdata->vern;
	}

	if(tfTotal <= 126)	// Not 128. TransformVerts rounds up to nearest 3, remember
	{
		tfvbase = (void *)DCACHE;
		tfdbase = (void *)(DCACHE + 512);
	}
	else if(tfTotal <= 255)	// Not 256. TransformVerts rounds up to nearest 3, remember
	{
		tfvbase = (void *)DCACHE;
		tfdbase = transformedDepths;
	}
	else
	{
		tfvbase = transformedVertices;
		tfdbase = transformedDepths;
	}


	tfv = tfvbase;
	tfd = tfdbase;

	tfTotal = 0;

	for (loop = 0; loop < obs; loop++)
	{
		world = (PSIOBJECT*)psiData->objectTable[loop];

	 	gte_SetRotMatrix(&world->matrixscale);		 
	   	gte_SetTransMatrix(&world->matrixscale);	

		gte_ldv0(&world->meshdata->center);

		gte_rtps();

		modctrl->NormTop = world->meshdata->nortop;
		

		gte_stszotz(&world->depth);

		transformVertexListA_ChickenRun(world->meshdata->vertop, world->meshdata->vern, tfv, tfd );

		if(modctrl->lighting)
		{
			register SVECTOR	*np;
			gte_SetRotMatrix(&world->matrix);			 
			np = (SVECTOR*)world->meshdata->nortop;
	   		//gte_SetTransMatrix(&world->matrix);	

			for(i = world->meshdata->norn; i != 0; i--)
			{
				gte_ldv0(np);
				gte_rtv0();		// an 8 cycle job, with two nops preceding it
				np++;			// do stuff while the rt's going on
				tfn++;
#ifndef _WINDOWS
				gte_stsv(GETN(0));
#endif
			}
		}

		tfv += world->meshdata->vern;
		tfd += world->meshdata->vern;
		tfTotal += world->meshdata->vern;
	}

//	printf("tf = %d\n",tfTotal);


	modctrl->PrimTop = (ULONG*)psiData->primitiveList;

	/*
	j = modctrl->depthShift;

	if (j == 0)
	{
		j = DEFAULTDEPTHSHIFT;
	}
	*/

	if (psiData->flags & ACTOR_DYNAMICSORT)
	{
#ifndef _WINDOWS
	 	customPsiCalcMaxMin(psiData, tfdbase);
#else
		//PsiCalcMaxMin(psiData, tfdbase);
#endif


		world = (PSIOBJECT*)psiData->objectTable[0];

		if (modctrl->depthoverride)
		{
			depth = modctrl->depthoverride;
		}
		else
		{
			depth = world->depth;
		}
		
		modctrl->PrimLeft = psiData->noofPrims;
		modctrl->VertTop = world->meshdata->vertop;

//		if((depth >> modctrl->depthShift) < 0 || (depth >> modctrl->depthShift) > 1023)
//		{
//			DB("Depth Error %d!\n",depth);
//		}

		if((depth >> modctrl->depthShift) < 0)
			depth = 0;
			
		if((depth >> modctrl->depthShift) > 1023)
		{
			depth = 1023 << modctrl->depthShift;
		}



#ifndef _WINDOWS
		customPsiSortPrimitives(tfvbase,tfdbase);
#else
		//PsiSortPrimitives(tfvbase,tfdbase);
#endif

		modctrl->polysdrawn = sortCount;

		if(modctrl->lighting == DIRECTIONONLY)	// the mode we're using for all ingame models
		{
//	DB(" **** OLD DIRECTION-ONLY RENDERER ****\n");

#ifndef _WINDOWS
			customPsiDrawSortedPrimitives(depth >> modctrl->depthShift, tfvbase);
#else
			//PsiDrawSortedPrims(depth >> modctrl->depthShift, tfvbase);
#endif
		}
		else
		{
//	DB(" **** OLD FULL-VERSION RENDERER (lighting = %d) ****\n",modctrl->lighting);
#ifndef _WINDOWS
			customPsiDrawSortedPrimitives_Full(depth >> modctrl->depthShift, tfvbase);
#else
			//PsiDrawSortedPrims(depth >> modctrl->depthShift, tfvbase);
#endif
		}
	}
	else
	{
// speed optim version is not un-sorted-object compatable
		for (loop = 0; loop < obs; loop++)
		{
			world = (PSIOBJECT*)psiData->objectTable[loop];
	
			if (modctrl->depthoverride)
			{
				depth = modctrl->depthoverride;
			}
			else
			{
				depth = world->depth;
			}
	
			modctrl->VertTop = world->meshdata->vertop;
		 	modctrl->SortOffs = world->meshdata->sortlistptr[s];
			modctrl->PrimLeft = world->meshdata->sortlistsize[s];

//	DB(" **** OLD PER-MODEL-SORT RENDERER (which shouldn't work) ****\n",modctrl->lighting);

			psiDrawPrimitives(depth >> modctrl->depthShift, tfvbase,tfdbase);
		}
	}
	TIMER_STOP(TIMER_PSIREND);

}
#endif





