#include "main.h"
#include "subgame.h"
#include "puzzles.h"
#include "overlays.h"
#include "gametext.h"
#include "maths.h"
#include "debris.h"
#include "custom.h"
#include "map_draw.h"
#include "ranges.h"
#include "loadsnd.h"
#include "sound.h"
#include <islsfx2.h>


int SFX_PITCH_RAND = 256;

// for debugging purposes
ACTOR *myactor;

int subGameRestart;

// ====================================================================================================
void moveActorTowardsCamera(ACTOR* actor, int dist)
{
	VECTOR v;
	long m;

	v.vx =  mycamera.vpx - actor->position.vx;
	v.vy =  mycamera.vpy - actor->position.vy;
	v.vz =  mycamera.vpz - actor->position.vz;

	m = Magnitude(&v);
	SCALEVECTOR(&v, (4096*dist)/m);
	ADDTOVECTOR(&actor->position, &v);
}


// ====================================================================================================
int getWorldPosOfBone(ACTOR* actor, char *bone, VECTOR *res)
{

	long t[3];
	static VECTOR org = {0,0,0};


	PSIOBJECT *child, *parent;
	VECTOR parentPos;
			// calculate chickenpos
			// temp

	actorSetAnimation(actor, actor->animation.animData[0].actualFrame);

	parent = actor->psiData.object;
	
	ASSERT(parent);

	child = psiObjectScan(parent, bone);

	ASSERT(child);

	t[0] = GsWSMATRIX.t[0];
	t[1] = GsWSMATRIX.t[1];
	t[2] = GsWSMATRIX.t[2];
	GsWSMATRIX.t[0] = 0;
	GsWSMATRIX.t[1] = 0;
	GsWSMATRIX.t[2] = 0;
	gte_SetTransMatrix(&GsWSMATRIX);

	if((parent->rotate.vx) || (parent->rotate.vy) || (parent->rotate.vz))
	{
		MATRIX		rotmat1;
		RotMatrixYXZ_gte(&parent->rotate,&rotmat1);

		gte_SetRotMatrix(&rotmat1);
	//			gte_SetTransMatrix	// not doing an rtirtr, so we don't need so set the tx to zero
		gte_ldlvl(&parent->matrix.t);
		gte_rtir();
		gte_stlvl(&parent->matrix.t);
	}

	parent->matrix.t[0] += actor->position.vx;
	parent->matrix.t[1] += actor->position.vy;	// + (37<<3);
	parent->matrix.t[2] += actor->position.vz;


	// SL: setup the scale global, before we do the local matrix thing...
	PSIrootScale = &parent->scale;

	// SL: transform the bones in model space...
	psiCalcLocalMatrix(parent);


	gte_SetRotMatrix(&child->matrixscale);
	gte_SetTransMatrix(&child->matrixscale);
	gte_ldlvl(&org);	
	gte_rtirtr();
	gte_stlvl(res);

	GsWSMATRIX.t[0] = t[0];
	GsWSMATRIX.t[1] = t[1];
	GsWSMATRIX.t[2] = t[2];

	return TRUE;

}

int drawClippedSpriteOverlay(TextureType *spr, int x, int y, int depth, short clipLeft, short clipRight, short clipTop, short clipBottom)
{
	return drawClippedSpriteOverlayColour(spr, x, y, depth,clipLeft, clipRight, clipTop, clipBottom, 0x808080);
	
}


int PrintFixedDepth3DSprite(TextureType *spr,VERT *vect,SHORT scale, unsigned long colour, long depth)
{
	POLY_FT4 *si;
	LONG spritez;

	LONG		width;
	LONG		height;
	LONG distancescale;

	BEGINPRIM(si, POLY_FT4);

// scary scaling-and-transform-in-one-go code from the Action Man people...
	width = (spr->w);
	gte_SetLDDQB(0);			// clear offset control reg (C2_DQB)
	gte_ldv0(vect)	;//vert);
	gte_SetLDDQA(width);		// shove sprite width into control reg (C2_DQA)
	gte_rtps();				// do the rtps
	gte_stsxy(&si->x0);	//scrxy);		// get screen x and y
	gte_stszotz(&spritez);	//depth);		// get order table z
// end of scaling-and-transform

	if(spritez < 20) return 0;

//MIKEY	if(spritez > (1024<<3))
//		spritez = (1024<<3)-1;


	gte_stopz(&distancescale);		// get scaled width of sprite
	distancescale >>= 16;

	width = (distancescale * scale) >> 8;

	if(width < 3)
		return 0;	// better max-distance check

 	si->x1=si->x3=si->x0+width;
 	si->x0=si->x2=si->x0-width;
   	if (si->x1<0) return 0;
   	if (si->x0>640) return 0;


	if((spr->u1 - spr->u0) == (spr->v2 - spr->v0))

		height = width;
	else
		height = width * (spr->v2 - spr->v0) / (spr->u1 - spr->u0);

	si->y2=si->y3=si->y0+height;
	si->y1=si->y0=si->y0-height;
   	if (si->y2< 0) return 0;
   	if (si->y0> 480) return 0;

// Grrr. The new libs don't allow the sprite's (u/v/tpage/clut) to be copied across as longs.

	*(ULONG *)(&si->u0) = ((unsigned long)*(USHORT *)&spr->u0)
		                  | (((unsigned long)(spr->clut)) <<16);
	*(ULONG *)(&si->u2) = ((unsigned long)*(USHORT *)&spr->u2);
	*(ULONG *)(&si->u3) = ((unsigned long)*(USHORT *)&spr->u3);

	if( ! (colour & 0xF0000000) )
	{
		*(ULONG *)(&si->u1) = ((unsigned long)*(USHORT *)&spr->u1)
							  | (((unsigned long)(spr->tpage)) <<16);
		*(ULONG*)&si->r0 = colour | (GPU_COM_TF4<<24);
	}
	else
	{
		*(ULONG *)(&si->u1) = ((unsigned long)*(USHORT *)&spr->u1)
							  | (((unsigned long)(spr->tpage)) <<16)
							  | ((colour >> 8) & 0x00600000);
		*(ULONG*)&si->r0 = (colour & 0xffffff) | ((GPU_COM_TF4+2)<<24);
	}

	setlen(si, 9);	// don't do "setPolyFT4", because we just did the "gpu_com", and orr-ed in the transparancy

	//MIKEY
	si->tag = SEMITRANS_NONE;
	si->tpage = spr->tpage;
	si->code = GPU_COM_TF4;

	//ENDPRIM(si, (spritez >> 3), POLY_FT4);
	ENDPRIM(si, depth, POLY_FT4);

	return 1;
}






//--------------------------------------------------------------------------------------------------------------------------------------
int drawClippedSpriteOverlayColour(TextureType *spr, int x, int y, int depth, short clipLeft, short clipRight, short clipTop, short clipBottom, ULONG colour)
{
	POLY_FT4 *si;
	unsigned short dl=0, dr=0, dt=0, db=0;
	unsigned char u0, u1, u2, u3;

	short width, height;

	width = (spr->u1 - spr->u0)*1.25;
//	height = (spr->v2 - spr->v0)*1.875;
	height = 20;//MIKEY - for power bar fatness theight;


	// check to see if it totally clipped
	if((x>clipRight)||((x+width)<clipLeft)||(y>clipBottom)||((y+height)<clipTop))
		return 0;

	y*=1.875;
	x+=256;
	y+=240;
	x*=1.25;

	clipTop*=1.875;
	clipTop+=240;
	clipBottom*=1.875;
	clipBottom+=240;
	clipLeft+=256;
	clipLeft*=1.25;
	clipRight+=256;
	clipRight*=1.25;


	BEGINPRIM(si, POLY_FT4);

	if(clipLeft > x)
	{
		si->x0 = si->x2 = clipLeft;
		dl = clipLeft - x;
	}
	else
		si->x0 = si->x2 = x;

	if(clipRight < (x+width))
	{
		si->x1 = si->x3 = clipRight;
		dr = (x+width) - clipRight ;
	}
	else
		si->x1 = si->x3 = (x+width);

		
		
	if(clipTop > y)
	{
		si->y0 = si->y1 = clipTop;
		dt = clipTop - y;
	}
	else
		si->y0 = si->y1 = y;
	
	if(clipBottom< (y+height))
	{
		si->y2 = si->y3 = clipBottom;
		db =  (y+height) - clipBottom;
	}
	else
		si->y2 = si->y3 = (y+height);

	*(ULONG *)(&si->u0) = ((unsigned long)*(USHORT *)&(spr->u0)
		                  | (((unsigned long)(spr->clut)) <<16));


	*(ULONG *)(&si->u2) = ((unsigned long)*(USHORT *)&spr->u2);
	*(ULONG *)(&si->u3) = ((unsigned long)*(USHORT *)&spr->u3);

	*(ULONG *)(&si->u1) = ((unsigned long)*(USHORT *)&spr->u1)
						  | (((unsigned long)(spr->tpage)) <<16);

	si->u0 += dl;
	si->u1 -= dr;
	si->u2 += dl;
	si->u3 -= dr;

	si->v0 = si->v0 + 2;//tst1;//dt;MIKEY - so power bar is fat enough
	si->v1 = si->v1 + 2;//tst1;//dt;

	si->v2 = si->v0 + 4;//tst2;//(si->y2 - si->y0)*1.875;
	si->v3 = si->v1 + 4;//tst2;//(si->y2 - si->y0)*1.875;




	*(ULONG*)&si->r0 = (0xffffff & colour) | ((GPU_COM_TF4)<<24);
	setlen(si, 9);

	ENDPRIM(si, depth, POLY_FT4);
	return 1;
}

int SG_ARROW_FLASH_FREQ = 280;
int SG_ARROW_LX = -220;
int SG_ARROW_RX = 200;
int SG_ARROW_MIN_ALPHA = 32;

void DrawDirectionArrows(TextureType *rarrow, int yPos)
{
	static long frameCount = 0;
	int alpha;

	frameCount++;
//			 3 2 1											 1							2	  3
	alpha =  ( ( (rsin(frameCount*SG_ARROW_FLASH_FREQ) + 4096) *(128-SG_ARROW_MIN_ALPHA))/8192) + SG_ARROW_MIN_ALPHA;
	overlaySprite(rarrow, SG_ARROW_RX, yPos, 4, alpha*(0x10101));
	overlaySpriteFlipped(rarrow, SG_ARROW_LX, yPos, 4, alpha*(0x10101));
}



typedef struct 
{
	int posX, posY;
	int numB, numS, numG;
	int depth;
	TextureType *lines[5];
	TextureType *count[4];
	ULONG bronzeColour;
	ULONG silverColour;
	ULONG goldColour;
	int lastScore;
	int fraction;

}CricketScore;

CricketScore cricketScore;



//----------------------------------------------------------------------------------------
void initCricketScores(int x, int y, int numBronze, int numSilver, int numGold, int depth)
{
	//load in textures and details
   //textures come from game\generic\hencount\hencount.spt

	cricketScore.lines[0] = textureFindInAllBanks("LINE1");
	ASSERT(cricketScore.lines[0]);
	cricketScore.lines[1] = textureFindInAllBanks("LINE2");
	ASSERT(cricketScore.lines[1]);
	cricketScore.lines[2] = textureFindInAllBanks("LINE3");
	ASSERT(cricketScore.lines[2]);
	cricketScore.lines[3] = textureFindInAllBanks("LINE4");
	ASSERT(cricketScore.lines[3]);
	cricketScore.lines[4] = textureFindInAllBanks("LINE5");
	ASSERT(cricketScore.lines[4]);

	cricketScore.count[0] = textureFindInAllBanks("COUNT2");
	ASSERT(cricketScore.count[0]);
	cricketScore.count[1] = textureFindInAllBanks("COUNT3");
	ASSERT(cricketScore.count[1]);
	cricketScore.count[2] = textureFindInAllBanks("COUNT4");
	ASSERT(cricketScore.count[2]);
	cricketScore.count[3] = textureFindInAllBanks("COUNT5");
	ASSERT(cricketScore.count[3]);

//	cricketScore.bronzeColour = ((ULONG)110) | (((ULONG)65)<<8)  | (((ULONG)15)<<16);
	cricketScore.bronzeColour = ((ULONG)130) | (((ULONG)80)<<8)  | (((ULONG)40)<<16);
	cricketScore.silverColour =	((ULONG)110) | (((ULONG)140)<<8) | (((ULONG)130)<<16);
	cricketScore.goldColour   =	((ULONG)255) | (((ULONG)120)<<8) | (((ULONG)20)<<16);

	cricketScore.posX = x;
	cricketScore.posY = y;
	cricketScore.numB = numBronze;
	cricketScore.numS = numSilver;
	cricketScore.numG = numGold;
	
	cricketScore.lastScore = 0;
	cricketScore.fraction = 0;

}


int CRICKET_XSEP = 56;
int CRICKET_YSEP = 30;
int CRICKET1_DX  = 0;
int CRICKET2_DX  = 21;
int CRICKET3_DX  = 29;
int CRICKET4_DX  = 38;
int CRICKET5_DY  = 6;

//temp 

int CRICK_R = 100;
int CRICK_G = 100;
int CRICK_B = 100;



#define CRICKET_TIME_TO_DRAW_LINE 5

// (debug x, y - will be taken out)  num is num of complete lines, fraction is(1==4096) how much of the next line has been drawn (usually 0)
void drawCricketScores(int x, int y, int num)
{
 	int i,j;
	int columns, numLeft;//?
	int spacesLeft = cricketScore.numB;
	int fractionToDo;
	
	ULONG colour;

	i=num -  cricketScore.lastScore;

	if((i == 1) && (cricketScore.fraction == 0))
	{
		// start her up
		cricketScore.fraction = 1;
	}
	if(i > 1)
	{
		// line being started before previous line has been drawn
		cricketScore.lastScore = num-1;
		cricketScore.fraction = 1;
	}

	if(cricketScore.fraction)
	{
		cricketScore.fraction += 4100/CRICKET_TIME_TO_DRAW_LINE;
 
		if(cricketScore.fraction >= 4096)
		{
			cricketScore.fraction = 0;
			cricketScore.lastScore = num;
		}
	}

	numLeft = cricketScore.lastScore;


	if(num < cricketScore.numB)
		colour = (CRICK_B)<<16 | (CRICK_G)<<8 | (CRICK_R);
	else if(num < cricketScore.numS)
		colour = cricketScore.bronzeColour;
	else if(num < cricketScore.numG)
		colour = cricketScore.silverColour;
	else 
		colour = cricketScore.goldColour;


	fractionToDo = cricketScore.fraction > 0 ? 1:0;
	

	cricketScore.posX = x;
	cricketScore.posY = y;


	columns = cricketScore.numB/10;
	if(cricketScore.numB%10)
		columns++;

	if(columns < (1+(num/10)))
		columns = (1+(num/10));



	// however many columns you need
	for(j=0; j<columns; j++)
	{
		//2 rows
		for(i=0; i<2; i++)
		{
			if(numLeft >= 5)
			{
				//5 complete one
				overlaySprite(cricketScore.count[3], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth, colour);
			} 
			else if(numLeft <= 0) 
			{
				if((spacesLeft <=0) && (!fractionToDo))
					break;
				

				//just drawing the spaces
				if(spacesLeft >= 5)
					overlayTranspSprite(cricketScore.count[3], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth+1, 0x404040|OV_TRANSSPR_SEMI);
				else if(spacesLeft == 4)
					overlayTranspSprite(cricketScore.count[2], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth+1, 0x404040|OV_TRANSSPR_SEMI);
				else if(spacesLeft == 3)
					overlayTranspSprite(cricketScore.count[1], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth+1, 0x404040|OV_TRANSSPR_SEMI);
				else if(spacesLeft == 2)
					overlayTranspSprite(cricketScore.count[0], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth+1, 0x404040|OV_TRANSSPR_SEMI);
				else if(spacesLeft == 1)
					overlayTranspSprite(cricketScore.lines[0], CRICKET1_DX + cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth+1, 0x404040|OV_TRANSSPR_SEMI);

				if(fractionToDo)
				{
					// fraction not done yet so must be first line
					int x,y, clipBottom;

					x = CRICKET1_DX + cricketScore.posX + CRICKET_XSEP*j;
					y = cricketScore.posY + CRICKET_YSEP*i;
					clipBottom = y + ((cricketScore.lines[0]->h)*cricketScore.fraction)/4096;

//					DB("%d %d %d %d h=%d\n", x, y, (x+cricketScore.lines[0]->w), clipBottom, (cricketScore.lines[0]->h));

					drawClippedSpriteOverlayColour(cricketScore.lines[0], x, y, cricketScore.depth, x, x+cricketScore.lines[0]->w, y, clipBottom, colour);
//					overlaySprite(cricketScore.lines[0], CRICKET1_DX + cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth, 0x707070|OV_TRANSSPR_SEMI);
					fractionToDo = 0;
				}



				// no more left to draw
			}
			else//need to draw only some marked
			{
				if(spacesLeft > numLeft)
				{
					// need to draw some alpha ones
					if(spacesLeft >= 5)
						overlayTranspSprite(cricketScore.count[3], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth+1, 0x404040|OV_TRANSSPR_SEMI);
					else if(spacesLeft == 4)
						overlayTranspSprite(cricketScore.count[2], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth+1, 0x404040|OV_TRANSSPR_SEMI);
					else if(spacesLeft == 3)
						overlayTranspSprite(cricketScore.count[1], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth+1, 0x404040|OV_TRANSSPR_SEMI);
					else if(spacesLeft == 2)
						overlayTranspSprite(cricketScore.count[0], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth+1, 0x404040|OV_TRANSSPR_SEMI);
					else if(spacesLeft == 1)
						overlayTranspSprite(cricketScore.lines[0], CRICKET1_DX + cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth+1, 0x404040|OV_TRANSSPR_SEMI);
				}

				// now draw the marked ones over the top
				if(numLeft == 4)
					overlaySprite(cricketScore.count[2], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth, colour);
				else if(numLeft == 3)
					overlaySprite(cricketScore.count[1], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth, colour);
				else if(numLeft == 2)
					overlaySprite(cricketScore.count[0], cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth, colour);
				else if(numLeft == 1)
					overlaySprite(cricketScore.lines[0], CRICKET1_DX + cricketScore.posX + CRICKET_XSEP*j, cricketScore.posY + CRICKET_YSEP*i, cricketScore.depth, colour);

				if(fractionToDo)
				{
					int x,y, clipBottom;

					if(numLeft == 1)
					{
						// fraction not done yet so must be first line
						x = CRICKET2_DX + cricketScore.posX + CRICKET_XSEP*j;
						y = cricketScore.posY + CRICKET_YSEP*i;
						clipBottom = y + ((cricketScore.lines[1]->h)*cricketScore.fraction)/4096;

						//DB("x%d y%d r%d b%d h=%d fraction = %d\n", x, y, (x+cricketScore.lines[0]->w), clipBottom, (cricketScore.lines[0]->h), fraction);

						drawClippedSpriteOverlayColour(cricketScore.lines[1], x, y, cricketScore.depth, x, x+cricketScore.lines[1]->w, y, clipBottom, colour);
					}
					if(numLeft == 2)
					{
						// fraction not done yet so must be first line
						x = CRICKET3_DX + cricketScore.posX + CRICKET_XSEP*j;
						y = cricketScore.posY + CRICKET_YSEP*i;
						clipBottom = y + ((cricketScore.lines[2]->h)*cricketScore.fraction)/4096;

						drawClippedSpriteOverlayColour(cricketScore.lines[2], x, y, cricketScore.depth, x, x+cricketScore.lines[2]->w, y, clipBottom, colour);
					}
					if(numLeft == 3)
					{
						// fraction not done yet so must be first line
						x = CRICKET4_DX + cricketScore.posX + CRICKET_XSEP*j;
						y = cricketScore.posY + CRICKET_YSEP*i;
						clipBottom = y + ((cricketScore.lines[3]->h)*cricketScore.fraction)/4096;

						drawClippedSpriteOverlayColour(cricketScore.lines[3], x, y, cricketScore.depth, x, x+cricketScore.lines[3]->w, y, clipBottom, colour);
					}
					if(numLeft == 4)
					{
						// fraction not done yet so must be first line
						x =  cricketScore.posX + CRICKET_XSEP*j;
						//actually clipRight!
						y = CRICKET5_DY +cricketScore.posY + CRICKET_YSEP*i;
						clipBottom = x + ((cricketScore.lines[4]->w)*cricketScore.fraction)/4096;

						drawClippedSpriteOverlayColour(cricketScore.lines[4], x, y, cricketScore.depth, x, clipBottom, y, y+cricketScore.lines[4]->h, colour);
					}
					fractionToDo = 0;

				}

			}
			numLeft -= 5;
			spacesLeft -= 5;
		}
	}
}



void resetCricketScores()
{
	cricketScore.lastScore = 0;
	cricketScore.fraction = 0;
}







ACTOR *stopWatch;
TextureType *stopBack;
TextureType *stopIn;
TextureType *stopOut;
TextureType *flasher;


int stopWatchXPos, stopWatchYPos;
int stopWatchLength;

int BACK_OFFSETX = -33;
int BACK_OFFSETY = -30;

int FLASH_OFFSETX = -33;
int FLASH_OFFSETY = -30;


int TIMER_BUTTON_OFF_X = -5;
int TIMER_BUTTON_OFF_Y = -37;
int fovStore = 0;

static int swFrameCount;
static int flashLength;
static int stopWatchLastTime;






//-------------------------------------------------------------------------------------
void initStopWatch(int x, int y, int fov)
{
	PSIMODEL *model;
	ANIM_SEGMENT *pAS;

	flashLength = 0;
	swFrameCount = 0;
	fovStore = fov;
	stopWatchLastTime = -1;

	stopBack = textureFindInAllBanks("TIMERB");
	stopOut = textureFindInAllBanks("TIMERT1");
	stopIn = textureFindInAllBanks("TIMERT2");
	flasher = textureFindInAllBanks("TIMERALPHA");;


	ASSERT(stopBack);
	ASSERT(stopIn);
	ASSERT(stopOut);
	ASSERT(flasher);

	model = BFF_IsModelLoaded("TIMER");
	ASSERT(model);
	stopWatch = actorCreate(model);
	ASSERT(stopWatch);
	actorInitAnim(stopWatch);	

	stopWatch->position.vx = 0;
	stopWatch->position.vy = 0;
	stopWatch->position.vz = 0;

	actorAnimate(stopWatch, 0, TRUE, 0, 100, 0, 0);

	stopWatch->animation.animData[0].speed = 0;

	pAS = stopWatch->animation.pSegments + stopWatch->animation.animData[0].segment;
	
	stopWatchLength = pAS->scaledAnimLength;


	stopWatchXPos = x;
	stopWatchYPos = y;

}


//--------------------------------------------------------------------------------
void resetStopWatch()
{
	flashLength = 0;
	swFrameCount = 0;
	stopWatchLastTime = -1;
}


int STOPWATCH_DISTANCE = 11000;
int SW_DEPTH_OVERR = 8;
//int SW_FACTOR = 4096;

int SW_OVERLAY_DEPTH = 10;

int STOPWATCH_FOV = 1000;

//-------------------------------------------------------------------------------------
void drawStopWatch(int time)
{
	int i;
	PSIMODELCTRL *modctrl = &PSImodelctrl;

	int depth = 1;
	VECTOR oldCamPos;
	VECTOR oldGaribPos;
	int prev_lighting;


	swFrameCount++;

	

	GsSetProjection(STOPWATCH_FOV);




	if(time > 4096)
		time = 4096;
	if(time < 0)
		time = 0;


	if((time == 4096) || (time == 0))
	{
		//draw In button
		overlaySprite(stopOut, stopWatchXPos + TIMER_BUTTON_OFF_X, stopWatchYPos + TIMER_BUTTON_OFF_Y, SW_OVERLAY_DEPTH,0xff808080);
	}
	else
	{
		//draw out button
		overlaySprite(stopIn, stopWatchXPos + TIMER_BUTTON_OFF_X, stopWatchYPos + TIMER_BUTTON_OFF_Y, SW_OVERLAY_DEPTH,0xff808080);
	}

	if((stopWatchLastTime != time) && (time > 3072) && (time < 4096))
	{
		if(flashLength == 0)
		{
			flashLength = (4096 - time)/50 + 1;
			swFrameCount = 0;
		}
		else if(flashLength == 1)
		{
			// do flasher
			if((swFrameCount % 7) >=5)
				overlayTranspSprite(stopBack, stopWatchXPos + FLASH_OFFSETX, stopWatchYPos + FLASH_OFFSETY, SW_OVERLAY_DEPTH-1,OV_TRANSSPR_ADD|0x0000ee);
//				overlayAlphaSprite(stopBack, stopWatchXPos + FLASH_OFFSETX, stopWatchYPos + FLASH_OFFSETY, SW_OVERLAY_DEPTH-1, 0x0080808);
  			else if((swFrameCount % 3)>=3)
				overlayTranspSprite(stopBack, stopWatchXPos + FLASH_OFFSETX, stopWatchYPos + FLASH_OFFSETY, SW_OVERLAY_DEPTH-1,OV_TRANSSPR_ADD|0x8080ff);
//				overlayAlphaSprite(stopBack, stopWatchXPos + FLASH_OFFSETX, stopWatchYPos + FLASH_OFFSETY, SW_OVERLAY_DEPTH-1, 0x00e0e0e);

			else if((swFrameCount % 3)>=1)
				overlayTranspSprite(stopBack, stopWatchXPos + FLASH_OFFSETX, stopWatchYPos + FLASH_OFFSETY, SW_OVERLAY_DEPTH-1,OV_TRANSSPR_ADD|0x0000ee);
//				overlayAlphaSprite(stopBack, stopWatchXPos + FLASH_OFFSETX, stopWatchYPos + FLASH_OFFSETY, SW_OVERLAY_DEPTH-1, 0x0080808);
			else
				flashLength = 0;
			
		}
		else
		{
			flashLength--;

			if(flashLength == 1)
				swFrameCount = 0;


		}

	}

	stopWatchLastTime = time;

	overlaySprite(stopBack, stopWatchXPos + BACK_OFFSETX, stopWatchYPos + BACK_OFFSETY, SW_OVERLAY_DEPTH,0xff808080);

	stopWatch->animation.animData[0].scaledFrameOffset = (stopWatchLength*time)/4096;// may have to factor this..
	actorMaintainAnimation(stopWatch);

	//gourad
	prev_lighting = modctrl->lighting;
	modctrl->lighting = NOLIGHTING;



// to here 
	// store cam pos

	oldCamPos.vx = mycamera.vpx;
	oldCamPos.vy = mycamera.vpy;
	oldCamPos.vz = mycamera.vpz;

	oldGaribPos.vx = mycamera.vrx;
	oldGaribPos.vy = mycamera.vry;
	oldGaribPos.vz = mycamera.vrz;


	mycamera.vrx = 0;
	mycamera.vry = 0;
	mycamera.vrz = 0;

	mycamera.vpx = 0;
	mycamera.vpy = 0;
	mycamera.vpz = -STOPWATCH_DISTANCE;

	mapCamSetRefView2L(&mycamera);




 		SetDrawOffsetDC(stopWatchXPos, stopWatchYPos-2); //MIKEY -2
/*
	{	// CPW: put it back
		DR_OFFSET *dof;
		u_short ofs[2];

	
		dof = BEGINPRIM(dof, DR_OFFSET);
		ofs[0] = currentDisplayPage->drawenv.ofs[0];
		ofs[1] = currentDisplayPage->drawenv.ofs[1];
		SetDrawOffset(dof, ofs);
		ENDPRIM(dof, 1, DR_OFFSET);	// MY_OFFSET_DEPTH
	}
  */

// here




	modctrl->depthoverride = SW_DEPTH_OVERR;

//	EXLIGHT_SetupActorLights(stopWatch);
	actorDraw(stopWatch);


	modctrl->depthoverride = 0;

	
	SetDrawOffsetDC(0,0);
	/*	{// set offset
		
		DR_OFFSET *dof;
		u_short ofs[2];


		dof = BEGINPRIM(dof, DR_OFFSET);
   		ofs[0] = currentDisplayPage->drawenv.ofs[0]+stopWatchXPos;
   		ofs[1] = currentDisplayPage->drawenv.ofs[1]+stopWatchYPos;
   		SetDrawOffset(dof, ofs);
   		ENDPRIM(dof, 1, DR_OFFSET);	//MY_OFFSET_DEPTH


	}
	  */

	//restore cam pos
	mycamera.vpx = oldCamPos.vx;
	mycamera.vpy = oldCamPos.vy;
	mycamera.vpz = oldCamPos.vz;

	mycamera.vrx = oldGaribPos.vx;
	mycamera.vry = oldGaribPos.vy;
	mycamera.vrz = oldGaribPos.vz;

	mapCamSetRefView2L(&mycamera);

	GsSetProjection(fovStore);

	PSImodelctrl.lighting = prev_lighting;

}


//-------------------------------------------------------------------------------------
void freeStopWatch()
{
	actorFree(stopWatch);
}


enum
{
	FOWLER_EYE_OPEN,
	FOWLER_EYE_CLOSED,
	FOWLER_EYE_ANGRY,
	FOWLER_EYE_MAD,
	FOWLER_EYE_CROSS,
	FOWLER_EYE_LEFT,
	NUM_FOWLER_EYES,
};

ACTOR *fowler=NULL;
int fowlerFOVStore = 1000;
int fowlerActive = FALSE;
TextureType *fowlerEyesAnim[NUM_FOWLER_EYES];
TextureAnimType *fowlerBlink;

TextureType *fowlerMedalAnim[3];
TextureAnimType *fowlerMedal;


int fowlerEyesTimer;
int fowlerTalking;
int fowlerAwardedMedal;
int fowlerStartAnimSegment;
int fowlerMedalSFX;
int fowlerSampleChannel;
int fowlerEyeState;
int currentSubGame;
int fowlerAnimOffset;//redundant
int medalAwarded;


short animSpeeds[NUM_SUBGAMES][4] = 
{
	{255, 255, 255, 255},
	{255, 255, 255, 255},
	{255, 255, 255, 255},
	{255, 255, 255, 255},
	{255, 255, 255, 255},
	{255, 255, 255, 255},
	{255, 255, 255, 255},
};


char *fowlerEyeNames[NUM_FOWLER_EYES] = 
{
	"FOWLER_EYEOPEN",
	"FOWLER_EYECLOSED",
	"FOWLER_EYEANGRY",
	"FOWLER_EYEMAD",
	"FOWLER_EYECROSS",
	"FOWLER_EYELEFT"
};

//-------------------------------------------------------------------------------------
//void fowlerSetMedalSfx(int medal)
//{
//	fowlerMedalSFX = medal;
//}

//-------------------------------------------------------------------------------------
void initFowler(int fov, int subgame)
{
	int i;
	PSIMODEL *model;
	TextureType *dummy;


	currentSubGame = subgame;

	model = BFF_IsModelLoaded("MFOWLER");
	ASSERT(model);
	fowler = actorCreate(model);
	ASSERT(fowler);
	actorInitAnim(fowler);	
	fowlerFOVStore = fov;


	for(i=0; i<NUM_FOWLER_EYES; i++)
	{
	 	fowlerEyesAnim[i] = textureFindInAllBanks(fowlerEyeNames[i]);
		ASSERT(fowlerEyesAnim[i]);
	}

	dummy = textureFindInAllBanks("FOWLER_EYES");
	ASSERT(dummy);

	fowlerBlink = textureCreateAnimation(dummy,fowlerEyesAnim,NUM_FOWLER_EYES);
	ASSERT(fowlerBlink);

	textureSetAnimation(fowlerBlink,0);


	fowlerMedalAnim[0] = textureFindInAllBanks("MEDALB");
	ASSERT(fowlerMedalAnim[0]);
	fowlerMedalAnim[1] = textureFindInAllBanks("MEDALS");
	ASSERT(fowlerMedalAnim[1]);
	fowlerMedalAnim[2] = textureFindInAllBanks("MEDALG");
	ASSERT(fowlerMedalAnim[2]);


	dummy = textureFindInAllBanks("MEDAL");
	ASSERT(dummy);

	fowlerMedal = textureCreateAnimation(dummy,fowlerMedalAnim,3);
	ASSERT(fowlerMedal);

	textureSetAnimation(fowlerMedal,1);




	fowlerActive = FALSE;

	fowlerEyeState = FOWLER_EYE_OPEN;

}



//-------------------------------------------------------------------------------------
// the offsets are defined in ranges.h  eg FOWLER_BRONZE_OFFSET
void startFowler(int medal)
{
	int i;
	ASSERT(fowler);

	//fowlerAnimOffset = animOffset;
	medalAwarded = medal;

	fowlerEyesTimer = 0;
	fowlerTalking = 0;
	fowlerSampleChannel = 0;
	fowlerAwardedMedal = 0;
	fowlerEyeState = 0;


	if(medalAwarded == GOLD)
		fowlerMedalSFX = SFX_FOWLER_GOLD;
	else if(medalAwarded == SILVER)
		fowlerMedalSFX = SFX_FOWLER_SILVER;
	else if(medalAwarded == BRONZE)
		fowlerMedalSFX = SFX_FOWLER_BRONZE;
	else
		fowlerMedalSFX = SFX_FOWLER_FAIL;


/*
	FOWLER_ARRIVE,
	FOWLER_TALK1,
	FOWLER_TALK2,
	FOWLER_TALK4,
	FOWLER_TALK3A,
	FOWLER_TALK3B,
	FOWLER_TALK3C,
	FOWLER_AWARD,
	FOWLER_WALKOFF_NORMAL,
	FOWLER_FAIL_ARRIVE,
	FOWLER_FAIL_TALK1,
	FOWLER_FAIL_TALK2,
	FOWLER_FAIL_TALK3,
	FOWLER_FAIL_TALK4,
	FOWLER_FAIL_WALKOFF_NORMAL,
	FOWLER_FAIL_WALKOFF1,
	FOWLER_FAIL_WALKOFF2,
	FOWLER_FAIL_WALKOFF3,
	FOWLER_FAIL_WALKOFF4,
*/




	if(medalAwarded == FAIL)
	{
		fowlerStartAnimSegment = FOWLER_FAIL_ARRIVE;
		
		actorAnimate(fowler,FOWLER_FAIL_ARRIVE , FALSE, FALSE, 256, 0, 0);
		actorAnimate(fowler,FOWLER_FAIL_TALK1 , FALSE, TRUE, 256, 0, 0);
		actorAnimate(fowler,FOWLER_FAIL_TALK2 , FALSE, TRUE, 256, 0, 0);
		actorAnimate(fowler,FOWLER_FAIL_TALK3 , FALSE, TRUE, 256, 0, 0);
		actorAnimate(fowler,FOWLER_FAIL_TALK4 , TRUE, TRUE, 256, 0, 0);
	}
	else
	{
		switch(medalAwarded)
		{
			case GOLD:
				textureSetAnimation(fowlerMedal,2);
//				DB("setting gold texture\n");
				break;
			case SILVER:
				textureSetAnimation(fowlerMedal,1);
//				DB("setting silver texture\n");
				break;
			case BRONZE:
				textureSetAnimation(fowlerMedal,0);
//				DB("setting bronze texture\n");
				break;
		}


		fowlerStartAnimSegment = FOWLER_ARRIVE;


		actorAnimate(fowler,FOWLER_ARRIVE, FALSE, FALSE, 256, 0, 0);
		actorAnimate(fowler,FOWLER_TALK1, FALSE, TRUE, 256, 0, 0);
		actorAnimate(fowler,FOWLER_TALK2, FALSE, TRUE, 256, 0, 0);

		i = utilRandomInt(2);

		switch(i)
		{
			case 0:
				actorAnimate(fowler,FOWLER_TALK3A, FALSE, TRUE, 256, 0, 0);
				break;
			case 1:
				actorAnimate(fowler,FOWLER_TALK3B, FALSE, TRUE, 256, 0, 0);
				break;
			case 2:
				actorAnimate(fowler,FOWLER_TALK3C, FALSE, TRUE, 256, 0, 0);
				break;
		}

		actorAnimate(fowler,FOWLER_TALK4, TRUE, TRUE, 256, 0, 0);


	}


	fowlerActive = TRUE;
	//fowlerStartAnimSegment = (FOWLER_ARRIVE + animOffset);
	textureSetAnimation(fowlerBlink,0);
	fowlerTalking = 0;
}


//-------------------------------------------------------------------------------------
void makeFowlerSpeak()
{
	SfxSampleType *res;
	int i;
	int endAnimOffset;

	//if fowler has started talking and hasn't been awarded the medal yet, check to see when the sample has finished
	//to do fowlers ending animations 
	if((fowlerAwardedMedal == 0)&&(fowlerTalking))
	{
		res = sfxGetChannelStatus(fowlerSampleChannel);
		if(!res)			 
		{
			fowlerAwardedMedal = 1;
			fowler->animation.animData[0].speed = 0;



			if(medalAwarded != FAIL)
			{
				actorAnimate(fowler, FOWLER_AWARD, FALSE, FALSE, 256, 0, 512);
			}




			i = utilRandomInt(100);

			switch(medalAwarded)
			{
				case GOLD:
					endAnimOffset = FOWLER_GOLD_LEAVE;
					break;
				case SILVER:
					endAnimOffset = FOWLER_SILVER_LEAVE;
					break;
				case BRONZE:
					endAnimOffset = FOWLER_BRONZE_LEAVE;
					break;
				case FAIL:
					endAnimOffset = FOWLER_FAIL_LEAVE;
					break;
				default:
					ASSERT(0);
					break;
			}


			if(i<30)
			{
				if(medalAwarded == FAIL)
				{
					actorAnimate(fowler, endAnimOffset, FALSE, FALSE, 256, 0, 0);
				}
				else
				{
					actorAnimate(fowler, FOWLER_WALKOFF_NORMAL, FALSE, TRUE, 256, 0, 0);
				}
			}
			else
			{
				if(medalAwarded == FAIL)
				{
					i = utilRandomInt(3)+1;
					actorAnimate(fowler, endAnimOffset+i, FALSE, FALSE, 256, 0, 512);
				}
				else
				{
					i = utilRandomInt(2);
					actorAnimate(fowler, endAnimOffset+i, FALSE, TRUE, 256, 0, 0);
				}
			}
		}
	}
	

	// start him speaking
	if((fowlerActive == 0)||(fowlerTalking)||(fowlerMedalSFX == -1))
		return;

	if(fowler->animation.animData[0].segment != fowlerStartAnimSegment)
	{
		fowlerSampleChannel = soundPlaySample(fowlerSubGameSample[fowlerMedalSFX], 0xffff, 0);
		fowlerTalking = 1;
	}
}



//if you want gourad....then
#define FOWLER_GOURAD

int FOWLER_FOV = 800;
int FOWLER_DISTANCE = 2000;
int FOWLER_DEPTH_OVERR = 8;

int FOWLER_XPOS = 180;
int	FOWLER_YPOS	= 190;//MIKEY220;


//-------------------------------------------------------------------------------------
void fowlerDraw()
{
	int i;
	PSIMODELCTRL *modctrl = &PSImodelctrl;

	int depth = 1;
	VECTOR oldCamPos;
	VECTOR oldGaribPos;
	int prev_lighting;

	ASSERT(fowlerActive);

	swFrameCount++;

	

	if(!fowlerEyesTimer)
	{
		if(utilRandomInt(100)>96)
		{
			textureSetAnimation(fowlerBlink,FOWLER_EYE_CLOSED);
			fowlerEyesTimer = 2;		// Hold the blink for 2! frames 
		}
	//	else
	//	{
	//		textureSetAnimation(fowlerBlink,0);
	//	}

	}
	else
	{
		fowlerEyesTimer--;
		if(fowlerEyesTimer <= 0)
		{

			if(fowlerEyeState != FOWLER_EYE_OPEN)
			{
				fowlerEyeState = FOWLER_EYE_OPEN;
			}
			else
			{
				i = utilRandomInt(100);

				if(i<60)
					fowlerEyeState = FOWLER_EYE_OPEN;
				else if(i<68)
					fowlerEyeState = FOWLER_EYE_ANGRY;
				else if(i<76)
					fowlerEyeState = FOWLER_EYE_MAD;
				else
					fowlerEyeState = FOWLER_EYE_LEFT;


			}
			textureSetAnimation(fowlerBlink,fowlerEyeState);
		}
	}



	
	GsSetProjection(FOWLER_FOV);

	actorMaintainAnimation(fowler);

	//gourad
#ifdef FOWLER_GOURAD
	prev_lighting = modctrl->lighting;
	modctrl->lighting = NOLIGHTING;
#endif



// to here 
	// store cam pos

	oldCamPos.vx = mycamera.vpx;
	oldCamPos.vy = mycamera.vpy;
	oldCamPos.vz = mycamera.vpz;

	oldGaribPos.vx = mycamera.vrx;
	oldGaribPos.vy = mycamera.vry;
	oldGaribPos.vz = mycamera.vrz;


	mycamera.vrx = 0;
	mycamera.vry = 0;
	mycamera.vrz = 0;

	mycamera.vpx = 0;
	mycamera.vpy = 0;
	mycamera.vpz = -FOWLER_DISTANCE;

	mapCamSetRefView2L(&mycamera);





	SetDrawOffsetDC(FOWLER_XPOS, FOWLER_YPOS);
/*
	{	// CPW: put it back
		DR_OFFSET *dof;
		u_short ofs[2];

	
		dof = BEGINPRIM(dof, DR_OFFSET);
		ofs[0] = currentDisplayPage->drawenv.ofs[0];
		ofs[1] = currentDisplayPage->drawenv.ofs[1];
		SetDrawOffset(dof, ofs);
		ENDPRIM(dof, 1, DR_OFFSET);	// MY_OFFSET_DEPTH
	}
  */

// here




//MIKEY	modctrl->depthoverride = FOWLER_DEPTH_OVERR;

#ifndef FOWLER_GOURAD
	EXLIGHT_SetupActorLights(fowler);
#endif

	actorDraw(fowler);


	modctrl->depthoverride = 0;

	
  	SetDrawOffsetDC(0,0);
/*
	{// set offset
		
		DR_OFFSET *dof;
		u_short ofs[2];


		dof = BEGINPRIM(dof, DR_OFFSET);
   		ofs[0] = currentDisplayPage->drawenv.ofs[0]+FOWLER_XPOS;
   		ofs[1] = currentDisplayPage->drawenv.ofs[1]+FOWLER_YPOS;
   		SetDrawOffset(dof, ofs);
   		ENDPRIM(dof, 1, DR_OFFSET);	//MY_OFFSET_DEPTH


	}
  */

	//restore cam pos
	mycamera.vpx = oldCamPos.vx;
	mycamera.vpy = oldCamPos.vy;
	mycamera.vpz = oldCamPos.vz;

	mycamera.vrx = oldGaribPos.vx;
	mycamera.vry = oldGaribPos.vy;
	mycamera.vrz = oldGaribPos.vz;

	mapCamSetRefView2L(&mycamera);

	GsSetProjection(fowlerFOVStore);

	
#ifdef FOWLER_GOURAD
	PSImodelctrl.lighting = prev_lighting;
#endif


}

//-------------------------------------------------------------------------------------
void freeFowler()
{
	textureDestroyAnimation(fowlerBlink);
	textureDestroyAnimation(fowlerMedal);
	actorFree(fowler);	

	fowler=NULL;
	fowlerActive = FALSE;
}






// Draw 2 overlays above each other . this isn't currently used and hasn't been tested!
////////////////////////////////////////////////////////////////////////////////////////
int drawVertScrollOverlay(TextureType *spr, int x, int y, int vPos, int depth)
{
	int clipR, clipB;
	int yPos;

	clipR = x + spr->w;
	clipB = y + spr->h;

	yPos = y + vPos;
	
	
	drawClippedSpriteOverlay(spr, x, yPos,depth, x, clipR, y, clipB);

	if(vPos > 0)
		yPos -= spr->h;
	else
		yPos += spr->h;

	drawClippedSpriteOverlay(spr, x, yPos,depth, x, clipR, y, clipB);

	return 1;


}



////////////////////////////////////////////////////////////////////////////////////////
int overlaySizeableSprite(TextureType *spr, int x, int y, int w, int h, int depth, unsigned long colour)
{
	POLY_FT4 *si;
	int alp;


	BEGINPRIM(si, POLY_FT4);

// u,v = doschop offsets
//	u=(spr->u*scaleX)/4096;
//	v=(spr->v*sprctrl.scaley)/4096;

	si->x0 = si->x2 = x;
	si->x1 = si->x3 = x+w;
	si->y0 = si->y1 = y;
	si->y2 = si->y3 = y+h;

	alp = (colour>>24) & 0xff;

// Grrr. The new libs don't allow the sprite's (u/v/tpage/clut) to be copied across as longs.

	*(ULONG *)(&si->u0) = ((unsigned long)*(USHORT *)&spr->u0)
		                  | (((unsigned long)(spr->clut)) <<16);
	*(ULONG *)(&si->u2) = ((unsigned long)*(USHORT *)&spr->u2);
	*(ULONG *)(&si->u3) = ((unsigned long)*(USHORT *)&spr->u3);

	*(ULONG *)(&si->u1) = ((unsigned long)*(USHORT *)&spr->u1)
						  | (((unsigned long)(spr->tpage)) <<16);
						  //| ((SEMITRANS_ADD-1) << (16+5));
	*(ULONG*)&si->r0 = (colour & 0xffffff) | ((GPU_COM_TF4)<<24);

	setlen(si, 9);	// don't do "setPolyFT4", because we just did the "gpu_com", and orr-ed in the transparancy

	
	ENDPRIM(si, depth, POLY_FT4);

	return 1;
}





// DH Generic Subgame funcs         ===================================================================
// ====================================================================================================
// generic camera used for looking round room - for wing making 



/*  not used for the mo -  maybe never
int sgCamNumFrames=-1;
int sgCamCurrentFrame;
VECTOR sgTargetPos;
VECTOR sgTargetLook;
VECTOR sgTargetStartPos;
VECTOR sgTargetStartLook;

void sgStartCameraMove(VECTOR *targetPos, VECTOR *targetLook, int numFrames)
{
	sgTargetPos = *targetPos;
	sgTargetLook = *targetLook;
	
	sgTargetStartPos.vx = mycamera.vpx;
	sgTargetStartPos.vy = mycamera.vpy;
	sgTargetStartPos.vz = mycamera.vpz;

	sgTargetStartLook.vx = mycamera.vrx;
	sgTargetStartLook.vy = mycamera.vry;
	sgTargetStartLook.vz = mycamera.vrz;


	//DB("start look %d, %d, %d\n", sgTargetStartLook.vx, sgTargetStartLook.vy, sgTargetStartLook.vz);
	
	sgCamNumFrames = numFrames;
	sgCamCurrentFrame = 1;

	sgUpdateCameraMove();

}
// ------------------------------------------------------------------------------------------------------
// returns 1 if reached target
int sgUpdateCameraMove()
{
	if(sgCamNumFrames < 1)
	{
		DB("boollooks\n");
	}

	if(sgCamCurrentFrame >= sgCamNumFrames)
		return 1;

	sgCamCurrentFrame++;

	mycamera.vpx = ((sgCamCurrentFrame*sgTargetPos.vx) +((sgCamNumFrames -sgCamCurrentFrame)*sgTargetStartPos.vx))/sgCamNumFrames;
	mycamera.vpy = ((sgCamCurrentFrame*sgTargetPos.vy) +((sgCamNumFrames -sgCamCurrentFrame)*sgTargetStartPos.vy))/sgCamNumFrames;
	mycamera.vpz = ((sgCamCurrentFrame*sgTargetPos.vz) +((sgCamNumFrames -sgCamCurrentFrame)*sgTargetStartPos.vz))/sgCamNumFrames;

	mycamera.vrx = ((sgCamCurrentFrame*sgTargetLook.vx) +((sgCamNumFrames -sgCamCurrentFrame)*sgTargetStartLook.vx))/sgCamNumFrames;
	mycamera.vry = ((sgCamCurrentFrame*sgTargetLook.vy) +((sgCamNumFrames -sgCamCurrentFrame)*sgTargetStartLook.vy))/sgCamNumFrames;
	mycamera.vrz = ((sgCamCurrentFrame*sgTargetLook.vz) +((sgCamNumFrames -sgCamCurrentFrame)*sgTargetStartLook.vz))/sgCamNumFrames;

	return 0;

}


*/



TextureType *subgamePowerBarTex[3];

void subgameInitPowerBar()
{
	subgamePowerBarTex[0] = textureFindInAllBanks("GUAGEMAINF");
	ASSERT(subgamePowerBarTex[0]);

	subgamePowerBarTex[1] = textureFindInAllBanks("GUAGEMIDDLE");
	ASSERT(subgamePowerBarTex[1]);

	subgamePowerBarTex[2] = textureFindInAllBanks("GUAGEMAINB");
	ASSERT(subgamePowerBarTex[2]);

}


int SG_TEXT_PANEL_XOFFSET = 0;
int SG_TEXT_PANEL_YOFFSET = 0;

int SUB_BAR_BAR_LEFT   = 24;
//#define SUB_BAR_BAR_TOP     15
//#define SUB_BAR_BAR_HEIGHT  13
int SUB_BAR_BAR_WIDTH  = 124;
//int SUB_BAR_YTEXT  = 20;
//int SUB_BAR_XTEXT  = 58;



int PB_CLIP_LEFT  =2;//MIKEY18;
int PB_CLIP_RIGHT = 146;
int PB_CLIP_TOP	   = 4;
int PB_CLIP_BOTTOM	= 14;

int PB_YPOS = 5;//MIKEY4;
int PB_XPOS = 17;


//------- power 0 -> 4096

void subgameDrawPowerBar(int x, int y, int inpower)
{
	POLY_G4 *speedbar;
	unsigned short r1,b1,g1;

	int power = SUB_BAR_BAR_WIDTH * inpower / 4096;

	overlaySprite(subgamePowerBarTex[0], x, y, 2,0xff808080);
//	overlaySprite(subgamePowerBarTex[1], x, x, PANEL_OVERLAYS_SORTDEPTH,0xff808080);
	overlaySprite(subgamePowerBarTex[2], x + SG_TEXT_PANEL_XOFFSET, y + SG_TEXT_PANEL_YOFFSET, 4,0xff808080);

	drawClippedSpriteOverlay(subgamePowerBarTex[1],PB_XPOS +  x - (SUB_BAR_BAR_WIDTH - power) , y + PB_YPOS, 3, x+PB_CLIP_LEFT, x+PB_CLIP_RIGHT, y+PB_CLIP_TOP, y + PB_CLIP_BOTTOM);

//	fontPrintCentred(font,(x  + SG_TEXT_PANEL_XOFFSET + SUB_BAR_XTEXT), y + SUB_BAR_YTEXT,TEXTSTR(TEXTSTR_SUB_POWER), 110, 110, 110);


// bar
/*		

	BEGINPRIM(speedbar, POLY_G4);
	setPolyG4(speedbar);				
	speedbar->x0 = x+SUB_BAR_BAR_LEFT;				
	speedbar->y0 = y+SUB_BAR_BAR_TOP;	
	

// for now
//	if(power > (SUB_BAR_BAR_WIDTH))
//		speedbar->x1 = (SUB_BAR_BAR_WIDTH + x);
//	else if(power  < SUB_BAR_BAR_LEFT)
//		speedbar->x1 = SUB_BAR_BAR_LEFT + x;
//	else
	speedbar->x1 = power + x + SUB_BAR_BAR_LEFT;
	
	speedbar->y1 = SUB_BAR_BAR_TOP + y;

	speedbar->x2 = x + SUB_BAR_BAR_LEFT;
	speedbar->y2 = y + SUB_BAR_BAR_TOP + SUB_BAR_BAR_HEIGHT;
	
	// on power
	speedbar->x3 = speedbar->x1;
	speedbar->y3 = y + SUB_BAR_BAR_TOP + SUB_BAR_BAR_HEIGHT;

	speedbar->r0 = 20;
	speedbar->g0 = 20;
	speedbar->b0 = 160;
	speedbar->r1 = 160 - SUB_BAR_BAR_WIDTH + power;
	speedbar->g1 = 160 - SUB_BAR_BAR_WIDTH + power;
	speedbar->b1 = 160;

	speedbar->r2 = speedbar->r0;
	speedbar->g2 = speedbar->g0;
	speedbar->b2 = speedbar->b0;
	speedbar->r3 = speedbar->r1;
	speedbar->g3 = speedbar->g1;
	speedbar->b3 = speedbar->b1;
		
	ENDPRIM(speedbar, 0, POLY_G4);
*/
	

}
















// ====================================================================================================
// ====================================================================================================


/*
void launchGame_Controls(LAUNCH_GAME_DATA *gd)
{

	gd->aimMoveState = 0;

	if (padData.analogYS[0] < -500)
	{
		gd->aimMoveState |= SUBGAME_MOVESTATE_DOWN;
	}

	if (padData.analogYS[0] > 500)
	{
		gd->aimMoveState |= SUBGAME_MOVESTATE_UP;
	}

	if (padData.analogXS[0] > 500)
	{		
		gd->aimMoveState |= SUBGAME_MOVESTATE_RIGHT;
	}

	if (padData.analogXS[0] < -500)
	{	
		gd->aimMoveState |= SUBGAME_MOVESTATE_LEFT;
	}
}




void launchGame_MoveAim(LAUNCH_GAME_DATA *gd)
{
VECTOR v;

	// First, lets deal with the inertia of the aiming movement.  If any of the directional
	// buttons are pressed then we accelerate in that direction.  If there is no button pressed
	// for a particular axis, then we decelerate.

	if (gd->aimMoveState & SUBGAME_MOVESTATE_UP)
	{
		if (gd->aimXMove++ >15)
			gd->aimXMove = 15;
	} else if (gd->aimMoveState & SUBGAME_MOVESTATE_DOWN) {
		if (gd->aimXMove-- < -15 )
			gd->aimXMove = -15;
	} else { 

		if (gd->aimXMove < 0)
			gd->aimXMove++;
		if (gd->aimXMove > 0)
			gd->aimXMove--;
	}
	
	if (gd->aimMoveState & SUBGAME_MOVESTATE_LEFT)
	{

		if (gd->aimYMove++ > 15)
			gd->aimYMove = 15;

	} else if (gd->aimMoveState & SUBGAME_MOVESTATE_RIGHT) {

		if (gd->aimYMove-- < -15 )
			gd->aimYMove = -15;

	} else {

		if (gd->aimYMove < 0)
			gd->aimYMove++;

		if (gd->aimYMove > 0)
			gd->aimYMove--;
	}

	// Now update the rotation angles and clamp them between -512 and 512 (for now)

	gd->aimXRot += gd->aimXMove;
	if (gd->aimXRot > 512)
	{
		gd->aimXRot = 512;
	}
	if (gd->aimXRot < -512)
	{
		gd->aimXRot = -512;
	}

	gd->aimYRot += gd->aimYMove;
	if (gd->aimYRot > 512)
	{
		gd->aimYMove = 0;
		gd->aimYRot = 512;
	}
	if (gd->aimYRot < -512)
	{
		gd->aimYMove = 0;
		gd->aimYRot = -512;	
	}

}


// ====================================================================================================
// ====================================================================================================

extern GsRVIEW2	mycamera;
void launchGame_SetupCamera(void)
{
POSMARK *posMark;

	// =====
	// Setup the position of the camera
	// =====
	posMark = levinfoFindMarker(LAUNCHGAME_CAMPOS);
	ASSERT(posMark != NULL);

	mycamera.vpx = posMark->x;
	mycamera.vpy = posMark->y;
	mycamera.vpz = posMark->z;


	// =====
	// Setup the look-at point of the camera
	// =====
	posMark = levinfoFindMarker(LAUNCHGAME_CAMLOOK);
	ASSERT(posMark != NULL);

	mycamera.vrx = posMark->x;
	mycamera.vry = posMark->y;
	mycamera.vrz = posMark->z;
}

*/	