/****************************************************************************
*
* GPU.H
*
* PROGRAMMER : Chris
*    VERSION : 00.00
*    CREATED : 04/06/98
*   MODIFIED : 04/06/98
*       TABS : 5
*
* DESCRIPTION
*	Header file for GPU.C
*
*****************************************************************************/

#ifndef _GPU_H
#define _GPU_H

/*---------------------------------------------------------------------------
 *	Import Headers
\*--------------------------------------------------------------------------*/

#include <sys\types.h>
#include <libgte.h>
#include <libgpu.h>
#include "typedefs.h"
#include "types.h"
#include "3d_gen.h"
#include "profile.h"

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

#define NTSC
//#define CREATE_MOVIE
//#define SNAPSHOT

/* -------- screen dimensions */

#ifdef NTSC
#define MY_PSX_W		512
#define MY_PSX_H		240
#define MY_PSX_X_OFF	0
#define MY_PSX_Y_OFF	0
#else
#define MY_PSX_W		512
#define MY_PSX_H		256
#define MY_PSX_X_OFF	0
#define MY_PSX_Y_OFF	24
#define PAL_MAGIC		256
#endif

/* -------- Primitive buffer definitions */

#define PBSIZE			(2000*13)		// # longs = (# polys * sizeof(GT4))
#define POLYPTR_CLAMP 	(1990*13)

/* -------- Ordering-Table definitions */

#define OTRESOLUTION	8			// each bucket is 8 Game Units
#define OTBITS			12             // Size of Ordering Table
#define OTSIZE			2564			// actual size of ordering table
#define OTRIGHT		(13-OTBITS)	// I use 0<otz<32767 rather than 0<otz<65535 So Decrease Shift by One

/* -------- Sprite definitions */

#define SPRITE_REL			0x00000000
#define SPRITE_ABS			0x01000000
#define SPRITE_SEMITRANS		0x02000000
#define SPRITE_SCALE		0x04000000
#define SPRITE_SHADE		0x08000000
#define SPRITE_TINT			0x10000000
#define SPRITE_TRANS_HALF	0x00000000
#define SPRITE_TRANS_ADD		0x20000000
#define SPRITE_TRANS_SUB		0x40000000
#define SPRITE_TRANS_QUARTER	0x60000000
#define SPRITE_COLOUR(r,g,b) ((r)|((g)<<8)|((b)<<16))

enum { BUF_NEXT, BUF_CURRENT };

#ifndef NTSC
#define PAL
#endif

/*---------------------------------------------------------------------------
 *	Type Definitions
\*--------------------------------------------------------------------------*/

typedef struct {
	int		current_buffer;	// Current Buffer
	uint32*	ot;				// Order table pointer for work buffer
	char*	polyptr;			// current Polygon pointer
	char*	curpolybuf;		// current poly buffer
	char*	polybuf_limit;		// near the end of the current poly buffer
	int		nOTSize;			// number of OT entries
	int		nPBSize;			// size of polygon buffers
	uint32*	order_table[2];	// Pointers for Order Tables
	uint32*	poly_buffer[2];	// Pointers for PolyBuffers
	DRAWENV	draw[2];			// Drawing environments
	DISPENV	disp[2];			// Display environments
}DB_STRUCT;

typedef struct {
	uint32	tag;
	uint8	r0,g0,b0,code;
	sint16	x0,y0;
	uint32	u0v0clut;
	sint16	x1,y1;
	uint32	u1v1tpage;
	sint16	x2,y2;
	uint32	u2v2pad;
}PHD_FT3;

typedef struct {
	uint32	tag;
	uint8	r0,g0,b0,code;
	sint16	x0,y0;
	uint32	u0v0clut;
	sint16	x1,y1;
	uint32	u1v1tpage;
	sint16	x2,y2;
	uint32	u2v2pad;
	sint16	x3,y3;
	uint32	u3v3pad;
}PHD_FT4;

typedef struct {
	uint32	*tag;
	uint8	r0,g0,b0,code;
	sint32	xy0;
	uint32	u0v0clut;
	uint8   	r1,g1,b1,pad1;
	sint32	xy1;
	uint32	u1v1tpage;
	uint8	r2,g2,b2,pad2;
	sint32	xy2;
	uint32	u2v2pad;
}PHD_GT3;

typedef struct {
	uint32  *tag;
	uint8   r0,g0,b0,code;
	sint32  xy0;
	uint32  u0v0clut;
	uint8   r1,g1,b1,pad1;
	sint32  xy1;
	uint32  u1v1tpage;
	uint8   r2,g2,b2,pad2;
	sint32  xy2;
	uint32  u2v2pad;
	uint8   r3,g3,b3,pad3;
	sint32  xy3;
	uint32  u3v3pad;
}PHD_GT4;

typedef struct {
	uint32 u0v0clut;
	uint32 u1v1tpage;
	uint32 u2v2pad;
	uint32 u3v3pad;
}PSXTEXTSTRUCT;

typedef struct {
	uint8  u0,v0;
	uint16 clut;
	uint8  u1,v1;
	uint16 tpage;
	uint8  u2,v2;
	uint8  codeGT4,codeGT3;
	uint8  u3,v3;
	uint16 pad3;
}PSXTEXTI;

typedef struct {
	sint16 x1,y1,x2,y2;
	uint16 clut,tpage;
	uint8  u1,v1,u2,v2;
} PSXSPRITESTRUCT;

typedef void (* PFNVSYNCROUTINE)(void);
typedef int (*PFNIDLECHECKROUTINE)(void);
typedef int (*PFNIDLEROUTINE)(PFNIDLECHECKROUTINE);

typedef struct {
	UBYTE u0, v0;
	UWORD clut;
	UBYTE u1, v1;
	UWORD tpage;
	UBYTE u2, v2;
	UBYTE id[2];
	UBYTE u3, v3;
	UWORD wclut;
}TEXTURE;

typedef struct {
	TEXTURE t[3];
}MMTEXTURE;

/*---------------------------------------------------------------------------
 *	Macros
\*--------------------------------------------------------------------------*/

#define MyaddPrim(OT, Z, P) addPrim(((OT)+(Z)),P)

#define MAKE_RGB(r,g,b) ((r)|((g)<<8)|((b)<<16))

#define S_GOURAUD_COL(r,g,b,s) ((r)|((g)<<8)|((b)<<16))
#define S_COLOUR(r,g,b) ((r)|((g)<<8)|((b)<<16))

/*---------------------------------------------------------------------------
 *	Prototypes
\*--------------------------------------------------------------------------*/

extern DB_STRUCT db;					// The double buffering info
extern volatile uint32 GnFrameCounter;		// Global Frame Counter..
extern volatile uint32 GnLastFrameCount;	// Number of frames last time...

extern uint32 GadwOrderingTables[];
extern uint32 GadwPolygonBuffers[];

extern PSXTEXTSTRUCT* psxtextinfo;
extern PSXSPRITESTRUCT* psxspriteinfo;
extern MMTEXTURE *RoomTextInfo;

extern void GPU_Init();
extern void GPU_Cleanup();
extern void GPU_ClearVRAM();
extern void GPU_UseOrderingTables(uint32* pBuffers,int nOTSize);
extern void GPU_UsePolygonBuffers(uint32* pBuffers,int nPBSize);
extern void GPU_BeginScene();
extern void GPU_EndScene();
extern int GPU_Flip(PFNIDLEROUTINE pfnIdleRoutine);
extern void GPU_ResetLastFrameCount();
extern uint32 GPU_GetFrameCount();
extern int GPU_FlipNoIdle();
extern void GPU_FlipNow();
extern void GPU_FlipToBuffer(int nBuffer);
extern RECT* GPU_GetDispRect(int nWhich);
extern RECT* GPU_GetDrawRect(int nWhich);
extern void GPU_SetScreenPosition(sint16 nX,sint16 nY);
extern void GPU_GetScreenPosition(sint16* pnX,sint16* pnY);
extern bool GPU_EnableDither(bool tEnable);
extern bool GPU_EnableBGClear(bool tEnable);
extern uint32 GPU_SetBGColour(uint8 nR,uint8 nG,uint8 nB);
extern int GPU_SetHorizontalResolution(int nNewRes);
extern int GPU_GetHorizontalResolution();

#ifdef PROFILE_ME
extern bool GPU_EnableProfilerBar(bool tEnable);
#endif

extern void VSYNC_Init();
extern void VSYNC_Cleanup();
extern void VSYNC_Add(PFNVSYNCROUTINE pfnRoutine);
extern void VSYNC_Remove(PFNVSYNCROUTINE pfnRoutine);
#endif
