/******************************************************************************************
	CRTEST PS   (c) 1999-2001 ISL

	options.c:			Options screen stuff
******************************************************************************************/

#include "global.h"
#include "main.h"
#include "menu.h"
#include "map_draw.h"
#include "bff_load.h"
#include "debris.h"
#include "lights.h"
#include "timer.h"
#include "maths.h"
#include "overlays.h"
#include "map_view.h"
#include "global.h"
#include <psitypes.h>
#include "options.h"
#include "gallery.h"
#include "scenics.h"
#include "overlays.h"
#include "pad.h"
#include "gametext.h"
#include "card.h"
#include "demo.h"
#include "loadsnd.h"
#include "inventory.h"
#include "puzzles.h"
#include "wings.h"
#include "sound.h"
#include "charactr.h"
#include "credits.h"
#include "map_play.h"
#include "seesaw.h"
#include "catapult.h"
#include "fireworks.h"
#include "engine.h"
#include "construct.h"
#include "egglaying.h"
#include <isltex.h>

void optionsControlMethodDraw(void);
void optionsControlMethodCycle(void);

//#define MAKE_BOMB_UNAVAILABLE

#define FRAMES 20;			// number of frames to move the camera between options
							// change this to slow down / speed up
int desprojection;
char medalsopening;
char medalsclosing;

int fowleranim;

gametimerType optionstimestore;
gametimerType *optionstime = &optionstimestore;

int options_returnlevel;			// ok, as soon as you come into the options screen from 

VECTOR fowlerposition;

PSIMODEL *bronzemodel = NULL;
PSIMODEL *silvermodel = NULL;
PSIMODEL *goldmodel = NULL;
PSIMODEL *fowlermodel = NULL;

ACTOR *bronzeactor;
ACTOR *silveractor;
ACTOR *goldactor;
ACTOR *fowleractor;

int options_language_changed;
int options_bomb_avail = 0;

//void optionsCheckForLevelsAvailable(void);		// There are only 13 levels available

// Defs for the FMV sequences... fill in later when we know what resolution / colour depth / frames they're gonna be
/*StrDataType game_vid_def =
{
	"\\TEST.STR;1",			//	char		*strName;				// Stream file name. 
	STR_MODE24,				//	short		mode;						// 24-Bit or 16-Bit streaming.
	STR_BORDERS_ON,			//	short		drawBorders;				// != 0 if borders on.
	320,					//	u_short		scrWidth;				// Screen res width.
	0,						//	u_short		x;							// X,Y position. 
	(256-VID_HEIGHT)/2,		//	u_short		y;
	320,					//	u_short		width;						// Stream width and height.
	VID_HEIGHT,				//	u_short		height;
	(1201-3),				//	u_long		endFrame;					// Last frame No.
	0,						//	u_long		vlcBufSize;					// Size of each VLC buffer (including header) - 0 means use max.
	127						//	u_short		volume;						// Left and Right ADPCM volume.
};*/






int anim_numbers[TOTAL_STATES][3] =		// arriving, at, leaving for each object
{
	{0,0,0},					// Bed

	{1,0,1},					// Clock

	{0,0,0},					// Medal Board

	{0,1,0},					// Radio

	{1,2,3},					// PSX

	{0,0,0},					// Mirror

	{0,0,0},					// Door

	{1,1,2},					// Camera

	{0,0,0},					// Pictures

	{1,2,3},					// Diary

	{0,2,1}						// Bomb
};

SCENIC *option_scenics[TOTAL_STATES];


// level numbers - levselopt.quitflag is set to one of these on quitting, for the level to start at
enum {O_NULL,
	O_ACT1,
	O_DOGCHASE,
	
	O_ACT2,
	O_SEESAW,
	O_FIREWORKS,
	O_CATAPULT,
	O_PIEMACHINE,
	
	O_ACT3,
	O_EGGLAYING,
	O_ENGINE,
	O_CONSTRUCTION,
	O_WINGMAKING,
	O_CRATE,
	O_NUM_LEVELS,
	O_EXITHUT,			// Just to exit the hut and be standing outside
	O_CREDITS};			// Exit the options and go to credits

// Heading text for the menus

int optiontextnumbers[]={
	TEXTSTR_OPTIONS_HEADING_LOADSAVE,			// 0	"LOAD / SAVE GAME"
	TEXTSTR_OPTIONS_HEADING_TIMES,				// 1	"BEST TIMES"
	TEXTSTR_OPTIONS_MENU_RATINGS,				// 2	"RATINGS"
	TEXTSTR_OPTIONS_HEADING_SOUND,				// 2	"SOUND"			
	TEXTSTR_OPTIONS_HEADING_CONTROLLER,			// 3	"CONTROLLER SETUP"	
	TEXTSTR_OPTIONS_HEADING_SCREEN,				// 4	"SCREEN ADJUST"
	TEXTSTR_OPTIONS_HEADING_EXIT,				// 5	"EXIT"		
	TEXTSTR_OPTIONS_HEADING_MOVIES,				// 6	"VIEW MOVIES",		
	TEXTSTR_OPTIONS_HEADING_LANGUAGE,			// 7	"LANGUAGE SELECT"
	TEXTSTR_OPTIONS_HEADING_GALLERY,			// 8	"VIEW PICTURE GALLERY
	TEXTSTR_OPTIONS_HEADING_CREDITS,			// 9	"CREDITS"
	TEXTSTR_OPTIONS_HEADING_LEVEL,				// 10	"LEVEL SELECT"	
	0,											// 11	" "		
	0,											// 12	" "				
	TEXTSTR_OPTIONS_HEADING_RATINGS,			// 13	"RATINGS"			
	TEXTSTR_OPTIONS_HEADING_TIMES,				// 15	"BEST TIMES"
	TEXTSTR_OPTIONS_HEADING_SAVE,				// 16	"SAVE GAME"		
	TEXTSTR_OPTIONS_HEADING_LOAD,				// 17	"LOAD GAME"
	TEXTSTR_OPTIONS_ACT1,						// 18	"Act 1"
	TEXTSTR_OPTIONS_ACT2,						// 19	"Act 2"
	TEXTSTR_OPTIONS_ACT3};						// 20	"Act 3"		

#define LANGUAGE_MAIN_NUM 0
unsigned short optionnumbers[]={
	SAVE_MAIN_NUM,
	TIMES_MAIN_NUM,
	RATINGS_MAIN_NUM,
	SOUND_MAIN_NUM-1,
	CONTROLLER_MAIN_NUM,
	SCREENSETUP_MAIN_NUM,
	EXIT_MAIN_NUM,
	MOVIES_MAIN_NUM,							// movies
	LANGUAGE_MAIN_NUM,
	GALLERY_MAIN_NUM,
	CREDITS_MAIN_NUM,
	LEVELSELECT_MAIN_NUM,
	0,	// opt main
	0,	// total states
	0,	// ratings
	0,	// times
	2,	// save_load - 2 (same as "save_main") is enough to cover the messages anyway
	2,	// load_load
	6	// control_method
};


	unsigned short musicposition;

	// Text for the Menus

	int languagetext[] =
	{
		TEXTSTR_OPTIONS_LANGUAGE_ENGLISH,
		TEXTSTR_OPTIONS_LANGUAGE_GERMAN,
		TEXTSTR_OPTIONS_LANGUAGE_FRENCH,
		TEXTSTR_OPTIONS_LANGUAGE_ITALIAN
	};

	int savetext[] =
	{
		TEXTSTR_OPTIONS_MENU_LOADGAME,	//	"Load game"
		TEXTSTR_OPTIONS_MENU_SAVEGAME	//	"Save game"
	};

	int soundtext[] =
	{

		TEXTSTR_OPTIONS_MENU_SFXVOLUME,			//"SFX volume:          "
		TEXTSTR_OPTIONS_MENU_SPEECHVOLUME,		//"Speech volume:          "
		TEXTSTR_OPTIONS_MENU_MUSICVOLUME,		//"Music volume:          "
		TEXTSTR_OPTIONS_MENU_STEREO,			//"Stereo:     "
	};

	int controllertext[] = 
	{
		TEXTSTR_OPTIONS_CONTROLLER_VIBRATION,
		TEXTSTR_OPTIONS_HEADING_CONTROL_METHOD
	};

int moviestext[NUM_MOVIES - SELECTABLE_MOVIE_BASE]=
{
	TEXTSTR_OPTIONS_MOVIE_NAME_1,
	TEXTSTR_OPTIONS_MOVIE_NAME_2, 
	TEXTSTR_OPTIONS_MOVIE_NAME_3,
	TEXTSTR_OPTIONS_MOVIE_NAME_4, 
	TEXTSTR_OPTIONS_MOVIE_NAME_5,
	TEXTSTR_OPTIONS_MOVIE_NAME_6, 
	TEXTSTR_OPTIONS_MOVIE_NAME_7,
	TEXTSTR_OPTIONS_MOVIE_NAME_8, 
	TEXTSTR_OPTIONS_MOVIE_NAME_9,
	TEXTSTR_OPTIONS_MOVIE_NAME_10, 
	TEXTSTR_OPTIONS_MOVIE_NAME_11,
	TEXTSTR_OPTIONS_MOVIE_NAME_12, 
	TEXTSTR_OPTIONS_MOVIE_NAME_13,
	TEXTSTR_OPTIONS_MOVIE_NAME_14,
	TEXTSTR_OPTIONS_MOVIE_NAME_15
};

int leveltext[] =				// _U means unavailable - u aint played it, so u dont get to see what its called
{
	// Heading Text
	TEXTSTR_OPTIONS_ACT1,					// "Act 1"
	TEXTSTR_OPTIONS_ACT2,					// "Act 2"
	TEXTSTR_OPTIONS_ACT3,					// "Act 3"

	// Act 1 Text
	TEXTSTR_OPTIONS_MENU_STARTACT1,			// "Begin Act 1"
	TEXTSTR_OPTIONS_MENU_ACT1BOSS,			// "Act 1 Boss: Dog Chase"
	TEXTSTR_OPTIONS_MENU_ACT1BOSS_U,		// "Act 1 Boss" (Unavailable)

	// Act 2 Text
	TEXTSTR_OPTIONS_MENU_STARTACT2,			// "Begin Act 2"
	TEXTSTR_OPTIONS_MENU_SEESAWGAME,		// "Seesaw Subgame"
	TEXTSTR_OPTIONS_MENU_SEESAWGAME_U,		// "Subgame 1
	TEXTSTR_OPTIONS_MENU_FIREWORKSGAME,		// "Fireworks Subgame"
	TEXTSTR_OPTIONS_MENU_FIREWORKSGAME_U,	// "Subgame 2"
	TEXTSTR_OPTIONS_MENU_CATAPULTGAME,		// "Catapult Subgame"
	TEXTSTR_OPTIONS_MENU_CATAPULTGAME_U,	// "Subgame 3"
	TEXTSTR_OPTIONS_MENU_ACT2BOSS,			// "Act 2 Boss: Pie Machine"
	TEXTSTR_OPTIONS_MENU_ACT2BOSS_U,		// "Act 2 Boss"

	// Act 3 Text
	TEXTSTR_OPTIONS_MENU_STARTACT3,			// "Begin Act 3"
	TEXTSTR_OPTIONS_MENU_EGGGAME,			// "Egg Laying Subgame"
	TEXTSTR_OPTIONS_MENU_EGGGAME_U,			// "Subgame 1"
	TEXTSTR_OPTIONS_MENU_ENGINEGAME,		// "Engine Subgame"
	TEXTSTR_OPTIONS_MENU_ENGINEGAME_U,		// "Subgame 2"
	TEXTSTR_OPTIONS_MENU_CONSTRUCTIONGAME,	// "Construction Subgame"
	TEXTSTR_OPTIONS_MENU_CONSTRUCTIONGAME_U, // "Subgame 3"
	TEXTSTR_OPTIONS_MENU_WINGSGAME,			// "Wing Making Subgame"
	TEXTSTR_OPTIONS_MENU_WINGSGAME_U,		// "Subgame 4"
	TEXTSTR_OPTIONS_MENU_ACT3BOSS,			// "Act 3 Boss: The Crate"
	TEXTSTR_OPTIONS_MENU_ACT3BOSS_U			// "Act 3 Boss"
};


#define MENUSPEED 40					// speed of menus opening / closing

int pad_delay;


enum {CAMERA_MOVING,
CAMERA_STATIC};

// Variables for the level select menu
struct {unsigned short currentstage;		// Act 1, 2 or 3
		unsigned short currentlevel;			// Sub-level number
		unsigned short quitflag;				// Set to whatever level / stage we're gonna go to when we leave the hut
} levselopt;
  
int currentmovie;
											
unsigned char camerastate;
unsigned char optionstate;
unsigned char lastoptionstate;
unsigned char textmoving;

// These three are for the growy/shrinky menu, used by the options and inter-level splash screens
unsigned char menuopening;
unsigned char menuclosing;
int menuwidth;


unsigned int optionTextRGB = 128;
int optionTextRGBAdd = -8;

// RFW - Moved to makefile & linkfile
//#include "cntrscreen.c"

TextureType *filmreel;
TextureType *optionarrows[4];
TextureType *shot;
TextureType *controllerspr;
TextureType *pictureframe;
TextureType *gallerythumbs[11];

int framestodo = 0;

OPTIONDATASTR optionData;
int current_option;
int current_suboption;
int current_subsuboption;

GsRVIEW2 prevcamera;
GsRVIEW2 nextcamera;
GsRVIEW2 currentcamera;
GsRVIEW2 optioncams[OPTIONS_MAIN];
GsRVIEW2 exitcam;
GsRVIEW2 camstep;

VECTOR medalpositions[6];

// SFX

SfxSampleType *clock_sam;
SfxSampleType *Bleep1;
SfxSampleType *Bleep2;
SfxSampleType *Bleep3;
SfxSampleType *Bleep4;
SfxSampleType *BleepSelect;
SfxSampleType *CaseOpens1;
SfxSampleType *Clik1;
SfxSampleType *Clik2;
SfxSampleType *Clik3;
SfxSampleType *Clik4;
SfxSampleType *LowBzzz1;
SfxSampleType *LowBzzz2;
SfxSampleType *LowBzzz3;
SfxSampleType *MenuBleep;
SfxSampleType *MenuBomb1;
SfxSampleType *MenuCloses1;
SfxSampleType *MenuOpen1;
SfxSampleType *MovieStart1;
SfxSampleType *RadioTune;


// Stuff for the animated texture to make Fowler's eyes blink

TextureType *Fowler_eyesdummy;
TextureType *Fowler_eyesanim[2];
TextureAnimType *Fowler_eyesblinking;
int Fowler_eyestimer;
int stickup, stickdown, stickright, stickleft;



void optionsDebouncedAnalogCycle(void)
{
	if(!stickleft)
	{
		if(pReadPad->analogXS[0]<-3172)
			stickleft=1;
	}
	else if(stickleft)
	{
		if(pReadPad->analogXS[0]>-1024)
			stickleft=0;
		else
			stickleft=2;
	}

	if(!stickright)
	{
		if(pReadPad->analogXS[0]>3172)
			stickright = 1;
	}
	else if(stickright)
	{
		if(pReadPad->analogXS[0]<1024)
			stickright=0;
		else
			stickright=2;
	}

	if(!stickup)
	{
		if(pReadPad->analogYS[0]<-3172)
			stickup=1;
	}
	else if(stickup)
	{
		if(pReadPad->analogYS[0]>-1024)
			stickup=0;
		else
			stickup=2;
	}

	if(!stickdown)
	{
		if(pReadPad->analogYS[0]>3172)
			stickdown=1;
	}
	else if(stickdown)
	{
		if(pReadPad->analogYS[0]<1024)
			stickdown=0;
		else
			stickdown=2;
	}
}



//----------------------------------------------------------------------------------
//	Function 	: void optionsScenicsInit(void)
//	Purpose 	: Hunt through the level, for the scenic objects that we need to animate
//	Parameters 	: None
//	Returns 	: None
//  Info		: They're defined in the EGG file as having tags 300,301,302... matching the "states"
//----------------------------------------------------------------------------------

void optionsScenicsInit(void)
{
	int i;
	DB("scenics init\n");

	for(i = 0; i < TOTAL_STATES; i++)
	{

		option_scenics[i] = scenicFind(i + 300);

// Woohoo! Random poker fixed. RFW 17 Jly 00
		if(i == 1)
		{
			DB("clock\n");
			scenicSetAnim(option_scenics[1],1,0);	// Set the clock so it stops wobbling about...
		}
		else if(i == current_option)
		{
			DB("option %d scenic 1\n",i);
			scenicSetAnim(option_scenics[i], anim_numbers[i][1], 0);
		}
		else
		{
			DB("option %d scenic 2\n",i);
			scenicSetAnim(option_scenics[i], anim_numbers[i][2], 0);
		}
	}
	DB("all done\n");
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsLoadData(void)
//	Purpose 	: Initialise variables, set starting positions etc
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

// Get the data loaded & set up
// (Called on the return from playing a vid)
void optionsLoadData()
{
	//========== Loading... =========
	loadsndLoadBank("A1_FOWLER");

  //	overlayLoadingBegin(1);
	

	mapviewLoadMap("A1_FOWLER");							// Load the map we're going to use

	// Load sound bank
	
	clock_sam = sfxFindSampleInAllBanks("alarmclock1");
	ASSERT(clock_sam);

	Bleep1 =sfxFindSampleInAllBanks("bleep1");
	ASSERT(Bleep1);

	Bleep2 =sfxFindSampleInAllBanks("bleep2");
	ASSERT(Bleep2);

	Bleep3 =sfxFindSampleInAllBanks("bleep3");
	ASSERT(Bleep3);

	Bleep4 =sfxFindSampleInAllBanks("bleep4");
	ASSERT(Bleep4);

	BleepSelect =sfxFindSampleInAllBanks("bleepselect");
	ASSERT(BleepSelect);

	CaseOpens1 =sfxFindSampleInAllBanks("caseopens1");
	ASSERT(CaseOpens1);

	Clik1 =sfxFindSampleInAllBanks("clik1");
	ASSERT(Clik1);

	Clik2 =sfxFindSampleInAllBanks("clik2");
	ASSERT(Clik2);

	Clik3 =sfxFindSampleInAllBanks("clik3");
	ASSERT(Clik3);

	Clik4 =sfxFindSampleInAllBanks("clik4");
	ASSERT(Clik4);

	LowBzzz1 =sfxFindSampleInAllBanks("lowbzzz1");
	ASSERT(LowBzzz1);

	LowBzzz2 =sfxFindSampleInAllBanks("lowbzzz2");
	ASSERT(LowBzzz2);

	LowBzzz3 =sfxFindSampleInAllBanks("lowbzzz3");
	ASSERT(LowBzzz3);

	MenuBleep =sfxFindSampleInAllBanks("menubleep");
	ASSERT(MenuBleep);

	MenuBomb1 =sfxFindSampleInAllBanks("menubomb1");
	ASSERT(MenuBomb1);

	MenuCloses1 =sfxFindSampleInAllBanks("menucloses1");
	ASSERT(MenuCloses1);

	MenuOpen1 =sfxFindSampleInAllBanks("menuopen1");
	ASSERT(MenuOpen1);

	MovieStart1 =sfxFindSampleInAllBanks("moviestart1");
	ASSERT(MovieStart1);

	RadioTune = sfxFindSampleInAllBanks("radiotune1");
	ASSERT(RadioTune);


	optionsScenicsInit();
  //	overlayLoadingEnd();
	
	// ========== All Loaded =========

	filmreel = textureFindInAllBanks("FILMREEL");
	ASSERT(filmreel);

	gallerythumbs[0] = textureFindInAllBanks("THUMB1");
	ASSERT(gallerythumbs[0]);

	gallerythumbs[1] = textureFindInAllBanks("THUMB2");
	ASSERT(gallerythumbs[1]);

	gallerythumbs[2] = textureFindInAllBanks("THUMB3");
	ASSERT(gallerythumbs[2]);

	gallerythumbs[3] = textureFindInAllBanks("THUMB4");
	ASSERT(gallerythumbs[3]);
	
	gallerythumbs[4] = textureFindInAllBanks("THUMB5");
	ASSERT(gallerythumbs[4]);

	gallerythumbs[5] = textureFindInAllBanks("THUMB6");
	ASSERT(gallerythumbs[5]);

	gallerythumbs[6] = textureFindInAllBanks("THUMB7");
	ASSERT(gallerythumbs[6]);

	gallerythumbs[7] = textureFindInAllBanks("THUMB8");
	ASSERT(gallerythumbs[7]);

	gallerythumbs[8] = textureFindInAllBanks("THUMB9");
	ASSERT(gallerythumbs[8]);

	gallerythumbs[9] = textureFindInAllBanks("THUMB10");
	ASSERT(gallerythumbs[9]);

	gallerythumbs[10] = textureFindInAllBanks("THUMB11");
	ASSERT(gallerythumbs[10]);

	pictureframe = textureFindInAllBanks("FRAME");
	ASSERT(pictureframe);

	optionarrows[0] = textureFindInAllBanks("RARROW");
	ASSERT(optionarrows[0]);

	optionarrows[2] = textureFindInAllBanks("UARROW");
	ASSERT(optionarrows[2]);

	optionarrows[3] = textureFindInAllBanks("DARROW");
	ASSERT(optionarrows[3]);

	shot=textureFindInAllBanks("CHICK");
	ASSERT(shot);

	controllerspr = textureFindInAllBanks("CONTROL");
	ASSERT(controllerspr);


	bronzemodel = BFF_IsModelLoaded("MEDALB");
	ASSERT(bronzemodel);
	bronzeactor = actorCreate(bronzemodel);
	ASSERT(bronzeactor);
	actorInitAnim(bronzeactor);										
	actorAnimate(bronzeactor, 0, 1, 0, 0, 1, 0);

	silvermodel = BFF_IsModelLoaded("MEDALS");
	ASSERT(bronzemodel);
	silveractor = actorCreate(silvermodel);
	ASSERT(silveractor);
	actorInitAnim(silveractor);										
	actorAnimate(silveractor, 0, 1, 0, 0, 1, 0);

	goldmodel = BFF_IsModelLoaded("MEDALG");
	ASSERT(goldmodel);
	goldactor = actorCreate(goldmodel);
	ASSERT(goldactor);
	actorInitAnim(goldactor);			
	actorAnimate(goldactor, 0, 1, 0, 0, 1, 0);

	fowlermodel = BFF_IsModelLoaded("FOWLER");
	ASSERT(fowlermodel);

	fowleractor = actorCreate(fowlermodel);
	ASSERT(fowleractor);
	
	fowleractor->psiData.object->rotate.vy = 1024;

	actorInitAnim(fowleractor);
	actorAnimate(fowleractor, 2, 0, 0, 512, 1, 0);

	// JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM 
	//
	// JIM : Fowlers position should be set to <1500, -340, 1550> for the Dreamcast, 
	// cuz otherwise he's melding with the wall...
	//
	// JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM JIM 
	fowleractor->position.vx = 1500;
	fowleractor->position.vy = -340;
	fowleractor->position.vz = 1550;

	medalpositions[0].vy=-520; 
	medalpositions[0].vx=1800; 
	medalpositions[0].vz=1380;
	
	medalpositions[1].vy=-420; 
	medalpositions[1].vx=1800; 
	medalpositions[1].vz=1380;
	
	medalpositions[2].vy=-320; 
	medalpositions[2].vx=1800; 
	medalpositions[2].vz=1380;

	medalpositions[3].vy=-520; 
	medalpositions[3].vx=1800; 
	medalpositions[3].vz=1150;
	
	medalpositions[4].vy=-420; 
	medalpositions[4].vx=1800; 
	medalpositions[4].vz=1150;
	
	medalpositions[5].vy=-320; 
	medalpositions[5].vx=1800; 
	medalpositions[5].vz=1150;

//	optionsDoTestData();

//	optionsCheckForLevelsAvailable();

	options_language_changed = 0;

	// Set up the texanim for Fowler's eyes

	Fowler_eyesanim[0] = textureFindInAllBanks("FOWLER_EYEOPEN");
	ASSERT(Fowler_eyesanim[0]);

	Fowler_eyesanim[1] = textureFindInAllBanks("FOWLER_EYECLOSED");
	ASSERT(Fowler_eyesanim[1]);

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

	Fowler_eyesblinking = textureCreateAnimation(Fowler_eyesdummy,Fowler_eyesanim,2);
	ASSERT(Fowler_eyesblinking);

	Fowler_eyestimer = 0;
}

void optionsStart(int mode)
{
	overlayLoadingBegin(1);

// top bits are where-from

	if(mode & OPTIONS_FROM_TITLE)
	{
		options_bomb_avail = 1;
	}
	else
	{
		options_bomb_avail = 0;
	}
	mode = mode & 0x7f;


// They're reset to default at bootup time if there's no memory card saved state
//	optionsResetAllToDefaults();
	exitcam.vpx =218;
	exitcam.vpy =-455;
	exitcam.vpz =-2206;
	exitcam.vrx =107;
	exitcam.vry =-455;
	exitcam.vrz =-6293;

	pad_delay = 0;
	levselopt.quitflag = 0;
	menuopening=0;
	menuclosing=0;
	menuwidth = 0;

	levselopt.currentlevel = levselopt.currentstage = 0;

	optioncams[0].vpx = 71;			// Bed
	optioncams[0].vpy = -859;
	optioncams[0].vpz = -406;
	optioncams[0].vrx = 99;
	optioncams[0].vry = 590;
	optioncams[0].vrz = 3423;

	optioncams[1].vpx = 580;		// Clock
	optioncams[1].vpy = -796;
	optioncams[1].vpz = 187;
	optioncams[1].vrx = 608;
	optioncams[1].vry = 653;
	optioncams[1].vrz = 4016;

	optioncams[2].vpx = 286;		// Medals Board
	optioncams[2].vpy = -412;
	optioncams[2].vpz = 1276;
	optioncams[2].vrx = 4380;
	optioncams[2].vry = -414;
	optioncams[2].vrz = 1276;

	optioncams[3].vpx = -508;		// Radio
	optioncams[3].vpy = -703;
	optioncams[3].vpz = 9;
	optioncams[3].vrx = 3227;
	optioncams[3].vry = 224;
	optioncams[3].vrz = 1394;

	optioncams[4].vpx = -41;		// PSX
	optioncams[4].vpy = -1111;
	optioncams[4].vpz = -365;
	optioncams[4].vrx = 3412;
	optioncams[4].vry = 1087;
	optioncams[4].vrz = -279;

	optioncams[5].vpx = 242;		// Mirror
	optioncams[5].vpy = -944;
	optioncams[5].vpz = -455;
	optioncams[5].vrx = 2907;
	optioncams[5].vry = 988;
	optioncams[5].vrz = -2889;

	optioncams[6].vpx = 232;		// Door
	optioncams[6].vpy = -440;
	optioncams[6].vpz = 656;
	optioncams[6].vrx = 232;
	optioncams[6].vry = -440;
	optioncams[6].vrz = -2751;

	optioncams[7].vpx = 35;			// Projector
	optioncams[7].vpy = -817;
	optioncams[7].vpz = -367;
	optioncams[7].vrx = -1682;
	optioncams[7].vry = 106;
	optioncams[7].vrz = -3969;

	optioncams[8].vpx = 486;		// Cape
	optioncams[8].vpy = -606;
	optioncams[8].vpz = -959;
	optioncams[8].vrx = -3553;
	optioncams[8].vry = -858;
	optioncams[8].vrz = -1596;

	optioncams[9].vpx = 710;		// Pictures
	optioncams[9].vpy = -1010;
	optioncams[9].vpz = -305;
	optioncams[9].vrx = -3229;
	optioncams[9].vry = 106;
	optioncams[9].vrz = -396;

	optioncams[10].vpx = 313;		// Diary (credits)
	optioncams[10].vpy = -909;
	optioncams[10].vpz = 192;
	optioncams[10].vrx = -3020;
	optioncams[10].vry = 1459;
	optioncams[10].vrz = 417;

	optioncams[11].vpx = 643;		// Bomb
	optioncams[11].vpy = -971;
	optioncams[11].vpz = -714;
	optioncams[11].vrx = -1754;
	optioncams[11].vry = -590;
	optioncams[11].vrz = 2584;
	
	switch(mode)
	{
		case OPTIONS_BOMB_START:
			current_option = LEVELSELECT_MAIN;
			camerastate = CAMERA_STATIC;
			optionstate = OPTIONS_MAIN;
			currentcamera = optioncams[current_option];

// "Show" demo should start with the bomb open & the menu onscreen
#ifdef GAME_SHOW_DEMO
			optionstate=current_option;
			current_suboption=0;
			if((optionstate!=EXIT_MAIN) && (optionstate!=RATINGS_MAIN) && (optionstate!=CREDITS_MAIN))
				menuopening=1;
#endif

			break;

		case OPTIONS_CINEMA_START:
			current_option = MOVIES_MAIN;
			camerastate = CAMERA_STATIC;
			optionstate = OPTIONS_MAIN;
			currentcamera = optioncams[current_option];
			break;

		case OPTIONS_DOOR_START:
			current_option = EXIT_MAIN;
			camerastate = CAMERA_STATIC;
			optionstate = OPTIONS_MAIN;
			currentcamera = optioncams[current_option];
			break;

		case OPTIONS_DIARY_START:
			current_option = CREDITS_MAIN;
			camerastate = CAMERA_STATIC;
			optionstate = OPTIONS_MAIN;
			currentcamera = optioncams[current_option];
			break;
		default:
		case OPTIONS_BED_START:
			current_option=SAVE_MAIN;
			camerastate = CAMERA_STATIC;
			optionstate = OPTIONS_MAIN;
			currentcamera=optioncams[current_option];
			break;
	}

	if(music_playing == TUNE_1_INTRO)	// If we've come from the front, and the intro's not over, keep it running
	{
		sound_XA_PauseForLoading();
	}
	else
	{
		sound_XA_Stop();
	}

	optionsLoadData();


// We'll hop off the intro, and into the briefing track
// (Largely because the briefing track isn't being used on the briefings due to the number of loads, and the
// possibility of XA speech)
	if(music_to_resume == TUNE_1_INTRO)
	{
		sound_XA_Resume(TUNE_1_INTRO);
		sound_XA_Queue(TUNE_2_BRIEFING);
	}
	else	// We came in from the outside...
	{
		sound_XA_Start(TUNE_2_BRIEFING);
	}

	// Setup the draw and cycle routines
	draw_routine = optionsDraw;
	cycle_routine = optionsCycle;
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsEnd(void)
//	Purpose 	: Free stuff and go back to the menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsFree(void)
{
	textureDestroyAnimation(Fowler_eyesblinking);

	actorFree(bronzeactor);
	actorFree(silveractor);
	actorFree(goldactor);
	actorFree(fowleractor);
	mapviewReleaseMap();

// If you changed the language in the options screen,
// do a quick realloc of the language data so the memory isn't fragged

	if(options_language_changed)
	{
		sound_XA_Stop();
	DB("Before realloc\n");
 //	memoryShow();
		gameTextDestroy();
		gameTextInit("SHELL\\GAMETEXT.TXT", TEXTSTR_MAX, LANG_FILE_NUMLANGS, gameTextLang);		// 4 is number of langs, gameTextLang is one we want
	DB("After realloc\n");
 //	memoryShow();
	}

}

void optionsEnd(void)
{
	optionsFree();
	menuStart();	//Eventually we'll appear outside Fowler's hut
}






//----------------------------------------------------------------------------------
//	Function 	: void optionsDrawOnly(void)
//	Purpose 	: Draw routine for drawing just the basic background
//	Parameters 	: None
//	Returns 	: None
//  Info		: For use with the centrescreen routine
//----------------------------------------------------------------------------------

void optionsDrawOnly(void)
{
	int textx;
	char *heading;

	GsSetProjection(800);
	mycamera=currentcamera;
	mapCamSetRefView2L(&mycamera);

	mapviewBasicMapDraw();

	optionsAlphaRectangle(-240, -101, 480, 13, 0, 0x202020);
	if(optiontextnumbers[current_option])
	{
		heading = fontUpper(TEXTSTR(optiontextnumbers[current_option]));
		fontPrintCentred(font, 0,-100, heading,128,128,128);
	}
	optionsAlphaRectangle(-200, -70, 400, (optionnumbers[current_option]*20)+10, 0, 0x202020);//0x001020);
}






//----------------------------------------------------------------------------------
//	Function 	: void optionsDraw(void)
//	Purpose 	: Main draw routine
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsDraw(void)
{
	int textx;
	int i;		

	// Blink Fowler's eyes...

	if(!Fowler_eyestimer)
	{
		if(utilRandomInt(100)>93)
		{
			textureSetAnimation(Fowler_eyesblinking,1);
			Fowler_eyestimer = 1;		// Hold the blink for two frames otherwise it looks kinda crap
		}
		else
		{
			textureSetAnimation(Fowler_eyesblinking,0);
		}
	}
	else
		Fowler_eyestimer--;

	if(optionstate!=RATINGS_MAIN)
		GsSetProjection(800);

	mycamera=currentcamera;
	mapCamSetRefView2L(&mycamera);

	actorMaintainAnimation(fowleractor);

//	int actorAnimate(ACTOR *pActor, int animNum, char loop, char queue, int actualSpeed, char skipendframe, int blend)

	if(current_option==RATINGS_MAIN)
	{

		if(actorNearEndOfAnimation(fowleractor, fowleractor->animation.animData[0].segment, 1))
		{	
			if(fowleractor->animation.animData[0].segment==0)		// If he's just finished 0
				actorAnimate(fowleractor, 1, 0, 0, 256, 0, 512);	// Go to 1
			else if(fowleractor->animation.animData[0].segment==1)
				actorAnimate(fowleractor,2,0,0,256,0,512);			// go to 2
			else if(fowleractor->animation.animData[0].segment==2)	
				actorAnimate(fowleractor,11,0,0,256,0,512);			// Go to 11;
			else 
				actorAnimate(fowleractor, 11,0,0,256,0,512);
		}
	}

	else
	{
		if(actorNearEndOfAnimation(fowleractor, fowleractor->animation.animData[0].segment, 1))
		{	

			if(utilRandomInt(10)<5)
				actorAnimate(fowleractor, 13, 0, 0, 256, 1, 512);
			else
				actorAnimate(fowleractor, utilRandomInt(5)+13, 0, 0, 256, 1, 512);
		}
	}


	actorDraw(fowleractor);
/*
	{
		POLY_F4 *si4;

		BEGINPRIM(si4, POLY_F4);
		si4->r0 =  0x11;
		si4->g0 = 0x11;
		si4->b0 = 0x33;

		si4->x0 = si4->x2 = -256;
		si4->x1 = si4->x3 = 256;

		si4->y0 = si4->y1 = -128;
		si4->y2 = si4->y3 = 128;

		setPolyF4(si4);
		ENDPRIM(si4, 1023, POLY_F4);
	}
  */

	// Draw the medals ----------------------------------------

	for(i=0;i<6;i++)
	{		
		switch(gameSaveData.medals_won[i])
		{

			case 1:		// Got a bronze
				bronzeactor->position.vy=medalpositions[i].vy; 
				bronzeactor->position.vx=medalpositions[i].vx; 
				bronzeactor->position.vz=medalpositions[i].vz;
				bronzeactor->psiData.object->rotate.vy = 1024;
				psiSetAmbient(1028,1028,1028);
				actorMaintainAnimation(bronzeactor);
				actorDraw(bronzeactor);

				break;

			case 2:		// Got a sliver (ar maybe even a silver)
				silveractor->position.vy=medalpositions[i].vy; 
				silveractor->position.vx=medalpositions[i].vx; 
				silveractor->position.vz=medalpositions[i].vz;
				silveractor->psiData.object->rotate.vy = 1024;
				psiSetAmbient(1028,1028,1028);
				actorMaintainAnimation(silveractor);
				actorDraw(silveractor);
				break;

			case 3:		// Got a gold
				goldactor->position.vy=medalpositions[i].vy; 
				goldactor->position.vx=medalpositions[i].vx; 
				goldactor->position.vz=medalpositions[i].vz;
				goldactor->psiData.object->rotate.vy = 1024;
				psiSetAmbient(1028,1028,1028);
				actorMaintainAnimation(goldactor);
				actorDraw(goldactor);
				break;
					
			default:	// No medals won at all.... Draw a medal outline ??
				break;
		}
		
		if((optionstate==RATINGS_MAIN) && (desprojection==1400))
		{	
			if(gameSaveData.medals_won[i]>0)
			{
				if(i==0)
					fontPrintCentred(font,-164,-46, TEXTSTR(TEXTSTR_OPTIONS_MENU_SEESAWGAME),128,128,128);
				else if(i==1)
					fontPrint(font,	-164,10, TEXTSTR(TEXTSTR_OPTIONS_MENU_FIREWORKSGAME),128,128,128);
				else if(i==2)
					fontPrint(font,	-164,66, TEXTSTR(TEXTSTR_OPTIONS_MENU_CATAPULTGAME),128,128,128);
				else if(i==3)
					fontPrint(font,	40,-46, TEXTSTR(TEXTSTR_OPTIONS_MENU_ENGINEGAME),128,128,128);
				else if(i==4)
					fontPrint(font,	10,10, TEXTSTR(TEXTSTR_OPTIONS_MENU_CONSTRUCTIONGAME),128,128,128);
				else if(i==5)
					fontPrint(font,	10,66, TEXTSTR(TEXTSTR_OPTIONS_MENU_WINGSGAME),128,128,128);
			}
		}
	}

	mapviewBasicMapDraw();

	optionsAlphaRectangle( -240, -101, 480, 16, 0, 0x202020);

// RFW - I've made this a general routine so that the inter-level splashes can call it easily
	if(camerastate==CAMERA_STATIC)
		optionsAlphaMainMenuDraw(-70,(optionnumbers[current_option]*20)+10, 0x202020);

/*
	if(camerastate==CAMERA_STATIC)
		optionsAlphaRectangle( -(menuwidth/2), -70, menuwidth, (optionnumbers[current_option]*20)+10, 0, 0x202020);
	
	if(menuopening)
	{
		if(menuwidth<400)	
			menuwidth+=MENUSPEED;
		else 
			menuopening=0;
	}
	
	else if(menuclosing)
	{
		if(menuwidth>0)
			menuwidth-=MENUSPEED;
		else
		{
			menuclosing=0;
			menuwidth=0;
		}
	}
*/
	// If we're still on one of the main menus (and not one of the sub-menus like sound test, load game etc)

	if(optionstate<TOTAL_STATES)
	{
		if(optiontextnumbers[current_option])
		{
			char *heading;
//			if((current_option==EXIT_MAIN)&&(options_returnlevel))

			if(current_option==EXIT_MAIN)
			{
				if(gamePlayData->tasks_done[TASK_A1_BRIEF_FMA])
				{
					heading = fontUpper(TEXTSTR(TEXTSTR_OPTIONS_HEADING_RETURN));
				}
				else
				{
					heading = fontUpper(TEXTSTR(TEXTSTR_OPTIONS_BEGIN_GAME));
				}
			}
			else
			{
				heading = fontUpper(TEXTSTR(optiontextnumbers[current_option]));
			}

			textx=fontExtentW(font, heading);
			fontPrint(font, -(textx/2),-100, heading,128,128,128);
		}

		// Draw the little help-text thingies at the bottom of the screen

		if(current_option==SCREENSETUP_MAIN)
		{
			char *str;
			int size;

			str = TEXTSTR(TEXTSTR_OPTIONS_CANCEL_ACCEPT);	//"@T Cancel     @X Accept"
			size = fontExtentW(font,str);
			fontPrint(font,-(size/2), BOTTOM_WINDOW_Y+10+(100-(menuwidth/4))/4,str,128,128,128);
			optionsAlphaRectangle( (-(size)/2)-4,BOTTOM_WINDOW_Y+ 5+(100-(menuwidth/4))/4, (size)+8,18, 0, 0x003000);


			str = TEXTSTR(TEXTSTR_OPTIONS_SELECT);	//"@X Select"
			size = fontExtentW(font,str);
			fontPrint(font,         -(size/2)   ,BOTTOM_WINDOW_Y+35-(100-(menuwidth/4))/4,str,128,128,128);
			optionsAlphaRectangle( (-(size)/2)-4,BOTTOM_WINDOW_Y+30-(100-(menuwidth/4))/4, (size)+8,18, 0, 0x003000);

			if((!menuclosing)||(!menuopening)) lastoptionstate=OPTIONS_MAIN;
		}
		// 		else if((current_option==SAVE_MAIN) ||(current_option==LANGUAGE_MAIN) || (current_option==MOVIES_MAIN) ||(current_option==CONTROL_METHOD) ||(current_option==GALLERY_MAIN))
		else if((current_option==SAVE_MAIN) || (current_option==MOVIES_MAIN) ||(current_option==CONTROL_METHOD) ||(current_option==GALLERY_MAIN))
		{
			char *str;
			int size;

			str = TEXTSTR(TEXTSTR_OPTIONS_SELECT_CLOSE);	//"@X Select     @T Close menu"
			size = fontExtentW(font,str);
			fontPrint(font,         -(size/2)   ,BOTTOM_WINDOW_Y+10+(100-(menuwidth/4))/4,str,128,128,128);
			optionsAlphaRectangle( (-(size)/2)-4,BOTTOM_WINDOW_Y+ 5+(100-(menuwidth/4))/4, (size)+8,18, 0, 0x003000);

			str = TEXTSTR(TEXTSTR_OPTIONS_SELECT);	//"@X Select"
			size = fontExtentW(font,str);
			fontPrint(font,         -(size/2),   BOTTOM_WINDOW_Y+35-(100-(menuwidth/4))/4,str,128,128,128);
			optionsAlphaRectangle( (-(size)/2)-4,BOTTOM_WINDOW_Y+30-(100-(menuwidth/4))/4, (size)+8,18, 0, 0x003000);

			if((!menuclosing)||(!menuopening)) lastoptionstate=OPTIONS_MAIN;
		}
		else if(current_option==RATINGS_MAIN)
		{	
			char *str;
			int size;
			str = TEXTSTR(TEXTSTR_OPTIONS_BACK);		// "@T Back"
			size = fontExtentW(font,str);

			if(desprojection>840)
			{
				fontPrint(font,-(size)/2,   BOTTOM_WINDOW_Y+31-((desprojection-800)/14),str,128,128,128);
				optionsAlphaRectangle( -60, BOTTOM_WINDOW_Y+26-((desprojection-800)/14), 120, 18, 0, 0x003000);
			}
		}

		else if(current_option!=EXIT_MAIN)
		{
			char *str;
			int size;
			str = TEXTSTR(TEXTSTR_OPTIONS_CLOSE_MENU);		// "@T Close menu"
			size = fontExtentW(font,str);

			fontPrint(font,-(size)/2,    BOTTOM_WINDOW_Y+10+(100-(menuwidth/4))/4,str,128,128,128);
			optionsAlphaRectangle( -100, BOTTOM_WINDOW_Y+ 5+(100-(menuwidth/4))/4, 200, 18, 0, 0x003000);

			str = TEXTSTR(TEXTSTR_OPTIONS_SELECT);	//"@X Select"
			size = fontExtentW(font,str);
			fontPrint(         font,-(size/2)   ,BOTTOM_WINDOW_Y+35-(100-(menuwidth/4))/4,str,128,128,128);
			optionsAlphaRectangle( (-(size)/2)-4,BOTTOM_WINDOW_Y+30-(100-(menuwidth/4))/4, (size)+8,18, 0, 0x003000);
		}
		else
		{
			char *str;
			int size;

			str = TEXTSTR(TEXTSTR_OPTIONS_SELECT);	//"@X Select"
			size = fontExtentW(font,str);
			fontPrint(font,         -(size/2)   ,BOTTOM_WINDOW_Y+35-(100-(menuwidth/4))/4,str,128,128,128);
			optionsAlphaRectangle( (-(size)/2)-4,BOTTOM_WINDOW_Y+30-(100-(menuwidth/4))/4, (size)+8,18, 0, 0x003000);
		}

		if((!menuopening)&&(!menuclosing))
		{
			if(optionstate==OPTIONS_MAIN)
			{
				overlaySpriteFlipped(optionarrows[0], -232, -100, 0, ((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)));
				overlaySprite(       optionarrows[0],  215, -100, 0, ((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)));
			}

			else
			{
				switch(current_option)
				{
					case SAVE_MAIN:
						optionsDrawList(savetext, 0,SAVE_MAIN_NUM, 0,0);
						break;
					case TIMES_MAIN:
						optionsDrawBestTimes();
						break;
					case SOUND_MAIN:
						optionsDrawList(soundtext, 0, SOUND_MAIN_NUM-1, 50,1);
						optionsDrawSoundOptions();
						break;
					case CONTROLLER_MAIN:
						optionsDrawControllerOptions();
						break;
					case SCREENSETUP_MAIN:
						centreScreenStart();
						break;
//					case LANGUAGE_MAIN:
//						optionsDrawList(languagetext, 0, LANGUAGE_MAIN_NUM, 0, 0);
						break;
					case MOVIES_MAIN:
						optionsMoviesDraw();
						break;
					case GALLERY_MAIN:
						optionsGalleryDraw();
						break;
					case LEVELSELECT_MAIN:
						optionsDrawLevelSelect();
					default: 
						break;
				}
			}
		}
	}


	else if(optionstate>TOTAL_STATES)		// we're on one of the sub-menus
	{
		switch(optionstate)
		{
			case SAVE_LOAD:					
				break;
			case LOAD_LOAD:					
				break;
			case CONTROL_METHOD:
				optionsControlMethodDraw();
				break;
			default:
				break;
		}
	}
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsCycle(void)
//	Purpose 	: Main Cycle routine
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------
void optionsPhaseMenuRGB()
{
	optionTextRGB+=optionTextRGBAdd;
	if((optionTextRGB>127)||(optionTextRGB<72))
		optionTextRGBAdd=-optionTextRGBAdd;
}

void optionsCycle(void)
{
	int i;
	int found;
	mapviewBasicMapCycle();
//	debugPrintf("return level is currently: %d\n",options_returnlevel);

	optionsPhaseMenuRGB();
	
	// if you open and close the menu very fast lots of times and then hit X,
	// it gets confused and draws the menu text without the background. This fixes it...
	if((optionstate!=OPTIONS_MAIN)&& (optionstate!=RATINGS_MAIN) && (!menuopening)&&(!menuclosing)) menuwidth = 400;

	if(optionstate==OPTIONS_MAIN)
	{
		if(camerastate==CAMERA_STATIC)
		{
			if(pReadPad->debounce[0] & PAD_CROSS)
			{
				soundPlaySample(MenuOpen1, 255, 1000);

				optionstate=current_option;
				current_suboption=0;
				if((optionstate!=EXIT_MAIN) && (optionstate!=RATINGS_MAIN) && (optionstate!=CREDITS_MAIN))
					menuopening=1;

				if(optionstate==RATINGS_MAIN)
				{
					desprojection = 800;
					medalsopening = 1;
				}

				if(optionstate==EXIT_MAIN)
				{
					prevcamera = currentcamera;
					nextcamera= exitcam;
	
					// work out a smooth transition (use 8-bit fixed point for more accuracy)
					camstep.vpx=((nextcamera.vpx-prevcamera.vpx)<<8)/40;
					camstep.vpy=((nextcamera.vpy-prevcamera.vpy)<<8)/40;
					camstep.vpz=((nextcamera.vpz-prevcamera.vpz)<<8)/40;
					camstep.vrx=((nextcamera.vrx-prevcamera.vrx)<<8)/40;
					camstep.vry=((nextcamera.vry-prevcamera.vry)<<8)/40;
					camstep.vrz=((nextcamera.vrz-prevcamera.vrz)<<8)/40;
					camerastate=CAMERA_MOVING;
					framestodo=40;
				}

				if(optionstate==CREDITS_MAIN)
				{
					levselopt.quitflag = O_CREDITS;
				}

				menuwidth=0;
			}
		}

		if (((pReadPad->debounce[0] & PAD_RIGHT) ||(pReadPad->analogXS[0]>3172)) &&(camerastate==CAMERA_STATIC))
		{
			if(!menuopening & !menuclosing)
			{
				soundPlaySample(Clik3,255,1000);

				if(option_scenics[current_option] !=NULL)		// Leaving anim for this object
					actorAnimate(option_scenics[current_option]->pActor, anim_numbers[current_option][2], 0, 0 , (1<<ANIMSHIFT), 0, 1024);

				prevcamera=currentcamera;
				current_option++;
				
#ifdef MAKE_BOMB_UNAVAILABLE
				if((!options_bomb_avail) && current_option == LEVELSELECT_MAIN)
					current_option++;
#endif

//#if PALMODE==0
				if(current_option == LANGUAGE_MAIN)
					current_option++;

				if (current_option == CONTROLLER_MAIN)
					current_option++;

//#endif


				if(current_option>OPTIONS_MAIN-1) 
					current_option=SAVE_MAIN;



				if(option_scenics[current_option] !=NULL)	// Arriving anim for this object
					actorAnimate(option_scenics[current_option]->pActor, anim_numbers[current_option][0], 0, 0 , (1<<ANIMSHIFT), 0, 1024);
			
				// Play the sounds
				switch(current_option)
				{
				case LEVELSELECT_MAIN:
					soundPlaySample(MenuBomb1,255,500);
					break;
				case TIMES_MAIN:
					soundPlaySample(clock_sam,255,1200);
					break;
				case CONTROLLER_MAIN:
					soundPlaySample(CaseOpens1,255,800);
					break;
				case MOVIES_MAIN:
					soundPlaySample(MovieStart1,255,1000);
					break;
				case SOUND_MAIN:
					soundPlaySample(RadioTune,255,1200);
					break;
				}

				nextcamera=optioncams[current_option];
			
				// work out a smooth transition (use 8-bit fixed point for more accuracy)
				camstep.vpx=((nextcamera.vpx-prevcamera.vpx)<<8)/FRAMES;
				camstep.vpy=((nextcamera.vpy-prevcamera.vpy)<<8)/FRAMES;
				camstep.vpz=((nextcamera.vpz-prevcamera.vpz)<<8)/FRAMES;
				camstep.vrx=((nextcamera.vrx-prevcamera.vrx)<<8)/FRAMES;
				camstep.vry=((nextcamera.vry-prevcamera.vry)<<8)/FRAMES;
				camstep.vrz=((nextcamera.vrz-prevcamera.vrz)<<8)/FRAMES;
				camerastate=CAMERA_MOVING;
				framestodo=FRAMES;
			}
		}

		else if (((pReadPad->debounce[0] & PAD_LEFT) ||(pReadPad->analogXS[0]<-3172))&&(camerastate==CAMERA_STATIC))
		{
			if(!menuopening && !menuclosing)
			{	
				soundPlaySample(Clik3,255,1000);

				if(option_scenics[current_option] !=NULL)		// Leaving anim for this object
					actorAnimate(option_scenics[current_option]->pActor, anim_numbers[current_option][2], 0, 0 , (1<<ANIMSHIFT), 0, 1024);

				prevcamera=currentcamera;
				current_option--;

				if (current_option<SAVE_MAIN) 
					current_option=OPTIONS_MAIN-1;

#ifdef MAKE_BOMB_UNAVAILABLE
				if((!options_bomb_avail) && current_option == LEVELSELECT_MAIN)
					current_option--;
				if (current_option<SAVE_MAIN) 
					current_option=OPTIONS_MAIN-1;
#endif
//#if PALMODE==0
				if(current_option == LANGUAGE_MAIN)
					current_option--;

				if (current_option == CONTROLLER_MAIN)
					current_option--;
//#endif

				if(current_option == LEVELSELECT_MAIN)
					actorAnimate(option_scenics[current_option]->pActor, anim_numbers[current_option][0], 0, 0 , (2<<ANIMSHIFT), 0, 1024);
	
				else if(option_scenics[current_option] !=NULL)		// Arriving anim for this object
					actorAnimate(option_scenics[current_option]->pActor, anim_numbers[current_option][0], 0, 0 , (1<<ANIMSHIFT), 0, 1024);

				// Play the sounds
				switch(current_option)
				{
				case LEVELSELECT_MAIN:
					soundPlaySample(MenuBomb1,255,500);
					break;
				case TIMES_MAIN:
					soundPlaySample(clock_sam,255,1200);
					break;
				case CONTROLLER_MAIN:
					soundPlaySample(CaseOpens1,255,800);
					break;
				case MOVIES_MAIN:
					soundPlaySample(MovieStart1,255,1000);
					break;
				case SOUND_MAIN:
					soundPlaySample(RadioTune,255,800);
					break;
				}
				
				nextcamera=optioncams[current_option];

				// work out a smooth transition (use 8-bit fixed point for more accuracy)
				camstep.vpx=((nextcamera.vpx-prevcamera.vpx)<<8)/FRAMES;
				camstep.vpy=((nextcamera.vpy-prevcamera.vpy)<<8)/FRAMES;
				camstep.vpz=((nextcamera.vpz-prevcamera.vpz)<<8)/FRAMES;
				camstep.vrx=((nextcamera.vrx-prevcamera.vrx)<<8)/FRAMES;
				camstep.vry=((nextcamera.vry-prevcamera.vry)<<8)/FRAMES;
				camstep.vrz=((nextcamera.vrz-prevcamera.vrz)<<8)/FRAMES;
				camerastate=CAMERA_MOVING;
				framestodo=FRAMES;
			}
		}
	}

	else if((optionstate<TOTAL_STATES)&& (optionstate!=RATINGS_MAIN) && (optionstate!=GALLERY_MAIN))
	{
		if(pReadPad->debounce[0] & PAD_TRIANGLE)
		{
			soundPlaySample(MenuCloses1,255,1000);
			menuclosing=1;
			menuwidth=400;

			optionstate = OPTIONS_MAIN;
		}
		
		if ((pReadPad->debounce[0] & PAD_UP) ||(pReadPad->analogYS[0]<-2048))
		{
			current_suboption--;
		}
		
		else if((pReadPad->debounce[0] & PAD_DOWN)||(pReadPad->analogYS[0]>2048))
		{
			current_suboption++;
		}
		
		if(current_suboption<0)
		{
			current_suboption=optionnumbers[current_option]-1;
		}
		
		else if (current_suboption>optionnumbers[current_option]-1)
		{
			current_suboption=0;
		}

		switch (current_option)
		{
		case SAVE_MAIN:
			optionsSaveCycle();
			break;
		case SOUND_MAIN:
			optionsSoundCycle();
			break;
		case CONTROLLER_MAIN:
			optionsControllerCycle();
			break;
//		case LANGUAGE_MAIN:
//			optionsLangselectCycle();
			break;
		case LEVELSELECT_MAIN:
			optionsLevelSelectCycle();
			break;
		case RATINGS_MAIN:
			optionsRatingsCycle();
			break;
		case MOVIES_MAIN:
			optionsMoviesCycle();
			break;
/*		case SCREENSETUP_MAIN :
			centreScreenCycle();
			break; */

		default:
			break;
		}
	}
	
	else if(optionstate==RATINGS_MAIN)
		optionsRatingsCycle();
	else if(optionstate==GALLERY_MAIN)
		optionsGalleryCycle();

	// if we're on one of the sub-menus
	if(optionstate>TOTAL_STATES)
	{
		switch(optionstate)
		{
			case CONTROL_METHOD:
				optionsControlMethodCycle();
				break;
			default:
				break;
		}
	}

	optionsSetCamera();

	if(levselopt.quitflag>0)
	{
		optionsEndToGame();
	}
}


void optionsEndToGame(void)
{
	optionsFree();

	gameCalledFrom = GAMECALLEDFROM_REPLAY;

	switch(levselopt.quitflag)
	{

		case O_EXITHUT:		// Standing outside the hut

			gameCalledFrom = GAMECALLEDFROM_GAME;

//   Oops! If the pause menu's going to let you call here from anywhere, we need to ba able to return to wherever we
// came from.


// Okay. Figure out where we restart the game from, and go from there...
			if(!gameSaveData.levels_available[REPLAY_AVAILABLE_ACT2])
			{
				// We're on act1
				if(!gameSaveData.levels_available[REPLAY_AVAILABLE_ACT1BOSS])
				{
					if(!gamePlayData->tasks_done[TASK_A1_BRIEF_FMA])
					{
						levflowAct1FromOptions();
					}
					else
					{
						inventoryEnsureStreamBank(STREAMBANK_INVENTORYACT1);

// TBD  want to go to... "options_returnlevel". Oops, that's a number
						mapplayStart("A1_COOP1_N",1);
					}
				}
				else
				{
					levflowDogchaseStart();
				}
			}
			else if(!gameSaveData.levels_available[REPLAY_AVAILABLE_ACT3])
			{
				// We're on act2
				if(!gameSaveData.levels_available[REPLAY_AVAILABLE_ACT2BOSS])
				{
					if(!gamePlayData->tasks_done[TASK_A2_BRIEF_FMA])
					{
						levflowAct2FromOptions();
					}
					else
					{
						inventoryEnsureStreamBank(STREAMBANK_INVENTORYACT2);
						mapplayStart("A2_COOP1_D",1);
					}
				}
				else
				{
					levflowCogchaseStart();
				}
			}
			else
			{
				// We're on act3
				if(!gameSaveData.levels_available[REPLAY_AVAILABLE_ACT3BOSS])
				{
					if(!gamePlayData->tasks_done[TASK_A4_BRIEF_FMA])
					{
						levflowAct3FromOptions();
					}
					else
					{
						inventoryEnsureStreamBank(STREAMBANK_INVENTORYACT4);
						mapplayStart("A4_COOP1_N",1);
					}
				}
				else
				{
					// No invent streambank rqd
					levflowFlymachineStart();
				}
			}
			break;





		case O_ACT1:		// Start Act 1
			levflowAct1FromOptions();
			break;

		case O_DOGCHASE:	// Start Dog Chase
			levflowDogchaseStart();
			break;

		case O_ACT2:		// Start Act 2
			levflowAct2FromOptions();
			break;

		case O_SEESAW:		// Start Seesaw
			main_EnsureOverlay(ACT2_SUBGAME_OVERLAY);
			seesawStart();
			break;

		case O_FIREWORKS:	// Start Fireworks
			main_EnsureOverlay(ACT2_SUBGAME_OVERLAY);
			fireworksStart("A2_FIREWORKS");
			break;

		case O_CATAPULT:	// Start Catapult
			main_EnsureOverlay(ACT2_SUBGAME_OVERLAY);
			catapultStart("DAYTIME");
			break;

		case O_PIEMACHINE:	// Start Pie Machine
			levflowCogchaseStart();
			break;



		case O_ACT3:		// Start Act 3
			levflowAct3FromOptions();
			break;

		case O_EGGLAYING:	// Start egglaying
			main_EnsureOverlay(ACT4_SUBGAME_OVERLAY);
			elStart();
			break;

		case O_ENGINE:		// Start Enginegame
			main_EnsureOverlay(ACT4_SUBGAME_OVERLAY);
			engineStart();
			break;

		case O_CONSTRUCTION:	// Start construction game
			main_EnsureOverlay(ACT4_SUBGAME_OVERLAY);
			constructStart();
			break;

		case O_WINGMAKING:		// Start Wing making game
			main_EnsureOverlay(ACT4_SUBGAME_OVERLAY);
			wingStart();
			break;

		case O_CRATE:
			levflowFlymachineStart();
			break;

		case O_CREDITS:
			creditsStart();
			break;

		default:
			menuStart();
			break;
	}
}



//----------------------------------------------------------------------------------
//	Function 	: void optionsSetCamera(void)
//	Purpose 	: Move the camera along it's path - if it's reached where it's been going to, stop it
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsSetCamera(void)
{
	if(camerastate==CAMERA_MOVING)
	{
		currentcamera.vpx+=camstep.vpx>>8;
		currentcamera.vpy+=camstep.vpy>>8;
		currentcamera.vpz+=camstep.vpz>>8;
		currentcamera.vrx+=camstep.vrx>>8;
		currentcamera.vry+=camstep.vry>>8;
		currentcamera.vrz+=camstep.vrz>>8;
	
		framestodo--;
		if(!framestodo)
		{
			camerastate=CAMERA_STATIC;

			if(current_option==RATINGS_MAIN)
				actorAnimate(fowleractor, 0, 0, 0, 256, 1, 512);

			if((current_option==1) || (current_option==8))		// 1 & 8 need to loop
				actorAnimate(option_scenics[current_option]->pActor, anim_numbers[current_option][1], 1, 0 , (1<<ANIMSHIFT), 0, 1024);
			else if(current_option==11)	// 11 needs to blend slower
				actorAnimate(option_scenics[current_option]->pActor, anim_numbers[current_option][1], 0, 0 , (1<<ANIMSHIFT), 0, 256);
			else	// anything else...
				if(option_scenics[current_option] !=NULL)
				{
					debugPrintf("Animating scenic number %d\n",current_option);
					actorAnimate(option_scenics[current_option]->pActor, anim_numbers[current_option][1], 0, 0 , (1<<ANIMSHIFT), 0, 1024);
				}
			//if(option_scenics[current_option] !=NULL)
				//scenicSetAnim(option_scenics[current_option], anim_numbers[current_option][1], 0);

			// Set the camera to what it should be to stop accumulative errors
			currentcamera=optioncams[current_option];	

			if(nextcamera.vrz==exitcam.vrz)
				levselopt.quitflag = O_EXITHUT; 
		}
	}
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsAlphaRectangle(TextureType *spr, int x, int y, int w, int h, int depth, unsigned long colour)
//	Purpose 	: Draw a semi-transparent rectangle with a border
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsAlphaRectangle(int x, int y, int w, int h, int depth, unsigned long colour)
{	
	overlayAlphaBox(x, y, w, h, (unsigned char) (colour>>16) & 0xff, (unsigned char) (colour>>8) & 0xff, (unsigned char) (colour) & 0xff);

	if((w<1)||(h<13)) return;

	overlayLine(x,y,x+w,y,0x444444);			// top
	overlayLine(x+w,y,x+w,y+h,0x444444);		// right
	overlayLine(x,y+h,x+w,y+h,0x000000);		// bottom
	overlayLine(x,y,x,y+h,0x000000);			// left
}


void optionsAlphaMainMenuInit()
{
	menuopening=0;
	menuclosing=0;
	menuwidth = 0;
}


// RFW - I've made this a general routine so that the inter-level splashes can call it easily
// It's the growy / shrinky main menu
int optionsAlphaMainMenuDraw(int y, int h, int colour)
{
	if(menuwidth > 0)
	{
		optionsAlphaRectangle( -(menuwidth/2), -70, menuwidth, h, 0, colour);
	}

	if(menuopening)
	{
		if(menuwidth<400)	
			menuwidth+=MENUSPEED;
		else 
			menuopening=0;
	}
	else if(menuclosing)
	{
		if(menuwidth>0)
			menuwidth-=MENUSPEED;
		else
		{
			menuclosing=0;
			menuwidth=0;
		}
	}
	if(menuwidth >= 400)
		return 1;
	else
		return 0;
}



//----------------------------------------------------------------------------------
//	Function 	: void optionsDrawList(int *text_ids, unsigned short base_item, unsigned short num_items , int x, int align)
//	Purpose 	: Draw a semi-transparent rectangle with a border
//	Parameters 	: Pointer to start of text, number of strings to print, Align = 0 for centre, 1 for right-align
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsDrawList(int *text_ids, unsigned short base_item, unsigned short num_items , int x, int align)
{
	int i;				// counter
	int textx;			// text centrer
	char *str;

	for(i=0;i<num_items;i++)
	{
		str = TEXTSTR(text_ids[i+base_item]);
		switch(align)
		{
			case 1:
				textx = x - fontExtentW(font, str);
				break;
			case 0:
			default:
				textx = x - fontExtentW(font, str)/2;
				break;
		}

		if(i+base_item==current_suboption)
			fontPrint(font, textx,-60+((i+base_item)*20), str,optionTextRGB,optionTextRGB,optionTextRGB);
		else
			fontPrint(font, textx,-60+((i+base_item)*20), str,64,64,96);
	}
}






//----------------------------------------------------------------------------------
//	Function 	: void optionsHitOptions(int which)
//	Purpose 	: Make the options affect the hardware
//	Parameters 	: The option(s)
//	Returns 	: None
//  Info		: After we've loaded the options from a memory card
//				  we need to actually hit the hardware in the same way
//				  that the original options-setting code did
//----------------------------------------------------------------------------------

void optionsHitOptions(int which)
{
	if(which & OPTIONS_HIT_SCREEN_POS)
	{
		displayPage[0].dispenv.screen.x = displayPage[1].dispenv.screen.x = optionData.screen.offset_x;
		displayPage[0].dispenv.screen.y = displayPage[1].dispenv.screen.y = optionData.screen.offset_y;
	}
	if(which & OPTIONS_HIT_SHOCKENABLE)
	{
		pReadPad->shockEnable = optionData.control.vibration;
	}

	if(which & OPTIONS_HIT_SFX_VOL)
	{
		sfxSetGlobalVolume(optionData.sound.sfxvol);	// the sfxglobalvolume is 0...255
	}


//	if(which & OPTIONS_HIT_MASTER_VOL)
//	{
//		sfxSetGlobalVolume(optionData.sound.mastervol * 2);	// the sfxglobalvolume is 0...256
//	}

// tbd - The separate sfx/speech/music volumes aren't dealt with anywhere yet
// tbd - stereo (pick up in sound.c's 3d functions - always set the "pan" to straight ahead ?)
}






//----------------------------------------------------------------------------------
//	Function 	: void optionsDrawControllerOptions(void)
//	Purpose 	: Draw the controller options menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: The options available will change dependent on the type of controller connected
//----------------------------------------------------------------------------------

void optionsDrawControllerOptions(void)
{
	int textx;
	int i;

	if(pReadPad->present[0]==PADTYPE_NONE)
	{
		fontPrintCentred(font,0,80,TEXTSTR(TEXTSTR_OPTIONS_CONTROLLER_NO_PAD),128,128,128);
	}

	if(pReadPad->present[0]!=PADTYPE_DUALSHOCK)		// Grey em out if theres no dualshock
	{
		fontPrint(font,-74,-60, TEXTSTR(controllertext[0]),64,64,64);
		fontPrint(font, -133,-40, TEXTSTR(controllertext[1]),64,64,64);
		fontPrint(font,30,-60,TEXTSTR(TEXTSTR_OPTIONS_OFF),64,64,64);
	}
	
	else
	{	
		if(current_suboption==0)
		{
			fontPrint(font, -74, -60, TEXTSTR(controllertext[0]),optionTextRGB,optionTextRGB,optionTextRGB);
			fontPrint(font, -133, -40, TEXTSTR(controllertext[1]),64,64,96);
			
			if(pReadPad->shockEnable)//(optionData.control.vibration)
				fontPrint(font,30,-60,TEXTSTR(TEXTSTR_OPTIONS_ON),optionTextRGB,optionTextRGB,optionTextRGB);
			else
				fontPrint(font,30,-60,TEXTSTR(TEXTSTR_OPTIONS_OFF),optionTextRGB,optionTextRGB,optionTextRGB);
		}

		else
		{
			fontPrint(font, -133, -40, TEXTSTR(controllertext[1]),optionTextRGB,optionTextRGB,optionTextRGB);
			fontPrint(font, -74,-60, TEXTSTR(controllertext[0]),64,64,96);
			if(pReadPad->shockEnable)
				fontPrint(font,30,-60,TEXTSTR(TEXTSTR_OPTIONS_ON),64,64,96);
			else
				fontPrint(font,30,-60,TEXTSTR(TEXTSTR_OPTIONS_OFF),64,64,96);
		}
	}
}






//----------------------------------------------------------------------------------
//	Function 	: void optionsControllerCycle(void)
//	Purpose 	: Cycle routine for the controller menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsControllerCycle(void)
{
	if(pReadPad->debounce[0] & PAD_CROSS)
	{
		switch(current_suboption)
		{
			case 0:								// Enable / disable vibration
				if(pReadPad->shockEnable) pReadPad->shockEnable=0;
				else 
				{
					pReadPad->shockEnable = 1;
					pReadPad->currShock[0]=117;		// Test vibration
					pReadPad->shock[0]=1280;
					pReadPad->shockDiv[0]=128;
					pReadPad->buzzTime[0]=19;
				}
				optionData.control.vibration=pReadPad->shockEnable;
				break;
			case 1:
				optionstate = CONTROL_METHOD;
				current_option = CONTROL_METHOD;
				current_suboption = 0;
				pReadPad->debounce[0] = 0;
				break;
			default:
				break;
		}
	}
}


//----------------------------------------------------------------------------------
//	Function 	: void optionsSoundCycle(void)
//	Purpose 	: Cycle routine for the Sound menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsSoundCycle(void)
{
	if(pReadPad->debounce[0] & PAD_CROSS)
	{
		switch(current_suboption)
		{
			case 3:									// Switch from mono to stereo
				if(optionData.sound.stereo ==1)			// enable stereo by default
					optionData.sound.stereo=0;
				else
					optionData.sound.stereo=1;
				break;
			default:
				break;
		}
	}

	if((pReadPad->digital[0] & PAD_LEFT) ||(pReadPad->analogXS[0]<-2048))
	{
		soundPlaySample(Clik1,255,1000);
		switch(current_suboption)
		{
		case 0:
			if(optionData.sound.sfxvol>0)
				optionData.sound.sfxvol-=2;
			break;
		case 1:
			if(optionData.sound.speechvol>0)
				optionData.sound.speechvol-=2;
			break;
		case 2:
			if(optionData.sound.musicvol>0)
				optionData.sound.musicvol-=2;
			break;
		default:
			break;
		}
	}

	if((pReadPad->digital[0] & PAD_RIGHT) ||(pReadPad->analogXS[0]>2048))
	{
		soundPlaySample(Clik1,255,1000);

		switch(current_suboption)
		{
		case 0:
			if(optionData.sound.sfxvol<128)
				optionData.sound.sfxvol+=2;
			break;

		case 1:
			if(optionData.sound.speechvol<128)
				optionData.sound.speechvol+=2;
			break;

		case 2:
			if(optionData.sound.musicvol<128)
				optionData.sound.musicvol+=2;
			break;
		default:
			break;
		}
	}

	sound_XA_VolRefresh();

}






//----------------------------------------------------------------------------------
//	Function 	: void optionsResetAllToDefaults(void)
//	Purpose 	: Clear all of the game options to default values
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsResetAllToDefaults(void)
{
	if((pReadPad->present[0]==PADTYPE_DUALSHOCK)||(pReadPad->present[0]==PADTYPE_ANALOG))
										// if Dual shock or Analog pad available
		optionData.control.analog=1;	// enable analog by default

	else
		optionData.control.analog=0;

	if(pReadPad->present[0]==PADTYPE_DUALSHOCK)
	{									// if Dual shock pad available
		optionData.control.vibration=1;	// enable vibration by default
	}
	else
	{
		optionData.control.vibration=0;
	}
	
	optionData.sound.stereo = 1;			// enable stereo by default
	optionData.sound.sfxvol = 64;			// the SFX volume
	optionData.sound.speechvol = 64;		// the speech volume
	optionData.sound.musicvol = 64;		// the music volume

#if PALMODE==1
	optionData.screen.offset_x = 2;
	optionData.screen.offset_y = 18;
#else
	optionData.screen.offset_x = 0;
	optionData.screen.offset_y = 3;
#endif

	optionsHitOptions(OPTIONS_HIT_ALL);
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsDrawSoundOptions(void)
//	Purpose 	: Draw routine for the sound menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsDrawSoundOptions(void)
{
	int i;
	
	if(current_suboption<3)
		optionsDrawBoxOutline(59, -58+(current_suboption*20),132,9,(optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB));//0xffffff);

	for(i=0;i<optionData.sound.musicvol;i+=6)
		overlayFilledRectangle( i+60, -17, 4, 8, 0x880000+(i<<1));

	for(i=0;i<optionData.sound.speechvol;i+=6)
		overlayFilledRectangle( i+60, -37, 4, 8, 0x880000+(i<<1));

	for(i=0;i<optionData.sound.sfxvol;i+=6)
		overlayFilledRectangle( i+60, -57, 4, 8, 0x880000+(i<<1));

/*	if(current_suboption!=3)
	{
		if(optionData.sound.stereo)
			fontPrint(font, 50 + 6,0, TEXTSTR(TEXTSTR_OPTIONS_ON),64,64,96);
		else
			fontPrint(font, 50 + 6,0, TEXTSTR(TEXTSTR_OPTIONS_OFF),64,64,96);
	}
	else
	{
		if(optionData.sound.stereo)
			fontPrint(font, 50 + 6,0, TEXTSTR(TEXTSTR_OPTIONS_ON),optionTextRGB,optionTextRGB,optionTextRGB);
		else
			fontPrint(font, 50 + 6,0, TEXTSTR(TEXTSTR_OPTIONS_OFF),optionTextRGB,optionTextRGB,optionTextRGB);
	} */
}




//----------------------------------------------------------------------------------
//	Function 	: void optionsDrawBoxOutline(int x, int y, int w, int h, unsigned int colour)
//	Purpose 	: Draw a box
//	Parameters 	: x,y,width,height,colour
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsDrawBoxOutline(int x, int y, int w, int h, unsigned int colour)
{
	overlayLine(x,y,x+w,y,colour);			// top
	overlayLine(x+w,y,x+w,y+h,colour);		// right
	overlayLine(x,y+h,x+w,y+h,colour);		// bottom
	overlayLine(x,y,x,y+h,colour);			// left
}






//----------------------------------------------------------------------------------
//	Function 	: void optionsDrawRatingsTimes(void)
//	Purpose 	: Draw routine for the Times sub-menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsDrawBestTimes(void)
{	int i;
//	for(i=0;i<N_TIMED_LEVELS;i++)
//		debugPrintf("L: %d   T: %d\n",i,gameSaveData.best_times[i]);

	// Act 1 total
	if(gameSaveData.best_times[TIME_ACT1]==INIT_ACT1_BEST)		// If we aint finished it yet...grey it out
	{
		fontPrint(font,-180, -60, TEXTSTR(TEXTSTR_OPTIONS_ACT1), 64,64,64);
		optionsFramesToTimer (gameSaveData.best_times[TIME_ACT1], optionstime);
		optionsDrawTime(optionstime, 70, -60, 64,64,64);
	}
	else
	{
		fontPrint(font,-180, -60, TEXTSTR(TEXTSTR_OPTIONS_ACT1), 64,64,96);
		optionsFramesToTimer (gameSaveData.best_times[TIME_ACT1], optionstime);
		optionsDrawTime(optionstime, 70, -60, 64,64,96);
	}


	// Act 1 Boss
	// Only print the proper name if the best time is actually there
	// If the time isn't the default of 5mins, assume the level's been played at least once

	if(gameSaveData.best_times[TIME_DOGCHASE]!=INIT_DOGCHASE_BEST)		
	{
		fontPrint(font,-180,-40,TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT1BOSS),64,64,96);
		optionsFramesToTimer (gameSaveData.best_times[TIME_DOGCHASE], optionstime);
		optionsDrawTime(optionstime, 70, -40, 64,64,96);
	}
	else
	{
		fontPrint(font,-180,-40,TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT1BOSS_U),64,64,64);
		optionsFramesToTimer (gameSaveData.best_times[TIME_DOGCHASE], optionstime);
		optionsDrawTime(optionstime, 70, -40, 64,64,64);
	}


	// Act 2 total

	if(gameSaveData.best_times[TIME_ACT2]==INIT_ACT2_BEST)
	{
		fontPrint(font,-180, -20, TEXTSTR(TEXTSTR_OPTIONS_ACT2), 64,64,64);
		optionsFramesToTimer (gameSaveData.best_times[TIME_ACT2], optionstime);
		optionsDrawTime(optionstime, 70, -20, 64,64,64);
	}
	else
	{
		fontPrint(font,-180, -20, TEXTSTR(TEXTSTR_OPTIONS_ACT2), 64,64,96);
		optionsFramesToTimer (gameSaveData.best_times[TIME_ACT2], optionstime);
		optionsDrawTime(optionstime, 70, -20, 64,64,96);
	}

	// Act 2 Boss

	if(gameSaveData.best_times[TIME_COGCHASE]!=INIT_COGCHASE_BEST)
	{
		fontPrint(font,-180,0,TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT2BOSS),64,64,96);
		optionsFramesToTimer (gameSaveData.best_times[TIME_COGCHASE], optionstime);		
		optionsDrawTime(optionstime, 70, 0, 64,64,96);
	}
	else
	{
		fontPrint(font,-180,0,TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT2BOSS_U),64,64,64);
		optionsFramesToTimer (gameSaveData.best_times[TIME_COGCHASE], optionstime);		
		optionsDrawTime(optionstime, 70, 0, 64,64,64);
	}


	// Act 4 total

	if(gameSaveData.best_times[TIME_ACT4]==INIT_ACT3_BEST)
	{
		fontPrint(font,-180, 20, TEXTSTR(TEXTSTR_OPTIONS_ACT3), 64,64,64);
		optionsFramesToTimer (gameSaveData.best_times[TIME_ACT4], optionstime);		// Act 3 is actually act 4 
		optionsDrawTime(optionstime, 70, 20, 64,64,64);
	}
	else
	{
		fontPrint(font,-180, 20, TEXTSTR(TEXTSTR_OPTIONS_ACT3), 64,64,96);
		optionsFramesToTimer (gameSaveData.best_times[TIME_ACT4], optionstime);		// Act 3 is actually act 4 
		optionsDrawTime(optionstime, 70, 20, 64,64,96);
	}

	// Total Playing Time

	fontPrint(font,-180, 40, TEXTSTR(TEXTSTR_OPTIONS_TOTAL_TIME), 64,64,96);
	optionsFramesToTimer (gameSaveData.time_spent_playing, optionstime);
	optionsDrawTime(optionstime, 70, 40, 64,64,96);
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsDrawLevelSelect(void)
//	Purpose 	: Draw routine for the Level Select menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsDrawLevelSelect(void)
{
	int i;

	fontPrintCentred(font, 0,-64, TEXTSTR(TEXTSTR_OPTIONS_ACT1+levselopt.currentstage),128,128,128);
	
	if(levselopt.currentstage>0)
		overlaySpriteFlipped(optionarrows[0], -198, -12, 0,  ((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)));

	if(levselopt.currentstage<2)
		overlaySprite(optionarrows[0], 180, -12,0,  ((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)));

	switch(levselopt.currentstage)
	{
		case 0:		// Act 1
			
			if(gameSaveData.levels_available[REPLAY_AVAILABLE_ACT1])
			{
				if(levselopt.currentlevel==0)
					fontPrintCentred(font, 0,-40, TEXTSTR(TEXTSTR_OPTIONS_MENU_STARTACT1),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0,-40, TEXTSTR(TEXTSTR_OPTIONS_MENU_STARTACT1),64,64,96);
			}
			else
				fontPrintCentred(font,0,-40,TEXTSTR(TEXTSTR_OPTIONS_MENU_STARTACT1),64,64,64);


			if(gameSaveData.levels_available[REPLAY_AVAILABLE_ACT1BOSS])
			{
				if(levselopt.currentlevel==1)
					fontPrintCentred(font, 0,-20, TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT1BOSS),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0,-20, TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT1BOSS),64,64,96);
			}
			else
				fontPrintCentred(font, 0,-20, TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT1BOSS_U),64,64,64);

			break;

		case 1:		// Act 2
			
			if(gameSaveData.levels_available[REPLAY_AVAILABLE_ACT2])
			{
				if(levselopt.currentlevel==0)
					fontPrintCentred(font, 0,-40, TEXTSTR(TEXTSTR_OPTIONS_MENU_STARTACT2),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0,-40, TEXTSTR(TEXTSTR_OPTIONS_MENU_STARTACT2),64,64,96);
			}	
			else
					fontPrintCentred(font, 0,-40, TEXTSTR(TEXTSTR_OPTIONS_MENU_STARTACT2),64,64,64);


			if(gameSaveData.levels_available[REPLAY_AVAILABLE_SEESAW])
			{
				if(levselopt.currentlevel==1)
					fontPrintCentred(font, 0,-20, TEXTSTR(TEXTSTR_OPTIONS_MENU_SEESAWGAME),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0,-20, TEXTSTR(TEXTSTR_OPTIONS_MENU_SEESAWGAME),64,64,96);
			}
			else
				fontPrintCentred(font, 0,-20, TEXTSTR(TEXTSTR_OPTIONS_MENU_SEESAWGAME_U),64,64,64);


			if(gameSaveData.levels_available[REPLAY_AVAILABLE_FIREWORKS])
			{
				if(levselopt.currentlevel==2)
					fontPrintCentred(font, 0, 0, TEXTSTR(TEXTSTR_OPTIONS_MENU_FIREWORKSGAME),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0, 0, TEXTSTR(TEXTSTR_OPTIONS_MENU_FIREWORKSGAME),64,64,96);
			}
			else
				fontPrintCentred(font, 0, 0, TEXTSTR(TEXTSTR_OPTIONS_MENU_FIREWORKSGAME_U),64,64,64);


			if(gameSaveData.levels_available[REPLAY_AVAILABLE_CATAPULT])
			{
				if(levselopt.currentlevel==3)
					fontPrintCentred(font, 0, 20, TEXTSTR(TEXTSTR_OPTIONS_MENU_CATAPULTGAME),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0, 20, TEXTSTR(TEXTSTR_OPTIONS_MENU_CATAPULTGAME),64,64,96);
			}
			else
				fontPrintCentred(font, 0, 20, TEXTSTR(TEXTSTR_OPTIONS_MENU_CATAPULTGAME_U),64,64,64);


			if(gameSaveData.levels_available[REPLAY_AVAILABLE_ACT2BOSS])
			{
				if(levselopt.currentlevel==4)
					fontPrintCentred(font, 0, 40, TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT2BOSS),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0, 40, TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT2BOSS),64,64,96);
			}
			else
				fontPrintCentred(font, 0, 40, TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT2BOSS_U),64,64,64);

			break;
			
		case 2:		// Act 3
		
			if(gameSaveData.levels_available[REPLAY_AVAILABLE_ACT3])
			{
				if(levselopt.currentlevel==0)
					fontPrintCentred(font, 0,-45, TEXTSTR(TEXTSTR_OPTIONS_MENU_STARTACT3),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0,-45, TEXTSTR(TEXTSTR_OPTIONS_MENU_STARTACT3),64,64,96);
			}
			else
				fontPrintCentred(font, 0,-45, TEXTSTR(TEXTSTR_OPTIONS_MENU_STARTACT3),64,64,64);


			if(gameSaveData.levels_available[REPLAY_AVAILABLE_EGGLAYING])
			{
				if(levselopt.currentlevel==1)
					fontPrintCentred(font, 0,-26, TEXTSTR(TEXTSTR_OPTIONS_MENU_EGGGAME),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0,-26, TEXTSTR(TEXTSTR_OPTIONS_MENU_EGGGAME),64,64,96);
			}
			else
				fontPrintCentred(font, 0,-26, TEXTSTR(TEXTSTR_OPTIONS_MENU_EGGGAME_U),64,64,64);
		

			if(gameSaveData.levels_available[REPLAY_AVAILABLE_ENGINE])
			{
				if(levselopt.currentlevel==2)
					fontPrintCentred(font, 0,-9, TEXTSTR(TEXTSTR_OPTIONS_MENU_ENGINEGAME),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0,-9, TEXTSTR(TEXTSTR_OPTIONS_MENU_ENGINEGAME),64,64,96);
			}
			else
				fontPrintCentred(font, 0,-9, TEXTSTR(TEXTSTR_OPTIONS_MENU_ENGINEGAME_U),64,64,64);

			
			if(gameSaveData.levels_available[REPLAY_AVAILABLE_BUILDING])
			{
				if(levselopt.currentlevel==3)
					fontPrintCentred(font, 0,8, TEXTSTR(TEXTSTR_OPTIONS_MENU_CONSTRUCTIONGAME),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0,8, TEXTSTR(TEXTSTR_OPTIONS_MENU_CONSTRUCTIONGAME),64,64,96);
			}
			else
				fontPrintCentred(font, 0,8, TEXTSTR(TEXTSTR_OPTIONS_MENU_CONSTRUCTIONGAME_U),64,64,64);


			if(gameSaveData.levels_available[REPLAY_AVAILABLE_WINGMAKING])
			{
				if(levselopt.currentlevel==4)
					fontPrintCentred(font, 0, 25, TEXTSTR(TEXTSTR_OPTIONS_MENU_WINGSGAME),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0, 25, TEXTSTR(TEXTSTR_OPTIONS_MENU_WINGSGAME),64,64,96);
			}
			else
				fontPrintCentred(font, 0, 25, TEXTSTR(TEXTSTR_OPTIONS_MENU_WINGSGAME_U),64,64,64);

			if(gameSaveData.levels_available[REPLAY_AVAILABLE_ACT3BOSS])
			{
				if(levselopt.currentlevel==5)
					fontPrintCentred(font, 0, 42, TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT3BOSS),optionTextRGB,optionTextRGB,optionTextRGB);
				else
					fontPrintCentred(font, 0, 42, TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT3BOSS),64,64,96);
			}
			else
				fontPrintCentred(font, 0, 42, TEXTSTR(TEXTSTR_OPTIONS_MENU_ACT3BOSS_U),64,64,64);
	}
}




//----------------------------------------------------------------------------------
//	Function 	: void optionsLevelSelectCycle(void)
//	Purpose 	: Cycle routine for the Level Select menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsLevelSelectCycle(void)
{
	int maxoption,minoption;
	int num_levels_available;

	maxoption = minoption = 0;
	switch(levselopt.currentstage)
	{
	case 0:
		num_levels_available = (gameSaveData.levels_available[REPLAY_AVAILABLE_ACT1]>0) + (gameSaveData.levels_available[REPLAY_AVAILABLE_ACT1BOSS]>0);
		maxoption = num_levels_available-1;
		break;
	case 1:
		num_levels_available = (gameSaveData.levels_available[REPLAY_AVAILABLE_ACT2]>0) + (gameSaveData.levels_available[REPLAY_AVAILABLE_SEESAW]>0) + (gameSaveData.levels_available[REPLAY_AVAILABLE_FIREWORKS]>0) + (gameSaveData.levels_available[REPLAY_AVAILABLE_CATAPULT]>0) + (gameSaveData.levels_available[REPLAY_AVAILABLE_ACT2BOSS]>0);
		maxoption = num_levels_available-1;
		break;
	case 2:
		num_levels_available = (gameSaveData.levels_available[REPLAY_AVAILABLE_ACT3]>0) + (gameSaveData.levels_available[REPLAY_AVAILABLE_EGGLAYING]>0) + (gameSaveData.levels_available[REPLAY_AVAILABLE_ENGINE]>0) + (gameSaveData.levels_available[REPLAY_AVAILABLE_BUILDING]>0) + (gameSaveData.levels_available[REPLAY_AVAILABLE_WINGMAKING]>0) + (gameSaveData.levels_available[REPLAY_AVAILABLE_ACT3BOSS]>0);
		maxoption = num_levels_available-1;
		break;
	default:
		break;
	}
	
	if((pReadPad->debounce[0] & PAD_LEFT) ||(pReadPad->analogXS[0]<-2048))
		if(levselopt.currentstage>0)
		{
			soundPlaySample(Clik2,255,1000);

			levselopt.currentlevel = 0;
			levselopt.currentstage--;
		}

	if((pReadPad->debounce[0] & PAD_RIGHT) ||(pReadPad->analogXS[0]>2048))
		if(levselopt.currentstage<2)
		{
			soundPlaySample(Clik2,255,1000);

			levselopt.currentlevel = 0;
			levselopt.currentstage++;
		}
	
	if((pReadPad->debounce[0] & PAD_UP) ||(pReadPad->analogYS[0]<-2048))
		if(levselopt.currentlevel>0)
		{
			soundPlaySample(Clik2,255,1000);

			// get the previous available level
			levselopt.currentlevel--;
		}

	if((pReadPad->debounce[0] & PAD_DOWN) ||(pReadPad->analogYS[0]>2048))
		if(levselopt.currentlevel<maxoption)
		{
			soundPlaySample(Clik2,255,1000);

			levselopt.currentlevel++;
			// get the next available level
		}

	if((pReadPad->debounce[0] & (PAD_START | PAD_CROSS)) && maxoption >= 0)  // if no levels available, maxoption==-1
	{
		levselopt.quitflag = levselopt.currentlevel;
		levselopt.quitflag++;		// start from 1, not 0
		if(levselopt.currentstage==1)	// Act 2 - 2 levels in act 1
			levselopt.quitflag+=2;
		if(levselopt.currentstage==2)	// Act 3 - 7 levels in acts 1 and 2
			levselopt.quitflag+=7;
		debugPrintf("Quitflag set to value: %d\n",levselopt.quitflag);
	}
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsSaveCycle(void)
//	Purpose 	: Cycle routine for the Save/Load menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsSaveCycle(void)
{
	if(pReadPad->debounce[0] & PAD_CROSS)
	{
		switch(current_suboption)
		{
		case 0:
			optionstate = LOAD_LOAD;	
			cardFowlerLoadStart();
			break;
		case 1:
			optionstate = SAVE_LOAD;
			cardFowlerSaveStart();
			break;
		}
	}
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsReturn(void)
//	Purpose 	: Return from a menu to the main rotating-around state
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsReturn()
{
	optionstate=OPTIONS_MAIN;
	if(optionstate == SAVE_LOAD || optionstate == LOAD_LOAD)
		optionstate = SAVE_MAIN;
	draw_routine = optionsDraw;
	cycle_routine = optionsCycle;
	menuclosing=1;
	menuwidth=400;
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsRatingsCycle(void)
//	Purpose 	: Cycle routine for the Ratings menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsRatingsCycle(void)
{
	if((desprojection<1400)&&(medalsopening))
	{
		desprojection+=25;
		if(desprojection==1400)
			medalsopening=0;
	}
	
	if((pReadPad->debounce[0] & PAD_TRIANGLE) && (desprojection==1400))
	{
		medalsclosing = 1;
	}

	if(medalsclosing)
	{
		desprojection-=25;
		if(desprojection==800)
		{
			medalsclosing=0;
			optionstate = OPTIONS_MAIN;
		}
	}

	GsSetProjection(desprojection);
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsDoTestData(void)
//	Purpose 	: Fill in some stuff for testing
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsDoTestData(void)
{
	int i;
	//return;


#ifdef DEBUG
	for(i=0;i<13;i++)			// Make them all available!
		gameSaveData.levels_available[i] = 1;

	for(i=0;i<NUM_MOVIES;i++)
	{
		gameSaveData.movies_available[i]=1;			// make none of them available
	}

	for(i=8;i<NUM_MOVIES;i+=2)			// make half available
	{
		gameSaveData.movies_available[i]=0;
	}

/*	for(i=0;i<6;i++)
	{
		if(i<4)
			gameSaveData.medals_won[i]=i;
		else
			gameSaveData.medals_won[i]=i/2;
	}*/

#endif


}





//----------------------------------------------------------------------------------
//	Function 	: void optionsLangselectCycle(void)
//	Purpose 	: Cycle Routine for the Language select menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsLangselectCycle(void)
{
	int rqd_lang = gameTextLang;

	if(pReadPad->debounce[0] & PAD_CROSS)
	{
		switch(current_suboption)
		{
			case 1:
				rqd_lang = LANG_F;
				break;
			case 2:
				rqd_lang = LANG_D;
				break;
			case 3:
				rqd_lang = LANG_IT;
				break;
			default:
			case 0:
				rqd_lang = LANG_UK;
				break;
		}

		if(rqd_lang != gameTextLang)
		{
#ifndef _WINDOWS
		sound_XA_PauseForLoading();

			gameTextLang = rqd_lang;

			gameTextDestroy();	// Free up old version

			gameTextInit("SHELL\\GAMETEXT.TXT", TEXTSTR_MAX, LANG_FILE_NUMLANGS, gameTextLang);		// 4 is number of langs, gameTextLang is one we want
			options_language_changed = 1;
		sound_XA_Resume(-1);
#endif
		}
	}


// tbd - we'll need to do some memory rearrangement, methinks...

}






//----------------------------------------------------------------------------------
//	Function 	: void optionsMoviesCycle(void)
//	Purpose 	: Cycle Routine for the movies menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsMoviesCycle(void)
{
	if((pReadPad->debounce[0] & PAD_RIGHT) ||(pReadPad->analogXS[0]>2048))
		if(currentmovie < NUM_MOVIES - SELECTABLE_MOVIE_BASE - 1)
			currentmovie++;

	if((pReadPad->debounce[0] & PAD_LEFT) ||(pReadPad->analogXS[0]<-2048))
		if(currentmovie>0)
			currentmovie--;

#ifndef _WINDOWS
	if(pReadPad->debounce[0] & (PAD_CROSS | PAD_CIRCLE))
	{
		if(gameSaveData.movies_available[currentmovie])
		{
// tbd - If we're going to play a movie, chances are we'll need to unload the options info for the duration...
// (We're pretty safe vram-wise)

			sound_XA_PauseForLoading();

			optionsFree();
			main_EnsureOverlay(VIDEO_PLAYING_OVERLAY);
			video_PlayVid(currentmovie + SELECTABLE_MOVIE_BASE, 0);
			optionsLoadData();

			sound_XA_Resume(-1);
		
		}
		else
		{
			soundPlaySample(LowBzzz1, 255, 1000);
		}
	}
#endif
}






//----------------------------------------------------------------------------------
//	Function 	: void optionsMoviesDraw(void)
//	Purpose 	: Draw routine for the Movies menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsMoviesDraw(void)
{
	if(gameSaveData.movies_available[currentmovie])
	{
		overlaySprite(shot, -64, -32, 0, 0x808080);
		overlaySprite(filmreel, -98, -47, 0, 0x808080);
		fontPrint(font, -fontExtentW(font,TEXTSTR(moviestext[currentmovie]))/2,68,TEXTSTR(moviestext[currentmovie]),128,128,128);
	}
	else
	{
		char temp[80];
		sprintf(temp,"%s %i",(char *)TEXTSTR(TEXTSTR_OPTIONS_MOVIE_NUMBER),(currentmovie+1));
		fontPrintCentred(font, 0,-12-12,temp,128,128,128);
		fontPrintCentred(font, 0,-12+12,TEXTSTR(TEXTSTR_OPTIONS_MOVIE_LOCKED),128,128,128);

		overlayFilledRectangle(-128, -64,256,128, 0x440000);
		optionsDrawBoxOutline(-129, -65,257,129,0xffffff);
	}

	if(currentmovie>0)
		overlaySpriteFlipped(optionarrows[0], -158, -8, 0,  ((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)));
	if(currentmovie < NUM_MOVIES - SELECTABLE_MOVIE_BASE)
		overlaySprite(optionarrows[0], 140, -8, 0,  ((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)));
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsDrawTime(gametimerType *timetoprint, int x, int y)
//	Purpose 	: Print a time
//	Parameters 	: A pointer to a gametimer structure, x and y position to print at
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsDrawTime(gametimerType *timetoprint, int x, int y, int r, int g, int b)
{	// Hours:minutes:seconds
	char *time={"00:00:00"};

	*time = (unsigned char) timetoprint->tenshours+48;
	*(time+1) = (unsigned char) timetoprint->hours+48;
	*(time+3) = (unsigned char) timetoprint->tensminutes+48;
	*(time+4) = (unsigned char) timetoprint->minutes+48;
	*(time+6) = (unsigned char) timetoprint->tensseconds+48;
	*(time+7) = (unsigned char) timetoprint->seconds+48;

	fontPrint(font,x,y,time,r, g, b);
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsFramesToTimer (int timeinframes, gametimerType *timer)
//	Purpose 	: Convert a frame count to minutes, seconds etc...
//	Parameters 	: A frame count, a pointer to a gametimer structure to fill in
//	Returns 	: None
//  Info		: This working properly all hangs on the frame rate not dropping to below 2 frames throughout..
//				  Also, it only goes up to 99 hours 59 minutes and 59 seconds
//----------------------------------------------------------------------------------

void optionsFramesToTimer (int timeinframes, gametimerType *timer)
{
#if(PALMODE==YES)
	timer->hundredths = timeinframes*4;
	timer->tenths = (timer->hundredths/10);
	timer->seconds = (timer->tenths/10);
	timer->tensseconds = (timer->seconds/10);
	timer->minutes = (timer->tensseconds/6);
	timer->tensminutes = (timer->minutes/10);
	timer->hours = (timer->tensminutes/6);
	timer->tenshours = (timer->hours/10);
	timer->days = (timer->days/24);

	timer->hundredths = (timer->hundredths%10);
	timer->tenths = (timer->tenths%10);
	timer->seconds = (timer->seconds%10);
	timer->tensseconds = (timer->tensseconds%6);
	timer->minutes = (timer->minutes%10);
	timer->tensminutes = (timer->tensminutes%6);
	timer->hours = (timer->hours%10);
	timer->tenshours = (timer->tenshours%10);
#else
	timer->hundredths = (timeinframes*3);	// It'll be off by 3 thousandths of a second or so each frame
	timer->tenths = (timeinframes/3);
	timer->seconds = (timer->tenths/10);
	timer->tensseconds = (timer->seconds/10);
	timer->minutes = (timer->tensseconds/6);
	timer->tensminutes = (timer->minutes/10);
	timer->hours = (timer->tensminutes/6);
	timer->tenshours = (timer->hours/10);
	timer->days = (timer->days/24);

	timer->hundredths = (timer->hundredths%10);
	timer->tenths = (timer->tenths%10);
	timer->seconds = (timer->seconds%10);
	timer->tensseconds = (timer->tensseconds%6);
	timer->minutes = (timer->minutes%10);
	timer->tensminutes = (timer->tensminutes%6);
	timer->hours = (timer->hours%10);
	timer->tenshours = (timer->tenshours%10);
#endif
}
/*
void optionsCheckForLevelsAvailable(void)		// There are only 13 levels available
{	
	int i;

	for(i=0;i<N_REPLAY_LEVELS;i++)
		gameSaveData.levels_available[i] = 0;

	// Act 1

	gameSaveData.levels_available[REPLAY_AVAILABLE_ACT1] = 1;		// Always available


	// Dog chase

	if(gameSaveData.inventory_item_status[BOOTS]==INV_STATUS_REMOVED	// Available if you've returned all these items
		&& gameSaveData.inventory_item_status[A1POLES]==INV_STATUS_REMOVED	// might be better to set the flag somewhere in the fma?
		&& gameSaveData.inventory_item_status[GLOVES]==INV_STATUS_REMOVED
		&& gameSaveData.inventory_item_status[NIGHTDRESS]==INV_STATUS_REMOVED)
		gameSaveData.levels_available[REPLAY_AVAILABLE_ACT1BOSS] = 1;


	// Act 2

	if(gameSaveData.best_times[TIME_DOGCHASE] != INIT_DOGCHASE_BEST)		// If you've finished the dogchase, Act 2 is available
		gameSaveData.levels_available[REPLAY_AVAILABLE_ACT2] = 1;


	// Seesaw

	if(gameSaveData.inventory_item_status[COOKING_WEIGHTS]==INV_STATUS_REMOVED)	// Seesaw - Available if you've returned the weights
		gameSaveData.levels_available[REPLAY_AVAILABLE_SEESAW] = 1;


	// Fireworks

	if(gameSaveData.inventory_item_status[MATCHES]==INV_STATUS_REMOVED	// Fireworks - available if you've returned the matches and fireworks
		&& gameSaveData.inventory_item_status[FIREWORKS] == INV_STATUS_REMOVED)
		gameSaveData.levels_available[REPLAY_AVAILABLE_FIREWORKS] = 1;

	
	// Catapult

	if(gameSaveData.inventory_item_status[TENNIS_RACKET]==INV_STATUS_REMOVED	// Available if you've returned all these items
		&& gameSaveData.inventory_item_status[PRAM_CHASSIS]==INV_STATUS_REMOVED	// might be better to set the flag somewhere in the fma?
		&& gameSaveData.inventory_item_status[STRONG_CORD]==INV_STATUS_REMOVED
		&& gameSaveData.inventory_item_status[BROKEN_LADDER]==INV_STATUS_REMOVED)
		gameSaveData.levels_available[REPLAY_AVAILABLE_CATAPULT] = 1;


	// Act 2 Boss
	if((gameSaveData.medals_won[MEDAL_WON_SEESAW]>0)
		&&(gameSaveData.medals_won[MEDAL_WON_FIREWORKS]>0)
		&&(gameSaveData.medals_won[MEDAL_WON_CATAPULT]>0))
		gameSaveData.levels_available[REPLAY_AVAILABLE_ACT2BOSS] = 1;

	
	// Act 3						// This is gonna have to be based on completing the cogshase successfully 
									// - there aint anything to test for that condition yet as far as i can see!
//	gameSaveData.levels_available[REPLAY_AVAILABLE_ACT3] = 1;		
	if(gameSaveData.best_times[TIME_COGCHASE] != INIT_COGCHASE_BEST)
		gameSaveData.levels_available[REPLAY_AVAILABLE_ACT3] = 1;



	// Egg laying game				// Again, dunno what condition to test for this one !
	gameSaveData.levels_available[REPLAY_AVAILABLE_EGGLAYING] = 1;

	// Engine game
	if(gameSaveData.inventory_item_status[OIL_CAN]==INV_STATUS_REMOVED	// Available if you've returned all these items
		&& gameSaveData.inventory_item_status[ENGINE]==INV_STATUS_REMOVED	// might be better to set the flag somewhere in the fma?
		&& gameSaveData.inventory_item_status[CHAIN]==INV_STATUS_REMOVED)
		gameSaveData.levels_available[REPLAY_AVAILABLE_ENGINE] = 1;

	// Construction game
	if(gameSaveData.inventory_item_status[BINOCULARS]==INV_STATUS_REMOVED	// Available if you've returned all these items
		&& gameSaveData.inventory_item_status[WOOD]==INV_STATUS_REMOVED	// might be better to set the flag somewhere in the fma?
		&& gameSaveData.inventory_item_status[TOOLS]==INV_STATUS_REMOVED
		&& gameSaveData.inventory_item_status[COGS]==INV_STATUS_REMOVED)
		gameSaveData.levels_available[REPLAY_AVAILABLE_BUILDING] = 1;


	// Wingmaking game
	if(gameSaveData.inventory_item_status[LAUNDRY]==INV_STATUS_REMOVED	// Available if you've returned all these items
		&& gameSaveData.inventory_item_status[YARN]==INV_STATUS_REMOVED	// might be better to set the flag somewhere in the fma?
		&& gameSaveData.inventory_item_status[A4POLES]==INV_STATUS_REMOVED)
		gameSaveData.levels_available[REPLAY_AVAILABLE_WINGMAKING] = 1;

	// Crate sequence
	if((gameSaveData.medals_won[MEDAL_WON_ENGINE]>0)
		&&(gameSaveData.medals_won[MEDAL_WON_CONSTRUCTION]>0)			// TBD:
		&&(gameSaveData.medals_won[MEDAL_WON_WINGS]>0))				// Add the egglaying game to this list when its done
		gameSaveData.levels_available[REPLAY_AVAILABLE_ACT3BOSS] = 1;
}
*/



//----------------------------------------------------------------------------------
//	Function 	: void optionsResetGame(void)
//	Purpose 	: Reset all the game variables
//	Parameters 	: None
//	Returns 	: None
//  Info		: Resets the game so you have to play it from the start again (why you would ever want to do this I do not know!)
//----------------------------------------------------------------------------------

void optionsResetGame(void)		
{
// RFW - Simpler way :)
	cardInitialPrefs(&optionData);
	cardInitialGameState();

/*

	int i,j;

	// Reset the map pieces

	gamePlayData->map_pieces_got[0] = 1;
	for(i=1;i<14;i++) gamePlayData->map_pieces_got[i] = 0;


	// Reset the medals

	for(i=0;i<N_MEDAL_LEVELS;i++) gameSaveData.medals_won[i] = 0;


	// Reset all the inventories

	for(i=0;i<NUM_CHARACTER_INVS;i++)
	{	
		currentInv = &gamePlayData->inventories[i];
		
		for(j=0;j<6;j++)
		{
			currentInv->slot_contents[j] = EMPTY;
		}
		
		currentInv->selected_item = EMPTY;
	}

	// Reset all the movies

	for(i=0;i<NUM_MOVIES;i++)
		gameSaveData.movies_available[i] = 0;

	// Reset all the stills

	for(i=0;i<30;i++)
		gameSaveData.stills_available[i] = 0;		

	// Reset all the available levels

	for(i=0;i<N_REPLAY_LEVELS;i++)
		gameSaveData.levels_available[i] = 0;

	// Reset the chickens rescued tally

	for(i=0;i<N_RESCUE_LEVELS;i++)
		gameSaveData.best_chickens_rescued[i] = 0;
	
	// Reset the best times

	for(i=0;i<N_TIMED_LEVELS;i++)
		gameSaveData.best_times[i];			

	// Reset the game timer

	gameSaveData.time_spent_playing = 0;

	// Reset all the task flags

	for(i=0;i<MAX_TASKS;i++)
		gamePlayData->tasks_done[MAX_TASKS] = 0;

	// Reset the sprouts stuff

	for(i=0;i<LEVNUMBER_NUM_LEVELS;i++)
		gamePlayData->pickups_collected[i] = 0;

	gamePlayData->sprouts_carried = 0;

	// respot all the items

	for(i=0;i<TOTAL_ITEMS;i++)
		scenicInventoryNotification(i,SCENIC_INVENTORY_RESPOT);
*/
}





//----------------------------------------------------------------------------------
//	Function 	: void optionsControlMethodDraw(void)
//	Purpose 	: Draw the control method select menu
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsControlMethodDraw(void)
{
	char *heading;

	overlaySprite(controllerspr,  -70, -44, 0, 0x808080);
	overlaySpriteFlipped(optionarrows[0], -232, -100, 0, ((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)));
	overlaySprite(optionarrows[0],  215, -100, 0, ((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)));
	heading = fontUpper(TEXTSTR(TEXTSTR_OPTIONS_CONTROL_METHOD1+current_suboption));
	fontPrintCentred(font, 0,-100, heading,128,128,128);
	fontPrintCentred(font,4,-56,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_ROTCAMERA),128,128,128);
	fontPrint(font,86,-44,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_TIPTOE),128,128,128);
	fontPrint(font,86,-30,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_INVENTORY),128,128,128);
//	fontPrintCentred(font, 0,64, TEXTSTR(TEXTSTR_OPTIONS_SELECT_CLOSE),128,128,128);
	{
		char *str;
		int size;

		str = TEXTSTR(TEXTSTR_OPTIONS_SELECT_CLOSE);	//"@X Select     @T Close menu"
		size = fontExtentW(font,str);
		fontPrint(font,         -(size/2)   ,BOTTOM_WINDOW_Y+10+(100-(menuwidth/4))/4,str,128,128,128);
		optionsAlphaRectangle( (-(size)/2)-4,BOTTOM_WINDOW_Y+ 5+(100-(menuwidth/4))/4, (size)+8,18, 0, 0x003000);
	}

	fontPrint(font,86,23,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_ROTATE),128,128,128);
	fontPrint(font,86,33,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_CAMERA),128,128,128);
	fontPrint(font,-140,-47,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_CYCLE),128,128,128);
	fontPrint(font,-140,-36,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_ITEMS),128,128,128);
	fontPrint(font,-176,-20,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_ONSCREEN),128,128,128);
	fontPrint(font,-190,-8,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_HELP),128,128,128);
	fontPrint(font,-150,16,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_MOVE),128,128,128);
	fontPrint(font,-178,28,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_CHARACTER),128,128,128);
	fontPrint(font,-20,28,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_PAUSE),128,128,128);
	switch(current_suboption)
	{
	case 0:
		fontPrint(font,84,-17,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_THROW),128,128,128);
		fontPrint(font,84,-3,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_JUMP),128,128,128);
		fontPrint(font,86,9,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_ACTION),128,128,128);
		break;
	case 1:
		fontPrint(font,84,-17,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_THROW),128,128,128);
		fontPrint(font,84,-3,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_ACTION),128,128,128);
		fontPrint(font,86,9,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_JUMP),128,128,128);
		break;
	case 2:
		fontPrint(font,84,-17,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_JUMP),128,128,128);
		fontPrint(font,84,-3,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_ACTION),128,128,128);
		fontPrint(font,86,9,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_THROW),128,128,128);
		break;
	case 3:
		fontPrint(font,84,-17,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_ACTION),128,128,128);
		fontPrint(font,84,-3,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_JUMP),128,128,128);
		fontPrint(font,86,9,TEXTSTR(TEXTSTR_OPTIONS_CONTROL_THROW),128,128,128);
		break;
	}
}




//----------------------------------------------------------------------------------
//	Function 	: void optionsControlMethodCycle(void)
//	Purpose 	: Control method select
//	Parameters 	: None
//	Returns 	: None
//  Info		: 
//----------------------------------------------------------------------------------

void optionsControlMethodCycle(void)
{
	if(pReadPad->debounce[0] & PAD_LEFT)
		current_suboption--;

	if(current_suboption<0)
		current_suboption = NUM_CONTROL_METHODS-1;

	if(pReadPad->debounce[0] & PAD_RIGHT)
		current_suboption++;
	if(current_suboption>NUM_CONTROL_METHODS-1)
		current_suboption = 0;
	
	if(pReadPad->debounce[0] & PAD_CROSS)
	{
		controlMap = current_suboption;
		optionstate = CONTROLLER_MAIN;
		current_option = CONTROLLER_MAIN;
	}

	if(pReadPad->debounce[0] & PAD_TRIANGLE)
	{
		optionstate = CONTROLLER_MAIN;
		current_option = CONTROLLER_MAIN;
	}
}



void optionsGalleryDraw(void)
{
	int i;
	int picnumber;

//	debugPrintf("%d\n",current_suboption);
	picnumber = 0;

/*	for(i=0;i<10;i+=2)
		gameSaveData.stills_available[i]=1;*/


	// Pics 0 to 4
	for(i=-256+76;i<194;i+=75)
	{

		if(picnumber==current_suboption)
		{
			if(gameSaveData.stills_available[picnumber])	
				overlaySprite(gallerythumbs[picnumber],  i+5, -57, 0, 0xa0a0a0);		// Question Mark
			else
				overlaySprite(gallerythumbs[10],  i+5, -57, 0, 0xb0b0b0);

			overlaySprite(pictureframe,  i, -61, 0, 0xffffff);	
			optionsDrawBoxOutline(i-1, -62,65,65,((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)) + 0x606060);
			optionsDrawBoxOutline(i-2, -63,67,67,((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)) + 0x303030);

		}

		else
		{
			if(gameSaveData.stills_available[picnumber])	
				overlaySprite(gallerythumbs[picnumber],  i+5, -57, 0, 0x606060);		// Question Mark
			else
				overlaySprite(gallerythumbs[10],  i+5, -57, 0, 0x808080);

			overlaySprite(pictureframe,  i, -61, 0, 0x909090);	
	

		}

		picnumber++;
	}

	// pics 5 to 9
	for(i=-256+76;i<194;i+=75)
	{
		if(picnumber==current_suboption)
		{
			if(gameSaveData.stills_available[picnumber])
				overlaySprite(gallerythumbs[picnumber],  i+5, 12, 0, 0xa0a0a0);
			else
				overlaySprite(gallerythumbs[10],  i+5, 12, 0, 0xb0b0b0);

			overlaySprite(pictureframe,  i, 8, 0, 0xffffff);
	
			optionsDrawBoxOutline(i-1, 7,65,65,((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)) + 0x606060);
			optionsDrawBoxOutline(i-2, 6,67,67,((optionTextRGB<<16)+(optionTextRGB<<8)+(optionTextRGB)) + 0x303030);
		}

		else
		{
			if(gameSaveData.stills_available[picnumber])
				overlaySprite(gallerythumbs[picnumber],  i+5, 12, 0, 0x606060);
			else
				overlaySprite(gallerythumbs[10],  i+5, 12, 0, 0x808080);

				overlaySprite(pictureframe,  i, 8, 0, 0x909090);
		}
		picnumber++;
	}
}

void optionsGalleryCycle(void)
{
	if(pReadPad->debounce[0] & PAD_LEFT)
	{
		current_suboption--;
		soundPlaySample(Clik2,255,1000);
	}

	if(pReadPad->debounce[0] & PAD_RIGHT)
	{
		current_suboption++;
		soundPlaySample(Clik2,255,1000);
	}

	if((pReadPad->debounce[0] & PAD_UP) && (current_suboption>4))
	{
		current_suboption-=5;
		soundPlaySample(Clik2,255,1000);
	}

	if((pReadPad->debounce[0] & PAD_DOWN) && (current_suboption<5))
	{
		current_suboption+=5;
		soundPlaySample(Clik2,255,1000);
	}

	if(current_suboption>9) current_suboption = 0;
	
	if(current_suboption<0) current_suboption = 9;

	if(pReadPad->debounce[0] & PAD_TRIANGLE)
	{
		soundPlaySample(MenuCloses1,255,1000);
		menuclosing=1;
		menuwidth=400;

		optionstate = OPTIONS_MAIN;
	}
	
	if(pReadPad->debounce[0] & PAD_CROSS) 
	{
		if(gameSaveData.stills_available[current_suboption])
		{
			soundPlaySample(Clik2,255,1000);
			galleryStart(current_suboption);
		}
		else
		{
			soundPlaySample(LowBzzz1, 255, 1000);
			// Bleep!
		}
	}
}
