#include <sys\types.h>
#include <libgte.h>
#include <libgpu.h>
#include <gtemac.h>
#include <inline_c.h>
#include "typedefs.h"
#include "types.h"
#include "3d_gen.h"
#include "gpu.h"
#include "gen_draw.h"
#include "memory.h"
#include "specific.h"
#include "..\game\objects.h"
#include "..\game\items.h"
#include "..\game\anim.h"
#include "..\game\inventry.h"
#include "..\game\lara.h"

extern void DownLoadMatrix();

/*---------------------------------------------------------------------------
 *	Constants
\*--------------------------------------------------------------------------*/

#define UNIT_SHADOW_SHIFT 8

/*---------------------------------------------------------------------------
 *	Globals
\*--------------------------------------------------------------------------*/


GouraudBarColourSet healthBarColourSet = {
	{ 0x40, 0x60, 0x80, 0x60, 0x40 },	// left red
	{   0,	 0,	  0,	   0,    0 },	// left green
	{   0,	 0,	  0,    0,    0 },	// left blue
	{   0,	 0,	  0,    0,    0 },	// right red
	{ 0x80, 0xc0, 0xff, 0xc0, 0x80 },	// right green
	{   0,	 0,	  0,    0,    0 }	// right blue
};

GouraudBarColourSet poisonBarColourSet = {
	{ 0x60, 0xb0, 0xf0, 0xb0, 0x60 },	// left red
	{ 0x60, 0xb0, 0xf0, 0xb0, 0x60 },	// left red
	{   0,	 0,	  0,    0,    0 },	// left blue
	{ 0x60, 0xb0, 0xf0, 0xb0, 0x60 },	// right red
	{ 0x60, 0xb0, 0xf0, 0xb0, 0x60 },	// right green
	{   0,	 0,	  0,    0,    0 }	// right blue
};

GouraudBarColourSet airBarColourSet = {
	{  0,  0,  0,  0,  0},	// left red
	{113,146,113, 93, 74},	// left green
	{123,154,123,107, 91},	// left blue
	{  0,  0,  0,  0,  0},	// right red
	{113,146,113, 93, 74},	// right green
	{  0,  0,  0,  0,  0}	// right blue
};

GouraudBarColourSet dashBarColourSet = {
	{ 0x90, 0xc0, 0xf0, 0xc0, 0x90 },	// left red
	{	0,	 0,	  0,	   0,    0 },	// left green
	{	0,	 0,	  0,	   0,    0 },	// left blue
	{ 0x90, 0xc0, 0xf0, 0xc0, 0x90 },	// left red
	{ 0x90, 0xc0, 0xf0, 0xc0, 0x90 },	// left red
	{	0,	 0,	  0,	   0,    0 }	// right blue
};

GouraudBarColourSet coldBarColourSet = {
	{   0,	 0,	  0,    0,    0 },	// left red
	{   0,	 0,	  0,    0,    0 },	// left green
	{ 0x60, 0x80, 0xa0, 0x80, 0x60 },	// left blue
	{ 0x60, 0x80, 0xa0, 0x80, 0x60 },	// right red
	{   0,	 0,	  0,    0,    0 },	// right green
	{   0,	 0,	  0,    0,    0 }	// right blue
};

#ifdef LOAD_KANJI
/**********************************************************************************************************
 *		Draw KANJI character
 *********************************************************************************************************/
extern sint16 kanji_tpages[];
extern sint16 kanji_clutnum;
extern sint16 kanji_clut_table[];
void	S_DrawKanji( sint32 x, sint32 y, sint32 z, sint32 scaleH, sint32 scaleV, sint16 sprnum, sint16 shade, uint16 flags )
{

	DR_TPAGE			*dr_tpage;
	SPRT 				*p;
	PSXSPRITESTRUCT     *dptr;
	sint32				x1,y1,x2,y2;
	uint16				tpage, u,v;
	uint16				us[]={   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0, 768,768,768,768,768,768,768,768};
	uint16				vs[]={ 240, 240, 240, 240, 240, 240,  496, 496, 496, 496, 496, 496, 384,400,416,432,448,464,480,496};
//	uint16				us[]={   0,  64, 128, 192, 256, 320,    0,  64, 128, 192, 256, 320, 896,896,896,896,896,896,896,896};
//	uint16				vs[]={ 240, 240, 240, 240, 240, 240,  496, 496, 496, 496, 496, 496, 384,400,416,432,448,464,480,496};

	if (db.polyptr>=db.polybuf_limit)
		return;

	tpage = sprnum/16;
	if (tpage>=20) return;

	u = ((sprnum%16)*16) + us[tpage];
	v = vs[tpage];

	dptr = &psxspriteinfo[kanji_clutnum];
	x1 = x;
	y1 = y-15;
	x2 = x+15;
	y2 = y;

	if ( x2<0 || y2<0 || x1>=phd_winwidth || y1>=phd_winheight )
		return;

	p=(SPRT*)db.polyptr;
	setSprt(p);                  		// This Is A 4 Sided Flat Texture Map
//	setShadeTex(p,1);						// With Shading          0=Shading
//	setSemiTrans(p,0);                      // NO Semi Transparent!! 0=No Semi Trans
	p->x0 = x1;
	p->y0 = y1;
	p->w = x2-x1;
	p->h = y2-y1;
	p->r0 = p->g0 = p->b0 = (uint8)((0x1fff-shade)>>5);
	p->clut = dptr->clut;
	p->u0 = u;
	p->v0 = v;
	MyaddPrim( db.ot,z, p );

	dr_tpage=(DR_TPAGE*)(p+1);
	setDrawTPage(dr_tpage,1,1,kanji_tpages[tpage]);
	MyaddPrim(db.ot,z,dr_tpage);
	db.polyptr=(char*)(dr_tpage+1);
}

void	S_DrawKanjiPage( sint32 x, sint32 y, sint32 z, sint32 scaleH, sint32 scaleV, sint16 sprnum, sint16 shade, uint16 flags )
{

	DR_TPAGE			*dr_tpage;
	SPRT 				*p;
	PSXSPRITESTRUCT     *dptr;
	sint32				x1,y1,x2,y2;
	uint16				tpage, u,v;
	uint16				us[]={   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0, 768,768,768,768,768,768,768,768};
	uint16				vs[]={ 240, 240, 240, 240, 240, 240,  496, 496, 496, 496, 496, 496, 384,400,416,432,448,464,480,496};

	if (db.polyptr>=db.polybuf_limit)
		return;

	tpage = sprnum/16;
	if (tpage>=20) return;

	u = ((sprnum%16)*16) + us[tpage];
	v = vs[tpage];

	dptr = &psxspriteinfo[kanji_clutnum];
	x1 = x;
	y1 = y-15;
	x2 = x+255;
	y2 = y;

	if ( x2<0 || y2<0 || x1>=phd_winwidth || y1>=phd_winheight )
		return;

	p=(SPRT*)db.polyptr;
	setSprt(p);                  		// This Is A 4 Sided Flat Texture Map
//	setShadeTex(p,1);						// With Shading          0=Shading
//	setSemiTrans(p,0);                      // NO Semi Transparent!! 0=No Semi Trans
	p->x0 = x1;
	p->y0 = y1;
	p->w = x2-x1;
	p->h = y2-y1;
	p->r0 = p->g0 = p->b0 = (uint8)((0x1fff-shade)>>5);
	p->clut = dptr->clut;
	p->u0 = u;
	p->v0 = v;
	MyaddPrim( db.ot,z, p );

	dr_tpage=(DR_TPAGE*)(p+1);
	setDrawTPage(dr_tpage,1,1,kanji_tpages[tpage]);
	MyaddPrim(db.ot,z,dr_tpage);
	db.polyptr=(char*)(dr_tpage+1);
}

#endif

/**********************************************************************************************************
 *		Draw Sprite at specific screen location with scaleable width and height
 *********************************************************************************************************/

ULONG TextLight[] = {
	0x808080,		// normal
	0x00b0b0,		// 0x70a0a0,		// gold
	0xa0a0a0,		// grey
	0x6060ff,		// red
	0xff8080,		// blue
	0x4080c0,		// bronze
	0x60c0c0,		// pad text
	0x00c000,		// Green
	0x00c000,		// Green
	0x000080,		// Red (little shading)
	0x008080,		// Yellow (little shading)
	0x404080,		// Red (little shading)
};
ULONG TextDark[] = {
	0x808080,		// normal
	0x005050,		// 0x184040,		// gold
	0x181818,		// grey
	0x000018,		// red
	0x180000,		// blue
	0x001040,		// bronze
	0x101010,		// pad text
	0x004000,		// Green
	0x004000,		// Green
	0x000040,		// Red (little shading)
	0x004040,		// Yellow (little shading)
	0x101040,		// Red (little shading)
};

void	S_DrawScreenSprite(sint32 x, sint32 y, sint32 z, sint32 scaleH, sint32 scaleV, sint16 sprnum, sint16 shade, uint16 flags)
{
	SPRT *p;
//	POLY_FT4 *ft4;
	POLY_GT4 *gt4;
	DR_TPAGE *dr_tpage;
	PSXSPRITESTRUCT *dptr;
	sint32 x1, y1, x2, y2;

	if (db.polyptr >= db.polybuf_limit)
		return;

	dptr = &psxspriteinfo[sprnum];

	if ((scaleH | scaleV) == 0x10000)
	{
		x1 = dptr->x1 + x;
		y1 = dptr->y1 + y;
		x2 = dptr->x2 + x;
		y2 = dptr->y2 + y;
	}
	else
	{
		x1 = ((dptr->x1 * scaleH) >> 16) + x;
		y1 = ((dptr->y1 * scaleV) >> 16) + y;
		x2 = ((dptr->x2 * scaleH) >> 16) + x;
		y2 = ((dptr->y2 * scaleV) >> 16) + y;
	}

	if ( x2<0 || y2<0 || x1>=phd_winwidth || y1>=phd_winheight )
		return;

	gt4=(POLY_GT4*)db.polyptr;

	setXY4(gt4,x1,y1,x2,y1,x1,y2,x2,y2);
	setUV4(gt4,
		dptr->u1, dptr->v1,
		dptr->u1+(dptr->x2-dptr->x1), dptr->v1,
		dptr->u1, dptr->v1+(dptr->y2-dptr->y1),
		dptr->u1+(dptr->x2-dptr->x1), dptr->v1+(dptr->y2-dptr->y1));

	*((LONG *)&gt4->r0) = TextLight[shade];
	*((LONG *)&gt4->r1) = TextLight[shade];
	*((LONG *)&gt4->r2) = TextDark[shade];
	*((LONG *)&gt4->r3) = TextDark[shade];
	setPolyGT4(gt4);
	gt4->clut = dptr->clut;
	gt4->tpage = dptr->tpage;
	MyaddPrim(db.ot, z, gt4);

	db.polyptr=(char*)(gt4+1);

//	dr_tpage=(DR_TPAGE*)(gt4+1);
//	setDrawTPage(dr_tpage,1,1,dptr->tpage);
//	MyaddPrim(db.ot,z,dr_tpage);
//	db.polyptr=(char*)(dr_tpage+1);

	if (db.polyptr>=db.polybuf_limit)
		return;

	p=(SPRT*)db.polyptr;
	setlen(p, 4);
	setcode(p, 0x66);
	p->x0 = x1+2;	// Offset shadow to right and down.
	p->y0 = y1+1;
	p->w = x2-x1;
	p->h = y2-y1;
	p->r0 = p->g0 = p->b0 = 128;
	p->clut = dptr->clut;
	p->u0 = dptr->u1;
	p->v0 = dptr->v1;
	MyaddPrim( db.ot,z+1, p );

	if ((char *)p >= db.polybuf_limit)
	{
		db.polyptr = (char *)p;
		return;
	}

	dr_tpage=(DR_TPAGE*)(p+1);
	setDrawTPage(dr_tpage,0,1,((dptr->tpage & (~96)) | (2<<5)));	// Set colour subtraction for shadows.
	MyaddPrim(db.ot,z+1,dr_tpage);
	db.polyptr=(char*)(dr_tpage+1);
}


void	S_DrawPickup(sint16 x, sint16 y, sint16 object_num)
{
	phd_PutPolygons(meshes[objects[object_num].mesh_index], 1);
}

#if 0
/*******************************************************************************************************
 *						Draw 3D Sprite At certain scale for Pickups
 ******************************************************************************************************/
void	S_DrawPickup( sint32 x, sint32 y, sint32 scale, sint16 sprnum, sint16 shade, uint16 flags )
{
	POLY_FT4 			*p;
	PSXSPRITESTRUCT     *dptr;
	sint32				x1,y1,x2,y2;

	if (db.polyptr>=db.polybuf_limit)
		return;

	dptr = &psxspriteinfo[sprnum];
	x1 = ((dptr->x1*scale)>>16)+x;
	y1 = ((dptr->y1*scale)>>16)+y;
	x2 = ((dptr->x2*scale)>>16)+x;
	y2 = ((dptr->y2*scale)>>16)+y;

	if ( x2<0 || y2<0 || x1>=phd_winwidth || y1>=phd_winheight )
		return;

	p = (POLY_FT4 *)db.polyptr;
	setPolyFT4(p);                  		// This Is A 4 Sided flat Texture Map

	p->x0 = (sint16)x1;
	p->y0 = (sint16)y1;
	p->x1 = (sint16)x2;
	p->y1 = (sint16)y1;
	p->x2 = (sint16)x1;
	p->y2 = (sint16)y2;
	p->x3 = (sint16)x2;
	p->y3 = (sint16)y2;

	p->r0 = p->g0 = p->b0 = (uint8)((0x1fff-shade)>>5);

	p->clut = dptr->clut;
	p->tpage = dptr->tpage;
	p->u0 = dptr->u1;
	p->v0 = dptr->v1;
	p->u1 = dptr->u2;
	p->v1 = dptr->v1;
	p->u2 = dptr->u1;
	p->v2 = dptr->v2;
	p->u3 = dptr->u2;
	p->v3 = dptr->v2;

	MyaddPrim( db.ot,0, p );
	db.polyptr=(char*)(p+1);
}
#endif
/*******************************************************************************************************
 *						Draw Line Box on Screen
 ******************************************************************************************************/
void	S_DrawScreenBox(sint32 sx, sint32 sy, sint32 z, sint32	w, sint32 h, sint32 col, SG_COL *grdptr, uint16 flags)
{
	LINE_G2 *p;
	u_long *ot;
	SG_COL colors[4];

	if (db.polyptr>=db.polybuf_limit)
		return;

	if (grdptr == NULL)
	{
		colors[0] = colors[1] = colors[2] = colors[3] = inv_colours[col];
		grdptr = &colors[0];
	}

	ot = db.ot;					// Order Table Pointer

	p = (LINE_G2 *)db.polyptr;
	w--;
	h--;
	z >>= 2;

	*((SG_COL *)&p->r0) = *(grdptr);
	*((SG_COL *)&p->r1) = *(grdptr+1);
	setLineG2(p);                          		// Gouraud Shaded Line points 0 to 1
	if ( flags )
		setSemiTrans(p,1);                      // Semi Transparent!! 1=Semi Trans
	p->x0 = sx;
	p->y0 = sy;
	p->x1 = sx+w;
	p->y1 = sy;
	MyaddPrim( ot,z,p );
	p++;

	if ((char *)p>=db.polybuf_limit)
	{
		db.polyptr = (char *) p;
		return;
	}

	*((SG_COL *)&p->r0) = *(grdptr+1);
	*((SG_COL *)&p->r1) = *(grdptr+2);
	setLineG2(p);                          		// Gouraud Shaded Line points 1 to 2
	if ( flags )
		setSemiTrans(p,1);                      // Semi Transparent!! 1=Semi Trans
	p->x0 = sx+w;
	p->y0 = sy;
	p->x1 = sx+w;
	p->y1 = sy+h;
	MyaddPrim( ot,z,p );
	p++;

	if ((char *)p>=db.polybuf_limit)
	{
		db.polyptr = (char *) p;
		return;
	}

	*((SG_COL *)&p->r0) = *(grdptr+2);
	*((SG_COL *)&p->r1) = *(grdptr+3);
	setLineG2(p);                          		// Gouraud Shaded Line points 2 to 3
	if ( flags )
		setSemiTrans(p,1);                      // Semi Transparent!! 1=Semi Trans
	p->x0 = sx+w;
	p->y0 = sy+h;
	p->x1 = sx;
	p->y1 = sy+h;
	MyaddPrim( ot,z,p );
	p++;

	if ((char *)p>=db.polybuf_limit)
	{
		db.polyptr = (char *) p;
		return;
	}

	*((SG_COL *)&p->r0) = *(grdptr+3);
	*((SG_COL *)&p->r1) = *(grdptr);
	setLineG2(p);                          		// Gouraud Shaded Line points 1 to 2
	if ( flags )
		setSemiTrans(p,1);                      // Semi Transparent!! 1=Semi Trans
	p->x0 = sx;
	p->y0 = sy+h;
	p->x1 = sx;
	p->y1 = sy;
	MyaddPrim( ot,z,p );

	db.polyptr=(char*)(p+1);
}

/********************************************************************************************************
 *					Draw Filled Box on Screen....
 *******************************************************************************************************/
void	S_DrawScreenFBox( sint32 sx, sint32 sy, sint32 z, sint32 w, sint32 h, sint32 col, SG_COL *grdptr, uint16 flags )
{
	POLY_G4 		*p;
	SG_COL			colors[4];

	if (db.polyptr>=db.polybuf_limit)
		return;

	if ( grdptr==NULL )
	{
		colors[0] = colors[1] = colors[2] = colors[3] = inv_colours[col];
		grdptr = &colors[0];
	}
	p = (POLY_G4 *)db.polyptr;
	*((SG_COL *)&p->r0) = *(grdptr);
	*((SG_COL *)&p->r1) = *(grdptr+1);
	*((SG_COL *)&p->r2) = *(grdptr+3);
	*((SG_COL *)&p->r3) = *(grdptr+2);
	setPolyG4(p);                          		// Gouraud Shaded Texture Map Quad
	if ( flags )
		setSemiTrans(p,1);                      // Semi Transparent!! 1=Semi Trans
	p->x0 = sx;
	p->y0 = sy;
	p->x1 = sx+w;
	p->y1 = sy;
	p->x2 = sx;
	p->y2 = sy+h;
	p->x3 = sx+w;
	p->y3 = sy+h;
	MyaddPrim( db.ot,(z>>2),p );
	db.polyptr=(char*)(p+1);
}

/********************************************************************************************************
 *			   					Draw Line On Screen
 *******************************************************************************************************/
void	S_DrawScreenLine( sint32 sx, sint32 sy, sint32 z, sint32 w, sint32 h, sint32 col, SG_COL *grdptr, uint16 flags )
{
	LINE_G2			*p;
	SG_COL			colors[2];

	if (db.polyptr>=db.polybuf_limit)
		return;

	if ( grdptr==NULL )
	{
		colors[0] = colors[1] = inv_colours[col];
		grdptr = &colors[0];
	}
	p = (LINE_G2 *)db.polyptr;
	*((SG_COL *)&p->r0) = *(grdptr);
	*((SG_COL *)&p->r1) = *(grdptr+1);
	setLineG2(p);                          		// Gouraud Shaded Line
	if ( flags )
		setSemiTrans(p,1);                      	// Semi Transparent!!
	p->x0 = sx;
	p->y0 = sy;
	p->x1 = sx+w;
	p->y1 = sy+h;
	MyaddPrim( db.ot,(z>>2), p );
	db.polyptr=(char*)(p+1);
}


/*******************************************************************************
 *			Draw Single Color Rectangle
 ******************************************************************************/
static void	S_DrawFlatBox( sint32 sx, sint32 sy, sint32 z, sint32 w, sint32 h, SG_COL *grdptr )
{
	POLY_F4  *p;

	if (db.polyptr>=db.polybuf_limit)
		return;

	p = (POLY_F4 *)db.polyptr;
	*((SG_COL *)&p->r0) = *(grdptr);
	setPolyF4(p);                          		// Gouraud Shaded Texture Map Quad
	p->x0 = sx;
	p->y0 = sy;
	p->x1 = sx+w;
	p->y1 = sy;
	p->x2 = sx;
	p->y2 = sy+h;
	p->x3 = sx+w;
	p->y3 = sy+h;
	MyaddPrim( db.ot,z,p );
	db.polyptr=(char*)(p+1);
}


/*******************************************************************************
 *			Draw Gouraud Bar (health, air, load, music, sound)
 ******************************************************************************/
static SG_COL L_GB_Outline[] = {
	S_GOURAUD_COL( 80,130,130,128),
	S_GOURAUD_COL(160,160,160,128),
	S_GOURAUD_COL( 80,130,130,128),
	S_GOURAUD_COL(160,160,160,128)
};

static SG_COL L_GB_Edge1[] = {
	S_GOURAUD_COL( 40, 65, 65,128),
	S_GOURAUD_COL( 80, 80, 80,128)
};

static SG_COL L_GB_Edge2[] = {
	S_GOURAUD_COL( 80, 80, 80,128),
	S_GOURAUD_COL( 40, 65, 65,128)
};

void S_DrawGouraudBar(short nXPos, short nYPos, short nWidth, short nBarWidth, GouraudBarColourSet* pColourSet)
{
	int w2, i;
	SG_COL line_col[2];
	SG_COL black_col = S_GOURAUD_COL( 0,0,0,128 );

	if (nBarWidth)
	{
		--nBarWidth;
		w2=nWidth-nBarWidth;

		for ( i=0 ; i<5 ; ++i )
		{
			line_col[0]=S_GOURAUD_COL(pColourSet->abLeftRed[i],pColourSet->abLeftGreen[i],pColourSet->abLeftBlue[i],0);
			line_col[1]=S_GOURAUD_COL(((pColourSet->abLeftRed[i]*w2 + pColourSet->abRightRed[i]*nBarWidth)/nWidth),
								(( pColourSet->abLeftGreen[i]*w2+pColourSet->abRightGreen[i]*nBarWidth)/nWidth),
								(( pColourSet->abLeftBlue[i]*w2 +pColourSet->abRightBlue[i]*nBarWidth)/nWidth),0);
			S_DrawScreenLine(nXPos,nYPos+i,0,nBarWidth,0,0,line_col,0);
		}
	}
	S_DrawScreenBox(nXPos-2, nYPos-2, 0, nWidth+5, 9, 0, L_GB_Outline, 0);
	S_DrawScreenLine(nXPos-3,nYPos-1,0,0,6,0,L_GB_Edge1,0);
	S_DrawScreenLine(nXPos+nWidth+3,nYPos-1,0,0,6,0,L_GB_Edge2,0);
  	S_DrawFlatBox(nXPos-1,nYPos-1,0,nWidth+3,7,&black_col);
}

#if 0
/*******************************************************************************
 *			Draw health bar onto screen
 ******************************************************************************/
#define HEALTHBAR_W		133

//#if LANGUAGE == 3
//#define HEALTHBAR_X		20
//#define HEALTHBAR_Y		22
//#else
#define HEALTHBAR_X		(phd_scrwidth-36-HEALTHBAR_W)
#define HEALTHBAR_Y		18
//#endif

void	S_DrawHealthBar( int percent )
{

	S_DrawGouraudBar(HEALTHBAR_X,HEALTHBAR_Y,HEALTHBAR_W,percent*HEALTHBAR_W/100,&healthBarColourSet);
}


/*******************************************************************************
 *			Draw Air bar onto screen
 ******************************************************************************/
#define AIRBAR_W 		133

//#if LANGUAGE == 3
//#define AIRBAR_X		20
//#define AIRBAR_Y		34
//#else
#define AIRBAR_X		(phd_scrwidth-36-AIRBAR_W)
#define AIRBAR_Y		32
//#endif

void	S_DrawAirBar( int percent )
{
	S_DrawGouraudBar(AIRBAR_X,AIRBAR_Y,AIRBAR_W,percent*AIRBAR_W/100,&airBarColourSet);
}

/*******************************************************************************
*	Draw Dash Power-Up Bar
*/
#define DASHBAR_X	(512-36-HEALTHBAR_W)
#define DASHBAR_Y	50

void	S_DrawDashBar(int percent)
{
	S_DrawGouraudBar(DASHBAR_X, DASHBAR_Y, HEALTHBAR_W, (percent*HEALTHBAR_W)/100, &DashBarColourSet);
}

#endif

#ifdef GAMEDEBUG
void S_DrawLine( sint32 x1, sint32 y1, sint32 z, sint32 x2, sint32 y2, sint32 col, SG_COL *grdptr, uint16 flags )
{
	LINE_G2			*p;
	SG_COL			colors[2];

	if (db.polyptr>=db.polybuf_limit)
		return;

	if ( grdptr==NULL )
	{
		colors[0] = colors[1] = inv_colours[col];
		grdptr = &colors[0];
	}
	p = (LINE_G2 *)db.polyptr;
	*((SG_COL *)&p->r0) = *(grdptr);
	*((SG_COL *)&p->r1) = *(grdptr+1);
	setLineG2(p);                          		// Gouraud Shaded Line
	if ( flags )
		setSemiTrans(p,1);                      	// Semi Transparent!!
	p->x0 = x1;
	p->y0 = y1;
	p->x1 = x2;
	p->y1 = y2;
	MyaddPrim( db.ot,(z>>2), p );
	db.polyptr=(char*)(p+1);
}
#endif

void S_DrawSprite(uint32 dwFlags, sint32 nX, sint32 nY, sint32 nZ, sint16 nSprite, sint16 nShade, sint16 nScale)
{
	uint32 dwRGBC;
	POLY_FT4* pFT4;
	sint32 x1, y1, x2, y2;
	sint32 xv, yv, zv, otz;
	PSXSPRITESTRUCT* pSpriteInfo;

	if (db.polyptr >= db.polybuf_limit)
		return;

//	printf(".");
	return;

#if 0
	if (dwFlags&SPRITE_ABS)
	{
//##		nX-=w2v_matrix[M03];
//##		nY-=w2v_matrix[M13];
//##		nZ-=w2v_matrix[M23];
		nX-=w2v_matrix->tx;
		nY-=w2v_matrix->ty;
		nZ-=w2v_matrix->tz;

		if ((nX < -phd_viewdist) ||  (nX > phd_viewdist)
		||  (nY < -phd_viewdist)	||  (nY > phd_viewdist)
		||  (nZ < -phd_viewdist)	||  (nZ > phd_viewdist))
				return;

//##		zv = w2v_matrix[M20]*nX + w2v_matrix->[M21]*nY + w2v_matrix[M22]*nZ;
		zv = w2v_matrix->m20*nX + w2v_matrix->m21*nY + w2v_matrix->m22*nZ;

		if ((zv < phd_znear) || (zv >= phd_zfar))
			return;

//		xv = w2v_matrix[M00]*nX + w2v_matrix[M01]*nY + w2v_matrix[M02]*nZ;
//		yv = w2v_matrix[M10]*nX + w2v_matrix[M11]*nY + w2v_matrix[M12]*nZ;
		xv = w2v_matrix->m00*nX + w2v_matrix->m01*nY + w2v_matrix->m02*nZ;
		yv = w2v_matrix->m10*nX + w2v_matrix->m11*nY + w2v_matrix->m12*nZ;
	}
	else
#endif
	{
		if ((nX|nY|nZ) == 0)
		{
//##			zv = phd_mxptr[M23];
			zv = Matrix->tz;

			if ((zv < phd_znear) || (zv >= phd_zfar))
				return;

//##			xv = phd_mxptr[M03];
//##			yv = phd_mxptr[M13];
			xv = Matrix->tx;
			yv = Matrix->ty;
		}
		else
		{
//##			zv = phd_mxptr[M20]*nX + phd_mxptr[M21]*nY + phd_mxptr[M22]*nZ + phd_mxptr[M23];
			zv = Matrix->m20*nX + Matrix->m21*nY + Matrix->m22*nZ + Matrix->tz;

			if ((zv < phd_znear) || (zv >= phd_zfar))
				return;

//##			xv = phd_mxptr[M00]*nX + phd_mxptr[M01]*nY + phd_mxptr[M02]*nZ + phd_mxptr[M03];
//##			yv = phd_mxptr[M10]*nX + phd_mxptr[M11]*nY + phd_mxptr[M12]*nZ + phd_mxptr[M13];
			xv = Matrix->m00*nX + Matrix->m01*nY + Matrix->m02*nZ + Matrix->tx;
			yv = Matrix->m10*nX + Matrix->m11*nY + Matrix->m12*nZ + Matrix->ty;
		}
	}

	otz = zv >> (W2V_SHIFT+2);
	zv /= phd_persp;

	pSpriteInfo = psxspriteinfo+nSprite;
	x1 = pSpriteInfo->x1;
	y1 = pSpriteInfo->y1;
	x2 = pSpriteInfo->x2;
	y2 = pSpriteInfo->y2;

	if (dwFlags&SPRITE_SCALE)
	{
		x1 = (x1 * nScale) << (W2V_SHIFT-8);
		x2 = (x2 * nScale) << (W2V_SHIFT-8);
		nScale -= (nScale>>2);

		y1 = (y1 * nScale) << (W2V_SHIFT-8);
		y2 = (y2 * nScale) << (W2V_SHIFT-8);
	}
	else
	{
		x1 <<= W2V_SHIFT;
		y1 <<= W2V_SHIFT;
		x2 <<= W2V_SHIFT;
		y2 <<= W2V_SHIFT;
	}

	x1 = (sint32)((xv + x1) / zv+phd_centerx); if (x1>=phd_winwidth) return;
	y1 = (sint32)((yv + y1) / zv+phd_centery); if (y1>=phd_winheight) return;
	x2 = (sint32)((xv + x2) / zv+phd_centerx); if (x2<0) return;
	y2 = (sint32)((yv + y2) / zv+phd_centery); if (y2<0) return;

	if (dwFlags&SPRITE_SHADE)
	{
		nShade = (0x1fff-nShade)>>5;

		if (otz>DPQ_START)
			nShade-=(otz-DPQ_START)>>5;

		if (nShade<0)
			nShade=0;

		if (nShade>255)
			nShade=255;

		if (dwFlags&SPRITE_TINT)
		{
			uint32 nR,nG,nB;

			nR=(dwFlags&0xff)*nShade; if (nR&0xffff0000) nR=255; else nR>>=8;
			nG=((dwFlags>>8)&0xff)*nShade; if (nG&0xffff0000) nG=255; else nG>>=8;
			nB=((dwFlags>>16)&0xff)*nShade; if (nB&0xffff0000) nB=255; else nB>>=8;
			dwRGBC=MAKE_RGB(nR,nG,nB);
		}
		else
			dwRGBC=MAKE_RGB(nShade,nShade,nShade);
	}
	else if (dwFlags&SPRITE_TINT)
		dwRGBC=dwFlags&0x00ffffff;
	else
		dwRGBC=0x808080;

	pFT4=(POLY_FT4*)db.polyptr;
	*((uint32*)pFT4)=0x09000000;
	*((uint32*)&pFT4->r0)=dwRGBC|0x2c000000|(dwFlags&SPRITE_SEMITRANS);
	*((uint32*)&pFT4->x0)=(x1&0xffff)|(y1<<16);
	*((uint32*)&pFT4->x1)=(x2&0xffff)|(y1<<16);
	*((uint32*)&pFT4->x2)=(x1&0xffff)|(y2<<16);
	*((uint32*)&pFT4->x3)=(x2&0xffff)|(y2<<16);
	*((uint32*)&pFT4->u0)=pSpriteInfo->u1|(pSpriteInfo->v1<<8)|(pSpriteInfo->clut<<16);
	*((uint32*)&pFT4->u1)=pSpriteInfo->u2|(pSpriteInfo->v1<<8)|((pSpriteInfo->tpage<<16)|((dwFlags&0x60000000)>>8));
	*((uint32*)&pFT4->u2)=pSpriteInfo->u1|(pSpriteInfo->v2<<8);
	*((uint32*)&pFT4->u3)=pSpriteInfo->u2|(pSpriteInfo->v2<<8);
	MyaddPrim(db.ot,otz>>OTRIGHT,pFT4);
	db.polyptr=(char*)(pFT4+1);
}

void	S_PrintShadow(sint16 size, sint16 *bptr, ITEM_INFO *iptr, int underwater)
{
	POLY_FT4* p;
	int midx,addx;
	int midz,addz;
	uint32 otz,piss,flag;
	long	rgb;
	PSXSPRITESTRUCT* dptr;
	SVECTOR svec[4],* sptr;			// Vertices For Shadows

//	return;

	if (db.polyptr >= db.polybuf_limit)
		return;

	rgb = (4096 - abs(iptr->floor - lara_item->pos.y_pos))>>6;
	if (rgb < 32)
		rgb = 32;

	phd_PushMatrix();
	phd_TranslateAbs(iptr->pos.x_pos,iptr->floor-16, iptr->pos.z_pos);

//##	if (*(phd_mxptr+M23)<=phd_znear || *(phd_mxptr+M23)>=phd_zfar)		// Return Now if shadow
	if ((Matrix->tz <= phd_znear)
	||  (Matrix->tz >= phd_zfar))		// Return Now if shadow
	{																// Is Too Near OR Too Far
		phd_PopMatrix();
		return;
	}

	phd_RotY(iptr->pos.y_rot);
//##	DownLoadMatrix();

	midx=(*(bptr+0)+*(bptr+1))>>1;
	midz=(*(bptr+4)+*(bptr+5))>>1;
	size += size>>1;
	addx=((*(bptr+1)-*(bptr+0))*size)>>(UNIT_SHADOW_SHIFT+1);
	addz=((*(bptr+5)-*(bptr+4))*size)>>(UNIT_SHADOW_SHIFT+1);

	sptr=svec;
	sptr->vx=midx-addx;
	sptr->vy=0;
	sptr->vz=midz+addz;
	++sptr;
	sptr->vx=midx+addx;
	sptr->vy=0;
	sptr->vz=midz+addz;
	++sptr;
	sptr->vx=midx+addx;
	sptr->vy=0;
	sptr->vz=midz-addz;
	++sptr;
	sptr->vx=midx-addx;
	sptr->vy=0;
	sptr->vz=midz-addz;

	p=(POLY_FT4*)db.polyptr;
	if (RotAverageNclip4(svec+0,svec+1,svec+3,svec+2,
						 (uint32*)&p->x0,(uint32*)&p->x1,(uint32*)&p->x2,(uint32*)&p->x3,
						 &piss,&otz,&flag)<=0)
	{
		phd_PopMatrix();
		return;
	}

	if ((flag&OBJ_FLAG_BITS) || otz>=(DPQ_END>>3))
	{
		phd_PopMatrix();
		return;
	}

	dptr=psxspriteinfo+objects[SHADOW].mesh_index;

	*((uint32*)p)=0x09000000;

	rgb = rgb|(rgb<<8)|(rgb<<16)|(0x2e<<24);	// RGB,ID
	*((uint32*)&p->r0) = rgb;
	p->clut=dptr->clut;
	p->tpage = dptr->tpage;
	p->u0=dptr->u1;
	p->v0=dptr->v1;
	p->u1=dptr->u2;
	p->v1=dptr->v1;
	p->u2=dptr->u1;
	p->v2=dptr->v2;
	p->u3=dptr->u2;
	p->v3=dptr->v2;
	MyaddPrim(db.ot, otz, p);
	db.polyptr=(char*)(p+1);
	phd_PopMatrix();
}

void S_InsertBackPolygon(sint32 min_x, sint32 min_y, sint32 max_x, sint32 max_y, uint32 col)
{
	POLY_G4 *p;
//	return;

	if (db.polyptr>=db.polybuf_limit)
		return;
//	printf("Hello\n");
	p = (POLY_G4 *)db.polyptr;
	*((uint32*)&(p->r0)) = col;
	*((uint32*)&(p->r1)) = col;
	*((uint32*)&(p->r2)) = col;
	*((uint32*)&(p->r3)) = col;
	setPolyG4(p);                          		// Gouraud Shaded Texture Map Quad
	p->x0 = min_x;
	p->y0 = min_y;
	p->x1 = max_x;
	p->y1 = min_y;
	p->x2 = min_x;
	p->y2 = max_y;
	p->x3 = max_x;
	p->y3 = max_y;
	MyaddPrim( db.ot,OTSIZE-2,p );
	db.polyptr=(char*)(p+1);
}

#if 0
sint32 scrnx,scrny;

int GetScreenPosRel(sint32 in_x, sint32 in_y, sint32 in_z, PHD_VECTOR *out)
{
	sint32	x,y,z, *mptr;


	mptr = phd_mxptr;

	x = (*(mptr+M00) * in_x) + (*(mptr+M01) * in_y) + (*(mptr+M02) * in_z) + *(mptr+M03);
	y = (*(mptr+M10) * in_x) + (*(mptr+M11) * in_y) + (*(mptr+M12) * in_z) + *(mptr+M13);
	z = (*(mptr+M20) * in_x) + (*(mptr+M21) * in_y) + (*(mptr+M22) * in_z) + *(mptr+M23);

	if (z>=phd_znear)
	{
		if (z>phd_zfar)
			z = phd_zfar;
		out->z = z = phd_persp/z;
		out->x = x*z+phd_centerx;
		out->y = y*z+phd_centery;
		return(0);
	}
	else
	{
		out->x = x;
		out->y = y;
		out->z = phd_znear;
		return(1);
	}
}

#endif

