/*********************************************************************************************/
/*                                                                                           */
/* Inventory                                                                                 */
/*                                                                                           */
/*********************************************************************************************/

/*---------------------------------------------------------------------------
 *	Import Headers
\*--------------------------------------------------------------------------*/

#ifdef PSX_VERSION
#include "../spec_psx/typedefs.h"
#include "../spec_psx/psxinput.h"
#include "../spec_psx/picture.h"
#include "../spec_psx/specific.h"
#include "../spec_psx/gen_draw.h"
#include "../spec_psx/option.h"
#include "../spec_psx/3d_obj.h"
extern void mQuickW2VMatrix();
extern void mTranslaterXYZ(LONG, LONG, LONG);
#else
#include "../specific/standard.h"
#include "../specific/global.h"
#include "../specific/input.h"
#include "../specific/output.h"
#include "../specific/hwrender.h"
#endif

#include "objects.h"
#include "lara.h"
#include "camera.h"
#include "control.h"
#include "sound.h"
#include "inventry.h"
#include "invdata.h"
#include "invfunc.h"
#include "laramisc.h"
#include "health.h"
#include "title.h"
#include "draw.h"
#include "demo.h"
#include "savegame.h"

uchar NoInventoryItemDraw = 0;
#ifdef PSX_VERSION
#ifdef LOG
#define Log(format,args...) printf(format "\n" , ## args)
#else
#define Log(args...)
#endif
#endif

/* -------- externals */

#ifdef PC_VERSION
void DoInventoryBackground(void);
#endif

void GetGlobeMeshFlags();
void DisplayArrowText( RING_INFO *ring );

/****************************** Inventory Global Variables ***************************************/

									   // Xrot,  Yrot,   Zrot,   NameString
sint16 	GlobeLevelAngles[7][4]	=	{	{	-1536, -7936,   1536,  GT_LSLONDON		},	// India.
									{	 1024, -512,   -256,   GT_LSSPAC		},	// South Pacific.
									{	 2560,  21248, -4096,  GT_LSNEVADA		},	// Nevada.
									{	-3328,  29440,  1024,  GT_LSPERU		},	// Peru. (Extra secret level). Ha!
									{	 3072, -20992,  6400,  GT_LSLONDON		},	// London.
									{	-5120, -15360, -18688, GT_LSANTARC	},		// Antarctica.
									{	0, 0, 0, 0	},						// Back to normal.
								};

uchar 	GlobeLevelComplete[6];

sint16 NextAdventure;

sint16	GlobeXRot,GlobeYRot,GlobeZRot, GlobeLevel;
sint32	GlobeButton;
long		wrap;

sint16	Inventory_Displaying=0;
sint16	Inventory_Chosen=-1;
sint32	Inventory_ExtraData[8]={0};
sint32	Inventory_Mode=INV_TITLE_MODE;
sint32	Inventory_DemoMode=0;

#ifndef PSX_VERSION
sint16	Option_Gamma_Level = 0;
sint16	Option_Detail_Level = 255;
sint16	Option_SoundFX_Volume = 165;
sint16	Option_Music_Volume = 255;
#else
sint16	mytemp=0;
#endif

sint16	JustSaved,NewAdventureLoadGame;

sint32	idelay=0, idcount=0;
sint16	item_data=0;

#ifdef PSX_VERSION
sint16	old_iconfig;
sint16	old_VibrateOn;
#endif

/****************************** Internal Prototypes ******************************************/

void 	Construct_Inventory(void);
void	SelectMeshes(INVENTORY_ITEM *inv_item);
sint32	AnimateInventoryItem(INVENTORY_ITEM *inv_item);
void 	DrawInventoryItem(INVENTORY_ITEM *inv_item);
void	DoInventoryPicture(void);

/*********************************** FUNCTION CODE *******************************************/

sint32 Display_Inventory(sint32 inventory_mode)
{
#ifdef PSX_VERSION
	TEXTSTRING *nojoytext=NULL;
#endif
	int	demo_needed=0;
	int n,frm, busy=0, pass_open=0;
	PHD_3DPOS 	viewer;
	sint16	angle,first_time=0;
	sint32	tempSint32;
	sint16	icam2obj = CAMERA_2_RING;
	INVENTORY_ITEM	*inv_item;
	sint16	itilt = ITEM_TILT;
	IMOTION_INFO imo = {0};
	RING_INFO	ring = {0};
//	PHD_ANGLE	angles[2];
/*#ifdef GAMEDEBUG
	TEXTSTRING *tl=NULL, *tr=NULL, *bl=NULL, *br=NULL;

	tl = T_Print(0,16,0,"TL");
	tr = T_Print(0,16,0,"TR");
	T_RightAlign(tr,1);
	bl = T_Print(0,0,0,"BL");
	T_BottomAlign(bl,1);
	br = T_Print(0,0,0,"BR");
	T_RightAlign(br,1);
	T_BottomAlign(br,1);
#endif*/

/* -------- init level selector */

	if (inventory_mode == INV_LEVELSELECT_MODE)
	{
		first_time = 1;
		GetGlobeMeshFlags();

		JustSaved = NewAdventureLoadGame = 0;
		wrap = 0;
	}

	S_SetReverbType(0);

	if (inventory_mode==INV_KEYS_MODE && !inv_keys_objects)
	{
		Inventory_Chosen = -1;
#ifdef PSX_VERSION
		input &= ~IN_PAUSE;
#endif
		return(0);
	}

	if ((inventory_mode != INV_TITLE_MODE)
	&&  (inventory_mode != INV_LEVELSELECT_MODE))
	{
		XASetFadeSpeed(32);
		XAFade(0);
		CreateMonoScreen();
	}

	T_RemovePrint(ammotext);
	ammotext=NULL;

	AlterFOV(GAME_FOV*ONE_DEGREE);
	Inventory_Mode = inventory_mode;

	inv_nframes = 2;
	Construct_Inventory();

	if ((inventory_mode != INV_TITLE_MODE)
	&&  (inventory_mode != INV_LEVELSELECT_MODE))
#ifdef PSX_VERSION
//		S_InitFade( FADE_MAX,FADE_MID,1 );				// copy screen into buffer, and trigger a fade-down
#else
		S_FadeInInventory(1);														// copy screen into buffer, and trigger a fade-down
	else
		S_FadeInInventory(0);														// don't copy screen into buffer, trigger a fade from black to full
#endif

//	mn_stop_ambient_samples();                      // stop the ambient samples
//	S_SoundStopAllSamples();						// PAUL stop samples whilst in Inventry
	SOUND_Stop();

	if ((inventory_mode != INV_TITLE_MODE)
	&&  (inventory_mode != INV_LEVELSELECT_MODE))
#ifdef PSX_VERSION
	{
		XAWaitFade();
		S_CDPause();									// also pause CD tracks
	}
#else
		S_CDVolume(0);									// also pause CD tracks
#endif

	// Setup current ring according to mode
	switch (inventory_mode)
	{
		case INV_DEATH_MODE:
		case INV_SAVE_MODE:
		case INV_LOAD_MODE:
		case INV_TITLE_MODE:
			Inv_RingInit(&ring, OPTION_RING, inv_option_list, inv_option_objects, inv_option_current, &imo);
			break;
		case INV_KEYS_MODE:
			Inv_RingInit(&ring, KEYS_RING, inv_keys_list, inv_keys_objects, inv_main_current, &imo);
			break;
		case INV_LEVELSELECT_MODE:
			Inv_RingInit(&ring, LEVELSELECT_RING, inv_levelselect_list, 1, 0, &imo);
			break;
		default:
			if (inv_main_objects)
				Inv_RingInit(&ring, MAIN_RING, inv_main_list, inv_main_objects, inv_main_current, &imo);
			else
				Inv_RingInit(&ring, OPTION_RING, inv_option_list, inv_option_objects, inv_option_current, &imo);
			break;
	}

	if (inventory_mode != INV_TITLE_MODE)
		SoundEffect(111, NULL, SFX_ALWAYS);

	inv_nframes = 2;

/********************************************************************************************/
/*          START OF INVENTORY LOOP															*/
/********************************************************************************************/

	do {
		wrap += 16;
		wrap &= 255;

#ifdef PC_VERSION
		if (((inventory_mode == INV_TITLE_MODE)
		||  (inventory_mode == INV_LEVELSELECT_MODE))
		&&  (cdtrack > 0))
			S_CDLoop();
#endif

	// Calc item positions depending on qty
		Inv_RingCalcAdders(&ring, ROTATE_DURATION);

	/*********  GET INPUT ***********************************************************************/
		S_UpdateInput();

#ifdef PSX_VERSION
		if ((Inventory_Mode == INV_TITLE_MODE)
		||  (Inventory_Mode == INV_LEVELSELECT_MODE))
		{
			reset_flag=0;

			if (input & IN_PAUSE)
				input |= IN_SELECT;
		}

		if ((inventory_mode != INV_TITLE_MODE)
		&&  (inventory_mode != INV_LEVELSELECT_MODE))
			XAFade(0);	// try this in case of re triggering
#endif

	/* Demo mode overrides this input */
		if (Inventory_DemoMode)
		{
			// If demo interrupted
			if (input)
				return (gameflow.on_demo_interrupt);

			GetDemoInput();

			// If demo ends
			if (input == -1)
				return (gameflow.on_demo_end);
		}
		else
		{
			if (input)
				noinput_count=0;
		}

		inputDB = GetDebouncedInput(input);

#ifdef PC_VERSION
		/* If No Input For a while may want to quit back to Title Page again */
		if ( Inventory_Mode==INV_TITLE_MODE && !input && !inputDB)
		{
			if ( gameflow.num_demos || gameflow.noinput_timeout )
			{
				noinput_count++;
				if ( noinput_count>gameflow.noinput_time)
					reset_flag = demo_needed = 1;
			}
		}
		else
		{
			noinput_count=0;
			reset_flag = 0;
		}

		if (game_closedown)
			return (EXIT_TO_TITLE);
#endif

#ifdef PSX_VERSION
		if ( !PadConnected )                    // Some Buffoon has removed their Controller
		{
			if ( nojoytext==NULL )
			{
  				nojoytext = T_Print(0, 62, 9, GF_PSXStrings[PSSTR_NOJOY_TEXT] );
   				T_CentreH( nojoytext, 1 );
				T_FlashText(nojoytext, 1, 20);
			}
		}
		else
		{
			if ( nojoytext )
			{
				T_RemovePrint(nojoytext);
				nojoytext = NULL;
			}
		}
#endif
		if (((Inventory_Mode == INV_SAVE_MODE)
		||   (Inventory_Mode == INV_LOAD_MODE)
		||   (Inventory_Mode == INV_DEATH_MODE))
		&&   (!pass_open))
		{
			inputDB = SELECT_ITEM;
			input = 0;
		}

		if ((Inventory_Mode == INV_LEVELSELECT_MODE)
		&&  (first_time)
		&&  (!ring.imo->count))
		{
			inputDB = SELECT_ITEM;
			first_time = input = 0;
		}

//		if (Inventory_Mode==INV_LEVELSELECT_MODE && first_time && !ring.rotating)
//			inputDB =	input = IN_RIGHT;
//		else if (first_time && ring.rotating)
//			first_time = 0;

		// Frame compensated bits
		for (frm=0;frm<inv_nframes;frm++)
		{
			// update delay counter
			if (idelay)
			{
				if (idcount)
					idcount--;
				else
					idelay=0;
			}

			// do opening, closing and switching ring movements
			Inv_RingDoMotions(&ring);
		}
		ring.camera.z_pos = ring.radius+icam2obj;

/*********  SETUP 3D SYSTEM ***********************************************************************/
/*  Centre of ring is positioned at 0,0,0 and the objects rotate around the Y axis.				  */
/*  The camera is moved depending on the state of the ring and which ring is being viewed.		  */
/**************************************************************************************************/

#ifdef PC_VERSION
		S_InitialisePolyList(SIPL_DONT_CLEAR_SCREEN);	// bgnd clears it
#else
		S_InitialisePolyList();
#endif

	/*********  INSERT BACKGROUND FOR INVENTORY *******************************************************/
		if ((Inventory_Mode == INV_TITLE_MODE)
		||  (Inventory_Mode == INV_LEVELSELECT_MODE))
			DoInventoryPicture();
		else
			DrawMonoScreen(0x50, 0x50, 0x70);

		S_AnimateTextures(inv_nframes);

	/*********  SETUP VIEW FOR INVENTORY RING *********************************************************/
		// Setup world to view matrix
		Inv_RingGetView(&ring, &viewer);
		phd_GenerateW2V( &viewer );
#ifdef PSX_VERSION
		mQuickW2VMatrix();
#endif
		Inv_RingLight(&ring,0);

	/*********  INSERT ALL OBJECTS IN INVENTORY *******************************************************/
		phd_PushMatrix();
		// set centre position of ring
		phd_TranslateAbs( ring.ringpos.x_pos, ring.ringpos.y_pos, ring.ringpos.z_pos );
		phd_RotYXZ( ring.ringpos.y_rot, ring.ringpos.x_rot, ring.ringpos.z_rot );

		for ( n=0,angle=0;n<ring.number_of_objects;n++ )
		{
			inv_item = *(ring.list+n);
			if (n==ring.current_object)
			{
				/*********  THIS OBJECT IS AT FRONT OF RING ***********************************************/
				// item is at front
				for (frm=0;frm<inv_nframes;frm++)
				{
					// Frame compensated
					if (ring.rotating)
					{
#ifdef PC_VERSION
						ls_adder = LOW_LIGHT;
#endif
						if (inv_item->y_rot!=0)
						{
							if (inv_item->y_rot<0)
								inv_item->y_rot+=0x200;
							else
								inv_item->y_rot-=0x200;
						}
					}
					else if (imo.status==RNG_SELECTED ||
							 imo.status==RNG_DESELECTING ||
							 imo.status==RNG_SELECTING ||
							 imo.status==RNG_DESELECT ||
							 imo.status==RNG_CLOSING_ITEM)
					{
#ifdef PC_VERSION
						ls_adder = HIGH_LIGHT;
#endif
						if (inv_item->y_rot != inv_item->y_rot_sel)
						{
							tempSint32 = inv_item->y_rot_sel - inv_item->y_rot;
							if (tempSint32>0 && tempSint32<0x8000)
								inv_item->y_rot+=0x400;
							else
								inv_item->y_rot-=0x400;
							inv_item->y_rot &= 0xfc00;
						}
					}
					else if (ring.number_of_objects==1 || !(input&IN_LEFT || input&IN_RIGHT))
					{
#ifdef PC_VERSION
						ls_adder = HIGH_LIGHT;
#endif
						inv_item->y_rot+=0x100;
					}
				}
				if ((imo.status==RNG_OPEN || imo.status==RNG_SELECTING ||
					 imo.status==RNG_SELECTED || imo.status==RNG_DESELECTING ||
					 imo.status==RNG_DESELECT || imo.status==RNG_CLOSING_ITEM)
					 && !ring.rotating && !(input&IN_LEFT || input&IN_RIGHT))
					 RingNotActive(inv_item);
			}
			else
			{
				/*********  THIS OBJECT IS NOT AT FRONT OF RING ******************************************/
				// Non selected item
#ifdef PC_VERSION
				ls_adder = LOW_LIGHT;
#endif
				for (frm=0;frm<inv_nframes;frm++)
				{
					if (inv_item->y_rot!=0)
					{
						if (inv_item->y_rot<0)
							inv_item->y_rot+=0x100;
						else
							inv_item->y_rot-=0x100;
					}
				}
			}
			if (imo.status==RNG_OPEN || imo.status==RNG_SELECTING ||
				imo.status==RNG_SELECTED || imo.status==RNG_DESELECTING ||
				imo.status==RNG_DESELECT || imo.status==RNG_CLOSING_ITEM)
				RingIsOpen(&ring);
			else
				RingIsNotOpen(&ring);

			if (imo.status==RNG_OPENING || imo.status==RNG_CLOSING ||
				imo.status==RNG_MAIN2OPTION || imo.status==RNG_OPTION2MAIN ||
				imo.status==RNG_EXITING_INVENTORY || imo.status==RNG_DONE
				|| ring.rotating)
				RingActive();

		/*********  DRAW THIS OBJECT ***********************************************/

			phd_PushMatrix();
			phd_RotYXZ( angle, 0, 0 );			// items angle from centre of ring
			phd_TranslateRel(ring.radius, 0, 0 );	// translate by radius
			phd_RotYXZ( 0x4000, (sint16)(itilt+inv_item->pt_xrot), 0 );	// tilt item
			DrawInventoryItem(inv_item);		// draw item
			phd_PopMatrix();
			angle += ring.angle_adder;			// calc angle for next item
			angle &= 0xffff;
		}
		phd_PopMatrix();

		/*********  ALL OBJECTS HAVE BEEN INSERTED INTO DRAW LIST ************************/
		/*********  NOW INSERT TEXT AND OUTPUT TO SCREEN *********************************/
		//mn_update_sound_effects();
#ifdef PC_VERSION
		DrawModeInfo();
#endif
		T_DrawText();
		S_OutputPolyList();
		SOUND_EndScene();		// finish sorting out looping sound effects
		camera.number_frames = inv_nframes = S_DumpScreen();
		if (CurrentLevel!=LV_GYM)
			savegame.timer+=inv_nframes/2;

		/*********  RING MOVEMENT AND INDIVIDUAL ITEM CONTROL ****************************/
		// Get input if ring isn't rotating
		if (!ring.rotating )
		{
			switch (imo.status)
			{
				// ring is OPEN
				case RNG_OPEN:
#ifdef PSX_VERSION
					DisplayArrowText( &ring );
					DisplaySelectText();
					if ( Inventory_Mode!=INV_TITLE_MODE && Inventory_Mode!=INV_LEVELSELECT_MODE && Inventory_Mode!=INV_DEATH_MODE )
						DisplayDeselectText();
#endif
					// ROTATE RIGHT
			  		if ((input&ROTATE_RIGHT) && ring.number_of_objects>1)
				  	{
						Inv_RingRotateLeft(&ring);
                        		SoundEffect(108, NULL, SFX_ALWAYS);
						break;
				  	}
					// ROTATE LEFT
				  	if ((input&ROTATE_LEFT) && ring.number_of_objects>1)
			  		{
						Inv_RingRotateRight(&ring);
                        		SoundEffect(108, NULL, SFX_ALWAYS);
						break;
			  		}
					// EXIT WITHOUT CHOOSING
					if ( reset_flag || (inputDB&EXIT_INVENTORY) )
					{
						if ( reset_flag || (Inventory_Mode!=INV_TITLE_MODE && Inventory_Mode!=INV_LEVELSELECT_MODE))
						{
						    SoundEffect(112, NULL, SFX_ALWAYS);
							Inventory_Chosen = -1;
							if (ring.type==MAIN_RING)
								inv_main_current = ring.current_object;
							else
								inv_option_current = ring.current_object;

							if ( inventory_mode != INV_TITLE_MODE && inventory_mode != INV_LEVELSELECT_MODE)						// DELS!... check this with paul/jason
#ifdef PSX_VERSION
								S_InitFade( FADE_MID,FADE_MAX,0 );				// fade from MID... to MAX
#else
								S_FadeOutInventory(1);													// fade from almost min... to MAX
							else
								S_FadeOutInventory(0);													// fade from MAX to BLACK
#endif
							Inv_RingMotionSetup(&ring, RNG_CLOSING, RNG_DONE, CLOSE_FRAMES);
							Inv_RingMotionRadius(&ring, 0);
							Inv_RingMotionCameraPos(&ring, CAMERA_STARTHEIGHT);
							Inv_RingMotionRotation(&ring, CLOSE_ROTATION, (sint16)(ring.ringpos.y_rot-CLOSE_ROTATION));
							input = 0;
							inputDB = 0;
						}
					}
#ifdef PSX_VERSION
					/* Handle Kicking Off Demo from Title Page */
					if ( gameflow.num_demos && Inventory_Mode==INV_TITLE_MODE )
					{
						if ( !input && !inputDB )
						{
							noinput_count++;
							if ( noinput_count>=gameflow.noinput_time )
							{
								SoundEffect(112, NULL, SFX_ALWAYS);
								Inventory_Chosen = -1;
								if (ring.type==MAIN_RING)
									inv_main_current = ring.current_object;
								else
									inv_option_current = ring.current_object;
								Inv_RingMotionSetup(&ring, RNG_CLOSING, RNG_DONE, CLOSE_FRAMES);
								Inv_RingMotionRadius(&ring, 0);
								Inv_RingMotionCameraPos(&ring, CAMERA_STARTHEIGHT);
								Inv_RingMotionRotation(&ring, CLOSE_ROTATION, ring.ringpos.y_rot-CLOSE_ROTATION);
								input = 0;
								inputDB = 0;
								demo_needed = 1;
							}
						}
						else
						{
							noinput_count=0;
						}
					}
					else
					{
#ifdef PSX_SONY_DEMO_SHELL
						if ( !input && !inputDB )
						{
							if (noinput_count++ > gameflow.noinput_time)
								reset_flag = 1;
						}
						else
#endif
							noinput_count=0;
					}
#endif
					// SELECT AN OBJECT
					if ((inputDB&SELECT_ITEM))
					{
						if ((Inventory_Mode==INV_SAVE_MODE || Inventory_Mode==INV_LOAD_MODE || Inventory_Mode==INV_DEATH_MODE) && !pass_open)
							pass_open=1;
						item_data = 0;
						/* Choose an inventory item */
						if (ring.type==MAIN_RING)
						{
							inv_main_current = ring.current_object;
							inv_item = inv_main_list[ring.current_object];
						}
						else if (ring.type==OPTION_RING)
						{
							inv_option_current = ring.current_object;
							inv_item = inv_option_list[ring.current_object];
						}
						else if (ring.type==LEVELSELECT_RING)
						{
							inv_option_current = ring.current_object;
							inv_item = inv_levelselect_list[ring.current_object];
						}
						else
						{
							inv_keys_current = ring.current_object;
							inv_item = inv_keys_list[ring.current_object];
						}
						inv_item->goal_frame = inv_item->open_frame;
						inv_item->anim_direction = 1;

						Inv_RingMotionSetup(&ring, RNG_SELECTING, RNG_SELECTED, SELECTING_FRAMES);
						Inv_RingMotionRotation(&ring, 0, (sint16)(0xc000-(ring.current_object*ring.angle_adder)));
						Inv_RingMotionItemSelect(&ring, inv_item);
						input = 0;
						inputDB = 0;
						switch (inv_item->object_number)
						{
//							case PHOTO_OPTION:
//								SoundEffect(109, NULL, SFX_ALWAYS);
//								break;
//							case CONTROL_OPTION:
//				                SoundEffect(110, NULL, SFX_ALWAYS);
//								break;
							case MAP_OPTION:
								SoundEffect(113, NULL, SFX_ALWAYS);
								break;
//							case PASSPORT_OPTION:
//								SoundEffect(115, NULL, SFX_ALWAYS);
//								break;
							case GUN_OPTION:
							case SHOTGUN_OPTION:
							case MAGNUM_OPTION:
							case UZI_OPTION:
							case HARPOON_OPTION:
							case M16_OPTION:
							case ROCKET_OPTION:
							case GRENADE_OPTION:
								SoundEffect(114, NULL, SFX_ALWAYS);
								break;
							default:
								SoundEffect(109, NULL, SFX_ALWAYS);
								break;
						}
					}
					if (inputDB&IN_FORWARD && inventory_mode!=INV_TITLE_MODE && inventory_mode!=INV_LEVELSELECT_MODE && inventory_mode!=INV_KEYS_MODE)
					{
						if (ring.type==MAIN_RING)
						{
							if (inv_keys_objects)
							{
								// MOVE FROM MAIN RING TO KEYS RING
								Inv_RingMotionSetup(&ring, RNG_CLOSING, RNG_MAIN2KEYS, RINGSWITCH_FRAMES/2);
								Inv_RingMotionRadius(&ring, 0);
								Inv_RingMotionRotation(&ring, CLOSE_ROTATION, (sint16)(ring.ringpos.y_rot-CLOSE_ROTATION));
								Inv_RingMotionCameraPitch(&ring, 0x2000);
								imo.misc = 0x2000;
							}
							input = 0;
							inputDB = 0;
						}
						else if (ring.type==OPTION_RING)
						{
							if (inv_main_objects)
							{
								// MOVE FROM OPTION RING TO MAIN RING
								Inv_RingMotionSetup(&ring, RNG_CLOSING, RNG_OPTION2MAIN, RINGSWITCH_FRAMES/2);
								Inv_RingMotionRadius(&ring, 0);
								Inv_RingMotionRotation(&ring, CLOSE_ROTATION, (sint16)(ring.ringpos.y_rot-CLOSE_ROTATION));
								Inv_RingMotionCameraPitch(&ring, 0x2000);
								imo.misc = 0x2000;
							}
							inputDB = 0;
						}
					}
					else if (inputDB&IN_BACK && inventory_mode!=INV_TITLE_MODE && inventory_mode!=INV_LEVELSELECT_MODE && inventory_mode!=INV_KEYS_MODE)
					{
					   	if (ring.type==KEYS_RING)
					   	{
					   		if (inv_main_objects)
					   		{
					   			// MOVE FROM KEYS RING TO MAIN RING
					   			Inv_RingMotionSetup(&ring, RNG_CLOSING, RNG_KEYS2MAIN, RINGSWITCH_FRAMES/2);
					   			Inv_RingMotionRadius(&ring, 0);
					   			Inv_RingMotionRotation(&ring, CLOSE_ROTATION, (sint16)(ring.ringpos.y_rot-CLOSE_ROTATION));
					   			Inv_RingMotionCameraPitch(&ring, 0-0x2000);
					   			imo.misc = 0-0x2000;
					   		}
					   		input = 0;
					   		inputDB = 0;
					   	}
					   	else if (ring.type==MAIN_RING)
					   	{
					   		if (inv_option_objects && !gameflow.lockout_optionring)
					   		{
					   			// SWAP FROM MAIN RING TO OPTION RING
					   			Inv_RingMotionSetup(&ring, RNG_CLOSING, RNG_MAIN2OPTION, RINGSWITCH_FRAMES/2);
					   			Inv_RingMotionRadius(&ring, 0);
					   			Inv_RingMotionRotation(&ring, CLOSE_ROTATION, (sint16)(ring.ringpos.y_rot-CLOSE_ROTATION));
					   			Inv_RingMotionCameraPitch(&ring, 0-0x2000);
					   			imo.misc = 0-0x2000;
					   		}
					   		inputDB = 0;
					   	}

					}
					break;


				// ring is changing to OPTION
				case RNG_MAIN2OPTION:
					Inv_RingMotionSetup(&ring, RNG_OPENING, RNG_OPEN, RINGSWITCH_FRAMES/2);
					Inv_RingMotionRadius(&ring, RING_RADIUS);
					imo.camera_pitch_target = 0;
					ring.camera_pitch = -(sint16)imo.misc;
					imo.camera_pitch_rate = imo.misc/(RINGSWITCH_FRAMES/2);

					ring.list = inv_option_list;
					ring.type = OPTION_RING;
					inv_main_current = ring.current_object;

					ring.number_of_objects = inv_option_objects;
					ring.current_object = inv_option_current;

					// now calc rotation for new ring
					Inv_RingCalcAdders(&ring, ROTATE_DURATION);
					Inv_RingMotionRotation(&ring, OPEN_ROTATION, (sint16)(0xc000-(ring.current_object*ring.angle_adder)));
					ring.ringpos.y_rot = imo.rotate_target+OPEN_ROTATION;
					break;


				// ring is changing to MAIN
				case RNG_OPTION2MAIN:
					Inv_RingMotionSetup(&ring, RNG_OPENING, RNG_OPEN, RINGSWITCH_FRAMES/2);
					Inv_RingMotionRadius(&ring, RING_RADIUS);
					imo.camera_pitch_target = 0;
					ring.camera_pitch = -(sint16)imo.misc;
					imo.camera_pitch_rate = imo.misc/(RINGSWITCH_FRAMES/2);

					ring.list = inv_main_list;
					ring.type = MAIN_RING;
					inv_option_objects = ring.number_of_objects;
					inv_option_current = ring.current_object;

					ring.number_of_objects = inv_main_objects;
					ring.current_object = inv_main_current;

					// now calc rotation for new ring
					Inv_RingCalcAdders(&ring, ROTATE_DURATION);
					Inv_RingMotionRotation(&ring, OPEN_ROTATION, (sint16)(0xc000-(ring.current_object*ring.angle_adder)));
					ring.ringpos.y_rot = imo.rotate_target+OPEN_ROTATION;
					break;

				// ring is changing to MAIN
				case RNG_MAIN2KEYS:
					Inv_RingMotionSetup(&ring, RNG_OPENING, RNG_OPEN, RINGSWITCH_FRAMES/2);
					Inv_RingMotionRadius(&ring, RING_RADIUS);
					imo.camera_pitch_target = 0;
					ring.camera_pitch = -(sint16)imo.misc;
					imo.camera_pitch_rate = imo.misc/(RINGSWITCH_FRAMES/2);

					ring.list = inv_keys_list;
					ring.type = KEYS_RING;
					inv_main_objects = ring.number_of_objects;
					inv_main_current = ring.current_object;

					ring.number_of_objects = inv_keys_objects;
					ring.current_object = inv_keys_current;

					// now calc rotation for new ring
					Inv_RingCalcAdders(&ring, ROTATE_DURATION);
					Inv_RingMotionRotation(&ring, OPEN_ROTATION, (sint16)(0xc000-(ring.current_object*ring.angle_adder)));
					ring.ringpos.y_rot = imo.rotate_target+OPEN_ROTATION;
					break;

				case RNG_KEYS2MAIN:
					Inv_RingMotionSetup(&ring, RNG_OPENING, RNG_OPEN, RINGSWITCH_FRAMES/2);
					Inv_RingMotionRadius(&ring, RING_RADIUS);
					imo.camera_pitch_target = 0;
					ring.camera_pitch = -(sint16)imo.misc;
					imo.camera_pitch_rate = imo.misc/(RINGSWITCH_FRAMES/2);

					ring.list = inv_main_list;
					ring.type = MAIN_RING;
					inv_keys_current = ring.current_object;

					ring.number_of_objects = inv_main_objects;
					ring.current_object = inv_main_current;

					// now calc rotation for new ring
					Inv_RingCalcAdders(&ring, ROTATE_DURATION);
					Inv_RingMotionRotation(&ring, OPEN_ROTATION, (sint16)(0xc000-(ring.current_object*ring.angle_adder)));
					ring.ringpos.y_rot = imo.rotate_target+OPEN_ROTATION;
					break;

				// ring item is closing
				case RNG_CLOSING_ITEM:
					inv_item = *(ring.list+ring.current_object);
					for (frm=0;frm<inv_nframes;frm++)
					{
						if (!AnimateInventoryItem(inv_item))
						{
							// Change PASSPORT object to single mesh version
							if (inv_item->object_number==PASSPORT_OPTION)
							{
								inv_item->object_number=PASSPORT_CLOSED;
								inv_item->current_frame = 0;
							}
							imo.count = SELECTING_FRAMES;
							imo.status = imo.status_target;
							Inv_RingMotionItemDeselect(&ring, inv_item);
							break;
						}
					}
					break;
				// ring item is to be deselected
				case RNG_DESELECT:
#ifdef PSX_VERSION
					if ( Inventory_Mode==INV_TITLE_MODE || Inventory_Mode==INV_DEATH_MODE || Inventory_Mode==INV_LEVELSELECT_MODE)
						RemoveDeselectText();
#endif
					SoundEffect(112, NULL, SFX_ALWAYS);
					Inv_RingMotionSetup(&ring, RNG_DESELECTING, RNG_OPEN, SELECTING_FRAMES);
					Inv_RingMotionRotation(&ring, 0, (sint16)(0xc000-(ring.current_object*ring.angle_adder)));
					input = 0;
					inputDB = 0;
					break;
				// ring item is SELECTED
				case RNG_SELECTED:
#ifdef PSX_VERSION
					RemoveArrowText();
					DisplaySelectText();
					if ((Inventory_Mode != INV_DEATH_MODE)
					&&  (Inventory_Mode != INV_LEVELSELECT_MODE))
						DisplayDeselectText();
#endif
					inv_item = *(ring.list+ring.current_object);
					// Change PASSPORT object to animating version
					if (inv_item->object_number==PASSPORT_CLOSED)
						inv_item->object_number=PASSPORT_OPTION;
					// Do item's animation
					for (frm=0;frm<inv_nframes;frm++)
					{
						busy = 0;
						if (inv_item->y_rot == inv_item->y_rot_sel)
							busy = AnimateInventoryItem(inv_item);
					}
					// If not animating
					if (!busy && !idelay)
					{
						do_inventory_options(inv_item);

						// DESELECT THIS OBJECT
						if ((inputDB & DESELECT_ITEM))
						{
							inv_item->sprlist = NULL;
							Inv_RingMotionSetup(&ring, RNG_CLOSING_ITEM,  RNG_DESELECT, 0);
							input = 0;
							inputDB = 0;

							/* Gav: let's get out of here if user has pressed ESC */
							if (Inventory_Mode == INV_LOAD_MODE || Inventory_Mode == INV_SAVE_MODE)
							{
								Inv_RingMotionSetup(&ring, RNG_CLOSING_ITEM, RNG_EXITING_INVENTORY, 0);
								input = inputDB = 0;
							}
						}

						// SELECT THIS OBJECT AND EXIT INVENTORY
						if ( inputDB&SELECT_ITEM)
						{
							inv_item->sprlist = NULL;
							Inventory_Chosen = inv_item->object_number;
							if (ring.type==MAIN_RING)
								inv_main_current = ring.current_object;
							else
								inv_option_current = ring.current_object;

							if (Inventory_Mode == INV_LEVELSELECT_MODE)
							{
								if ((inv_item->object_number == PASSPORT_OPTION && JustSaved))
									Inv_RingMotionSetup(&ring, RNG_CLOSING_ITEM, RNG_DESELECT, 0);
								else
									Inv_RingMotionSetup(&ring, RNG_CLOSING_ITEM, RNG_EXITING_INVENTORY, 0);
								JustSaved = 0;
							}
							else if (Inventory_Mode==INV_TITLE_MODE &&
							   		(inv_item->object_number==DETAIL_OPTION ||
									inv_item->object_number==SOUND_OPTION ||
									inv_item->object_number==CONTROL_OPTION))
								Inv_RingMotionSetup(&ring, RNG_CLOSING_ITEM, RNG_DESELECT, 0);
							else
								Inv_RingMotionSetup(&ring, RNG_CLOSING_ITEM, RNG_EXITING_INVENTORY, 0);
							input = 0;
							inputDB = 0;
						}
					}
					break;
				// ring close and exit
				case RNG_EXITING_INVENTORY:
#ifdef PSX_VERSION
					RemovePromptText();
#endif
					if (!imo.count)
					{
						if ((inventory_mode != INV_TITLE_MODE)
						&&  (inventory_mode != INV_LEVELSELECT_MODE))
#ifdef PSX_VERSION
							S_InitFade( FADE_MID,FADE_MAX,0 );				// fade from MID... to MAX
#else
							S_FadeOutInventory(1);													// fade from almost min... to MAX (ingame)
						else
							S_FadeOutInventory(0);													// fade from MAX to BLACK (titlepage)
#endif
						Inv_RingMotionSetup(&ring, RNG_CLOSING, RNG_DONE, CLOSE_FRAMES);
						Inv_RingMotionRadius(&ring, 0);
						Inv_RingMotionCameraPos(&ring, CAMERA_STARTHEIGHT);
						Inv_RingMotionRotation(&ring, CLOSE_ROTATION, (sint16)(ring.ringpos.y_rot-CLOSE_ROTATION));
					}
					break;
				default:
					break;
			}
		}
		/********************************************************************************************/
		/*          END OF INVENTORY LOOP															*/
		/********************************************************************************************/

	}while(imo.status!=RNG_DONE);


#ifdef PSX_VERSION
	if ((inventory_mode != INV_TITLE_MODE)
	&&  (inventory_mode != INV_LEVELSELECT_MODE))
	{
		if ((Inventory_Chosen != PASSPORT_OPTION)
		|| ((Inventory_Chosen == PASSPORT_OPTION)
		&&  (Inventory_ExtraData[1] != -2000)))
			RemoveMonoScreen();
	}
#endif

#ifdef PC_VERSION
	if (inventory_mode != INV_TITLE_MODE && inventory_mode != INV_LEVELSELECT_MODE)
	{
		if(Inventory_Chosen != PASSPORT_OPTION)
			RemoveMonoScreen(0);
		else
		{
			if(Inventory_ExtraData[0] == 1)
				RemoveMonoScreen(0);
			else
				RemoveMonoScreen(1);
		}
	}
#endif

	RemoveInventoryText();

#ifdef PSX_VERSION
	RemovePromptText();
	if ( nojoytext )
	{
		T_FlashText(nojoytext, 0, 20);
		T_RemovePrint( nojoytext );	nojoytext = NULL;
	}
#endif

	S_FinishInventory();

	Inventory_Displaying = 0;

	if ( reset_flag )
	{
		return( EXIT_TO_TITLE );
	}

	if ( demo_needed )
		return( STARTDEMO );

	/* Selection operations */
	if (Inventory_Chosen==-1)
	{
#ifdef PC_VERSION
		if (inventory_mode!=INV_TITLE_MODE && Option_Music_Volume)
			S_CDVolume(Option_Music_Volume * 25 + 5);
#else
		if ((inventory_mode != INV_TITLE_MODE)
		&&  (inventory_mode != INV_LEVELSELECT_MODE))
		{
			XASetFadeSpeed(8);
			XAFade(XAMasterVolume);
			S_CDRestart();									// un-pause CD tracks
		}
		input &= ~IN_PAUSE;
#endif

		return(0);
	}

	switch (Inventory_Chosen)
	{
		/* Option Ring */
		case PASSPORT_OPTION:
#ifdef PC_VERSION
			if (Inventory_ExtraData[0]==1 && Option_Music_Volume)
				S_CDVolume(Option_Music_Volume * 25 + 5);
			/* Gav: exit without restarting CD track */
#elif defined(FULL_SAVE)
			if ((Inventory_Mode != INV_LEVELSELECT_MODE)
			&&  (Inventory_Mode != INV_TITLE_MODE)
			&&  (Inventory_Mode != INV_DEATH_MODE)
			&&  (CurrentLevel != LV_GYM)
			&&  (Inventory_ExtraData[0] == 1))
				break;
#endif
			return(1);
			break;

		case PHOTO_OPTION:
			if (gameflow.gym_enabled)
			{
				Inventory_ExtraData[1]=0;
				/* Gav: exit without restarting CD track */
				return(1);
			}
			else
				break;
		case DETAIL_OPTION:
		case SOUND_OPTION:
		case CONTROL_OPTION:
		case GAMMA_OPTION:
			break;
		/* Inventory Ring */
		case GUN_OPTION:
			UseItem(GUN_OPTION);
			break;
		case SHOTGUN_OPTION:
			UseItem(SHOTGUN_OPTION);
			break;
		case MAGNUM_OPTION:
			UseItem(MAGNUM_OPTION);
			break;
		case UZI_OPTION:
			UseItem(UZI_OPTION);
			break;
		case HARPOON_OPTION:
			UseItem(HARPOON_OPTION);
			break;
		case M16_OPTION:
			UseItem(M16_OPTION);
			break;
		case ROCKET_OPTION:
			UseItem(ROCKET_OPTION);
			break;
		case GRENADE_OPTION:
			UseItem(GRENADE_OPTION);
			break;
		case FLAREBOX_OPTION:
			UseItem(FLAREBOX_OPTION);
			break;
		case MEDI_OPTION:
			UseItem(MEDI_OPTION);
#if defined(PC_VERSION) && defined(GAMEDEBUG)
			level.health_used += 500;
#endif
			break;
		case BIGMEDI_OPTION:
			UseItem(BIGMEDI_OPTION);
#if defined(PC_VERSION) && defined(GAMEDEBUG)
			level.health_used += 1000;
#endif
			break;
		default:
			break;
	}


#ifdef PC_VERSION
	/* Gav: restart CD track here - means that if passport selected don't restart then immediately stop
			  CD and cause a second or two pause for your trouble */
	if (inventory_mode!=INV_TITLE_MODE && inventory_mode!=INV_LEVELSELECT_MODE && Option_Music_Volume)
		S_CDVolume(Option_Music_Volume * 25 + 5);
#else
	if ((inventory_mode != INV_TITLE_MODE)
	&&  (inventory_mode != INV_LEVELSELECT_MODE))
	{
		XASetFadeSpeed(8);
		XAFade(XAMasterVolume);
		S_CDRestart();									// un-pause CD tracks
	}
#endif
#ifdef PSX_VERSION
	input &= ~IN_PAUSE;
#endif
	return(0);
}






/********************************************************************************************/
/*          MISC INVENTORY ROUTINES															*/
/********************************************************************************************/
/* Initialise inventory */
void Construct_Inventory(void)
{
	int		n;
	INVENTORY_ITEM	*inv_item;

	/* Turn off water effects */
	S_SetupAboveWater(0);

#ifdef PC_VERSION
	if (Inventory_Mode != INV_TITLE_MODE)
		TempVideoAdjust(hires_flag, 1.0);
#endif

	/* Reset bounds */
	phd_left = 0;
	phd_top = 0;
	phd_right = phd_winxmax;
	phd_bottom = phd_winymax;
//	phd_left=phd_winxmin;
//	phd_top=phd_winymin;
//	phd_right=phd_winxmin+phd_winwidth;
//	phd_bottom=phd_winymin+phd_winheight;

	Inventory_Displaying = 1;
	/* Reset return data */
	Inventory_Chosen = 0;
	for (n=0;n<8;n++)
	{
		Inventory_ExtraData[n] = 0;
	}
	if (Inventory_Mode==INV_TITLE_MODE)
	{
		if (gameflow.gym_enabled)
			inv_option_objects = TITLE_RING_OBJECTS;
		else
			inv_option_objects = TITLE_RING_OBJECTS;
	}
	else
		inv_option_objects = OPTION_RING_OBJECTS;

	/* Initialise inventory items*/
	for (n=0;n<inv_main_objects;n++)
	{
		inv_item = inv_main_list[n];
		inv_item->drawn_meshes = inv_item->which_meshes;
//		if (inv_item->object_number==MAP_OPTION && Compass_Status)
//		{
//			inv_item->current_frame = inv_item->open_frame;
//			inv_item->drawn_meshes = 0xffffffff;
//		}
//		else
			inv_item->current_frame = 0;
		inv_item->goal_frame = inv_item->current_frame;
		inv_item->anim_count = 0;
		inv_item->y_rot = 0;
	}


	for (n=0;n<inv_option_objects;n++)
	{
		inv_item = inv_option_list[n];
		inv_item->current_frame = 0;
		inv_item->goal_frame = inv_item->current_frame;
		inv_item->anim_count = 0;
		inv_item->y_rot = 0;
	}

	for (n=0;n<2;n++)
	{
		inv_item = inv_levelselect_list[n];
		if (n==0)
			inv_item->drawn_meshes = 0xffffffff;
		else
			inv_item->drawn_meshes = 0xf81;
		inv_item->current_frame = 0;
		inv_item->goal_frame = inv_item->current_frame;
		inv_item->anim_count = 0;
		inv_item->y_rot = 0;
	}
	/* Reset rings to first item in each ring */
	inv_main_current = 0;	// reset inventory ring
	if (OpenInvOnGym && Inventory_Mode==INV_TITLE_MODE && !gameflow.loadsave_disabled && gameflow.gym_enabled)
#ifdef PC_VERSION
		inv_option_current = 4;	// 3 Without GYM
#else
		inv_option_current = 4;
#endif
	else
	{
		inv_option_current = 0;
		OpenInvOnGym = 0;
	}
	item_data = 0;

}

void	SelectMeshes(INVENTORY_ITEM *inv_item)	// Which meshes to draw when selected.
{
	int	frame;

	if (inv_item->object_number == PASSPORT_OPTION)
	{
		frame = inv_item->current_frame;
		if (frame < 4)
			inv_item->drawn_meshes = PASS_MESH|PINFRONT;
		else if (frame <= 16)
		{
			// opening to, and on, first page
			inv_item->drawn_meshes = PASS_MESH|PINFRONT|PPAGE1;
		}
		else if (frame < 19)
		{
			// moving to middle pages
			inv_item->drawn_meshes = PASS_MESH|PINFRONT|PPAGE1|PPAGE2;
		}
		else if (frame == 19)
		{
			// open on middle page
			inv_item->drawn_meshes = PASS_MESH|PPAGE1|PPAGE2;
		}
		else if (frame < 24)
		{
			// moving to last page
			inv_item->drawn_meshes = PASS_MESH|PPAGE1|PPAGE2|PINBACK;
		}
		else if (frame < 29)
		{
			// open on last page and moving to closed
			inv_item->drawn_meshes = PASS_MESH|PPAGE2|PINBACK;
		}
		else if (frame == 29)
		{
			// closed
			inv_item->drawn_meshes = PASS_MESH;
		}
	}
	else if (inv_item->object_number == MAP_OPTION)
	{
		frame = inv_item->current_frame;
		if (frame && frame<18)
			inv_item->drawn_meshes = 0xffffffff;
		else
			inv_item->drawn_meshes = inv_item->which_meshes;
	}
	else if (inv_item->object_number != GAMMA_OPTION)
		inv_item->drawn_meshes = 0xffffffff;
}

//	returns 1 if currently animating
sint32	AnimateInventoryItem(INVENTORY_ITEM *inv_item)
{
	if (inv_item->current_frame != inv_item->goal_frame)
	{
		if (inv_item->anim_count)
		{
			inv_item->anim_count--;
		}
		else
		{
			inv_item->anim_count = inv_item->anim_speed;
			inv_item->current_frame += inv_item->anim_direction;
			if (inv_item->current_frame >= inv_item->frames_total)
				inv_item->current_frame = 0;
			else if (inv_item->current_frame<0)
				inv_item->current_frame = inv_item->frames_total-1;
		}
		SelectMeshes(inv_item);
		return(1);
	}
	SelectMeshes(inv_item);
	return(0);
}

#define LIT_MESHES	0x7e

void DrawInventoryItem(INVENTORY_ITEM *inv_item)
{
	int		   hours,minutes,seconds, totsec;
	int 		clip,i,poppush;
	sint16 mesh, mesh_num;
	OBJECT_INFO *object;
	sint32 		*bone;
//	sint32 		*packed_rotation;
	sint16		*rotation;
	sint16 		*frame;
	INVENTORY_SPRITE *isprite,**isprite_list;
	sint32			xv,yv,zv,zp;
	sint32			sx,sy;

#ifdef PC_VERSION
	nPolyType = INVENTRY_POLY;
#endif

	if (NoInventoryItemDraw)
		return;

	if ( inv_item->object_number==MAP_OPTION )
	{
		totsec = savegame.timer/30;
		seconds = totsec%60;
		minutes = ((totsec%3600)*-91)/5;
		hours = ((totsec/12)*-91)/5;
		seconds *=-1092;
	}
	else
	   hours=minutes=seconds=totsec=0;

	phd_TranslateRel( 0,inv_item->ytrans,inv_item->ztrans );
	phd_RotYXZ( inv_item->y_rot, inv_item->x_rot, 0 );

	if (inv_item->object_number == GAMMA_OPTION)	// Level select globe?
		phd_RotYXZ( GlobeYRot,GlobeXRot, GlobeZRot);

	object = &objects[inv_item->object_number];

	if (!object->loaded)
	{
		Log("Object %d Not Loaded",inv_item->object_number);
		return;
	}

	if (object->nmeshes < 0)					// If NumMeshes < 0 Indicates A Sprite!!!
	{
		mesh = object->mesh_index;
		S_DrawSprite(SPRITE_REL,0,0,0,mesh,0,0);
		return;
	}

	if ((isprite_list = inv_item->sprlist))
	{
		//	Get screen relative position
#ifdef PSX_VERSION	// ## Chris
		zv = Matrix->tz;
		xv = Matrix->tx;
		yv = Matrix->ty;
#else
		zv = *(phd_mxptr+M23);
		xv = *(phd_mxptr+M03);
		yv = *(phd_mxptr+M13);
#endif

		zp = zv/phd_persp;
		sx =(sint32)( xv/zp + phd_centerx);
		sy =(sint32)( yv/zp + phd_centery);


		while ((isprite = *isprite_list++))
		{
			if ( zv<phd_znear || zv>phd_zfar )
				break;
			while (isprite->shape)
			{
				switch (isprite->shape)
				{
					case SHAPE_SPRITE:
						S_DrawScreenSprite( sx+isprite->x, sy+isprite->y, isprite->z, isprite->param1, isprite->param2, (sint16)(static_objects[ALPHABET].mesh_number+isprite->sprnum), 16*256, 0);
						break;
					case SHAPE_LINE:
						S_DrawScreenLine( sx+isprite->x, sy+isprite->y, isprite->z, isprite->param1, isprite->param2, isprite->sprnum, isprite->grdptr, 0);
						break;
					case SHAPE_BOX:
						S_DrawScreenBox( sx+isprite->x, sy+isprite->y, isprite->z, isprite->param1, isprite->param2, isprite->sprnum, isprite->grdptr, 0);
						break;
					case SHAPE_FBOX:
						S_DrawScreenFBox( sx+isprite->x, sy+isprite->y, isprite->z, isprite->param1, isprite->param2, isprite->sprnum, isprite->grdptr, 0);
						break;
					default:
						break;
				}
				isprite++;
			}
		}
	}

	frame = object->frame_base + inv_item->current_frame * (anims[object->anim_index].interpolation>>8);

	phd_PushMatrix();

	if ((clip = S_GetObjectBounds(frame)))
	{
//		S_PrintObjectOutline(frame, C_DARKGREEN);
		/* Translate object 0 */
		phd_TranslateRel((sint32)*(frame+6), (sint32)*(frame+7), (sint32)*(frame+8));
		rotation = frame+9;
		gar_RotYXZsuperpack(&rotation, 0);

		mesh = object->mesh_index;
		bone = bones + object->bone_index;

		mesh_num=1;
		/* Draw object zero */

		if (inv_item->object_number == GAMMA_OPTION)	// Globe?
			inv_item->drawn_meshes = ~8;

		if (mesh_num&inv_item->drawn_meshes)
		{
			if (inv_item->object_number == GAMMA_OPTION)	// Globe?
			{
#ifdef PSX_VERSION
				db.ot += 64;                         	// Push back globe underneath.
				Inv_GlobeLight(mesh_num);
				phd_PutPolygons(meshes[mesh], clip );
				db.ot -= 64;
#else
				Inv_GlobeLight(mesh_num);
				phd_PutPolygons(meshes[mesh], clip );
#endif
			}
			else
				phd_PutPolygons(meshes[mesh], clip );
		}

		for ( i=object->nmeshes-1; i>0; i-- )
		{
			mesh++;
			mesh_num<<=1;

			poppush = *(bone++);			// Do Automated Hierarchy
			if (poppush & 1)                // Push Pop
				phd_PopMatrix();
			if (poppush & 2)
				phd_PushMatrix();

			phd_TranslateRel(*(bone), *(bone+1), *(bone+2));
			gar_RotYXZsuperpack(&rotation, 0);

			if ( inv_item->object_number==MAP_OPTION )	// STOPWATCH REALLY
			{
				/* DO STOPWATCH HANDS *****************/
//				if ( i==2 )	// Second Hand
				if ( i==1 )	// Second Hand
				{
					phd_RotZ( (PHD_ANGLE)seconds );
					inv_item->misc_data[1] = inv_item->misc_data[0];
					inv_item->misc_data[0] = seconds;
				}
//				if ( i==3 ) // Minute Hand
				if ( i==2 ) // Minute Hand
					phd_RotZ( (PHD_ANGLE)minutes );
//				if ( i==4 ) // Hour Hand
				if ( i==3 ) // Hour Hand
					phd_RotZ( (PHD_ANGLE)hours );
			}

			if (inv_item->object_number == GAMMA_OPTION)	// Globe?
				Inv_GlobeLight(mesh_num);

			if (mesh_num&inv_item->drawn_meshes)
			{
				if (inv_item->object_number == GAMMA_OPTION)	// Globe?
				{
#ifdef PSX_VERSION
					if (!(mesh_num & LIT_MESHES))
						db.ot += 32;                         	// Push back globe underneath.
					phd_PutPolygons(meshes[mesh], clip );
					if (!(mesh_num & LIT_MESHES))
						db.ot -= 32;
#else
					phd_PutPolygons(meshes[mesh], clip );
#endif
				}
				else
					phd_PutPolygons(meshes[mesh], clip );
			}
			bone += 3;
		}
	}
	phd_PopMatrix();
}


sint32	GetDebouncedInput(sint32 input)
{
	int j;

	j = input^(input&oldInputDB);
	oldInputDB = input;
	input &= j;

/*
	if (input && !oldInputDB)
	{
		oldInputDB = input;
	}
	else if (!input)
	{
		oldInputDB = 0;
	}
	else
	{
		input = 0;
	}
*/
	return(input);
}


#ifdef PSX_VERSION

void DoInventoryPicture(void)
	{
#ifdef PSX_VERSION
	S_DrawPic();
#else
	S_CopyBufferToScreen();	 // Picture? // Clearscreen on PC
#endif
	}

#endif


#ifdef PC_VERSION

#define MENU_BACKGROUND 0



void DoInventoryBackground(void)
{
	static int bz=12288;

	PHD_ANGLE	angles[2];
	sint16 		*frame;
	PHD_3DPOS 	viewer;



	S_CopyBufferToScreen();	 // Picture? // Clearscreen on PC

	if (!objects[MENU_BACKGROUND].loaded)
		return;

	phd_GetVectorAngles( 0,0x1000,0, angles );
	viewer.x_pos = 0;
	viewer.y_pos = -0x200;
	viewer.z_pos = 0;
	viewer.x_rot = angles[1];
	viewer.y_rot = angles[0];
	viewer.z_rot = 0;
	phd_GenerateW2V( &viewer );

	ls_divider = 0x6000;
	phd_GetVectorAngles( -0x600, 0x100, 0x400, angles );
#ifdef PC_VERSION
	phd_RotateLight( angles[1],angles[0] );
#endif

//	S_SetupAboveWater(0);

#if 0
	if (input&IN_SLOW && input&IN_LEFT)
		bz+=WALL_L;
	if (input&IN_SLOW && input&IN_RIGHT)
		bz-=WALL_L;
	sprintf(exit_message, "BZ %d",bz);
	PrintDbug(4,10,exit_message);
#endif

	phd_PushMatrix();

	phd_TranslateAbs( 0,bz,0);
	phd_RotYXZ(	0,0x4000,(short)0x8000 );

	frame = anims[objects[MENU_BACKGROUND].anim_index].frame_ptr + 9;
	gar_RotYXZsuperpack(&frame, 0);
	phd_RotYXZ(	(sint16)0x8000,0,0 );

	S_InsertInvBgnd(meshes[objects[MENU_BACKGROUND].mesh_index]);
	phd_PopMatrix();
}
#endif


void GetGlobeMeshFlags()
{
	GlobeLevelComplete[0] = savegame.IndiaComplete;
	GlobeLevelComplete[1] = savegame.SPacificComplete;
	GlobeLevelComplete[2] = savegame.NevadaComplete;
  	GlobeLevelComplete[3] = 255;	// Say 'Don't draw this mesh'.
	GlobeLevelComplete[4] = savegame.LondonComplete;

	if (savegame.IndiaComplete && savegame.SPacificComplete && savegame.NevadaComplete && savegame.LondonComplete)
		GlobeLevelComplete[5] = savegame.AntarcticaComplete;
	else
		GlobeLevelComplete[5] = 255;	// Say 'Don't draw this mesh'.

	GlobeLevel = 0;

	while(GlobeLevelComplete[GlobeLevel])
		GlobeLevel++;
}
