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

	dogchase.c:			Act 1 dog-chase sequence featuring Mrs Tweedy mannequin
******************************************************************************************/

//****Includes****

#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 "overlays.h"
#include "dogchase.h"
#include "collide.h"
#include "enemies.h"
#include "camera.h"
#include "dualshock.h"
#include "ranges.h"
#include "crate.h"
#include "demo.h"
#include "card.h"		
#include "puzzles.h"
#include "gametext.h"
#include <islxa.h>
#include "sound.h"
#include "options.h"
#include "loadsnd.h"
#include "deth.h"
#include "startup.h"
#include "pause.h"

#ifdef DREAMCAST
#undef NULL
#define NULL 0
#endif

#ifdef _WINDOWS
#define LEFT_BALANCE_KEY (DIK_1)
#define RIGHT_BALANCE_KEY (DIK_3)
#endif

extern void collideFree();
void dogchaseFree(void);
static void dogchaseCycle(void);
static void dogchaseSetControlCycle(void);
static void dogchaseSetControlDraw(void);
static void dogchaseEndSuccess(void);
static void dogchaseEndFail(void);
static void dogchaseDrawSpeedMeter(void);
static void dogchaseMoveDogs(void);
static void dogchaseMoveTweedy(void);
static int dogchaseCollision(void);
static void dogchaseDrawOverlays(void);
static void dogchaseDrawModels(void);
static void dogchaseUpdateAnimations(void);
static void dogchaseUpdateTimer(int x);
static void dogchaseUpdateState(void);
static void dogchaseFullScreenOverlayAlpha(unsigned long colour);
static void dogchaseGenerateNewDust(VECTOR position, int number, int scale);
static void dogchaseDrawAndCheckDust(void);
static void dogchaseGenerateNewChicken(VECTOR position, int velocity, int destination, int door);
static void dogchaseMoveChickens(void);
static void dogchaseDoStartupAnimation(void);
static void dogchaseDrawSuccessOverlay(void);
static void dogchaseDrawTime(int x, int y);
static void dogchaseOverlayAlpha(int x, int y, int w, int h , unsigned long rgb, int colour);
static int dogchaseOverlaySprite(TextureType *spr, int x, int y, int w, int h, int depth, unsigned long colour);
static void dogchaseDrawNumber(int number, int x, int y, int r, int g, int b);
static void dogchaseDrawBriefing(void);
static void dogchaseDrawDeadMessage(void);
static void dogchaseEndRestart(void);
static void dogchaseDeadCycle(void);
static void dogchaseDeadDraw(void);



//----------------------
// Stuff for the doors
//----------------------

#define OPEN 1
#define CLOSED 0
#define OPENING 2

extern int pause_levelplaying;

static PSIMODEL *doorl_model = NULL;
static PSIMODEL *doorr_model = NULL;
static PSIMODEL *endgate_model = NULL;

static ACTOR *endgate_actor;

typedef struct {
	int speed;
	ACTOR *actor;
	int angle;
	int desiredangle;
	unsigned char status;
} doorType;

static doorType door1;
static doorType door2;
static doorType door3;
static doorType door4;

static int doorcolour;

void dogchaseEndRestart(void);
void dogchaseDrawDeadMessage(void);

static int dogchasetime;
static int bubbletimer;
static int chickentalktimer;			// delay between chicken stories
static int dogbarktimer;				// delay between dog barks

#ifdef	DREAMCAST
int	dogchaseClearState = FALSE;
#endif

//-----------------------
// Stuff for the speed / balance bar stuff
//-----------------------

static struct {
	int bar_height;
	int bar_top;
	int bar_left; } controlstuff;

//----------------------

//----------------------
// Stuff for the Tweedy
//----------------------

#define MAXBALANCE 1150
#define MINBALANCE 0
#define BALANCEINCR 3			// how much your balance increases by each frame when you're hitting buttons.
#define MAX_TWEEDYSPEED 11268	// maximum speed of Mrs Tweedy mannequin (6bit fixed point)
#define SLOW_LIMIT 3000			// less than this is slow
#define MED_LIMIT 4000			// between slow and this is med
#define FAST_LIMIT 4000			// otherwise you're going fast
#define MIN_TWEEDYSPEED 2400

static struct {
	VECTOR position;
	int balance;				// 0 to 1150, where 575 is middle balance (ie. balanced properly)
	unsigned char status;
	int desiredangle;			// the direction we want to be facing
	COLLDATA *collision;
	unsigned char animsegment;	// the seg we *want* to be playing, not necessarily the one we are playing
	int animspeed;
	int collision_centre;		// the offset of the collision sphere from the tweedy's origin on the y axis (so that it's near her feet rather than her tummy
	ENEMY enemyStruc;
	PSIMODEL *model;
	ACTOR *actor;
	char we_just_hit_something;
	VECTOR actualspeed;
	VECTOR desiredspeed;
	int totalspeed;
	unsigned char timer;
	int randommov;
	int desiredlarmangle;
	int desiredrarmangle;
	char larmmovingup;
	char larmmovingdown;
	char rarmmovingup;
	char rarmmovingdown;
	int balancemov;				// Speed of the balance indicator
	int endtimer;
} tweedy;


//----------------------
// General stuff
//----------------------

static TextureType *bar1;
static TextureType *bar2;
static TextureType *bar3;
static TextureType *bar4;
static TextureType *bar5;
static TextureType *bubble1;
static TextureType *bubble2;
static TextureType *bubble3;
static TextureType *bubble4;
static TextureType *bubble5;
static TextureType *bubble6;

static TextureType *chickensprites[44];
#ifdef _WINDOWS
 static TextureType *outcirclespr;
 static TextureType *outsquarespr;
#endif
static TextureType *incirclespr;
static TextureType *insquarespr;

#define DOGCHASE_PROJECTION 500

static unsigned short dogchaseState;
static unsigned long DC_fadecol;
static unsigned short dogchaseFrameCounter;

static int chickens_rescued = 0;
static FMA_WORLD2 *dogchase_fma_world = NULL;
static FMA_WORLD *dogchase_sky_world = NULL;

enum{
	DC_BRIEFING,
	DC_STARTING,				// dogs looking, just sitting then walking
	DC_RUNNING,					// dogs going after mannequin
	DC_DIED,					// mannequin caught
	DC_ESCAPED};


//----------------------
// Stuff for the dogs
//----------------------

#define DOG_SITTING 12
#define	DOG_GETTINGUP 13
#define DOG_SNIFFING 19
#define DOG_WALKSNIFF 18
#define	DOG_WALKING 1
#define DOG_RUNNING 2
#define DOG_JUMPING 26
#define DOG_BRAKELEFT 14
#define DOG_BRAKERIGHT 15
#define DOG_BARKING 22

#define NUM_WAYPOINTS 78
static char dc_drawoverlay;

typedef struct {
	VECTOR position;			// x,y,z position in world space
	int state;
	COLLDATA collision;
	int animsegment;			// which anim segment we currently need to be playing
	int animspeed;				// how fast it should be animated
	int nextwaypoint;			// the point we're headed to
	VECTOR currentangle;		// rotations about the three axes
	VECTOR desiredangle;		// rotations about the three axes
	int xstep;					// speed in the x direction, basically
	int ystep;					// ditto y
	int zstep;					// ditto z
	int zdist;					// distance from the current waypoint to the next in z
	int xdist;					// ditto x
	int ydist;					// ditto y
	PSIMODEL *model;
	ACTOR *actor;
	} dogType;

static dogType doggy1;
static dogType doggy2;

static int dog1waypoints[NUM_WAYPOINTS][4] ={


	{-360,	3660,	64,	DOG_WALKSNIFF}, 
	{-300,	2160,	62,	DOG_WALKSNIFF}, 
	{-300,	-1640,	62,	DOG_WALKING},
	{-180,	-3980,	48,	DOG_WALKING}, 
	{60,	-5340,	28,	DOG_RUNNING},
	{420,	-6300,	26,	DOG_RUNNING},
	{1020,	-7560,	25,	DOG_RUNNING},
	{1680,	-8400,	23,	DOG_BRAKELEFT},
	{2820,	-10020,	22,	DOG_JUMPING},
	{3480,	-11220,	23,	DOG_RUNNING},		//10 
	{3840,	-12360,	22,	DOG_RUNNING},
	{4380,	-13080,	22,	DOG_RUNNING},
	{4680,	-14220,	23,	DOG_RUNNING},
	{4920,	-15240,	22,	DOG_RUNNING},
	{5340,	-16200,	22,	DOG_RUNNING},
	{5520,	-17040,	23,	DOG_RUNNING}, 
	{5580,	-18300,	22,	DOG_RUNNING}, 
	{5400,	-19260,	22,	DOG_RUNNING}, 
	{4920,	-20040,	21,	DOG_BRAKELEFT}, 
	{5160,	-21060,	22,	DOG_RUNNING},		//20
	{5460,	-22080,	22,	DOG_JUMPING}, 
	{5480,	-23280,	21,	DOG_RUNNING}, 
	{5220,	-24120,	22,	DOG_RUNNING}, 
	{4920,	-25140,	22,	DOG_RUNNING}, 
	{4800,	-26220,	22,	DOG_RUNNING}, 
	{4560,	-27660,	21,	DOG_RUNNING}, 
	{4260,	-28860,	22,	DOG_RUNNING}, 
	{4320,	-29760,	22,	DOG_JUMPING}, 
	{4380,	-30720,	21,	DOG_RUNNING}, 
	{4320,	-31740,	22,	DOG_RUNNING},		//30
	{4380,	-32880,	22,	DOG_RUNNING}, 
	{4260,	-34260,	21,	DOG_JUMPING}, 
	{4200,	-35160,	21,	DOG_RUNNING}, 
	{4140,	-36180,	22,	DOG_RUNNING}, 
	{3900,	-36780,	22,	DOG_RUNNING}, 
	{3960,	-38280,	21,	DOG_RUNNING}, 
	{4080,	-39540,	21,	DOG_RUNNING}, 
	{4020,	-40500,	22,	DOG_BRAKERIGHT}, 
	{3780,	-41760,	23,	DOG_RUNNING}, 
	{3900,	-43260,	21,	DOG_RUNNING},		//40
	{3300,	-44340,	22,	DOG_RUNNING}, 
	{2880,	-45420,	22,	DOG_RUNNING}, 
	{2640,	-46800,	23,	DOG_JUMPING}, 
	{2540,	-48420,	23,	DOG_RUNNING}, 
	{2360,	-49740,	23,	DOG_JUMPING}, 
	{2340,	-51180,	22,	DOG_RUNNING}, 
	{2160,	-52620,	23,	DOG_RUNNING}, 
	{2220,	-54420,	23,	DOG_RUNNING}, 
	{2580,	-55440,	23,	DOG_RUNNING}, 
	{3060,	-56700,	23,	DOG_RUNNING},		//50
	{3420,	-57960,	22,	DOG_RUNNING}, 
	{3300,	-59580,	22,	DOG_RUNNING}, 
	{3480,	-60720,	23,	DOG_JUMPING}, 
	{3600,	-62340,	22,	DOG_RUNNING},		//54
	{3780,	-63660,	22,	DOG_BRAKELEFT}, 
	{4320,	-65040,	22,	DOG_RUNNING}, 
	{4380,	-74940,	140,DOG_RUNNING},
	{4020,	-75960,	22,	DOG_RUNNING}, 
	{3720,	-76680,	22,	DOG_RUNNING},
	{3420,	-77640,	22,	DOG_RUNNING},
	{2820,	-78600,	22,	DOG_RUNNING},
	{2520,	-79920,	22,	DOG_RUNNING},
	{2100,	-81540,	22,	DOG_RUNNING},
	{1440,	-82860,	23,	DOG_BRAKERIGHT},	//64 
	{900,	-84300,	22,	DOG_RUNNING},
	{420,	-85920,	22,	DOG_RUNNING},
	{-240,	-87120,	22,	DOG_RUNNING},
	{-360,	-88740,	22,	DOG_RUNNING},
	{-420,	-90240,	22,	DOG_RUNNING},
	{-480,	-91620,	23,	DOG_RUNNING}, 
	{-780,	-92520,	23,	DOG_RUNNING}, 
	{-1270,	-93720,	22,	DOG_RUNNING}, 
	{-1690,	-94860,	22,	DOG_RUNNING}, 
	{-1990,	-96120,	22,	DOG_RUNNING},		//74
	{-2320,	-97080,	22,	DOG_RUNNING},		//75
	{-2720,	-99120,	52,	DOG_WALKING},		//76 
	{-2990,	-101000,	4095,	DOG_BARKING},	//77
	{0,	0,	30,	DOG_JUMPING}						//78
};


static int dog2waypoints[NUM_WAYPOINTS][4] ={
// x,y,z, frames to get from this point to the next,animation to play
	{-1380,	3600,	68,	DOG_WALKSNIFF}, 
	{-1320,	2040,	68,	DOG_WALKSNIFF}, 
	{-1080,	-1860,	62,	DOG_WALKSNIFF},
	{-900,	-4380,	54,	DOG_WALKING}, 
	{-540,	-5460,	26,	DOG_RUNNING},
	{-360,	-6420,	26,	DOG_RUNNING},
	{360,	-7740,	24,	DOG_RUNNING},
	{960,	-8760,	22,	DOG_BRAKERIGHT},
	{1740,	-10320,	22,	DOG_RUNNING},
	{2400,	-11460,	22,	DOG_RUNNING},		//10 
	{2880,	-12540,	22,	DOG_RUNNING},
	{3480,	-13680,	22,	DOG_RUNNING},
	{4200,	-14880,	22,	DOG_RUNNING},
	{5460,	-15720,	23,	DOG_RUNNING},
	{6360,	-16740,	23,	DOG_BRAKERIGHT},
	{6060,	-17820,	23,	DOG_RUNNING}, 
	{6120,	-18780,	23,	DOG_RUNNING}, 
	{4800,	-19620,	23,	DOG_RUNNING}, 
	{4380,	-20700,	23,	DOG_RUNNING}, 
	{4140,	-21660,	23,	DOG_JUMPING},		//20
	{3840,	-23220,	23,	DOG_RUNNING}, 
	{3420,	-24120,	23,	DOG_RUNNING}, 
	{3360,	-25680,	23,	DOG_RUNNING}, 
	{3420,	-28380,	29,	DOG_RUNNING}, 
	{3480,	-30060,	29,	DOG_RUNNING}, 
	{3540,	-31380,	23,	DOG_RUNNING}, 
	{3660,	-32100,	23,	DOG_RUNNING}, 
	{3600,	-33420,	23,	DOG_RUNNING}, 
	{3480,	-33960,	23,	DOG_RUNNING}, 
	{3300,	-35220,	23,	DOG_RUNNING},		//30
	{3240,	-36300,	23,	DOG_RUNNING}, 
	{3120,	-37560,	23,	DOG_RUNNING}, 
	{3060,	-38760,	23,	DOG_RUNNING}, 
	{3000,	-39660,	23,	DOG_RUNNING}, 
	{2940,	-40860,	23,	DOG_RUNNING}, 
	{2880,	-42480,	23,	DOG_RUNNING}, 
	{2760,	-43680,	23,	DOG_RUNNING}, 
	{2520,	-44400,	23,	DOG_RUNNING}, 
	{2100,	-44820,	23,	DOG_RUNNING}, 
	{1920,	-45660,	23,	DOG_RUNNING},		//40
	{1560,	-46620,	23,	DOG_RUNNING}, 
	{1500,	-48300,	23,	DOG_RUNNING}, 
	{1440,	-49800,	23,	DOG_BRAKELEFT}, 
	{1740,	-50400,	23,	DOG_RUNNING}, 
	{2040,	-51360,	23,	DOG_RUNNING}, 
	{2340,	-51960,	23,	DOG_RUNNING}, 
	{2880,	-52980,	23,	DOG_JUMPING}, 
	{3480,	-54060,	23,	DOG_RUNNING}, 
	{3660,	-55680,	23,	DOG_RUNNING}, 
	{3960,	-57120,	23,	DOG_RUNNING},		//50
	{4140,	-58500,	23,	DOG_RUNNING}, 
	{4500,	-59880,	23,	DOG_RUNNING}, 
	{5100,	-60960,	23,	DOG_JUMPING}, 
	{5040,	-62520,	25,	DOG_RUNNING},		//54
	{4800,	-63360,	23,	DOG_RUNNING}, 
	{4260,	-64620,	23,	DOG_RUNNING}, 
	{3840,	-65820,	24,	DOG_RUNNING},
	{3480,	-66660,	24,	DOG_RUNNING}, 
	{3360,	-67440,	24,	DOG_RUNNING},
	{3240,	-69060,	24,	DOG_RUNNING},
	{3000,	-72600,	44,	DOG_RUNNING},
	{2880,	-74940,	28,	DOG_RUNNING},
	{3240,	-76800,	25,	DOG_RUNNING},
	{3360,	-78900,	58,	DOG_RUNNING},		//64 
	{900,	-84300,	70,	DOG_RUNNING},
	{420,	-85920,	24,	DOG_RUNNING},
	{-140,	-87160,	25,	DOG_RUNNING},
	{-260,	-88780,	26,	DOG_RUNNING},
	{-320,	-90280,	26,	DOG_BRAKERIGHT},
	{-380,	-91660,	26,	DOG_RUNNING}, 
	{-680,	-92560,	27,	DOG_RUNNING}, 
	{-1160,	-93660,	27,	DOG_RUNNING}, 
	{-1520,	-94820,	27,	DOG_RUNNING}, 
	{-1820,	-96360,	28,	DOG_RUNNING},		//74
	{-1880,	-97120,	27,	DOG_RUNNING}, 
	{-2120,	-99160,	54,	DOG_WALKING}, 
	{-2180,	-101100,	4095, DOG_BARKING},
	{0,0,30,DOG_JUMPING}
};


//----------------------
// Stuff for the dust
//----------------------

#define MAX_DUST 16
static int number_of_active_dust_particles;
static TextureType *dustspr[4];

typedef struct {
	int counter;
	VERT position;
	int scale;
} dustType;

static int active_dustbits;
static dustType mydust[MAX_DUST];


//----------------------
// Stuff for the timer
//----------------------

#ifdef DREAMCAST

#if PALMODE == YES
int FRAMESSEC = 25;
#else
int FRAMESSEC = 30;
#endif

#else

#if PALMODE == YES
#define FRAMESSEC 25				
#else
#define FRAMESSEC 30				
#endif

#endif

static struct {
	unsigned long hours;
	unsigned long tensminutes;
	unsigned long minutes;
	unsigned long tensseconds;
	unsigned long seconds;
	unsigned long tenths;
	unsigned long hundredths;
} dogchaseTimer;


//-----------------------
// Stuff for the casual chickens
//-----------------------
#ifdef DREAMCAST
#undef DEAD
#endif

#define DEAD 0
#define ALIVE 1
#define MAX_CHICKENS 24				// maximum number of chickens active at a particular time

typedef struct {
	int speed;						// x velocity
	unsigned char status;			// alive or dead
	unsigned char framenumber;		// the current animation frame number
	unsigned char animcounter;
	unsigned char door;				// the door behind which this chicken is situated			
//#ifdef _WINDOWS
	VECTOR position;			
//#else
//	VERT position;			// RFW. How come this worked? VERT is SHORT coordinates, which is no way big enough for the dogchase :/
//#endif
	int destination;				// the x position it needs to get to before it is killed
} dogchaseChickenType;

static dogchaseChickenType dogchaseChickens[MAX_CHICKENS];

static int active_chickens;
static int dc_timer1;

SfxSampleType *mannequinsounds[26];
SfxSampleType *dogsounds[4];
SfxSampleType *othersounds[8];
SfxSampleType *foot1;
SfxSampleType *foot2;

static int circletimer;
static int squaretimer;

// Order in which chicken voice samples to be played
static int sampleorder[] = {3,2,8,4,11,1,5,17,6,0,10,20,1,7,21,1,19,9,16,24,25};

// Number of frames between samples playing
#if PALMODE==1
static int sampledelay[] = {60,	// Hot in here
							80,	// Where are we going
							120,	// Are we going on holiday
							90,	// Are we nearly there yet
							60,	// Standin on me leg
							30,	// Sorry
							80,	// Have to work together
							50,	// Need the toilet
							70,	// oo-er ginger
							50,	// cmon girlz
							90,	// careful with those knitting needles
							90,	// sorry
							80,	// can we stop yet
							90,	// Get your foot out of my eye
							90,	// Sorry
							50,	// Stop that
							50,	// she started it
							50,	// Faster
							50,	// Watch out
							50,
							60};
#else
static int sampledelay[] = {72,	// Hot in here
							96,	// Where are we going
							144,	// Are we going on holiday
							108,	// Are we nearly there yet
							72,	// Standin on me leg
							36,	// Sorry
							96,	// Have to work together
							60,	// Need the toilet
							84,	// oo-er ginger
							60,	// cmon girls
							108,	// careful with those knitting needles
							108,	// sorry
							96,	// can we stop yet
							108,	// foot out of my eye
							108, //sorry
							60,	// Stop that
							60, // she started it
							60,	// Faster
							60,	// Watch out
							60,
							72};
#endif

static int samplelistposition;
//static int hitouchdelay;
static int leftshouttimer;
static int rightshouttimer;

//-------------------------
// Code starts here
//-------------------------

//**************************************************************************************

//-------------------------
// dogchaseStart()
//
// Initialise stuff, load models, textures etc
//-------------------------
//int options_returnlevel;

void dogchaseStart(void)
{
	int i;
	VECTOR myvec;

#ifdef	DREAMCAST
	dogchaseClearState = TRUE;
#endif

	leftshouttimer = 120;
	rightshouttimer = 120;
	squaretimer = 0;
	circletimer = 0;
	dogbarktimer = 0;

	//SB - replaced PALMODE since DC has a 50/60 Hz switch! Please leave!!
	if(palMode)
		chickentalktimer = 75;
	else
		chickentalktimer = 90;

	samplelistposition = 0;

//	hitouchdelay = 0;
	sound_FreeLanguageBank();
//	loadsndLoadBank("A1_DOGCHASE");
	sound_LoadLanguageBankBody(gameTextLang, "A1_DOGCHASE");	// Loads "a2_dogchase\\a2_dogchase_eng.sbb" (or other language versions)

	if(gameCalledFrom != GAMECALLEDFROM_DEBUG)
	{
		gameSaveData.levels_available[REPLAY_AVAILABLE_ACT1] = REPLAY_BEATEN;
		if(!gameSaveData.levels_available[REPLAY_AVAILABLE_ACT1BOSS])
		{
			gameSaveData.levels_available[REPLAY_AVAILABLE_ACT1BOSS] = REPLAY_NOTBEATEN;
		}
	}
	overlayLoadingBegin(1);

	tweedy.collision =MALLOC(sizeof(COLLDATA));

	dc_timer1 = 0;
	dc_drawoverlay = FALSE;

	actorInitialise();
	dsEvent_Init();
	active_chickens = 0;
	chickens_rescued = 0;
	tweedy.we_just_hit_something = FALSE;
	dogchaseFrameCounter = 0;
	dogchaseState = DC_BRIEFING;
	tweedy.balance = MAXBALANCE/2;
	tweedy.randommov = 0;
	tweedy.desiredlarmangle = 0;
	tweedy.desiredrarmangle = 0;
	tweedy.larmmovingup=0;
	tweedy.larmmovingdown=0;
	tweedy.rarmmovingup=0;
	tweedy.rarmmovingdown=0;
	tweedy.balancemov = 0;
	tweedy.endtimer=20;

	controlstuff.bar_top = 69;
	controlstuff.bar_left = -99;
	controlstuff.bar_height = 14;
	bubbletimer = 0;

	//----------------------------------------
	// Zero the timer
	//----------------------------------------

	dogchaseFrameCounter = 0;
	dogchaseTimer.minutes = 0;
	dogchaseTimer.tensseconds = 0;
	dogchaseTimer.seconds = 0;
	dogchaseTimer.tenths = 0;
	dogchaseTimer.hundredths = 0;	

	//----------------------------------------
	// Load and initialise the map
	//----------------------------------------

//	DB("DogChase Load\n");
//	memoryShow();

//	EXLIGHT_Initialise();
	mapviewLoadMap("A1_DOGCHASE");								
	setupCollision("A1_DOGCHASE");								
	EXLIGHT_PostBFF();
	
	foot1 = sfxFindSampleInAllBanks("foot1");
	ASSERT(foot1);

	foot2 = sfxFindSampleInAllBanks("foot2");
	ASSERT(foot2);

	mannequinsounds[0] = sfxFindSampleInAllBanks("in_game_babs_00");	//"ing_01a");		// oh, ginger
	VERIFY(mannequinsounds[0]);

	mannequinsounds[1] = sfxFindSampleInAllBanks("in_game_babs_03");	//"ing_04c");		// sorry!
	VERIFY(mannequinsounds[1]);

	mannequinsounds[2] = sfxFindSampleInAllBanks("in_game_babs_04");	//"ing_05a");		// where're we going
	VERIFY(mannequinsounds[2]);

	mannequinsounds[3] = sfxFindSampleInAllBanks("in_game_babs_05");	//"ing_06a");		// its hot in here
	VERIFY(mannequinsounds[3]);

	mannequinsounds[4] = sfxFindSampleInAllBanks("in_game_babs_08");	//"ing_09a");		// are we nearly there yet
	VERIFY(mannequinsounds[4]);

	mannequinsounds[5] = sfxFindSampleInAllBanks("in_game_babs_09");	//"ing_10a");		// are we half way yet
	VERIFY(mannequinsounds[5]);

	mannequinsounds[6] = sfxFindSampleInAllBanks("in_game_babs_10");	//"ing_11a");		// i need the toilet
	VERIFY(mannequinsounds[6]);

	mannequinsounds[7] = sfxFindSampleInAllBanks("in_game_babs_13");	//"ing_14b");		// can we stop yet?
	VERIFY(mannequinsounds[7]);

	mannequinsounds[8] = sfxFindSampleInAllBanks("in_game_babs_15");	//"ing_16b");		// are we going on holiday?
	ASSERT(mannequinsounds[8]);

	mannequinsounds[9] = sfxFindSampleInAllBanks("in_game_babs_16");	//"ing_17c");		// she started it
	ASSERT(mannequinsounds[9]);

	mannequinsounds[10] = sfxFindSampleInAllBanks("egg_laying_bunty_06");	//"ing_bunty_13b");	// come on girls
	ASSERT(mannequinsounds[10]);

	mannequinsounds[11] = sfxFindSampleInAllBanks("egg_laying_bunty_18");	//"ing_bunty_25a");	// you're standin on me leg
	ASSERT(mannequinsounds[11]);

	mannequinsounds[12] = sfxFindSampleInAllBanks("in_game_ginger_39");		//"ing_ginger_43a"); stop it
	ASSERT(mannequinsounds[12]);

	mannequinsounds[13] = sfxFindSampleInAllBanks("in_game_ginger_40");		//"ing_ginger_44a"); left
	ASSERT(mannequinsounds[13]);

	mannequinsounds[14] = sfxFindSampleInAllBanks("in_game_ginger_40");		//"ing_ginger_44a");	// left
	ASSERT(mannequinsounds[14]);

	mannequinsounds[15] = sfxFindSampleInAllBanks("in_game_ginger_41");		//"ing_ginger_45a");	// right
	ASSERT(mannequinsounds[15]);

	mannequinsounds[16] = sfxFindSampleInAllBanks("in_game_ginger_42");		//"ing_ginger_46a");	// faster
	ASSERT(mannequinsounds[16]);

	mannequinsounds[17] = sfxFindSampleInAllBanks("in_game_ginger_43");		//"ing_ginger_47a");	// we'll have to work together
	ASSERT(mannequinsounds[17]);

	mannequinsounds[18] = sfxFindSampleInAllBanks("in_game_ginger_45");		//"ing_ginger_49a");	// they're gaining
	ASSERT(mannequinsounds[18]);

	mannequinsounds[19] = sfxFindSampleInAllBanks("in_game_ginger_49");		//"ing_ginger_53a");	// stop that
	ASSERT(mannequinsounds[19]);

	mannequinsounds[20] = sfxFindSampleInAllBanks("in_game_ginger_50");		//"ing_ginger_54b");	// ow, babs will you be careful with those knitting needles
	ASSERT(mannequinsounds[20]);

	mannequinsounds[21] = sfxFindSampleInAllBanks("in_game_ginger_38");		//"ing_ginger_58a");	// ow, get your foot out of my eye (ENG) will you lot quieten down? (EU)
	ASSERT(mannequinsounds[21]);

	mannequinsounds[22] = sfxFindSampleInAllBanks("in_game_ginger_82");		//"ing_ginger_87b");	// we're getting nowhere
	ASSERT(mannequinsounds[22]);

	mannequinsounds[23] = sfxFindSampleInAllBanks("in_game_ginger_37");		//"ing_ginger_41a");	// we're back inside the farm
	ASSERT(mannequinsounds[23]);

	mannequinsounds[24] = sfxFindSampleInAllBanks("egg_laying_bunty_21");		//"ing_bunty_28a");	// is that one of you're bloobin needles?
	ASSERT(mannequinsounds[24]);

	mannequinsounds[25] = sfxFindSampleInAllBanks("egg_laying_bunty_16");		//"ing_bunty_03c");	// oh, watch out (ENG) budge over (EU)
	ASSERT(mannequinsounds[25]);

	dogsounds[0] = sfxFindSampleInAllBanks("dogbark1");
	ASSERT(dogsounds[0]);

	dogsounds[1] = sfxFindSampleInAllBanks("dogbark2");
	ASSERT(dogsounds[1]);

	dogsounds[2] = sfxFindSampleInAllBanks("dogbark3");
	ASSERT(dogsounds[2]);

	dogsounds[3] = sfxFindSampleInAllBanks("dogwalks1");
	ASSERT(dogsounds[3]);

	othersounds[0] = sfxFindSampleInAllBanks("cluck");
	ASSERT(othersounds[0]);

	othersounds[1] = sfxFindSampleInAllBanks("clucking");
	ASSERT(othersounds[1]);

	othersounds[2] = sfxFindSampleInAllBanks("hitground1");
	ASSERT(othersounds[2]);

	othersounds[3] = sfxFindSampleInAllBanks("metalgate1");
	ASSERT(othersounds[3]);

	othersounds[4] = sfxFindSampleInAllBanks("metalgate2");
	ASSERT(othersounds[4]);

	othersounds[5] = sfxFindSampleInAllBanks("ouch_05");
	ASSERT(othersounds[5]);

	othersounds[6] = sfxFindSampleInAllBanks("owl");
	ASSERT(othersounds[6]);


	//-----------------------
	// Stuff for the casual chickens
	//-----------------------

	for(i=0;i<MAX_CHICKENS;i++)
	{
		dogchaseChickens[i].speed = 0;
		dogchaseChickens[i].status = DEAD;
	}

	//----------------------------------------
	// Load and initialise the doors
	//----------------------------------------

	doorl_model = BFF_IsModelLoaded("LEFTDOOR");
	ASSERT(doorl_model);

	doorr_model = BFF_IsModelLoaded("RIGHTDOOR");
	ASSERT(doorr_model);

	door1.actor = actorCreate(doorl_model);
	ASSERT(door1.actor);

	door2.actor = actorCreate(doorl_model);
	ASSERT(door2.actor);

	door3.actor = actorCreate(doorr_model);
	ASSERT(door3.actor);

	door4.actor = actorCreate(doorr_model);
	ASSERT(door4.actor);

	actorInitAnim(door1.actor);										
	actorInitAnim(door2.actor);										
	actorInitAnim(door3.actor);										
	actorInitAnim(door4.actor);										

	actorSetAnimSpeed(door1.actor, door1.speed);
	actorSetAnimSpeed(door2.actor, door2.speed);
	actorSetAnimSpeed(door3.actor, door3.speed);
	actorSetAnimSpeed(door4.actor, door4.speed);

	actorAnimate(door1.actor, 0, 1, 0, door1.speed, 1, 0);
	actorAnimate(door2.actor, 0, 1, 0, door2.speed, 1, 0);
	actorAnimate(door3.actor, 0, 1, 0, door3.speed, 1, 0);
	actorAnimate(door4.actor, 0, 1, 0, door4.speed, 1, 0);

	door1.actor->position.vy = -800; 
	door1.actor->position.vx = 2580; 
	door1.actor->position.vz = -30820;		
	
	door2.actor->position.vy = -800; 
	door2.actor->position.vx = 2580; 
	door2.actor->position.vz = -36460;		

	door3.actor->position.vy = 30; 
	door3.actor->position.vx = 5550; 
	door3.actor->position.vz = -65970;		

	door4.actor->position.vy = 30; 
	door4.actor->position.vx = 5550; 
	door4.actor->position.vz = -71600;	
	
	doorcolour = 512;

	door1.status =door2.status = door3.status = door4.status = CLOSED;

	endgate_model = BFF_IsModelLoaded("ENDGATE");
	ASSERT(endgate_model);

	endgate_actor = actorCreate(endgate_model);
	ASSERT(endgate_actor);

	actorInitAnim(endgate_actor);										
	actorAnimate(endgate_actor, 0, 1, 0, 0, 1, 0);

	endgate_actor->position.vx = -2400;
	endgate_actor->position.vy = -100;
	endgate_actor->position.vz = -101460;

	door1.speed = door2.speed = door3.speed = door4.speed = 0;


	//----------------------------------------
	// Load and initialise the mannequin
	//----------------------------------------

	tweedy.model = BFF_IsModelLoaded("MANNEQUIN");
	ASSERT(tweedy.model);

	tweedy.actor = actorCreate(tweedy.model);
	ASSERT(tweedy.actor);

	actorInitAnim(tweedy.actor);	
	ASSERT(tweedy.actor);
	
	tweedy.actor->position.vx = -540;
	tweedy.actor->position.vy = -620;
	tweedy.actor->position.vz = 1800;
	tweedy.collision->pPos = &tweedy.actor->position;
	tweedy.collision->pVel = NULL;
	tweedy.collision->bounce = 0;
	tweedy.collision->radius = 4096 * 30;
//	debugPrintf("Tweedy collision x: %d  y: %d   z: %d\n",tweedy.collision->pPos->vx,tweedy.collision->pPos->vy,tweedy.collision->pPos->vz);
#ifdef DREAMCAST
	tweedy.collision->pCollBox = enemyGlobals.pCollBoxes;
#endif

	tweedy.enemyStruc.readData.pModel = tweedy.model;	
	tweedy.enemyStruc.readData.pActor = tweedy.actor;	
	enemyPlaceAt(&tweedy.enemyStruc, tweedy.actor->position.vx, tweedy.actor->position.vy, tweedy.actor->position.vz);

	tweedy.actualspeed.vx = 0;
	tweedy.actualspeed.vz = 0;
	tweedy.desiredspeed.vx = 0;
	tweedy.desiredspeed.vy = 0;

	tweedy.timer = 0;

	tweedy.desiredangle = 0;
	tweedy.animsegment = TWEEDY_IDLE;
	actorAnimate(tweedy.actor, tweedy.animsegment, 1, 0, 128, 1, 0);

	
	//----------------------------------------
	// Load and initialise doggy2
	//----------------------------------------
	
	// Load the model

	doggy1.model = BFF_IsModelLoaded("DOG01");
	ASSERT(doggy1.model);

	doggy2.actor = actorCreate(doggy1.model);
	ASSERT(doggy2.actor);

	actorInitAnim(doggy2.actor);

	doggy2.animsegment = DOG_SITTING;
	
	doggy2.nextwaypoint = 0;
	
	doggy2.zdist = doggy2.position.vz - dog2waypoints[doggy2.nextwaypoint][1];
	doggy2.xdist = doggy2.position.vx - dog2waypoints[doggy2.nextwaypoint][0];
	doggy2.zstep = doggy2.zdist<<4/dog2waypoints[doggy2.nextwaypoint][2];
	doggy2.xstep = doggy2.xdist<<4/dog2waypoints[doggy2.nextwaypoint][2];

	doggy2.actor->psiData.object->rotate.vy=0;

	doggy2.animspeed = 0;

	doggy2.state = DOG_RUNNING;

	actorAnimate(doggy2.actor, doggy2.animsegment, 1, 0, doggy2.animspeed, 1, 0);

	doggy2.position.vx = dog2waypoints[0][0];
	doggy2.position.vy = 120;
	doggy2.position.vz = dog2waypoints[0][1];

	doggy2.actor->position.vy = doggy2.position.vy; 
	doggy2.actor->position.vx = doggy2.position.vx; 
	doggy2.actor->position.vz = doggy2.position.vz;


	//-------------------------------
	// load and initialise doggy 1
	//-------------------------------

	doggy1.actor = actorCreate(doggy1.model);
	ASSERT(doggy1.actor);
	actorInitAnim(doggy1.actor);										

	doggy1.animsegment = DOG_SITTING;

	doggy1.animspeed = 0;

	doggy1.position.vx = dog1waypoints[0][0];
	doggy1.position.vy = 120;
	doggy1.position.vz = dog1waypoints[0][1];

	doggy1.actor->position.vy = doggy1.position.vy; 
	doggy1.actor->position.vx = doggy1.position.vx; 
	doggy1.actor->position.vz = doggy1.position.vz;

	doggy1.nextwaypoint = 0;
	
	doggy1.zdist = doggy1.position.vz - dog1waypoints[doggy1.nextwaypoint][1];
	doggy1.xdist = doggy1.position.vx - dog1waypoints[doggy1.nextwaypoint][0];
	doggy1.zstep = doggy1.zdist<<4/dog1waypoints[doggy1.nextwaypoint][2];
	doggy1.xstep = doggy1.xdist<<4/dog1waypoints[doggy1.nextwaypoint][2];

	doggy1.actor->psiData.object->rotate.vy=0;

	doggy1.state = DOG_RUNNING;

	actorAnimate(doggy1.actor, DOG_SITTING, 1, 0, doggy1.animspeed, 1, 0);


	//----------------------------------------
	// Get pointers to the additional textures
	//----------------------------------------

	bar1 = textureFindInAllBanks("BALANCE");
	ASSERT(bar1);

	bar2 = textureFindInAllBanks("OVERLAY");
	ASSERT(bar2);

	bar3 = textureFindInAllBanks("BAR3");
	ASSERT(bar3);
	
	bar4 = textureFindInAllBanks("SPIRITBACK");
	ASSERT(bar4);
	
	bar5 = textureFindInAllBanks("BUBBLE");
	ASSERT(bar5);

#ifdef DREAMCAST
	incirclespr = textureFindInAllBanks("B_BUTTONIN");
#else
  #ifdef _WINDOWS
	outcirclespr = textureFindInAllBanks("PCBUT_3");
	incirclespr = textureFindInAllBanks("PCBUT_3D");
  #else
	incirclespr = textureFindInAllBanks("INCIRCLE");
  #endif
#endif
	ASSERT(incirclespr);

#ifdef DREAMCAST
	insquarespr = textureFindInAllBanks("X_BUTTONIN");
#else
  #ifdef _WINDOWS
	outsquarespr = textureFindInAllBanks("PCBUT_1");
	insquarespr = textureFindInAllBanks("PCBUT_1D");
  #else
	insquarespr = textureFindInAllBanks("INSQUARE");
  #endif
#endif
	ASSERT(insquarespr);

	bubble1 = textureFindInAllBanks("BUBBLE1");
	ASSERT(bubble1);

	bubble2 = textureFindInAllBanks("BUBBLE2");
	ASSERT(bubble2);

	bubble3 = textureFindInAllBanks("BUBBLE3");
	ASSERT(bubble3);

	bubble4 = textureFindInAllBanks("BUBBLE4");
	ASSERT(bubble4);
	
	bubble5 = textureFindInAllBanks("BUBBLE5");
	ASSERT(bubble5);

	bubble6 = textureFindInAllBanks("BUBBLE6");
	ASSERT(bubble6);

	bar5 = bubble1;
	// Get pointers to all the chicken sprites

	chickensprites[0] = textureFindInAllBanks("CHICKR1");
	ASSERT(chickensprites[0]);
	chickensprites[1] = textureFindInAllBanks("CHICKR2");
	ASSERT(chickensprites[1]);
	chickensprites[2] = textureFindInAllBanks("CHICKR3");
	ASSERT(chickensprites[2]);
	chickensprites[3] = textureFindInAllBanks("CHICKR4");
	ASSERT(chickensprites[3]);
	chickensprites[4] = textureFindInAllBanks("CHICKR5");
	ASSERT(chickensprites[4]);
	chickensprites[5] = textureFindInAllBanks("CHICKR6");
	ASSERT(chickensprites[5]);
	chickensprites[6] = textureFindInAllBanks("CHICKR7");
	ASSERT(chickensprites[6]);
	chickensprites[7] = textureFindInAllBanks("CHICKR8");
	ASSERT(chickensprites[7]);
	chickensprites[8] = textureFindInAllBanks("CHICKR9");
	ASSERT(chickensprites[8]);
	chickensprites[9] = textureFindInAllBanks("CHICKR10");
	ASSERT(chickensprites[9]);
	chickensprites[10] = textureFindInAllBanks("CHICKR11");
	ASSERT(chickensprites[10]);
	chickensprites[11] = textureFindInAllBanks("CHICKR12");
	ASSERT(chickensprites[11]);
	chickensprites[12] = textureFindInAllBanks("CHICKR13");
	ASSERT(chickensprites[12]);
	chickensprites[13] = textureFindInAllBanks("CHICKR14");
	ASSERT(chickensprites[13]);
	chickensprites[14] = textureFindInAllBanks("CHICKR15");
	ASSERT(chickensprites[14]);
	chickensprites[15] = textureFindInAllBanks("CHICKR16");
	ASSERT(chickensprites[15]);
	chickensprites[16] = textureFindInAllBanks("CHICKR17");
	ASSERT(chickensprites[16]);
	chickensprites[17] = textureFindInAllBanks("CHICKR18");
	ASSERT(chickensprites[17]);
	chickensprites[18] = textureFindInAllBanks("CHICKR19");
	ASSERT(chickensprites[18]);
	chickensprites[19] = textureFindInAllBanks("CHICKR20");
	ASSERT(chickensprites[19]);
	chickensprites[20] = textureFindInAllBanks("CHICKR21");
	ASSERT(chickensprites[20]);
	chickensprites[21] = textureFindInAllBanks("CHICKR22");
	ASSERT(chickensprites[21]);

	//---------------------------------------
	// Initialise the dust
	//---------------------------------------

	dustspr[0] = textureFindInAllBanks("DUST1");
	ASSERT(dustspr[0]);

	dustspr[1] = textureFindInAllBanks("DUST2");
	ASSERT(dustspr[1]);

	dustspr[2] = textureFindInAllBanks("DUST3");
	ASSERT(dustspr[2]);

	dustspr[3] = textureFindInAllBanks("DUST4");
	ASSERT(dustspr[3]);

	for(i=0;i<MAX_DUST;i++)
	{
		mydust[i].counter=0;
		mydust[i].position.vx=0;
		mydust[i].position.vy=0;
		mydust[i].position.vz=0;
	}

	active_dustbits = 0;

	//----------------------------------------
	// Do the rest of the stuff (set up camera, set colours etc etc)
	//----------------------------------------

	actorInitialise();

	PSImodelctrl.farclip = 1024;

	GsSetProjection(DOGCHASE_PROJECTION);

	DC_fadecol = 0x00000000;
	dogchaseState = DC_BRIEFING;
	draw_routine = dogchaseDraw;
	cycle_routine = dogchaseCycle;
	
	
	initCamera();
	changeCamMode(RAILCAM);

	camVars.targetEnemy = &tweedy.enemyStruc;	
	camVars.lookDistance = 5500;			// Camera's distance from the tweedy
	camVars.currentRailCamNum = 0;
	camVars.currentRailPoint = 0;
	camVars.currentRailDist = 0;
	camVars.railCamDirection = -1;
	camVars.railTargetRail = TRUE;
	camVars.railCamYOffset = 250;

	dogchase_fma_world = (void *)BFF_FindObject(BFF_FMA_WORLD2_ID,utilStr2CRC("LNDMAP"));
	ASSERT(dogchase_fma_world);
	
	dogchase_sky_world = (void *)BFF_FindObject(BFF_FMA_WORLD_ID,utilStr2CRC("SKY"));	// Should only be one world in the BFF

	PSImodelctrl.lighting = DIRECTIONONLY;
	camVars.targetEnemy = &tweedy.enemyStruc;

	// Chickens for door 1
	myvec.vx=2180;
	myvec.vy=-90;
	myvec.vz=-31000;
	dogchaseGenerateNewChicken(myvec, 70, 7000,1);

	myvec.vx-=450;
	myvec.vz+=200;
	dogchaseGenerateNewChicken(myvec, 70, 7000,1);

	myvec.vx-=250;
	myvec.vz-=100;
	dogchaseGenerateNewChicken(myvec, 70, 7000,1);

	myvec.vx-=50;
	myvec.vz-=120;
	dogchaseGenerateNewChicken(myvec, 70, 7000,1);

	myvec.vx-=30;
	myvec.vz+=200;
	dogchaseGenerateNewChicken(myvec, 70, 7000,1);

	myvec.vx-=50;
	myvec.vz+=100;
	dogchaseGenerateNewChicken(myvec, 70, 7000,1);

	// Chickens for door 2

	myvec.vx=2180;
	myvec.vy=-90;
	myvec.vz=-36700;
	dogchaseGenerateNewChicken(myvec, 70, 7000,2);
			
	myvec.vx-=450;
	myvec.vz+=100;
	dogchaseGenerateNewChicken(myvec, 70, 7000,2);

	myvec.vx-=250;
	myvec.vz-=230;
	dogchaseGenerateNewChicken(myvec, 70, 7000,2);

	myvec.vx-=170;
	myvec.vz+=230;
	dogchaseGenerateNewChicken(myvec, 70, 7000,2);
	
	myvec.vx-=170;
	myvec.vz+=130;
	
	dogchaseGenerateNewChicken(myvec, 70, 7000,2);
	myvec.vx-=70;
	myvec.vz-=230;
	dogchaseGenerateNewChicken(myvec, 70, 7000,2);

	// Chickens for door 3

	myvec.vx=5860;
	myvec.vy=600;
	myvec.vz=-66400;
	dogchaseGenerateNewChicken(myvec, -80, 2500,3);
			
	myvec.vx+=150;
	myvec.vz-=100;
	dogchaseGenerateNewChicken(myvec, -80, 2500,3);
	
	myvec.vx+=5;
	myvec.vz+=200;
	dogchaseGenerateNewChicken(myvec, -80, 2500,3);
			
	myvec.vx+=250;
	myvec.vz+=12;
	dogchaseGenerateNewChicken(myvec, -80, 2500,3);

	myvec.vx-=350;
	myvec.vz-=100;
	dogchaseGenerateNewChicken(myvec, -80, 2500,3);
			
	myvec.vx+=50;
	myvec.vz-=300;
	dogchaseGenerateNewChicken(myvec, -80, 2500,3);

	// Chickens for door 4

	myvec.vx=5860;
	myvec.vy=600;
	myvec.vz=-72000;
	dogchaseGenerateNewChicken(myvec, -80, 2500,4);
			
	myvec.vx+=50;
	myvec.vz+=100;
	dogchaseGenerateNewChicken(myvec, -80, 2500,4);

	myvec.vx+=150;
	myvec.vz+=100;
	dogchaseGenerateNewChicken(myvec, -80, 2500,4);

	myvec.vx-=50;
	myvec.vz+=120;
	dogchaseGenerateNewChicken(myvec, -80, 2500,4);

	myvec.vx+=350;
	myvec.vz-=100;
	dogchaseGenerateNewChicken(myvec, -80, 2500,4);

	myvec.vx-=350;
	myvec.vz-=100;
	dogchaseGenerateNewChicken(myvec, -80, 2500,4);

	overlayLoadingEnd();

#ifdef DREAMCAST
	ScreenFade(0,255,20);
	keepFade = NO;
#endif
	dogchaseMoveTweedy();
}


//----------------------------
// dogchaseDraw()
//
// Draw stuff...
//----------------------------

void dogchaseDraw(void)
{	
	upDateCamera();

	max_map_ot_depth = 750;

	switch(dogchaseState)
	{
	case DC_BRIEFING:

#ifndef _WINDOWS
		dogchaseDrawOverlays();
		dogchaseDrawBriefing();
		dogchaseDrawModels();
		MapDraw_DrawFMA_World(dogchase_fma_world);
#else		
		dogchaseDrawModels();
		MapDraw_DrawFMA_World(dogchase_fma_world);
		dogchaseDrawOverlays();
		dogchaseDrawBriefing();
#endif
		break;

	case DC_STARTING:
#ifdef DREAMCAST
		if(pauseOn)
			camVars.railCamYOffset = 250;
		else
			camVars.railCamYOffset = 950;
#else
			camVars.railCamYOffset = 950;
#endif

#ifndef _WINDOWS
		dogchaseDrawOverlays();
#endif
		dogchaseDrawModels();
		MapDraw_DrawFMA_World(dogchase_fma_world);
#ifdef _WINDOWS
		dogchaseDrawOverlays();
#endif
		break;
	
	case DC_RUNNING:				// dogs going after mannequin
#ifndef _WINDOWS
		dogchaseDrawOverlays();
#endif
		dogchaseDrawModels();
		MapDraw_DrawFMA_World(dogchase_fma_world);

#ifdef _WINDOWS
		dogchaseDrawOverlays();
#endif

		break;
	
	case DC_DIED:					// mannequin caught
		break;
	
	case DC_ESCAPED:				// mannequin escaped 
		dogchaseDrawModels();
		MapDraw_DrawFMA_World(dogchase_fma_world);
		if(DC_fadecol<0xff000000)
		{
			DC_fadecol+=0x11000000;
			dogchaseFullScreenOverlayAlpha(DC_fadecol);
		}
		dogchaseDrawSuccessOverlay();
		break;					

	default:
		break;
	};
}


//-------------------------------
// dogchaseCycle()
//
// Call whatever other functions are needed depending on the state
//-------------------------------

static void dogchaseCycle(void)
{
	int increment;
	int old;
	
	if((dc_drawoverlay == FALSE) && (dogchaseState!=DC_BRIEFING))

	dogchaseFrameCounter++;		// increment each frame
		camVars.railCamYOffset = 250;

	if(dogchaseState==DC_STARTING)
	dc_timer1++;
	dogchaseUpdateState();
	dsEvent_Update();
	EXLIGHT_Update();

	if(dogchaseState == DC_BRIEFING)
	{
		tweedy.animsegment = TWEEDY_IDLE;
		if (tweedy.actor->animation.animData[0].segment!=tweedy.animsegment)	// if we're not showing the animation we want to be 
			actorAnimate(tweedy.actor, tweedy.animsegment, 1, 0, tweedy.animspeed, 1, 128);
		
		doggy1.currentangle.vy = 0;
		doggy1.desiredangle.vy = 0;
		doggy1.actor->psiData.object->rotate.vy = 0;

		doggy2.currentangle.vy = 0;
		doggy2.desiredangle.vy = 0;
		doggy2.actor->psiData.object->rotate.vy = 0;
	}

	if((dogchaseState==DC_RUNNING) ||(dogchaseState==DC_STARTING))
	{
		if(pReadPad->debounce[0] & PAD_START)
		{
			pause_levelplaying=LEVNUMBER_A1_DOGCHASE;
			pauseStart();
			return;
		}
	}

	switch(dogchaseState)
	{
	case DC_RUNNING:
		dogchaseUpdateTimer(0);
		dogchaseMoveDogs();
		if(dogchaseState==DC_DIED)		// We *could* have died here, in which case we want to break, as all the memory's been fucked
		{
			debugPrintf("In cycle routine... DC died");
			return;
		}
		dogchaseMoveTweedy();
		dogchaseMoveChickens();
		dogchaseAnimate();
		break;
	case DC_BRIEFING:
		dogchaseAnimate();
		break;	
	case DC_STARTING:
		dogchaseUpdateTimer(0);
		dogchaseMoveTweedy();
		dogchaseAnimate();
		break;
	case DC_DIED:
#ifdef DREAMCAST
		if(DC_fadecol==0xff)
		{
			//debugPrintf("Hello!");
			if(pReadPad->debounce[0] & PAD_CROSS)
			{
				//dogchaseFree();
			//	debugPrintf("Free success!");
				levflowDogchaseRestart();
			}
//SB
			if(pReadPad->debounce[0] & PAD_CIRCLE)
			{
				//dogchaseFree();
			//	debugPrintf("Free success!");
				levflowDogchaseFail();
			}
		}
#endif
		break;
	case DC_ESCAPED:
		dogchaseMoveTweedy();
		dogchaseMoveDogs();
		dogchaseAnimate();
		if(DC_fadecol==0xff000000)
			dogchaseEndSuccess();
		break;
	default:
		break;
	}
}




//------------------------------------------------
// dogchaseEndSuccess()
//
// Free memory and start act 2 FMA
//------------------------------------------------

static void dogchaseEndSuccess(void)
{
	dogchaseFree();
	levflowDogchaseSuccess();
}



//----------------------------------------
// dogchaseDrawSpeedMeter()
//
// Draw the speed / balance meter
//----------------------------------------

// RFW, I'm writing a Windows COPY of the speedo, coz otherwise it just gets IFDEF-FED to hell

#ifndef _WINDOWS
static void dogchaseDrawSpeedMeter(void)
{
	POLY_G4 *speedbar;

	if(pReadPad->debounce[0] & PAD_SQUARE)
	{
		squaretimer = 2;
	}
	else if(squaretimer>0)
	{
		squaretimer--;
	}

	if(squaretimer>0)
	{
#ifdef DREAMCAST
		overlaySprite(insquarespr,-120,71,-1,0x808080);
#else
		overlaySprite(insquarespr,-122,70,0,0x808080);
#endif
	}
	else
	{
#ifdef DREAMCAST
   		fontPrint(font, -124, 73, "@S",128,128,128);
#else
   		fontPrint(font, -124, 74, "@S",128,128,128);
#endif
	}

	if(pReadPad->debounce[0] & PAD_CIRCLE)
	{
		circletimer = 2;
	}
	else if(circletimer>0)
	{
		circletimer--;
	}

	if(circletimer>0)
	{
#ifdef DREAMCAST
		overlaySprite(incirclespr,106,71,-1,0x808080);
#else
		overlaySprite(incirclespr,104,70,0,0x808080);
#endif
	}
	else
	{
#ifdef DREAMCAST
		fontPrint(font,102,73,"@C",128 ,128 ,128);
#else
		fontPrint(font,102,74,"@C",128 ,128 ,128);
#endif
	}
  //   	fontPrint(font, -49, 91, TEXTSTR(TEXTSTR_SUB_DOG_BALANCE),96 ,96 ,128);
  #if TERRIT!=1	// Europeans... long words
	fontPrintCentred(font, 3, 91, TEXTSTR(TEXTSTR_SUB_DOG_BALANCE),96 ,96 ,128);	// Centred text, so it's ok for Euro. RFW, 25 Sep 00
  #else
	fontPrintCentred(font, 3, 94, TEXTSTR(TEXTSTR_SUB_DOG_BALANCE),96 ,96 ,128);	// Centred text, so it's ok for Euro. RFW, 25 Sep 00
  #endif

#ifdef DREAMCAST
 #if TERRIT!=1
	overlaySprite(bar3, -75, 83, 3, 0x808080);
 #else
	overlaySpriteScaled(bar3, -91, 83, 3, 0x808080,310,310);
 #endif
	overlaySprite(bar1, -125, 65, 4, 0x808080);	//-130
	overlaySprite(bar2, -91, 69, 3, 0x808080);
#else
 #if TERRIT!=1	// Europeans... long words
	overlaySprite(bar3, -75, 83, 0, 0x808080);
 #else
	overlaySpriteScaled(bar3, -91, 83, 0, 0x808080,310,310);
 #endif
	overlaySprite(bar1, -125, 65, 2, 0x808080);	//-130
	overlaySprite(bar2, -91, 69, 0, 0x808080);
#endif
	
	bubbletimer++;
	if(bubbletimer==3)
	{
		bubbletimer = 0;
		
		if(bar5==bubble1) bar5 = bubble2;
		else if(bar5==bubble2) bar5 = bubble3;
		else if(bar5==bubble3) bar5 = bubble4;
		else if(bar5==bubble4) bar5 = bubble5;
		else if(bar5==bubble5) bar5 = bubble6;
		else if(bar5==bubble6) bar5 = bubble1;
	}

#ifdef DREAMCAST
	overlayTranspSprite(bar5,controlstuff.bar_left+(tweedy.balance/6),69,4,0x808080);

	overlayTranspSprite(bar4, -91, 68,5,0x808080);
#else
	overlayTranspSprite(bar5,controlstuff.bar_left+(tweedy.balance/6),69,3,0x808080);

	overlayTranspSprite(bar4, -91, 68,4,0x808080);
#endif
}
#endif	// windows





// --- Windows version of the speedo ---
#ifdef _WINDOWS

static void dogchaseDrawSpeedMeter(void)
{
	POLY_G4 *speedbar;

	overlayTranspSprite(bar4, -91, 68,4,0x808080);
	overlayTranspSprite(bar5,controlstuff.bar_left+(tweedy.balance/6),69,3,0x808080);

	bubbletimer++;
	if(bubbletimer==3)
	{
		bubbletimer = 0;
		
		if(bar5==bubble1) bar5 = bubble2;
		else if(bar5==bubble2) bar5 = bubble3;
		else if(bar5==bubble3) bar5 = bubble4;
		else if(bar5==bubble4) bar5 = bubble5;
		else if(bar5==bubble5) bar5 = bubble6;
		else if(bar5==bubble6) bar5 = bubble1;
	}


	// Note - there's a bug in Windows in that the 3rd strip of "bar1" (It's 258 wide, & so dos-chopped into 128,128,2) isn't plotted properly

	overlaySprite(bar2, -91, 69, 0, 0x808080);
	overlaySprite(bar1, -125, 65, 2, 0x808080);	//-130


	if(gameTextLang == LANG_UK)	//#if TERRIT!=1	// Europeans... long words
		overlaySprite(bar3, -75, 83, 0, 0x808080);
	else
		overlaySpriteScaled(bar3, -91, 83, 0, 0x808080,310,310);





  //   	fontPrint(font, -49, 91, TEXTSTR(TEXTSTR_SUB_DOG_BALANCE),96 ,96 ,128);
 	if(gameTextLang == LANG_UK)	// #if TERRIT!=1	// Europeans... long words
		fontPrintCentred(font, 3, 91, TEXTSTR(TEXTSTR_SUB_DOG_BALANCE),96 ,96 ,128);	// Centred text, so it's ok for Euro. RFW, 25 Sep 00
	else
		fontPrintCentred(font, 3, 94, TEXTSTR(TEXTSTR_SUB_DOG_BALANCE),96 ,96 ,128);	// Centred text, so it's ok for Euro. RFW, 25 Sep 00

//	if(pReadPad->debounce[0] & PAD_SQUARE)
	if(DI_KEY(LEFT_BALANCE_KEY))
	{
		squaretimer = 2;
	}
	else if(squaretimer>0)
	{
		squaretimer--;
	}
	if(squaretimer>0)
	{
		overlaySprite(insquarespr,-122,70,0,0x606060);
//   		fontPrint(font, -124+1, 74+1, "@S",96,96,96);
	}
	else
	{
		overlaySprite(outsquarespr,-122,70,0,0x808080);
//   		fontPrint(font, -124, 74, "@S",128,128,128);
	}

//	if(pReadPad->debounce[0] & PAD_CIRCLE)
	if(DI_KEY(RIGHT_BALANCE_KEY))
	{
		circletimer = 2;
	}
	else if(circletimer>0)
	{
		circletimer--;
	}

	if(circletimer>0)
	{
		overlaySprite(incirclespr,104,70,0,0x606060);
//		fontPrint(font,102+1,74+1,"@C",96 ,96 ,96);
	}
	else
	{
		overlaySprite(outcirclespr,104,70,0,0x808080);
//		fontPrint(font,102,74,"@C",128 ,128 ,128);
	}
}
#endif




//---------------------------------------------------
// dogchaseMoveDogs()
//
// move the two dogs along their waypoints
//---------------------------------------------------

static void dogchaseMoveDogs(void)
{
	VECTOR v;
	int distance;

	// Work out the distance from the dog's current position to the waypoint it's headed to

	v.vx = doggy1.actor->position.vx - dog1waypoints[doggy1.nextwaypoint][0];		// X axis distance
	v.vy = 0;		// Just ignore the Y
	v.vz = doggy1.actor->position.vz - dog1waypoints[doggy1.nextwaypoint][1];		// Z axis distance

	// If it's less than 100, head off to the next waypoint

	if((Magnitude(&v)<100)&&(doggy1.nextwaypoint!=77))
	{	
		doggy1.nextwaypoint++;
	


		// Work out the distance to the next waypoint

		doggy1.zdist = doggy1.position.vz - dog1waypoints[doggy1.nextwaypoint][1];	
		doggy1.xdist = doggy1.position.vx - dog1waypoints[doggy1.nextwaypoint][0];

		// Get the step over the required number of frames (4-bit fixed point)

		doggy1.xstep = (doggy1.xdist<<4)/dog1waypoints[doggy1.nextwaypoint][2];
		doggy1.zstep = (doggy1.zdist<<4)/dog1waypoints[doggy1.nextwaypoint][2];

		// Slow the dogs down if the gates've been opened

		if(doggy1.nextwaypoint==29)
		{
//			if(door1.status!=CLOSED)
//				doggy1.zstep/=2;
		}

		else if(doggy1.nextwaypoint==35)
		{
//			if(door2.status!=CLOSED)
//				doggy1.zstep/=2;
		}

		else if(doggy1.nextwaypoint==56)
		{
//			if(door3.status!=CLOSED)
//				doggy1.zstep /=2;
		}

		// Work out the new heading

		doggy1.currentangle.vy = doggy1.actor->psiData.object->rotate.vy;
		doggy1.desiredangle.vy = (int)((calc_angle( (long) doggy1.xdist, (long) doggy1.zdist)) & 0xffff);
		
		// Set the new animation segment

		doggy1.animsegment = dog1waypoints[doggy1.nextwaypoint][3];
	
		// Generate a new dust effect

		if((doggy1.animsegment==DOG_RUNNING)||(doggy1.animsegment==DOG_JUMPING)||(doggy1.animsegment==DOG_BRAKELEFT)||(doggy1.animsegment==DOG_BRAKERIGHT))
		{
			dogchaseGenerateNewDust(doggy1.position, 500,1024);
			dogchaseGenerateNewDust(doggy1.position, 750,768);
			dogchaseGenerateNewDust(doggy1.position, 1000, 512);
		}
	}

	if(doggy1.currentangle.vy!=doggy1.desiredangle.vy)
		doggy1.currentangle.vy=enemyTendTowards(doggy1.desiredangle.vy, doggy1.currentangle.vy, 40);

	doggy1.position.vx-=doggy1.xstep>>4;
	doggy1.position.vz-=doggy1.zstep>>4;	
	
	// Stick the dog to the floor

	if((doggy1.position.vz<-41600) && (doggy1.position.vz>-45000))
	{
		if(doggy1.position.vy<900)
		doggy1.position.vy+=20;
	}

	else if(doggy1.position.vz<-45000)
		doggy1.position.vy = 900;

	// Work out the distance from the dog's current position to the next waypoint

	v.vx = doggy2.actor->position.vx - dog2waypoints[doggy2.nextwaypoint][0];		// X axis distance
	v.vy = 0;		// Just ignore the Y
	v.vz = doggy2.actor->position.vz - dog2waypoints[doggy2.nextwaypoint][1];		// Z axis distance

	if((Magnitude(&v)<100) && (doggy1.nextwaypoint!=77))
	{
		doggy2.nextwaypoint++;

		// Get the distance from the current z to the waypoint z
		doggy2.zdist = doggy2.position.vz - dog2waypoints[doggy2.nextwaypoint][1];
		doggy2.xdist = doggy2.position.vx - dog2waypoints[doggy2.nextwaypoint][0];

		// Get the step over the required number of frames (4-bit fixed point)
		doggy2.zstep = (doggy2.zdist<<4)/dog2waypoints[doggy2.nextwaypoint][2];
		doggy2.xstep = (doggy2.xdist<<4)/dog2waypoints[doggy2.nextwaypoint][2];

		// Work out the new heading
		doggy2.currentangle.vy = doggy2.actor->psiData.object->rotate.vy;
		doggy2.desiredangle.vy = (int)((calc_angle( (long) doggy2.xdist, (long) doggy2.zdist)) & 0xffff);
			
		doggy2.animsegment = dog2waypoints[doggy2.nextwaypoint][3];
	
		if((doggy1.animsegment==DOG_RUNNING)||(doggy1.animsegment==DOG_JUMPING)||(doggy1.animsegment==DOG_BRAKELEFT)||(doggy1.animsegment==DOG_BRAKERIGHT))
		{
			dogchaseGenerateNewDust(doggy2.position, 500,1024);
			dogchaseGenerateNewDust(doggy2.position, 750,768);
			dogchaseGenerateNewDust(doggy2.position, 1000, 512);
		}
	}

	if(doggy2.currentangle.vy!=doggy2.desiredangle.vy)
		doggy2.currentangle.vy=enemyTendTowards(doggy2.desiredangle.vy, doggy2.currentangle.vy, 40);

	doggy2.position.vx-=doggy2.xstep>>4;
	doggy2.position.vz-=doggy2.zstep>>4;
	
	if((doggy2.position.vz<-41600) && (doggy2.position.vz>-45000))
	{
		if(doggy2.position.vy<900)
			doggy2.position.vy+=20;
	}
	
	else if(doggy2.position.vz<-45000)
		doggy2.position.vy = 900;

		
	// If the Dog is close to the Tweedy, Set the new waypoint to the Tweedy's current position

	if(doggy1.state == DOG_JUMPING)
	{
		v.vx = doggy1.actor->position.vx - tweedy.actor->position.vx;		// X axis distance
		v.vy = doggy1.actor->position.vy - tweedy.actor->position.vy;		// Y axis distance
		v.vz = doggy1.actor->position.vz - tweedy.actor->position.vz;		// Z axis distance

		if(Magnitude(&v)<1400)
		{
			dogchaseFree();
			levflowDogchaseDied();
			debugPrintf("Returned ok");
			dogchaseState = DC_DIED;
			return;
		}
	}



	// Dog 1
	if((tweedy.actor->position.vz-doggy1.position.vz>-1500) &&(doggy1.state == DOG_RUNNING))
	{		
		// Work out the co-ordinates for the next waypoint

		v.vx = doggy1.actor->position.vx - tweedy.actor->position.vx;		// X axis distance
		v.vy = doggy1.actor->position.vy - tweedy.actor->position.vy;		// Y axis distance
		v.vz = doggy1.actor->position.vz - tweedy.actor->position.vz;		// Z axis distance

		// Now set the resulting vector as the next waypoint for this dog
	
		dog1waypoints[77][0] = doggy1.actor->position.vx - v.vx;
		dog1waypoints[77][1] = doggy1.actor->position.vz - v.vz;
		doggy1.nextwaypoint = 77;
		
		// Work out the distance to the next waypoint

		doggy1.zdist = doggy1.position.vz - dog1waypoints[doggy1.nextwaypoint][1];	
		doggy1.xdist = doggy1.position.vx - dog1waypoints[doggy1.nextwaypoint][0];

		// Get the step over the required number of frames (4-bit fixed point)

		doggy1.xstep = (doggy1.xdist<<4)/dog1waypoints[doggy1.nextwaypoint][2];
		doggy1.zstep = (doggy1.zdist<<4)/dog1waypoints[doggy1.nextwaypoint][2];

		// Work out the new heading

		doggy1.currentangle.vy = doggy1.actor->psiData.object->rotate.vy;
		doggy1.desiredangle.vy = ((int)((calc_angle( (long) doggy1.xdist, (long) doggy1.zdist)) & 0xffff));

		// Set the new animation segment and speed

		doggy1.animsegment = dog1waypoints[doggy1.nextwaypoint][3];
		doggy1.animspeed = 128;

		// Generate a new dust effect

		if((doggy1.animsegment==DOG_RUNNING)||(doggy1.animsegment==DOG_JUMPING)||(doggy1.animsegment==DOG_BRAKELEFT)||(doggy1.animsegment==DOG_BRAKERIGHT))
		{
			dogchaseGenerateNewDust(doggy1.position, 500,1024);
			dogchaseGenerateNewDust(doggy1.position, 750,768);
			dogchaseGenerateNewDust(doggy1.position, 1000, 512);
		}
// Moved to after the video play RFW. 25 Sep
//		if(doggy2.state!=DOG_JUMPING)
//			sound_XA_Start(TUNE_4_FAILED + SOUND_XA_NOLOOP);

		doggy1.state = DOG_JUMPING;
	}

	// If the Dog is close to the Tweedy, Set the new waypoint to a point midway between the Tweedy's current position and the dogs
	// and the waypoint after that to the Tweedy herself
	if(doggy2.state == DOG_JUMPING)
	{
		v.vx = doggy2.actor->position.vx - tweedy.actor->position.vx;		// X axis distance
		v.vy = doggy2.actor->position.vy - tweedy.actor->position.vy;		// Y axis distance
		v.vz = doggy2.actor->position.vz - tweedy.actor->position.vz;		// Z axis distance
		if(Magnitude(&v)<1400)
		{
			dogchaseFree();
			levflowDogchaseDied();
			debugPrintf("Returned OK\n");
			dogchaseState = DC_DIED;
			return;
		}
	}

	// Dog 2
	if((tweedy.actor->position.vz-doggy2.position.vz>-1500) &&(doggy2.state == DOG_RUNNING))
	{		
		// Work out the co-ordinates for the next waypoint

		v.vx = doggy2.actor->position.vx - tweedy.actor->position.vx;		// X axis distance
		v.vy = doggy2.actor->position.vy - tweedy.actor->position.vy;		// Y axis distance
		v.vz = doggy2.actor->position.vz - tweedy.actor->position.vz;		// Z axis distance

		// Now set the resulting vector as the next waypoint for this dog
	
		dog2waypoints[77][0] = doggy2.actor->position.vx - v.vx;
		dog2waypoints[77][1] = doggy2.actor->position.vz - v.vz;
		doggy2.nextwaypoint = 77;
		
		// Work out the distance to the next waypoint

		doggy2.zdist = doggy2.position.vz - dog2waypoints[doggy2.nextwaypoint][1];	
		doggy2.xdist = doggy2.position.vx - dog2waypoints[doggy2.nextwaypoint][0];

		// Get the step over the required number of frames (4-bit fixed point)

		doggy2.xstep = (doggy2.xdist<<4)/dog2waypoints[doggy2.nextwaypoint][2];
		doggy2.zstep = (doggy2.zdist<<4)/dog2waypoints[doggy2.nextwaypoint][2];


		// Slow the dogs down if the gates've been opened

		if(doggy2.nextwaypoint==25)
		{
//			if(door1.status!=CLOSED)
//				doggy2.zstep/=2;
		}

		else if(doggy2.nextwaypoint==31)
		{
//			if(door2.status!=CLOSED)
//				doggy2.zstep/=2;
		}

		else if(doggy2.nextwaypoint==57)
		{
//			if(door3.status!=CLOSED) 
//				doggy2.zstep /=2;
		}
		
		else if(doggy2.nextwaypoint==60)
		{
//			if(door4.status!=CLOSED)
//				doggy2.zstep/=2;
		}

		// Work out the new heading

		doggy2.currentangle.vy = doggy2.actor->psiData.object->rotate.vy;
		doggy2.desiredangle.vy = ((int)((calc_angle( (long) doggy2.xdist, (long) doggy2.zdist)) & 0xffff));

		// Set the new animation segment and speed

		doggy2.animsegment = dog2waypoints[doggy2.nextwaypoint][3];
		doggy2.animspeed = 128;
	
		// Generate a new dust effect

		if((doggy2.animsegment==DOG_RUNNING)||(doggy2.animsegment==DOG_JUMPING)||(doggy2.animsegment==DOG_BRAKELEFT)||(doggy2.animsegment==DOG_BRAKERIGHT))
		{
			dogchaseGenerateNewDust(doggy2.position, 500,1024);
			dogchaseGenerateNewDust(doggy2.position, 750,768);
			dogchaseGenerateNewDust(doggy2.position, 1000, 512);
		}

// Moved to after the video play RFW. 25 Sep
//		if(doggy1.state!=DOG_JUMPING)
//			sound_XA_Start(TUNE_4_FAILED + SOUND_XA_NOLOOP);

		doggy2.state = DOG_JUMPING;
	}
	if(utilRandomInt(1000)>950)
		soundPlaySample(dogsounds[utilRandomInt(3)], 0xffff, 800);
}


//----------------------------------------------
// dogchaseMoveTweedy()
//
// Move the Tweedy and open the doors if she's near 'em
//----------------------------------------------

static void dogchaseMoveTweedy(void)
{
//	int items_hit;
	int jxpos;
	int jypos;


	if(tweedy.timer) tweedy.timer--;

	if(tweedy.actor->position.vz>=-100000)
	{
		if(chickentalktimer)
			chickentalktimer--;
		else
		{
			chickentalktimer = sampledelay[samplelistposition];		// 2 to 4 seconds
/*
#if TERRIT==2		//BP: English sounds are 8khz
			soundPlaySample(mannequinsounds[sampleorder[samplelistposition]], 0xffff, 800);
#else				//BP: Euro sounds are 11khz
			soundPlaySample(mannequinsounds[sampleorder[samplelistposition]], 0xffff, 1100);
#endif
*/



#if TERRIT!=1	//RFW: English AND AMERICAN sounds are 8khz. 0=US, 1=EURO, 2=UK
			soundPlaySample(mannequinsounds[sampleorder[samplelistposition]], 0xffff, 800);
#else				//BP: Euro sounds are 11khz
			soundPlaySample(mannequinsounds[sampleorder[samplelistposition]], 0xffff, 1100);
#endif

			samplelistposition++;
			if(samplelistposition>20)
				samplelistposition = 0;
		}
	

		if((doggy1.state == DOG_RUNNING) && (doggy2.state==DOG_RUNNING))
		{
			int temp;

			jxpos = pReadPad->analogXS[0];
			jypos = pReadPad->analogYS[0];

			if(pReadPad->digital[0] & PAD_LEFT)
				jxpos = -4095;

			if(pReadPad->digital[0] & PAD_RIGHT)
				jxpos = 4095;

			if(pReadPad->digital[0] & PAD_UP)
				jypos = -4095;
			
			if(pReadPad->digital[0] & PAD_DOWN)
				jypos = 4095;

			if(ABS(tweedy.balance-575)<400)
				tweedy.balancemov+=jxpos/3000;

			if(tweedy.balancemov>16)
				tweedy.balancemov = 16;

			if(tweedy.balancemov<-16)
				tweedy.balancemov = -16;

			tweedy.balance+=tweedy.balancemov;
	
			if(tweedy.balance<0)
				tweedy.balance = 0;
			else if(tweedy.balance>MAXBALANCE)
				tweedy.balance = MAXBALANCE;

			if(ABS(tweedy.balance-575)>40)
				jxpos+=(tweedy.balance-575)*6;

			if(leftshouttimer)
				leftshouttimer--;
			if(rightshouttimer)
				rightshouttimer--;

			if((tweedy.balance-575)<-300)
			{
				if(!leftshouttimer)
				{
#if TERRIT!=1	//RFW: English AND AMERICAN sounds are 8khz. 0=US, 1=EURO, 2=UK
					soundPlaySample(mannequinsounds[14],0xffff,800);
#else
					soundPlaySample(mannequinsounds[14],0xffff,1100);
#endif
					leftshouttimer = 120;
				}
			}

			else if((tweedy.balance-575)>300)
			{
				if(!rightshouttimer)
				{
#if TERRIT!=1	//RFW: English AND AMERICAN sounds are 8khz. 0=US, 1=EURO, 2=UK
					soundPlaySample(mannequinsounds[15],0xffff,800);
#else
					soundPlaySample(mannequinsounds[15],0xffff,1100);
#endif
					rightshouttimer = 120;

				}
			}

			if(jxpos>4096) jxpos = 4096;
			if(jxpos<-4096) jxpos = -4096;
			if(jypos>4096) jypos = 4096;
			if(jypos<-4096) jypos = -4096;
		
			if((jxpos) || (jypos))
				tweedy.desiredangle=-((utilCalcAngle(jxpos,jypos)) & 4095);

			tweedy.desiredspeed.vx = jxpos/64;
			tweedy.desiredspeed.vz = jypos/64;
	
			if(tweedy.actualspeed.vx<tweedy.desiredspeed.vx)
			tweedy.actualspeed.vx+=4;

			else if(tweedy.actualspeed.vx>tweedy.desiredspeed.vx)
				tweedy.actualspeed.vx-=4;

			if(tweedy.actualspeed.vz<tweedy.desiredspeed.vz)
				tweedy.actualspeed.vz+=4;

			else if(tweedy.actualspeed.vz>tweedy.desiredspeed.vz)
				tweedy.actualspeed.vz-=4;
	   	}

		if((doggy1.state == DOG_JUMPING) || (doggy2.state==DOG_JUMPING))
		{
			tweedy.actualspeed.vx = 0;
			tweedy.actualspeed.vz = 0;
		}

		// Left balance - square ------------------------------------------------------------------------------------

#ifdef _WINDOWS
		if(DI_KEY(LEFT_BALANCE_KEY))
#else
		if(pReadPad->debounce[0] & PAD_SQUARE)
#endif
		{
			tweedy.balancemov -= BALANCEINCR;

			// Make sure the arm isnt moving any more
			if((tweedy.larmmovingup ==0) && (tweedy.larmmovingdown==0))
			{
				tweedy.desiredlarmangle = 768;
				tweedy.larmmovingup = 1;
			}
		}									

		// If the tweedy's arm is moving up, move it until you hit the destination then set it moving down again
		if(tweedy.larmmovingup)
		{
			PSIOBJECT *object;

			object = psiObjectScan(tweedy.actor->psiData.object, "SQUARE");

			if(object)
			{	
				if(object->rotate.vz<tweedy.desiredlarmangle)
					object->rotate.vz=enemyTendTowards(tweedy.desiredlarmangle, object->rotate.vz, 128);
			
				if(object->rotate.vz==tweedy.desiredlarmangle)
				{
					tweedy.larmmovingup=0;
					tweedy.larmmovingdown=1;
					tweedy.desiredlarmangle =0;
				}
			}
		}

		if(tweedy.larmmovingdown)
		{
			PSIOBJECT *object;

			object = psiObjectScan(tweedy.actor->psiData.object, "SQUARE");

			if(object->rotate.vz>tweedy.desiredlarmangle)
				object->rotate.vz=enemyTendTowards(tweedy.desiredlarmangle, object->rotate.vz, 256);
	
			if(object->rotate.vz==tweedy.desiredlarmangle)
				tweedy.larmmovingdown = 0;
		}


		//-----------------------------------------------------------------------------------------------------------------------------



		// Right balance - circle
#ifdef _WINDOWS
		if(DI_KEY(RIGHT_BALANCE_KEY))
#else
		if(pReadPad->debounce[0] & PAD_CIRCLE)
#endif
		{
			tweedy.balancemov += BALANCEINCR;

			// Make sure the arm isnt moving any more
			if((tweedy.rarmmovingup ==0) && (tweedy.rarmmovingdown==0))
			{
				tweedy.desiredrarmangle = 3328; //(4096-768)
				tweedy.rarmmovingup = 1;
			}
		}									

		// If the tweedy's arm is moving up, move it until you hit the destination then set it moving down again
		if(tweedy.rarmmovingup)
		{
			PSIOBJECT *object;

			object = psiObjectScan(tweedy.actor->psiData.object, "CIRCLE");

			if(object)
			{	
				if(object->rotate.vz!=tweedy.desiredrarmangle)
					object->rotate.vz=enemyTendTowards(tweedy.desiredrarmangle, object->rotate.vz, 128);
				
				if(object->rotate.vz==tweedy.desiredrarmangle)
				{
					tweedy.rarmmovingup=0;
					tweedy.rarmmovingdown=1;
					tweedy.desiredrarmangle =0;
				}
			}
		}

		if(tweedy.rarmmovingdown)
		{
			PSIOBJECT *object;

			object = psiObjectScan(tweedy.actor->psiData.object, "CIRCLE");

			if(object->rotate.vz!=tweedy.desiredrarmangle)
					object->rotate.vz=enemyTendTowards(tweedy.desiredrarmangle, object->rotate.vz, 256);
	
			if(object->rotate.vz==tweedy.desiredrarmangle)
				tweedy.rarmmovingdown = 0;
		}

		// Rotate the body bone
		{
			PSIOBJECT *object;

			object = psiObjectScan(tweedy.actor->psiData.object, "BARRY");
			if(object)
			{	
				object->rotate.vz=(((tweedy.balance-575)*3172)/4096);
			}
			else
				debugPrintf("body bone not found!\n");

		}

		// Update the animation

		if(tweedy.animsegment!=TWEEDY_COLLIDE)
		{
			if((tweedy.actualspeed.vx) ||(tweedy.actualspeed.vz))
				tweedy.animsegment = TWEEDY_WALK;

			else
				tweedy.animsegment = TWEEDY_IDLE;
	
			tweedy.actor->position.vx+=tweedy.actualspeed.vx;
			tweedy.actor->position.vz-=tweedy.actualspeed.vz;

			if(tweedy.actor->position.vz > 1800)
				tweedy.actor->position.vz = 1800;

			if(tweedy.actor->psiData.object->rotate.vy!=tweedy.desiredangle)
				tweedy.actor->psiData.object->rotate.vy=enemyTendTowards(tweedy.desiredangle, tweedy.actor->psiData.object->rotate.vy, 128);
		}

		// Update the animation speed

		if((tweedy.animsegment==TWEEDY_WALK) || (tweedy.animsegment==TWEEDY_WAVEARMS))
		{
			if(abs(tweedy.actualspeed.vz)>abs(tweedy.actualspeed.vx))
				tweedy.animspeed = abs(tweedy.actualspeed.vz*8);
			else
				tweedy.animspeed = abs(tweedy.actualspeed.vx*8);
		}

		else if(tweedy.animsegment==TWEEDY_COLLIDE)
		{
			tweedy.animspeed = 256;
		}

		else if(tweedy.animsegment== TWEEDY_IDLE)
		{
			tweedy.animspeed = 384;
		}

		actorSetAnimSpeed(tweedy.actor, tweedy.animspeed);
	
		// Update the animation

		// Play footstep sounds
		if(tweedy.actor->animation.animData[0].actualFrame==5) 
			soundPlaySample(foot1,0xffff,800);
			
		else if(tweedy.actor->animation.animData[0].actualFrame==25)
			soundPlaySample(foot2, 0xffff, 800);


		// Deal with changes in the animation
	
		if (tweedy.actor->animation.animData[0].segment!=tweedy.animsegment)	// if we're not showing the animation we want to be 
		{	
			if((tweedy.actor->animation.animData[0].segment==TWEEDY_WALK) && (tweedy.animsegment==TWEEDY_WAVEARMS))
			{
				if(tweedy.actor->animation.animData[0].actualFrame>=260)
					actorAnimate(tweedy.actor, tweedy.animsegment, 1, 0, tweedy.animspeed, 1, 128);
			}		
		
			else if((tweedy.actor->animation.animData[0].segment==TWEEDY_WAVEARMS) && (tweedy.animsegment==TWEEDY_WALK))
			{
				if(tweedy.actor->animation.animData[0].actualFrame>=332)
					actorAnimate(tweedy.actor, tweedy.animsegment, 1, 0, tweedy.animspeed, 1, 128);
			}		
			else
				actorAnimate(tweedy.actor, tweedy.animsegment, 1, 0, tweedy.animspeed, 1, 128);
		}

		// If we're on the collide anim, and it's finished, go back to the 'walk' anim
		if(tweedy.actor->animation.animData[0].actualFrame>=56)
			tweedy.animsegment = TWEEDY_WALK;

		// Collision check
	
		tweedy.enemyStruc.pos.vx=tweedy.actor->position.vx;
		if(dogchaseState==DC_BRIEFING)
			tweedy.enemyStruc.pos.vy=tweedy.actor->position.vy+168;
		else
			tweedy.enemyStruc.pos.vy=tweedy.actor->position.vy+470;

		tweedy.enemyStruc.pos.vz=tweedy.actor->position.vz;
	
		//items_hit=

		dogchaseCollision();

//		if(hitouchdelay)
//			hitouchdelay--;

		/*if((tweedy.animsegment!=TWEEDY_COLLIDE) && (!tweedy.timer))
		{
			if(tweedy.we_just_hit_something == TRUE)
			{
				if(!hitouchdelay)
				{
					soundPlaySample(othersounds[5],0xffff,800);

					//SB - replaced PALMODE since DC has a 50/60 Hz switch! Please leave!!
					if(palMode)
						hitouchdelay = 50;
					else
						hitouchdelay = 60;
				}
				
				tweedy.animsegment = TWEEDY_COLLIDE;

				tweedy.timer = FRAMESSEC*2;		// Wait for 2 seconds before we can collide with something again
				dsEvent_Add(0, 0, 1, 1200, 0, 7, NULL);
			}

			else if(items_hit>1)
			{
				dsEvent_Add(0, 0, 1, 100, 0, 2, NULL);
			}
		}*/

		if((tweedy.actor->position.vz<-31100)&&(tweedy.actor->position.vz>-31200)&&(tweedy.actor->position.vx<3660))
		{
			if(door1.status==CLOSED)
			{
				soundPlaySample(othersounds[3],0xffff,800);
				door1.status = OPENING;
				door1.speed = 256;
			}
		}

		else if((tweedy.actor->position.vz<-36800)&&(tweedy.actor->position.vz>-36900)&&(tweedy.actor->position.vx<3660))
		{
			if(door2.status==CLOSED)
			{	
				soundPlaySample(othersounds[4],0xffff,800);
				door2.status = OPENING;
				door2.speed = 256;
			}
		}

		else if((tweedy.actor->position.vz<-66440)&&(tweedy.actor->position.vz>-66540)&&(tweedy.actor->position.vx>4620))
		{
			if(door3.status==CLOSED)
			{	
				soundPlaySample(othersounds[3],0xffff,800);
				door3.status = OPENING;
				door3.speed = 256;
			}
		}

		else if((tweedy.actor->position.vz<-72080)&&(tweedy.actor->position.vz>-72180)&&(tweedy.actor->position.vx>4620))
		{
			if(door4.status==CLOSED)
			{
				soundPlaySample(othersounds[4],0xffff,800);
				door4.status = OPENING;
				door4.speed = 256;
			}
		}
	}

	else
	{
		if(tweedy.actor->position.vz>-102500)
		{
			tweedy.animsegment = 8;
			jxpos = 0;
			jypos = 2048;

			tweedy.desiredangle=0;

			tweedy.desiredspeed.vx = jxpos/64;
			tweedy.desiredspeed.vz = jypos/64;
	
			if(tweedy.actualspeed.vx<tweedy.desiredspeed.vx)
				tweedy.actualspeed.vx+=4;

			else if(tweedy.actualspeed.vx>tweedy.desiredspeed.vx)
				tweedy.actualspeed.vx-=4;

			if(tweedy.actualspeed.vz<tweedy.desiredspeed.vz)
				tweedy.actualspeed.vz+=4;

			else if(tweedy.actualspeed.vz>tweedy.desiredspeed.vz)
				tweedy.actualspeed.vz-=4;

			tweedy.balance=enemyTendTowards(575, tweedy.balance, 16);

			// Rotate the body bone
			{
				PSIOBJECT *object;

				object = psiObjectScan(tweedy.actor->psiData.object, "BARRY");

				if(object)
					object->rotate.vz=(((tweedy.balance-575)*3172)/4096);

				object = psiObjectScan(tweedy.actor->psiData.object, "CIRCLE");

				if(object)
					object->rotate.vz=enemyTendTowards(0,object->rotate.vz,8);

				object = psiObjectScan(tweedy.actor->psiData.object, "SQUARE");

				if(object)
					object->rotate.vz=enemyTendTowards(0,object->rotate.vz,8);
			}
		
			if(tweedy.actor->position.vx<-2500)
				tweedy.actor->position.vx+=8;
			if(tweedy.actor->position.vx>-2500)
				tweedy.actor->position.vx-=8;

			tweedy.actor->position.vz-=tweedy.actualspeed.vz;

			if(tweedy.actor->position.vz > 1800)
				tweedy.actor->position.vz = 1800;

			if(tweedy.actor->psiData.object->rotate.vy!=tweedy.desiredangle)
				tweedy.actor->psiData.object->rotate.vy=enemyTendTowards(tweedy.desiredangle, tweedy.actor->psiData.object->rotate.vy, 128);

			if (tweedy.actor->animation.animData[0].segment!=tweedy.animsegment)	// if we're not showing the animation we want to be 
				actorAnimate(tweedy.actor, tweedy.animsegment, 1, 0, tweedy.animspeed, 1, 128);
		}
		
		else
		{
			if(tweedy.endtimer)
			{
				tweedy.endtimer--;
				actorSetAnimSpeed(tweedy.actor,0);
			}
			
			if(!tweedy.endtimer)
			{
				if(tweedy.animsegment!=9)
#if TERRIT!=1
				soundPlaySample(mannequinsounds[23],0xffff, 800);
#else
				soundPlaySample(mannequinsounds[23],0xffff, 1100);
#endif
				tweedy.animsegment = 9;


				if(dogchaseState!=DC_ESCAPED)
					actorSetAnimSpeed(tweedy.actor,160);
				
				else
				{	
					if(door1.actor->animation.animData[0].actualFrame>=23)

					actorSetAnimSpeed(tweedy.actor,0);
				}

				if (tweedy.actor->animation.animData[0].segment!=tweedy.animsegment)	// if we're not showing the animation we want to be 
					actorAnimate(tweedy.actor, tweedy.animsegment, 0, 0, tweedy.animspeed, 0, 128);
			}
		}
	}

}



//--------------------------------------------
// dogchaseCollision()
//
// Check to see if the tweedy has collided with something and if so, is it something that 
// triggers a wobble
//--------------------------------------------

#define WINDOWS_MANNEQ_HEIGHT_ADJUST	30
static int dogchaseCollision(void)
{	
	int items_hit;
	VECTOR emptyvec;
	int i;

	if(dogchaseState==DC_ESCAPED)
		DB("Bad!\n");

	if((doggy1.state==DOG_JUMPING) ||(doggy2.state==DOG_JUMPING))
		return 0;

#ifdef DREAMCAST
	tweedy.collision_centre = -730;
#else
	tweedy.collision_centre = -680;
#endif
	tweedy.actor->position.vy-=tweedy.collision_centre;
	tweedy.collision->pPos = &tweedy.actor->position;
	tweedy.collision->pVel = &emptyvec;			// dont need this?
	tweedy.collision->bounce = 0;
	tweedy.collision->radius = 4096 * 30;
//	debugPrintf("Tweedy collision x: %d  y: %d   z: %d\n",tweedy.collision->pPos->vx,tweedy.collision->pPos->vy,tweedy.collision->pPos->vz);
	tweedy.collision->nBoxes = numCollBoxes;

#ifdef _WINDOWS
	tweedy.actor->position.vy += WINDOWS_MANNEQ_HEIGHT_ADJUST;	// RFW, forcing it above ground on the PC
#endif

	tweedy.actor->position.vy<<=9;				// scale the positions up by 512 
	tweedy.actor->position.vx<<=9;				// for the collision stuff to work
	tweedy.actor->position.vz<<=9;		


	tweedy.collision->oldPos.vx = tweedy.actor->position.vx;
	tweedy.collision->oldPos.vy = tweedy.actor->position.vy;
	tweedy.collision->oldPos.vz = tweedy.actor->position.vz;



	items_hit = collboxCheckSphere(tweedy.collision);

//	debugPrintf("Returned!");

	tweedy.we_just_hit_something = FALSE;

	tweedy.actor->position.vy>>=9;				// scale the positions back down again
	tweedy.actor->position.vx>>=9; 
	tweedy.actor->position.vz>>=9;	

#ifdef _WINDOWS
	tweedy.actor->position.vy -= WINDOWS_MANNEQ_HEIGHT_ADJUST;	// RFW, forcing it above ground on the PC
#endif

	tweedy.actor->position.vy+=tweedy.collision_centre;

	if(items_hit)
	{	
		for(i=0;i<items_hit;i++)
		{
			if(tweedy.actor->position.vz>-46000)
			{
				if((pHitData[i].pCollBox->sY+pHitData[i].pCollBox->pY)>>9==-800)
				{	
					tweedy.we_just_hit_something = TRUE;
				}
			}
			
			else 
			{
				if((pHitData[i].pCollBox->sY+pHitData[i].pCollBox->pY)>>9==0)
				{	
					tweedy.we_just_hit_something = TRUE;
				}
			}
		}
	}

	if((tweedy.actor->position.vz<-41600) && (tweedy.actor->position.vz>-45000))
		tweedy.actor->position.vy+=15;
	else	
		tweedy.actor->position.vy++;

	return items_hit;
}


//------------------------------------------
// dogchaseDrawOverlays()
//
// Draw the overlays - time, help text, speed / balance bar etc
//------------------------------------------

static void dogchaseDrawOverlays(void)
{
	int i;
	if(dogchaseState!=DC_BRIEFING)
	{
		//SB - replaced PALMODE since DC has a 50/60 Hz switch! Please leave!!
		if(palMode)
			dogchaseDrawTime(-240, -110);
		else
			dogchaseDrawTime(-240, -100);
	}
	if(dc_drawoverlay == TRUE)
	{
		dogchaseDrawSuccessOverlay();
	}
	else
	{
		dogchaseDrawSpeedMeter();
	}
	dogchaseDrawAndCheckDust();
}


//----------------------------------
// dogchaseDrawModels()
//
// Draw all the shadows and the actors and animating objects
//----------------------------------

#ifdef _WINDOWS
extern int runningHard;
#endif

static void dogchaseDrawModels(void)
{
	doggy1.actor->position.vy=doggy1.position.vy; 
	doggy1.actor->position.vx=doggy1.position.vx; 
	doggy1.actor->position.vz=doggy1.position.vz;
	doggy1.actor->psiData.object->rotate.vy = doggy1.currentangle.vy;

	doggy2.actor->position.vy=doggy2.position.vy; 
	doggy2.actor->position.vx=doggy2.position.vx; 
	doggy2.actor->position.vz=doggy2.position.vz;
	doggy2.actor->psiData.object->rotate.vy = doggy2.currentangle.vy;
	
	EXLIGHT_SetupActorLights(tweedy.actor);
	psiSetAmbient(512,512,512);

#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(tweedy.actor);
	else
		d2mActorDraw(tweedy.actor);
#else
	actorDraw(tweedy.actor);
#endif

//#ifndef _WINDOWS
	EXLIGHT_DrawShadow(tweedy.actor);
//#endif

	EXLIGHT_SetupActorLights(doggy1.actor);
	psiSetAmbient(512,512,512);
#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(doggy1.actor);
	else
		d2mActorDraw(doggy1.actor);
#else
	actorDraw(doggy1.actor);
#endif
		
	EXLIGHT_SetupActorLights(doggy2.actor);
	psiSetAmbient(512,512,512);
#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(doggy2.actor);
	else
		d2mActorDraw(doggy2.actor);
#else
	actorDraw(doggy2.actor);
#endif
	
	if((tweedy.actor->position.vz<door1.actor->position.vz+5000)&&(tweedy.actor->position.vz>door1.actor->position.vz-15000))
	{
		EXLIGHT_SetupActorLights(door1.actor);
		if(door1.status==CLOSED)
		{
			if(dogchaseFrameCounter%3==1)
			{
				if(doorcolour==512)
				{
					doorcolour = 2048;
				}
				else
				{
					doorcolour = 512;
				}
			}

			psiSetAmbient(doorcolour,doorcolour,doorcolour);
		}

#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(door1.actor);
	else
		d2mActorDraw(door1.actor);
#else
		actorDraw(door1.actor);
#endif


	}

	if((tweedy.actor->position.vz<door2.actor->position.vz+5000)&&(tweedy.actor->position.vz>door2.actor->position.vz-15000))
	{
		EXLIGHT_SetupActorLights(door2.actor);
		if(door2.status==CLOSED)
		{
			if(dogchaseFrameCounter%3==1)
			{
				if(doorcolour==512)
				{
					doorcolour = 2048;
				}
				else
				{
					doorcolour = 512;
				}
			}

			psiSetAmbient(doorcolour,doorcolour,doorcolour);
		}

#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(door2.actor);
	else
		d2mActorDraw(door2.actor);
#else
		actorDraw(door2.actor);
#endif

	}

	if((tweedy.actor->position.vz<door3.actor->position.vz+5000)&&(tweedy.actor->position.vz>door3.actor->position.vz-15000))
	{
		EXLIGHT_SetupActorLights(door3.actor);
		if(door3.status==CLOSED)
		{
			if(dogchaseFrameCounter%3==1)
			{
				if(doorcolour==512)
				{
					doorcolour = 2048;
				}
				else
				{
					doorcolour = 512;
				}
			}

			psiSetAmbient(doorcolour,doorcolour,doorcolour);
		}

#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(door3.actor);
	else
		d2mActorDraw(door3.actor);
#else
		actorDraw(door3.actor);
#endif
	}

	if((tweedy.actor->position.vz<door4.actor->position.vz+5000)&&(tweedy.actor->position.vz>door4.actor->position.vz-15000))
	{
		EXLIGHT_SetupActorLights(door4.actor);
		if(door4.status==CLOSED)
		{
			if(dogchaseFrameCounter%3==1)
			{
				if(doorcolour==512)
				{
					doorcolour = 2048;
				}
				else
				{
					doorcolour = 512;
				}
			}

			psiSetAmbient(doorcolour,doorcolour,doorcolour);
		}

#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(door4.actor);
	else
		d2mActorDraw(door4.actor);
#else
		actorDraw(door4.actor);
#endif
	}

	if(tweedy.actor->position.vz<-95500)
	{
		EXLIGHT_SetupActorLights(endgate_actor);
#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(endgate_actor);
	else
		d2mActorDraw(endgate_actor);
#else
		actorDraw(endgate_actor);
#endif
	}
}


//--------------------------------------------
// dogchaseAnimate()
//
// Update the tweedy and the dogs' and the doors' animations
//--------------------------------------------

void dogchaseAnimate(void)
{
	int i;
	VECTOR v;
	PSIOBJECT *object;

	// Turn the heads of the two dogs so that they are always looking at the mannewuin

	object = psiObjectScan(doggy1.actor->psiData.object, "HEAD");
	if(object)
	{
		int xdistance;
		int zdistance;
		int headangle;

		// Work out the distance between the dog and the tweedy in x
		doggy1.xdist = doggy1.position.vx - tweedy.actor->position.vx;

		doggy1.zdist = doggy1.position.vz - tweedy.actor->position.vz;	

		// Calculate the angle between the dog and the tweedy

		headangle = (int)((calc_angle( (long) doggy1.xdist, (long) doggy1.zdist)) & 0xffff);

		if(doggy1.actor->animation.animData[0].segment==DOG_SITTING)
			object->rotate.vz = headangle;
		else
			object->rotate.vz = 0;
	}

	object = psiObjectScan(doggy2.actor->psiData.object, "HEAD");
	if(object)
	{
		int xdistance;
		int zdistance;
		int headangle;

		// Work out the distance between the dog and the tweedy in x
		doggy2.xdist = doggy2.position.vx - tweedy.actor->position.vx;

		doggy2.zdist = doggy2.position.vz - tweedy.actor->position.vz;	

		// Calculate the angle between the dog and the tweedy

		headangle = (int)((calc_angle( (long) doggy2.xdist, (long) doggy2.zdist)) & 0xffff);

		if(doggy2.actor->animation.animData[0].segment==DOG_SITTING)
			object->rotate.vz = headangle;
		else
			object->rotate.vz = 0;
	}

	actorSetAnimSpeed(door1.actor, door1.speed);
	actorSetAnimSpeed(door2.actor, door2.speed);
	actorSetAnimSpeed(door3.actor, door3.speed);
	actorSetAnimSpeed(door4.actor, door4.speed);

	if((tweedy.actor->position.vz<door1.actor->position.vz+5000)&&(tweedy.actor->position.vz>door1.actor->position.vz-15000))
		actorMaintainAnimation(door1.actor);
	
	if((tweedy.actor->position.vz<door2.actor->position.vz+5000)&&(tweedy.actor->position.vz>door2.actor->position.vz-15000))
		actorMaintainAnimation(door2.actor);

	if((tweedy.actor->position.vz<door3.actor->position.vz+5000)&&(tweedy.actor->position.vz>door3.actor->position.vz-15000))
		actorMaintainAnimation(door3.actor);

	if((tweedy.actor->position.vz<door4.actor->position.vz+5000)&&(tweedy.actor->position.vz>door4.actor->position.vz-15000))
		actorMaintainAnimation(door4.actor);

	if(tweedy.actor->position.vz<-95000)
		actorMaintainAnimation(endgate_actor);

	if(tweedy.actor->position.vz<-101500)
	{
		if(endgate_actor->animation.animData[0].segment==0)
			actorAnimate(endgate_actor, 1, 0, 0, 256, 1, 0);

		if(dc_drawoverlay==FALSE)
		{	
			dogchasetime = dogchaseFrameCounter;
			
			// Save the best time (If it is a best time)
			if(dogchasetime<gameSaveData.best_times[TIME_DOGCHASE])
				gameSaveData.best_times[TIME_DOGCHASE] = dogchasetime;

			dc_drawoverlay = TRUE;
		}
	}

	actorMaintainAnimation(doggy1.actor);
	actorMaintainAnimation(doggy2.actor);
	actorMaintainAnimation(tweedy.actor);
	
	// Deal with the dogs' animation

	if((doggy1.animsegment!=DOG_RUNNING)&&(doggy1.actor->animation.endOfCurrentAnim))
		doggy1.animsegment=DOG_RUNNING;

	if(doggy1.actor->animation.animData[0].segment!=doggy1.animsegment)
			actorAnimate(doggy1.actor, doggy1.animsegment, 1, 0, doggy1.animspeed, 1, 512);

	if((doggy2.animsegment!=DOG_RUNNING)&&(doggy2.actor->animation.endOfCurrentAnim))
		doggy2.animsegment=DOG_RUNNING;

	if(doggy2.actor->animation.animData[0].segment!=doggy2.animsegment)
			actorAnimate(doggy2.actor, doggy2.animsegment,1, 0, doggy2.animspeed, 1, 512);
	
	dogchaseUpdateAnimations();
}


//--------------------------------------
// dogchaseUpdateAnimations()
//
// Update the actor's animations
//--------------------------------------

static void dogchaseUpdateAnimations(void)
{
	VECTOR myvec;
	int i;
	if(door1.status==OPENING)
	{
		if(door1.actor->animation.animData[0].actualFrame>=23)
		{	
			door1.status = OPEN;
			door1.speed =0;
			chickens_rescued+=6;
			
			// Start all of the chickens behind this door moving

			soundPlaySample(othersounds[1],0xffff,800);

			for(i=0;i<MAX_CHICKENS;i++)
			{
				if(dogchaseChickens[i].door==1)
					dogchaseChickens[i].speed = 70;
			}
		}
	}

	if(door2.status==OPENING)
	{
		if(door2.actor->animation.animData[0].actualFrame>=23)
		{	

			door2.status = OPEN;
			door2.speed =0;
			chickens_rescued+=6;
			
			soundPlaySample(othersounds[1],0xffff,800);
			// Start all of the chickens behind this door moving

			for(i=0;i<MAX_CHICKENS;i++)
			{
				if(dogchaseChickens[i].door==2)
					dogchaseChickens[i].speed = 70;
			}
		}
	}

	if(door3.status==OPENING)
	{
		if(door3.actor->animation.animData[0].actualFrame>=23)
		{	
			door3.status = OPEN;
			door3.speed =0;
			chickens_rescued+=6;
			
			soundPlaySample(othersounds[1],0xffff,800);

			// Start all of the chickens behind this door moving

			for(i=0;i<MAX_CHICKENS;i++)
			{
				if(dogchaseChickens[i].door==3)
					dogchaseChickens[i].speed = -70;
			}
		}
	}

	if(door4.status==OPENING)
	{
		if(door4.actor->animation.animData[0].actualFrame>=23)
		{	
			door4.status = OPEN;
			door4.speed =0;
			chickens_rescued+=6;
			
			soundPlaySample(othersounds[1],0xffff,800);

			// Start all of the chickens behind this door moving

			for(i=0;i<MAX_CHICKENS;i++)
			{
				if(dogchaseChickens[i].door==4)
					dogchaseChickens[i].speed = -70;
			}
		}
	}
}


//---------------------------------
// dogchaseUpdateTimer()
//
// Update the program timer and split it up into minutes and seconds and fractions of a second
//---------------------------------
// Theres probably a better way of doing a timer using hblanks rather than fps
static void dogchaseUpdateTimer(int x)
{
	if((tweedy.actor->position.vz<-101500) && (!x))	// If we're thru the gates, stop increasing the timer
		return;
	
	//SB - replaced PALMODE since DC has a 50/60 Hz switch! Please leave!!
	if(palMode)
	{
		dogchaseTimer.hundredths = dogchaseFrameCounter*4;
		dogchaseTimer.tenths = (dogchaseTimer.hundredths/10);
		dogchaseTimer.seconds = (dogchaseTimer.tenths/10);
		dogchaseTimer.tensseconds = (dogchaseTimer.seconds/10);
		dogchaseTimer.minutes = (dogchaseTimer.tensseconds/6);

		dogchaseTimer.hundredths = (dogchaseTimer.hundredths%10);
		dogchaseTimer.tenths = (dogchaseTimer.tenths%10);
		dogchaseTimer.seconds = (dogchaseTimer.seconds%10);
		dogchaseTimer.tensseconds = (dogchaseTimer.tensseconds%6);
	}
	else
	{
		dogchaseTimer.hundredths = (dogchaseFrameCounter*3);	// It'll be off by 3 thousandths of a second or so each frame
		dogchaseTimer.tenths = (dogchaseFrameCounter/3);
		dogchaseTimer.seconds = (dogchaseTimer.tenths/10);
		dogchaseTimer.tensseconds = (dogchaseTimer.seconds/10);
		dogchaseTimer.minutes = (dogchaseTimer.tensseconds/6);
		
		dogchaseTimer.hundredths = (dogchaseTimer.hundredths%10);
		dogchaseTimer.tenths = (dogchaseTimer.tenths%10);
		dogchaseTimer.seconds = (dogchaseTimer.seconds%10);
		dogchaseTimer.tensseconds = (dogchaseTimer.tensseconds%6);
	}
}


//---------------------------------
// dogchaseFullScreenOverlayAlpha()
//
// Draw a big, black, semi-transparent poly over the whole screen, for fade in/out
//---------------------------------

static void dogchaseFullScreenOverlayAlpha(unsigned long colour)
{	
	deathScreenAdd(colour & 0xff, colour & 0xff, colour & 0xff, SEMITRANS_SUB, 0);

}


//-----------------------------------
// Generate some new dust at position
//-----------------------------------

static void dogchaseGenerateNewDust(VECTOR position, int number, int scale)
{
	int i;

	if(active_dustbits>=MAX_DUST) return;	// no more left, sorry....

	for(i=0;mydust[i].counter!=0;i++);		// get next available
	
	mydust[i].counter = 11;
	mydust[i].position.vz = position.vz-mycamera.vpz+number;
	mydust[i].position.vx = position.vx-mycamera.vpx;
	mydust[i].position.vy = position.vy-mycamera.vpy+30;
	mydust[i].scale = scale;

	active_dustbits++;
}


//------------------------------------
// Draw the dust and check to see if it's finished - if it has, kill it
//------------------------------------

static void dogchaseDrawAndCheckDust(void)
{
	int i;

	VERT v;
#ifdef _WINDOWS
		extern int useScale2D;

		int temp;
		temp = useScale2D;
		useScale2D=0;
#endif

	for(i=0;i<MAX_DUST;i++)
	{
		if(mydust[i].counter)
		{
			Print3DSelfAlphaSprite(dustspr[3-((int)mydust[i].counter/3)], &mydust[i].position,mydust[i].scale,0x202020);
			mydust[i].counter--;
			if(!mydust[i].counter)
				active_dustbits--;
		}
	}


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

		if(dogchaseChickens[i].status==ALIVE)
		{
			v.vx = dogchaseChickens[i].position.vx - mycamera.vpx;
			v.vy = dogchaseChickens[i].position.vy - mycamera.vpy;
			v.vz = dogchaseChickens[i].position.vz - mycamera.vpz;

			if(dogchaseChickens[i].position.vz > mycamera.vpz + 100)	// RFW, close to the camera test. RQD for _WINDOWS. Handy on PSX.
			{
				if(dogchaseChickens[i].speed>0)
					Print3DSprite(chickensprites[dogchaseChickens[i].framenumber],&v, 1024, 0x505050);
				else
					Print3DSpriteFlipped(chickensprites[dogchaseChickens[i].framenumber],&v, 1024, 0x505050);
			}
		}
	}
#ifdef _WINDOWS
	useScale2D = temp;
#endif
}


//--------------------------------
// dogchaseGenerateNewChicken()
//
// Generate a new chicken sprite at position
//
//--------------------------------

static void dogchaseGenerateNewChicken(VECTOR position, int velocity, int destination, int door)
{
	int i;

	for(i=0;dogchaseChickens[i].status!=DEAD;i++){}				// get next available
	
	if(i>MAX_CHICKENS) return;
	active_chickens++;
	dogchaseChickens[i].status = ALIVE;	

	dogchaseChickens[i].position.vx = position.vx;
	dogchaseChickens[i].position.vy = position.vy;
	dogchaseChickens[i].position.vz = position.vz;
	dogchaseChickens[i].speed = 0;								// only gonna travel left to right or r to l...
	dogchaseChickens[i].destination = destination;
	dogchaseChickens[i].framenumber = abs(utilRandomInt(20));	// give it a random starting frame between 0 and 20
	dogchaseChickens[i].animcounter = 0;
	dogchaseChickens[i].door = door;
}


//---------------------------------
// dogchaseMoveChickens()
//
// move the chickens and kill em if they're at their destination
//---------------------------------

static void dogchaseMoveChickens(void)
{
	int i;
	for(i=0;i<MAX_CHICKENS;i++)
	{
		if((dogchaseChickens[i].status==ALIVE)&&(dogchaseChickens[i].speed!=0))
		{
			if(dogchaseChickens[i].door==3)
				dogchaseChickens[i].position.vz-=30;
			dogchaseChickens[i].position.vx+=dogchaseChickens[i].speed;

			// Update the animation counter

			dogchaseChickens[i].animcounter++;

			// If it's greater than 10, go to the next frame

			if(dogchaseChickens[i].animcounter>10)
			{
				dogchaseChickens[i].framenumber++;
				if(dogchaseChickens[i].framenumber>21)
					dogchaseChickens[i].framenumber = 0;
			}

			if(dogchaseChickens[i].speed>0)
			{
				if(dogchaseChickens[i].position.vx>=dogchaseChickens[i].destination)
				{
					dogchaseChickens[i].status = DEAD;
					active_chickens--;
				}
			}
		
			else if(dogchaseChickens[i].speed<0)
			{
				if(dogchaseChickens[i].position.vx<=dogchaseChickens[i].destination)
				{
					dogchaseChickens[i].status = DEAD;
					active_chickens--;
				}
			}

			// If the frame is bigger than 7, make the chicken fly up then, at 14, fly down

			if(tweedy.actor->position.vz>-45000)
			{
				if(dogchaseChickens[i].framenumber>=7)
					dogchaseChickens[i].position.vy-=30;
				if((dogchaseChickens[i].framenumber>=14)&&(dogchaseChickens[i].position.vy<-90))
					dogchaseChickens[i].position.vy+=30;
			}
			else
			{
				if(dogchaseChickens[i].framenumber>=7)
					dogchaseChickens[i].position.vy-=30;
				if((dogchaseChickens[i].framenumber>=14)&&(dogchaseChickens[i].position.vy<600))
					dogchaseChickens[i].position.vy+=30;
			}
		}
	}
}


//------------------------------------
// dogchaseUpdateState()
//
// Update the state of the dogchase
//------------------------------------

static void dogchaseUpdateState(void)
{
#ifdef DEBUG
	if(SwimCheatCycle())
	{
		dc_drawoverlay = TRUE;
		dogchaseState = DC_ESCAPED;
// Removed RFW, so it quits without a quick burst
//		sound_XA_Start(TUNE_3_COMPLETE + SOUND_XA_NOLOOP);
	}
#endif



	switch(dogchaseState)
	{
		case DC_RUNNING:
			if(tweedy.actor->animation.animData[0].actualFrame>=189)
			{
				dc_drawoverlay = TRUE;
				dogchaseState = DC_ESCAPED;
				soundPlaySample(othersounds[2],0xffff,800);

// RFW - removed, 25 Sep, becuase we're now going direct to video, rather than having a "success" overlay here. Just a quick burst of XA is a tad scrappy
//				sound_XA_Start(TUNE_3_COMPLETE + SOUND_XA_NOLOOP);
			}
		break;

		case DC_BRIEFING:
			if(pReadPad->debounce[0] & PAD_CROSS)
			{
				soundPlaySample(othersounds[6],0xffff,800);
				dogchaseState = DC_STARTING;
			}
			break;

		case DC_STARTING:
			if((dc_timer1>200)||(tweedy.actor->position.vz<0))
			{
				dogchaseState = DC_RUNNING;
				doggy1.animspeed = 256;
				doggy2.animspeed = 256;
			}
			break;
		default:
			break;
	};
}


//------------------------------------
// dogchaseDrawSuccessOverlay()
//
// Draw an overlay on a transparent poly showing how many chickens you've rescued, and your time
//------------------------------------

static void dogchaseDrawSuccessOverlay(void)
{
	int temp;
	int i;

	// For Fowler's highscore page
	if (chickens_rescued > gameSaveData.best_chickens_rescued[RESCUELEVEL_CHASE1])
		gameSaveData.best_chickens_rescued[RESCUELEVEL_CHASE1] = chickens_rescued;

	// For the end-of-level splashscreen. Since there's no replay of a successful dogchase, this IS the best
	gamePlayData->best_chickens_rescued_this_act[RESCUELEVEL_CHASE1] = chickens_rescued;



	fontCentredMultiLine(font,0,-60,320,TEXTSTR(TEXTSTR_SUB_DOG_SUCCESS1),128,128,128);
	fontCentredMultiLine(font,0,-34,320,TEXTSTR(TEXTSTR_SUB_DOG_SUCCESS2),128,128,128);
	dogchaseDrawNumber(chickens_rescued, -70, -15, 128,128,128);
	fontPrint(font,-36,-15,TEXTSTR(TEXTSTR_SUB_DOG_SUCCESS3),128,128,128);

	fontPrintRightAligned(font,23,9,TEXTSTR(TEXTSTR_SUB_DOG_TIME),128,128,128);
	dogchaseDrawTime(27,9);

	fontPrintRightAligned(font,23,25,TEXTSTR(TEXTSTR_SUB_DOG_BEST_TIME),128,128,128);
	temp = dogchaseFrameCounter;
	dogchaseFrameCounter = gameSaveData.best_times[TIME_DOGCHASE];
	dogchaseUpdateTimer(1);
	dogchaseDrawTime(27,25);
	dogchaseFrameCounter = temp;
	dogchaseUpdateTimer(1);

	overlayLine(-160,-64,160,-64,0xffffff);			// top
	overlayLine(-160,64,160,64,0x888888);			// bottom
	overlayLine(-160,-64,-160,64,0xffffff);			// left
	overlayLine(160,-64,160,64,0x888888);			// right

//	overlayAlphaBox(-160, -64, 320, 120, 40, 40,40);
	overlayAlphaBox(-160, -64, 320, 128, 40, 40,40);	// RFW 10 Oct 00. Okay, who changed to box not to match the outline?
}


//--------------------------------------
// dogchaseDrawTime()
//
// Convert the dogchaseTimer to chars and print em
//--------------------------------------

static void dogchaseDrawTime(int x, int y)
{
	char time[14]={"0:00"};

	*time = (unsigned char) dogchaseTimer.minutes+48;			// 0 is ascii 48
	*(time+2) = (unsigned char)dogchaseTimer.tensseconds+48;
	*(time+3) = (unsigned char)dogchaseTimer.seconds+48;
//	*(time+5) = (unsigned char)dogchaseTimer.tenths+48;
//	*(time+6) = (unsigned char)dogchaseTimer.hundredths+48;

	fontPrint(font,x,y,time,128,128,128);
}


//---------------------------------
// dogchaseOverlayAlpha()
//
// Draw a semi-transparent rectangle
//
//---------------------------------

static void dogchaseOverlayAlpha(int x, int y, int w, int h , unsigned long rgb, int colour)
{
	POLY_F4 *f4;
	DR_TPAGE *tp;

#ifdef _WINDOWS
	BEGINPRIM(tp, DR_TPAGE);
	setDrawTPage(tp,1,1,((colour-1)<<5));
	ENDPRIM(tp,0,DR_TPAGE);
#endif

	BEGINPRIM(f4, POLY_F4);
	setPolyF4(f4);
	f4->code = f4->code | 2;

	f4->x0=f4->x2=x;
	f4->x1=f4->x3=x+w;
	f4->y0=f4->y1=y;
	f4->y2=f4->y3=y+h;
	setRGB0(f4, rgb>>16 & 0xff, rgb>>8 & 0xff, rgb & 0xff);

	ENDPRIM(f4, 0, POLY_F4);


#ifndef _WINDOWS
	BEGINPRIM(tp, DR_TPAGE);
	setDrawTPage(tp,1,1,((colour-1)<<5));
	ENDPRIM(tp,0,DR_TPAGE);
#endif
}


//-------------------------------------
// dogchaseDrawNumber()
//
// Convert an int between 0 and 99 to a string and print it out
//
//-------------------------------------

static void dogchaseDrawNumber(int number, int x, int y, int r, int g, int b)
{
	int tens;
	int units;
	char text[2];

	text[1] = 0;	// Tsk! RFW

	if((number>99)||(number<0)) return;

	units = (int) number%10;
	number-=units;
	tens = ((int) number%100)/10;
	number-=tens;
	
	if(!tens)
	{
		*text = (unsigned char)units+48;
		fontPrint(font,x,y,text, r, g, b);
	}

	else 
	{
		*text = (unsigned char)tens+48;
		fontPrint(font,x,y,text, r, g, b);
		*text = (unsigned char)units+48;
		fontPrint(font,x+12,y,text, r, g, b);
	}
}




static void dogchaseDrawBriefing(void)
{
	int wid;

// RFW - dealing with long German text strings
	if(gameTextLang == LANG_D)
		wid = 460;
	else
		wid = 320;

#ifdef _WINDOWS
	// JH: DOGCHASE_BRIEFING_WIDTH, where the hell is it defined.  nowhere! as far as I can tell

	//dogchaseOverlayAlpha(-DOGCHASE_BRIEFING_WIDTH/2, -96, DOGCHASE_BRIEFING_WIDTH, 140, 0x000044, 0x20000060);
#endif

	fontCentredMultiLine(font,0,-88,wid-2,TEXTSTR(TEXTSTR_SUB_DOG_BRIEFING1),128,128,128);
	fontCentredMultiLine(font,0,-58,wid-2,TEXTSTR(TEXTSTR_SUB_DOG_BRIEFING2),128,128,128);
	fontCentredMultiLine(font,0,-16,wid-2,TEXTSTR(TEXTSTR_SUB_DOG_BRIEFING3),128,128,128);
	fontCentredMultiLine(font,0, 28,wid-2,TEXTSTR(TEXTSTR_SUB_DOG_BRIEFING5),128,128,128);

	overlayLine(-wid/2,-96, wid/2,-96,0xffffff);			// top
	overlayLine(-wid/2, 44, wid/2, 44,0x888888);			// bottom
	overlayLine(-wid/2,-96,-wid/2, 44,0xffffff);			// left
	overlayLine( wid/2,-96, wid/2, 44,0x888888);			// right

#ifndef _WINDOWS
	overlayAlphaBox(-(wid/2), -96, wid, 140, 30, 30,40);
#endif
}



static void dogchaseDrawDeadMessage(void)
{
// RFW - dealing with long German text strings
	int hei;
	if(gameTextLang == LANG_D)
		hei = 100;
	else
		hei = 80;


#ifdef _WINDOWS
	dogchaseOverlayAlpha(-160, -60, 320, hei, 0x000088, 0x20000080);
#endif

	fontCentredMultiLine(font,0,-46,318,TEXTSTR(TEXTSTR_SUB_DOG_FAIL1),128,128,128);
	fontCentredMultiLine(font,0,-22,318,TEXTSTR(TEXTSTR_SUB_DOG_FAIL2),128,128,128);

	overlayLine(-160,    -60, 160,     -60,0xffffff);			// top
	overlayLine(-160,-60+hei, 160, -60+hei,0x888888);			// bottom
	overlayLine(-160,    -60,-160, -60+hei,0xffffff);			// left
	overlayLine( 160,    -60, 160, -60+hei,0x888888);			// right

#ifndef _WINDOWS
	dogchaseOverlayAlpha(-160, -60, 320, hei, 0x000088, 0x20000080);
#endif
}


void dogchaseFree(void)
{
#ifdef	DREAMCAST
	if(!dogchaseClearState)
		return;

	dogchaseClearState = FALSE;
#endif

	collideFree();
	debugPrintf("Collide free ok\n");
	FREE(tweedy.collision);
	debugPrintf("tweedy.collision freed ok\n");
	actorFree(tweedy.actor);
	debugPrintf("tweedy.actor freed ok\n");
	actorFree(doggy1.actor);
	debugPrintf("doggy1.actor freed ok\n");
	actorFree(doggy2.actor);
	debugPrintf("doggy2.actor freed ok\n");
	actorFree(door1.actor);
	actorFree(door2.actor);
	actorFree(door3.actor);
	actorFree(door4.actor);
	actorFree(endgate_actor);
	doorr_model = NULL;
	doorl_model = NULL;
	tweedy.model = NULL;
	doggy1.model = NULL;
	endgate_model = NULL;

	enemyDeleteAll();

	mapviewReleaseMap();

	sound_XA_Stop();
#ifdef DREAMCAST
	noEggFade = YES;
#endif
	sound_LoadLanguageBank(gameTextLang);
#ifdef DREAMCAST
	noEggFade = NO;
#endif

}



// Re-written stuff so it doesnt crash after the FMV

void dogchaseDeadStart(void)
{
	cycle_routine = dogchaseDeadCycle;
	draw_routine = dogchaseDeadDraw;

// RFW - Moved this here 25 Sep. It used to be before the vid.
	sound_XA_Start(TUNE_4_FAILED + SOUND_XA_NOLOOP);
#ifdef DREAMCAST
	overlayLoadingEnd();
#endif
}

static void dogchaseDeadCycle(void)
{
	if(pReadPad->debounce[0] & PAD_CROSS)
		levflowDogchaseRestart();
#ifdef DREAMCAST
	else if(pReadPad->debounce[0] & PAD_CIRCLE)
#else
	else if(pReadPad->debounce[0] & PAD_TRIANGLE)
#endif
		levflowDogchaseFail();
}

static void dogchaseDeadDraw(void)
{
		dogchaseDrawDeadMessage();
}

