// OverGfx.c

#include "ult_64.h"
#include "main.h"
#include "file.h"
#include "define.h"
#include "ml.h"

#include "misc.h"
#include "overgfx.h"
#include "menu.h"
#include "camera.h"
#include "cammodes.h"
#include "sub.h"
#include "stats.h"


extern int demoMode,camLetterBox;
extern int Num3PtPlayers,Human3PtMatchPlayers[];
extern int time_mark;
extern int gameOver;

extern char *Plays[];

#define	SHOT_ON_TIME	(ONE_SEC*9)
#define	SLIDE_TIME		(ONE_SEC/2)

#define	BoxW	(168+24)
#define	BoxH	31
#define	BoxXs	0
#define	BoxYs	(ManYs+9)

#define	ManW	24
#define	ManWc	5
#define	ManWg	22
#define	ManH	49
#define	ManBPP	8
#define	ManY	(2048/(1<<ManWc))
#define	ManXs	16
#define	ManYs	218

#define	TeamW	112
#define	TeamH	32
#define	TeamXs	(ManXs+28)
#define	TeamYs	BoxYs

#define	ScoreW	40
#define	ScoreH	32
#define	ScoreXs	(TeamXs+79)
#define	ScoreYs	TeamYs

#define	QtrXs	TeamXs
#define	QtrYs	(BoxYs+41)

#define	TimeW	96
#define	TimeWc	7
#define	TimeH	30
#define	TimeBPP	8
#define	TimeY	((2048/(1<<ShotWc))*8/ShotBPP)
#define	TimeXs	(SCR_X_RES-TimeW)
#define	TimeYs	250

#define	ShotW	96
#define	ShotWc	7
#define	ShotH	30
#define	ShotBPP	8
#define	ShotY	((2048/(1<<ShotWc))*8/ShotBPP)
#define	ShotXs	(SCR_X_RES-ShotW)
#define	ShotYs	210

#define	TopW	192
#define	TopWc	8
#define	TopH	13
#define	TopY	((2048/(1<<TopWc))*8/TopBPP)
#define	TopBPP	8
#define	TopXs	BodyXs
#define	TopYs	BodyYs

#define	BodyW	192
#define	BodyWc	8
#define	BodyH	57
#define	BodyY	((2048/(1<<BodyWc))*8/BodyBPP)
#define	BodyBPP	8
#define	BodyXs	(SCR_X_RES-BodyW)
#define	BodyYs	(SCR_Y_RES-BodyH-10)

#define	MomW	144
#define	MomWc	8
#define	MomH	23
#define	MomHo	21
#define	MomY	(2048/(1<<MomWc))
#define	MomXs	158
#define	MomYs	8
#define	MomC	71

#define	TurboW	96
#define	TurboWc	7
#define	TurboH	14
#define	TurboY	(2048/(1<<TurboWc))
#define	TurboX1	44
#define	TurboX2	320
#define	TurboY1	8
#define	TurboY2	26

#define	TurboIw	92
#define	TurboIx	2

#define	HeadingX	10
#define	NumX		120
#define	Line1Y		26
#define	LineYd		13
#define	Line2Y		(Line1Y+LineYd)
#define	Line3Y		(Line2Y+LineYd)

#define	BackW	120
#define	BackWc	8
#define	BackWg	116
#define	BackH	102
#define	BackY	(2048/(1<<BackWc))
#define	BackXs	((SCR_X_RES-BackWg)/2)
#define	BackYs	((SCR_Y_RES-102)/2)

#define	SelW	96
#define	SelWg	SelW
#define	SelWc	7
#define	SelH	14
#define	SelY	(2048/(1<<SelWc))
#define	SelXs	(BackXs+((BackWg-SelWg)/2))
#define	SelYs	(ItemYs-1)
#define	SelYd	15

#define	ItemW	120
#define	ItemWc	7
#define	ItemH	14
#define	ItemY	(2048/(1<<ItemWc))
#define	ItemXs	(BackXs)
#define	ItemYs	(BackYs+8)
#define	ItemYd	15

#define	CharW		16
#define	CharH		12
#define	CharX		0
#define	CharY		10
#define	CharXs	44
#define	CharYs	11

#define	CamBackW	200
#define	CamBackWc	8
#define	CamBackH	45
#define	CamBackY	(2048/(1<<CamBackWc))
#define	CamBackXs	130
#define	CamBackYs	121

#define	CamLevelW	96
#define	CamLevelWc	7
#define	CamLevelH	10
#define	CamLevelY	(2048/(1<<CamLevelWc))
#define	CamLevelXs	228
#define	CamLevelYs	147

#define	CamBarW		192
#define	CamBarWc	9
#define	CamBarH		14
#define	CamBarY		(2048/(1<<CamBarWc))
#define	CamBarXs	134
#define	CamBar1Ys	128
#define	CamBar2Ys	145
#define	CamBarYs	CamBar1Ys
#define	CamBarYd	(CamBar2Ys-CamBar1Ys)

#define	Pt3BackW	24
#define	Pt3BackWc	5
#define	Pt3BackH	141
#define	Pt3BackY	(2048/(1<<Pt3BackWc))
int		Pt3BackXs	[2][2]= { {10,0},{10,238}};
#define	Pt3BackYs	50

#define	Pt3TopW		24
#define	Pt3TopWc	5
#define	Pt3TopH		120
#define	Pt3TopY		(2048/(1<<Pt3TopWc))
#define	Pt3TopXs	0
#define	Pt3TopYs	(Pt3BackH-Pt3TopH-2)

#define	Num3PtW		24
#define	Num3PtYs	Pt3BackYs

#define	Clock3W		56
#define	Clock3Wc	6
#define	Clock3H		30
#define	Clock3Y		(2048/(1<<Clock3Wc))
#define	Clock3Ys	218
#define	Clock3X1	10
#define	Clock3X2	238


typedef struct SLetter
{
	u8
		TexX,
		TexY,
		Width,
		Height,
		Lift,
		Page,
		pad[2];
} SLetter;

typedef struct SBoxText
{
	u16
		Xpos,
		Ypos;
	char
		Text[60];
} SBoxText;

typedef struct SPt3o
{
	u8
		Back[Pt3BackW*Pt3BackH];
	RGBA16
		Pal[256];
	u8
		Top[Pt3TopW*Pt3TopH],
		Clock[Clock3W*Clock3H];
} SPt3o;

typedef struct SOver
{
	RGBA16
		Pal[256];
	u8
		Man[ManW*ManH*ManBPP/8],
		Time[TimeW*TimeH],
		TimeMin[TimeW*TimeH],
		Shot[ShotW*ShotH],
		Headline[16*13],
		TurboB[TurboW*TurboH],
		TurboF[TurboW*TurboH],
		MomB[MomW*MomH],
		MomF[MomW*MomHo],
		CamLevel[CamLevelW*CamLevelH],
		CamBar[CamBarW*CamBarH],
		BoxTex[32*16],
		BarTex[16*14];
} SOver;


bool
	ShowReplayPanel,
	ShowFreeThrowHelp,
	FreeThrowsShown[4];

u32
	ReplayTextTimer;


static const int
	SummTx[2] =
	{
		0,
		SCR_X_RES-BodyW
	};

static SPt3o
	*Pt3o;

static SOver
	*Over;

static void
	*Swiss11,
	*Swiss13;

static int
	SB_Delay=0,
	SB_Duration=0,
	SB_Time=0;

static char
	QuarterText[20],
	StatTitle[64],
	SubTitle[64];

static SBoxText
	StatText[6+2],
	HintText[10],
	SubText[5];

static int
	HintLineCount,
	HintCounter = 0;

static u8
	DemoFlash,
	StatCount,
	SubLines,
	SubTimer,
//	SubCard = FALSE,
	*ReplayTex;

static RGBA32
	Color;

global int SubCard = FALSE;

static void RenderPlayerCard(int no, int type);
static void RenderTeamCard(int team, int type);

//int BuildNextHint(int dir);


//*****************************************************************************
//	Card Stuff
//*****************************************************************************
int	CardX,CardY;
int	CurrentCardType;
int	CurrentPlyrType;
int	CardDelay;
int	CardCtr;
int	PendingCardType;
int	PendingTeam;
int	PendingPlyr;
int	PendingType;



//*****************************************************************************
//	LED Lights
//*****************************************************************************

//-----------------------------------------------------------------------------
//	Segment Indicator Bit Flags
//
//				   0
//				 -----
//				 |   |
//				5|   |1
//				 | 6 |
//				 -----
//				 |   |
//				4|   |2
//				 | 3 |
//				 -----
//-----------------------------------------------------------------------------
#define	LED0		1
#define	LED1		2
#define	LED2		4
#define	LED3		8
#define	LED4		16
#define	LED5		32
#define	LED6		64


//-----------------------------------------------------------------------------
//	Numeral Segmentation
//-----------------------------------------------------------------------------
u8	LEDs[10]=
		{
		LED0|LED1|LED2|LED3|LED4|LED5,		// 0
		LED1|LED2,							// 1
		LED0|LED1|LED3|LED4|LED6,			// 2
		LED0|LED1|LED2|LED3|LED6,			// 3
		LED1|LED2|LED5|LED6,				// 4
		LED0|LED2|LED3|LED5|LED6,			// 5
		LED0|LED2|LED3|LED4|LED5|LED6,		// 6
		LED0|LED1|LED2,						// 7
		LED0|LED1|LED2|LED3|LED4|LED5|LED6,	// 8
		LED0|LED1|LED2|LED3|LED5|LED6,		// 9
		};

//-----------------------------------------------------------------------------
//	Support Routines
//-----------------------------------------------------------------------------
static void SetLED(RGBA16 *p, int n, int o, RGBA16 on, RGBA16 off);
static void FormatNum(char *text,int n);
static int	PutDigit(char *text, int n);



//*****************************************************************************
//	Routines
//*****************************************************************************



static void SetAlpha( const u8 alpha )
{
	Color.a = alpha;
}


static Gfx *DrawBox( Gfx *gp, const s32 x, const s32 y, const s32 w, const s32 h )
{
	gDPPipeSync( gp++ );
	gDPSetTextureLUT( gp++, G_TT_NONE );
	gDPSetCombineMode( gp++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM );
	gDPSetRenderMode( gp++, G_RM_CLD_SURF, G_RM_CLD_SURF2 );
	gDPSetPrimColor( gp++, 0, 0, 255, 255, 255, Color.a );

	gDPLoadTextureBlock( gp++,
											 Over->BoxTex,
											 G_IM_FMT_IA,
											 G_IM_SIZ_8b,
											 32, 16,
											 0,
											 G_TX_CLAMP,
											 G_TX_CLAMP,
											 5, 4,
											 G_TX_NOLOD,
											 G_TX_NOLOD );

	if (x >= 0)
	{
		// Top left...
		gSPTextureRectangle( gp++,
												 (x)<<2, (y)<<2,
												 (x+16)<<2, (y+8)<<2,
												 0,
												 0<<5, 0<<5,
												 1<<10, 1<<10 );

		// Mid left...
		gSPTextureRectangle( gp++,
												 (x)<<2, (y+8)<<2,
												 (x+16)<<2, (y+h-8)<<2,
												 0,
												 0<<5, 8<<5,
												 1<<10, 0<<10 );
		// Bot left...
		gSPTextureRectangle( gp++,
												 (x)<<2, (y+h-8)<<2,
												 (x+16)<<2, (y+h)<<2,
												 0,
												 0<<5, 8<<5,
												 1<<10, 1<<10 );
	}

	// Top middle...
	gSPTextureRectangle( gp++,
											 (x+16)<<2, (y)<<2,
											 (x+w-16)<<2, (y+8)<<2,
											 0,
											 16<<5, 0<<5,
											 0<<10, 1<<10 );

	// Mid middle...
	gSPTextureRectangle( gp++,
											 (x+16)<<2, (y+8)<<2,
											 (x+w-16)<<2, (y+h-8)<<2,
											 0,
											 16<<5, 8<<5,
											 0<<10, 0<<10 );

	// Bot middle...
	gSPTextureRectangle( gp++,
											 (x+16)<<2, (y+h-8)<<2,
											 (x+w-16)<<2, (y+h)<<2,
											 0,
											 16<<5, 8<<5,
											 0<<10, 1<<10 );

	if ((x+w) <= SCR_X_RES)
	{
		// Top right...
		gSPTextureRectangle( gp++,
												 (x+w-16)<<2, (y)<<2,
												 (x+w)<<2, (y+8)<<2,
												 0,
												 16<<5, 0<<5,
												 1<<10, 1<<10 );
		// Mid right...
		gSPTextureRectangle( gp++,
												 (x+w-16)<<2, (y+8)<<2,
												 (x+w)<<2, (y+h-8)<<2,
												 0,
												 16<<5, 8<<5,
												 1<<10, 0<<10 );

		// Bot right...
		gSPTextureRectangle( gp++,
												 (x+w-16)<<2, (y+h-8)<<2,
												 (x+w)<<2, (y+h)<<2,
												 0,
												 16<<5, 8<<5,
												 1<<10, 1<<10 );
	}


	return( gp );
}


static Gfx *DrawHeadline( Gfx *gp, s32 x, s32 y, s32 w, s32 h )
{
	x += 2;
	y += 2;
	w -= 4;

	gDPPipeSync( gp++ );
	gDPSetRenderMode( gp++, G_RM_OPA_SURF, G_RM_OPA_SURF2 );
	gDPSetCombineMode( gp++, G_CC_DECALRGBA, G_CC_DECALRGBA );
	gDPSetTextureLUT( gp++, G_TT_RGBA16 );

	gDPLoadTLUT_pal256( gp++, Over->Pal );

	gDPLoadTextureBlock( gp++,
											 Over->Headline,
											 G_IM_FMT_CI,
											 G_IM_SIZ_8b,
											 16, 13,
											 0,
											 G_TX_CLAMP,
											 G_TX_CLAMP,
											 4, 4,
											 G_TX_NOLOD,
											 G_TX_NOLOD );

	if (x >= 0)
	{
		// Left...
		gSPTextureRectangle( gp++,
												 (x)<<2, (y)<<2,
												 (x+8)<<2, (y+13)<<2,
												 0,
												 0<<5, 0<<5,
												 1<<10, 1<<10 );
	}

	// Middle...
	gSPTextureRectangle( gp++,
											 (x+8)<<2, (y)<<2,
											 (x+w-8)<<2, (y+13)<<2,
											 0,
											 8<<5, 0<<5,
											 0<<10, 1<<10 );

	if ((x+w) <= SCR_X_RES)
	{
		// Right...
		gSPTextureRectangle( gp++,
												 (x+w-8)<<2, (y)<<2,
												 (x+w)<<2, (y+13)<<2,
												 0,
												 8<<5, 0<<5,
												 1<<10, 1<<10 );
	}


	y += 13;
	h -= 13;
	if (h > 0)
	{
		// Bottom...
		gSPTextureRectangle( gp++,
												 (x)<<2, (y)<<2,
												 (x+w)<<2, (y+h)<<2,
												 0,
												 0<<5, 12<<5,
												 0<<10, 0<<10 );
	}


	return( gp );
}


static u8
	*Font = NULL;

static void SetFont( u8 *font )
{
	Font = font;
}


static void SetColor( u8 r, u8 g, u8 b )
{
	Color.r = r;
	Color.g = g;
	Color.b = b;
}


static s32 GetTextWidth( const char *text )
{
	SLetter
		*letter;
	u8
		*data;
	s32
		width = 0;

	while (*text)
	{
		letter = (SLetter *)&Font[(4*4)+(2*32*128)];
		letter += *text - ' ';

		width += letter->Width + 1;
		text++;
	}

	return( width-1 );
}


void BuildPlayerName1(PlyrRomData_T *prom, char * txt, int width)
{
	strcpy(txt,prom->pcz__pCName);
	strcat(txt," ");
	strcat(txt,prom->pcz__pSName);

	if(GetTextWidth(txt) > width)
	{	// bug # 750
		StrInitials(txt,prom->pcz__pCName);
		strcat(txt," ");
		strcat(txt,prom->pcz__pSName);
	}
}



static Gfx *DrawText( Gfx *gp, const char *text, const s32 xpos, const s32 y )
{
	SLetter
		*letter;
	char
		c;
	s32
		i,
		x;

	gDPPipeSync( gp++ );
	gDPSetTextureLUT( gp++, G_TT_NONE );
	gDPSetCombineMode( gp++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM );
	gDPSetRenderMode( gp++, G_RM_XLU_SURF, G_RM_XLU_SURF2 );
	gDPSetPrimColor( gp++, 0, 0, Color.r, Color.g, Color.b, Color.a );


	gDPLoadTextureBlock( gp++,
											 &Font[(4*4)+(0*32*128)],
											 G_IM_FMT_IA,
											 G_IM_SIZ_8b,
											 32, 128,
											 0,
											 G_TX_CLAMP,
											 G_TX_CLAMP,
											 5, 7,
											 G_TX_NOLOD,
											 G_TX_NOLOD );

	i = 0;
	x = xpos;
	while (text[i])
	{
		c = text[i] - ' ';
		letter = (SLetter *)&Font[(4*4)+(2*32*128)];
		letter += c;

		if (letter->Page == 0)
		{
			gSPTextureRectangle( gp++,
													 (x)<<2,
													 (y - letter->Lift)<<2,
													 (x + letter->Width)<<2,
													 (y - letter->Lift + letter->Height)<<2,
													 0,
													 (letter->TexX)<<5,
													 (letter->TexY)<<5,
													 1<<10, 1<<10 );
		}

		x += letter->Width + 1;
		i++;
	}


	gDPLoadTextureBlock( gp++,
											 &Font[(4*4)+(1*32*128)],
											 G_IM_FMT_IA,
											 G_IM_SIZ_8b,
											 32, 128,
											 0,
											 G_TX_CLAMP,
											 G_TX_CLAMP,
											 5, 7,
											 G_TX_NOLOD,
											 G_TX_NOLOD );

	i = 0;
	x = xpos;
	while (text[i])
	{
		c = text[i] - ' ';
		letter = (SLetter *)&Font[(4*4)+(2*32*128)];
		letter += c;

		if (letter->Page == 1)
		{
			gSPTextureRectangle( gp++,
													 (x)<<2,
													 (y - letter->Lift)<<2,
													 (x + letter->Width)<<2,
													 (y - letter->Lift + letter->Height)<<2,
													 0,
													 (letter->TexX)<<5,
													 (letter->TexY)<<5,
													 1<<10, 1<<10 );
		}

		x += letter->Width + 1;
		i++;
	}


	return( gp );
}


static void Stat_Reset()
{
	StatCount = 0;
}


static void Stat_Add( const u16 x, const u16 y, const char *text )
{
	SBoxText
		*st;

	st = &StatText[StatCount];

	st->Xpos = x + BodyXs;
	st->Ypos = y + BodyYs;

	strcpy( st->Text, text );

	StatCount++;
}


static Gfx *Stat_Draw( Gfx *gp )
{
	SBoxText
		*st;
	s32
		i;

	st = StatText;

	for (i=0; i<StatCount; i++)
	{
		gp = DrawText( gp, st->Text, st->Xpos, st->Ypos );

		st++;
	}

	return( gp );
}


void OverGfx_Init( void *workspace )
{
	SB_Time = 0;
	SB_Delay = 0;
	SB_Duration = 0;

	SubLines = 0;
	SubCard = FALSE;

	DemoFlash = 0;
	ShowReplayPanel = FALSE;
	ShowFreeThrowHelp = FALSE;

	FreeThrowsShown[0] = FALSE;
	FreeThrowsShown[1] = FALSE;
	FreeThrowsShown[2] = FALSE;
	FreeThrowsShown[3] = FALSE;


	Swiss13 = AllocAndLoadFile( "SWISS13.FNT", MEM_ANY );
	Swiss11 = AllocAndLoadFile( "SWISS11.FNT", MEM_ANY );

	if (C3PT)
		Pt3o=(SPt3o *)AllocAndLoadFile("PT3.TEX",MEM_ANY);

	Over=(SOver *)AllocAndLoadFile("OVER.TEX",MEM_ANY);

	*(u16 *)&Over->Pal[0] = 0;

	if (!C3PT)
	{
		ReplayTex = AllocAndLoadFile( "Replay.TEX", MEM_ANY );
		*(u16 *)ReplayTex = 0;
	}
}


void OverGfx_Deinit()
{
	if (!C3PT)
		MemFree( ReplayTex );

	MemFree( Over );

	if (C3PT)
		MemFree(Pt3o);

	MemFree( Swiss11 );
	MemFree( Swiss13 );
}


#define	G_CC_MAN	0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE, 0

static Gfx *DrawContestSummary(Gfx *gp)
{
	int		i;
	int		h;
	int		y;
	int		dir;
	char	txt[64];
	char	num[4];
	playert	*plyr;
	s32
		x;

	// Draw it
	for (i=0; i<Num3PtPlayers; i++)
	{
		plyr=&player[Human3PtMatchPlayers[i]];
		dir=i? 1 : -1;

		SetAlpha( 255 );
		if (i)
			gp = DrawBox( gp, SCR_X_RES-BodyW, BodyYs, BodyW+16, BodyH );
		else
			gp = DrawBox( gp, -16, BodyYs, BodyW+16, BodyH );

		gp = DrawHeadline( gp, SummTx[i], TopYs, BodyW, 13 );

		SetFont( Swiss13 );
		SetColor( 255, 255, 255 );

		// Draw the title text
//		strcpy(txt,plyr->plyrROM->pcz__pCName);
//		strcat(txt," ");
//		strcat(txt,plyr->plyrROM->pcz__pSName);
		BuildPlayerName1(plyr->plyrROM,txt, BodyW-12);	// condenses if too big

		
		x = (TopW - GetTextWidth( txt )) / 2;
		gp = DrawText( gp, txt, SummTx[i]+x, TopYs+13 );

		SetColor( 0, 0, 0 );

		*(u32 *)num = 0;
		IntToDecStr( plyr->Score3, num );
//		sprintf(txt,"%s scores %s point%c",plyr->plyrROM->pcz__pSName,num,(plyr->Score3!=1)? 's': 0 );
// fixes bug # 926 - Mr. WWWWWWWW  (put "points" on next line
		sprintf(txt,"%s scores %s",plyr->plyrROM->pcz__pSName,num);
		x = (BodyW - GetTextWidth( txt )) / 2;
		gp = DrawText( gp, txt, SummTx[i]+x, BodyYs+30 );

		sprintf(txt,"point%s in this round",(plyr->Score3!=1)? "s": "");
		x = (BodyW - GetTextWidth( txt )) / 2;
		gp = DrawText( gp, txt, SummTx[i]+x, BodyYs+46 );
//		x = (BodyW - GetTextWidth( "in this round" )) / 2;
//		gp = DrawText( gp, "in this round", SummTx[i]+x, BodyYs+46 );
	}

	return( gp );
}


static Gfx *DrawBar( Gfx *gp, const u32 x, const u32 y, const u32 w )
{
	gDPPipeSync( gp++ );
	gDPSetCombineMode( gp++, G_CC_DECALRGBA, G_CC_DECALRGBA );
	gDPSetRenderMode( gp++, G_RM_OPA_SURF, G_RM_OPA_SURF2 );
	gDPSetTextureLUT( gp++, G_TT_RGBA16 );
	gDPLoadTLUT_pal256( gp++, Over->Pal );

	if (MenuWhich == MENU_CAMERA && menuChoice == 1)
	{
		s32
			y,
			w,
			h;

		for (y=0; y<CamBarH; y+=CamBarY)
		{
			h=CamBarH-y;
			if (h>CamBarY)
				h=CamBarY;

			gDPLoadTextureBlock(gp++,&Over->CamBar[CamBarW*y],G_IM_FMT_CI,G_IM_SIZ_8b,
				CamBarW,h,0,G_TX_WRAP,G_TX_WRAP,8,8,G_TX_NOLOD,G_TX_NOLOD);
			gSPTextureRectangle(gp++,CamBarXs<<2,(CamBarYs+y+menuChoice*CamBarYd)<<2,(CamBarXs+CamBarW)<<2,(CamBarYs+y+menuChoice*CamBarYd+h)<<2,
				0,0,0,(1<<10),(1<<10));
		}

#if 0
		w=camZoomUser*CamLevelW/200;

		for (y=0; y<CamLevelH; y+=CamLevelY)
		{
			h=CamLevelH-y;
			if (h>CamLevelY)
				h=CamLevelY;

			gDPLoadTextureBlock(gp++,&Over->CamLevel[y*CamLevelW],G_IM_FMT_CI,G_IM_SIZ_8b,
				CamLevelW,h,0,G_TX_WRAP,G_TX_WRAP,CamLevelWc,8,G_TX_NOLOD,G_TX_NOLOD);
			gSPTextureRectangle(gp++,(CamLevelXs)<<2,(CamLevelYs+y)<<2,(CamLevelXs+w)<<2,(CamLevelYs+y+h)<<2,
				0,0,0,(1<<10),(1<<10));
		}
#endif
	}
	else
	{
		gDPLoadTextureBlock( gp++,
												 Over->BarTex,
												 G_IM_FMT_CI,
												 G_IM_SIZ_8b,
												 16, 14,
												 0,
												 G_TX_WRAP,
												 G_TX_WRAP,
												 4, 4,
												 G_TX_NOLOD,
												 G_TX_NOLOD );

		// Left...
		gSPTextureRectangle( gp++,
												 (x)<<2,
												 (y)<<2,
												 (x+8)<<2,
												 (y+14)<<2,
												 0,
												 0<<5, 0<<5,
												 1<<10, 1<<10 );

		// Middle...
		gSPTextureRectangle( gp++,
												 (x+8)<<2,
												 (y)<<2,
												 (x+w-8)<<2,
												 (y+14)<<2,
												 0,
												 8<<5, 0<<5,
												 0<<10, 1<<10 );

		// Right...
		gSPTextureRectangle( gp++,
												 (x+w-8)<<2,
												 (y)<<2,
												 (x+w)<<2,
												 (y+14)<<2,
												 0,
												 8<<5, 0<<5,
												 1<<10, 1<<10 );
	}

	return( gp );
}


static Gfx *DrawMenu( Gfx *gp,
											char *items[],
											const s32 count,
											const s32 select,
											const s32 width )
{
	s32
		i,
		l,
		x,
		y,
		height;

	height = (count * 15) + (2*8);

	l = (SCR_X_RES - width) / 2;
	y = (SCR_Y_RES - height) / 2;

	SetAlpha( 255 );

	gp = DrawBox( gp, l, y, width, height );


	SetFont( Swiss13 );
	y += 8+12;

	for (i=0; i<count; i++)
	{
		if (i == select)
		{
			gp = DrawBar( gp, l+8, y-10, width-16 );

			SetColor( 255, 255, 255 );
		}
		else if (!pauseSelectable[i])
			SetColor( 128, 128, 128 );
		else
			SetColor( 0, 0, 0 );

		if (MenuWhich == MENU_CAMERA || MenuWhich == MENU_QUIT)
			x = l+16;
		else
			x = (SCR_X_RES - GetTextWidth( items[i] )) / 2;

		gp = DrawText( gp, items[i], x, y );

		y += 15;
	}

	return( gp );
}


static Gfx *DrawPauseMenu(Gfx *gp)
{
	gp = DrawMenu( gp,
								 pauseMenuStrings,
								 menuChoices,
								 menuChoice,
								 BackW );

	return( gp );
}


static Gfx *DrawCamMenu( Gfx *gp )
{
	static char
		*menu[] =
		{
			"Camera Mode: XXXXXXXX",
			"Zoom Level:"
		};
	s32
		y,
		w,
		h;

	strcpy( &menu[0][13], camModeNames[camMode] );

	gp = DrawMenu( gp,
								 menu,
								 2,
								 menuChoice,
								 206 );

	gDPPipeSync( gp++ );
	gDPSetCombineMode( gp++, G_CC_DECALRGBA, G_CC_DECALRGBA );
	gDPSetRenderMode( gp++, G_RM_OPA_SURF, G_RM_OPA_SURF2 );
	gDPSetTextureLUT( gp++, G_TT_RGBA16 );
	gDPLoadTLUT_pal256( gp++, Over->Pal );

#if 0
	for (y=0; y<CamBarH; y+=CamBarY)
	{
		h=CamBarH-y;
		if (h>CamBarY)
			h=CamBarY;

		gDPLoadTextureBlock(gp++,&Over->CamBar[CamBarW*y],G_IM_FMT_CI,G_IM_SIZ_8b,
			CamBarW,h,0,G_TX_WRAP,G_TX_WRAP,8,8,G_TX_NOLOD,G_TX_NOLOD);
		gSPTextureRectangle(gp++,CamBarXs<<2,(CamBarYs+y+menuChoice*CamBarYd)<<2,(CamBarXs+CamBarW)<<2,(CamBarYs+y+menuChoice*CamBarYd+h)<<2,
			0,0,0,(1<<10),(1<<10));
	}
#endif

	w=camZoomUser*CamLevelW/200;

	for (y=0; y<CamLevelH; y+=CamLevelY)
	{
		h=CamLevelH-y;
		if (h>CamLevelY)
			h=CamLevelY;

		gDPLoadTextureBlock(gp++,&Over->CamLevel[y*CamLevelW],G_IM_FMT_CI,G_IM_SIZ_8b,
			CamLevelW,h,0,G_TX_WRAP,G_TX_WRAP,CamLevelWc,8,G_TX_NOLOD,G_TX_NOLOD);
		gSPTextureRectangle(gp++,(CamLevelXs)<<2,(CamLevelYs+y)<<2,(CamLevelXs+w)<<2,(CamLevelYs+y+h)<<2,
			0,0,0,(1<<10),(1<<10));
	}

	return( gp );
}


static Gfx *Draw3PtMenu(Gfx *gp)
{
	static char
		*menu[] =
		{
			"Quit Round"
		};

	gp = DrawMenu( gp,
								 menu,
								 1,
								 menuChoice,
								 BackW );

	return( gp );
}




static Gfx *DrawPracticeMenu(Gfx *gp)
{
	gp = DrawMenu( gp,
								 PracticeMenuStrings,
								 NUM_PRACTICE_MENU_OPTIONS,
								 menuChoice,
								 BackW );

	return( gp );
}
/**********
static Gfx *DrawPracticeMenu(Gfx *gp)
{
	static char
		*menu[] =
		{
			"Quit Practice"
		};

	gp = DrawMenu( gp,
								 menu,
								 1,
								 menuChoice,
								 BackW );

	return( gp );
}
**************/

static Gfx *DrawQuitMenu(Gfx *gp)
{
	char
		text[32],
		*menu[] = { text };

	strcpy( text, "Are you sure? " );

	if (ReallyQuit)
		strcat( text, "Yes" );
	else
		strcat( text, "No" );

	gp = DrawMenu( gp,
								 menu,
								 1,
								 menuChoice,
								 136 );

	return( gp );
}


static void Sub_Reset()
{
	SubLines = 0;
}


static void Sub_Add( const u16 x, const u16 y, const char *text )
{
	SBoxText
		*st;

	st = &SubText[SubLines];

	st->Xpos = x + BodyXs;
	st->Ypos = y + BodyYs;

	strcpy( st->Text, text );

	SubLines++;
}


static void Sub_Setup( int team )
{
	int		i, p;
	char	msg[32];
	TeamRamData_T	*td;
	PlyrRamData_T	*pd;
	char
		text[64];
	s32
		x;

	if (PracticeMode)
		return;

	// Render the title line
	strcpy( SubTitle, pcl__gMatch->apcl_mTeamRom[team]->pcz__tCityName );

	// If same teams, distinguish with 'Home' or 'Away'
	if (!stricmp( pcl__gMatch->apcl_mTeamRom[team]->pcz__tCityName,
								pcl__gMatch->apcl_mTeamRom[1-team]->pcz__tCityName ))
	{
		if (team)
			strcat( SubTitle, " - Away" );
		else
			strcat( SubTitle, " - Home" );
	}

	Sub_Reset();
	SetFont( Swiss13 );

	td=pcl__gMatch->apcl_mTeamRam[team];

	for (i=0; i<subNumPlayers; i++)
	{
		// Print incoming player's name
		pd = &td->pcl__tPlyrRam[subIn[i]];
		p = pd->pcl__pPlyrRom->ub___pNum;
		if (p == 100)
			strcpy( msg, "00" );
		else
		{
			*(u32 *)msg = 0;
			IntToDecStr( p, msg );
		}
		strcpy( text, msg );
		strcat( text, "- " );
		strcat( text, pd->pcl__pPlyrRom->pcz__pCName );
		strcat( text, " " );
		strcat( text, pd->pcl__pPlyrRom->pcz__pSName );


		strcat( text, " in for " );


		// Print outgoing player's name
		pd = &td->pcl__tPlyrRam[subOut[i]];
		p = pd->pcl__pPlyrRom->ub___pNum;
		if (p == 100)
			strcpy( msg, "00" );
		else
		{
			*(u32 *)msg = 0;
			IntToDecStr( p, msg );
		}
		strcat( text, msg );
		strcat( text, "- " );
		strcat( text, pd->pcl__pPlyrRom->pcz__pCName );
		strcat( text, " " );
		strcat( text, pd->pcl__pPlyrRom->pcz__pSName );

		if (strlen( text ) > 59)
			FatalError( "Text too long!", __FILE__, __LINE__ );

		Sub_Add( 0, (i*15)+12, text );
	}
}


static Gfx *Sub_Draw( Gfx *gp )
{
	s32
		i,
		x,
		y,
		w,
		width,
		height;

	SetFont( Swiss13 );
	SetAlpha( 255 );

	height = (SubLines * 15) + 15 + 8;
	width =  GetTextWidth( SubTitle ) + 16;

	for (i=0; i<SubLines; i++)
	{
		w = GetTextWidth( SubText[i].Text ) + 16;

		if (w > width)
			width = w;
	}

	x = (SCR_X_RES - width) / 2;
	y = (SCR_Y_RES - height) / 2;

	gp = DrawBox( gp, x, y, width, height );

	gp = DrawHeadline( gp, x, y, width, 13 );

	SetColor( 255, 255, 255 );
	w = (width - GetTextWidth( SubTitle )) / 2;
	gp = DrawText( gp, SubTitle, x+w, y+12 );

	SetColor( 0, 0, 0 );
	for (i=0; i<SubLines; i++)
	{
		w = (width - GetTextWidth( SubText[i].Text )) / 2;
		gp = DrawText( gp, SubText[i].Text, x+w, y+14+15+(i*15) );
	}

	return( gp );
}



static Gfx *DrawFreeThrowHelp( Gfx *gp )
{
	static const char
		*text[] =
		{
			"Press the B Button to start the free throw, then use",
			"the Control Stick to move the target bar",
			"down into the colored part of the meter.",
			"Then press the B Button again to take the shot when",
			"the moving net is lined up with the basket."
		};
	s32
		i,
		x,
		y,
		w,
		width,
		height;

	SetFont( Swiss13 );
	SetAlpha( 255 );
	SetColor( 0, 0, 0 );

	height = (5*15)+(2*8);
	width = 0;

	for (i=0; i<5; i++)
	{
		w = GetTextWidth( text[i] ) + 16;

		if (w > width)
			width = w;
	}

	x = (SCR_X_RES - width) / 2;
	y = (SCR_Y_RES - height) / 2;

	gp = DrawBox( gp, x, y, width, height );

	y += 8+12;
	for (i=0; i<5; i++)
	{
		w = (width - GetTextWidth( text[i] )) / 2;
		gp = DrawText( gp, text[i], x+w, y );
		y += 15;
	}

	return( gp );
}


#define REPLAY_W 320
#define REPLAY_H 56
#define REPLAY_X ((SCR_X_RES-REPLAY_W)/2)

static Gfx *DrawReplay( Gfx *gp )
{
	static const char
		text[] = "Press R Button for Replay Panel";
	u8
		*tex;
	s32
		x = 0,
		w = 32;

	if (ShowReplayPanel)
	{
		tex = &ReplayTex[256*2];

		gp = DrawBox( gp, REPLAY_X-8, SCR_Y_RES-80-8, REPLAY_W+16, REPLAY_H+16 );

		gDPPipeSync( gp++ );
		gDPSetCombineMode( gp++, G_CC_DECALRGBA, G_CC_DECALRGBA );
		gDPSetRenderMode( gp++, G_RM_OPA_SURF, G_RM_OPA_SURF );
		gDPSetTextureLUT( gp++, G_TT_RGBA16 );
		gDPLoadTLUT_pal256( gp++, ReplayTex );

		while (x < REPLAY_W)
		{
			if ((x+w) > REPLAY_W)
				w -= (x+w) - REPLAY_W;

			gDPLoadTextureBlock( gp++,
													 tex,
													 G_IM_FMT_CI,
													 G_IM_SIZ_8b,
													 w, REPLAY_H,
													 0,
													 G_TX_CLAMP,
													 G_TX_CLAMP,
													 5, 6,
													 G_TX_NOLOD,
													 G_TX_NOLOD );

			gSPTextureRectangle( gp++,
													 (REPLAY_X+x)<<2,
													 (SCR_Y_RES-80)<<2,
													 (REPLAY_X+x+w)<<2,
													 (SCR_Y_RES-80+REPLAY_H)<<2,
													 0, 0, 0,
													 1<<10, 1<<10 );

			x += 32;
			tex += (32*REPLAY_H);
		}
	}
	else if (ReplayTextTimer)
	{
		ReplayTextTimer--;

		SetFont( Swiss13 );
		SetAlpha( 255 );
		SetColor( 0, 0, 0 );

		w = GetTextWidth( text );
		gp = DrawText( gp, text, (SCR_X_RES-w)/2, SCR_Y_RES-40 );
	}

	return( gp );
}


Gfx *OverGfx_Draw( Gfx *gp, dyn *d )
{
	int		i,ci;
	int		h;
	int		alpha;
	int		secs,mins,digits[5];
	bool	ltmClock=FALSE;
	int		tx,ty,sx,sy,ww,hh;
	u8*		tex;
	char
		text[32];
	s32
		x,
		y,
		w,
		same;

	if (AttractMode || camLetterBox)
		return( gp );


	gDPSetAlphaCompare( gp++, G_AC_THRESHOLD );
	gDPSetBlendColor( gp++, 0, 0, 0, 8 );


	if (manualReplayFlag)
		gp = DrawReplay( gp );


	// Handle 3-point overlays here
	if (C3PT)
	{
		SetFont( Swiss13 );
		SetAlpha( 255 );
		SetColor( 0, 0, 0 );

		for (i=0; i<Num3PtPlayers; i++)
		{
			char	num[4];
			int		j;

			// Draw the background
			gDPPipeSync(gp++);
			gDPSetTextureLUT(gp++, G_TT_NONE);
			gDPSetCombineMode(gp++,G_CC_DECALRGBA,G_CC_DECALRGBA);
			gDPSetRenderMode(gp++,G_RM_XLU_SURF,G_RM_XLU_SURF);

			sx=Pt3BackXs[Num3PtPlayers-1][i];
			for (y=0; y<Pt3BackH; y+=Pt3BackY)
			{
				h=Pt3BackH-y;
				if (h>Pt3BackY)
					h=Pt3BackY;

				gDPLoadTextureBlock(gp++,&Pt3o->Back[y*Pt3BackW],G_IM_FMT_IA,G_IM_SIZ_8b,
					Pt3BackW,h,0,G_TX_WRAP,G_TX_WRAP,Pt3BackWc,8,G_TX_NOLOD,G_TX_NOLOD);
				gSPTextureRectangle(gp++,sx<<2,(Pt3BackYs+y)<<2,
					(sx+Pt3BackW)<<2,(Pt3BackYs+y+h)<<2,0,0,0,(1<<10),(1<<10));
			}

			for (j=0; j<sizeof(num)/sizeof(num[0]); j++)
				num[j]=0;
			IntToDecStr(player[Human3PtMatchPlayers[i]].Score3,num);
			x = (Num3PtW - GetTextWidth( num )) / 2;
			gp = DrawText( gp, num, sx+x, Num3PtYs+14 );

			// Draw the score bar
			gDPPipeSync(gp++);
			gDPSetTextureLUT( gp++, G_TT_RGBA16 );
			gDPLoadTLUT_pal256( gp++, Pt3o->Pal );
			gDPSetCombineMode(gp++,G_CC_DECALRGBA,G_CC_DECALRGBA);
			gDPSetRenderMode(gp++,G_RM_OPA_SURF,G_RM_OPA_SURF);
			gDPSetBlendColor(gp++,0xff,0xff,0x00,0x08);
			gDPSetAlphaCompare(gp++,G_AC_THRESHOLD);

			sx+=Pt3TopXs;
			sy=Pt3BackYs+Pt3TopYs;
			for (y=Pt3TopH-4*player[Human3PtMatchPlayers[i]].Score3; y<Pt3TopH; y+=Pt3TopY)
			{
				h=Pt3TopH-y;
				if (h>Pt3TopY)
					h=Pt3TopY;

				gDPLoadTextureBlock(gp++,&Pt3o->Top[y*Pt3TopW],G_IM_FMT_CI,G_IM_SIZ_8b,
					Pt3TopW,h,0,G_TX_WRAP,G_TX_WRAP,Pt3TopWc,8,G_TX_NOLOD,G_TX_NOLOD);
				gSPTextureRectangle(gp++,sx<<2,(sy+y)<<2,
					(sx+Pt3TopW)<<2,(sy+y+h)<<2,0,0,0,(1<<10),(1<<10));
			}
		}

		if (end_time<=-ONE_SEC*3)
		{
			gp = DrawContestSummary(gp);
		}
		else
		{
			// Set up the palette
			if (C3PT && time_left>time_mark)
				secs=(time_mark+ONE_SEC-1)/ONE_SEC;
			else
				secs=(time_left+ONE_SEC-1)/ONE_SEC;
			if (secs<0)
				secs=0;
			digits[0]=secs/10;
			digits[1]=secs%10;
			SetLED(Pt3o->Pal,digits[0],32,Pt3o->Pal[215],Pt3o->Pal[216]);
			SetLED(Pt3o->Pal,digits[1],39,Pt3o->Pal[215],Pt3o->Pal[216]);
		
			gDPPipeSync(gp++);
			gDPLoadTLUT_pal256( gp++, Pt3o->Pal );
			for (y=0; y<ShotH; y+=ShotY)
			{
				h=Clock3H-y;
				if (h>Clock3Y)
					h=Clock3Y;

				gDPLoadTextureBlock( gp++,
									 &Pt3o->Clock[Clock3W*y],
									 G_IM_FMT_CI,
									 G_IM_SIZ_8b,
									 Clock3W,
									 h,
									 0,
									 G_TX_WRAP,
									 G_TX_WRAP,
									 7, 6,
									 G_TX_NOLOD, G_TX_NOLOD );
				gSPTextureRectangle( gp++, Clock3X1<<2, (Clock3Ys+y)<<2, (Clock3X1+Clock3W)<<2, (Clock3Ys+y+h)<<2,
					0, 0<<5, 0<<5, (1<<10), (1<<10) );

				if (Num3PtPlayers>1)
					gSPTextureRectangle( gp++, Clock3X2<<2, (Clock3Ys+y)<<2, (Clock3X2+Clock3W)<<2, (Clock3Ys+y+h)<<2,
						0, 0<<5, 0<<5, (1<<10), (1<<10) );
			}
		}
	}


	// Draw menu...
	if (menuFlag && !replay_flag)
	{
		if(SubCard)
		{
			CardCtr = 0;	//fixes bug # 654 - leave player box up in lower right
		}	 
		SubCard = FALSE;

		switch (MenuWhich)
		{
			case MENU_PAUSE:
				gp = DrawPauseMenu( gp );
				break;

			case MENU_CAMERA:
				gp = DrawCamMenu( gp );
				break;

			case MENU_CONTEST:
				gp = Draw3PtMenu( gp );
				break;

			case MENU_PRACTICE:
				gp = DrawPracticeMenu( gp );
				break;

			case MENU_QUIT:
				gp = DrawQuitMenu( gp );
				break;


			case MENU_HINT:
				gp = OverGfx_DrawGameHint( gp, 2 );
				break;
		}
	}


	if (C3PT)
		return( gp );

	// Print practice mode switch crap
	if (PracticeMode)
	{
		SetFont( Swiss13 );
		SetAlpha( 255 );
		SetColor( 255, 255, 255 );

		if (!(replay_flag || menuFlag))
		{
			if (ft_flag || free_throws)
				gp = DrawText( gp, "Press L Button to finish practicing free throws", 10, 270);
			else
			{
				gp=DrawText(gp,"Press L Button to begin practicing free throws",10,270);
			
			}
		}
	}

	if (ShowFreeThrowHelp && !menuFlag &!menuScoreboardFlag)
	{
		gp = DrawFreeThrowHelp( gp );
	}

	if (demoMode)
	{
		DemoFlash--;

		if (DemoFlash & 16)
		{
			SetFont( Swiss13 );
			SetAlpha( 255 );
			SetColor( 0, 0, 0 );
			gp = DrawText( gp, "DEMO", 32, SCR_Y_RES-24 );
		}
	}


	if (SubCard && !gameOver)
	{
		gp = Sub_Draw( gp );

		SubTimer--;
		if (!SubTimer)
			SubCard = FALSE;
	}


	// Draw regular overlay stuff
	// Show Card
	if ((ft_flag || free_throws) && !PracticeMode)
	{
		if (CurrentPlyrType!=CARD_FTS)
		{
			RenderPlayerCard(free_thrower,CARD_FTS);
			CurrentPlyrType=CARD_FTS;
			CardCtr=-1;
		}
	}
	else if (CardCtr<0)
		CardCtr=ONE_SEC*2;

	if (CardDelay)
	{
		// Is it time to display the card yet?
		if (!--CardDelay)
		{
			RenderPlayerCard(PendingPlyr,PendingType);
		}
	}
//	else if (CardCtr && (!(ft_flag || free_throws) && !replay_flag))	// This code is for player cards
	else if (CardCtr && !replay_flag && !ScoreBoardCam)	// This code is for player cards
	{
		CardCtr--;

		SetAlpha( 255 );

		gp = DrawBox( gp, BodyXs, BodyYs, BodyW+16, BodyH );

		gp = DrawHeadline( gp, TopXs, TopYs, BodyW, 13 );

		SetFont( Swiss13 );

		SetColor( 255, 255, 255 );
		gp = DrawText( gp, StatTitle, BodyXs+10, TopYs+12 );

		SetColor( 0, 0, 0 );
		gp = Stat_Draw( gp );
	}

	// Only draw the card counter if in free throws
	if (ft_flag || free_throws)
		return gp;

	gDPPipeSync( gp++ );
	gDPSetRenderMode( gp++, G_RM_OPA_SURF, G_RM_OPA_SURF2 );
	gDPSetCombineMode( gp++, G_CC_DECALRGBA, G_CC_DECALRGBA );
	gSPTexture( gp++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON );
	gDPSetTextureLUT( gp++, G_TT_RGBA16 );

	gDPSetBlendColor(gp++,0xff,0xff,0x00,0x08);
	gDPSetAlphaCompare(gp++,G_AC_THRESHOLD);

	// All the overlays share the same palette
	gDPLoadTLUT_pal256( gp++, Over->Pal );

	// Draw all clocks...

	if (SCORE)
	{
		// Draw shot clock...
		x=SCR_X_RES-TimeW;
		y=(CardCtr)? BodyYs-ShotH-8 : 250-TimeH;

		if (SEC24_CLOCK &&
				time_left &&
				shot_clock < SHOT_ON_TIME &&
				shot_clock<time_left &&
				!replay_flag)
		{
			// Set up the palette
			secs=(shot_clock+ONE_SEC-1)/ONE_SEC;
			if (secs<0)
				secs=0;
			digits[0]=secs/10;
			digits[1]=secs%10;
			SetLED(Over->Pal,digits[0],32,Over->Pal[215],Over->Pal[216]);
			SetLED(Over->Pal,digits[1],39,Over->Pal[215],Over->Pal[216]);
		
			for (y=0; y<ShotH; y+=ShotY)
			{
				h=ShotH-y;
				if (h>ShotY)
					h=ShotY;

				gDPLoadTextureBlock( gp++,
									 &Over->Shot[ShotW*y],
									 G_IM_FMT_CI,
									 G_IM_SIZ_8b,
									 ShotW,
									 h,
									 0,
									 G_TX_WRAP,
									 G_TX_WRAP,
									 7, 6,
									 G_TX_NOLOD, G_TX_NOLOD );
				gSPTextureRectangle( gp++, ShotXs<<2, (ShotYs+y)<<2, (ShotXs+ShotW)<<2, (ShotYs+y+h)<<2,
					0, 0<<5, 0<<5, (1<<10), (1<<10) );
			}
		}

		// Draw time clock...
		y=250;

		// Determine the digits
		secs=time_left+(ONE_SEC/10-1);
		if (secs<0)
			secs=0;
		mins=secs/(ONE_SEC*60);
		secs-=mins*(ONE_SEC*60);
		digits[0]=mins/10;
		digits[1]=mins%10;
		digits[2]=secs/(10*ONE_SEC);
		secs-=digits[2]*10*ONE_SEC;
		digits[3]=secs/ONE_SEC;
		secs-=digits[3]*ONE_SEC;
		digits[4]=secs/(ONE_SEC/10);

		// Setup palette seconds (standard to both formats
		Over->Pal[1]=Over->Pal[2]=Over->Pal[digits[0]? 214:213];
		SetLED(Over->Pal,digits[2],10,Over->Pal[214],Over->Pal[213]);
		SetLED(Over->Pal,digits[3],17,Over->Pal[214],Over->Pal[213]);
		SetLED(Over->Pal,digits[(digits[0]|digits[1])?1:4],3,Over->Pal[214],Over->Pal[213]);

		if (digits[0]||digits[1])	// More than a minute?
		{
			SetLED(Over->Pal,digits[1],3,Over->Pal[214],Over->Pal[213]);
			tex=Over->Time;
		}
		else
		{
			SetLED(Over->Pal,digits[4],3,Over->Pal[214],Over->Pal[213]);
			tex=Over->TimeMin;
		}

		if (!CardCtr && !PracticeMode)
		{
			for (y=0; y<TimeH; y+=TimeY)
			{
				h=TimeH-y;
				if (h>TimeY)
					h=TimeY;

				gDPLoadTextureBlock( gp++,
									 &tex[TimeW*y],
									 G_IM_FMT_CI,
									 G_IM_SIZ_8b,
									 TimeW,
									 h,
									 0,
									 G_TX_WRAP,
									 G_TX_WRAP,
									 7, 6,
									 G_TX_NOLOD, G_TX_NOLOD );

				gSPTextureRectangle( gp++, TimeXs<<2, (TimeYs+y)<<2, (TimeXs+TimeW)<<2, (TimeYs+y+h)<<2,
					0, 0<<5, 0<<5, (1<<10), (1<<10) );

			}
		}
	}


	// Print score

	if (!replay_flag && SCORE)
	{
		if (SB_Delay)
			SB_Delay--;
		else if (SB_Duration)
		{
			SB_Duration--;

			// Determine alpha of score box

			if (SB_Time-SB_Duration<SLIDE_TIME)
				alpha=(SB_Time-SB_Duration)*0xff/SLIDE_TIME;
			else if (SB_Duration<SLIDE_TIME)
				alpha=SB_Duration*0xff/SLIDE_TIME;
			else
				alpha=0xff;

			SetAlpha( alpha );


			// Draw score box

			gp = DrawBox( gp, BoxXs-16, BoxYs, BoxW+16, 32 );


			SetFont( Swiss13 );
			SetColor( 0, 0, 0 );

			// Draw Team Names

			if (!stricmp( TROM(0)->pcz__tName, TROM(1)->pcz__tName ))
				same = TRUE;
			else
				same = FALSE;

			strcpy( text, TROM(0)->pcz__tName );
			strupper( text );
			if (same) strcat( text, " - H" );
			gp = DrawText( gp, text, TeamXs, BoxYs+27 );

			strcpy( text, TROM(1)->pcz__tName );
			strupper( text );
			if (same) strcat( text, " - A" );
			gp = DrawText( gp, text, TeamXs, BoxYs+14 );

			// Draw Scores

			Set8s( text, 0, 8 );
			IntToDecStr( TRAM(0)->uw___tPoints, text );
			w = GetTextWidth( text );
			gp = DrawText( gp, text, BoxW-w-8, BoxYs+27 );

			Set8s( text, 0, 8 );
			IntToDecStr( TRAM(1)->uw___tPoints, text );
			w = GetTextWidth( text );
			gp = DrawText( gp, text, BoxW-w-8, BoxYs+14 );

			
			// Draw Quarter Info

			SetFont( Swiss11 );
			SetColor( 255, 255, 255 );

			gp = DrawText( gp, QuarterText, QtrXs, QtrYs );


			// Draw NBA Logo
			gDPPipeSync( gp++ );
			gDPSetCombineMode( gp++, G_CC_MAN, G_CC_MAN );
			gDPSetBlendColor(gp++,0x00,0x00,0x00,0x08);
			gDPSetAlphaCompare(gp++,G_AC_THRESHOLD);
			gDPLoadTLUT_pal256( gp++, Over->Pal );
			gDPSetTextureLUT( gp++, G_TT_RGBA16 );

			gDPLoadTextureBlock(gp++,Over->Man,G_IM_FMT_CI,G_IM_SIZ_8b,
				ManW,ManH,0,G_TX_WRAP,G_TX_WRAP,8,8,G_TX_NOLOD,G_TX_NOLOD);
			gSPTextureRectangle(gp++,ManXs<<2,ManYs<<2,(ManXs+ManW)<<2,(ManYs+ManH)<<2,
				0,0,0,(1<<10),(1<<10));
		}
	}


	if (!C3PT && DC_Play)
	{
		char	*ps;

		DC_Play--;
		SetFont( Swiss13 );
		SetColor( 255, 255, 255 );
		ps=Plays[ai_team[ball_handler/5].current_set];
		w=GetTextWidth(ps);

		gp=DrawText( gp, ps, (SCR_X_RES-w)/2, 40);
	}

	// Draw turbo
	if (pcl__gPreferences->sb___IndicateTurbo && !replay_flag)
	{
		for (i=0; i<10; i++)
		{
			playert	*plyr;

			if (!(ci=(plyr=&player[i])->control))
				continue;

			sx=((ci-1)&1)? TurboX2 : TurboX1;
			sy=((ci-1)&2)? TurboY2 : TurboY1;

			// Draw the turbo background
			gDPPipeSync( gp++ );
			gDPSetRenderMode(gp++,G_RM_XLU_SURF,G_RM_XLU_SURF);
			gDPSetCombineMode(gp++,G_CC_DECALRGBA,G_CC_DECALRGBA);
			gDPSetTextureLUT( gp++, G_TT_NONE );
			gDPSetBlendColor(gp++,0x00,0x00,0x00,0x08);
			gDPSetAlphaCompare(gp++,G_AC_THRESHOLD);

			for (y=0; y<TurboH; y+=TurboY)
			{
				h=TurboH-y;
				if (h>TurboY)
					h=TurboY;

				gDPLoadTextureBlock(gp++,&Over->TurboB[y*TurboW],G_IM_FMT_IA,G_IM_SIZ_8b,
					TurboW,h,0,G_TX_WRAP,G_TX_WRAP,TurboWc,8,G_TX_NOLOD,G_TX_NOLOD);
				gSPTextureRectangle(gp++,sx<<2,(sy+y)<<2,(sx+TurboW)<<2,(sy+y+h)<<2,
					0,0,0,(1<<10),(1<<10));
			}

			// Draw the turbo foreground
			if (plyr->max_turbo)
			{
				int
					turbo;

				gDPPipeSync( gp++ );
				gDPSetRenderMode(gp++,G_RM_OPA_SURF,G_RM_OPA_SURF);
				gDPSetBlendColor(gp++,0x00,0x00,0x00,0x08);
				gDPSetAlphaCompare(gp++,G_AC_THRESHOLD);
				gDPSetCombineMode(gp++,G_CC_DECALRGBA,G_CC_DECALRGBA);
				gDPLoadTLUT_pal256( gp++, Over->Pal );
				gDPSetTextureLUT( gp++, G_TT_RGBA16 );

				turbo = plyr->turbo;
				if (turbo > plyr->max_turbo)
					turbo = plyr->max_turbo;

				ww=TurboIw*turbo/plyr->max_turbo;
				for (y=0; y<TurboH; y+=TurboY)
				{
					h=TurboH-y;
					if (h>TurboY)
						h=TurboY;

					gDPLoadTextureBlock(gp++,&Over->TurboF[y*MomW],G_IM_FMT_CI,G_IM_SIZ_8b,
						TurboW,h,0,G_TX_WRAP,G_TX_WRAP,TurboWc,8,G_TX_NOLOD,G_TX_NOLOD);
					gSPTextureRectangle(gp++,sx<<2,(sy+y)<<2,(sx+ww+TurboIx)<<2,(sy+y+h)<<2,
						0,0,0,(1<<10),(1<<10));
				}
			}

			SetFont( Swiss13 );
			SetColor( 255, 255, 255 );
			SetAlpha( 255 );

			text[0] = ci + '0';
			text[1] = 0;

			gp = DrawText( gp, text, sx+CharXs, sy+CharYs );
		}
	}

	// Draw momentum meter
	if (pcl__gPreferences->sb___MomentumMeter && !replay_flag && !PracticeMode)
	{
		gDPPipeSync( gp++ );
		gDPSetRenderMode(gp++,G_RM_XLU_SURF,G_RM_XLU_SURF);
		gDPSetCombineMode(gp++,G_CC_DECALRGBA,G_CC_DECALRGBA);
		gDPSetTextureLUT( gp++, G_TT_NONE );
		gDPSetBlendColor(gp++,0x00,0x00,0x00,0x08);
		gDPSetAlphaCompare(gp++,G_AC_THRESHOLD);

		// Draw the meter background
		for (y=0; y<MomH; y+=MomY)
		{
			h=MomH-y;
			if (h>MomY)
				h=MomY;

			gDPLoadTextureBlock(gp++,&Over->MomB[y*MomW],G_IM_FMT_IA,G_IM_SIZ_8b,
				MomW,h,0,G_TX_WRAP,G_TX_WRAP,MomWc,8,G_TX_NOLOD,G_TX_NOLOD);
			gSPTextureRectangle(gp++,MomXs<<2,(MomYs+y)<<2,(MomXs+MomW)<<2,(MomYs+y+h)<<2,
				0,0,0,(1<<10),(1<<10));
		}

		// Draw the meter foreground
		if (momentum)
		{
			gDPPipeSync( gp++ );
			gDPSetRenderMode(gp++,G_RM_OPA_SURF,G_RM_OPA_SURF);
			gDPSetBlendColor(gp++,0x00,0x00,0x00,0x08);
			gDPSetAlphaCompare(gp++,G_AC_THRESHOLD);
			gDPSetCombineMode(gp++,G_CC_DECALRGBA,G_CC_DECALRGBA);
			gDPLoadTLUT_pal256( gp++, Over->Pal );
			gDPSetTextureLUT( gp++, G_TT_RGBA16 );

			ww=momentum*68/100;
			if (mom_team)	// Away team
				sx=69-ww;
			else			// Home team
				sx=74;

			for (y=0; y<MomHo; y+=MomY)
			{
				h=MomHo-y;
				if (h>MomY)
					h=MomY;

				gDPLoadTextureBlock(gp++,&Over->MomF[y*MomW],G_IM_FMT_CI,G_IM_SIZ_8b,
					MomW,h,0,G_TX_WRAP,G_TX_WRAP,MomWc,8,G_TX_NOLOD,G_TX_NOLOD);
				gSPTextureRectangle(gp++,(MomXs+sx)<<2,(MomYs+y)<<2,(MomXs+sx+ww)<<2,(MomYs+y+h)<<2,
					0,sx<<5,0,(1<<10),(1<<10));
			}
		}


		if (!stricmp( TROM(0)->pcz__tAbbr, TROM(1)->pcz__tAbbr ))
			same = TRUE;
		else
			same = FALSE;

		SetFont( Swiss13 );
		SetAlpha( 255 );
		SetColor( 255, 255, 255 );

		y = MomYs+16;
		sx = 230-36;
		tx = 230+36;

		if (same)
		{
			w = GetTextWidth( "A" );
			gp = DrawText( gp, "A", sx-(w/2), y );

			w = GetTextWidth( "H" );
			gp = DrawText( gp, "H", tx-(w/2), y );
		}
		else
		{
			w = GetTextWidth( TROM(1)->pcz__tAbbr );
			gp = DrawText( gp, TROM(1)->pcz__tAbbr, sx-(w/2), y );

			w = GetTextWidth( TROM(0)->pcz__tAbbr );
			gp = DrawText( gp, TROM(0)->pcz__tAbbr, tx-(w/2), y );
		}
	}

	return( gp );
}


void OverGfx_QuarterInit(int q)
{
	static const char
		*numtext[] =
		{
			"1st",
			"2nd",
			"3rd",
			"4th",
			"5th",
			"6th",
			"7th",
			"8th",
			"9th",	// Placeholder to deter crashing due to order of call
		};

	// Initialize (nothing) for 3 point contest here
	if (C3PT)
	{
		QuarterText[0] = 0;
		return;
	}

	if (q < 4)
	{
		strcpy( QuarterText, numtext[q] );
		strcat( QuarterText, " Quarter" );
	}
	else
	{
		strcpy( QuarterText, numtext[q-4] );
		strcat( QuarterText, " Overtime Period" );
	}
}



	void
SetLED
	(
	RGBA16	*p,			// Palette to update
	int		n,			// Number to display in LED
	int		o,			// Offset to first palette index of LED
	RGBA16	on,			// Color of lit segment
	RGBA16	off			// Color of unlit segment
	)
{
	int	i;
	int	mask;
	int	segs;

	segs=LEDs[n];

	for (i=0,mask=1; i<7; i++,mask<<=1)
		p[o+i]=(segs&mask)? on : off;
}


	void
FormatNum
	(
	char	*text,
	int		n
	)
{
	int	p;

	p=PutDigit(text,n);
	text[p]=0;
}



	int
PutDigit
	(
	char	*text,
	int		n
	)
{
	char	d;
	int		nn;
	int		p;

	nn=n/10;
	d=n-nn*10;

	if (nn)
	{
		text[p=PutDigit(text,nn)]='0'+d;
		return p+1;
	}
	else
	{
		text[0]='0'+d;
		return 1;
	}
}


	void
OverGfx_ShowScore
	(
	int	delay,
	int duration
	)
{
	if (!PracticeMode)
	{
		SB_Delay=delay;
		SB_Time=SB_Duration=duration+ONE_SEC;
	}
}

void OverGfx_ShowPlayerCard
	(
	int	no,			// Player number
	int	type,		// Card type
	int	duration	// Length of time to show card
	)
{
	// Should the card be shown?
	if (PracticeMode)
		return;

	if (CardCtr)		// Not if another card is already up
		return;

	if (shot_clock<SHOT_ON_TIME)	// Do not put up if player card present
		return;

	if (!pcl__gPreferences->sb___ShowStatistics)	// Not if turned off
		return;

	if (time_left<ONE_MIN)	// Do not show stats in last minute of quarter
		return;

	// If a card is pending, supersede it with this one
	if (CardDelay)
	{
		PendingPlyr=no;
		PendingType=type;
		PendingCardType=CARD_TYPE_PLAYER;
		return;
	}

	// Put up the pretty card
	CardCtr=duration;
	CardDelay=0;
	CurrentCardType=CARD_TYPE_PLAYER;
	CurrentPlyrType=type;
	RenderPlayerCard(no,type);
}


void OverGfx_ShowTeamCard
	(
	int	team,
	int	type,		// Card type
	int	duration	// Length of time to show card
	)
{
	if (PracticeMode)
		return;

	if (type == CARD_TYPE_DQ)
	{
		SubCard = TRUE;
		SubTimer = duration;
		Sub_Setup( team );
		return;
	}

	// Should the card be shown?

// only other thing is timeout - make sure it has top priority (overwrite any current 9/29/99 -mjk)
//	if (CardCtr)		// Not if another card is already up
//		return;

	//if (shot_clock<SHOT_ON_TIME)	// Do not put up if player card present
	//	return;

	//if (!pcl__gPreferences->sb___ShowStatistics)	// Not if turned off
	//	return;

	//if (time_left<ONE_MIN)	// Do not show stats in last minute of quarter
	//	return;

	// If a card is pending, supersede it with this one
	if (CardDelay)
	{
		CardDelay = 0;
		PendingPlyr=-1;
//		PendingType=type;
//		PendingCardType=CARD_TYPE_TEAM;
//		return;
	}

	// Put up the pretty card
	CardCtr=duration;
	CardDelay=0;
	CurrentCardType=CARD_TYPE_TEAM;
	CurrentPlyrType=type;
	RenderTeamCard(team,type);
}




#define	GS(x)	plyr->plyrRAM->cl___pStatGame.uw___p##x
#define	EGS(x)	plyr->plyrRAM->ExtraPlayerGameStats.Num##x
#undef SS
#define	SS(x)	stats->uw___p##x

int pc_tw = BodyW-10-16;	// BodyW=192 (title starts 10 in from left





static void RenderPlayerCard(int no, int type)
{
	int		i,j;
	int		jn;			// Jersey number
	int		asf;		// Average significant figures
	char	txt[64];
	playert	*plyr;
	int		stat,avg,att;
	int		avgn,avgd;
	int		points;
	char	*msg;
	char	*amsg;
	bool	pct;
	PlyrRamStat_T	*stats;

	if (PracticeMode || SubCard)	// SubCard and Player card share StatText - Subcard has priority
		return;

	if(no < 0 || no > 9 )
		return;

	plyr=&player[no];
	asf=1;		// Default is 1 digit past the decimal point
	att=-1;		// Indicate no attempted stat
	pct=FALSE;

//	if (plyr->plyrRAM->cl___pStatPlayoff.uw___pGP)
	if (sb___gPlyRound >= 0)			// Playoffs.
	{
		stats=&plyr->plyrRAM->cl___pStatPlayoff;
		amsg="Playoff Avg.";
	}
//	else if (plyr->plyrRAM->cl___pStatSeason.uw___pGP)
	else if (pcl__gOptions->sw___SeasonMatch)			// Season.
	{
		stats=&plyr->plyrRAM->cl___pStatSeason;
		amsg="Season Avg.";
	}
	else
	{
		stats=&plyr->plyrROM->cl___pStatNBA;
		amsg="98-99 Avg.";
	}

	// Render the title line
	jn=plyr->plyrROM->ub___pNum;
	if (jn==100)
		strcpy(StatTitle,"00-");
	else if (jn<10)
	{
		StatTitle[0]=jn+'0';
		StatTitle[1]='-';
		StatTitle[2]=0;
	}
	else
	{
		StatTitle[0]=(jn/10)+'0';
		StatTitle[1]=(jn%10)+'0';
		StatTitle[2]='-';
		StatTitle[3]=0;
	}
/*******
	strcat(StatTitle,plyr->plyrROM->pcz__pCName);
	strcat(StatTitle," ");
	strcat(StatTitle,plyr->plyrROM->pcz__pSName);
********/

	SetFont( Swiss13 );
	BuildPlayerName1(plyr->plyrROM, txt, pc_tw);	// condenses if too big

	strcat(StatTitle,txt);

	// Get the stat information
	switch(type)
	{
		case CARD_STEAL:
			stat=GS(STL);
			avgn=SS(STL)*10;
			avgd=stats->uw___pGP;
			msg="Steals";
			break;

		case CARD_TO:
			stat=GS(TO);
			avgn=SS(TO)*10;
			avgd=stats->uw___pGP;
			msg="TO's";
			return;

		case CARD_ASSIST:
			stat=GS(AST);
			avgn=SS(AST)*10;
			avgd=stats->uw___pGP;
			msg="Assists";
			break;

		case CARD_FGS:
			stat = GS(FGM)+GS(3PM) + EGS(5PM)+ EGS(10PM)+ EGS(15PM);
			att =  GS(FGA)+GS(3PA) + EGS(5PA)+ EGS(10PA)+ EGS(15PA);

			// following addresses bug #707 ( notice I didn't say "fixes") 
			if(stat < 0)	
			{
#if DEBUG				
				BRK;
#endif
				stat = 0;	
			}			
			
			if(att < 0)	
			{
#if DEBUG				
				BRK;
#endif
				att = 0;	
			}			

			avgn=(SS(FGM)+SS(3PM))*10000;
			avgd=SS(FGA)+SS(3PA);
			msg="Field Goals";
			asf=2;
			pct=TRUE;
			break;

		case CARD_3PTS:
			stat=GS(3PM);
			att=GS(3PA);
			avgn=SS(3PM)*10000;
			avgd=SS(3PA);
			msg="3 Pt.";
			asf=2;
			pct=TRUE;
			break;

		case CARD_FTS:
			stat=GS(FTM);
			att=GS(FTA);
			avgn=SS(FTM)*10000;
			avgd=SS(FTA);
			msg="Free Throws";
			asf=2;
			pct=TRUE;
			break;

		case CARD_REB:
			stat=GS(OFF)+GS(DEF);
			avgn=(SS(OFF)+SS(DEF))*10;
			avgd=stats->uw___pGP;
			msg="Rebounds";
			break;

		case CARD_BLOCK:
			stat=GS(BLK);
			avgn=SS(BLK)*10;
			avgd=stats->uw___pGP;
			msg="Blocks";
			break;

		case CARD_FOUL:
			stat=GS(PF);
			avgn=SS(PF)*10;
			avgd=stats->uw___pGP;
			msg="Fouls";
			if (plyr->plyrRAM->cl___pStatGame.uw___pDQ)
			{
				CardCtr=0;
				return;
			}
			break;

		default:
			BRK;
	}

	Stat_Reset();

	// Render the body text
	Stat_Add( HeadingX, Line1Y, msg );
	Stat_Add( HeadingX, Line2Y, amsg );
	Stat_Add( HeadingX, Line3Y, "Points" );

	// Render the stat number
	Set8s( txt, 0, 16 );
	IntToDecStr(stat,txt);
	if (type == CARD_FTS || att>0)	// Show the stats line
	{
		strcat(txt,"/");
		IntToDecStr(att,txt+strlen(txt));
	}
	Stat_Add( NumX, Line1Y, txt );

	//	Render the average number
	if (avgd)
	{
		avg=avgn/avgd;
		txt[0]=txt[1]=txt[2]=txt[3]=txt[4]=txt[5]=txt[6]=txt[7]=txt[8]=0;
		IntToDecStr(avg,txt);
		i=strlen(txt);
		if (!i)		// Nothing, assume zero
			strcpy(txt,"0");
		else if (i<=asf)		// Less than 1
		{
			for (j=asf; j>asf-i; j--)
				txt[j+1]=txt[j-i];
			for (j=0; j<asf-i; j++)
				txt[j+2]='0';
			txt[0]='0';
			txt[1]='.';
		}
		else	// Greater than
		{
			for (j=0; j<asf; j++)
				txt[i-j]=txt[i-j-1];
			txt[i-asf]='.';
		}
		if (pct)
			strcat(txt,"%");

		Stat_Add( NumX, Line2Y, txt );
	}
	else
		Stat_Add( NumX, Line2Y, "N/A" );

	// Render the points
	stat = GS(FTM) + GS(FGM)*2 + GS(3PM)*3 + EGS(5PM)*5 + EGS(10PM)*10 + EGS(15PM)*15;
	Set8s( txt, 0, 8 );
	IntToDecStr(stat,txt);
	Stat_Add( NumX, Line3Y, txt );
}


void OverGfx_ResetCard(void)
{
	CardDelay=CardCtr=0;
	CurrentCardType=CARD_TYPE_NONE;
}

static char *nummies[]=
				{
				"1st",
				"2nd",
				"3rd",
				"4th",
				"5th",
				"6th",
				"7th",
				"8th",
				"9th"
				};

static void RenderTeamCard(int team, int type)
{
	int		i, p;
	char	msg[32];
	TeamRamData_T	*td;
	PlyrRamData_T	*pd;
	char
		text[64];
	s32
		x;

	if (PracticeMode)
		return;

	// Render the title line
	strcpy( StatTitle, pcl__gMatch->apcl_mTeamRom[team]->pcz__tCityName );

	// If same teams, distinguish with 'Home' or 'Away'
	if (!stricmp( pcl__gMatch->apcl_mTeamRom[team]->pcz__tCityName,
								pcl__gMatch->apcl_mTeamRom[1-team]->pcz__tCityName ))
	{
		if (team)
			strcat( StatTitle, " - Away" );
		else
			strcat( StatTitle, " - Home" );
	}

	Stat_Reset();
	SetFont( Swiss13 );

	switch(type)
	{
		case CARD_TYPE_TIMEOUT:
/*** following doesn't work in overtime - use # remaining
			i = GetNumberTimeOutsRemaining(team);
			strcpy(msg,nummies[MAX_TIMEOUTS - i]);
			strcat(msg," Time-Out Called");
			Stat_Add( HeadingX, Line1Y, msg );
*********/
			i = GetNumberTimeOutsRemaining(team);
			msg[0]=i+'0';	// poor mans int2str
			msg[1] = 0;

			strcpy(text,"Time-Out Called - ");

			strcat( text, msg );
			strcat( text, " Remaining");

			Stat_Add( HeadingX, Line1Y, text);

//			Stat_Add( HeadingX, Line2Y, text);

			break;

		case CARD_TYPE_DQ:
			td=pcl__gMatch->apcl_mTeamRam[team];

			for (i=0; i<subNumPlayers; i++)
			{
				// Print incoming player's name
				pd = &td->pcl__tPlyrRam[subIn[i]];
				p = pd->pcl__pPlyrRom->ub___pNum;
				if (p == 100)
					strcpy( msg, "00" );
				else
				{
					*(u32 *)msg = 0;
					IntToDecStr( p, msg );
				}
				strcpy( text, msg );
				strcat( text, "- " );
				strcat( text, pd->pcl__pPlyrRom->pcz__pCName );
				strcat( text, " " );
				strcat( text, pd->pcl__pPlyrRom->pcz__pSName );


				strcat( text, " in for " );


				// Print outgoing player's name
				pd = &td->pcl__tPlyrRam[subOut[i]];
				p = pd->pcl__pPlyrRom->ub___pNum;
				if (p == 100)
					strcpy( msg, "00" );
				else
				{
					*(u32 *)msg = 0;
					IntToDecStr( p, msg );
				}
				strcat( text, msg );
				strcat( text, "- " );
				strcat( text, pd->pcl__pPlyrRom->pcz__pCName );
				strcat( text, " " );
				strcat( text, pd->pcl__pPlyrRom->pcz__pSName );

				if (strlen( text ) > 59)
					FatalError( "Text too long!", __FILE__, __LINE__ );

				Stat_Add( 0, (i*15)+12, text );
			}
			break;
	}
}


void OverGfx_UpdatePlayerCard(void)
{
	switch(CurrentPlyrType)
	{
		case CARD_FTS:
			RenderPlayerCard(free_thrower,CARD_FTS);
			break;
	}
}


#define MAX_HINTS	(42-1-1)

char * GameHints[MAX_HINTS+1] = {
// Tip #01

"To Shoot: Press and hold the B Button to begin your shot attempt. Release the B Button at the top of your player's jump for the best shot release.",

// Tip #02

"Pass the ball around to the open man and then shoot. If you shoot with a defender guarding you tight, your chances of hitting the shot will decrease dramatically.",

// Tip #03

"Some of the NBA Superstars have their own unique signature moves. Experiment with different players to find them all!",

// Tip #04

"Arcade Mode Only: Try to find special 'Sonic Boom' dunks that will level your opponents. These dunks will really raise the momentum meter in your favor.",

// Tip #05

"By pressing the Down C Button while you have the ball, you can switch the hand you are using to dribble. Try switching your dribble away from the closest defender to decrease his chances of stealing it.",

// Tip #06

//"The Up C Button will pass the ball to the teammate closest to the hoop. While this is normally a risky pass, if the player is wide open it can result is an easy score or even an Alley-Oop!!!",
  "The Up C Button will pass the ball to the teammate closest to the hoop. While this is normally a risky pass, if the player is wide open it can result in an easy score or even an Alley-Oop!!!",

// Tip #07

"If you press the Down C Button on defense, you will switch control to the defender that is closest to the ballhandler. Pressing it again will switch to the second closest. This is a great way to apply pressure and then quickly switch to jump into the passing lane for a steal.",

// Tip #08

"If you press the Up  C Button on defense, you will switch control to the defender that is closest to the hoop. This is a great way to catch up to a player that has just passed you, or a quick way to set up for a rebound on a missed shot.",

// Tip #09

"Having trouble keeping up with the offense? Try turning on the AUTO SWITCH option in the Preferences screen. This will automatically switch your control to the defender that is the closest to the ball.",

// Tip #10

"You can win the Tip-off by pressing the B Button faster than your opponent. Winning the Tip-off will give you the ball at the start of the 1st and 4th quarters.",

// Tip #11

"Be sure to check the player ratings to find each player's strengths and weaknesses. You can view them from the Stats option by toggling to the player and pressing the Left or Right C Button to view the ratings category.",

// Tip #12

"If Pro control has you all thumbs, try starting out with Rookie control. The CPU will automatically switch the ball to the correct hand, call for a pick, cut to the hoop, backdown in the post, call for the ball when they are open, and more.",

// Tip #13

"You can greatly increase your chances of intercepting a pass by placing yourself between the ball and the intended receiver and pressing the A (Steal) Button at the correct moment.",

// Tip #14

//"You can press and hold the Right C Button to intentionally foul. This is mainly helpful at the end of a game when you are losing and your opponent can run down the shot clock. Be careful though, because if you intentionally foul a player without the ball you will get called for a flagrant foul.",
  "You can press and hold the Right C Button to intentionally foul. This is mainly helpful at the end of a game when you are losing and your opponent can run down the shot clock. Be careful, though, because if you intentionally foul a player without the ball you will get called for a flagrant foul.",

// Tip #15

"If you turn fatigue on, you must keep a close watch on your player's energy level. When players are tired they move slower, shoot at a lower percentage, and are less effective in general.",

// Tip #16

//"If you hold the R Button while on defense, your player will go into the defensive shuffle mode. While in this mode, steal swipes will be more effective and you will be able to guard players backing down in the post more easily. However, your overall movement will be slower and it will be easier to get beaten by the defender with turbo and special dribble moves.",
  "If you hold the R Button while on defense, your player will go into the defensive shuffle mode. While in this mode, steal swipes will be more effective and you will be able to guard players backing down in the post more easily. However, your overall movement will be slower and it will be easier to get beaten by your opponent with turbo and special dribble moves.",

// Tip #17

"By selecting Ladder Draft, the pick order is flipped for Round #2. For example, the team that picked last in Round #1 would be first in Round #2. This mode matches Fantasy Basketball drafts while the standard mode matches the real NBA draft.",

// Tip #18

"Think you have what it takes to get an inexperienced rookie to the NBA Finals? Select Create Player and create a Career Player. Career Players start with a very low player ratings which can be improved by using them in Season and Playoff games.",

// Tip #19

"There are two ways to power-up a Career Player's ratings. The normal way is by 'collecting' stats in each category to add to the power bar. When each category's power bar fills, that category will raise a level. The second and fastest way is with outstanding performances in a game. For example, 10 assists in one game may raise you an entire level.",

// Tip #20

"Think you're a one-player show on the floor? Maybe you have a favorite player and want to stick with them all game? Go to the Team Settings screen and assign that player to your controller. You will now be locked as him and won't have to worry about anyone else on the court.",

// Tip #21

//"Want to keep track of every stat you have compounded while playing? Select Custom User from the Main Menu screen. Once you set one up, select your Custom User from the Controller Select screen before each game. Return to Custom User and select 'View' to see your Career stats.",
  "Want to keep track of every stat you have accumulated while playing? Select Custom User from the Main Menu screen. Once you set one up, select your Custom User from the Controller Select screen before each game. Return to Custom User and select 'View' to see your career stats.",

// Tip #22

"3-Point Contest: Use the Left C Button to pick up a ball from the rack. Then press and hold the B Button to begin the shot. Release the B Button at the top of the jump for the highest percentage shot release.",

// Tip #23

"Lightly tapping the B Button when you have the ball will perform a Pump Fake. If timed correctly, you may get your defender to jump at the fake, leaving you wide open to shoot when he lands.",

// Tip #24

"Lightly tapping the R Button when you have the ball will perform a Spin Dribble. You can use this move to get past tough defenders, or to create some space for open shots.",

// Tip #25

"If you enter Create Player and choose to create a non-career player, your attribute rating points will be unlimited.",

// Tip #26

//"Better dribblers can fake slow defenders by pressing the Left C Button to perform a special dribble. If the defense is slow to collapse, you can score an easy basket!",
  "Better dribblers can fake slow defenders by pressing the Left C Button to perform a special dribble. If the defense is slow to react, you can score an easy basket!",

// Tip #27

"Sim Season Mode too slow for you after playing the fast-paced Arcade Mode? Go to the options screen and change the game speed until the bar is full. This will allow you to play Sim Season Mode at Arcade Mode speed.",

// Tip #28

"There are three ways to break an opposing team's full momentum meter in Arcade Mode. You can wait until the quarter ends, perform a 'Sonic Boom' dunk on them, or hit from the Hot Spot. Once their momentum meter is decreased, they will lose all super abilities.",

// Tip #29

"If you fill your momentum meter in Arcade Mode, your team will get special abilities. They will have passes that are faster and harder to intercept, a higher overall shooting percentage, faster and more effective special dribbles, and the ability to super dunk from just inside the 3-Point line.",

// Tip #30

"Found any codes yet? One way to find some is by pressing the C Buttons in different combinations while you are on the Team Select Screen.",

// Tip #31

"Check http://www.nintendosports.com for all the latest inside strategies and tips on NBA Courtside 2. You may even find some special codes!",

// Tip #32

//"Milk... it does a body good.",

// Tip #33

"Make sure you look left, right and then left again before crossing the street!",

// Tip #34

"Be sure not to reset or turn the power off while the game is saving. This may result in unrecoverable data loss.",

// Tip #35

"This above all: to thine own self be true - Shakespeare",

// Tip #36

"Lightly tap the Right C Button when you have the ball to call for a pick. When you do this, the teammate with the passing cursor will try to 'pick' your defender so you can go right past him. Be careful, though, because other defenders may pick up on it and switch off their man to cover you.",

// Tip #37

"Press and hold the A Button when you have the ball to initiate a give and go. This will pass the ball to the teammate with the passing icon under him. When he receives the pass, this player will remain under CPU control and your initial passer will remain under your control. Now you can move around to get open before the CPU passes the ball back to you.",

// Tip #38

//"Press the Right C Button on offense to make the CPU teammate with the passing icon under them cut to the hoop. If you are careful not to press the analog stick, you can simply hit the B Button to pass it to him as he heads for the hoop.",
  "Press the Right C Button on offense to make the CPU teammate with the passing icon under him cut to the hoop. If you are careful not to press the Control Stick, you can simply hit the B Button to pass it to him as he heads for the hoop.",

// Tip #39

//"The brown paper bag over your drink thing... it isn't fooling anyone!",

// Tip #40

"If you want to play a multi-player game, make sure all of the controllers you will be playing with are inserted before you power-up the system.",

// Tip #41

"If your current offensive strategy isn't working well, use the + Control Pad and the L Button to call different plays. You can call eight different sets.",

// Tip #42

"Press the Z and R Buttons together to switch to icon passing. Now you can tap the appropriate button to pass to a teammate, or hold the button to make a player break to the basket.",

//
//"Do not place in rectum."

NULL,

};




static void AddStatBoxText(char *string)
{
char	*p,*w,*lw,*lp;
char	line[80];
//int		linecount;
int		firstWord,done;

	p = string;
	
	done = 0;
//	linecount = 0;

	while(!done)
	{
		w = line;
		*w = 0;
		firstWord = 1;
		lp = p;

		while(1)
		{
			// get start of next word...
			for(; *p; p++)
			{
				if((*p) != ' ')
				{
					 break;
				}
			}
			
			if(!(*p))	// hit end??
			{	
				done = 1;
				break;
			}

			// add space?
			if(!firstWord)
			{
				*(w++) = ' ';
			}
			firstWord = 0;

			lw = w;

			// write word...
			while(1)
			{
				if((*p) == ' ' || !(*p))
				{
					break;
				}
				*w = *p;
				w++; p++;
			}
			*w = 0;

			if( strlen(line) >= 58)
			{	// too long, restore last pointers to last word
				w = lw;
				p = lp;
				*w = 0;
				break;
			}
			lp = p;
		}


//		Stat_Add( 0, (linecount*15)+12, line );

		strcpy(HintText[HintLineCount++].Text, line );

//		linecount++;
	}

}


int OverGfx_BuildNextHint( int dir, int buttons )
{

#if	1	//def DEBUG
//	if(CardCtr <= 0)
	{
		HintCounter += dir;
		if(HintCounter < 0)
			HintCounter = MAX_HINTS-1;
		else if(HintCounter >= MAX_HINTS)
			HintCounter = 0;

		if(GameHints[HintCounter] == NULL)
		{
			HintCounter = 0;
		}

//		strcpy(StatTitle,"Game Hints - Press the B Button to Exit");
//		Stat_Reset();
		strcpy(HintText[0].Text,"Game Hints");

		if (buttons)
		{
			strcpy(HintText[1].Text,"Press the B Button to Exit, Left/Right to Change");
			HintLineCount = 2;
		}
		else
			HintLineCount = 1;

		AddStatBoxText(GameHints[HintCounter]);


//		SubCard = 1;
//		CardCtr = StatCount * 4 * ONE_SEC;

//		ShowFreeThrowHelp = FALSE;

	}

	return(HintLineCount);	// number of lines
#endif

}


Gfx *OverGfx_DrawGameHint( Gfx *gp, s32 title_lines )
{
	s32
		i,
		x,
		y,ty,
		w,
		width,
		height;

	SetFont( Swiss13 );
	SetAlpha( 255 );

	height = (HintLineCount * 15) + 6;
	width = 0;

	for (i=0; i<HintLineCount; i++)
	{
		w = GetTextWidth( HintText[i].Text ) + 16;

		if (w > width)
			width = w;
	}

	x = (SCR_X_RES - width) / 2;
	y = (SCR_Y_RES - height) / 2 ;

	gp = DrawBox( gp, x, y, width, height );

	gp = DrawHeadline( gp, x, y, width, 29-((2-title_lines)*15) );

	ty = y+12;
 	
	for (i=0; i<HintLineCount; i++)
	{
		if (i < title_lines)
		{
			SetColor( 255, 255, 255 );
			ty = y+13 + i *13;
		}
		else
		{
			SetColor( 0, 0, 0 );
			ty = y+28-15 +(i*15);
		}
		w = (width - GetTextWidth( HintText[i].Text )) / 2;
		gp = DrawText( gp, HintText[i].Text, x+w, ty);
	}

	return( gp );
}


/***********************    end of file: overgfx.c  *************************/
