/******************************************************************************************/
/*                                                                                           */
/* Inventory Functions                                                                            */
/*                                                                                           */
/*********************************************************************************************/

#ifdef PSX_VERSION
#include <sys\types.h>
#include <string.h>
#include <stdio.h>
#include "../spec_psx/typedefs.h"
#include "../spec_psx/psxinput.h"
#include "../spec_psx/3d_gen.h"
#include "../spec_psx/gen_draw.h"
#include "../spec_psx/option.h"
extern void SetLightMatrices();
#else
#include "../specific/standard.h"
#include "../specific/input.h"
#endif

#include "objects.h"
#include "lara.h"
#include "control.h"
#include "inventry.h"
#include "invfunc.h"
#include "invdata.h"
#include "savegame.h"
#include "title.h"
#include "health.h"
#include "laraanim.h"

sint16 LevelSecrets[21] = {0, 6, 4, 5, 0, 3, 3, 3, 1, 5, 5, 6, 1, 3, 2, 3, 3, 3, 3, 0, 0};
extern long	wrap;

extern short rcossin_tbl[];

void SelectMeshes(INVENTORY_ITEM *inv_item);
//	sint32	AnimateInventoryItem(INVENTORY_ITEM *inv_item)
//	void DrawInventoryItem(INVENTORY_ITEM *inv_item)

void	InitColours(void)
{
	/* Setup inventory colours */
	inv_colours[C_BLACK] = S_COLOUR(0,0,0);
	inv_colours[C_GREY] = S_COLOUR(64,64,64);
	inv_colours[C_WHITE] = S_COLOUR(255,255,255);
	inv_colours[C_RED] = S_COLOUR(255,0,0);
	inv_colours[C_ORANGE] = S_COLOUR(255,128,0);
	inv_colours[C_YELLOW] = S_COLOUR(255,255,0);
	inv_colours[C_DARKGREEN] = S_COLOUR(0,128,0);
	inv_colours[C_GREEN] = S_COLOUR(0,255,0);
	inv_colours[C_CYAN] = S_COLOUR(0,255,255);
	inv_colours[C_BLUE] = S_COLOUR(0,0,255);
	inv_colours[C_MAGENTA] = S_COLOUR(255,0,255);

}

void	RingIsOpen(RING_INFO *ring)
{
	if (Inventory_Mode == INV_TITLE_MODE)
	{
#ifdef USE_INVENTORY_TAG
		if (!Inv_tagText)
		{
			Inv_tagText = T_Print(0,26,0,GF_GameStrings[GT_SECURITY_TAG]);
			T_CentreH(Inv_tagText, 1);
		}
#endif
		return;
	}
/*	if (!Inv_levelText)
	{
		Inv_levelText = T_Print(0,26,0,GF_Level_Names[CurrentLevel]);
		T_CentreH(Inv_levelText, 1);
	}*/
	if (!Inv_ringText)
	{
		switch (ring->type)
		{
			case MAIN_RING:
				Inv_ringText = T_Print(0, 26, IT_BRONZE, GF_GameStrings[GT_MAIN_HEADING]);
				break;
			case OPTION_RING:
				if (Inventory_Mode == INV_DEATH_MODE)
					Inv_ringText = T_Print(0, 26, IT_BRONZE, GF_GameStrings[GT_GAMEOVER_HEADING]);
				else
					Inv_ringText = T_Print(0, 26, IT_BRONZE, GF_GameStrings[GT_OPTION_HEADING]);
				break;
			case KEYS_RING:
				Inv_ringText = T_Print(0, 26, IT_BRONZE, GF_GameStrings[GT_KEYS_HEADING]);
				break;
			case LEVELSELECT_RING:
				Inv_ringText = T_Print(0, 26, IT_BRONZE, GF_GameStrings[GT_LEVELSELECT]);
				break;
		}
		T_CentreH(Inv_ringText, 1);
	}
	if (Inventory_Mode == INV_KEYS_MODE || Inventory_Mode==INV_DEATH_MODE)
		return;

   	if (!Inv_upArrow1)
   	{
   		if (ring->type == OPTION_RING || (ring->type == MAIN_RING && inv_keys_objects))
   		{
   			Inv_upArrow1 = T_Print(20, 28, IT_GREY, "[");
   			Inv_upArrow2 = T_Print(-20, 28, IT_GREY, "[");
   			T_RightAlign(Inv_upArrow2, 1);
   		}
   	}

	if (!Inv_downArrow1)
   	{
   		if ((ring->type == MAIN_RING && !gameflow.lockout_optionring) || ring->type == KEYS_RING)
   		{
   			Inv_downArrow1 = T_Print(20,-15, IT_GREY, "]");
   			T_BottomAlign(Inv_downArrow1, 1);
   			Inv_downArrow2 = T_Print(-20,-15, IT_GREY, "]");
   			T_BottomAlign(Inv_downArrow2, 1);
   			T_RightAlign(Inv_downArrow2, 1);
   		}
   	}
}

void	RingIsNotOpen(RING_INFO *ring)
{
//	T_RemovePrint(Inv_levelText);	Inv_levelText=NULL;
	T_RemovePrint(Inv_tagText);	Inv_tagText=NULL;
	T_RemovePrint(Inv_ringText);	Inv_ringText=NULL;
	T_RemovePrint(Inv_upArrow1);	Inv_upArrow1=NULL;
	T_RemovePrint(Inv_upArrow2);	Inv_upArrow2=NULL;
	T_RemovePrint(Inv_downArrow1);	Inv_downArrow1=NULL;
	T_RemovePrint(Inv_downArrow2);	Inv_downArrow2=NULL;
}

void	RingNotActive(INVENTORY_ITEM *inv_item)
{
	/* Not frame compensated */

	int		tempInt;
	char	tempText[64];

	if (!Inv_itemText[IT_NAME])
	{
		switch (inv_item->object_number)
		{
			case PUZZLE_OPTION1:
				Inv_itemText[IT_NAME] = T_Print(0,-16,0,GF_Puzzle1Strings[CurrentLevel]);
				break;
			case PUZZLE_OPTION2:
				Inv_itemText[IT_NAME] = T_Print(0,-16,0,GF_Puzzle2Strings[CurrentLevel]);
				break;
			case PUZZLE_OPTION3:
				Inv_itemText[IT_NAME] = T_Print(0,-16,0,GF_Puzzle3Strings[CurrentLevel]);
				break;
			case PUZZLE_OPTION4:
				Inv_itemText[IT_NAME] = T_Print(0,-16,0,GF_Puzzle4Strings[CurrentLevel]);
				break;


			case PICKUP_OPTION1:
				Inv_itemText[IT_NAME] = T_Print(0,-16,0,GF_Pickup1Strings[CurrentLevel]);
				break;
			case PICKUP_OPTION2:
				Inv_itemText[IT_NAME] = T_Print(0,-16,0,GF_Pickup2Strings[CurrentLevel]);
				break;


			case KEY_OPTION1:
				Inv_itemText[IT_NAME] = T_Print(0,-16,0,GF_Key1Strings[CurrentLevel]);
				break;
			case KEY_OPTION2:
				Inv_itemText[IT_NAME] = T_Print(0,-16,0,GF_Key2Strings[CurrentLevel]);
				break;
			case KEY_OPTION3:
				Inv_itemText[IT_NAME] = T_Print(0,-16,0,GF_Key3Strings[CurrentLevel]);
				break;
			case KEY_OPTION4:
				Inv_itemText[IT_NAME] = T_Print(0,-16,0,GF_Key4Strings[CurrentLevel]);
				break;

			case PASSPORT_OPTION:
			case GAMMA_OPTION:
				break;
			default:
				Inv_itemText[IT_NAME] = T_Print(0, -16, IT_BRONZE, inv_item->itemText);
				break;
		}
		if (Inv_itemText[IT_NAME])
		{
			T_BottomAlign(Inv_itemText[IT_NAME], 1);
			T_CentreH(Inv_itemText[IT_NAME], 1);
		}
	}

	// Print Quantities if any

	tempInt = Inv_RequestItem(inv_item->object_number); // Item qty
	switch (inv_item->object_number)
	{
		case SHOTGUN_OPTION:
			if (!Inv_itemText[IT_QTY] && !savegame.bonus_flag )
				wsprintf(tempText, "%5d", lara.shotgun.ammo/SHOTGUN_AMMO_CLIP);
			else return;
			break;
		case MAGNUM_OPTION:
			if (!Inv_itemText[IT_QTY] && !savegame.bonus_flag )
				wsprintf(tempText, "%5d", lara.magnums.ammo);
			else return;
			break;
		case UZI_OPTION:
			if (!Inv_itemText[IT_QTY] && !savegame.bonus_flag )
				wsprintf(tempText, "%5d", lara.uzis.ammo);
			else return;
			break;
		case HARPOON_OPTION:
			if (!Inv_itemText[IT_QTY] && !savegame.bonus_flag )
				wsprintf(tempText, "%5d", lara.harpoon.ammo);
			else return;
			break;
		case M16_OPTION:
			if (!Inv_itemText[IT_QTY] && !savegame.bonus_flag )
				wsprintf(tempText, "%5d", lara.m16.ammo);
			else return;
			break;
		case ROCKET_OPTION:
			if (!Inv_itemText[IT_QTY] && !savegame.bonus_flag )
				wsprintf(tempText, "%5d", lara.rocket.ammo);
			else return;
			break;
		case GRENADE_OPTION:
			if (!Inv_itemText[IT_QTY] && !savegame.bonus_flag )
				wsprintf(tempText, "%5d", lara.grenade.ammo);
			else return;
			break;
		case SG_AMMO_OPTION:
			if (!Inv_itemText[IT_QTY])
				wsprintf(tempText, "%d", tempInt *NUM_SG_SHELLS );
			else return;
			break;
		case MAG_AMMO_OPTION:
		case UZI_AMMO_OPTION:
		case M16_AMMO_OPTION:
			if (!Inv_itemText[IT_QTY] && !savegame.bonus_flag)
				wsprintf(tempText, "%d", tempInt *2 );
			else return;
			break;
		case HARPOON_AMMO_OPTION:
			if (!Inv_itemText[IT_QTY] && !savegame.bonus_flag)
//				wsprintf(tempText, "%d", tempInt *HARPOON_AMMO_CLIP );
				wsprintf(tempText, "%d", lara.harpoon.ammo);
			else return;
			break;
		case ROCKET_AMMO_OPTION:
		case GRENADE_AMMO_OPTION:
		case FLAREBOX_OPTION:
			if (!Inv_itemText[IT_QTY] && !savegame.bonus_flag)
				wsprintf(tempText, "%d", tempInt);
			else return;
			break;
		case MEDI_OPTION:
		case BIGMEDI_OPTION:
			health_bar_timer = 40;
			DrawHealthBar(FlashIt());
		case PUZZLE_OPTION1:
		case PUZZLE_OPTION2:
		case PUZZLE_OPTION3:
		case PUZZLE_OPTION4:
		case PICKUP_OPTION1:
		case PICKUP_OPTION2:
		case KEY_OPTION1:
		case KEY_OPTION2:
		case KEY_OPTION3:
		case KEY_OPTION4:
		case ICON_PICKUP1_OPTION:
		case ICON_PICKUP2_OPTION:
		case ICON_PICKUP3_OPTION:
		case ICON_PICKUP4_OPTION:
		case SAVEGAME_CRYSTAL_OPTION:
			if (!Inv_itemText[IT_QTY] && tempInt>1)
				wsprintf(tempText, "%d", tempInt);
			else
				return;
			break;
		default:
			return;
	}
	if (!Inv_itemText[IT_QTY])
	{
//		MakeAmmoString(tempText);
		Inv_itemText[IT_QTY] = T_Print(64,-56,3,tempText);
		T_BottomAlign(Inv_itemText[IT_QTY], 1);
		T_CentreH(Inv_itemText[IT_QTY], 1);
	}

}
void	RingActive(void)
{
	T_RemovePrint(Inv_itemText[IT_NAME]);
	Inv_itemText[IT_NAME]=NULL;
	T_RemovePrint(Inv_itemText[IT_QTY]);
	Inv_itemText[IT_QTY]=NULL;
}


/* INVENTORY GAME CALLS */
//
//	int	Inv_AddItem(int	itemNum);		-	Add this item to inventory, returns 1 if successfull
//	int	Inv_RequestItem(int itemNum);	-	Checks if item is in inventory, returns how many of this type
//	int	Inv_RemoveItem(int itemNum);	-	Removes item from inventory, returns 1 if successful
//	int	Inv_GetCount(void);				-	Returns number of items held

int	Inv_AddItem(int itemNum)
{
	int	n,m,found=0;
	int	itemNumOption=0;
	INVENTORY_ITEM	*inv_item;

	itemNumOption = Inv_GetItemOption(itemNum);

	for ( n=0 ; n<inv_main_objects ; n++ )
	{
		inv_item = inv_main_list[n];

		if (inv_item->object_number == itemNumOption)
		{
			found = 1;
			break;
		}
	}

	for ( m=0 ; m<inv_keys_objects ; m++ )
	{
		inv_item = inv_keys_list[m];
		if (inv_item->object_number==itemNumOption)
		{
			found = 2;
			break;
		}
	}

	if (found==1)
	{
		/* Items of this type already held */
		if (itemNum == FLAREBOX_ITEM)
			inv_main_qtys[n]+=FLARE_AMMO_BOX;
		else	if (itemNum == HARPOON_AMMO_ITEM)
		    	lara.harpoon.ammo += HARPOON_AMMO_QTY;
		else
			inv_main_qtys[n]++;
		return(1);
	}
	else if (found==2)
	{
		/* Items of this type already held */
		inv_keys_qtys[m]++;
		return(1);
	}
	else
	{
		/* This is a new item and must be added to ring */
		switch (itemNum)
		{
			case MAP_CLOSED:
			case MAP_OPTION:
				Inv_InsertItem(&icompass_option);
				return(1);
			case GUN_ITEM:
			case GUN_OPTION:
				Inv_InsertItem(&igun_option);
				if (lara.last_gun_type == LG_UNARMED)
				{
					lara.last_gun_type = LG_PISTOLS;

					// Mesh Swap In Pistols To Holsters RF

					lara.mesh_ptrs[THIGH_L] = meshes[objects[PISTOLS].mesh_index + THIGH_L];
					lara.mesh_ptrs[THIGH_R] = meshes[objects[PISTOLS].mesh_index + THIGH_R];

				}
				return(1);
			case SHOTGUN_ITEM:
			case SHOTGUN_OPTION:
				if ((found=Inv_RequestItem(SG_AMMO_ITEM)))
				{
					for (n=0;n<found;n++)
					{
						Inv_RemoveItem(SG_AMMO_ITEM);
						lara.shotgun.ammo += SHOTGUN_AMMO_QTY;
					}
				}
				lara.shotgun.ammo += SHOTGUN_AMMO_QTY;
				Inv_InsertItem(&ishotgun_option);
				if (lara.last_gun_type == LG_UNARMED)
					lara.last_gun_type = LG_SHOTGUN;
				if (!lara.back_gun)
					lara.back_gun = SHOTGUN;
				GlobalItemReplace( SHOTGUN_ITEM, SG_AMMO_ITEM );
				break;
			case MAGNUM_ITEM:
			case MAGNUM_OPTION:
				if ((found=Inv_RequestItem(MAG_AMMO_ITEM)))
				{
					for (n=0;n<found;n++)
					{
						Inv_RemoveItem(MAG_AMMO_ITEM);
						lara.magnums.ammo += MAGNUM_AMMO_QTY;
					}
				}
				GlobalItemReplace( MAGNUM_ITEM, MAG_AMMO_ITEM );
				lara.magnums.ammo += MAGNUM_AMMO_QTY;					// Magnums have two clips in
				Inv_InsertItem(&imagnum_option);
				break;
			case UZI_ITEM:
			case UZI_OPTION:
				if ((found=Inv_RequestItem(UZI_AMMO_ITEM)))
				{
					for (n=0;n<found;n++)
					{
						Inv_RemoveItem(UZI_AMMO_ITEM);
						lara.uzis.ammo += UZI_AMMO_QTY;
					}
				}
				GlobalItemReplace( UZI_ITEM, UZI_AMMO_ITEM );
				lara.uzis.ammo += UZI_AMMO_QTY;	   						// Uzis have 2 Clips
				Inv_InsertItem(&iuzi_option);
				break;
			case HARPOON_ITEM:
			case HARPOON_OPTION:
				if ((found=Inv_RequestItem(HARPOON_AMMO_ITEM)))
				{
					for (n=0;n<found;n++)
					{
						Inv_RemoveItem(HARPOON_AMMO_ITEM);
//						lara.harpoon.ammo += HARPOON_AMMO_QTY;
					}
				}
				GlobalItemReplace( HARPOON_ITEM, HARPOON_AMMO_ITEM );
				lara.harpoon.ammo += HARPOON_AMMO_QTY;
				Inv_InsertItem(&iharpoon_option);
				break;
			case M16_ITEM:
			case M16_OPTION:
				if ((found=Inv_RequestItem(M16_AMMO_ITEM)))
				{
					for (n=0;n<found;n++)
					{
						Inv_RemoveItem(M16_AMMO_ITEM);
						lara.m16.ammo += M16_AMMO_QTY;
					}
				}
				GlobalItemReplace( M16_ITEM, M16_AMMO_ITEM );
				lara.m16.ammo += M16_AMMO_QTY;
				Inv_InsertItem(&im16_option);
				break;
			case ROCKET_GUN_ITEM:
			case ROCKET_OPTION:
				if ((found=Inv_RequestItem(ROCKET_AMMO_ITEM)))
				{
					for (n=0;n<found;n++)
					{
						Inv_RemoveItem(ROCKET_AMMO_ITEM);
						lara.rocket.ammo += ROCKET_AMMO_QTY;
					}
				}
				GlobalItemReplace( ROCKET_GUN_ITEM, ROCKET_AMMO_ITEM );
				lara.rocket.ammo += ROCKET_AMMO_QTY;
				Inv_InsertItem(&irocket_option);
				break;

			case GRENADE_GUN_ITEM:
			case GRENADE_OPTION:
				if ((found=Inv_RequestItem(GRENADE_AMMO_ITEM)))
				{
					for (n=0;n<found;n++)
					{
						Inv_RemoveItem(GRENADE_AMMO_ITEM);
						lara.grenade.ammo += GRENADE_AMMO_QTY;
					}
				}
				GlobalItemReplace( GRENADE_GUN_ITEM, GRENADE_AMMO_ITEM );
				lara.grenade.ammo += GRENADE_AMMO_QTY;
				Inv_InsertItem(&igrenade_option);
				break;

			case SG_AMMO_ITEM:
			case SG_AMMO_OPTION:
				if(Inv_RequestItem(SHOTGUN_ITEM))
					lara.shotgun.ammo += SHOTGUN_AMMO_QTY;
				else
					Inv_InsertItem(&isgunammo_option);
				break;
			case MAG_AMMO_ITEM:
			case MAG_AMMO_OPTION:
				if(Inv_RequestItem(MAGNUM_ITEM))
					lara.magnums.ammo += MAGNUM_AMMO_QTY;
				else
					Inv_InsertItem(&imagammo_option);
				break;
			case UZI_AMMO_ITEM:
			case UZI_AMMO_OPTION:
				if(Inv_RequestItem(UZI_ITEM))
					lara.uzis.ammo += UZI_AMMO_QTY;
				else
					Inv_InsertItem(&iuziammo_option);
				break;
			case HARPOON_AMMO_ITEM:
			case HARPOON_AMMO_OPTION:
				lara.harpoon.ammo += HARPOON_AMMO_QTY;
				if(!Inv_RequestItem(HARPOON_ITEM))
				{
					if(!Inv_RequestItem(HARPOON_AMMO_ITEM))
				 		Inv_InsertItem(&iharpoonammo_option);
				}
//				if(Inv_RequestItem(HARPOON_ITEM))
//					lara.harpoon.ammo += HARPOON_AMMO_QTY;
//				else
//					Inv_InsertItem(&iharpoonammo_option);
				break;
			case M16_AMMO_ITEM:
			case M16_AMMO_OPTION:
				if(Inv_RequestItem(M16_ITEM))
					lara.m16.ammo += M16_AMMO_QTY;
				else
					Inv_InsertItem(&im16ammo_option);
				break;
			case ROCKET_AMMO_ITEM:
			case ROCKET_AMMO_OPTION:
				if(Inv_RequestItem(ROCKET_GUN_ITEM))
					lara.rocket.ammo += ROCKET_AMMO_QTY;
				else
					Inv_InsertItem(&irocketammo_option);
				break;
			case GRENADE_AMMO_ITEM:
			case GRENADE_AMMO_OPTION:
				if(Inv_RequestItem(GRENADE_GUN_ITEM))
					lara.grenade.ammo += GRENADE_AMMO_QTY;
				else
					Inv_InsertItem(&igrenadeammo_option);
				break;
			case FLAREBOX_ITEM:
			case FLAREBOX_OPTION:
				// Box of 6 flares
				Inv_InsertItem(&iflare_option);
				for (n=0;n<(FLARE_AMMO_BOX-1);n++)
					Inv_AddItem(FLARE_ITEM);
				return(1);
			case FLARE_ITEM:
				// single flare
				Inv_InsertItem(&iflare_option);
				return(1);
  			case MEDI_ITEM:
			case MEDI_OPTION:
		    		Inv_InsertItem(&imedi_option);
				return(1);
			case BIGMEDI_ITEM:
			case BIGMEDI_OPTION:
				Inv_InsertItem(&ibigmedi_option);
				return(1);

			case SECRET_ITEM1:
				savegame.secrets |= 1;
				return(1);
			case SECRET_ITEM2:
				savegame.secrets |= 2;
				return(1);
			case SECRET_ITEM3:
				savegame.secrets |= 4;
				return(1);

			case PICKUP_ITEM1:
			case PICKUP_OPTION1:
				Inv_InsertItem(&ipickup1_option);
				return(1);
			case PICKUP_ITEM2:
			case PICKUP_OPTION2:
				Inv_InsertItem(&ipickup2_option);
				return(1);

			case PUZZLE_ITEM1:
			case PUZZLE_OPTION1:
				Inv_InsertItem(&ipuzzle1_option);
				return(1);
			case PUZZLE_ITEM2:
			case PUZZLE_OPTION2:
				Inv_InsertItem(&ipuzzle2_option);
				return(1);
			case PUZZLE_ITEM3:
			case PUZZLE_OPTION3:
				Inv_InsertItem(&ipuzzle3_option);
				return(1);
			case PUZZLE_ITEM4:
			case PUZZLE_OPTION4:
				Inv_InsertItem(&ipuzzle4_option);
				return(1);

			case KEY_ITEM1:
			case KEY_OPTION1:
				Inv_InsertItem(&ikey1_option);
				if (CurrentLevel == LV_GYM)
					savegame.QuadbikeKeyFlag = 1;
				return(1);
			case KEY_ITEM2:
			case KEY_OPTION2:
				Inv_InsertItem(&ikey2_option);
				return(1);
			case KEY_ITEM3:
			case KEY_OPTION3:
				Inv_InsertItem(&ikey3_option);
				return(1);
			case KEY_ITEM4:
			case KEY_OPTION4:
				Inv_InsertItem(&ikey4_option);
				return(1);
			case ICON_PICKUP1_ITEM:
			case ICON_PICKUP1_OPTION:
				Inv_InsertItem(&icon1_option);
				return(1);
			case ICON_PICKUP2_ITEM:
			case ICON_PICKUP2_OPTION:
				Inv_InsertItem(&icon2_option);
				return(1);
			case ICON_PICKUP3_ITEM:
			case ICON_PICKUP3_OPTION:
				Inv_InsertItem(&icon3_option);
				return(1);
			case ICON_PICKUP4_ITEM:
			case ICON_PICKUP4_OPTION:
				Inv_InsertItem(&icon4_option);
				return(1);
			case SAVEGAME_CRYSTAL_ITEM:
			case SAVEGAME_CRYSTAL_OPTION:
				Inv_InsertItem(&sgcrystal_option);
				return(1);
			default:
				return(0);
		}
	}
	return(0);
}
void	Inv_InsertItem(INVENTORY_ITEM *inv_item)
{
	int n, m;
	INVENTORY_ITEM *inv_place;

	if (inv_item->inv_pos < 100)
	{
		for (n=0;n<inv_main_objects;n++)
		{
			inv_place = inv_main_list[n];
			if (inv_place->inv_pos > inv_item->inv_pos)
				break;
		}
		if (n==inv_main_objects)
		{
			// This item goes at end
			inv_main_list[inv_main_objects] = inv_item;
			inv_main_qtys[inv_main_objects] = 1;
			inv_main_objects++;
		}
		else
		{
			// This item must be inserted at position n
			for (m=inv_main_objects;m>(n-1);m-- )
			{
			  inv_main_list[m+1] = inv_main_list[m];
			  inv_main_qtys[m+1] = inv_main_qtys[m];
			}
			inv_main_list[n] = inv_item;
			inv_main_qtys[n] = 1;
			inv_main_objects++;
		}
	}
	else
	{
		for (n=0;n<inv_keys_objects;n++)
		{
			inv_place = inv_keys_list[n];
			if (inv_place->inv_pos > inv_item->inv_pos)
				break;
		}
		if (n==inv_keys_objects)
		{
			// This item goes at end
			inv_keys_list[inv_keys_objects] = inv_item;
			inv_keys_qtys[inv_keys_objects] = 1;
			inv_keys_objects++;
		}
		else
		{
			// This item must be inserted at position n
			for (m=inv_keys_objects;m>(n-1);m-- )
			{
			  inv_keys_list[m+1] = inv_keys_list[m];
			  inv_keys_qtys[m+1] = inv_keys_qtys[m];
			}
			inv_keys_list[n] = inv_item;
			inv_keys_qtys[n] = 1;
			inv_keys_objects++;
		}
	}
}


int		Inv_RequestItem(int	itemNum)
{
	int	n;
	int	itemNumOption;
	INVENTORY_ITEM	*inv_item;

	itemNumOption = Inv_GetItemOption(itemNum);

	for (n=0;n<inv_main_objects;n++)
	{
		inv_item = inv_main_list[n];
		if (inv_item->object_number==itemNumOption)
			return(inv_main_qtys[n]);
	}
	for (n=0;n<inv_keys_objects;n++)
	{
		inv_item = inv_keys_list[n];
		if (inv_item->object_number==itemNumOption)
			return(inv_keys_qtys[n]);
	}
	return(0);
}

void Inv_RemoveAllItems(void)
{
	inv_main_objects = 0;
	inv_main_current = 0;

	inv_keys_objects = 0;
	inv_keys_current = 0;
}


int	Inv_RemoveItem(int itemNum)
{
	int	n, m;
	int	itemNumOption;
	INVENTORY_ITEM	*inv_item;

	itemNumOption = Inv_GetItemOption(itemNum);

	for (n=0;n<inv_main_objects;n++)
	{
		inv_item = inv_main_list[n];

		if (inv_item->object_number==itemNumOption)
		{
			inv_main_qtys[n]--;

			if (inv_main_qtys[n]<=0)
			{
				inv_main_objects--;
				for(m=n;m<inv_main_objects;m++)
				{
					inv_main_list[m] = inv_main_list[m+1];
					inv_main_qtys[m] = inv_main_qtys[m+1];
				}
			}
			return(1);
		}
	}
	for (n=0;n<inv_keys_objects;n++)
	{
		inv_item = inv_keys_list[n];
		if (inv_item->object_number==itemNumOption)
		{
			inv_keys_qtys[n]--;
			if (inv_keys_qtys[n]<=0)
			{
				inv_keys_objects--;
				for(m=n;m<inv_keys_objects;m++)
				{
					inv_keys_list[m] = inv_keys_list[m+1];
					inv_keys_qtys[m] = inv_keys_qtys[m+1];
				}
			}
			return(1);
		}
	}
	return(0);
}

int	Inv_GetCount(void)
{
	int	n, qty=0;
	for (n=0;n<inv_main_objects;n++)
	{
		qty += inv_main_qtys[n];
	}
	return(qty);
}


int	Inv_GetItemOption(int	itemNum)
{
	switch (itemNum)
	{
		case GUN_ITEM:
		case GUN_OPTION:
			return(GUN_OPTION);
		case FLARE_ITEM:
		case FLAREBOX_ITEM:
		case FLAREBOX_OPTION:
			return(FLAREBOX_OPTION);
		case SHOTGUN_ITEM:
		case SHOTGUN_OPTION:
			return(SHOTGUN_OPTION);
		case MAGNUM_ITEM:
		case MAGNUM_OPTION:
			return(MAGNUM_OPTION);
		case UZI_ITEM:
		case UZI_OPTION:
			return(UZI_OPTION);
		case M16_ITEM:
		case M16_OPTION:
			return(M16_OPTION);
		case ROCKET_GUN_ITEM:
		case ROCKET_OPTION:
			return(ROCKET_OPTION);
		case GRENADE_GUN_ITEM:
		case GRENADE_OPTION:
			return(GRENADE_OPTION);
		case HARPOON_ITEM:
		case HARPOON_OPTION:
			return(HARPOON_OPTION);
		case SG_AMMO_ITEM:
		case SG_AMMO_OPTION:
			return(SG_AMMO_OPTION);
		case MAG_AMMO_ITEM:
		case MAG_AMMO_OPTION:
			return(MAG_AMMO_OPTION);
		case HARPOON_AMMO_ITEM:
		case HARPOON_AMMO_OPTION:
			return(HARPOON_AMMO_OPTION);
		case M16_AMMO_ITEM:
		case M16_AMMO_OPTION:
			return(M16_AMMO_OPTION);
		case ROCKET_AMMO_ITEM:
		case ROCKET_AMMO_OPTION:
			return(ROCKET_AMMO_OPTION);
		case GRENADE_AMMO_ITEM:
		case GRENADE_AMMO_OPTION:
			return(GRENADE_AMMO_OPTION);
		case UZI_AMMO_ITEM:
		case UZI_AMMO_OPTION:
			return(UZI_AMMO_OPTION);
		case MEDI_ITEM:
		case MEDI_OPTION:
			return(MEDI_OPTION);
		case BIGMEDI_ITEM:
		case BIGMEDI_OPTION:
			return(BIGMEDI_OPTION);


		case PUZZLE_ITEM1:
		case PUZZLE_OPTION1:
			return(PUZZLE_OPTION1);
		case PUZZLE_ITEM2:
		case PUZZLE_OPTION2:
			return(PUZZLE_OPTION2);
		case PUZZLE_ITEM3:
		case PUZZLE_OPTION3:
			return(PUZZLE_OPTION3);
		case PUZZLE_ITEM4:
		case PUZZLE_OPTION4:
			return(PUZZLE_OPTION4);


		case PICKUP_ITEM1:
		case PICKUP_OPTION1:
			return(PICKUP_OPTION1);
		case PICKUP_ITEM2:
		case PICKUP_OPTION2:
			return(PICKUP_OPTION2);


		case KEY_ITEM1:
		case KEY_OPTION1:
			return(KEY_OPTION1);
		case KEY_ITEM2:
		case KEY_OPTION2:
			return(KEY_OPTION2);
		case KEY_ITEM3:
		case KEY_OPTION3:
			return(KEY_OPTION3);
		case KEY_ITEM4:
		case KEY_OPTION4:
			return(KEY_OPTION4);
		case ICON_PICKUP1_ITEM:
		case ICON_PICKUP1_OPTION:
			return(ICON_PICKUP1_OPTION);
		case ICON_PICKUP2_ITEM:
		case ICON_PICKUP2_OPTION:
			return(ICON_PICKUP2_OPTION);
		case ICON_PICKUP3_ITEM:
		case ICON_PICKUP3_OPTION:
			return(ICON_PICKUP3_OPTION);
		case ICON_PICKUP4_ITEM:
		case ICON_PICKUP4_OPTION:
			return(ICON_PICKUP4_OPTION);
		case SAVEGAME_CRYSTAL_ITEM:
		case SAVEGAME_CRYSTAL_OPTION:
			return(SAVEGAME_CRYSTAL_OPTION);
	}
	return(-1);
}

void	RemoveInventoryText(void)
{
	int n;

	for (n=0;n<IT_NUMBEROF;n++)
	{
		T_RemovePrint(Inv_itemText[n]);
		Inv_itemText[n]=NULL;
	}
}

/*********************************************************************/
/*     RING FUNCTIONS  											 	 */
void	Inv_RingInit(RING_INFO *ring, sint16 type, INVENTORY_ITEM **list, sint16 qty, sint16 current, IMOTION_INFO *imo)
{
	ring->type = type;
	ring->radius = 0;
	ring->list = list;
	ring->number_of_objects = qty;
	ring->current_object = current;
	ring->angle_adder = 0x10000/qty;	// angle between each object

	if (Inventory_Mode!=INV_TITLE_MODE)
		ring->camera_pitch = 0;
	else
		ring->camera_pitch = 0x400;

	ring->rotating = 0;
	ring->rot_count = 0;
	ring->target_object = 0;
	ring->rot_adder = 0;
	ring->rot_adderL = 0;
	ring->rot_adderR = 0;


	ring->imo = imo;

	ring->camera.x_pos = 0;
	ring->camera.y_pos = CAMERA_STARTHEIGHT;
	ring->camera.z_pos = 0x380;
	ring->camera.x_rot = 0;
	ring->camera.y_rot = 0;
	ring->camera.z_rot = 0;

	Inv_RingMotionInit(ring, OPEN_FRAMES, RNG_OPENING, RNG_OPEN);
	Inv_RingMotionRadius(ring, RING_RADIUS);
	Inv_RingMotionCameraPos(ring, CAMERA_HEIGHT);
	Inv_RingMotionRotation(ring, OPEN_ROTATION, (sint16)(0xc000-(ring->current_object*ring->angle_adder)));

	ring->ringpos.x_pos = 0;
	ring->ringpos.y_pos = 0;
	ring->ringpos.z_pos = 0;
	ring->ringpos.x_rot = 0;
	ring->ringpos.y_rot = imo->rotate_target-OPEN_ROTATION;
	ring->ringpos.z_rot = 0;

#ifdef PC_VERSION
	ring->light.x = -0x600;
	ring->light.y = 0x100;
	ring->light.z = 0x400;
#endif
}

void	Inv_RingGetView(RING_INFO *ring, PHD_3DPOS *viewer)
{
	PHD_ANGLE	angles[2];

	phd_GetVectorAngles( 0-ring->camera.x_pos,CAMERA_YOFFSET-ring->camera.y_pos,ring->radius-ring->camera.z_pos, angles );
	viewer->x_pos = ring->camera.x_pos;
	viewer->y_pos = ring->camera.y_pos;
	viewer->z_pos = ring->camera.z_pos;
	viewer->x_rot = angles[1] + ring->camera_pitch;
	viewer->y_rot = angles[0];
	viewer->z_rot = 0;
}

#ifdef PSX_VERSION
#include "..\spec_psx\maths.h"
extern MATRIX3D LightCol;
extern SVECTOR3D LPos[];
#else
#include "..\specific\litesrc.h"
#endif

void	Inv_RingLight(RING_INFO *ring,sint16 object_number)
{
#ifdef PSX_VERSION

	LightCol.m00 = 0xcf0;
	LightCol.m10 = 0x680;
	LightCol.m20 = 0x000;

	LightCol.m01 = 0xcf0;
	LightCol.m11 = 0xcf0;
	LightCol.m21 = 0xcf0;

	LightCol.m02 = 0x0;
	LightCol.m12 = 0x0;
	LightCol.m22 = 0xc00;

	LPos[0].x = 4096;
	LPos[0].y = -4096;
	LPos[0].z = 3072;

	LPos[1].x = -4096;
	LPos[1].y = -4096;
	LPos[1].z = 3072;

	LPos[2].x = 0;
	LPos[2].y = 2048;
	LPos[2].z = 3072;

	SetBackColor(32, 32, 32);
	SetLightMatrices();
#else
	LightCol[M00] = 0xcf0;
	LightCol[M10] = 0x680;
	LightCol[M20] = 0x000;

	LightCol[M01] = 0xcf0;
	LightCol[M11] = 0xcf0;
	LightCol[M21] = 0xcf0;

	LightCol[M02] = 0x0;
	LightCol[M12] = 0x0;
	LightCol[M22] = 0xc00;

	LPos[0].x = 4096<<2;
	LPos[0].y = -4096<<2;
	LPos[0].z = 3072<<2;

	LPos[1].x = -4096<<2;
	LPos[1].y = -4096<<2;
	LPos[1].z = 3072<<2;

	LPos[2].x = 0<<2;
	LPos[2].y = 2048<<2;
	LPos[2].z = 3072<<2;

	smcr = 32;
	smcg = 32;
	smcb = 32;

	{

	int x,y,z;
	sint32 *mptr;

	mptr = w2v_matrix;

	x = (mptr[M00] * LPos[0].x + mptr[M01] * LPos[0].y + mptr[M02] * LPos[0].z)>>W2V_SHIFT;
	y = (mptr[M10] * LPos[0].x + mptr[M11] * LPos[0].y + mptr[M12] * LPos[0].z)>>W2V_SHIFT;
	z = (mptr[M20] * LPos[0].x + mptr[M21] * LPos[0].y + mptr[M22] * LPos[0].z)>>W2V_SHIFT;

	LPos[0].x = x;
	LPos[0].y = y;
	LPos[0].z = z;

	x = (mptr[M00] * LPos[1].x + mptr[M01] * LPos[1].y + mptr[M02] * LPos[1].z)>>W2V_SHIFT;
	y = (mptr[M10] * LPos[1].x + mptr[M11] * LPos[1].y + mptr[M12] * LPos[1].z)>>W2V_SHIFT;
	z = (mptr[M20] * LPos[1].x + mptr[M21] * LPos[1].y + mptr[M22] * LPos[1].z)>>W2V_SHIFT;

	LPos[1].x = x;
	LPos[1].y = y;
	LPos[1].z = z;

	x = (mptr[M00] * LPos[2].x + mptr[M01] * LPos[2].y + mptr[M02] * LPos[2].z)>>W2V_SHIFT;
	y = (mptr[M10] * LPos[2].x + mptr[M11] * LPos[2].y + mptr[M12] * LPos[2].z)>>W2V_SHIFT;
	z = (mptr[M20] * LPos[2].x + mptr[M21] * LPos[2].y + mptr[M22] * LPos[2].z)>>W2V_SHIFT;

	LPos[2].x = x;
	LPos[2].y = y;
	LPos[2].z = z;

	}

	/*
	PHD_ANGLE	angles[2];

	ls_divider = 0x6000;
	phd_GetVectorAngles( ring->light.x, ring->light.y, ring->light.z, angles );
	phd_RotateLight( angles[1],angles[0] );
	*/

#endif
}


#define LIT_MESHES	0x7e
#define	LONDON	2
#define	INDIA	4
#define	PERU		8
#define	NEVADA	16
#define	SPAC		32
#define	ANTARC	64

void	Inv_GlobeLight(sint16 object_number)
{
#ifdef PSX_VERSION
	if (object_number == 1)	// Globe.
	{
		LightCol.m00 = 0x000;
		LightCol.m10 = 0x100;
		LightCol.m20 = 0xf00;

		LightCol.m01 = 0x000;
		LightCol.m11 = 0x100;
		LightCol.m21 = 0xf00;

		LightCol.m02 = 0x0;
		LightCol.m12 = 0x100;
		LightCol.m22 = 0xf00;
	}
	else	if ((object_number & LIT_MESHES) == 0)	// Land.
	{
		LightCol.m00 = 0x100;
		LightCol.m10 = 0x400;
		LightCol.m20 = 0x100;

		LightCol.m01 = 0x100;
		LightCol.m11 = 0x400;
		LightCol.m21 = 0x100;

		LightCol.m02 = 0x100;
		LightCol.m12 = 0x400;
		LightCol.m22 = 0x100;
	}
	else if (	(object_number == LONDON && savegame.LondonComplete) ||
			(object_number == INDIA && savegame.IndiaComplete) ||
			(object_number == PERU && savegame.PeruComplete) ||
			(object_number == NEVADA && savegame.NevadaComplete) ||
			(object_number == SPAC && savegame.SPacificComplete) ||
			(object_number == ANTARC && savegame.AntarcticaComplete))
	{
		LightCol.m00 = rcossin_tbl[wrap<<5];
		LightCol.m10 = 0;
		LightCol.m20 = 0;
		LightCol.m01 = rcossin_tbl[wrap<<5];
		LightCol.m11 = 0;
		LightCol.m21 = 0;
		LightCol.m02 = rcossin_tbl[wrap<<5];
		LightCol.m12 = 0;
		LightCol.m22 = 0;
	}
	else
	{
		LightCol.m00 = 0;
		LightCol.m10 = rcossin_tbl[wrap<<5];
		LightCol.m20 = 0;
		LightCol.m01 = 0;
		LightCol.m11 = rcossin_tbl[wrap<<5];
		LightCol.m21 = 0;
		LightCol.m02 = 0;
		LightCol.m12 = rcossin_tbl[wrap<<5];
		LightCol.m22 = 0;
	}

	LPos[0].x = 4096;
	LPos[0].y = -4096;
	LPos[0].z = 3072;

	LPos[1].x = -4096;
	LPos[1].y = -4096;
	LPos[1].z = 3072;

	LPos[2].x = 0;
	LPos[2].y = 2048;
	LPos[2].z = 3072;

	SetBackColor(32, 32, 32);
	SetLightMatrices();
#else
	LightCol[M00] = 0xcf0;
	LightCol[M10] = 0x680;
	LightCol[M20] = 0x000;

	LightCol[M01] = 0xcf0;
	LightCol[M11] = 0xcf0;
	LightCol[M21] = 0xcf0;

	LightCol[M02] = 0x0;
	LightCol[M12] = 0x0;
	LightCol[M22] = 0xc00;

	LPos[0].x = 4096<<2;
	LPos[0].y = -4096<<2;
	LPos[0].z = 3072<<2;

	LPos[1].x = -4096<<2;
	LPos[1].y = -4096<<2;
	LPos[1].z = 3072<<2;

	LPos[2].x = 0<<2;
	LPos[2].y = 2048<<2;
	LPos[2].z = 3072<<2;

	smcr = 32;
	smcg = 32;
	smcb = 32;

	{

	int x,y,z;
	sint32 *mptr;

	mptr = w2v_matrix;

	x = (mptr[M00] * LPos[0].x + mptr[M01] * LPos[0].y + mptr[M02] * LPos[0].z)>>W2V_SHIFT;
	y = (mptr[M10] * LPos[0].x + mptr[M11] * LPos[0].y + mptr[M12] * LPos[0].z)>>W2V_SHIFT;
	z = (mptr[M20] * LPos[0].x + mptr[M21] * LPos[0].y + mptr[M22] * LPos[0].z)>>W2V_SHIFT;

	LPos[0].x = x;
	LPos[0].y = y;
	LPos[0].z = z;

	x = (mptr[M00] * LPos[1].x + mptr[M01] * LPos[1].y + mptr[M02] * LPos[1].z)>>W2V_SHIFT;
	y = (mptr[M10] * LPos[1].x + mptr[M11] * LPos[1].y + mptr[M12] * LPos[1].z)>>W2V_SHIFT;
	z = (mptr[M20] * LPos[1].x + mptr[M21] * LPos[1].y + mptr[M22] * LPos[1].z)>>W2V_SHIFT;

	LPos[1].x = x;
	LPos[1].y = y;
	LPos[1].z = z;

	x = (mptr[M00] * LPos[2].x + mptr[M01] * LPos[2].y + mptr[M02] * LPos[2].z)>>W2V_SHIFT;
	y = (mptr[M10] * LPos[2].x + mptr[M11] * LPos[2].y + mptr[M12] * LPos[2].z)>>W2V_SHIFT;
	z = (mptr[M20] * LPos[2].x + mptr[M21] * LPos[2].y + mptr[M22] * LPos[2].z)>>W2V_SHIFT;

	LPos[2].x = x;
	LPos[2].y = y;
	LPos[2].z = z;

	}









	/*
	PHD_ANGLE	angles[2];

	ls_divider = 0x6000;
	phd_GetVectorAngles( ring->light.x, ring->light.y, ring->light.z, angles );
	phd_RotateLight( angles[1],angles[0] );
	*/

#endif
}


void	Inv_RingCalcAdders(RING_INFO *ring, sint16 rotation_duration)
{
	ring->angle_adder = 0x10000/ring->number_of_objects;	// angle between each object
	ring->rot_adderL = ring->angle_adder/rotation_duration;			// rotational speed left
	ring->rot_adderR = -ring->rot_adderL;					// rotational speed right
}

void	Inv_RingDoMotions(RING_INFO *ring)
{
	INVENTORY_ITEM	*inv_item;
	IMOTION_INFO *imo;

	imo = ring->imo;

	if (imo->count)
	{
		ring->radius += imo->radius_rate;				// adjust radius
		ring->camera.y_pos += imo->camera_yrate;		// adjust camera
		ring->ringpos.y_rot += imo->rotate_rate;
		ring->camera_pitch += imo->camera_pitch_rate;

		inv_item = *(ring->list + ring->current_object);
		inv_item->pt_xrot += imo->item_ptxrot_rate;
		inv_item->x_rot += imo->item_xrot_rate;
		inv_item->ytrans += imo->item_ytrans_rate;
		inv_item->ztrans += imo->item_ztrans_rate;

		imo->count--;							// count down!
		if (!imo->count)
		{										// when done;-
			imo->status = imo->status_target;		// set status to target status

			if (imo->radius_rate)
			{
				imo->radius_rate = 0;
				ring->radius = imo->radius_target;		// set radius to target radius
			}
			if (imo->camera_yrate)
			{
				imo->camera_yrate = 0;
				ring->camera.y_pos = imo->camera_ytarget;	// set camera to target ypos
			}
			if (imo->rotate_rate)
			{
				imo->rotate_rate = 0;
				ring->ringpos.y_rot = imo->rotate_target;
			}
			if (imo->item_ptxrot_rate)
			{
				imo->item_ptxrot_rate = 0;
				inv_item->pt_xrot = imo->item_ptxrot_target;
			}
			if (imo->item_xrot_rate)
			{
				imo->item_xrot_rate   = 0;
				inv_item->x_rot = imo->item_xrot_target;
			}
			if (imo->item_ytrans_rate)
			{
				imo->item_ytrans_rate = 0;
				inv_item->ytrans = imo->item_ytrans_target;
			}
			if (imo->item_ztrans_rate)
			{
				imo->item_ztrans_rate = 0;
				inv_item->ztrans = imo->item_ztrans_target;
			}
			if (imo->camera_pitch_rate)
			{
				imo->camera_pitch_rate = 0;
				ring->camera_pitch = imo->camera_pitch_target;
			}
		}
	}
	// do rotating of current ring
	if (ring->rotating)
	{											// if rotating
		ring->ringpos.y_rot += ring->rot_adder;		// rotate ring
		ring->rot_count--;						// count down
		if (ring->rot_count==0)
		{										// when done;-
			ring->current_object = ring->target_object;	// set object
			ring->ringpos.y_rot = 0xc000-(ring->current_object*ring->angle_adder);	// set to exact angle position
			ring->rotating = 0;					// stop rotating
		}
	}
}

void	Inv_RingRotateLeft(RING_INFO *ring)
{
	ring->rotating = 1;
	ring->target_object = ring->current_object-1;

	if (ring->target_object < 0)
		ring->target_object = ring->number_of_objects-1;

	ring->rot_count = ROTATE_DURATION;
	ring->rot_adder = ring->rot_adderL;
}

void	Inv_RingRotateRight(RING_INFO *ring)
{
	ring->rotating = 1;
	ring->target_object = ring->current_object+1;

	if (ring->target_object >= ring->number_of_objects)
		ring->target_object = 0;

	ring->rot_count = ROTATE_DURATION;
	ring->rot_adder = ring->rot_adderR;
}


/*********************************************************************/
/*     MOTION FUNCTIONS  											 */

void	Inv_RingMotionInit(RING_INFO *ring, sint16 frames, sint16 status, sint16 status_target)
{
	IMOTION_INFO *imo;

	imo = ring->imo;
	imo->count = frames;
	imo->status = status;
	imo->status_target = status_target;
	imo->radius_target = 0;
	imo->radius_rate = 0;
	imo->camera_ytarget = 0;
	imo->camera_yrate = 0;
	imo->camera_pitch_target = 0;
	imo->camera_pitch_rate = 0;
	imo->rotate_target = 0;
	imo->rotate_rate = 0;
	imo->item_ptxrot_target	= 0;
	imo->item_ptxrot_rate = 0;
	imo->item_xrot_target = 0;
	imo->item_xrot_rate = 0;
	imo->item_ytrans_target = 0;
	imo->item_ytrans_rate = 0;
	imo->item_ztrans_target = 0;
	imo->item_ztrans_rate = 0;
	imo->misc = 0;
}
void	Inv_RingMotionSetup(RING_INFO *ring, sint16 status, sint16 status_target, sint16 frames)
{
	IMOTION_INFO *imo;

	imo = ring->imo;
	imo->count = frames;
	imo->status = status;
	imo->status_target = status_target;
	imo->radius_rate = 0;
	imo->camera_yrate = 0;
}

void	Inv_RingMotionRadius(RING_INFO *ring, sint16 target)
{
	IMOTION_INFO *imo;

	imo = ring->imo;
	imo->radius_target = target;
	imo->radius_rate = (target-ring->radius)/imo->count;
}

void	Inv_RingMotionRotation(RING_INFO *ring, sint16 rotation, sint16 target)
{
	IMOTION_INFO *imo;

	imo = ring->imo;
	imo->rotate_rate = rotation/imo->count;
	imo->rotate_target = target;
}

void	Inv_RingMotionCameraPos(RING_INFO *ring, sint16 target)
{
	IMOTION_INFO *imo;

	imo = ring->imo;
	imo->camera_ytarget = target;
	imo->camera_yrate = (target - ring->camera.y_pos)/imo->count;
}

void	Inv_RingMotionCameraPitch(RING_INFO *ring, sint16 target)
{
	IMOTION_INFO *imo;

	imo = ring->imo;
	imo->camera_pitch_target = target;
	imo->camera_pitch_rate = target/imo->count;
}


void	Inv_RingMotionItemSelect(RING_INFO *ring, INVENTORY_ITEM *inv_item)
{
	IMOTION_INFO *imo;

	imo = ring->imo;
	imo->item_ptxrot_target = inv_item->pt_xrot_sel;
	imo->item_ptxrot_rate   = inv_item->pt_xrot_sel/imo->count;
	imo->item_xrot_target = inv_item->x_rot_sel;
	imo->item_xrot_rate   = (inv_item->x_rot_sel-inv_item->x_rot_nosel)/imo->count;
	imo->item_ytrans_target = inv_item->ytrans_sel;
	imo->item_ytrans_rate = inv_item->ytrans_sel/imo->count;
	imo->item_ztrans_target = inv_item->ztrans_sel;
	imo->item_ztrans_rate = inv_item->ztrans_sel/imo->count;
}

void	Inv_RingMotionItemDeselect(RING_INFO *ring, INVENTORY_ITEM *inv_item)
{
	IMOTION_INFO *imo;

	imo = ring->imo;
	imo->item_ptxrot_target = 0;
	imo->item_ptxrot_rate   = 0-inv_item->pt_xrot_sel/imo->count;
	imo->item_xrot_target = inv_item->x_rot_nosel;
	imo->item_xrot_rate   = (inv_item->x_rot_nosel-inv_item->x_rot_sel)/imo->count;
	imo->item_ytrans_target = 0;
	imo->item_ytrans_rate = 0-inv_item->ytrans_sel/imo->count;
	imo->item_ztrans_target = 0;
	imo->item_ztrans_rate = 0-inv_item->ztrans_sel/imo->count;
}



/*************************************************************************************************
	R E Q U E S T E R   F U N C T I O N S
*************************************************************************************************/
#ifdef PSX_VERSION
	char	down_prompt[] = { 32,15,32,32,32,32,32,32,32,32,
									32,32,32,32,32,32,32,32,
									32,32,32,32,32,32,32,32,
									32,32,32,32,32,32,32,32,
									32,32,32,32,32,32,32,32,15,32,0 };
	char	up_prompt[] = {   32,16,32,32,32,32,32,32,32,32,
									32,32,32,32,32,32,32,32,
									32,32,32,32,32,32,32,32,
									32,32,32,32,32,32,32,32,
									32,32,32,32,32,32,32,32,16,32,0 };
#endif

void Init_Requester(REQUEST_INFO *req)
{
	int	n;

#if defined(GAMEDEBUG) && defined(PSX_VERSION)
	printf("Init_Requester\n");
#endif

	req->items = 0;
	req->heading1text = NULL;
	req->heading2text = NULL;
	req->heading1_flags = 0;
	req->heading2_flags = 0;
	req->backgroundtext = NULL;
	req->background_flags = R_USE;
	req->moreuptext = NULL;
	req->moreup_flags = R_USE;
	req->moredowntext = NULL;
	req->moredown_flags = R_USE;
	for (n=0;n<MAX_REQLINES;n++)
	{
		req->texts1[n] = NULL;
		req->texts1_flags[n] = 0;
		req->texts2[n] = NULL;
		req->texts2_flags[n] = 0;
	}
	req->itemtexts1_flags = RequesterFlags1;
	req->itemtexts2_flags = RequesterFlags2;

#ifdef PC_VERSION
	req->original_render_width=GetRenderWidth();
	req->original_render_height=GetRenderHeight();
#endif
}

void Remove_Requester(REQUEST_INFO *req)
{
	int	n;
#ifdef PSX_VERSION
	char *tptr1, *tptr2;
#endif
#if defined(GAMEDEBUG) && defined(PSX_VERSION)
	printf("Remove_Requester\n");
#endif

	T_RemovePrint(req->heading1text);	req->heading1text = NULL;
	T_RemovePrint(req->heading2text);	req->heading2text = NULL;
	T_RemovePrint(req->backgroundtext);	req->backgroundtext = NULL;
	T_RemovePrint(req->moreuptext);		req->moreuptext = NULL;
	T_RemovePrint(req->moredowntext);	req->moredowntext = NULL;
	for (n=0;n<MAX_REQLINES;n++)
	{
		T_RemovePrint(req->texts1[n]);	req->texts1[n] = NULL;
		T_RemovePrint(req->texts2[n]);	req->texts2[n] = NULL;
	}
#ifdef PSX_VERSION
	tptr1 = req->itemtexts1;
	tptr2 = req->itemtexts2;
	for (n=0;n<MAXIMUM_LEVELS*LEVLEN;n++)
	{
		*(tptr1++) = 0;
		*(tptr2++) = 0;
	}
#endif
}

void ReqItemCentreAlign(REQUEST_INFO *req, TEXTSTRING *txt)
{
	if (txt)
	{
		txt->xpos = req->xpos;
		txt->bgndOffX = 0;
	}
}

void ReqItemLeftalign(REQUEST_INFO *req, TEXTSTRING *txt)
{
	int x;
#ifdef PC_VERSION
	uint32	scaleH = GetTextScaleH(txt->scaleH);
#else
	uint32	scaleH = 0x10000;
#endif
	if (txt)
	{
		x = (( (req->pixwidth*scaleH) >>16 )/2 - T_GetTextWidth(txt)/2) - ((8*scaleH)>>16);
		txt->xpos = req->xpos - x;
		txt->bgndOffX = x;
	}
}
void ReqItemRightalign(REQUEST_INFO *req, TEXTSTRING *txt)
{
	int x;
#ifdef PC_VERSION
	uint32	scaleH = GetTextScaleH(txt->scaleH);
#else
	uint32	scaleH = 0x10000;
#endif
	if (txt)
	{
		x = (( (req->pixwidth*scaleH) >>16 )/2 - T_GetTextWidth(txt)/2) - ((8*scaleH)>>16);
		txt->xpos = req->xpos + x;
		txt->bgndOffX = -x;
	}
}

sint32 Display_Requester(REQUEST_INFO *req, int des, int backgrounds)
{
	int	n;
	int	linesheight = (req->vis_lines*req->line_height)+10;
	int	lineoneoff = req->ypos - linesheight;
	int	lineqty = req->vis_lines;

#ifdef PC_VERSION
	int nWidth=GetRenderWidth();
	int nHeight=GetRenderHeight();
	if (nWidth!=req->original_render_width || nHeight!=req->original_render_height)
	{
		Remove_Requester(req);	// Handy Dude frig (but I don't know if it's 100% cool)
		req->original_render_width=nWidth;
		req->original_render_height=nHeight;
	}
#endif

	req->itemtexts1_flags = RequesterFlags1;
	req->itemtexts2_flags = RequesterFlags2;

	if (req->items<req->vis_lines)
		lineqty = req->items;

	for (n=0;n<lineqty;n++)
	{
		if (req->texts1[n])
		{
			T_RemovePrint(req->texts1[n]);
			req->texts1[n] = NULL;
		}
	}

	/* PRINT HEADING */
	if ( req->heading1_flags&R_USE )
	{
		if (!req->heading1text)
		{
			long	tcol;

			if (req->heading1_flags &R_HEADING)
				tcol = 5;
			else if (req->heading1_flags &R_BEST_TIME)
				tcol = 10;
			else if (req->heading1_flags &R_NORMAL_TIME)
				tcol = 2;
			else if (req->heading1_flags & R_NO_TIME)
				tcol = 11;
			else
				tcol = 0;

			req->heading1text = T_Print(req->xpos, lineoneoff-req->line_height-10, tcol, req->heading1_str);
			T_CentreH(req->heading1text, 1);
			T_BottomAlign(req->heading1text, 1);
			if (backgrounds)
			{
				T_AddBackground(req->heading1text, (uint16)((sint16)req->pixwidth-4),0, 0,0,8, C_BLACK, req_main_gour1, D_TRANS2);
				T_AddOutline(req->heading1text, 1, C_ORANGE, req_main_gour2, (uint16)NULL);
			}
		}
		if (req->heading1_flags&R_LEFTALIGN)
			ReqItemLeftalign( req, req->heading1text);
		if (req->heading1_flags&R_RIGHTALIGN)
			ReqItemRightalign( req, req->heading1text);
	}
	/* PRINT HEADING 2 */
	if ( req->heading2_flags&R_USE )
	{
		if (!req->heading2text)
		{
			req->heading2text = T_Print(req->xpos, lineoneoff-req->line_height-10, req->zpos, req->heading2_str);
			T_CentreH(req->heading2text, 1);
			T_BottomAlign(req->heading2text, 1);
			if (backgrounds)
			{
				T_AddBackground(req->heading2text, (sint16)(req->pixwidth-4),0, 0,0,8, (sint16)C_BLACK, req_main_gour1, (sint16)D_TRANS2);
				T_AddOutline(req->heading2text, 1, C_ORANGE, req_main_gour2, (uint16)NULL);
			}
		}
		if (req->heading2_flags&R_LEFTALIGN)
			ReqItemLeftalign( req, req->heading2text);
		if (req->heading2_flags&R_RIGHTALIGN)
			ReqItemRightalign( req, req->heading2text);
	}
	/* ADD REQUESTER BACKGROUND */
	if ( backgrounds && !req->backgroundtext && req->background_flags&R_USE)
	{
		req->backgroundtext = T_Print(req->xpos, lineoneoff-req->line_height-12, 0, " ");
		T_CentreH(req->backgroundtext, 1);
		T_BottomAlign(req->backgroundtext, 1);
		T_AddBackground(req->backgroundtext, (sint16)req->pixwidth, (sint16)(linesheight+req->line_height+12), 0,0,48, (sint16)C_BLACK, req_bgnd_gour1, (sint16)D_TRANS1);
		T_AddOutline(req->backgroundtext, 1, C_BLUE, req_bgnd_gour2, (uint16)NULL);
	}

	/* PRINT ARROW PROMPTS UP */
	if (req->line_offset)
	{
		if (!req->moreuptext && req->moreup_flags&R_USE)
		{
#ifdef PC_VERSION
//			req->moreuptext = T_Print(req->xpos, lineoneoff-req->line_height, 0, " ");
//			T_AddBackground(req->moreuptext, 16, 6, 0,8,8, C_BLACK, req_bgnd_moreup, D_TRANS1);
#else
			req->moreuptext = T_Print(req->xpos-5, lineoneoff-req->line_height+6, 0, up_prompt );
#endif
			T_CentreH(req->moreuptext, 1);
			T_BottomAlign(req->moreuptext, 1);
		}
	}
	else
	{
		T_RemovePrint(req->moreuptext);
		req->moreuptext = NULL;
	}

	/* PRINT ARROW PROMPTS DOWN */
	if (req->items > (req->line_offset+req->vis_lines))
	{
		if (!req->moredowntext && req->moredown_flags&R_USE)
		{
#ifdef PC_VERSION
//			req->moredowntext = T_Print(req->xpos, req->ypos-8, 0, " ");
//			T_AddBackground(req->moredowntext, 16, 6, 0,0,8, C_BLACK, req_bgnd_moredown, D_TRANS1);
#else
			req->moredowntext = T_Print(req->xpos-5, req->ypos-16, 0, down_prompt );
#endif
			T_CentreH(req->moredowntext, 1);
			T_BottomAlign(req->moredowntext, 1);
		}
	}
	else
	{
		T_RemovePrint(req->moredowntext);
		req->moredowntext = NULL;
	}


	/* PRINT VISIBLE REQUESTER ITEMS */
	for (n=0;n<lineqty;n++)
	{
		// Handle requester items 1
//		if (req->texts1_flags[n]&R_USE)
		if (req->itemtexts1_flags[n+req->line_offset]&R_USE)
		{
			if (!req->texts1[n])
			{
				long	tcol;

				if (req->itemtexts1_flags[n+req->line_offset]&R_HEADING)
					tcol = 5;
				else if (req->itemtexts1_flags[n+req->line_offset]&R_BEST_TIME)
					tcol = 10;
				else if (req->itemtexts1_flags[n+req->line_offset]&R_NORMAL_TIME)
					tcol = 2;
				else if (req->itemtexts1_flags[n+req->line_offset]&R_NO_TIME)
					tcol = 11;
				else
					tcol = 0;

 				req->texts1[n] = T_Print(0,lineoneoff+(n*req->line_height),tcol, req->itemtexts1+((n+req->line_offset)*req->itemtextlen));
				T_CentreH(req->texts1[n], 1);
				T_BottomAlign(req->texts1[n], 1);
			}

			if (!req->noselector && (n+req->line_offset) == req->selected)
			{
				T_AddBackground(req->texts1[n], (sint16)(req->pixwidth-12),19, 0,0,16, (sint16)C_BLACK, req_unsel_gour1, (sint16)D_TRANS1);
				T_AddOutline(req->texts1[n], 1, C_ORANGE, req_sel_gour2, (uint16)NULL);
			}
			else
			{
				T_RemoveBackground(req->texts1[n]);
				T_RemoveOutline(req->texts1[n]);
			}
//			if (req->texts1_flags[n]&R_LEFTALIGN)
			if (req->itemtexts1_flags[n+req->line_offset]&R_LEFTALIGN)
				ReqItemLeftalign( req, req->texts1[n]);
//			else if (req->texts1_flags[n]&R_RIGHTALIGN)
			else if (req->itemtexts1_flags[n+req->line_offset]&R_RIGHTALIGN)
				ReqItemRightalign( req, req->texts1[n]);
			else
				ReqItemCentreAlign( req, req->texts1[n]);
		}
		else
		{
			T_RemovePrint(req->texts1[n]);
			T_RemoveBackground(req->texts1[n]);
			T_RemoveOutline(req->texts1[n]);
			req->texts1[n] = NULL;
		}
		// Handle requester items 2
//		if (req->texts2_flags[n]&R_USE)
		if (req->itemtexts2_flags[n+req->line_offset]&R_USE)
		{
			if (!req->texts2[n])
			{
 				req->texts2[n] = T_Print(0,lineoneoff+(n*req->line_height),0, req->itemtexts2+((n+req->line_offset)*req->itemtextlen));
				T_CentreH(req->texts2[n], 1);
				T_BottomAlign(req->texts2[n], 1);
			}
//			if (req->texts2_flags[n]&R_LEFTALIGN)
			if (req->itemtexts2_flags[n+req->line_offset]&R_LEFTALIGN)
				ReqItemLeftalign( req, req->texts2[n]);
//			if (req->texts2_flags[n]&R_RIGHTALIGN)
			else if (req->itemtexts2_flags[n+req->line_offset]&R_RIGHTALIGN)
				ReqItemRightalign( req, req->texts2[n]);
			else
				ReqItemCentreAlign( req, req->texts2[n]);
		}
		else
		{
			T_RemovePrint(req->texts2[n]);
			T_RemoveBackground(req->texts2[n]);
			T_RemoveOutline(req->texts2[n]);
			req->texts2[n] = NULL;
		}
	}
	/* IF SCROLLING LIST UP/DOWN */
//	if (req->line_offset != req->line_oldoffset)
	if (0)
	{
		// Change Level names due to movement
		for (n=0;n<lineqty;n++)
		{
//			if (req->texts1[n] && req->texts1_flags[n]&R_USE)
			if (req->texts1[n] && req->itemtexts1_flags[n+req->line_offset]&R_USE)
				T_ChangeText(req->texts1[n], req->itemtexts1+((n+req->line_offset)*req->itemtextlen));
//			if (req->texts1_flags[n]&R_LEFTALIGN)
			if (req->itemtexts1_flags[n+req->line_offset]&R_LEFTALIGN)
				ReqItemLeftalign( req, req->texts1[n]);
//			if (req->texts1_flags[n]&R_RIGHTALIGN)
			else if (req->itemtexts1_flags[n+req->line_offset]&R_RIGHTALIGN)
				ReqItemRightalign( req, req->texts1[n]);
			else
				ReqItemCentreAlign( req, req->texts1[n]);


//			if (req->texts2[n] && req->texts2_flags[n]&R_USE)
			if (req->texts2[n] && req->itemtexts2_flags[n+req->line_offset]&R_USE)
				T_ChangeText(req->texts2[n], req->itemtexts2+((n+req->line_offset)*req->itemtextlen));

//			if (req->texts2_flags[n]&R_LEFTALIGN)
			if (req->itemtexts2_flags[n+req->line_offset]&R_LEFTALIGN)
				ReqItemLeftalign( req, req->texts2[n]);
//			if (req->texts2_flags[n]&R_RIGHTALIGN)
			else if (req->itemtexts2_flags[n+req->line_offset]&R_RIGHTALIGN)
				ReqItemRightalign( req, req->texts2[n]);
			else
				ReqItemCentreAlign( req, req->texts2[n]);
		}
	}

	if (inputDB&IN_BACK)
	{
		if (req->noselector)
		{
			req->line_oldoffset = req->line_offset;
			if (req->line_offset+req->vis_lines<req->items)
			{
				req->line_offset++;
				SoundEffect(115,NULL,PITCH_SHIFT+0x4000000);
			}
		}
		else
		{
			if (req->selected<req->items-1)
			{
				req->selected++;
				SoundEffect(115,NULL,PITCH_SHIFT+0x4000000);
			}
			req->line_oldoffset = req->line_offset;
			if (req->selected>(req->line_offset+req->vis_lines-1))
			{
				req->line_offset++;
//				SoundEffect(115,NULL,PITCH_SHIFT+0x4000000);
			}
		}
	}
	else if (inputDB&IN_FORWARD)
	{
		if (req->noselector)
		{
			req->line_oldoffset = req->line_offset;
			if (req->line_offset>0)
			{
				req->line_offset--;
				SoundEffect(115,NULL,PITCH_SHIFT+0x4000000);
			}
		}
		else
		{
			if (req->selected>0)
			{
				req->selected--;
				SoundEffect(115,NULL,PITCH_SHIFT+0x4000000);
			}
			req->line_oldoffset = req->line_offset;
			if (req->selected<req->line_offset)
			{
				req->line_offset--;
//				SoundEffect(115,NULL,PITCH_SHIFT+0x4000000);
			}
		}
	}
	else if (inputDB&SELECT_ITEM)
	{
#ifdef PC_VERSION
		if (!strncmp(req->texts1[req->selected-req->line_offset]->string, GF_PCStrings[PCSTR_SAVESLOT], 12) &&
			 !strcmp(passport_text1->string, GF_GameStrings[GT_LOADGAME]))
		{
			input = 0;
			return(0);
		}
#endif
		Remove_Requester(req);
		return(req->selected+1);
	}
	else if (inputDB&DESELECT_ITEM && des==1)
	{
		Remove_Requester(req);
		return(-1);
	}
#ifdef PSX_VERSION
	if (reset_flag && des!=2)
		Remove_Requester(req);
#endif
//#ifdef GAMEDEBUG
//	sprintf(exit_message,"Offs=%d %d %d",req->line_offset,req->noselector, req->selected);
//	PrintDbug(0,1,exit_message);
//#endif
	return(0);
}

void SetRequesterHeading( REQUEST_INFO *req, char *text1, uint32 flags1, char *text2, uint32 flags2 )
{
	T_RemovePrint(req->heading1text); req->heading1text = NULL;
	T_RemovePrint(req->heading2text); req->heading2text = NULL;

	if (text1)
	{
		sprintf( req->heading1_str, text1 );
		req->heading1_flags = R_USE|flags1;
	}
	else
	{
		sprintf( req->heading1_str, "u" );
		req->heading1_flags = 0;
	}
	if (text2)
	{
		sprintf( req->heading2_str, text2 );
		req->heading2_flags = R_USE|flags2;
	}
	else
	{
		sprintf( req->heading2_str, "u" );
		req->heading2_flags = 0;
	}
}

void RemoveAllReqItems( REQUEST_INFO *req )
{
//	int n;
#if defined(GAMEDEBUG) && defined(PSX_VERSION)
	printf("RemoveAllReqItems\n");
#endif
	req->items = 0;
	req->line_offset = 0;
	req->selected = 0;
}

void ChangeRequesterItem( REQUEST_INFO *req, int item, char *text1, uint32 flags1, char *text2, uint32 flags2 )
{
	T_RemovePrint(req->texts1[item]); req->texts1[item] = NULL;
	T_RemovePrint(req->texts2[item]); req->texts2[item] = NULL;

	if ( text1 )
	{
		sprintf( req->itemtexts1+(item*req->itemtextlen), text1 );
//		req->texts1_flags[item] = R_USE|flags1;
		req->itemtexts1_flags[item] = R_USE|flags1;
	}
	else
	{
//		req->texts1_flags[item] = 0;
		req->itemtexts1_flags[item] = 0;
	}

	if ( text2 )
	{
		sprintf( req->itemtexts2+(item*req->itemtextlen), text2 );
//		req->texts2_flags[item] = R_USE|flags2;
		req->itemtexts2_flags[item] = R_USE|flags2;
	}
	else
	{
//		req->texts2_flags[item] = 0;
		req->itemtexts2_flags[item] = 0;
	}
}

void AddRequesterItem( REQUEST_INFO *req, char *text1, uint32 flags1, char *text2, uint32 flags2 )
{
	req->itemtexts1_flags = RequesterFlags1;
	req->itemtexts2_flags = RequesterFlags2;

	if ( text1 )
	{
		sprintf( req->itemtexts1+(req->items*req->itemtextlen), text1 );
//		req->texts1_flags[req->items] = R_USE|flags1;
		req->itemtexts1_flags[req->items] = R_USE|flags1;
	}
	else
	{
//		req->texts1_flags[req->items] = 0;
		req->itemtexts1_flags[req->items] = 0;
	}

	if ( text2 )
	{
		sprintf( req->itemtexts2+(req->items*req->itemtextlen), text2 );
//		req->texts2_flags[req->items] = R_USE|flags2;
		req->itemtexts2_flags[req->items] = R_USE|flags2;
	}
	else
	{
//		req->texts2_flags[req->items] = 0;
		req->itemtexts2_flags[req->items] = 0;
	}
	req->items++;
}

#ifdef PC_VERSION
void SetPCRequesterSize(REQUEST_INFO *req, int maxlines, int ypos)
{
 	int height = GetRenderHeight();
 	int lines = (height/2) / (TEXT_HEIGHT+7);
 	if (lines>maxlines)
 		lines = maxlines;
 	req->ypos = ypos;
 	req->vis_lines = lines;
}
#endif

/*********************************************************************************
	S T A T I S T I C S   D I S P L A Y S
*********************************************************************************/
REQUEST_INFO Stats_Requester={0};
//char stats1_info[16][32];
//char stats2_info[16][32];


#define NUM_ASS_TIMES 10

int	AddAssaultTime(uint32 time)
{
	int	i,j,insert=0;

	for (i=0;i<NUM_ASS_TIMES;i++)
	{
		if (savegame.best_assault_times[i]==0 || time < savegame.best_assault_times[i] )
		{
			insert = 1;
			break;
		}
	}

	if (insert)
	{
		for (j=NUM_ASS_TIMES-1;j>i;j--)
			savegame.best_assault_times[j] = savegame.best_assault_times[j-1];
		savegame.best_assault_times[i] = time;
		return(1);
	}
	return(0);
}

int	AddQuadbikeTime(uint32 time)
{
	int	i,j,insert=0;

	for (i=0;i<NUM_ASS_TIMES;i++)
	{
		if (savegame.best_quadbike_times[i]==0 || time < savegame.best_quadbike_times[i] )
		{
			insert = 1;
			break;
		}
	}

	if (insert)
	{
		for (j=NUM_ASS_TIMES-1;j>i;j--)
			savegame.best_quadbike_times[j] = savegame.best_quadbike_times[j-1];
		savegame.best_quadbike_times[i] = time;
		return(1);
	}
	return(0);
}



void ShowGymStatsText( char *time_str, int type )
{
	// type: 0=endgame 1=in-game
	static int mode=0;
	int	select,m,s,h, i;
	char	str[32];

	if (mode==1)
	{
		if ((select = Display_Requester(&Stats_Requester,1, 1)))
			mode = 0;
		else
			input = inputDB = 0;
	}
	else
	{
		Stats_Requester.noselector = 1;
#ifdef PSX_VERSION
		Stats_Requester.ypos = -44;
		Stats_Requester.vis_lines = 7;
//		RemovePromptText();
#ifdef NTSC
		Stats_Requester.line_height = TEXT_HEIGHT+4;
#else
		Stats_Requester.line_height = TEXT_HEIGHT+7;
#endif
#else
		SetPCRequesterSize(&Stats_Requester,7,-32);
/*
		if (GetRenderHeight()>=400)
		{
			Stats_Requester.ypos = -80;
			Stats_Requester.vis_lines = 7;
		}
		else
		{
			Stats_Requester.ypos = 0;
			Stats_Requester.vis_lines = 5;
		}
*/
		Stats_Requester.line_height = TEXT_HEIGHT+7;
#endif
		Stats_Requester.items = 0;
		Stats_Requester.selected = 0;
		Stats_Requester.line_offset = 0;
		Stats_Requester.line_oldoffset = 0;
		Stats_Requester.pixwidth = 296;
		Stats_Requester.xpos = 0;
		Stats_Requester.zpos = 0;
#ifdef PSX_VERSION
		Stats_Requester.itemtexts1 = Save_Game_Strings;
		Stats_Requester.itemtexts2 = Save_Game_Strings2;
#else
		Stats_Requester.itemtexts1 = &Valid_Level_Strings[0][0];
		Stats_Requester.itemtexts2 = &Valid_Level_Strings2[0][0];
#endif
		Stats_Requester.itemtextlen = LEVLEN;

		Init_Requester(&Stats_Requester);

		SetRequesterHeading( &Stats_Requester, GF_GameStrings[GT_BESTTIMES], R_CENTRE, NULL,0);

		for(i=-1;i<NUM_ASS_TIMES;i++)
		{
			if (i==-1)
			{
				if (gameflow.language == 1)	// FRENCH
					AddRequesterItem(&Stats_Requester, "Entra(inement", R_CENTRE|R_HEADING, NULL, 0);
				else if (gameflow.language == 2)	// GERMAN
					AddRequesterItem(&Stats_Requester, "Hinderniskurs", R_CENTRE|R_HEADING, NULL, 0);
				else if (gameflow.language == 5)	// ITALIAN
					AddRequesterItem(&Stats_Requester, "Circuito d'addestramento", R_CENTRE|R_HEADING, NULL, 0);
				else if (gameflow.language == 6)	// SPANISH
					AddRequesterItem(&Stats_Requester, "Asaltar Carrera", R_CENTRE|R_HEADING, NULL, 0);
				else
					AddRequesterItem(&Stats_Requester, "Assault Course", R_CENTRE|R_HEADING, NULL, 0);
				continue;
			}

			if (savegame.best_assault_times[i]==0)
				break;

			s = savegame.best_assault_times[i]/30;
			h = ((savegame.best_assault_times[i]%30)*334)/100;
			m = s/60;
			s = s%60;

			sprintf(str,"%d:%2.2d.%02d",m,s,h);
			if (i==0)
				AddRequesterItem(&Stats_Requester, str, R_CENTRE|R_BEST_TIME, NULL, 0);
			else
				AddRequesterItem(&Stats_Requester, str, R_CENTRE|R_NORMAL_TIME, NULL, 0);
		}

		if (i==0)
			AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_NOTIMES], R_CENTRE|R_NO_TIME, NULL, 0);

		if (savegame.QuadbikeKeyFlag)
		{
			AddRequesterItem(&Stats_Requester, " ", R_CENTRE, NULL, 0);
			for(i=-1;i<NUM_ASS_TIMES;i++)
			{
				if (i==-1)
				{
					if (gameflow.language == 1)	// FRENCH
						AddRequesterItem(&Stats_Requester, "Course de moto", R_CENTRE|R_HEADING, NULL, 0);
					else if (gameflow.language == 2)	// GERMAN
						AddRequesterItem(&Stats_Requester, "Quadbike Teststrecke", R_CENTRE|R_HEADING, NULL, 0);
					else if (gameflow.language == 5)	// ITALIAN
						AddRequesterItem(&Stats_Requester, "Circuito per moto", R_CENTRE|R_HEADING, NULL, 0);
					else if (gameflow.language == 6)	// SPANISH
						AddRequesterItem(&Stats_Requester, "Circuito Moto Quad", R_CENTRE|R_HEADING, NULL, 0);
					else
				    		AddRequesterItem(&Stats_Requester, "Quadbike Track", R_CENTRE|R_HEADING, NULL, 0);
					continue;
				}

				if (savegame.best_quadbike_times[i]==0)
					break;

				s = savegame.best_quadbike_times[i]/30;
				h = ((savegame.best_quadbike_times[i]%30)*334)/100;
				m = s/60;
				s = s%60;

				sprintf(str,"%d:%2.2d.%02d",m,s,h);
				if (i==0)
					AddRequesterItem(&Stats_Requester, str, R_CENTRE|R_BEST_TIME, NULL, 0);
				else
					AddRequesterItem(&Stats_Requester, str, R_CENTRE|R_NORMAL_TIME, NULL, 0);
			}

			if (i==0)
				AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_NOTIMES], R_CENTRE|R_NO_TIME, NULL, 0);
		}

		mode = 1;
	}
}


void ShowStatsText( char *time_str, int type )
{
	static int	mode=0;
	int	select,numsecrets,distance,len=0;
	char	str[32];

	if (mode==1)
	{
		ChangeRequesterItem(&Stats_Requester, 0, GF_GameStrings[GT_STAT_TIME],R_LEFTALIGN, time_str ,R_RIGHTALIGN);
		if ((select = Display_Requester(&Stats_Requester,type,1)))
			mode = 0;
		else
			input = inputDB = 0;
	}
	else
	{
		Stats_Requester.noselector = 1;
#ifdef PSX_VERSION
		Stats_Requester.ypos = -44;
//		if (type)
			Stats_Requester.vis_lines = 7;
//		else
//			Stats_Requester.vis_lines = 8;

//		RemovePromptText();
#ifdef NTSC
		Stats_Requester.line_height = TEXT_HEIGHT+4;
#else
		Stats_Requester.line_height = TEXT_HEIGHT+7;
#endif
#else
		SetPCRequesterSize(&Stats_Requester,7,-32);
/*		if (GetRenderHeight()>=400)
		{
			Stats_Requester.ypos = -80;
			Stats_Requester.vis_lines = 7;
		}
		else
		{
			Stats_Requester.ypos = 0;
			Stats_Requester.vis_lines = 5;
		}
*/
		Stats_Requester.line_height = TEXT_HEIGHT+7;
#endif
		Stats_Requester.items = 0;
		Stats_Requester.selected = 0;
		Stats_Requester.line_offset = 0;
		Stats_Requester.line_oldoffset = 0;
		Stats_Requester.pixwidth = 304;
		Stats_Requester.xpos = 0;
		Stats_Requester.zpos = 0;
#ifdef PSX_VERSION
		Stats_Requester.itemtexts1 = Save_Game_Strings;
		Stats_Requester.itemtexts2 = Save_Game_Strings2;
#else
		Stats_Requester.itemtexts1 = Valid_Level_Strings[0];
		Stats_Requester.itemtexts2 = Valid_Level_Strings2[0];
#endif
		Stats_Requester.itemtextlen = LEVLEN;

		Init_Requester(&Stats_Requester);

		// HEADING:	Current Level Name
		SetRequesterHeading( &Stats_Requester, GF_Level_Names[CurrentLevel], R_CENTRE, NULL,0);
		// LINE1:	Elapsed Time
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_TIME],R_LEFTALIGN, time_str ,R_RIGHTALIGN);
		// LINE2:	Secrets Found
		/*
		if (GF_NumSecrets)
		{
			numsecrets = (savegame.secrets&1) + ((savegame.secrets&2)>>1) + ((savegame.secrets&4)>>2);
//			sprintf(str,"%d",numsecrets);
			if (numsecrets)
			{
				if (savegame.secrets&1)
					str[len++] = 127;
				else
				{
					str[len++] = ' ';
					str[len++] = ' ';
					str[len++] = ' ';
				}
				if (savegame.secrets&2)
					str[len++] = (char)128;
				else
				{
					str[len++] = ' ';
					str[len++] = ' ';
					str[len++] = ' ';
				}
				if (savegame.secrets&4)
					str[len++] = (char)129;
				else
				{
					str[len++] = ' ';
					str[len++] = ' ';
					str[len++] = ' ';
				}
				str[len] = 0;
			}
			else
				sprintf(str,GF_GameStrings[GT_NONE]);
			AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_SECRETS],R_LEFTALIGN, str,R_RIGHTALIGN);
		}
		*/
		numsecrets = (savegame.secrets&1) + ((savegame.secrets&2)>>1) + ((savegame.secrets&4)>>2) + ((savegame.secrets&8)>>3)
					+ ((savegame.secrets&16)>>4) + ((savegame.secrets&32)>>5) + ((savegame.secrets&64)>>6) + ((savegame.secrets&128)>>7); //I know, I know...
		if (LevelSecrets[CurrentLevel])
			sprintf(str,"%d %s %d",numsecrets, GF_GameStrings[GT_OF], LevelSecrets[CurrentLevel]);
		else
			sprintf(str,"%s",GF_GameStrings[GT_NONE]);

		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_SECRETS],R_LEFTALIGN, str,R_RIGHTALIGN);

		// LINE3:	Kills
		sprintf(str,"%d",savegame.kills);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_KILLS],R_LEFTALIGN,str,R_RIGHTALIGN);
		// LINE4:	Ammo Used
		sprintf(str,"%d",(int)savegame.ammo_used);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_AMMO],R_LEFTALIGN,str,R_RIGHTALIGN);
		// LINE5:	Hits
		sprintf(str,"%d",(int)savegame.ammo_hit);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_RATIO],R_LEFTALIGN,str,R_RIGHTALIGN);
		// LINE6:	Health Used
		if (savegame.health_used&1)
			sprintf(str,"%d.5",savegame.health_used>>1);
		else
			sprintf(str,"%d.0",savegame.health_used>>1);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_HEALTH],R_LEFTALIGN,str,R_RIGHTALIGN);

		// LINE7:	Distance Travelled
		distance = savegame.distance_travelled/445;
		if (distance>=1000)
			sprintf(str,"%d.%02dkm", distance/1000, distance%100);
		else
			sprintf(str,"%dm", distance);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_DISTANCE],R_LEFTALIGN,str,R_RIGHTALIGN);

		mode = 1;
	}
}

void ShowEndStatsText( void )
{
	static int	mode=0;
	int	select,numsecrets,distance, i, num;
	char	str[32];
	int	h=0,m=0,s=0;
	int totallevels = gameflow.num_levels-gameflow.num_demos;

	if (mode==1)
	{
		if ((select = Display_Requester(&Stats_Requester,0,1)))
			mode = 0;
		else
			input = inputDB = 0;
	}
	else
	{
		Stats_Requester.noselector = 1;
#ifdef PSX_VERSION
		Stats_Requester.ypos = -44;
		Stats_Requester.vis_lines = 7;
//		RemovePromptText();
#ifdef NTSC
		Stats_Requester.line_height = TEXT_HEIGHT+4;
#else
		Stats_Requester.line_height = TEXT_HEIGHT+7;
#endif
#else
		SetPCRequesterSize(&Stats_Requester,7,-32);
/*		if (GetRenderHeight()>=400)
		{
			Stats_Requester.ypos = -80;
			Stats_Requester.vis_lines = 7;
		}
		else
		{
			Stats_Requester.ypos = 0;
			Stats_Requester.vis_lines = 5;
		}
*/
		Stats_Requester.line_height = TEXT_HEIGHT+7;
#endif
		Stats_Requester.items = 0;
		Stats_Requester.selected = 0;
		Stats_Requester.line_offset = 0;
		Stats_Requester.line_oldoffset = 0;
		Stats_Requester.pixwidth = 304;
		Stats_Requester.xpos = 0;
		Stats_Requester.zpos = 0;
#ifdef PSX_VERSION
		Stats_Requester.itemtexts1 = Save_Game_Strings;
		Stats_Requester.itemtexts2 = Save_Game_Strings2;
		for (i=0;i<MAXIMUM_LEVELS*LEVLEN;i++)
			Save_Game_Strings[i] = Save_Game_Strings2[i] = 0;
#else
		Stats_Requester.itemtexts1 = Valid_Level_Strings[0];
		Stats_Requester.itemtexts2 = Valid_Level_Strings2[0];
#endif
		Stats_Requester.itemtextlen = LEVLEN;

		Init_Requester(&Stats_Requester);

		// HEADING:	End of game stats
		SetRequesterHeading( &Stats_Requester, GF_GameStrings[GT_GAMESTATS], R_CENTRE, NULL,0);
		// LINE1:	Elapsed Time
		s=0;
		for (i=1;i<totallevels;i++)
			s += savegame.start[i].timer;
		s = s/30;
		h = s/3600;
		m = (s/60)%60;
		s = s%60;
		sprintf(str,"%02d:%02d:%02d",h,m,s);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_TIME],R_LEFTALIGN, str ,R_RIGHTALIGN);

		// LINE2:	Secrets Found
		numsecrets = num = 0;
		for (i=0;i<totallevels;i++)
		{
			numsecrets += (savegame.start[i].secrets_found&1) + ((savegame.start[i].secrets_found&2)>>1) + ((savegame.start[i].secrets_found&4)>>2) + ((savegame.start[i].secrets_found&8)>>3)
						+ ((savegame.start[i].secrets_found&16)>>4) + ((savegame.start[i].secrets_found&32)>>5) + ((savegame.start[i].secrets_found&64)>>6) + ((savegame.start[i].secrets_found&128)>>7);
			num += LevelSecrets[i];
		}
		sprintf(str,"%d %s %d", numsecrets,GF_GameStrings[GT_OF], num);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_SECRETS],R_LEFTALIGN, str,R_RIGHTALIGN);

		// LINE3:	Kills
		num=0;
		for (i=1;i<totallevels;i++)
			num += savegame.start[i].kills;
		sprintf(str,"%d",num);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_KILLS],R_LEFTALIGN,str,R_RIGHTALIGN);

		// LINE4:	Ammo Used
		num=0;
		for (i=1;i<totallevels;i++)
			num += savegame.start[i].ammo_used;
		sprintf(str,"%d",num);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_AMMO],R_LEFTALIGN,str,R_RIGHTALIGN);

		// LINE5:	Hits
		num=0;
		for (i=1;i<totallevels;i++)
			num += savegame.start[i].ammo_hit;
		sprintf(str,"%d",num);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_RATIO],R_LEFTALIGN,str,R_RIGHTALIGN);
		// LINE6:	Health Used
		num=0;
		for (i=1;i<totallevels;i++)
			num += savegame.start[i].health_used;
		if (num&1)
			sprintf(str,"%d.5",num>>1);
		else
			sprintf(str,"%d.0",num>>1);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_HEALTH],R_LEFTALIGN,str,R_RIGHTALIGN);

		// LINE7:	Distance Travelled
		num=0;
		for (i=1;i<totallevels;i++)
			num += savegame.start[i].distance_travelled;

		distance = num/445;
		if (distance>=1000)
			sprintf(str,"%d.%02dkm", distance/1000, distance%100);
		else
			sprintf(str,"%dm", distance);
		AddRequesterItem(&Stats_Requester, GF_GameStrings[GT_STAT_DISTANCE],R_LEFTALIGN,str,R_RIGHTALIGN);

		mode = 1;
	}
}


//##	#if defined(PSX_VERSION) && defined(NTSC) && !defined(JAPAN)
int PauseResetRequester( void )
{
	static int mode=0;
	int i, select=0;

	if (mode==1)
	{
		if ((select = Display_Requester(&Stats_Requester,0,0))>0)
		{
			SoundEffect(109,NULL,NULL);
			mode = 0;
		}
		else
			input = inputDB = 0;
	}
	else
	{
		Stats_Requester.noselector = 0;
		Stats_Requester.ypos = -44;
		Stats_Requester.vis_lines = 2;
//		RemovePromptText();
		Stats_Requester.line_height = TEXT_HEIGHT+8;
		Stats_Requester.items = 0;
		Stats_Requester.selected = 1;
		Stats_Requester.line_offset = 0;
		Stats_Requester.line_oldoffset = 0;
		Stats_Requester.pixwidth = 100;
		Stats_Requester.xpos = 0;
		Stats_Requester.zpos = 0;
		Stats_Requester.itemtexts1 = Save_Game_Strings;
		Stats_Requester.itemtexts2 = Save_Game_Strings2;

		for (i=0;i<MAXIMUM_LEVELS*LEVLEN;i++)
			Save_Game_Strings[i] = Save_Game_Strings2[i] = 0;

		Stats_Requester.itemtextlen = LEVLEN;

		Init_Requester(&Stats_Requester);

		SetRequesterHeading(&Stats_Requester, GF_GameStrings[GT_EXIT2TITLE], R_CENTRE|R_NO_TIME, NULL,0);
		AddRequesterItem(&Stats_Requester,  GF_PSXStrings[PSSTR_GAPSTRING6], R_CENTRE,  NULL,0);
		AddRequesterItem(&Stats_Requester,  GF_PSXStrings[PSSTR_GAPSTRING7], R_CENTRE, NULL,0);

		mode = 1;
	}
	return(select);
}


int SureRequester( void )
{
	static int mode=0;
	int i, select=0;

	if (mode==1)
	{
		if ((select = Display_Requester(&Stats_Requester,0,0))>0)
		{
			SoundEffect(109,NULL,NULL);
			mode = 0;
		}
		else
			input = inputDB = 0;
	}
	else
	{
		Stats_Requester.noselector = 0;
		Stats_Requester.ypos = -44;
		Stats_Requester.vis_lines = 2;
//		RemovePromptText();
		Stats_Requester.line_height = TEXT_HEIGHT+8;
		Stats_Requester.items = 0;
		Stats_Requester.selected = 1;
		Stats_Requester.line_offset = 0;
		Stats_Requester.line_oldoffset = 0;
		Stats_Requester.pixwidth = 80;
		Stats_Requester.xpos = 0;
		Stats_Requester.zpos = 0;
		Stats_Requester.itemtexts1 = Save_Game_Strings;
		Stats_Requester.itemtexts2 = Save_Game_Strings2;
		for (i=0;i<MAXIMUM_LEVELS*LEVLEN;i++)
			Save_Game_Strings[i] = Save_Game_Strings2[i] = 0;
		Stats_Requester.itemtextlen = LEVLEN;

		Init_Requester(&Stats_Requester);

		SetRequesterHeading(&Stats_Requester, GF_PSXStrings[PSSTR_GAPSTRING5], R_CENTRE|R_NO_TIME, NULL,0);
		AddRequesterItem(&Stats_Requester, GF_PSXStrings[PSSTR_GAPSTRING6], R_CENTRE,  NULL,0);
		AddRequesterItem(&Stats_Requester, GF_PSXStrings[PSSTR_GAPSTRING7], R_CENTRE, NULL,0);

		mode = 1;
	}
	return(select);
}
//##	#endif


//#if defined(DEMO1) && !defined(NTSC)
int GetLanguageRequester( void )
{
	static int	mode=0;
	int	i, select=0;

	if (mode==1)
	{
		if ((select = Display_Requester(&Stats_Requester,2,0))>0)
			mode = 0;
		else
			input = inputDB = 0;
	}
	else
	{
		Stats_Requester.noselector = 0;
		Stats_Requester.ypos = -44;
		Stats_Requester.vis_lines = 3;
//		RemovePromptText();
		Stats_Requester.line_height = TEXT_HEIGHT+4;
		Stats_Requester.items = 0;
		Stats_Requester.selected = 0;
		Stats_Requester.line_offset = 0;
		Stats_Requester.line_oldoffset = 0;
		Stats_Requester.pixwidth = 100;
		Stats_Requester.xpos = 0;
		Stats_Requester.zpos = 0;
		Stats_Requester.itemtexts1 = Save_Game_Strings;
		Stats_Requester.itemtexts2 = Save_Game_Strings2;
		for (i=0;i<MAXIMUM_LEVELS*LEVLEN;i++)
			Save_Game_Strings[i] = Save_Game_Strings2[i] = 0;
		Stats_Requester.itemtextlen = LEVLEN;

		Init_Requester(&Stats_Requester);

		SetRequesterHeading(&Stats_Requester, "Select Language", R_CENTRE, NULL,0);
		AddRequesterItem(&Stats_Requester, "English", R_CENTRE,  NULL,0);
		AddRequesterItem(&Stats_Requester, "Deutsch", R_CENTRE, NULL,0);
		AddRequesterItem(&Stats_Requester, "Francais", R_CENTRE, NULL,0);

		mode = 1;
	}
	return(select);
}
//#endif
