#include "global.h"
#include "main.h"
#include "debris.h"
#include "lights.h"
#include "timer.h"
#include "maths.h"
#include "overlays.h"
#include "fx.h"
#include "powerbar.h"
#include "catapult.h"
#include "seesaw.h"
#include "demo.h"
#include "map_view.h"
#include "ranges.h"
//#include "text_ids.h"
#include "gametext.h"
#include "charactr.h"
#include "deth.h"
#include "enemies.h"
#include "dualshock.h"
#include <psitypes.h>
#include "construct.h"
#include "inventory.h"
#include "menu.h"
#include "maths.h"
#include "loadsnd.h"
#include "sound.h"
#include "overlays.h"
#include "card.h"
#include "sound.h"

#include "map_play.h"
#include "subgame.h"
#include "startup.h"
#include "loadsnd.h"
#include "pause.h"

#ifdef _WINDOWS
	#include "pckeys.h"
#endif

//#define CON_VIEW_POS
//#define CON_VIEW_STATES
//#define PRINT_SOUNDS


#define CON_SAWER_XPOS	76
#define CON_SAWER_YPOS	-50
#define CON_SAWER_ZPOS	861
#define CON_SAWER_YROT  1080

#define CON_HAMMER_XPOS	 -342
#define CON_HAMMER_YPOS	 240
#define CON_HAMMER_ZPOS	 -2486
#define CON_HAMMER_YROT  1110

#define CON_SPANNER_XPOS  942
#define CON_SPANNER_YPOS  120
#define CON_SPANNER_ZPOS  -1998
#define CON_SPANNER_YROT  3060


#define CON_NUM_RHYTHMS 10
#define CON_MAX_TIMES_PLAYED   4


#define CON_MAIN_PITCH  900

		
#if defined(DREAMCAST) || defined(_WINDOWS)
	int constructBoxDepth = 1000;
	int constructWorldDepth = 500;
	int constructFowlerBump = -1600;
#else
	#define constructBoxDepth 2
#endif


char rhythms[CON_NUM_RHYTHMS][8] = 
{
	{0,1,0,2,0,3,0,1},		//0
	{0,2,0,1,0,3,2,0},		//1
	{0,2,0,2,2,0,1,1},		//2
	{0,1,2,0,0,2,3,0},		//3
	{0,2,2,0,0,1,2,3},		//4
	{0,2,1,0,0,3,2,1},		//5
	{0,1,2,3,0,3,2,1},		//6
	{0,3,1,0,2,1,0,2},		//7
	{1,2,0,3,2,0,1,3},		//8
	{3,1,2,1,3,2,1,3},		//9
};


short whichTool[CON_NUM_RHYTHMS] = 
{
	CON_SAWER,			   //0
	CON_SPANNER,		   //1
	CON_HAMMER,			   //2
	CON_SAWER,			   //3
	CON_SPANNER,		   //4
	CON_SAWER,			   //5
	CON_HAMMER,			   //6
	CON_SAWER,			   //7
	CON_SPANNER,		   //8
	CON_HAMMER,			   //9
};
	







VECTOR	conCamPos[CON_NUM_TOOLS]=
{

	{402, -1765, -1649},		//CON_SAWER 
	{600, -1476, -827},			//CON_HAMMER
	{-860, -1534, -523},		//CON_SPANNER

};

VECTOR	conGaribPos[CON_NUM_TOOLS]=
{
	{130, -213, 1372},			//CON_SAWER 
	{-1378, 222, -3020},		//CON_HAMMER
	{1326, -17, -2936},		//CON_SPANNER

};

int conCamAngle[CON_NUM_TOOLS];



CONSTRUCT_DATA *con;

#define CONSTRUCT_FOV  700

#define CON_CAM_XSTART  0
#define CON_CAM_YSTART  0
#define CON_CAM_ZSTART  0

#define CON_GAR_XSTART  0
#define CON_GAR_YSTART  0
#define CON_GAR_ZSTART  1000

#define CON_PROGRESS_BRONZE_SCORE 140
#define CON_PROGRESS_SILVER_SCORE 170
#define CON_PROGRESS_GOLD_SCORE   200
#define CON_PROGRESS_MAX   208

// if you change the above you need to change these as well (in debugger)
#define CON_PROG_BRONZE_XOFFSET  138
#define CON_PROG_SILVER_XOFFSET  163
#define CON_PROG_GOLD_XOFFSET    188






//ACTOR *myactor = 0;

// 1 = h
// 2 = k
// 3 = kh
// 4 = ks
// 5 = ksh
// 6 = s
// 7 = sh

short conBackRythm[CON_NUM_RHYTHMS][32]=
{

	{ 3,0,1,1, 4,0,2,1, 3,0,1,0, 4,0,1,0, 3,0,1,0, 4,0,1,1, 3,0,1,0, 2,0,2,0},//rhythm0
	{ 4,0,1,1, 4,1,5,1, 4,1,1,0, 4,1,2,1, 4,0,1,1, 4,4,1,1, 4,1,1,1, 2,1,2,1},//rhythm1
	{ 4,1,6,0, 4,0,1,0, 6,0,0,0, 4,1,0,1, 6,0,1,0, 4,0,1,0, 4,0,1,0, 4,0,2,0},//rhythm2
	{ 2,0,1,0, 4,0,1,0, 6,0,1,0, 4,0,2,0, 2,0,1,0, 4,0,1,0, 5,0,1,0, 4,1,2,1},//rhythm3
	{ 4,1,1,1, 2,0,1,0, 4,0,1,0, 1,0,5,0, 4,0,1,1, 2,0,1,0, 4,0,1,0, 4,1,5,1},//rhythm4

	{ 4,0,2,1, 2,0,1,0, 4,0,1,0, 6,0,1,0, 4,0,2,0, 2,0,1,0, 4,0,1,0, 6,1,2,1},//rhythm5
	
	{ 4,0,2,0, 4,0,3,0, 4,0,1,0, 5,0,3,1, 4,0,3,1, 4,0,3,0, 4,0,1,0, 5,1,1,1},//rhythm6

	{ 4,0,2,0, 1,0,1,0, 6,0,1,0, 4,0,2,0, 1,0,1,0, 6,0,1,0, 1,0,1,0, 4,0,1,0},//rhythm7
	{ 2,0,1,1, 3,0,1,0, 4,1,1,0, 3,0,1,0, 4,0,1,0, 3,0,1,0, 2,0,1,0, 3,0,1,1},//rhythm8
	{ 4,0,3,0, 7,0,1,0, 5,0,3,0, 7,0,3,0, 6,0,1,0, 3,0,1,0, 6,0,1,0, 3,0,7,0},//rhythm9

};

/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/

char *constructSounds[NUM_CONSTRUCT_SAMPLES] =
{
	"h",				//SFX_CONSTRUCT_H           
	"k",				//SFX_CONSTRUCT_K			
	"kh",				//SFX_CONSTRUCT_KH			
	"ks",				//SFX_CONSTRUCT_KS			
	"ksh",				//SFX_CONSTRUCT_KSH			
	"s",				//SFX_CONSTRUCT_S			
	"sh",				//SFX_CONSTRUCT_SH			
	"chickhammer1",		//SFX_CONSTRUCT_HAMMER1		
	"chickhammer2",		//SFX_CONSTRUCT_HAMMER2		
	"chickhammer3",		//SFX_CONSTRUCT_HAMMER3		
	"chickspanner1",	//SFX_CONSTRUCT_SPANNER1	
	"chickspanner2",	//SFX_CONSTRUCT_SPANNER2	
	"chickspanner3",	//SFX_CONSTRUCT_SPANNER3	
	"saw1",				//SFX_CONSTRUCT_SAW1		
	"saw2",				//SFX_CONSTRUCT_SAW2		
	"saw3",				//SFX_CONSTRUCT_SAW3		
	"ohhhh",			//SFX_CONSTRUCT_TWEEDY1
	"ooah",				//SFX_CONSTRUCT_TWEEDY2
	"whoosh",			//SFX_CONSTRUCT_WHOOSH,
	"quackhuh",			//SFX_CONSTRUCT_QUACK, 
};


void constructLoadsnd(int levelNum, SfxSampleType **pSamples, int arraySize)
{
	int i;

	ASSERT(pSamples);

	for(i=0; i<arraySize; i++)
		pSamples[i] = NULL;

	ASSERT(arraySize >= NUM_CONSTRUCT_SAMPLES);


	for(i=0; i<NUM_CONSTRUCT_SAMPLES; i++)
	{
		pSamples[i]	= sfxFindSampleInAllBanks(constructSounds[i]);

#ifdef DEBUG
		if(pSamples[i] == NULL)
			DB("construct pSamples[%d] not found\n",i);
#endif
		ASSERT(pSamples[i]);
	}

																		 
	fowlerSubGameSample[SFX_FOWLER_BRONZE] = sfxFindSampleInAllBanks("sub_con_bronze");
	ASSERT(fowlerSubGameSample[SFX_FOWLER_BRONZE]);

	fowlerSubGameSample[SFX_FOWLER_SILVER] = sfxFindSampleInAllBanks("sub_con_silver");
	ASSERT(fowlerSubGameSample[SFX_FOWLER_SILVER]);

	fowlerSubGameSample[SFX_FOWLER_GOLD] = sfxFindSampleInAllBanks("sub_con_gold");
	ASSERT(fowlerSubGameSample[SFX_FOWLER_GOLD]);

	fowlerSubGameSample[SFX_FOWLER_FAIL] = sfxFindSampleInAllBanks("sub_con_fail");
	ASSERT(fowlerSubGameSample[SFX_FOWLER_FAIL]);
}

/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void constructStart()
{
	int i, dist, height;
	char string[32];

	overlayLoadingBegin(1);


	con = (CONSTRUCT_DATA*)MALLOC(sizeof(CONSTRUCT_DATA));
	memset(con, 0, sizeof(CONSTRUCT_DATA));

	if(gameCalledFrom != GAMECALLEDFROM_DEBUG)
	{
		if(!gameSaveData.levels_available[REPLAY_AVAILABLE_BUILDING])
		{
			gameSaveData.levels_available[REPLAY_AVAILABLE_BUILDING] = REPLAY_NOTBEATEN;
		}
	}



	draw_routine = constructDraw;
	cycle_routine = constructCycle;

//	fw->countdown = FW_COUNTDOWN_TIME * FRAMESEC;

//	pReadPad->shockEnable=1;	// Need to go from the options screen now. Sorry. Fred

	dsEvent_Init();

	// ============
	// Load the world map that we'll be using
	// ============

// RFW	EXLIGHT_Initialise();	// called inside mapviewLoadMap

//	loadsndLoadBank("A4_CONSTRUCT");
	sound_FreeLanguageBank();
	sound_LoadLanguageBankBody(gameTextLang, "A4_CONSTRUCT");	// Loads "A4_CONSTRUCT\\A4_CONSTRUCT_eng.sbb" (or other language versions)


	mapviewLoadMap("A4_CONSTRUCT");			// Load the map we're going to use
	setupCollision("A4_CONSTRUCT");			// Setup the collision for the level map
	EXLIGHT_PostBFF();


	initFowler(CONSTRUCT_FOV, SG_CONSTRUCT);
//	loadsndSubGames(LEVNUMBER_A4_CONSTRUCT, con->pSamples, NUM_CONSTRUCT_SAMPLES);
	constructLoadsnd(LEVNUMBER_A4_CONSTRUCT, con->pSamples, NUM_CONSTRUCT_SAMPLES);


	overlayLoadingEnd();


	con->tools[CON_HAMMER].model = BFF_IsModelLoaded("HAMMER");
	ASSERT(con->tools[CON_HAMMER].model);
	con->tools[CON_HAMMER].actor = actorCreate(con->tools[CON_HAMMER].model);
	ASSERT(con->tools[CON_HAMMER].actor);
	actorInitAnim(con->tools[CON_HAMMER].actor);	

	con->tools[CON_HAMMER].actor->position.vx = CON_HAMMER_XPOS;
	con->tools[CON_HAMMER].actor->position.vy = CON_HAMMER_YPOS;
	con->tools[CON_HAMMER].actor->position.vz = CON_HAMMER_ZPOS;
	con->tools[CON_HAMMER].actor->psiData.object->rotate.vy = CON_HAMMER_YROT;



	con->tools[CON_SPANNER].model = BFF_IsModelLoaded("SPANNER");
	ASSERT(con->tools[CON_SPANNER].model);
	con->tools[CON_SPANNER].actor = actorCreate(con->tools[CON_SPANNER].model);
	ASSERT(con->tools[CON_SPANNER].actor);
	actorInitAnim(con->tools[CON_SPANNER].actor);
	

	con->tools[CON_SPANNER].actor->position.vx =  CON_SPANNER_XPOS;
	con->tools[CON_SPANNER].actor->position.vy =  CON_SPANNER_YPOS;
	con->tools[CON_SPANNER].actor->position.vz =  CON_SPANNER_ZPOS;
	con->tools[CON_SPANNER].actor->psiData.object->rotate.vy = CON_SPANNER_YROT;


	con->tools[CON_SAWER].model = BFF_IsModelLoaded("SAWER");
	ASSERT(con->tools[CON_SAWER].model);
	con->tools[CON_SAWER].actor = actorCreate(con->tools[CON_SAWER].model);
	ASSERT(con->tools[CON_SAWER].actor);
	actorInitAnim(con->tools[CON_SAWER].actor);
	
	con->tools[CON_SAWER].actor->position.vx = CON_SAWER_XPOS;
	con->tools[CON_SAWER].actor->position.vy =	CON_SAWER_YPOS;
	con->tools[CON_SAWER].actor->position.vz =	CON_SAWER_ZPOS;
	con->tools[CON_SAWER].actor->psiData.object->rotate.vy = CON_SAWER_YROT;

	actorAnimate(con->tools[CON_SAWER].actor,CON_BREATH, TRUE, FALSE, 300, 0, 900);
	actorAnimate(con->tools[CON_SPANNER].actor,CON_BREATH, TRUE, FALSE, 300, 0, 900);
	actorAnimate(con->tools[CON_HAMMER].actor,CON_BREATH, TRUE, FALSE, 300, 0, 900);

	con->tools[CON_SAWER].state = CON_TOOL_PREPARE;


	con->tweedy.model = BFF_IsModelLoaded("MRTWEEDYC");
	ASSERT(con->tweedy.model);
	con->tweedy.actor = actorCreate(con->tweedy.model);
	ASSERT(con->tweedy.actor);
	actorInitAnim(con->tweedy.actor);

	actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_SIGH, FALSE, FALSE, 300, 0, 0);
	actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_BREATHE, FALSE, TRUE, 300, 0, 0);
	actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_SCRATCH_HEAD, FALSE, TRUE, 300, 0, 0);

	con->tweedy.state = CON_TWEEDY_STOP_WORKING;

	con->rhythm.state = CON_RHYTHM_STATE_STARTNEW;

	for(i=0; i<8; i++)
		con->rhythm.qMarkStates[i] = 0;//ie inactive


	PSImodelctrl.farclip =  1023;
	max_map_ot_depth = 1023;

	// init camera stuff
	con->cam.state = CON_CAMSTATE_ARRIVED;
	con->cam.targetTool = 0;
	con->cam.lastTool = 0;
	con->cam.distBetweenCamPos = 0;

	con->cam.pos = conCamPos[0];
	con->cam.garibPos = conGaribPos[0];


	mycamera.vpx = con->cam.pos.vx;
	mycamera.vpy = con->cam.pos.vy;
	mycamera.vpz = con->cam.pos.vz;

	mycamera.vrx = con->cam.garibPos.vx;
	mycamera.vry = con->cam.garibPos.vy;
	mycamera.vrz = con->cam.garibPos.vz;



	con->tweedy.overlay = textureFindInAllBanks("TELESC");
	ASSERT(con->tweedy.overlay);



	for(i=0; i<CON_NUM_TOOLS; i++)
	{
		dist = Magnitude2D( (conCamPos[i].vx - conGaribPos[i].vx), (conCamPos[i].vz - conGaribPos[i].vz) );
		height =  (conGaribPos[i].vy - conCamPos[i].vy);

		conCamAngle[i] = (4096*dist)/height;
	}


//	con->rhythm.chick[0] = textureFindInAllBanks("CHICK1");
//	ASSERT(con->rhythm.chick[0]);
//	con->rhythm.chick[1] = textureFindInAllBanks("CHICK2");
//	ASSERT(con->rhythm.chick[1]);


// Rhythm things

	con->rhythm.model =	BFF_IsModelLoaded("CHICK");
	ASSERT(con->rhythm.model);
	con->rhythm.actor = actorCreate(con->rhythm.model);
	ASSERT(con->rhythm.actor);
	actorInitAnim(con->rhythm.actor);

	actorAnimate(con->rhythm.actor, 0, TRUE, FALSE, 400, 0, 0);

#ifdef DREAMCAST
 	con->rhythm.buttons[CON_SQUARE] = textureFindInAllBanks("X_BUTTON");
	ASSERT(con->rhythm.buttons[CON_SQUARE]);
	con->rhythm.buttons[CON_CROSS] = textureFindInAllBanks("A_BUTTON");
	ASSERT(con->rhythm.buttons[CON_CROSS]);
	con->rhythm.buttons[CON_CIRCLE]	= textureFindInAllBanks("B_BUTTON");
	ASSERT(con->rhythm.buttons[CON_CIRCLE]);

	con->rhythm.wrongButtons[CON_SQUARE] = textureFindInAllBanks("X_BUTCROSS");
	ASSERT(con->rhythm.wrongButtons[CON_SQUARE]);
	con->rhythm.wrongButtons[CON_CROSS] = textureFindInAllBanks("A_BUTCROSS");
	ASSERT(con->rhythm.wrongButtons[CON_CROSS]);
	con->rhythm.wrongButtons[CON_CIRCLE]	= textureFindInAllBanks("B_BUTCROSS");
	ASSERT(con->rhythm.wrongButtons[CON_CIRCLE]);
#else
	#ifdef _WINDOWS
		con->rhythm.buttons[CON_SQUARE] = textureFindInAllBanks("PCBUT_4");
		ASSERT(con->rhythm.buttons[CON_SQUARE]);
		con->rhythm.buttons[CON_CROSS] = textureFindInAllBanks("PCBUT_3");
		ASSERT(con->rhythm.buttons[CON_CROSS]);
		con->rhythm.buttons[CON_CIRCLE]	= textureFindInAllBanks("PCBUT_2");
		ASSERT(con->rhythm.buttons[CON_CIRCLE]);

		con->rhythm.wrongButtons[CON_SQUARE] = textureFindInAllBanks("PCBUT_4X");
		ASSERT(con->rhythm.wrongButtons[CON_SQUARE]);
		con->rhythm.wrongButtons[CON_CROSS] = textureFindInAllBanks("PCBUT_3X");
		ASSERT(con->rhythm.wrongButtons[CON_CROSS]);
		con->rhythm.wrongButtons[CON_CIRCLE]	= textureFindInAllBanks("PCBUT_2X");
		ASSERT(con->rhythm.wrongButtons[CON_CIRCLE]);
	#else
		con->rhythm.buttons[CON_SQUARE] = textureFindInAllBanks("SQUARE");
		ASSERT(con->rhythm.buttons[CON_SQUARE]);
		con->rhythm.buttons[CON_CROSS] = textureFindInAllBanks("CROSS");
		ASSERT(con->rhythm.buttons[CON_CROSS]);
		con->rhythm.buttons[CON_CIRCLE]	= textureFindInAllBanks("CIRCLE");
		ASSERT(con->rhythm.buttons[CON_CIRCLE]);

		con->rhythm.wrongButtons[CON_SQUARE] = textureFindInAllBanks("SQUAREX");
		ASSERT(con->rhythm.wrongButtons[CON_SQUARE]);
		con->rhythm.wrongButtons[CON_CROSS] = textureFindInAllBanks("CROSSX");
		ASSERT(con->rhythm.wrongButtons[CON_CROSS]);
		con->rhythm.wrongButtons[CON_CIRCLE]	= textureFindInAllBanks("CIRCLEX");
		ASSERT(con->rhythm.wrongButtons[CON_CIRCLE]);
	#endif
#endif
	con->rhythm.back = textureFindInAllBanks("COMBO");
	ASSERT(con->rhythm.back);

	con->rhythm.qMark = textureFindInAllBanks("QMARK");
	ASSERT(con->rhythm.qMark);

//	con->progBar = textureFindInAllBanks("GRADER");
//	ASSERT(con->progBar);

	con->goldBar = textureFindInAllBanks("GRADERG");
	ASSERT(con->goldBar);
	con->silverBar = textureFindInAllBanks("GRADERS");
	ASSERT(con->silverBar);
	con->bronzeBar = textureFindInAllBanks("GRADERB");
	ASSERT(con->bronzeBar);

	con->arrow = textureFindInAllBanks("RARROW");
	ASSERT(con->arrow);


	con->tweedycEyesAnim[0] = textureFindInAllBanks("MRTWEEDYC_EYEOPEN");
	ASSERT(con->tweedycEyesAnim[0]);

	con->tweedycEyesAnim[1] = textureFindInAllBanks("MRTWEEDYC_EYECLOSED");
	ASSERT(con->tweedycEyesAnim[1]);

	con->tweedycEyesDummy = textureFindInAllBanks("MRTWEEDYC_EYES");
	ASSERT(con->tweedycEyesDummy);

	con->tweedycEyesBlinking = textureCreateAnimation(con->tweedycEyesDummy,con->tweedycEyesAnim,2);
	ASSERT(con->tweedycEyesBlinking);

	con->eyesTimer = 0;

	myactor = con->tools[CON_SAWER].actor;
}



/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void constructReset()
{
	int i, dist, height;
	char string[32];


	dsEvent_Init();

	con->progress = 0;
	con->gameState = CON_GAMESTATE_FADEIN;
	con->frameCount = 1;
	con->rhythm.currentBeat = 0;
	con->rhythm.currentRhythm = 0;
	con->rhythm.lastBeat = 0;
	con->rhythm.numTimesPlayed = 0;
	con->rhythm.posInBar = 0;
	con->rhythm.posOnWood = 0;
	con->rhythm.state = 0;
	con->whoosh = 0;

	for(i=0; i<8; i++)
		con->rhythm.qMarkStates[i] = 0;//ie inactive



	// setting arrays to 0
	memset((void*)con->rhythm.currentButtons, 0, 8);
	memset((void*)con->rhythm.pressedButtons, 0, 8);

	


	con->tools[CON_HAMMER].actor->position.vx = CON_HAMMER_XPOS;
	con->tools[CON_HAMMER].actor->position.vy = CON_HAMMER_YPOS;
	con->tools[CON_HAMMER].actor->position.vz = CON_HAMMER_ZPOS;
	con->tools[CON_HAMMER].actor->psiData.object->rotate.vy = CON_HAMMER_YROT;

	con->tools[CON_SPANNER].actor->position.vx =  CON_SPANNER_XPOS;
	con->tools[CON_SPANNER].actor->position.vy =  CON_SPANNER_YPOS;
	con->tools[CON_SPANNER].actor->position.vz =  CON_SPANNER_ZPOS;
	con->tools[CON_SPANNER].actor->psiData.object->rotate.vy = CON_SPANNER_YROT;

	con->tools[CON_SAWER].actor->position.vx = CON_SAWER_XPOS;
	con->tools[CON_SAWER].actor->position.vy =	CON_SAWER_YPOS;
	con->tools[CON_SAWER].actor->position.vz =	CON_SAWER_ZPOS;
	con->tools[CON_SAWER].actor->psiData.object->rotate.vy = CON_SAWER_YROT;

	actorAnimate(con->tools[CON_SAWER].actor,CON_BREATH, TRUE, FALSE, 300, 0, 900);
	actorAnimate(con->tools[CON_SPANNER].actor,CON_BREATH, TRUE, FALSE, 300, 0, 900);
	actorAnimate(con->tools[CON_HAMMER].actor,CON_BREATH, TRUE, FALSE, 300, 0, 900);

	con->tools[CON_SAWER].state = CON_TOOL_PREPARE;
	con->tools[CON_SPANNER].state = CON_TOOL_IDLE;
	con->tools[CON_HAMMER].state = CON_TOOL_IDLE;

	actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_SIGH, FALSE, FALSE, 300, 0, 0);
	actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_BREATHE, FALSE, TRUE, 300, 0, 0);
	actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_SCRATCH_HEAD, FALSE, TRUE, 300, 0, 0);

	con->tweedy.state = CON_TWEEDY_STOP_WORKING;

	con->rhythm.state = CON_RHYTHM_STATE_STARTNEW;

	// init camera stuff
	con->cam.state = CON_CAMSTATE_ARRIVED;
	con->cam.targetTool = 0;
	con->cam.lastTool = 0;
	con->cam.distBetweenCamPos = 0;

	con->cam.pos = conCamPos[0];
	con->cam.garibPos = conGaribPos[0];


	mycamera.vpx = con->cam.pos.vx;
	mycamera.vpy = con->cam.pos.vy;
	mycamera.vpz = con->cam.pos.vz;

	mycamera.vrx = con->cam.garibPos.vx;
	mycamera.vry = con->cam.garibPos.vy;
	mycamera.vrz = con->cam.garibPos.vz;

//	for(i=0; i<CON_NUM_TOOLS; i++)
//	{
//		dist = Magnitude2D( (conCamPos[i].vx - conGaribPos[i].vx), (conCamPos[i].vz - conGaribPos[i].vz) );
//		height =  (conGaribPos[i].vy - conCamPos[i].vy);

//		conCamAngle[i] = (4096*dist)/height;
//	}

	actorAnimate(con->rhythm.actor, 0, TRUE, FALSE, 400, 0, 0);

	con->eyesTimer = 0;

	myactor = con->tools[CON_SAWER].actor;

//	sound_XA_Start(levinfo->tune_number);

}


/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void constructEnd()
{

	sound_XA_Stop();
	sfxStopChannel(-1);


	if(subGameRestart == TRUE)
	{
		constructReset();
	}
	else
	{
		constructFree();
		
		//menuStart();

//		mapviewReleaseMap();

		memoryShowStats();
		memoryShow();
		act4SubgameComplete("A4_WORKHUT4");
	}


//	if(subGameRestart == TRUE)
//	{
//		constructStart();
//	}
//	else
//	{
//		act4SubgameComplete("A4_WORKHUT4");
//	}
}

#define CON_TELESCOPE_X  34
#ifdef DREAMCAST
#define CON_TELESCOPE_Y  -107
#else
#define CON_TELESCOPE_Y  -110
#endif
#define CON_INRO_TEXT_XPOS  -170


#ifdef DREAMCAST

#if PALMODE==1
int CON_ARROW_Y = -110;
#else
int CON_ARROW_Y = -108;
#endif

#else

#if PALMODE==1
#define CON_ARROW_Y  -110
#else
#define CON_ARROW_Y  -108
#endif

#endif


					   



/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void constructFree(void)
{

	sound_XA_Stop();
	sfxStopChannel(-1);

	mapviewReleaseMap();
	dsEvent_Init();
		

	textureDestroyAnimation(con->tweedycEyesBlinking);


	actorFree(con->tools[CON_HAMMER].actor);
	actorFree(con->tools[CON_SPANNER].actor);
	actorFree(con->tools[CON_SAWER].actor);
	actorFree(con->tweedy.actor);
	actorFree(con->rhythm.actor);
	freeFowler();
		
	FREE(con);

	memoryShowStats();
	memoryShow();

//		sound_XA_Stop();
	sound_LoadLanguageBank(gameTextLang);

}




/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void constructRestart()
{
	subGameRestart = TRUE;
	con->frameCount = 1;
	con->gameState = CON_GAMESTATE_FADEOUT;
}

/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void constructExit()
{
	con->frameCount = 1;
	con->gameState = CON_GAMESTATE_FADEOUT;
	subGameRestart = FALSE;
}



/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void constructDraw()
{
	int i;

#if defined(DREAMCAST)
	depthBump = constructWorldDepth;
#endif

#if defined(_WINDOWS)
	depthBump = 12000;
#endif

	GsSetProjection(CONSTRUCT_FOV);

	mapCamSetRefView2L(&mycamera);

#ifdef _WINDOWS
 	SetDrawOffsetPC(256, 128);

#endif
	
	MapDraw_DrawFMA_World((FMA_WORLD2 *)mapview_fma_world);

#if defined(_WINDOWS) || defined(DREAMCAST)
	depthBump = 0;
#endif

	actorMaintainAnimation(con->tools[CON_SAWER].actor);
	EXLIGHT_SetupActorLights(con->tools[CON_SAWER].actor);
#ifdef _WINDOWS
	d2mActorDraw(con->tools[CON_SAWER].actor);
#else
	actorDraw(con->tools[CON_SAWER].actor);
#endif

	actorMaintainAnimation(con->tools[CON_SPANNER].actor);
	EXLIGHT_SetupActorLights(con->tools[CON_SPANNER].actor);
#ifdef _WINDOWS
	d2mActorDraw(con->tools[CON_SPANNER].actor);
#else
	actorDraw(con->tools[CON_SPANNER].actor);
#endif

	actorMaintainAnimation(con->tools[CON_HAMMER].actor);
	EXLIGHT_SetupActorLights(con->tools[CON_HAMMER].actor);
#ifdef _WINDOWS
	d2mActorDraw(con->tools[CON_HAMMER].actor);
#else
	actorDraw(con->tools[CON_HAMMER].actor);
#endif

	if(!con->eyesTimer)
	{
		if(utilRandomInt(100)>93)
		{
			textureSetAnimation(con->tweedycEyesBlinking,1);
			con->eyesTimer = 2;		// Hold the blink for 3! frames 
		}
		else
		{
			textureSetAnimation(con->tweedycEyesBlinking,0);
		}
	}
	else
		con->eyesTimer--;


	if((con->gameState != CON_GAMESTATE_OUTRO)&&(con->gameState != CON_GAMESTATE_FADEIN) && (con->gameState != CON_GAMESTATE_FADEOUT))
	{

		conDrawRhythm();
		conDrawProgressBar();

	//	if((con->gameState != CON_GAMESTATE_FADEIN) && (con->gameState != CON_GAMESTATE_FADEOUT))
#ifdef DREAMCAST
		noFilter=1;
  		overlaySprite(con->tweedy.overlay, CON_TELESCOPE_X, CON_TELESCOPE_Y, 1500,0xff808080);
		noFilter=0;
#else
	#ifdef _WINDOWS
		SetDrawOffsetPC(256, 128);

  		overlaySprite(con->tweedy.overlay, CON_TELESCOPE_X, CON_TELESCOPE_Y, 11000,0xff808080);
	#else
		overlaySprite(con->tweedy.overlay, CON_TELESCOPE_X, CON_TELESCOPE_Y, 10,0xff808080);
	#endif
#endif
		conDrawTweedy();

	}

	constructPrintDebugText();

	switch(con->gameState)
	{
		case CON_GAMESTATE_FADEIN:

			if(subGameRestart == TRUE)
			{
				i= 255 - (con->frameCount)*20;
				if(i <= 0)
					con->gameState = CON_GAMESTATE_INTRO;
				else
					deathScreenAdd(i, i, i, SEMITRANS_SUB, 2);
			}
			else
				con->gameState = CON_GAMESTATE_INTRO;
			break;

		case CON_GAMESTATE_INTRO:
			conDrawIntro();
			break;

		case CON_GAMESTATE_RUNNING:
		case CON_GAMESTATE_ENDING:

			 DrawDirectionArrows(con->arrow, CON_ARROW_Y);

//			alpha = ((rsin(con->frameCount*SG_ARROW_FLASH_FREQ) + 4096) / 128) + 64;
//			overlaySprite(con->arrow, CON_ARROW_RX, CON_ARROW_Y, 4, alpha*(0x10101));
//			overlaySpriteFlipped(con->arrow, CON_ARROW_LX, CON_ARROW_Y, 4, alpha*(0x10101));
			break;

		case CON_GAMESTATE_OUTRO:

			if(con->progress < CON_PROGRESS_BRONZE_SCORE)
			{
				//fail
#ifdef DREAMCAST
				depthBump = constructFowlerBump;
#endif
				fowlerDraw();
				conDrawFail();
			}
			else if(con->progress < CON_PROGRESS_SILVER_SCORE)
			{
				//bronze
#ifdef DREAMCAST
				depthBump = constructFowlerBump;
#endif
				fowlerDraw();
				conDrawBronzeSuccess();
			}
			else if(con->progress < CON_PROGRESS_GOLD_SCORE)
			{
				//silver
#ifdef DREAMCAST
				depthBump = constructFowlerBump;
#endif
				fowlerDraw();
				conDrawSilverSuccess();

			}
			else
			{
				//gold
#ifdef DREAMCAST
				depthBump = constructFowlerBump;
#endif
				fowlerDraw();
				conDrawGoldSuccess();

			}
			break;

		case CON_GAMESTATE_FADEOUT:

			if(subGameRestart == TRUE)
			{
				i= (con->frameCount)*20;
				if(i > 220)
					deathScreenAdd(255, 255, 255, SEMITRANS_SUB, 0);

//				if(i >=255)
//				{
//					constructEnd();
//				}
				else
					deathScreenAdd(i, i, i, SEMITRANS_SUB, 0);
			}
//			else
//				constructEnd();

			break;
	}
#ifdef DREAMCAST
	depthBump = 0;
#endif

}








#define CON_PROGRESS_XPOS  6

#ifdef DREAMCAST

#if PALMODE==1
int CON_PROGRESS_YPOS = 90;
#else
int CON_PROGRESS_YPOS = 80;
#endif

#else

#if PALMODE==1
#define CON_PROGRESS_YPOS  90
#else
#define CON_PROGRESS_YPOS  80
#endif

#endif

#define CON_PROG_BAR_YOFFSET  -1




#define CON_PROGRESS_BACK_DEPTH   5
#define CON_PROGRESS_FRONT_DEPTH  constructBoxDepth - 1
#ifdef DREAMCAST
#define CON_PROGRESS_BAR_DEPTH    constructBoxDepth - 1
#else
#define CON_PROGRESS_BAR_DEPTH    2
#endif
#define CON_PROGRESS_BAR_LEFT   28
#define CON_PROGRESS_BAR_TOP    6
#define CON_PROGRESS_BAR_WIDTH  168
#define CON_PROGRESS_BAR_HEIGHT 9



//-----------------------------------------------------------------------------------------------------------------------
void conDrawProgressBar()
{
	POLY_G4 *bar;
	unsigned short r1,b1,g1;
	unsigned long gold, silver, bronze;


	gold = silver = bronze = 0xff808080;

	BEGINPRIM(bar, POLY_G4);
	setPolyG4(bar);				

#ifdef DREAMCAST
	{
		int x,y;

		x = CON_PROGRESS_XPOS; 
		y = CON_PROGRESS_YPOS; 

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

		bar->x0 = x + (CON_PROGRESS_BAR_LEFT*1.25);				
		bar->y0 = y + (CON_PROGRESS_BAR_TOP*1.875);	

		bar->x1 = bar->x0 + (((con->progress * CON_PROGRESS_BAR_WIDTH)/CON_PROGRESS_MAX)*1.25);
		bar->y1 = bar->y0;

		bar->x2 = bar->x0;
		bar->y2 = bar->y0 + (CON_PROGRESS_BAR_HEIGHT*1.875);
		
		// on power
		bar->x3 = bar->x1;
		bar->y3 = bar->y2;
	}
#else
	bar->x0 = CON_PROGRESS_XPOS + CON_PROGRESS_BAR_LEFT;				
	bar->y0 = CON_PROGRESS_YPOS + CON_PROGRESS_BAR_TOP;	

	bar->x1 = bar->x0 + (con->progress * CON_PROGRESS_BAR_WIDTH)/CON_PROGRESS_MAX;
	bar->y1 = bar->y0;

	bar->x2 = bar->x0;
	bar->y2 = bar->y0 + CON_PROGRESS_BAR_HEIGHT;
	
	// on power
	bar->x3 = bar->x1;
	bar->y3 = bar->y2;
#endif
	if(con->progress < CON_PROGRESS_BRONZE_SCORE)
	{
		// nothing
	 	bar->r0 = 110;
		bar->g0 = 110;
		bar->b0 = 110;
		bar->r1 = 120;
		bar->g1 = 120;
		bar->b1 = 120;
	}
	else if(con->progress < CON_PROGRESS_SILVER_SCORE)
	{
		//bronze

		bronze = 0xffcccccc;
	 	bar->r0 = 180;
		bar->g0 = 140;
		bar->b0 = 120;
		bar->r1 = 180;
		bar->g1 = 160;
		bar->b1 = 140;
	}
	else if(con->progress < CON_PROGRESS_GOLD_SCORE)
	{
		//silver
		bronze = silver = 0xffcccccc;

		bar->r0 = 160;
		bar->g0 = 160;
		bar->b0 = 210;
		bar->r1 = 190;
		bar->g1 = 190;
		bar->b1 = 210;
	}
	else
	{
		//gold
		bronze = silver = gold = 0xffcccccc;

		bar->r0 = 240;
		bar->g0 = 230;
		bar->b0 = 160;
		bar->r1 = 240;
		bar->g1 = 230;
		bar->b1 = 190;
	}

	bar->r2 = bar->r0;
	bar->g2 = bar->g0;
	bar->b2 = bar->b0;
	bar->r3 = bar->r1;
	bar->g3 = bar->g1;
	bar->b3 = bar->b1;
		
	ENDPRIM(bar, CON_PROGRESS_BAR_DEPTH, POLY_G4);

	overlaySprite(con->goldBar, CON_PROGRESS_XPOS + CON_PROG_GOLD_XOFFSET, CON_PROGRESS_YPOS + CON_PROG_BAR_YOFFSET, CON_PROGRESS_FRONT_DEPTH,0xff999999);
	overlaySprite(con->silverBar, CON_PROGRESS_XPOS + CON_PROG_SILVER_XOFFSET, CON_PROGRESS_YPOS + CON_PROG_BAR_YOFFSET, CON_PROGRESS_FRONT_DEPTH,0xff999999);
	overlaySprite(con->bronzeBar, CON_PROGRESS_XPOS + CON_PROG_BRONZE_XOFFSET, CON_PROGRESS_YPOS + CON_PROG_BAR_YOFFSET, CON_PROGRESS_FRONT_DEPTH,0xff999999);

}






#define CON_TWEEDY_CAM_LOOKATX  0
#define CON_TWEEDY_CAM_LOOKATY  0
#define CON_TWEEDY_CAM_LOOKATZ  0

#define CON_TWEEDY_CAM_X  0
#define CON_TWEEDY_CAM_Y  0
#define CON_TWEEDY_CAM_Z  -10000

#define MY_DEPTH_OVERRIDE  8
#define MY_OFFSET_DEPTH    1



#define CON_CLIP_XSIZE  140
#define CON_CLIP_YSIZE  70

#define CONTWEEDY_XOFFSET  136
#define CONTWEEDY_YOFFSET  100

#define CONTWEEDY_CLIP_XPOS  52
#define CONTWEEDY_CLIP_YPOS  -97

int ax=4,ay=6,bx=18,by=12;
//-----------------------------------------------------------------------------------------------------------------------
void conDrawTweedy()
{
	PSIMODELCTRL		*modctrl = &PSImodelctrl;

	int depth = 1;
	VECTOR oldCamPos;
	VECTOR oldGaribPos;

#ifdef DREAMCAST
	KMRECT area;

   	SetDrawOffsetDC(CONTWEEDY_CLIP_XPOS-CON_CLIP_XSIZE/2 + CONTWEEDY_XOFFSET, CONTWEEDY_CLIP_YPOS-CON_CLIP_YSIZE/2 + CONTWEEDY_YOFFSET);
#else
	#ifdef _WINDOWS
	{
		RECTPS clip;

		clip.x = CONTWEEDY_CLIP_XPOS;
		clip.y = CONTWEEDY_CLIP_YPOS;
		clip.w = CON_CLIP_XSIZE;
   		clip.h = CON_CLIP_YSIZE;
		SetDrawArea(NULL, &clip);

		SetDrawOffsetPC(256 + CONTWEEDY_CLIP_XPOS-CON_CLIP_XSIZE/2 + CONTWEEDY_XOFFSET,
						128 + CONTWEEDY_CLIP_YPOS-CON_CLIP_YSIZE/2 + CONTWEEDY_YOFFSET);
	}
	#else
	{	// CPW: put it back
		DR_AREA *da;
		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, MY_OFFSET_DEPTH, DR_OFFSET);

		da = BEGINPRIM(da, DR_AREA);
		SetDrawArea(da, &currentDisplayPage->drawenv.clip);
		ENDPRIM(da, depth, DR_AREA);
	}
	#endif
#endif


// 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 = CON_TWEEDY_CAM_LOOKATX;
	mycamera.vry = CON_TWEEDY_CAM_LOOKATY;
	mycamera.vrz = CON_TWEEDY_CAM_LOOKATZ;

	mycamera.vpx = CON_TWEEDY_CAM_X;
	mycamera.vpy = CON_TWEEDY_CAM_Y;
	mycamera.vpz = CON_TWEEDY_CAM_Z;


	mapCamSetRefView2L(&mycamera);

#if defined(DREAMCAST)
	depthBump=-3900;//-8500
	DCscaledown=1;
#else
	#ifdef _WINDOWS
		depthBump = -utilRandomInt(10000);
	#else
		PSImodelctrl.depthoverride = MY_DEPTH_OVERRIDE;
	#endif
#endif

	actorMaintainAnimation(con->tweedy.actor);
	EXLIGHT_SetupActorLights(con->tweedy.actor);
#ifdef DREAMCAST
	area.nXmin = 1;//ax;
	area.nYmin = 1;//ay;
	area.nXmax = 18;//bx;
	area.nYmax = 5;//by;
	clippingOn =1;
	kmSetUserClipping(&vertexBufferDesc, KM_USERCLIP_OUTSIDE,KM_OPAQUE_POLYGON,&area);
	actorDraw(con->tweedy.actor);
	clippingOn = 0;
	kmSetUserClipping(&vertexBufferDesc, KM_USERCLIP_DISABLE,KM_OPAQUE_POLYGON,&area);
	depthBump=0;
	DCscaledown=0;
#else
	#ifdef _WINDOWS
		d2mActorDraw(con->tweedy.actor);
	#else	// CPW: PSX
		actorDraw(con->tweedy.actor);
		PSImodelctrl.depthoverride = 0;
	#endif
#endif

	{// set clip window
		
#ifndef _WINDOWS
		RECT clip;
#else
		RECTPS clip;
#endif
		DR_AREA *da;
		DR_OFFSET *dof;
	
		u_short ofs[2];

		clip.x = currentDisplayPage->drawenv.clip.x + 256 + CONTWEEDY_CLIP_XPOS;
		clip.y = currentDisplayPage->drawenv.clip.y + 128 + CONTWEEDY_CLIP_YPOS;
		clip.w = CON_CLIP_XSIZE;
   		clip.h = CON_CLIP_YSIZE;
#ifdef DREAMCAST
		SetDrawOffsetDC(0,0);
#else
	#ifdef _WINDOWS
	{// CPW: on PC, put clip back afterwards
		RECTPS clip;

		clip.x = -256;
		clip.y = -128;
		clip.w = 512;
   		clip.h = 256;
		SetDrawOffsetPC(256, 128);
		SetDrawArea(NULL, &clip);

		SetDrawOffsetPC(0,0);
	}
	#else
		da = BEGINPRIM(da, DR_AREA);
   		SetDrawArea(da, &clip);
   		ENDPRIM(da, depth, DR_AREA);

		dof = BEGINPRIM(dof, DR_OFFSET);
		ofs[0] = currentDisplayPage->drawenv.ofs[0]+CONTWEEDY_CLIP_XPOS-CON_CLIP_XSIZE/2 + CONTWEEDY_XOFFSET;
		ofs[1] = currentDisplayPage->drawenv.ofs[1]+CONTWEEDY_CLIP_YPOS-CON_CLIP_YSIZE/2 + CONTWEEDY_YOFFSET;
		SetDrawOffset(dof, ofs);
		ENDPRIM(dof, MY_OFFSET_DEPTH, DR_OFFSET);
	#endif
#endif

	}


	//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);

}



#define CON_BACK_XPOS   16

#ifdef DREAMCAST

#if PALMODE==1
int CON_BACK_YPOS = 36;
#else
int CON_BACK_YPOS = 26;
#endif

#else

#if PALMODE==1
  #define CON_BACK_YPOS   36
#else
  #define CON_BACK_YPOS   26
#endif

#endif

#define BUTTON_START_X   2
#define BUTTON_START_Y   7
#define HALF_BEAT_DELTA  25
#define FULL_BEAT_DELTA  50
#define CHICK_START_Y    -22
int CON_CHICK_MOVE_FACTOR = 133;
#define CON_PRESSED_Y  25



// button is active from 0 - 12 these are the limits of when the button is lit up
#define CON_LIGHT_START    5
#define CON_LIGHT_END      10
#define QMARK_MOVE_FACTOR  5

//-----------------------------------------------------------------------------------------------------------------------
void conDrawRhythm()
{
	int i, tempInt;
	TextureType *texture;

/*
#ifdef BUFFALO
//#ifdef DEBUG

	char string[128];
	static int mynote = 0;

	if(pReadPad->debounce[0] & PAD_LEFT)
	{
		mynote--;
		if(mynote < 0) mynote = 31;
	}
	if(pReadPad->debounce[0] & PAD_RIGHT)
	{
		mynote++;
		if(mynote > 31) mynote = 0;
	}

	if(pReadPad->debounce[0] & PAD_UP)
	{
		conBackRythm[con->rhythm.currentRhythm][mynote]++;
		if(conBackRythm[con->rhythm.currentRhythm][mynote] > 7)
			conBackRythm[con->rhythm.currentRhythm][mynote] = 0;
	}

	if(pReadPad->debounce[0] & PAD_DOWN)
	{
		conBackRythm[con->rhythm.currentRhythm][mynote]--;
		if(conBackRythm[con->rhythm.currentRhythm][mynote] < 0)
			conBackRythm[con->rhythm.currentRhythm][mynote] = 7;
	}


	sprintf(string, "rhythm%d\nsel..%d.. . \n0.   %d%d%d%d 4. %d%d%d%d \n8. %d%d%d%d 12. %d%d%d%d \n16. %d%d%d%d 20. %d%d%d%d \n24. %d%d%d%d 28. %d%d%d%d ", con->rhythm.currentRhythm,mynote, 
		conBackRythm[con->rhythm.currentRhythm][0],conBackRythm[con->rhythm.currentRhythm][1],conBackRythm[con->rhythm.currentRhythm][2],conBackRythm[con->rhythm.currentRhythm][3],
		conBackRythm[con->rhythm.currentRhythm][4],conBackRythm[con->rhythm.currentRhythm][5],conBackRythm[con->rhythm.currentRhythm][6],conBackRythm[con->rhythm.currentRhythm][7],
		conBackRythm[con->rhythm.currentRhythm][8],conBackRythm[con->rhythm.currentRhythm][9],conBackRythm[con->rhythm.currentRhythm][10],conBackRythm[con->rhythm.currentRhythm][11],
		conBackRythm[con->rhythm.currentRhythm][12],conBackRythm[con->rhythm.currentRhythm][13],conBackRythm[con->rhythm.currentRhythm][14],conBackRythm[con->rhythm.currentRhythm][15],
		conBackRythm[con->rhythm.currentRhythm][16],conBackRythm[con->rhythm.currentRhythm][17],conBackRythm[con->rhythm.currentRhythm][18],conBackRythm[con->rhythm.currentRhythm][19],
		conBackRythm[con->rhythm.currentRhythm][20],conBackRythm[con->rhythm.currentRhythm][21],conBackRythm[con->rhythm.currentRhythm][22],conBackRythm[con->rhythm.currentRhythm][23],
		conBackRythm[con->rhythm.currentRhythm][24],conBackRythm[con->rhythm.currentRhythm][25],conBackRythm[con->rhythm.currentRhythm][26],conBackRythm[con->rhythm.currentRhythm][27],
		conBackRythm[con->rhythm.currentRhythm][28],conBackRythm[con->rhythm.currentRhythm][29],conBackRythm[con->rhythm.currentRhythm][30],conBackRythm[con->rhythm.currentRhythm][31]);

	fontPrintMultiLineBox(font, 0, 0, 340, string, 0, 128, 128);
	//fontPrint(font, -250, 0, string, 0, 128, 128);


#endif
 */
	


	overlaySprite(con->rhythm.back, CON_BACK_XPOS, CON_BACK_YPOS, constructBoxDepth+8,0xff808080);

	for(i=0; i<8; i++)
	{
		
		if(((con->rhythm.state == CON_RHYTHM_STATE_STARTNEW)||(con->rhythm.state == CON_RHYTHM_STATE_CHANGING))&&(con->rhythm.qMarkStates[i]))
		{
//			if((con->rhythm.qMarkStates[i] >1)&&(i<2))
//				DB("%d, state %d\n", i, con->rhythm.qMarkStates[i]);

			//DB("here1\n");
			tempInt = (CON_BACK_YPOS + BUTTON_START_Y + CON_PRESSED_Y) - ((con->rhythm.qMarkStates[i]-1) * QMARK_MOVE_FACTOR);
			overlaySprite(con->rhythm.qMark, CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, tempInt, constructBoxDepth+3,0xff808080);
		}
		
		if(con->rhythm.currentButtons[i] > 0)
		{

			//(con->rhythm.posInBar + (CON_TIME_FOR_BAR/16)) / (CON_TIME_FOR_BAR/8)

			if(con->tweedy.state != CON_TWEEDY_WORKING)
#ifdef DREAMCAST
				overlaySprite(con->rhythm.buttons[con->rhythm.currentButtons[i]-1], CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, CON_BACK_YPOS + BUTTON_START_Y, -5,0xff404080);
#else
				overlaySprite(con->rhythm.buttons[con->rhythm.currentButtons[i]-1], CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, CON_BACK_YPOS + BUTTON_START_Y, 5,0xff404080);
#endif
			else if((i == con->rhythm.currentBeat) && (con->rhythm.beatDistance >= CON_LIGHT_START ) && (con->rhythm.beatDistance <= CON_LIGHT_END) &&(con->rhythm.state ==CON_RHYTHM_STATE_TESTING) && ((con->rhythm.numTimesPlayed < (CON_MAX_TIMES_PLAYED-1))||(con->rhythm.currentBeat != 0 )) && (con->tweedy.state == CON_TWEEDY_WORKING))
#ifdef DREAMCAST
				overlaySprite(con->rhythm.buttons[con->rhythm.currentButtons[i]-1], CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, CON_BACK_YPOS + BUTTON_START_Y, -5,0xffeeeeee);
#else
				overlaySprite(con->rhythm.buttons[con->rhythm.currentButtons[i]-1], CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, CON_BACK_YPOS + BUTTON_START_Y, 5,0xffeeeeee);
#endif
			else
#ifdef DREAMCAST
				overlaySprite(con->rhythm.buttons[con->rhythm.currentButtons[i]-1], CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, CON_BACK_YPOS + BUTTON_START_Y, -5,0xff808080);
#else
				overlaySprite(con->rhythm.buttons[con->rhythm.currentButtons[i]-1], CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, CON_BACK_YPOS + BUTTON_START_Y, 5,0xff808080);
#endif
		}
		
		if(con->rhythm.pressedButtons[i] > 0)
#ifdef DREAMCAST
			overlaySprite(con->rhythm.buttons[con->rhythm.pressedButtons[i]-1], CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, CON_BACK_YPOS + BUTTON_START_Y + CON_PRESSED_Y, -5,0xff808080);
#else
			overlaySprite(con->rhythm.buttons[con->rhythm.pressedButtons[i]-1], CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, CON_BACK_YPOS + BUTTON_START_Y + CON_PRESSED_Y, 5,0xff808080);
#endif
		else if(con->rhythm.pressedButtons[i] < 0)
#ifdef DREAMCAST
			overlaySprite(con->rhythm.wrongButtons[-1 - con->rhythm.pressedButtons[i]], CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, CON_BACK_YPOS + BUTTON_START_Y + CON_PRESSED_Y, -5,0xff808080);
#else
			overlaySprite(con->rhythm.wrongButtons[-1 - con->rhythm.pressedButtons[i]], CON_BACK_XPOS + BUTTON_START_X + i*FULL_BEAT_DELTA/2, CON_BACK_YPOS + BUTTON_START_Y + CON_PRESSED_Y, 5,0xff808080);
#endif

	}
	

	if((con->rhythm.state == CON_RHYTHM_STATE_TESTING) || (con->rhythm.state == CON_RHYTHM_STATE_CHANGING))//(con->tweedy.state == CON_TWEEDY_WORKING)||(con->tweedy.state == CON_TWEEDY_SUSPICIOUS))//
	{

		conDrawChick();


//		if((con->frameCount % 4) < 2)
//			texture = con->rhythm.chick[0];
//		else
//			texture = con->rhythm.chick[1];

//		overlaySprite(texture, CON_BACK_XPOS + BUTTON_START_X + (con->rhythm.posOnWood * CON_CHICK_MOVE_FACTOR)/4096 , CON_BACK_YPOS + CHICK_START_Y, 5,0xff808080);
	}


}





#define CHICK_TWEEDY_CAM_LOOKATX  0
#define CHICK_TWEEDY_CAM_LOOKATY  0
#define CHICK_TWEEDY_CAM_LOOKATZ  0

#define CHICK_TWEEDY_CAM_X  0
#define CHICK_TWEEDY_CAM_Y  0
#define CHICK_TWEEDY_CAM_Z  -8000

//int MY_DEPTH_OVERRIDE = 8;
//int MY_OFFSET_DEPTH = 1;



#define CHICK_CLIP_XSIZE  52
#define CHICK_CLIP_YSIZE  64

#define CHICKTWEEDY_XOFFSET  50
#define CHICKTWEEDY_YOFFSET  98


#define CHICK_CHICK_CLIP_XPOS	6

#ifdef DREAMCAST

#if PALMODE==1
int CHICK_CHICK_CLIP_YPOS =	-28;
#else
int CHICK_CHICK_CLIP_YPOS = -38;
#endif

#else

#if PALMODE==1
#define CHICK_CHICK_CLIP_YPOS	-28
#else
#define CHICK_CHICK_CLIP_YPOS	-38
#endif

#endif
//int CON_CHICK_ROTATE = 0;


//-----------------------------------------------------------------------------------------------------------------------
void conDrawChick()
{
	PSIMODELCTRL		*modctrl = &PSImodelctrl;

	int depth = 1;
	VECTOR oldCamPos;
	VECTOR oldGaribPos;


	int clipXPos = CHICK_CHICK_CLIP_XPOS + (con->rhythm.posOnWood * CON_CHICK_MOVE_FACTOR)/4096;

//	con->rhythm.actor->psiData.object->rotate.vy = CON_CHICK_ROTATE;

	{	// CPW: put it back
		DR_AREA *da;
		DR_OFFSET *dof;
		u_short ofs[2];

#ifdef DREAMCAST
	SetDrawOffsetDC(clipXPos-CHICK_CLIP_XSIZE/2 + CHICKTWEEDY_XOFFSET,CHICK_CHICK_CLIP_YPOS-CHICK_CLIP_YSIZE/2 + CHICKTWEEDY_YOFFSET);
#else
	#ifdef _WINDOWS
		SetDrawOffsetPC(256 + clipXPos-CHICK_CLIP_XSIZE/2 + CHICKTWEEDY_XOFFSET,
						128 + CHICK_CHICK_CLIP_YPOS-CHICK_CLIP_YSIZE/2 + CHICKTWEEDY_YOFFSET);
	#else
		dof = BEGINPRIM(dof, DR_OFFSET);
		ofs[0] = currentDisplayPage->drawenv.ofs[0];
		ofs[1] = currentDisplayPage->drawenv.ofs[1];
		SetDrawOffset(dof, ofs);
		ENDPRIM(dof, MY_OFFSET_DEPTH, DR_OFFSET);

		da = BEGINPRIM(da, DR_AREA);
		SetDrawArea(da, &currentDisplayPage->drawenv.clip);
		ENDPRIM(da, depth, DR_AREA);
	#endif
#endif
	}


// 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 = CHICK_TWEEDY_CAM_LOOKATX;
	mycamera.vry = CHICK_TWEEDY_CAM_LOOKATY;
	mycamera.vrz = CHICK_TWEEDY_CAM_LOOKATZ;

	mycamera.vpx = CHICK_TWEEDY_CAM_X;
	mycamera.vpy = CHICK_TWEEDY_CAM_Y;
	mycamera.vpz = CHICK_TWEEDY_CAM_Z;


	mapCamSetRefView2L(&mycamera);


	PSImodelctrl.depthoverride = MY_DEPTH_OVERRIDE;

	actorMaintainAnimation(con->rhythm.actor);
	EXLIGHT_SetupActorLights(con->rhythm.actor);

#ifdef _WINDOWS
	d2mActorDraw(con->rhythm.actor);
#else
	actorDraw(con->rhythm.actor);
#endif

	PSImodelctrl.depthoverride = 0;

	
	{// set clip window
		
#ifndef _WINDOWS		
		RECT clip;
#else
		RECTPS clip;
#endif

		DR_AREA *da;
		DR_OFFSET *dof;

		u_short ofs[2];

		clip.x = currentDisplayPage->drawenv.clip.x + 256 + clipXPos;
		clip.y = currentDisplayPage->drawenv.clip.y + 128 + CHICK_CHICK_CLIP_YPOS;
		clip.w = CHICK_CLIP_XSIZE;
   		clip.h = CHICK_CLIP_YSIZE;
	
#ifdef DREAMCAST
	SetDrawOffsetDC(0,0);
#else
	#ifdef _WINDOWS
		SetDrawOffsetPC(0,0);
	#else
   		da = BEGINPRIM(da, DR_AREA);
   		SetDrawArea(da, &clip);
   		ENDPRIM(da, depth, DR_AREA);
		
		dof = BEGINPRIM(dof, DR_OFFSET);
		ofs[0] = currentDisplayPage->drawenv.ofs[0]+clipXPos-CHICK_CLIP_XSIZE/2 + CHICKTWEEDY_XOFFSET;
		ofs[1] = currentDisplayPage->drawenv.ofs[1]+CHICK_CHICK_CLIP_YPOS-CHICK_CLIP_YSIZE/2 + CHICKTWEEDY_YOFFSET;
		SetDrawOffset(dof, ofs);
		ENDPRIM(dof, MY_OFFSET_DEPTH, DR_OFFSET);
	#endif
#endif

	}


	//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);
}




void conDrawIntro()
{
	char string[256];
	
#ifdef _WINDOWS
	SetDrawOffsetPC(256, 128);
#endif

	sprintf(string, "%s\n\n%s\n\n%s\n\n%s",
		fontUpper((char*)TEXTSTR(TEXTSTR_NAME_OF_CONSTRUCT)),
		(char*)TEXTSTR(TEXTSTR_SUB_CON_INTRO1),
		(char*)TEXTSTR(TEXTSTR_SUB_CON_BUTTONS), 
		(char*)TEXTSTR(TEXTSTR_SUB_XSTART)
		);

	fontPrintMultiLineBox(font, 0, 10, 340, string, 100, 100, 100);
}






#define CON_OUTRO_WIDTH       380
#define CON_OUTRO_TEXT_XPOS   -196
#define CON_OUTRO_MARGIN      34

#define CON2_OUTRO_WIDTH      420
#define CON2_OUTRO_TEXT_XPOS  -220
#define CON2_OUTRO_MARGIN     26



//------------------------------------------------
void conDrawBronzeSuccess()
{
	char string[256];
	
	sprintf(string, "%s\n%s", (char*)TEXTSTR(TEXTSTR_SUB_CON_BRONZE), (char*)TEXTSTR(TEXTSTR_SUB_GAME_EXIT_RESTART));
	fontPrintMultiLineBoxSetDepth(font, 0, 10, 340, string, 120, 100, 0,constructBoxDepth);
}

//------------------------------------------------
void conDrawSilverSuccess()
{
	char string[256];
	
	sprintf(string, "%s\n%s", (char*)TEXTSTR(TEXTSTR_SUB_CON_SILVER), (char*)TEXTSTR(TEXTSTR_SUB_GAME_EXIT_RESTART));
	fontPrintMultiLineBoxSetDepth(font, 0, 10, 340, string, 120, 100, 0,constructBoxDepth);
}										   

//------------------------------------------------
void conDrawGoldSuccess()
{
	char string[256];
	
	sprintf(string, "%s\n%s", (char*)TEXTSTR(TEXTSTR_SUB_CON_GOLD), (char*)TEXTSTR(TEXTSTR_SUB_GAME_EXIT_RESTART));
	fontPrintMultiLineBoxSetDepth(font, 0, 10, 340, string, 120, 100, 0,constructBoxDepth);
}


//------------------------------------------------
void conDrawFail()
{
	char string[256];
	
	sprintf(string, "%s\n%s", (char*)TEXTSTR(TEXTSTR_SUB_CON_FAIL), (char*)TEXTSTR(TEXTSTR_SUB_GAME_EXIT_RESTART));
	fontPrintMultiLineBoxSetDepth(font, 0, 10, 340, string, 120, 100, 0,constructBoxDepth);
}




/*	--------------------------------------------------------------------------------
	Function 	: 
	Purpose 	: 
	Parameters 	: 
	Returns 	: 
	Info 		:
*/
void constructCycle()
{
	int i;


	con->frameCount++;

	EXLIGHT_Update();
	dsEvent_Update();


//	if(pReadPad->debounce[0] & PAD_TRIANGLE)
//		soundPlaySample(con->pSamples[SFX_CONSTRUCT_SPANNER3], 0x8080, 0);



	switch(con->gameState)
	{
		case CON_GAMESTATE_FADEIN:
			break;
		case CON_GAMESTATE_INTRO:
			if(pReadPad->debounce[0] & PAD_CROSS)
			{
				con->gameState = CON_GAMESTATE_RUNNING;
				subGameRestart = FALSE;
			}
#ifdef DREAMCAST
			else if(pReadPad->debounce[0] & PAD_CIRCLE)
#else
			else if(pReadPad->debounce[0] & PAD_TRIANGLE)
#endif
			{
				con->frameCount = 0;
				con->gameState = CON_GAMESTATE_FADEOUT;
				subGameRestart = FALSE;
				return;
			}
			break;

		case CON_GAMESTATE_RUNNING:


			if(pReadPad->debounce[0] & PAD_START)
			{
				pause_levelplaying = LEVNUMBER_A4_CONSTRUCT;
				pauseStart();
				return;
			}




#ifdef DEBUG
#ifdef DREAMCAST
			if(pReadPad->debounce[0] & PAD_L2)
#else
			if(SwimCheatCycle())
#endif
			{
				con->gameState = CON_GAMESTATE_ENDING;
				con->progress = CON_PROGRESS_BRONZE_SCORE;
				actorAnimate(con->tweedy.actor, CON_MRTWEEDY_OI_BUGGERS, FALSE, TRUE, 200, 0, 900);

			}
#endif


//			constructControl();
			conUpdateCamera();
			conUpdateRhythm();
			conUpdateTools();
			conUpdateMrTweedy();
			break;

		case CON_GAMESTATE_ENDING:

			// CON_MRTWEEDY_OI_BUGGERS


			if((con->tweedy.actor->animation.animData[0].reachedEnd)&&(con->tweedy.actor->animation.animData[0].scaledFrameOffset > 0) && (con->tweedy.actor->animation.animData[0].segment == CON_MRTWEEDY_OI_BUGGERS))
			{
				con->gameState = CON_GAMESTATE_OUTRO;



				if(con->progress < CON_PROGRESS_BRONZE_SCORE)
				{
					sound_XA_Start(TUNE_4_FAILED + SOUND_XA_NOLOOP);
					startFowler(FAIL);
				}
				else
				{
					if(gameCalledFrom != GAMECALLEDFROM_DEBUG)
					{
						gamePlayData->SubGameStates[SUBGAME_CONSTRUCT] = REPLAY_BEATEN;
						gameSaveData.levels_available[REPLAY_AVAILABLE_BUILDING] = REPLAY_BEATEN;
					}

					if(con->progress < CON_PROGRESS_SILVER_SCORE)
					{
						//bronze
						if(gameSaveData.medals_won[MEDAL_WON_CONSTRUCTION] < 1) 
							gameSaveData.medals_won[MEDAL_WON_CONSTRUCTION] = 1; 

						sound_XA_Start(TUNE_3_COMPLETE + SOUND_XA_NOLOOP);
						startFowler(BRONZE);

					}
					else if(con->progress < CON_PROGRESS_GOLD_SCORE)
					{
						//silver
						if(gameSaveData.medals_won[MEDAL_WON_CONSTRUCTION] < 2) 
							gameSaveData.medals_won[MEDAL_WON_CONSTRUCTION] = 2; 
						sound_XA_Start(TUNE_3_COMPLETE + SOUND_XA_NOLOOP);
						startFowler(SILVER);
					}
					else
					{
						//gold
						gameSaveData.medals_won[MEDAL_WON_CONSTRUCTION] = 3; 
						sound_XA_Start(TUNE_3_COMPLETE + SOUND_XA_NOLOOP);
						startFowler(GOLD);
					}
				}
			}



			// check for end of Tweedy anim then bring on outr screen
			break;

		case CON_GAMESTATE_OUTRO:

			makeFowlerSpeak();


			if(con->frameCount > 10)
			{
				if(pReadPad->debounce[0] & PAD_CROSS)
				{
					con->frameCount = 0;
					con->gameState = CON_GAMESTATE_FADEOUT;
					subGameRestart = TRUE;
				
				}
#ifdef DREAMCAST
				else if(pReadPad->debounce[0] & PAD_CIRCLE)
#else
				else if(pReadPad->debounce[0] & PAD_TRIANGLE)
#endif
				{
					con->frameCount = 0;
					con->gameState = CON_GAMESTATE_FADEOUT;
					subGameRestart = FALSE;
				}
			}
			break;

		case CON_GAMESTATE_FADEOUT:
			if(subGameRestart == TRUE)
			{
				i= (con->frameCount)*20;
				if(i >=255)
				{
					constructEnd();
					return;
				}
			}
			else
			{
				constructEnd();
				return;
			}
			break;
	}
#ifdef _WINDOWS
	DI_KEYUPDATEALL;
#endif
}



#define CON_RYTHM_TIME_PER_FRAME  64

#define CON_MYPITCH			 920
#define CON_TOOL_ANIM_SPEED  800


//would prefer 8 but sometimes they don't get played then
#define CON_BEAT_DIST_PLAYED_ON  7

//-----------------------------------------------------------------------------------------------------------------------
void conUpdateRhythm()
{
	int tempInt;
	int sampleNum;
	int sampleBeat;
	int soundPlayed=0;


	switch(con->rhythm.state)
	{
		case CON_RHYTHM_STATE_OFF:
			break;

		case CON_RHYTHM_STATE_SHOWING:
			break;

		case CON_RHYTHM_STATE_COUNTING:
			break;
		
		case CON_RHYTHM_STATE_TESTING:

		
			// which 1/8th your on
			con->rhythm.currentBeat = (con->rhythm.posInBar + (CON_TIME_FOR_BAR/16)) / (CON_TIME_FOR_BAR/8);
			con->rhythm.beatDistance = ((con->rhythm.posInBar + (CON_TIME_FOR_BAR/16)) % (CON_TIME_FOR_BAR/8))/64;

//			DB("beat= %d ,dist= %d\n", con->rhythm.currentBeat, con->rhythm.beatDistance);

			if(con->rhythm.currentBeat == 8)
				con->rhythm.currentBeat = 0;

			if((con->rhythm.lastBeat == 7) && (con->rhythm.currentBeat == 0))
			{
				for(tempInt=0; tempInt<8; tempInt++)
				{
					con->rhythm.pressedButtons[tempInt] = 0;
				}
			}



#ifdef _WINDOWS
			if((DI_KEY(DIK_2) || DI_KEY(DIK_3) || DI_KEY(DIK_4)) &&
				(con->rhythm.pressedButtons[con->rhythm.currentBeat] == 0) &&
				!((con->rhythm.numTimesPlayed == CON_MAX_TIMES_PLAYED-1) &&
				(con->rhythm.currentBeat == 0) && (con->rhythm.posInBar > 1000) ) &&
				(con->cam.state == CON_CAMSTATE_ARRIVED) && (con->tweedy.state == CON_TWEEDY_WORKING))
#else
			if((pReadPad->debounce[0] & (PAD_CROSS|PAD_CIRCLE|PAD_SQUARE)) &&
				(con->rhythm.pressedButtons[con->rhythm.currentBeat] == 0) &&
				!((con->rhythm.numTimesPlayed == CON_MAX_TIMES_PLAYED-1) &&
				(con->rhythm.currentBeat == 0) && (con->rhythm.posInBar > 1000) ) &&
				(con->cam.state == CON_CAMSTATE_ARRIVED) && (con->tweedy.state == CON_TWEEDY_WORKING))
#endif
			{
#ifdef _WINDOWS
				if(DI_KEYDEB(DIK_3))
#else
				if(pReadPad->debounce[0] & PAD_CROSS)
#endif
				{
					if((rhythms[con->rhythm.currentRhythm][con->rhythm.currentBeat] == CON_CROSS+1)&&(con->activeTool == con->tweedy.currentTool) )
						con->rhythm.pressedButtons[con->rhythm.currentBeat] = CON_CROSS+1;
					else
					{
						con->rhythm.pressedButtons[con->rhythm.currentBeat] = -(CON_CROSS+1);

//					DB("c:consoundPlayed pib=%d\n", con->rhythm.posInBar);

						// only play sound if Tweedy isn't playing same thing!
						conPlaySound(FALSE, CON_CROSS+1);
						soundPlayed = 1;
					}
				}

#ifdef _WINDOWS
				if(DI_KEYDEB(DIK_4))
#else
				if(pReadPad->debounce[0] & PAD_SQUARE)
#endif
				{
					if((rhythms[con->rhythm.currentRhythm][con->rhythm.currentBeat] == CON_SQUARE+1)&&(con->activeTool == con->tweedy.currentTool) )
						con->rhythm.pressedButtons[con->rhythm.currentBeat] = CON_SQUARE+1;
					else
					{
						con->rhythm.pressedButtons[con->rhythm.currentBeat] = -(CON_SQUARE+1);

						conPlaySound(FALSE, CON_SQUARE+1);
						soundPlayed = 1;
					}
				}

#ifdef _WINDOWS
				if(DI_KEYDEB(DIK_2))
#else
				if(pReadPad->debounce[0] & PAD_CIRCLE)
#endif
				{
					if((rhythms[con->rhythm.currentRhythm][con->rhythm.currentBeat] == CON_CIRCLE+1)&&(con->activeTool == con->tweedy.currentTool) )
						con->rhythm.pressedButtons[con->rhythm.currentBeat] = CON_CIRCLE+1;
					else
					{
						con->rhythm.pressedButtons[con->rhythm.currentBeat] = -(CON_CIRCLE+1);
		
						conPlaySound(FALSE, CON_CIRCLE+1);
						soundPlayed = 1;
					}
				}

				if(con->rhythm.pressedButtons[con->rhythm.currentBeat] < 0)
				{
					con->tweedy.state = CON_TWEEDY_SUSPICIOUS;
				}
				else
				{
					con->progress++;
					if(con->progress > CON_PROGRESS_MAX)
						con->progress = CON_PROGRESS_MAX;
				}

				actorAnimate(con->tools[con->activeTool].actor, CON_WORK, FALSE, FALSE, CON_TOOL_ANIM_SPEED, 0, 0);
				actorAnimate(con->tools[con->activeTool].actor, CON_READY, TRUE, TRUE, 300, 0, 0);
			}

			if(con->rhythm.beatDistance == CON_BEAT_DIST_PLAYED_ON)//(con->rhythm.posInBar % (CON_TIME_FOR_BAR/8)) == 0)
			{
				if((con->tweedy.state == CON_TWEEDY_WORKING) && (con->rhythm.currentButtons[con->rhythm.currentBeat] > 0))
				{

					//if(!soundPlayed)
					//{
						soundPlayed = 1;
						conPlaySound(TRUE, con->rhythm.currentButtons[con->rhythm.currentBeat]);// need to make this tweedy?, tool??, button

						//DB("%d\n",con->rhythm.currentBeat);
						//DB("consoundPlayed pib=%d\n", con->rhythm.posInBar);

					//}
					// try anim here may have to move it to previous frame!
					switch(con->tweedy.currentTool)
					{
						case CON_SAWER:
							actorAnimate(con->tweedy.actor, CON_MRTWEEDY_SAW, FALSE, FALSE, 600, 0, 0);
							break;
						case CON_HAMMER:
							actorAnimate(con->tweedy.actor, CON_MRTWEEDY_HAMMER, FALSE, FALSE, 600, 0, 0);
							break;
						case CON_SPANNER:
							actorAnimate(con->tweedy.actor, CON_MRTWEEDY_SPANNER, FALSE, FALSE, 600, 0, 0);
							break;
					}
				}
			}															    ///16
			
			
			// The money....
			// if tweedy or player hasn't made a noise find out which one and do it here
			if((!soundPlayed)&&((con->rhythm.posInBar) % (CON_TIME_FOR_BAR/32)) == 0)
			{
				//play 32 beat
				
//				if(con->rhythm.currentBeat == 0)
//					sampleBeat = 31;
//				else
					///sampleBeat = (con->rhythm.currentBeat*2)-1;
					sampleBeat = (con->rhythm.posInBar/(CON_TIME_FOR_BAR/32))-1;

				if(sampleBeat < 0)
					sampleBeat += 32;

				sampleNum = conBackRythm[con->rhythm.currentRhythm][sampleBeat];



				if(sampleNum > 0)
				{

#ifdef PRINT_SOUNDS
				DB("beat = %d  sn = %d\n",sampleBeat, sampleNum);
#endif
					sampleNum--;
					soundPlayed = 1;
					soundPlaySample(con->pSamples[sampleNum], 0xffff, CON_MYPITCH);
				}


			}


			con->rhythm.posInBar += CON_RYTHM_TIME_PER_FRAME;

		
			if((con->rhythm.posInBar > ((CON_TIME_FOR_BAR * 15)/16)) && (con->rhythm.numTimesPlayed < (CON_MAX_TIMES_PLAYED-1)))
				con->rhythm.posOnWood = con->rhythm.posInBar - CON_TIME_FOR_BAR;
			else
				con->rhythm.posOnWood = con->rhythm.posInBar;



			if(con->rhythm.posInBar == CON_TIME_FOR_BAR)
			{
				con->rhythm.posInBar = 0;
				con->rhythm.numTimesPlayed++;

			
				// start tweedy anims etc here
				if(con->rhythm.numTimesPlayed >= CON_MAX_TIMES_PLAYED)
				{
					con->rhythm.currentRhythm++;// = random(CON_NUM_RHYTHMS);

					if(con->rhythm.currentRhythm >= CON_NUM_RHYTHMS)
					{
						DB("ending Rhythms\n");
						con->rhythm.state = CON_RHYTHM_STATE_OFF;
						con->tweedy.state = CON_TWEEDY_STOP_WORKING;
//						con->rhythm.currentRhythm = 0;
						break;
					}

					con->rhythm.state = CON_RHYTHM_STATE_STARTNEW;


					con->tweedy.state = CON_TWEEDY_STOP_WORKING;

					con->rhythm.numTimesPlayed = 0;

					//clear buttons
					for(tempInt=0; tempInt<8; tempInt++)
					{
						con->rhythm.currentButtons[tempInt] = 0;
//						con->rhythm.pressedButtons[tempInt] = 0;
					}
					break;
				}
			}




			break;

		case CON_RHYTHM_STATE_STARTNEW:
			
	//		if(con->frameCount % 2)
	//		{
				tempInt=0; 
				while(tempInt<8) 
				{
					if(con->rhythm.qMarkStates[tempInt] == 0)
					{
						con->rhythm.qMarkStates[tempInt] = 1;
						break;
					}
					tempInt++;
				}
	//		}
			
		case CON_RHYTHM_STATE_CHANGING:

			con->rhythm.currentBeat = (con->rhythm.posInBar + (CON_TIME_FOR_BAR/16)) / (CON_TIME_FOR_BAR/8);
			con->rhythm.beatDistance = ((con->rhythm.posInBar + (CON_TIME_FOR_BAR/16)) % (CON_TIME_FOR_BAR/8))/64;

//			DB("beat= %d ,dist= %d\n", con->rhythm.currentBeat, con->rhythm.beatDistance);

																								  // if it hasn't started yet but it's gonna
			if(((con->rhythm.state == CON_RHYTHM_STATE_CHANGING)&&(con->rhythm.currentBeat < 8))||((con->rhythm.currentBeat == 8)&&(con->tweedy.state == CON_TWEEDY_WORKING)&&(con->rhythm.state == CON_RHYTHM_STATE_STARTNEW)))
			{
				//aaarrggh yes i know
				if(con->rhythm.currentBeat == 8)
					con->rhythm.currentBeat = 0;

				if(con->rhythm.beatDistance < CON_BEAT_DIST_PLAYED_ON)
					con->rhythm.qMarkStates[con->rhythm.currentBeat] = con->rhythm.beatDistance;
				else
					con->rhythm.qMarkStates[con->rhythm.currentBeat] = 0;

#ifdef DEBUG

//				if(con->rhythm.currentBeat <= 1)
//				{
//					DB("%d..%d\n", con->rhythm.currentBeat,con->rhythm.beatDistance);
//				}

#endif



			}


			if(con->rhythm.currentBeat == 8)
				con->rhythm.currentBeat = 0;


			if((con->rhythm.state != CON_RHYTHM_STATE_STARTNEW)&&(con->rhythm.beatDistance == CON_BEAT_DIST_PLAYED_ON))//(con->rhythm.posInBar % (CON_TIME_FOR_BAR/8)) == 0)
			{
				tempInt = (con->rhythm.posInBar / (CON_TIME_FOR_BAR/8));
				con->rhythm.currentButtons[tempInt] = rhythms[con->rhythm.currentRhythm][tempInt];

				if(/*(con->tweedy.state == CON_TWEEDY_WORKING) && */(con->rhythm.currentButtons[tempInt] > 0))
				{
					conPlaySound(TRUE, con->rhythm.currentButtons[tempInt]);// need to make this tweedy?, tool??, button
//					DB("b:consoundPlayed pib=%d\n", con->rhythm.posInBar);

					soundPlayed = 1;
				// try animhere may have to move it to previous frame!
					switch(con->tweedy.currentTool)
					{
						case CON_SAWER:
							actorAnimate(con->tweedy.actor, CON_MRTWEEDY_SAW, FALSE, FALSE, 900, 0, 0);
							break;
						case CON_HAMMER:
							actorAnimate(con->tweedy.actor, CON_MRTWEEDY_HAMMER, FALSE, FALSE, 900, 0, 0);
							break;
						case CON_SPANNER:
							actorAnimate(con->tweedy.actor, CON_MRTWEEDY_SPANNER, FALSE, FALSE, 900, 0, 0);
							break;
					}
				}
			}




			// MONEY money money
			if((!soundPlayed)&&(con->rhythm.posInBar % (CON_TIME_FOR_BAR/32)) == 0)
			{
				sampleBeat = (con->rhythm.posInBar/(CON_TIME_FOR_BAR/32))-1;

				if(sampleBeat < 0)
					sampleBeat += 32;


				sampleNum = conBackRythm[con->rhythm.currentRhythm][sampleBeat];

				if(sampleNum > 0)
				{


#ifdef PRINT_SOUNDS
				DB("beat = %d  sn = %d\n",sampleBeat, sampleNum);
#endif

					sampleNum--;
					soundPlaySample(con->pSamples[sampleNum], 0xffff, CON_MYPITCH);
					soundPlayed = 1;
				}
			}

			con->rhythm.posInBar += CON_RYTHM_TIME_PER_FRAME;

			if(con->rhythm.posInBar == CON_TIME_FOR_BAR)
			{
				con->rhythm.posInBar = 0;


				if(con->rhythm.state == CON_RHYTHM_STATE_STARTNEW)
				{
					 if(con->tweedy.state == CON_TWEEDY_WORKING)
 						con->rhythm.state = CON_RHYTHM_STATE_CHANGING;
				}
				else
					con->rhythm.state = CON_RHYTHM_STATE_TESTING;
			}

			if(con->rhythm.posInBar > ((CON_TIME_FOR_BAR * 15)/16))
				con->rhythm.posOnWood = con->rhythm.posInBar - CON_RYTHM_TIME_PER_FRAME;
			else
				con->rhythm.posOnWood = con->rhythm.posInBar;

			break;

//		case CON_RHYTHM_STATE_STARTNEW:

			// if tweedy ready then...
/*
			if(con->tweedy.state == CON_TWEEDY_WORKING)
			{
				if(con->rhythm.currentRhythm >= CON_NUM_RHYTHMS)
				{
					// Game Over . . .
					//con->gameState = CON_GAMESTATE_ENDING;
					con->rhythm.state = CON_RHYTHM_STATE_OFF;
//					con->tweedy.state = CON_TWEEDY_STOP_WORKING;
//					break;

					// animate Tweedy

					// game state = ending


//					con->rhythm.currentRhythm = 0;
				}

///				con->rhythm.posInBar = 0;
				con->rhythm.state = CON_RHYTHM_STATE_CHANGING;
			}
			break;
*/		
		case CON_RHYTHM_STATE_PLACINGBUTTONS:
			break;
	}


	if((con->rhythm.state != CON_RHYTHM_STATE_STARTNEW)&&(con->rhythm.state != CON_RHYTHM_STATE_OFF))
	{


		// test for and call chick anims here
		if(con->rhythm.currentBeat != con->rhythm.lastBeat)
		{

			if((rhythms[con->rhythm.currentRhythm][con->rhythm.currentBeat] > 0) && (con->tweedy.state == CON_TWEEDY_WORKING))
			{
				switch((rhythms[con->rhythm.currentRhythm][con->rhythm.currentBeat]-1))
				{
					case CON_SQUARE:
						actorAnimate(con->rhythm.actor, CON_CHICK_SQUARE, FALSE, FALSE,500, 0, 0);
						actorAnimate(con->rhythm.actor, CON_CHICK_WALK, TRUE, TRUE,500, 0, 0);
						//DB("square\n");
						break;

					case CON_CROSS:
						actorAnimate(con->rhythm.actor, CON_CHICK_CROSS, FALSE, FALSE,500, 0, 0);
						actorAnimate(con->rhythm.actor, CON_CHICK_WALK, TRUE, TRUE,500, 0, 0);
						//DB("cross\n");
						break;

					case CON_CIRCLE:
						actorAnimate(con->rhythm.actor, CON_CHICK_CIRCLE, FALSE, FALSE,500, 0, 0);
						actorAnimate(con->rhythm.actor, CON_CHICK_WALK, TRUE, TRUE,500, 0, 0);
						//DB("circle\n");
						break;

					default:
					//	DB("poo\n");
						break;
				}
			}


			con->rhythm.lastBeat = con->rhythm.currentBeat;
		}
	}

	if((!soundPlayed)&&(con->whoosh))
	{
		soundPlaySample(con->pSamples[SFX_CONSTRUCT_WHOOSH], 0x6060, RAND_FREQ(120));
		con->whoosh = 0;
	}

}


//-----------------------------------------------------------------------------------------------------------------------
void conUpdateMrTweedy()
{
	switch(con->tweedy.state)
	{
		case CON_TWEEDY_IDLE:
			

			if(con->frameCount == 2)
			{
//				int i;
				if(con->activeTool == con->tweedy.currentTool)
				{
					soundPlaySample(con->pSamples[SFX_CONSTRUCT_QUACK], 0xaaaa, RAND_FREQ(120));
				}
				else
				{
//					i = utilRandomInt(1);
//					if(i)
//						soundPlaySample(con->pSamples[SFX_CONSTRUCT_TWEEDY1], 0xaaaa, RAND_FREQ(120));
//					else
						soundPlaySample(con->pSamples[SFX_CONSTRUCT_TWEEDY2], 0xaaaa, RAND_FREQ(120));
				}
			}

			
			if((con->tweedy.actor->animation.queueSize == 0)&&(con->tweedy.actor->animation.animData[0].reachedEnd)&&(con->tweedy.actor->animation.animData[0].scaledFrameOffset > 0))
			{
				actorAnimate(con->rhythm.actor, CON_CHICK_WALK, TRUE, FALSE, 500, 0, 1024);
				con->tweedy.state = CON_TWEEDY_WORKING;
			}
			break;
		case CON_TWEEDY_WORKING:
			break;
		case CON_TWEEDY_STOP_WORKING:
			conTweedyChangeTool();
			break;
		case CON_TWEEDY_SUSPICIOUS:

			if(con->tweedy.currentTool == CON_SAWER)
				actorAnimate(con->tweedy.actor, CON_MRTWEEDY_SAW_HUH, FALSE, FALSE, 400, 0, 900);
			else if(con->tweedy.currentTool == CON_HAMMER)
				actorAnimate(con->tweedy.actor, CON_MRTWEEDY_HAMMER_HUH, FALSE, FALSE, 400, 0, 900);
			else if(con->tweedy.currentTool == CON_SPANNER)
				actorAnimate(con->tweedy.actor, CON_MRTWEEDY_SPANNER_HUH, FALSE, FALSE, 400, 0, 900);

			actorAnimate(con->rhythm.actor, CON_CHICK_HIDE, TRUE, FALSE, 500, 0, 1024);


			con->tweedy.state = CON_TWEEDY_IDLE;
			con->frameCount = 1;

			
			break;

		case CON_TWEEDY_ENDING:


			break;

	}
}

// alot of stuff to do - take it out of update
//-----------------------------------------------------------------------------------------------------------------------
void conTweedyChangeTool()
{

	// put down animation
	switch(con->tweedy.currentTool)
	{
		case CON_SAWER:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_SAW_PUTDOWN, FALSE, FALSE, 400, 0, 300);
			break;
		case CON_SPANNER:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_SPANNER_PUTDOWN, FALSE, FALSE, 400, 0, 300);
			break;
		case CON_HAMMER:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_HAMMER_PUTDOWN, FALSE, FALSE, 400, 0, 300);
			break;
	}

//	DB("cr = %d\n", con->rhythm.currentRhythm);

	// queue idle animation
	switch(con->rhythm.currentRhythm)
	{
		case 0:
		case 6:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_SCRATCH, FALSE, TRUE, 200, 0, 0);
			break;

		case 1:
		case 5:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE, FALSE, TRUE, 200, 0, 0);
			break;

		case 7:
		case 2:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_SCRATCH_HEAD, FALSE, TRUE, 200, 0, 0);
			break;

		case 3:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_BREATHE, FALSE, TRUE, 200, 0, 0);
			break;

		case 8:
		case 4:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_SIGH, FALSE, TRUE, 200, 0, 0);
			break;

		case 9:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_IDLE_SPECIAL, FALSE, TRUE, 200, 0, 0);
			break;

		case 10:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_OI_BUGGERS, FALSE, TRUE, 200, 0, 900);
			con->tweedy.state = CON_TWEEDY_ENDING;
			con->gameState = CON_GAMESTATE_ENDING;
			con->rhythm.state = CON_RHYTHM_STATE_OFF;
			return;
			break;

		default:
			DB("no idle for rhythm!\n");
	}

	// choose next tool
	//con->tweedy.currentTool = random(3);

	con->tweedy.currentTool = whichTool[con->rhythm.currentRhythm];




	switch(con->tweedy.currentTool)
	{
		case CON_SAWER:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_GET_SAW, FALSE, TRUE, 400, 0, 0);
			break;
		case CON_SPANNER:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_GET_SPANNER, FALSE, TRUE, 400, 0, 0);
			break;
		case CON_HAMMER:
			actorAnimate(con->tweedy.actor, CON_MRTWEEDY_GET_HAMMER, FALSE, TRUE, 400, 0, 0);
			break;
	}
	con->tweedy.state = CON_TWEEDY_IDLE;
///
	con->rhythm.posInBar = 0;
	con->rhythm.posOnWood = 0;

}



#define HAM1	1
#define HAM2	1
#define HAM3	1
#define HAM4    256
#define HAM5	0
#define HAM6	5


#define CON_HIT_PITCH  2800

#define CON_HIT_DELTA  400



//-----------------------------------------------------------------------------------------------------------------------
// add tools later
void conPlaySound(short tweedy, short button)
{
	int sample, pitch, res;

	if(tweedy)
	{
		switch(button-1)
		{
			case CON_SQUARE:
				if(con->tweedy.currentTool == CON_SAWER)
					sample = SFX_CONSTRUCT_SAW1;
				else if(con->tweedy.currentTool == CON_HAMMER)
					sample = SFX_CONSTRUCT_HAMMER1;
				else 
					sample = SFX_CONSTRUCT_SPANNER1;
				break;

			case CON_CROSS:
				if(con->tweedy.currentTool == CON_SAWER)
					sample = SFX_CONSTRUCT_SAW2;
				else if(con->tweedy.currentTool == CON_HAMMER)
					sample = SFX_CONSTRUCT_HAMMER2;
				else 
					sample = SFX_CONSTRUCT_SPANNER2;
				break;

			case CON_CIRCLE:
				if(con->tweedy.currentTool == CON_SAWER)
					sample = SFX_CONSTRUCT_SAW3;
				else if(con->tweedy.currentTool == CON_HAMMER)
					sample = SFX_CONSTRUCT_HAMMER3;
				else 
					sample = SFX_CONSTRUCT_SPANNER2;
				break;

			default:
				DB("illegal sound in conPlaySound\n");
				return;
		}
	}
	else
	{
		switch(button-1)
		{
			case CON_SQUARE:
				if(con->activeTool == CON_SAWER)
					sample = SFX_CONSTRUCT_SAW1;
				else if(con->activeTool == CON_HAMMER)
					sample = SFX_CONSTRUCT_HAMMER1;
				else 
					sample = SFX_CONSTRUCT_SPANNER1;
				break;

			case CON_CROSS:
				if(con->activeTool == CON_SAWER)
					sample = SFX_CONSTRUCT_SAW2;
				else if(con->activeTool == CON_HAMMER)
					sample = SFX_CONSTRUCT_HAMMER2;
				else 
					sample = SFX_CONSTRUCT_SPANNER2;
				break;

			case CON_CIRCLE:
				if(con->activeTool == CON_SAWER)
					sample = SFX_CONSTRUCT_SAW3;
				else if(con->activeTool == CON_HAMMER)
					sample = SFX_CONSTRUCT_HAMMER3;
				else 
					sample = SFX_CONSTRUCT_SPANNER3;//2
				break;

			default:
				DB("illegal sound in conPlaySound\n");
				return;

		}
		switch(con->activeTool)
		{


			case CON_SAWER:
				dsEvent_Add(0, 0, 1, 140, 0, 12, FALSE);
				break;
			case CON_HAMMER:
				dsEvent_Add(HAM1, HAM2, HAM3, HAM4, HAM5, HAM6, FALSE);
				break;
			case CON_SPANNER:
				dsEvent_Add(1, 1, 1, 112, 0, 16, FALSE);
				break;
		}
	}

	res = soundPlaySample(con->pSamples[sample], 0xffff, 0);

	

	//DB("res = %d\n", res);
}

//-----------------------------------------------------------------------------------------------------------------------
void conUpdateTools()
{
	int i;

	/*
	CON_BREATH,
	CON_TAP_FOOT,
	CON_LOOKAROUND,
	CON_GOTO_WORK,
	CON_WORK,
	CON_STOP_WORK,
	*/

	for(i=0; i< CON_NUM_TOOLS; i++)
	{
		switch(con->tools[i].state)
		{
			case CON_TOOL_IDLE:

//				if((random(100) == 5) && (con->tools[i].actor->animation.animData[0].segment == CON_BREATH))
//				{
//					actorAnimate(con->tools[i].actor,CON_LOOKAROUND, FALSE, FALSE, 300, 0, 900);
//					actorAnimate(con->tools[i].actor,CON_TAP_FOOT, FALSE, TRUE, 300, 0, 0);
//					actorAnimate(con->tools[i].actor,CON_BREATH, TRUE, TRUE, 300, 0, 0);
//				}
				break;

			case CON_TOOL_PREPARE:
				actorAnimate(con->tools[i].actor,CON_LOOKAROUND, FALSE, FALSE, 300, 0, 900);
				actorAnimate(con->tools[i].actor,CON_TAP_FOOT, FALSE, TRUE, 300, 0, 0);
				actorAnimate(con->tools[i].actor,CON_GOTO_WORK, FALSE, TRUE, 300, 0, 900);
				actorAnimate(con->tools[i].actor, CON_READY, TRUE, TRUE, 300, 0, 0);

				
//				if(con->tools[0].state == CON_TOOL_HITTING)
//					con->tools[0].state = CON_TOOL_STOPWORK;
//				if(con->tools[1].state == CON_TOOL_HITTING)
//					con->tools[1].state = CON_TOOL_STOPWORK;
//				if(con->tools[2].state == CON_TOOL_HITTING)
//					con->tools[2].state = CON_TOOL_STOPWORK;

				//debug stuff
				myactor = con->tools[i].actor;

				con->tools[i].state = CON_TOOL_HITTING;
				con->activeTool = i;
				break;

			case CON_TOOL_HITTING:
				break;

			case CON_TOOL_STOPWORK:
				actorAnimate(con->tools[i].actor,CON_STOP_WORK, FALSE, FALSE, 300, 0, 900);
				actorAnimate(con->tools[i].actor,CON_BREATH, TRUE, TRUE, 300, 0, 0);
				con->tools[i].state = CON_TOOL_IDLE;
				break;

		}
	}
}



//-----------------------------------------------------------------------------------------------------------------------
#define CON_CAM_MIN_SPEED  100
#define CON_CAM_MAX_SPEED  300

#define CON_CAM_NORMAL_MOVEMENT  1600

void conUpdateCamera()
{
	VECTOR v, v2;
	int dist, tempInt, height;

	switch(con->cam.state)
	{
		case CON_CAMSTATE_ARRIVED:
			   
			//for debug really

#ifdef DEBUG
//			if((pReadPad->digital[0] & PAD_R1) || (pReadPad->digital[0] & PAD_R2))
//				 return;
#endif

			if((pReadPad->analogXS[0] < -2000) ||(pReadPad->debounce[0] & PAD_LEFT))
			{
				con->cam.targetTool = (con->cam.targetTool == CON_NUM_TOOLS-1) ? 0:con->cam.targetTool+1;
				con->whoosh = 1;
			}
			else if((pReadPad->analogXS[0] > 2000)||(pReadPad->debounce[0] & PAD_RIGHT))
			{
				con->cam.targetTool = (con->cam.targetTool == 0) ? CON_NUM_TOOLS-1 : con->cam.targetTool-1;
				con->whoosh = 1;
			}
			else
			{
				break;
			}

			//DB("last  angle = %d\n", conCamAngle[con->cam.lastTool]);
			//DB(" target angle = %d\n", conCamAngle[con->cam.targetTool]);

			con->tools[con->cam.lastTool].state = CON_TOOL_STOPWORK;
			con->cam.state = CON_CAMSTATE_MOVING;
			SUBVECTOR(&v, &conCamPos[con->cam.targetTool], &con->cam.pos);// &conCamPos[con->cam.lastTool]);
			con->cam.distBetweenCamPos = Magnitude(&v);
			break;

		case CON_CAMSTATE_MOVING:

			SUBVECTOR(&v, &conCamPos[con->cam.targetTool], &con->cam.pos);
			
			dist = Magnitude(&v);

			ASSERT(dist);

			if(dist > CON_CAM_MIN_SPEED)
			{
				tempInt	= dist * CON_CAM_NORMAL_MOVEMENT / 4096;

				if(tempInt < CON_CAM_MIN_SPEED)
					tempInt = CON_CAM_MIN_SPEED;

				if(tempInt > CON_CAM_MAX_SPEED)
					tempInt = CON_CAM_MAX_SPEED;

				SCALEVECTOR(&v, ((4096*tempInt)/dist));

				dist -=tempInt;
			}
			else
			{
				con->cam.state = CON_CAMSTATE_ARRIVED;
				con->cam.lastTool = con->cam.targetTool;

				con->tools[con->cam.targetTool].state = CON_TOOL_PREPARE;
				dist = 0;
				break;
			}

			ADDTOVECTOR(&con->cam.pos, &v);

			// Now try moving garib exact same fraction of distance? so they arrive at precisely the same time???
			con->cam.garibPos.vx = (conGaribPos[con->cam.lastTool].vx * dist)/con->cam.distBetweenCamPos + (conGaribPos[con->cam.targetTool].vx * (con->cam.distBetweenCamPos - dist)) / con->cam.distBetweenCamPos;
			con->cam.garibPos.vy = (conGaribPos[con->cam.lastTool].vy * dist)/con->cam.distBetweenCamPos + (conGaribPos[con->cam.targetTool].vy * (con->cam.distBetweenCamPos - dist)) / con->cam.distBetweenCamPos;
			con->cam.garibPos.vz = (conGaribPos[con->cam.lastTool].vz * dist)/con->cam.distBetweenCamPos + (conGaribPos[con->cam.targetTool].vz * (con->cam.distBetweenCamPos - dist)) / con->cam.distBetweenCamPos;


			// find desired garib angle
			tempInt = (conCamAngle[con->cam.lastTool] * dist)/con->cam.distBetweenCamPos + (conCamAngle[con->cam.targetTool] * (con->cam.distBetweenCamPos - dist)) / con->cam.distBetweenCamPos;

//			DB("ti = %d\n", tempInt);
				

			dist = Magnitude2D((con->cam.pos.vx - con->cam.garibPos.vx), (con->cam.pos.vz - con->cam.garibPos.vz));
			//height = fast_sqrt(con->cam.pos.vy - con->cam.garibPos.vy);

			height = (dist * 4096) / tempInt;
			
			//dist = dist/height;

			mycamera.vpx = con->cam.pos.vx;
			mycamera.vpy = con->cam.pos.vy;
			mycamera.vpz = con->cam.pos.vz;

			mycamera.vrx = con->cam.garibPos.vx;
			mycamera.vry = (con->cam.garibPos.vy + (2*(con->cam.pos.vy + height)))/3;
			mycamera.vrz = con->cam.garibPos.vz;

			break;

	}
}




//-----------------------------------------------------------------------------------------------------------------------
/*
void constructControl()
{

#ifdef DEBUG

	//db
	if(pReadPad->digital[0]&PAD_R1 || pReadPad->digital[0]&PAD_R2)
	{
//		constructDebugMoveCamera();
//		constructDebugMoveActor();
		return;
	}

#endif


}
*/


//-----------------------------------------------------------------------------------------------------------------------
void constructPrintDebugText()
{
	char strBuff[128];


#ifdef CON_VIEW_POS

	sprintf(strBuff, "actorPos: %d %d %d rot %d", (int)myactor->position.vx, (int)myactor->position.vy, (int)myactor->position.vz, (int)myactor->psiData.object->rotate.vy);
	fontPrint(font, -240, -120, strBuff, 128, 128, 0);

	sprintf(strBuff, "cam pos: %d  %d  %d", (int)mycamera.vpx, (int)mycamera.vpy, (int)mycamera.vpz);
	fontPrint(font, -240, -110, strBuff, 128, 128, 0);
	sprintf(strBuff, "garib  : %d %d %d", (int)mycamera.vrx, (int)mycamera.vry, (int)mycamera.vrz);
	fontPrint(font, -240, -100, strBuff, 128, 128, 0);

	sprintf(strBuff, "target:%d, last:%d, state:%d", con->cam.targetTool, con->cam.lastTool, con->cam.state);
	fontPrint(font, -240, -90, strBuff, 128, 128, 0);


#endif

#ifdef CON_VIEW_STATES

	sprintf(strBuff, "sawer state %d", con->tools[CON_SAWER].state);
	fontPrint(font, -240, -120, strBuff, 128, 128, 0);
	
	sprintf(strBuff, "hammer state %d", con->tools[CON_HAMMER].state);
	fontPrint(font, -240, -110, strBuff, 128, 128, 0);

	sprintf(strBuff, "spanner state %d", con->tools[CON_SPANNER].state);
	fontPrint(font, -240, -100, strBuff, 128, 128, 0);

	sprintf(strBuff, "tweedy state %d", con->tweedy.state);
	fontPrint(font, -240, -90, strBuff, 128, 128, 0);

	sprintf(strBuff, "rhythm state %d", con->rhythm.state);
	fontPrint(font, -240, -80, strBuff, 128, 128, 0);

	sprintf(strBuff, "game state %d", con->gameState);
	fontPrint(font, -240, -70, strBuff, 128, 128, 0);
	

#endif



}

//-----------------------------------------------------------------------------------------------------------------------
void conMoveCanAndGarib(VECTOR *v)
{

	mycamera.vpx += v->vx;
	mycamera.vpy += v->vy;
	mycamera.vpz += v->vz;
	            
	mycamera.vrx += v->vx;
	mycamera.vry += v->vy;
	mycamera.vrz += v->vz;
}


//-----------------------------------------------------------------------------------------------------------------------
/*
void constructDebugMoveCamera()
{
	VECTOR v1, v2, v;
	


	if(pReadPad->digital[0] & PAD_R1)
	{
		v1.vx = mycamera.vpx;
		v1.vy = mycamera.vpy;
		v1.vz = mycamera.vpz;

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


		if(pReadPad->digital[0] & PAD_UP)
		{
			SUBVECTOR(&v, &v2, &v1);
			SCALEVECTOR(&v, 40);

			conMoveCanAndGarib(&v);
		}

		if(pReadPad->digital[0] & PAD_DOWN)
		{
			SUBVECTOR(&v, &v2, &v1);
			SCALEVECTOR(&v, -80);

			conMoveCanAndGarib(&v);
		}

		if(pReadPad->digital[0] & PAD_LEFT)
		{
			SUBVECTOR(&v, &v2, &v1);
			RotateVector2D(&v, &v, -16);

			ADDTOVECTOR(&v, &v1);
			
			mycamera.vrx = v.vx;
			mycamera.vry = v.vy;
			mycamera.vrz = v.vz;
		}

		if(pReadPad->digital[0] & PAD_RIGHT)
		{
			SUBVECTOR(&v, &v2, &v1);
			RotateVector2D(&v, &v, 16);

			ADDTOVECTOR(&v, &v1);
			
			mycamera.vrx = v.vx;
			mycamera.vry = v.vy;
			mycamera.vrz = v.vz;
		}

		if(pReadPad->digital[0] & PAD_TRIANGLE)
		{
			mycamera.vpy -= 20;
			mycamera.vry -= 20;
		}

		if(pReadPad->digital[0] & PAD_SQUARE)
		{
			mycamera.vpy += 20;
			mycamera.vry += 20;
		}

		if(pReadPad->digital[0] & PAD_CIRCLE)
		{
			mycamera.vry -= 20;
		}

		if(pReadPad->digital[0] & PAD_CROSS)
		{
			mycamera.vry += 20;
		}

		if(con->cam.state == CON_CAMSTATE_ARRIVED)
		{
			//set conCamPos and conGaribPos here//

			conCamPos[con->cam.targetTool].vx = mycamera.vpx;
			conCamPos[con->cam.targetTool].vy = mycamera.vpy;
			conCamPos[con->cam.targetTool].vz = mycamera.vpz;

			conGaribPos[con->cam.targetTool].vx = mycamera.vrx;
			conGaribPos[con->cam.targetTool].vy = mycamera.vry;
			conGaribPos[con->cam.targetTool].vz = mycamera.vrz;

		}

	}

}
*/
//-----------------------------------------------------------------------------------------------------------------------
void constructDebugMoveActor()
{
/*
	if(!myactor)
		return;


	if(pReadPad->digital[0] & PAD_L1)
	{


		if(pReadPad->analogYS[0] < -100)
		{
			myactor->position.vz -= pReadPad->analogYS[0]/160;
		}

		if(pReadPad->analogYS[0] > 100)
		{
			myactor->position.vz -= pReadPad->analogYS[0]/160;
		}

		if(pReadPad->analogXS[0] > 100)
		{	
			myactor->position.vx += pReadPad->analogXS[0]/160;
		}

		if(pReadPad->analogXS[0] < -100)
		{	
			myactor->position.vx += pReadPad->analogXS[0]/160;
		}

		if(pReadPad->digital[0] & PAD_TRIANGLE)
		{
			myactor->position.vy -= 10;
		}
		
		if(pReadPad->digital[0] & PAD_SQUARE)
		{
			myactor->position.vy += 10;
		}

		if(pReadPad->digital[0] & PAD_CIRCLE)
		{
			myactor->psiData.object->rotate.vy += 30;
		}

		if(pReadPad->digital[0] & PAD_CROSS)
		{
			myactor->psiData.object->rotate.vy -= 30;
		}
	}
*/
}