
#ifndef _CUSTOM_H_
#define _CUSTOM_H_

#include "PSX_PC.H"

// You only need the old-PSI renderer in the model viewer
// (It's now resident in an overlay)
#define INCLUDE_OLD_VERSION_RENDERER

typedef struct {
	long	next;
	u_char	out, in, dummy, cd;
	u_char	r0, g0, b0, code;
	u_char	r1, g1, b1, dummy1;
	u_char	r2, g2, b2, dummy2;
	u_short n0, v0;
	u_short v1, v2;
	int	padto8;
//	u_short n0,n1,n2,dummy3;
}D2M_TMD_P_FG3I;

typedef struct {
	long	next;
	u_char	out, in, dummy, cd;
	u_char	r0, g0, b0, code;
	u_char	r1, g1, b1, dummy1;
	u_char	r2, g2, b2, dummy2;
	u_char	r3, g3, b3, dummy3;
	u_short n0, v0;
	u_short v1, v2;
	u_short v3, dummy4;
	int	padto8;
//	u_short n0,n1,n2,n3;
}D2M_TMD_P_FG4I;

typedef struct {
	long	next;
	u_char  out, in, dummy, cd;
	u_char  tu0, tv0;
	u_short clut;
	u_char  tu1, tv1;
	u_short tpage;
	u_char  tu2, tv2;
	u_char  tile,p;
	u_char  r0, g0, b0, code;
	u_short n0, v0;
	u_short v1, v2;
// n0's already there
}D2M_TMD_P_FT3I;


typedef struct {
	long  next;
	u_char  out, in, dummy, cd;
	u_char  tu0, tv0;			
	u_short clut;
	u_char  tu1, tv1;
	u_short tpage;
	u_char  tu2, tv2;
	u_char  tile,p0;
	u_char  tu3, tv3;
	u_short p1;
	u_char  r0, g0, b0, code;
	
	u_short v0;
	u_short v1, v2;
	u_short v3;
	u_short	n0;
	u_short	padto8;
// n0's already there
}D2M_TMD_P_FT4I;

typedef struct {
	long  next;
	u_char  out, in, dummy, cd;
	u_char  tu0, tv0;			
	u_short clut;
	u_char  tu1, tv1;
	u_short tpage;
	u_char  tu2, tv2;
	u_char  tile,p0;
	u_char  tu3, tv3;
	u_short p1;
	u_char  r0, g0, b0, code;
	
	u_short v0;
	u_short v1, v2;
	u_short v3;
	u_short	n0;
	u_short	padto8;
// n0's already there
}D2M_TMD_P_SP4I;


typedef struct {
	long	next;
	u_char  out, in, dummy, cd;

	u_char  tu0, tv0;
	u_short clut;

	u_char  tu1, tv1;
	u_short tpage;

	u_char  tu2, tv2;
	u_short v0;

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

	RGBCD avgTexCol;
	u_short n0,n1,n2,n_dummy;
}D2M_TMD_P_GT3I;

typedef struct {
	long next;
	u_char  out, in, dummy, cd;

	u_char  tu0, tv0;
	u_short clut;

	u_char  tu1, tv1;
	u_short tpage;

	u_char  tu2, tv2;
	u_short v0;

	u_char  tu3, tv3;
	u_short v1;

	u_char  r0, g0, b0, code;
	u_char  r1, g1, b1, tile;
	u_char  r2, g2, b2, code2;
	u_char  r3, g3, b3, code3;
	u_short v2, v3;
	RGBCD avgTexCol;
	u_short n0,n1,n2,n3;
}D2M_TMD_P_GT4I;





typedef struct DIRECT2MESH
{
	int n_fg3s;
	int n_fg4s;
	int n_ft3s;
	int n_ft4s;
	int n_gt3s;
	int n_gt4s;
	int n_sprs;

	D2M_TMD_P_FG3I *fg3s;
	D2M_TMD_P_FG4I *fg4s;
	D2M_TMD_P_FT3I *ft3s;
	D2M_TMD_P_FT4I *ft4s;
	D2M_TMD_P_GT3I *gt3s;
	D2M_TMD_P_GT4I *gt4s;
	D2M_TMD_P_SP4I *sprs;
}DIRECT2MESH;


#define addPrimLen(ot,p,len,tempvar) \
{\
	tempvar = *(u_long *)(ot); \
    (*(u_long *)(ot) = (u_long)(p)); \
	tempvar |= (len<<24); \
	*(unsigned long *)(p) = tempvar; \
}
#define F3_PRIMLEN 4
#define FT3_PRIMLEN 7
#define G3_PRIMLEN 6
#define GT3_PRIMLEN 9

#define F4_PRIMLEN 5
#define FT4_PRIMLEN 9
#define G4_PRIMLEN 8
#define GT4_PRIMLEN 12



extern ULONG *sortedIndex;
extern int sortCount;
extern long minDepth;

extern int  tfTotal;

extern long maxDepth;
extern int maxDepthRange;
extern int depthRange;

typedef struct{
	SHORT x,y,z,w;
}SHORTQUAT;
typedef struct
{
	short x,y;
}SHORTXY;

// ===================================================================================
// PSI's inside a BFF file... Whatever next!?

#define BFF_PSI_ID (('P'<<0) | ('S'<<8) | ('I'<<16) | (0<<24))
#define BFF_PSI1_ID (('P'<<0) | ('S'<<8) | ('I'<<16) | (1<<24))

typedef unsigned char *BFF_PsiStr;
extern int	psiModelListLen;	// A bit messy...

PSIMODEL * BFF_IsModelLoaded(char *modelname);
PSIMODEL * BFF_IsCRCModelLoaded(unsigned long crc);
void BFF_Link_PSI(BFF_PsiStr *bffpsi);

typedef struct {
	char tname[32];
} PSITEXTURES;

void customPsiCalcMaxMin(PSIDATA *psiData, long *tfd);
void customPsiDrawSortedPrimitives(int depth,long *tfv);
void customPsiDrawSortedPrimitives_Full(int depth,long *tfv);
#ifndef DREAMCAST
void psiDrawPrimitives(int depth,long *tfv, long *tfd);
#endif

void ShortquaternionGetMatrix(SHORTQUAT *squat, MATRIX *dmatrix);
void ShortquaternionSlerpMatrix(SHORTQUAT *src1, SHORTQUAT *sp2, ULONG t,MATRIX *dmatrix);

//void psiCalcChildMatrix(PSIOBJECT *world, PSIOBJECT *parent);

void BFF_Link_PSI1(PSIMODEL *bffpsi);

void direct2psiDrawSegments(PSIDATA *psiData);
void transformVertexListA_ChickenRun(VERT *vertPtr, long numVerts, long *transformedVerts, long *transformedDepths);

extern TextureType* PageTexture(USHORT ix);

extern PSIMODEL *currentPSI;
extern PSITEXTURES	*currentTextureList;

void psiFixupMesh(PSIMESH *mesh);
void psiFixupOneRoot(PSIMESH *mesh);
void psiFixupPrims(PSIMODEL *psiModel);

#ifndef _OVERLAYS_H
#include "overlays.h"
#endif
void direct2FindTextureInstances(PSIMODEL *model,TEXINSTANCE *instance,TextureType *src);

void psiCalcChildMatrix(PSIOBJECT *world, PSIOBJECT *parent);





// optimisations in progress... Keep commented out for now
// (view ginger: SEK = 32/33 before, 20/21 after. Makes no diff to the SEK 100 in the piebarn :/ )

#define DCACHE_QUATERNION
// Bugger. We need the NAME of the MESH for the PSI-SCANNER!
// (tbd - work some CRC magic)
#ifndef _WINDOWS
#define STORE_LASTFRAME
#endif

#ifdef STORE_LASTFRAME
  #define LASTROTATATEKEY(mesh) (*(ULONG *)(&(mesh)->name[0]))
  #define LASTSCALEKEY(mesh) (*(ULONG *)(&(mesh)->name[4]))
  #define LASTMOVEKEY(mesh) (*(ULONG *)(&(mesh)->name[8]))

// name is still required for psiObjectScan
  #define MESH_NAMECRC(mesh) (*(ULONG *)(&(mesh)->name[12]))	// phew. And it's 16 long!
#endif


extern int MAXMODELS;
extern char *PSIname;
extern long *psiModelListCRC;
extern int TG4count;
extern int TG3count;
extern int TF4count;
extern int TF3count;
extern int F4count;
extern int F3count;
extern PSIMODEL **psiModelList;

void oldPsiRenderer(PSIDATA *psiData);

#endif
