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

	lscape.h:		Landscape specific draw routines

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

#ifndef _LSCAPE_H_
#define _LSCAPE_H_

#define NEW_GLOVER_LANDSCAPE



#define gte_ldrgb0(r0) __asm__ volatile (	\
	"lwc2	$20, 0( %0 );"					\
	:										\
	: "r"( r0 ))

#define gte_ldrgb1(r0) __asm__ volatile (	\
	"lwc2	$21, 0( %0 );"					\
	:										\
	: "r"( r0 ))


#define gte_ldrgb2(r0) __asm__ volatile (	\
	"lwc2	$22, 0( %0 );"					\
	:										\
	: "r"( r0 ))

#define gte_strgb0(r0) __asm__ volatile (	\
	"swc2	$20, 0( %0 );"					\
	:										\
	: "r"( r0 )								\
	: "memory" )

#define gte_strgb1(r0) __asm__ volatile (	\
	"swc2	$21, 0( %0 );"					\
	:										\
	: "r"( r0 )								\
	: "memory" )

#define gte_strgb2(r0) __asm__ volatile (	\
	"swc2	$22, 0( %0 );"					\
	:										\
	: "r"( r0 )								\
	: "memory" )



#define LSCAPE_ROTATEMODEL	(1)
#define LSCAPE_DRAWMODEL	(2)

#define OFFLEFT		1
#define OFFRIGHT	2
#define OFFUP		4
#define OFFDOWN		8
#define OFFFRONT	16
#define OFFBACK		32



/*
bit	0 = reserved ???
	1 = trans		no/yes	R
	2 = tri/quad			3/4
	3 = gouraud:	no/yes	G
	4 = texture:	no/yes	T
	5 = u/v anim:	no/yes	S
	6 = tex anim:	no/yes	A
*/


//#define PMASK_DUBSIDE		(1)
#define PMASK_TRANS			(2)
#define PMASK_UVANIM		(4)
#define PMASK_TEXANIM		(8)
#define PMASK_COLOURKEY		(16)
#define PMASK_NOTGOURAUD	(32)


/*
#define PTYPE_G3	(PMASK_GOURAUD)
#define PTYPE_G4	(PMASK_GOURAUD|PMASK_QUAD)
#define PTYPE_TG3	(PMASK_TEXTURE|PMASK_GOURAUD)
#define PTYPE_TG4	(PMASK_TEXTURE|PMASK_GOURAUD|PMASK_QUAD)
#define PTYPE_STG3	(PMASK_UVANIM|PMASK_TEXTURE|PMASK_GOURAUD)
#define PTYPE_STG4	(PMASK_UVANIM|PMASK_TEXTURE|PMASK_GOURAUD|PMASK_QUAD)
#define PTYPE_ATG3	(PMASK_TEXANIM|PMASK_TEXTURE|PMASK_GOURAUD)
#define PTYPE_ATG4	(PMASK_TEXANIM|PMASK_TEXTURE|PMASK_GOURAUD|PMASK_QUAD)
*/

// values for primtype
enum
{
	PTYPE_TG4,
	PTYPE_TG3
};

#define PTYPENUMBER_DOUBLESIDED	64
#define PTYPENUMBER_SPECIAL		128

#define TMD_PTYPE_LARGEST (56)

// values for flags. If any of these are set, primtype will be -ve

// This way, I'm guaranteeing that all TMD packets will start with these elements
typedef struct {
	char primtype;
	char flags;
	char src_size;
	char cpadding00;

	u_short v0, v1;	// verts at the beginning, so off-screen checks come before type checks
	u_short v2, v3;
} TMD_PTYPE_GENERIC;



// unlit primitives used for landscape drawing

// Textured Gouraud 3 sided
typedef struct {
	char primtype;
	char flags;
	char src_size;
	char cpadding00;

	u_short v0, v1;	// verts at the beginning, so off-screen checks come before type checks
	u_short v2, v3;

	u_char  tu0, tv0;
	u_short clut;

	u_char  tu1, tv1;
	u_short tpage;

	u_char  tu2, tv2;
	u_short spadding0;

	u_char  tu3, tv3;
	u_short spadding1;

	u_char  r0, g0, b0, code;
	u_char  r1, g1, b1, code2;	// same as code
	u_char  r2, g2, b2, code3;	// zero
	u_char  r3, g3, b3, cpadding2;
	SPRITEX	*spr;
}TMD_PTYPE_TG4;

typedef struct {
	char primtype;
	char flags;
	char src_size;
	char cpadding00;

	u_short v0, v1;	// verts at the beginning, so off-screen checks come before type checks
	u_short v2, spadding1;	// aka v3

	u_char  tu0, tv0;
	u_short clut;

	u_char  tu1, tv1;
	u_short tpage;

	u_char  tu2, tv2;
	u_short spadding0;

	u_char  r0, g0, b0, code;
	u_char  r1, g1, b1, code2;	  
	u_char  r2, g2, b2, cpadding1;

	SPRITEX	*spr;
} TMD_PTYPE_TG3;

// Gouraud 3 sided
typedef struct {
	u_long	id;

	u_short v0, v1;
	u_short v2, v3;

	u_char	r0, g0, b0, code;
	u_char	r1, g1, b1, pad0;
	u_char	r2, g2, b2, pad1;
}TMD_PTYPE_G3;

// Gouraud 4 sided
typedef struct {
	u_long	id;

	u_short v0, v1;
	u_short v2, v3;

	u_char	r0, g0, b0, code;
	u_char	r1, g1, b1, pad0;
	u_char	r2, g2, b2, pad1;
	u_char	r3, g3, b3, pad2;
}TMD_PTYPE_G4;


// now for the special ones ...

// Scrolling Textured Gouraud 3 sided
typedef struct {
	char primtype;
	char flags;
	char src_size;
	char cpadding00;

	u_short v0, v1;
	u_short v2, v3;

	u_char  tu0, tv0;
	u_short clut;

	u_char  tu1, tv1;
	u_short tpage;

	u_char  tu2, tv2;
	u_short	pad0;

	u_char  r0, g0, b0, code;
	u_char  r1, g1, b1, tile;	  
	u_char  r2, g2, b2, code2;

	SPRITEX	*spr;

	u_char	scrMask;
	u_char	scrSpeed;
	u_char	texFrames;
	u_char	texPrg;
}TMD_PTYPE_STG3;

// Scrolling Textured Gouraud 4 sided
typedef struct {
	char primtype;
	char flags;
	char src_size;
	char cpadding00;

	u_short v0, v1;
	u_short v2, v3;

	u_char  tu0, tv0;
	u_short clut;

	u_char  tu1, tv1;
	u_short tpage;

	u_char  tu2, tv2;
	u_short pad0;

	u_char  tu3, tv3;
	u_short pad1;

	u_char  r0, g0, b0, code;
	u_char  r1, g1, b1, tile;
	u_char  r2, g2, b2, code2;
	u_char  r3, g3, b3, code3;

	SPRITEX	*spr;

	u_char	scrMask;
	u_char	scrSpeed;
	u_char	texFrames;
	u_char	texPrg;
}TMD_PTYPE_STG4;



extern LINE_F2	polyLine;
extern int modelX, modelY, modelZ;

//static void waterEffectTG3(TMD_P_TG3A *op, VERT *vp);
//static void waterEffectTG4(TMD_P_TG4A *op, VERT *vp);
//static  PACKET *lscapeAddG4(TMD_P_F4G *op,POLY_G4 *si,long *transformedVerts, long *transformedDepths);
//static  PACKET *lscapeAddG3(TMD_P_F3G *op, POLY_G3 *si,long *transformedVerts, long *transformedDepths);

//inline static  PACKET *divideQuad(TMD_P_TG4A *opTG4,long *transformedVerts, long *transformedDepths,PACKET *packet);
//inline static  PACKET *divideTri(TMD_P_TG3A *opTG3,long *transformedVerts, long *transformedDepths,PACKET *packet);

void transformVertexList(VERT *vertPtr, long numVerts, long *transformedVerts, long *transformedDepths);

void renderSkyModel(long *transformedVerts, long *transformedDepths);


#define MAXSEGMENTVERTS 550

typedef struct {
	unsigned char	u;
	unsigned char	v;
	//USHORT			clut;
}UVCHAR;

typedef struct{
	unsigned char	u;
	unsigned char	v;
	unsigned short pad;
}UVCHAR4;

typedef struct {
	unsigned char	r;
	unsigned char	g;
	unsigned char	b;
	unsigned char	pad;
}RGBCHAR;




typedef struct {
	union
	{
		NEWMODEL *model;
		unsigned long crc;
	}u;
	short tag;
	short terrain;
}SCAPEMODEL;

typedef struct {
	ULONG nZones;
//	NEWMODEL **pZones;
	SCAPEMODEL *pZones;
}PSAWORLD;





extern long *transVerts;
extern long *transDepths;

extern long *transSubVerts;
extern long *transSubDepths;
//SPRITEX *pWaterSprites=NULL;
//PSAWORLD *pWld;
//SUBDIVCTRL	SubDivCtrl;



extern VERT		newVerts[10];	// verts created for sub div'ed polys
extern UVCHAR	uv[5];
extern UVCHAR4	uvStart[4];
extern RGBCHAR	rgbNew[5];
extern USHORT	tpage0;//,tpage1;
extern USHORT	clut0; //,clut1;

extern ULONG waterFrame;
extern LONG	 divideFlag;

extern int lscapeFogStartZ;
extern int lscapeFogEndZ;
extern int lscapeFogFlatZ;
extern int lscapeFogSpan;
extern int lscapeFogSpanShift;

//RGBCD  	lscapeFogColour={0,0,0,GPU_COM_F4};
extern VERT pBBox[9];// last one is a dummy



extern NEWMODEL *pSky;




#define LIGHTING_OFF 0
#define LIGHTING_DYNAMIC 1
#define LIGHTING_PARALLEL 2

// sub division stuff

#define	SUBDIVISIONDEPTH	1536
//#define	SUBDIVISIONDEPTH	0

#define	NOTINSIDE		0
#define	FULLINSIDE		1
#define	PARTINSIDE		2

typedef	struct	_SUBDIVCTRL
{
	long	zDepth;
	long 	otzDepth;

//	LONG	distance;
//	LONG	maxAmount;
//	LONG	currentAmount;

}SUBDIVCTRL;

#define SETSUBDIVDEPTH(D)	{SubDivCtrl.zDepth=D;SubDivCtrl.otzDepth=(D)/4;}
#define GETSUBDIVDEPTH		(SubDivCtrl.zDepth)

typedef struct
{
	int primLeft;
	ULONG *primTop;
	long *pTransVerts;
	long *pTransDepths;
}RENDERCTRL;

extern SUBDIVCTRL SubDivCtrl;
extern	long *transVerts;
extern	long *transDepths;

extern	SPRITEX *pWaterSprites;

void lscapeDrawAll(PSAWORLD *);
int lscapeDrawClipped(NEWMODEL *pModel, MATRIX *pMatrix, int);

void lscapeInit(void);
extern int world_base_y;

extern UBYTE clipped[1024];

/**************************************************************************
	FUNCTION:	lscapeDraw()
	PURPOSE:	Draw a landscape object (with proper depth sort)
	PARAMETERS:	Model structure
	RETURNS:	
**************************************************************************/

void lscapeDraw(NEWMODEL *model, int usefog);

/**************************************************************************
	FUNCTION:	lscapeDrawSub()
	PURPOSE:	Draw a landscape object (with proper depth sort) allso includes sub division checks
	PARAMETERS:	Model structure
	RETURNS:	
**************************************************************************/

void lscapeDrawSub(NEWMODEL *model);


/**************************************************************************
	FUNCTION:	lscapeDraw()
	PURPOSE:	Draw a landscape object (with proper depth sort), can rotate
	PARAMETERS:	Model structure
	RETURNS:	
**************************************************************************/
void lscapeDrawRotate(NEWMODEL *model, int usefog);

/**************************************************************************
	FUNCTION:	lscapeDrawBoundPoly()
	PURPOSE:	highlights the collision polys
	PARAMETERS:	
	RETURNS:	
**************************************************************************/

void lscapeDrawBoundPoly(int numPoints, Point2DType *points, int height, uchar r,uchar g,uchar b);

/**************************************************************************
	FUNCTION:	lscapeDrawBoundPoly3D()
	PURPOSE:	highlights the collision polys
	PARAMETERS:	
	RETURNS:	
**************************************************************************/

void lscapeDrawBoundPoly3D(int numPoints, Point3DType *points, uchar r,uchar g,uchar b);

//static  PACKET *divideTri (TMD_P_TG3A *opTG3,long *transformedVerts, long *transformedDepths,PACKET *packet);
//static  PACKET *divideQuad(TMD_P_TG4A *opTG4,long *transformedVerts, long *transformedDepths,PACKET *packet);


//static  PACKET *divideTriCrack (TMD_P_TG3A *opTG3,long *transformedVerts, long *transformedDepths,PACKET *packet);
//static  PACKET *divideQuadCrack(TMD_P_TG4A *opTG4,long *transformedVerts, long *transformedDepths,PACKET *packet);


extern PSAWORLD *pWld;

extern int lscape_collbox_toggle;

extern int lscapeFogStartZ;	// = 2900;
extern int lscapeFogEndZ;	//	= 3500;
extern int lscapeFogFlatZ;	//	= 4800;
extern RGBCD  	lscapeFogColour;	//={0,0,0,GPU_COM_F4};

extern USHORT overlayAlphaClut;


/* Chris's high speed assembler stuff */

// f1 is actually a strlen function. I used this to test whether all is well
int f1(char *);
// an assembler version of transformVertexList()
void transformVertexListA(VERT *vertPtr, long numVerts, long *transformedVerts, long *transformedDepths);


void lscapeSetTerrainTag(int tag, int terrain);
void lscapeSetTerrainPlat(DYNCOLLBOX *plat, int terrain);

void lscapeDrawCollBox(COLLBOX *pB, DYNCOLLBOX *pD);
void lscapeSetTerrainDepthOffset(int terrain);

#endif

