code:
#include "common.h"
#if defined DETECT_JOYSTICK_MENU && defined XINPUT
#include <windows.h>
#include <xinput.h>
#if !defined(PSAPI_VERSION) || (PSAPI_VERSION > 1)
#pragma comment( lib, "Xinput9_1_0.lib" )
#else
#pragma comment( lib, "Xinput.lib" )
#endif
#endif
#include "platform.h"
#include "crossplatform.h"
#include "Renderer.h"
#include "Frontend.h"
#include "Font.h"
#include "Camera.h"
#include "main.h"
#include "MBlur.h"
#include "postfx.h"
#include "custompipes.h"
#include "RwHelper.h"
#include "Text.h"
#include "Streaming.h"
#include "FileLoader.h"
#include "Collision.h"
#include "ModelInfo.h"
#include "Pad.h"
#include "ControllerConfig.h"
#include "IniFile.h"
#include "CarCtrl.h"
#include "Population.h"

// Menu screens array is at the bottom of the file.

#ifdef PC_MENU

#ifdef CUSTOM_FRONTEND_OPTIONS

#if defined(IMPROVED_VIDEOMODE) && !defined(GTA_HANDHELD)
	#define VIDEOMODE_SELECTOR MENUACTION_CFO_SELECT, "FEM_SCF", { new CCFOSelect((int8*)&FrontEndMenuManager.m_nPrefsWindowed, "VideoMode", "Windowed", screenModes, 2, true, ScreenModeAfterChange, true) },
#else
	#define VIDEOMODE_SELECTOR
#endif

#ifdef MULTISAMPLING
	#define MULTISAMPLING_SELECTOR MENUACTION_CFO_DYNAMIC, "FED_AAS", { new CCFODynamic((int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, "Graphics", "MultiSampling", MultiSamplingDraw, MultiSamplingButtonPress) },
#else
	#define MULTISAMPLING_SELECTOR
#endif

#ifdef CUTSCENE_BORDERS_SWITCH
	#define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, "FEM_CSB", { new CCFOSelect((int8 *)&CMenuManager::m_PrefsCutsceneBorders, "Display", "CutsceneBorders", off_on, 2, false) },
#else
	#define CUTSCENE_BORDERS_TOGGLE
#endif

#ifdef FREE_CAM
	#define FREE_CAM_TOGGLE MENUACTION_CFO_SELECT, "FEC_FRC", { new CCFOSelect((int8*)&TheCamera.bFreeCam, "Display", "FreeCam", off_on, 2, false) },
#else
	#define FREE_CAM_TOGGLE
#endif

#ifdef PS2_ALPHA_TEST
	#define DUALPASS_SELECTOR MENUACTION_CFO_SELECT, "FEM_2PR", { new CCFOSelect((int8*)&gPS2alphaTest, "Graphics", "PS2AlphaTest", off_on, 2, false) },
#else
	#define DUALPASS_SELECTOR
#endif

#ifdef PED_CAR_DENSITY_SLIDERS
	// 0.2f - 3.4f makes it possible to have 1.0f somewhere inbetween
	#define DENSITY_SLIDERS \
		MENUACTION_CFO_SLIDER, "FEM_PED", { new CCFOSlider(&CIniFile::PedNumberMultiplier, "Display", "PedDensity", 0.2f, 3.4f, PedDensityChange) }, \
		MENUACTION_CFO_SLIDER, "FEM_CAR", { new CCFOSlider(&CIniFile::CarNumberMultiplier, "Display", "CarDensity", 0.2f, 3.4f, CarDensityChange) },
#else
	#define DENSITY_SLIDERS
#endif

#ifdef NO_ISLAND_LOADING
	#define ISLAND_LOADING_SELECTOR MENUACTION_CFO_SELECT, "FEM_ISL", { new CCFOSelect((int8*)&CMenuManager::m_PrefsIslandLoading, "Graphics", "IslandLoading", islandLoadingOpts, ARRAY_SIZE(islandLoadingOpts), true, IslandLoadingAfterChange) },
#else
	#define ISLAND_LOADING_SELECTOR
#endif

#ifdef EXTENDED_COLOURFILTER
	#define POSTFX_SELECTORS \
		MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "Graphics", "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false) }, \
		MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "Graphics", "MotionBlur", off_on, 2, false) },
#else
	#define POSTFX_SELECTORS
#endif

#ifdef INVERT_LOOK_FOR_PAD
	#define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, "FEC_IVP", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, "Controller", "InvertPad", off_on, 2, false) },
#else
	#define INVERT_PAD_SELECTOR
#endif

#ifdef GAMEPAD_MENU
	#define SELECT_CONTROLLER_TYPE  MENUACTION_CFO_SELECT, "FEC_TYP", { new CCFOSelect((int8*)&CMenuManager::m_PrefsControllerType, "Controller", "Type", controllerTypes, ARRAY_SIZE(controllerTypes), false, ControllerTypeAfterChange) },
#else
	#define SELECT_CONTROLLER_TYPE
#endif

const char *filterNames[] = { "FEM_NON", "FEM_SIM", "FEM_NRM", "FEM_MOB" };
const char *off_on[] = { "FEM_OFF", "FEM_ON" };

void RestoreDefGraphics(int8 action) {
	if (action != FEOPTION_ACTION_SELECT)
		return;

	#ifdef PS2_ALPHA_TEST
		gPS2alphaTest = false;
	#endif
	#ifdef MULTISAMPLING
		FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0;
	#endif
	#ifdef NO_ISLAND_LOADING
	    	if (!FrontEndMenuManager.m_bGameNotLoaded) {
	    		FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW;
			CCollision::bAlreadyLoaded = false;
			CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
			CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
			CStreaming::RemoveUnusedBuildings(CGame::currLevel);
			CStreaming::RequestIslands(CGame::currLevel);
			CStreaming::LoadAllRequestedModels(true);
	    	} else
	    		FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW;
	#endif
	#ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those
		CMenuManager::m_PrefsFrameLimiter = true;
		CMenuManager::m_PrefsVsyncDisp = true;
		CMenuManager::m_PrefsVsync = true;
		CMenuManager::m_PrefsUseWideScreen = false;
		FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode;
		#if GTA_VERSION >= GTA3_PC_11
			if (_dwOperatingSystemVersion == OS_WIN98) {
				CMBlur::BlurOn = false;
				CMBlur::MotionBlurClose();
			} else {
				CMBlur::BlurOn = true;
				CMBlur::MotionBlurOpen(Scene.camera);
			}
		#else
			CMBlur::BlurOn = true;
		#endif
		FrontEndMenuManager.SaveSettings();
	#endif
}

void RestoreDefDisplay(int8 action) {
	if (action != FEOPTION_ACTION_SELECT)
		return;

	#ifdef CUTSCENE_BORDERS_SWITCH
		CMenuManager::m_PrefsCutsceneBorders = true;
	#endif
	#ifdef FREE_CAM
		TheCamera.bFreeCam = false;
	#endif
	#ifdef PED_CAR_DENSITY_SLIDERS
		CIniFile::LoadIniFile();
	#endif
	#ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those
		CMenuManager::m_PrefsBrightness = 256;
		CMenuManager::m_PrefsLOD = 1.2f;
		CRenderer::ms_lodDistScale = 1.2f;
		CMenuManager::m_PrefsShowSubtitles = true;
		FrontEndMenuManager.SaveSettings();
	#endif
}

#ifdef NO_ISLAND_LOADING
const char *islandLoadingOpts[] = { "FEM_LOW", "FEM_MED", "FEM_HIG" };
void IslandLoadingAfterChange(int8 before, int8 after) {
	if (!FrontEndMenuManager.m_bGameNotLoaded) {
		if (after > FrontEndMenuManager.ISLAND_LOADING_LOW) {
		    FrontEndMenuManager.m_PrefsIslandLoading = before; // calls below needs previous mode :shrug:

		    if (after == FrontEndMenuManager.ISLAND_LOADING_HIGH)
			    CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC);
		    if (before == FrontEndMenuManager.ISLAND_LOADING_LOW) {
			    if (CGame::currLevel != LEVEL_INDUSTRIAL)
				    CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL);
			    if (CGame::currLevel != LEVEL_COMMERCIAL)
				    CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL);
			    if (CGame::currLevel != LEVEL_SUBURBAN)
				    CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN);
			    CCollision::bAlreadyLoaded = true;
			    FrontEndMenuManager.m_PrefsIslandLoading = after;
			    CStreaming::RequestBigBuildings(CGame::currLevel);

		    } else if (before == FrontEndMenuManager.ISLAND_LOADING_HIGH) {
			    FrontEndMenuManager.m_PrefsIslandLoading = after;
			    CStreaming::RequestIslands(CGame::currLevel);
		    } else
		    	    FrontEndMenuManager.m_PrefsIslandLoading = after;

		} else { // low
		    CCollision::bAlreadyLoaded = false;
		    CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
		    CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
		    CStreaming::RemoveUnusedBuildings(CGame::currLevel);
		    CStreaming::RequestIslands(CGame::currLevel);
		}

		CStreaming::LoadAllRequestedModels(true);
	}

	FrontEndMenuManager.SetHelperText(0);
}
#endif

#ifdef PED_CAR_DENSITY_SLIDERS
void PedDensityChange(float before, float after) {
	CPopulation::MaxNumberOfPedsInUse = DEFAULT_MAX_NUMBER_OF_PEDS * after;
}

void CarDensityChange(float before, float after) {
	CCarCtrl::MaxNumberOfCarsInUse = DEFAULT_MAX_NUMBER_OF_CARS * after;
}
#endif

#ifndef MULTISAMPLING
void GraphicsGoBack() {
}
#else
void GraphicsGoBack() {
	FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
}

void MultiSamplingButtonPress(int8 action) {
	if (action == FEOPTION_ACTION_SELECT) {
		if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
			FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel;
			_psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode);
			FrontEndMenuManager.SetHelperText(0);
			FrontEndMenuManager.SaveSettings();
		}
	} else if (action == FEOPTION_ACTION_LEFT || action == FEOPTION_ACTION_RIGHT) {
		if (FrontEndMenuManager.m_bGameNotLoaded) {
			FrontEndMenuManager.m_nDisplayMSAALevel += (action == FEOPTION_ACTION_RIGHT ? 1 : -1);

			int i = 0;
			int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels();
			while (maxAA != 1) {
				i++;
				maxAA >>= 1;
			}

			if (FrontEndMenuManager.m_nDisplayMSAALevel < 0)
				FrontEndMenuManager.m_nDisplayMSAALevel = i;
			else if (FrontEndMenuManager.m_nDisplayMSAALevel > i)
				FrontEndMenuManager.m_nDisplayMSAALevel = 0;
		}
	} else if (action == FEOPTION_ACTION_FOCUSLOSS) {
		if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
			FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
			FrontEndMenuManager.SetHelperText(3);
		}
	}
}

wchar* MultiSamplingDraw(bool *disabled, bool userHovering) {
	static wchar unicodeTemp[64];
	if (userHovering) {
		if (FrontEndMenuManager.m_nDisplayMSAALevel == FrontEndMenuManager.m_nPrefsMSAALevel) {
			if (FrontEndMenuManager.m_nHelperTextMsgId == 1) // Press enter to apply
				FrontEndMenuManager.ResetHelperText();
		} else {
			FrontEndMenuManager.SetHelperText(1);
		}
	} else {
		if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
			FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
		}
	}

	if (!FrontEndMenuManager.m_bGameNotLoaded)
		*disabled = true;

	switch (FrontEndMenuManager.m_nDisplayMSAALevel) {
		case 0:
			return TheText.Get("FEM_OFF");
		default:
			sprintf(gString, "%iX", 1 << (FrontEndMenuManager.m_nDisplayMSAALevel));
			AsciiToUnicode(gString, unicodeTemp);
			return unicodeTemp;
	}
}
#endif

#ifdef IMPROVED_VIDEOMODE
const char* screenModes[] = { "FED_FLS", "FED_WND" };
void ScreenModeAfterChange(int8 before, int8 after)
{
	_psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); // apply same resolution
	FrontEndMenuManager.SetHelperText(0);
}

#endif

#ifdef DETECT_JOYSTICK_MENU
wchar selectedJoystickUnicode[128];
int cachedButtonNum = -1;

wchar* DetectJoystickDraw(bool* disabled, bool userHovering) {

#if defined RW_GL3 && !defined LIBRW_SDL2
	int numButtons;
	int found = -1;
	const char *joyname;
	if (userHovering) {
		for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) {
			if ((joyname = glfwGetJoystickName(i))) {
				const uint8* buttons = glfwGetJoystickButtons(i, &numButtons);
				for (int j = 0; j < numButtons; j++) {
					if (buttons[j]) {
						found = i;
						break;
					}
				}
				if (found != -1)
					break;
			}
		}

		if (found != -1 && PSGLOBAL(joy1id) != found) {
			if (PSGLOBAL(joy1id) != -1 && PSGLOBAL(joy1id) != found)
				PSGLOBAL(joy2id) = PSGLOBAL(joy1id);
			else
				PSGLOBAL(joy2id) = -1;

			strcpy(gSelectedJoystickName, joyname);
			PSGLOBAL(joy1id) = found;
			cachedButtonNum = numButtons;
		}
	}
	if (PSGLOBAL(joy1id) == -1)
#elif defined XINPUT
	int found = -1;
	XINPUT_STATE xstate;
	memset(&xstate, 0, sizeof(XINPUT_STATE));
	if (userHovering) {
		for (int i = 0; i <= 3; i++) {
			if (XInputGetState(i, &xstate) == ERROR_SUCCESS) {
				if (xstate.Gamepad.bLeftTrigger || xstate.Gamepad.bRightTrigger) {
					found = i;
					break;
				}
				for (int j = XINPUT_GAMEPAD_DPAD_UP; j != XINPUT_GAMEPAD_Y << 1; j = (j << 1)) {
					if (xstate.Gamepad.wButtons & j) {
						found = i;
						break;
					}
				}
				if (found != -1)
					break;
			}
		}
		if (found != -1 && CPad::XInputJoy1 != found) {
			// We should never leave pads -1, so we can process them when they're connected and kinda support hotplug.
			CPad::XInputJoy2 = (CPad::XInputJoy1 == -1 ? (found + 1) % 4 : CPad::XInputJoy1);
			CPad::XInputJoy1 = found;
			cachedButtonNum = 0; // fake too, because xinput bypass CControllerConfig
		}
	}
	sprintf(gSelectedJoystickName, "%d", CPad::XInputJoy1); // fake, on xinput we only store gamepad ids(thanks MS) so this is a temp variable to be used below
	if (CPad::XInputJoy1 == -1)
#endif
		AsciiToUnicode("Not found", selectedJoystickUnicode);
	else
		AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode);

	return selectedJoystickUnicode;
}

void DetectJoystickGoBack() {
	if (cachedButtonNum != -1) {
#ifdef LOAD_INI_SETTINGS
		ControlsManager.InitDefaultControlConfigJoyPad(cachedButtonNum);
		SaveINIControllerSettings();
#else
		// Otherwise no way to save gSelectedJoystickName or ms_padButtonsInited anyway :shrug: Why do you even use this config.??
#endif
		cachedButtonNum = -1;
	}
}
#endif

#ifdef GAMEPAD_MENU
const char* controllerTypes[] = { "FEC_DS2", "FEC_DS3", "FEC_DS4", "FEC_360", "FEC_ONE", "FEC_NSW" };
void ControllerTypeAfterChange(int8 before, int8 after)
{
	FrontEndMenuManager.LoadController(after);
}
#endif

CMenuScreenCustom aScreens[MENUPAGES] = {
	// MENUPAGE_NONE = 0
	{ "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, },

	// MENUPAGE_STATS = 1
	{ "FET_STA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
		MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_NEW_GAME = 2
	{ "FET_SGA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
		MENUACTION_CHANGEMENU, "FES_SNG", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD },
		MENUACTION_POPULATESLOTS_CHANGEMENU, "GMLOAD",  { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT },
		MENUACTION_POPULATESLOTS_CHANGEMENU, "FES_DGA", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT },
		MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_BRIEFS = 3
	{ "FET_BRE", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
		MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_CONTROLLER_SETTINGS = 4
#if defined(GAMEPAD_MENU) && !defined(GTA_HANDHELD)
	{ "FET_AGS", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
#else
	{ "FET_AGS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
#endif
		MENUACTION_CTRLCONFIG,		"FEC_CCF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
		MENUACTION_CTRLDISPLAY,		"FEC_CDP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
		INVERT_PAD_SELECTOR
		MENUACTION_CTRLVIBRATION,	"FEC_VIB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
		SELECT_CONTROLLER_TYPE
		MENUACTION_CHANGEMENU,		"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_SOUND_SETTINGS = 5
	{ "FET_AUD", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
		MENUACTION_MUSICVOLUME,		"FEA_MUS", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
		MENUACTION_SFXVOLUME,		"FEA_SFX", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
#ifdef EXTERNAL_3D_SOUND
		MENUACTION_AUDIOHW,			"FEA_3DH", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
		MENUACTION_SPEAKERCONF,		"FEA_SPK", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
#endif
#ifdef AUDIO_REFLECTIONS
		MENUACTION_DYNAMICACOUSTIC,	"FET_DAM", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
#endif
		MENUACTION_RADIO,			"FEA_RSS", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
		MENUACTION_RESTOREDEF,		"FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
		MENUACTION_CHANGEMENU,		"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

#ifndef GRAPHICS_MENU_OPTIONS
	// MENUPAGE_DISPLAY_SETTINGS = 6
	{ "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
		MENUACTION_BRIGHTNESS,	"FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		MENUACTION_DRAWDIST,	"FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		DENSITY_SLIDERS
		MENUACTION_FRAMESYNC,	"FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		MENUACTION_FRAMELIMIT,	"FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
#ifndef EXTENDED_COLOURFILTER
		MENUACTION_TRAILS,		"FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
#endif
		MENUACTION_SUBTITLES,	"FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		MENUACTION_WIDESCREEN,	"FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		MENUACTION_SCREENRES,	"FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		VIDEOMODE_SELECTOR
		MULTISAMPLING_SELECTOR
		ISLAND_LOADING_SELECTOR
		DUALPASS_SELECTOR
		CUTSCENE_BORDERS_TOGGLE
		FREE_CAM_TOGGLE
		POSTFX_SELECTORS
		// re3.cpp inserts here pipeline selectors if neo/neo.txd exists and EXTENDED_PIPELINES defined
		MENUACTION_RESTOREDEF,	"FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		MENUACTION_CHANGEMENU,	"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},
#else
	// MENUPAGE_DISPLAY_SETTINGS = 6
	{ "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
		MENUACTION_BRIGHTNESS,	"FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		MENUACTION_DRAWDIST,	"FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		DENSITY_SLIDERS
		CUTSCENE_BORDERS_TOGGLE
		FREE_CAM_TOGGLE
		MENUACTION_SUBTITLES,	"FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		MENUACTION_CFO_DYNAMIC,	"FET_DEF", { new CCFODynamic(nil, nil, nil, nil, RestoreDefDisplay) },
		MENUACTION_CHANGEMENU,	"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},
#endif

	// MENUPAGE_LANGUAGE_SETTINGS = 7
	{ "FET_LAN", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
		MENUACTION_LANG_ENG,	"FEL_ENG", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
		MENUACTION_LANG_FRE,	"FEL_FRE", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
		MENUACTION_LANG_GER,	"FEL_GER", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
		MENUACTION_LANG_ITA,	"FEL_ITA", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
		MENUACTION_LANG_SPA,    "FEL_SPA", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
		// CustomFrontendOptionsPopulate will add languages here, if files are found
		MENUACTION_CHANGEMENU,	"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_CHOOSE_LOAD_SLOT = 8
	{ "FET_LG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil,
		MENUACTION_CHANGEMENU,	"FESZ_CA", { nil, SAVESLOT_NONE,	MENUPAGE_NEW_GAME },
		MENUACTION_CHECKSAVE,	"FEM_SL0", { nil, SAVESLOT_1,		MENUPAGE_LOAD_SLOT_CONFIRM },
		MENUACTION_CHECKSAVE,	"FEM_SL1", { nil, SAVESLOT_2,		MENUPAGE_LOAD_SLOT_CONFIRM },
		MENUACTION_CHECKSAVE,	"FEM_SL2", { nil, SAVESLOT_3,		MENUPAGE_LOAD_SLOT_CONFIRM },
		MENUACTION_CHECKSAVE,	"FEM_SL3", { nil, SAVESLOT_4,		MENUPAGE_LOAD_SLOT_CONFIRM },
		MENUACTION_CHECKSAVE,	"FEM_SL4", { nil, SAVESLOT_5,		MENUPAGE_LOAD_SLOT_CONFIRM },
		MENUACTION_CHECKSAVE,	"FEM_SL5", { nil, SAVESLOT_6,		MENUPAGE_LOAD_SLOT_CONFIRM },
		MENUACTION_CHECKSAVE,	"FEM_SL6", { nil, SAVESLOT_7,		MENUPAGE_LOAD_SLOT_CONFIRM },
		MENUACTION_CHECKSAVE,	"FEM_SL7", { nil, SAVESLOT_8,		MENUPAGE_LOAD_SLOT_CONFIRM },
	},

	// MENUPAGE_CHOOSE_DELETE_SLOT = 9
	{ "FET_DG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil,
		MENUACTION_CHANGEMENU,	"FESZ_CA",	{ nil, SAVESLOT_NONE,	MENUPAGE_NEW_GAME },
		MENUACTION_CHANGEMENU,	"FEM_SL0",	{ nil, SAVESLOT_1,		MENUPAGE_DELETE_SLOT_CONFIRM },
		MENUACTION_CHANGEMENU,	"FEM_SL1",	{ nil, SAVESLOT_2,		MENUPAGE_DELETE_SLOT_CONFIRM },
		MENUACTION_CHANGEMENU,	"FEM_SL2",	{ nil, SAVESLOT_3,		MENUPAGE_DELETE_SLOT_CONFIRM },
		MENUACTION_CHANGEMENU,	"FEM_SL3",	{ nil, SAVESLOT_4,		MENUPAGE_DELETE_SLOT_CONFIRM },
		MENUACTION_CHANGEMENU,	"FEM_SL4",	{ nil, SAVESLOT_5,		MENUPAGE_DELETE_SLOT_CONFIRM },
		MENUACTION_CHANGEMENU,	"FEM_SL5",	{ nil, SAVESLOT_6,		MENUPAGE_DELETE_SLOT_CONFIRM },
		MENUACTION_CHANGEMENU,	"FEM_SL6",	{ nil, SAVESLOT_7,		MENUPAGE_DELETE_SLOT_CONFIRM },
		MENUACTION_CHANGEMENU,	"FEM_SL7",	{ nil, SAVESLOT_8,		MENUPAGE_DELETE_SLOT_CONFIRM },
	},

	// MENUPAGE_NEW_GAME_RELOAD = 10
	{ "FET_NG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil,
		MENUACTION_LABEL,		"FESZ_QR",	{ nil, SAVESLOT_NONE,	MENUPAGE_NONE },
		MENUACTION_CHANGEMENU,	"FEM_NO",	{ nil, SAVESLOT_NONE,	MENUPAGE_NEW_GAME },
		MENUACTION_NEWGAME,		"FEM_YES",	{ nil, SAVESLOT_NONE,	MENUPAGE_NEW_GAME_RELOAD },
	},

	// MENUPAGE_LOAD_SLOT_CONFIRM = 11
	{ "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, nil, nil,
		 MENUACTION_LABEL,		"FESZ_QL",	{ nil, SAVESLOT_NONE,	MENUPAGE_NONE },
		 MENUACTION_CHANGEMENU,	"FEM_NO",	{ nil, SAVESLOT_NONE,	MENUPAGE_CHOOSE_LOAD_SLOT },
		 MENUACTION_CHANGEMENU,	"FEM_YES",	{ nil, SAVESLOT_NONE,	MENUPAGE_LOADING_IN_PROGRESS },
	},

	// MENUPAGE_DELETE_SLOT_CONFIRM = 12
	{ "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,
		 MENUACTION_LABEL,		"FESZ_QD",	{ nil, SAVESLOT_NONE,  MENUPAGE_NONE },
		 MENUACTION_CHANGEMENU,	"FEM_NO",	{ nil, SAVESLOT_NONE,  MENUPAGE_CHOOSE_DELETE_SLOT },
		 MENUACTION_CHANGEMENU,	"FEM_YES",	{ nil, SAVESLOT_NONE,	MENUPAGE_DELETING },
	},

	// MENUPAGE_NO_MEMORY_CARD = 13
	{ "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		// hud adjustment page in mobile
	},

	// MENUPAGE_LOADING_IN_PROGRESS = 14
	{ "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		MENUACTION_LABEL, "FED_LDW", { nil, SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM },
	},

	// MENUPAGE_DELETING_IN_PROGRESS = 15
	{ "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		MENUACTION_LABEL, "FEDL_WR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_PS2_LOAD_FAILED = 16
	{ "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		MENUACTION_LABEL, "FES_LOE", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_DELETE_FAILED = 17
	{ "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		MENUACTION_LABEL, "FES_DEE", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT },
	},

	// MENUPAGE_DEBUG_MENU = 18
	{ "FED_DBG", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
		MENUACTION_RELOADIDE,	"FED_RID", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_RELOADIPL,	"FED_RIP", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_SETDBGFLAG,	"FED_DFL", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_SWITCHBIGWHITEDEBUGLIGHT,	"FED_DLS", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_PEDROADGROUPS,	"FED_SPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_CARROADGROUPS,	"FED_SCR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_COLLISIONPOLYS,	"FED_SCP", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_PARSEHEAP,	"FED_PAH", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_SHOWCULL,	"FED_SCZ", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_DEBUGSTREAM,	"FED_DSR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_CHANGEMENU,	"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_MEMORY_CARD_DEBUG = 19
	{ "FEM_MCM", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
		MENUACTION_REGMEMCARD1,	"FEM_RMC", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_TESTFORMATMEMCARD1,	"FEM_TFM", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_TESTUNFORMATMEMCARD1,	"FEM_TUM", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_CREATEROOTDIR,	"FEM_CRD", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_CREATELOADICONS,	"FEM_CLI", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_FILLWITHGUFF,	"FEM_FFF", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_SAVEONLYTHEGAME,	"FEM_SOG", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_SAVEGAME,	"FEM_STG", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_SAVEGAMEUNDERGTA,	"FEM_STS", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_CREATECOPYPROTECTED,	"FEM_CPD", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_MEMORY_CARD_TEST = 20
	{ "FEM_MC2", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,

	},

	// MENUPAGE_MULTIPLAYER_MAIN = 21
	{ "FET_MP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,

	},

	// MENUPAGE_PS2_SAVE_FAILED = 22
	{ "MCDNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_PS2_SAVE_FAILED_2 = 23
	{ "MCGNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// Unused in PC but anyway
	// MENUPAGE_SAVE = 24
#ifdef PS2_SAVE_DIALOG
	{ "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		MENUACTION_CHANGEMENU,			"FESZ_SA",	{ nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
		MENUACTION_RESUME_FROM_SAVEZONE,	"FESZ_CA",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},
#else
	{ "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		MENUACTION_LABEL,				"FES_SCG",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_POPULATESLOTS_CHANGEMENU,			"GMSAVE",	{ nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
		MENUACTION_RESUME_FROM_SAVEZONE,	"FESZ_CA",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},
#endif

	// MENUPAGE_NO_MEMORY_CARD_2 = 25
	{ "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		MENUACTION_CHANGEMENU,	"FESZ_CA",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_CHOOSE_SAVE_SLOT = 26
	{ "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		MENUACTION_RESUME_FROM_SAVEZONE,	"FESZ_CA", { nil, SAVESLOT_NONE,	MENUPAGE_NONE },
		MENUACTION_CHANGEMENU,			"FEM_SL1", { nil, SAVESLOT_1,		MENUPAGE_SAVE_OVERWRITE_CONFIRM },
		MENUACTION_CHANGEMENU,			"FEM_SL2", { nil, SAVESLOT_2,		MENUPAGE_SAVE_OVERWRITE_CONFIRM },
		MENUACTION_CHANGEMENU,			"FEM_SL3", { nil, SAVESLOT_3,		MENUPAGE_SAVE_OVERWRITE_CONFIRM },
		MENUACTION_CHANGEMENU,			"FEM_SL4", { nil, SAVESLOT_4,		MENUPAGE_SAVE_OVERWRITE_CONFIRM },
		MENUACTION_CHANGEMENU,			"FEM_SL5", { nil, SAVESLOT_5,		MENUPAGE_SAVE_OVERWRITE_CONFIRM },
		MENUACTION_CHANGEMENU,			"FEM_SL6", { nil, SAVESLOT_6,		MENUPAGE_SAVE_OVERWRITE_CONFIRM },
		MENUACTION_CHANGEMENU,			"FEM_SL7", { nil, SAVESLOT_7,		MENUPAGE_SAVE_OVERWRITE_CONFIRM },
		MENUACTION_CHANGEMENU,			"FEM_SL8", { nil, SAVESLOT_8,		MENUPAGE_SAVE_OVERWRITE_CONFIRM },
	},

	// MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27
	{ "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
		MENUACTION_LABEL,		"FESZ_QO", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_CHANGEMENU,	"FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS },
		MENUACTION_CHANGEMENU,	"FEM_NO",  { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
	},

	// MENUPAGE_MULTIPLAYER_MAP = 28
	{ "FET_MAP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,

	},

	// MENUPAGE_MULTIPLAYER_CONNECTION = 29
	{ "FET_CON", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,

	},

	// MENUPAGE_MULTIPLAYER_FIND_GAME = 30
	{ "FET_FG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,

	},

	// MENUPAGE_MULTIPLAYER_MODE = 31
	{ "FET_GT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,

	},

	// MENUPAGE_MULTIPLAYER_CREATE = 32
	{ "FET_HG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,

	},

	// MENUPAGE_MULTIPLAYER_START = 33
	{ "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,

	},

	// MENUPAGE_SKIN_SELECT_OLD = 34
	{ "FET_PS", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,

	},

	// MENUPAGE_CONTROLLER_PC = 35
	{ "FET_CTL", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
#ifdef PC_PLAYER_CONTROLS
		MENUACTION_CTRLMETHOD,	"FET_CME", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
#endif
		MENUACTION_KEYBOARDCTRLS,"FET_RDK", { nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS },
#ifdef GAMEPAD_MENU
		MENUACTION_CHANGEMENU, "FET_AGS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
#endif
#ifdef DETECT_JOYSTICK_MENU
		MENUACTION_CHANGEMENU,	"FEC_JOD", { nil, SAVESLOT_NONE, MENUPAGE_DETECT_JOYSTICK },
#endif
		MENUACTION_CHANGEMENU,	"FET_AMS", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
		MENUACTION_RESTOREDEF,	"FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
		MENUACTION_CHANGEMENU,	"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_CONTROLLER_PC_OLD1 = 36
	{ "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
		MENUACTION_GETKEY,	"FEC_PLB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
		MENUACTION_GETKEY,	"FEC_CWL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
		MENUACTION_GETKEY,	"FEC_CWR", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
		MENUACTION_GETKEY,	"FEC_LKT", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
		MENUACTION_GETKEY,	"FEC_PJP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
		MENUACTION_GETKEY,	"FEC_PSP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
		MENUACTION_GETKEY,	"FEC_TLF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
		MENUACTION_GETKEY,	"FEC_TRG", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
		MENUACTION_GETKEY,	"FEC_CCM", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
		MENUACTION_CHANGEMENU,	"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},

	// MENUPAGE_CONTROLLER_PC_OLD2 = 37
	{ "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,

	},

	// MENUPAGE_CONTROLLER_PC_OLD3 = 38
   { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
		MENUACTION_GETKEY,	"FEC_LUP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
		MENUACTION_GETKEY,	"FEC_LDN", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
		MENUACTION_GETKEY,	"FEC_SMS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
		MENUACTION_SHOWHEADBOB,	"FEC_GSL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
		MENUACTION_CHANGEMENU,	"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
   },

   // MENUPAGE_CONTROLLER_PC_OLD4 = 39
   { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,

   },

   // MENUPAGE_CONTROLLER_DEBUG = 40
   { "FEC_DBG", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
		MENUACTION_GETKEY,	"FEC_TGD",	{ nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
		MENUACTION_GETKEY,	"FEC_TDO",	{ nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
		MENUACTION_GETKEY,	"FEC_TSS",	{ nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
		MENUACTION_GETKEY,	"FEC_SMS",	{ nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
		MENUACTION_CHANGEMENU,	"FEDS_TB",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
   },

   // MENUPAGE_OPTIONS = 41
   { "FET_OPT", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
#ifdef GTA_HANDHELD
		MENUACTION_CHANGEMENU,		"FET_CTL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
#else
		MENUACTION_CHANGEMENU,		"FET_CTL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
#endif
		MENUACTION_LOADRADIO,		"FET_AUD", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
		MENUACTION_CHANGEMENU,		"FET_DIS", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
#ifdef GRAPHICS_MENU_OPTIONS
		MENUACTION_CHANGEMENU,		"FET_GFX", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS },
#endif
		MENUACTION_CHANGEMENU,		"FET_LAN", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
		MENUACTION_PLAYERSETUP,		"FET_PSU", { nil, SAVESLOT_NONE, MENUPAGE_SKIN_SELECT },
		MENUACTION_CHANGEMENU,		"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
   },

   // MENUPAGE_EXIT = 42
   { "FET_QG", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
	   MENUACTION_LABEL,		"FEQ_SRE",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
	   MENUACTION_DONTCANCEL,	"FEM_NO",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
	   MENUACTION_CANCELGAME,	"FEM_YES",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
   },

   // MENUPAGE_SAVING_IN_PROGRESS = 43
   { "", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
	   MENUACTION_LABEL,	"FES_WAR",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
   },

   // MENUPAGE_SAVE_SUCCESSFUL = 44
   { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
	   MENUACTION_LABEL,				"FES_SSC",	{ nil, SAVESLOT_LABEL,	MENUPAGE_NONE },
	   MENUACTION_RESUME_FROM_SAVEZONE,	"FEC_OKK",	{ nil, SAVESLOT_NONE,	MENUPAGE_CHOOSE_SAVE_SLOT },
   },

   // MENUPAGE_DELETING = 45
   { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,
	   MENUACTION_LABEL,	"FED_DLW",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
   },

   // MENUPAGE_DELETE_SUCCESS = 46
   { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,
		MENUACTION_LABEL,		"DEL_FNM", { nil, SAVESLOT_NONE,	MENUPAGE_NONE },
		MENUACTION_CHANGEMENU,	"FEC_OKK", { nil, SAVESLOT_NONE,	MENUPAGE_CHOOSE_DELETE_SLOT },
   },

   // MENUPAGE_SAVE_FAILED = 47
   { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
		MENUACTION_LABEL,		"FEC_SVU",	{ nil, SAVESLOT_NONE,	MENUPAGE_NONE },
		MENUACTION_CHANGEMENU,	"FEC_OKK",	{ nil, SAVESLOT_NONE,	MENUPAGE_CHOOSE_SAVE_SLOT },
   },

   // MENUPAGE_LOAD_FAILED = 48
   { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
		MENUACTION_LABEL,	"FEC_SVU",	{ nil, SAVESLOT_NONE,	MENUPAGE_NONE },
   },

   // MENUPAGE_LOAD_FAILED_2 = 49
   { "FET_LG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
		MENUACTION_LABEL,		"FEC_LUN",	{ nil, SAVESLOT_NONE,  MENUPAGE_NONE },
		MENUACTION_CHANGEMENU,	"FEDS_TB",	{ nil, SAVESLOT_NONE,  MENUPAGE_CHOOSE_LOAD_SLOT },
   },

   // MENUPAGE_FILTER_GAME = 50
   { "FIL_FLT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,

   },

   // MENUPAGE_START_MENU = 51
   { "FEM_MM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
		 MENUACTION_CHANGEMENU,	"FEN_STA",	{ nil, SAVESLOT_NONE,	MENUPAGE_NEW_GAME },
		 MENUACTION_CHANGEMENU,	"FET_OPT",	{ nil, SAVESLOT_NONE,	MENUPAGE_OPTIONS },
		 MENUACTION_CHANGEMENU,	"FEM_QT",	{ nil, SAVESLOT_NONE,	MENUPAGE_EXIT },
   },

   // MENUPAGE_PAUSE_MENU = 52
   { "FET_PAU", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
	   MENUACTION_RESUME,		"FEM_RES",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
	   MENUACTION_CHANGEMENU,	"FEN_STA",	{ nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
	   // CMenuManager::LoadAllTextures will add map here, if MENU_MAP enabled and map textures are found
	   MENUACTION_CHANGEMENU,	"FEP_STA",	{ nil, SAVESLOT_NONE, MENUPAGE_STATS },
	   MENUACTION_CHANGEMENU,	"FEP_BRI",	{ nil, SAVESLOT_NONE, MENUPAGE_BRIEFS },
	   MENUACTION_CHANGEMENU,	"FET_OPT",	{ nil, SAVESLOT_NONE, MENUPAGE_OPTIONS },
	   MENUACTION_CHANGEMENU,	"FEM_QT",	{ nil, SAVESLOT_NONE, MENUPAGE_EXIT },
   },

   // MENUPAGE_CHOOSE_MODE = 53
   { "FEN_STA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
	   MENUACTION_CHANGEMENU,	"FET_SP",	{ nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
	   MENUACTION_INITMP,		"FET_MP",	{ nil, SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN },
	   MENUACTION_CHANGEMENU,	"FEDS_TB",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
   },

   // MENUPAGE_SKIN_SELECT = 54
   { "FET_PSU", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
		MENUACTION_CHANGEMENU,	"FEDS_TB",	{ nil, SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN },
   },

   // MENUPAGE_KEYBOARD_CONTROLS = 55
   { "FET_STI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
		MENUACTION_CHANGEMENU,	"FEDS_TB",	{ nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
   },

   // MENUPAGE_MOUSE_CONTROLS = 56
   { "FET_MTI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
	   MENUACTION_MOUSESENS,	"FEC_MSH",	{ nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
	   MENUACTION_INVVERT,		"FEC_IVV",	{ nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
#ifndef GAMEPAD_MENU
       INVERT_PAD_SELECTOR
#endif
	   MENUACTION_MOUSESTEER,	"FET_MST",	{ nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
	   MENUACTION_CHANGEMENU,	"FEDS_TB",	{ nil, SAVESLOT_NONE, MENUPAGE_NONE },
   },
	// MENUPAGE_MISSION_RETRY = 57
#ifdef MISSION_REPLAY

   { "M_FAIL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
	   MENUACTION_LABEL,	    "FESZ_RM",  { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	   MENUACTION_CHANGEMENU,   "FEM_YES",  { nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS },
	   MENUACTION_REJECT_RETRY, "FEM_NO",   { nil, SAVESLOT_NONE, MENUPAGE_NONE },
   },
#else
   { "", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
	   // mission failed, wanna restart page in mobile
   },
#endif

#ifdef MENU_MAP
	// MENUPAGE_MAP
   { "FEG_MAP", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
		MENUACTION_UNK110,	"", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, // to prevent cross/enter to go back
		MENUACTION_CHANGEMENU,	"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
   },
#endif

#ifdef GRAPHICS_MENU_OPTIONS
	// MENUPAGE_GRAPHICS_SETTINGS
	{ "FET_GFX", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS,
		new CCustomScreenLayout({MENUSPRITE_MAINMENU, 50, 0, 20, FONT_HEADING, FESCREEN_LEFT_ALIGN, true, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), GraphicsGoBack,

#ifndef GTA_HANDHELD
		MENUACTION_SCREENRES,	"FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS },
#endif
		MENUACTION_WIDESCREEN,	"FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS },
		VIDEOMODE_SELECTOR
		MENUACTION_FRAMESYNC,	"FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		MENUACTION_FRAMELIMIT,	"FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
		MULTISAMPLING_SELECTOR
		ISLAND_LOADING_SELECTOR
		DUALPASS_SELECTOR
#ifdef EXTENDED_COLOURFILTER
		POSTFX_SELECTORS
#else
		MENUACTION_TRAILS,		"FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
#endif
		// re3.cpp inserts here pipeline selectors if neo/neo.txd exists and EXTENDED_PIPELINES defined
		MENUACTION_CFO_DYNAMIC,	"FET_DEF", { new CCFODynamic(nil, nil, nil, nil, RestoreDefGraphics) },
		MENUACTION_CHANGEMENU,	"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},
#endif

#ifdef DETECT_JOYSTICK_MENU
	// MENUPAGE_DETECT_JOYSTICK
	{ "FEC_JOD", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC,
		new CCustomScreenLayout({MENUSPRITE_MAINMENU, 40, 60, 20, FONT_BANK, FESCREEN_LEFT_ALIGN, false, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), DetectJoystickGoBack,

		MENUACTION_LABEL,	"FEC_JPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
		MENUACTION_CFO_DYNAMIC,	"FEC_JDE", { new CCFODynamic(nil, nil, nil, DetectJoystickDraw, nil) },
		MENUACTION_CHANGEMENU,	"FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
	},
#endif

   // MENUPAGE_UNK
   { "", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,

   },

};

#endif
#endif


code:
#define WITHDINPUT
#include "common.h"
#include "crossplatform.h"
#include "platform.h"
#ifdef XINPUT
#include <xinput.h>
#if !defined(PSAPI_VERSION) || (PSAPI_VERSION > 1)
#pragma comment( lib, "Xinput9_1_0.lib" )
#else
#pragma comment( lib, "Xinput.lib" )
#endif
#endif

#include "Pad.h"
#include "ControllerConfig.h"
#include "Timer.h"
#include "Frontend.h"
#include "Camera.h"
#include "Game.h"
#include "CutsceneMgr.h"
#include "Font.h"
#include "Hud.h"
#include "Text.h"
#include "Timer.h"
#include "Record.h"
#include "World.h"
#include "Vehicle.h"
#include "Ped.h"
#include "Population.h"
#include "Record.h"
#include "Replay.h"
#include "Weather.h"
#include "Streaming.h"
#include "PathFind.h"
#include "Wanted.h"
#include "General.h"

#ifdef GTA_PS2
#include "eetypes.h"
#include "libpad.h"
#endif

CPad Pads[MAX_PADS];
#ifdef GTA_PS2
u_long128 pad_dma_buf[scePadDmaBufferMax] __attribute__((aligned(64)));
u_long128 pad2_dma_buf[scePadDmaBufferMax] __attribute__((aligned(64)));
#endif

CMousePointerStateHelper MousePointerStateHelper;

bool CPad::bDisplayNoControllerMessage;
bool CPad::bObsoleteControllerMessage;
bool CPad::bOldDisplayNoControllerMessage;
bool CPad::m_bMapPadOneToPadTwo;
#ifdef INVERT_LOOK_FOR_PAD
bool CPad::bInvertLook4Pad;
#endif
#ifdef GTA_PS2
unsigned char act_direct[6];
unsigned char act_align[6];
#endif

CKeyboardState CPad::OldKeyState;
CKeyboardState CPad::NewKeyState;
CKeyboardState CPad::TempKeyState;

char CPad::KeyBoardCheatString[20];

CMouseControllerState CPad::OldMouseControllerState;
CMouseControllerState CPad::NewMouseControllerState;
CMouseControllerState CPad::PCTempMouseControllerState;

#ifdef DETECT_PAD_INPUT_SWITCH
bool CPad::IsAffectedByController = false;
#endif

_TODO("gbFastTime");
extern bool gbFastTime;

void WeaponCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT2"), true);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_BASEBALLBAT, 0);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_COLT45, 100);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_UZI, 100);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_SHOTGUN, 20);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_AK47, 200);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_M16, 200);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_SNIPERRIFLE, 5);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_ROCKETLAUNCHER, 5);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_MOLOTOV, 5);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_GRENADE, 5);
	FindPlayerPed()->GiveWeapon(WEAPONTYPE_FLAMETHROWER, 200);
}

void HealthCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT3"), true);
	FindPlayerPed()->m_fHealth = 100.0f;
	if (FindPlayerVehicle()) {
		FindPlayerVehicle()->m_fHealth = 1000.0f;
		if (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_CAR)
			((CAutomobile*)FindPlayerVehicle())->Damage.SetEngineStatus(0);
	}
}

void TankCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
	CStreaming::RequestModel(MI_RHINO, 0);
	CStreaming::LoadAllRequestedModels(false);
	if (CStreaming::ms_aInfoForModel[MI_RHINO].m_loadState == STREAMSTATE_LOADED) {
		CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
		int32 node = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 100.0f);

		if (node < 0) return;

#ifdef FIX_BUGS
		CAutomobile* tank = new CAutomobile(MI_RHINO, RANDOM_VEHICLE);
#else
		CAutomobile *tank = new CAutomobile(MI_RHINO, MISSION_VEHICLE);
#endif
		if (tank != nil) {
			CVector pos = ThePaths.m_pathNodes[node].GetPosition();
			pos.z += 4.0f;
			tank->SetPosition(pos);
			tank->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f));

			tank->SetStatus(STATUS_ABANDONED);
			tank->m_nDoorLock = CARLOCK_UNLOCKED;
			CWorld::Add(tank);
		}
	}
}

void BlowUpCarsCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);

	int i = CPools::GetVehiclePool()->GetSize();
	while (i-- > 0) {
		if (CVehicle *veh = CPools::GetVehiclePool()->GetSlot(i))
			veh->BlowUpCar(nil);
	}
}

void ChangePlayerCheat()
{
	int modelId;

	if (FindPlayerPed()->IsPedInControl() && CModelInfo::GetModelInfo("player", nil)) {
		CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
		CPlayerPed *ped = FindPlayerPed();
		AssocGroupId AnimGrp = ped->m_animGroup;
		do
		{
			do
				modelId = CGeneral::GetRandomNumberInRange(0, MI_CAS_WOM+1);
			while (!CModelInfo::GetModelInfo(modelId));
		} while (modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL04 || modelId == MI_TAXI_D);

		uint8 flags = CStreaming::ms_aInfoForModel[modelId].m_flags;
		ped->DeleteRwObject();
		CStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY| STREAMFLAGS_DONT_REMOVE);
		CStreaming::LoadAllRequestedModels(false);
		ped->m_modelIndex = -1;
		ped->SetModelIndex(modelId);
		ped->m_animGroup = AnimGrp;
		if (modelId != MI_PLAYER) {
			if (!(flags & STREAMFLAGS_DONT_REMOVE))
				CStreaming::SetModelIsDeletable(modelId);
		}
	}
}

void MayhemCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
	for (int i = PEDTYPE_CIVMALE; i < PEDTYPE_SPECIAL; i++)
		CPedType::SetThreats(i, PED_FLAG_PLAYER1 | PED_FLAG_PLAYER2 | PED_FLAG_PLAYER3 | PED_FLAG_PLAYER4 |
			PED_FLAG_CIVMALE | PED_FLAG_CIVFEMALE | PED_FLAG_COP | PED_FLAG_GANG1 |
			PED_FLAG_GANG2 | PED_FLAG_GANG3 | PED_FLAG_GANG4 | PED_FLAG_GANG5 |
			PED_FLAG_GANG6 | PED_FLAG_GANG7 | PED_FLAG_GANG8 | PED_FLAG_GANG9 |
			PED_FLAG_EMERGENCY | PED_FLAG_PROSTITUTE | PED_FLAG_CRIMINAL | PED_FLAG_SPECIAL );
}

void EverybodyAttacksPlayerCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
	for (int i = PEDTYPE_CIVMALE; i < PEDTYPE_SPECIAL; i++)
		CPedType::AddThreat(i, PED_FLAG_PLAYER1);
}

void WeaponsForAllCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
	CPopulation::ms_bGivePedsWeapons = !CPopulation::ms_bGivePedsWeapons;
}

void FastTimeCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
	if (CTimer::GetTimeScale() < 4.0f)
		CTimer::SetTimeScale(CTimer::GetTimeScale() * 2.0f);
}

void SlowTimeCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
	if (CTimer::GetTimeScale() > 0.25f)
		CTimer::SetTimeScale(CTimer::GetTimeScale() * 0.5f);
}

void MoneyCheat()
{
	CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 250000;
	CHud::SetHelpMessage(TheText.Get("CHEAT6"), true);
}

void ArmourCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT4"), true);
	FindPlayerPed()->m_fArmour = 100.0f;
}

void WantedLevelUpCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT5"), true);
	FindPlayerPed()->SetWantedLevel(Min(FindPlayerPed()->m_pWanted->GetWantedLevel() + 2, 6));
}

void WantedLevelDownCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT5"), true);
	FindPlayerPed()->SetWantedLevel(0);
}

void SunnyWeatherCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
	CWeather::ForceWeatherNow(WEATHER_SUNNY);
}

void CloudyWeatherCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
	CWeather::ForceWeatherNow(WEATHER_CLOUDY);
}

void RainyWeatherCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
	CWeather::ForceWeatherNow(WEATHER_RAINY);
}

void FoggyWeatherCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT7"), true);
	CWeather::ForceWeatherNow(WEATHER_FOGGY);
}

void FastWeatherCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
	gbFastTime = !gbFastTime;
}

void OnlyRenderWheelsCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
	CVehicle::bWheelsOnlyCheat = !CVehicle::bWheelsOnlyCheat;
}

void ChittyChittyBangBangCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
	CVehicle::bAllDodosCheat = !CVehicle::bAllDodosCheat;
}

void StrongGripCheat()
{
	CHud::SetHelpMessage(TheText.Get("CHEAT1"), true);
	CVehicle::bCheat3 = !CVehicle::bCheat3;
}

void NastyLimbsCheat()
{
	CPed::bNastyLimbsCheat = !CPed::bNastyLimbsCheat;
}
//////////////////////////////////////////////////////////////////////////

#ifdef KANGAROO_CHEAT
void KangarooCheat()
{
	wchar *string;
	CPed *playerPed = FindPlayerPed();
	int m_fMass;

	if (playerPed->m_ped_flagI80) {
		string = TheText.Get("CHEATOF");
		m_fMass = 70.0f;
	} else {
		string = TheText.Get("CHEAT1");
		m_fMass = 15.0f;
	}
	CHud::SetHelpMessage(string, true);
	playerPed->m_ped_flagI80 = !playerPed->m_ped_flagI80;

	playerPed->m_fMass = m_fMass;
	playerPed->m_fAirResistance = 0.4f / m_fMass;
}
#endif

#ifdef ALLCARSHELI_CHEAT
void AllCarsHeliCheat(void)
{
	wchar* string;
	if (bAllCarCheat) {
		string = TheText.Get("CHEATOF");
		bAllCarCheat = false;
	}
	else {
		string = TheText.Get("CHEAT1");
		bAllCarCheat = true;
	}
	CHud::SetHelpMessage(string, true);
}
#endif

#ifdef ALT_DODO_CHEAT
void AltDodoCheat(void)
{
	wchar* string;
	if (CVehicle::bAltDodoCheat) {
		string = TheText.Get("CHEATOF");
		CVehicle::bAltDodoCheat = false;
	}
	else {
		string = TheText.Get("CHEAT1");
		CVehicle::bAltDodoCheat = true;
	}
	CHud::SetHelpMessage(string, true);
}
#endif

bool
CControllerState::CheckForInput(void)
{
	return !!RightStickX || !!RightStickY || !!LeftStickX || !!LeftStickY
		|| !!DPadUp || !!DPadDown || !!DPadLeft || !!DPadRight
		|| !!Triangle || !!Cross || !!Circle || !!Square
		|| !!Start || !!Select
		|| !!LeftShoulder1 || !!LeftShoulder2 || !!RightShoulder1 || !!RightShoulder2
		|| !!LeftShock || !!RightShock;
}

void
CControllerState::Clear(void)
{
	LeftStickX = LeftStickY = RightStickX = RightStickY = 0;
	LeftShoulder1 = LeftShoulder2 = RightShoulder1 = RightShoulder2 = 0;
	DPadUp = DPadDown = DPadLeft = DPadRight = 0;
	Start = Select = 0;
	Square = Triangle = Cross = Circle = 0;
	LeftShock = RightShock = 0;
	NetworkTalk = 0;
}

void CKeyboardState::Clear()
{
	for ( int32 i = 0; i < ARRAY_SIZE(F); i++	)
		F[i] = 0;

	for ( int32 i = 0; i < ARRAY_SIZE(VK_KEYS); i++	 )
		VK_KEYS[i] = 0;

	ESC = INS = DEL = HOME = END = PGUP = PGDN = 0;

	UP = DOWN = LEFT = RIGHT = 0;

	NUMLOCK = 0;

	DIV = MUL = SUB = ADD = 0;

	DECIMAL = NUM1 = NUM2 = NUM3 = NUM4 = 0;

	NUM5 = NUM6 = NUM7 = NUM8 = 0;

	NUM9 = NUM0 = SCROLLLOCK = PAUSE = 0;

	BACKSP = TAB = CAPSLOCK = EXTENTER = 0;

	LSHIFT = SHIFT = RSHIFT = LCTRL = RCTRL = LALT = RALT = 0;

	LWIN = RWIN = APPS = 0;
}

#ifdef GTA_PS2_STUFF
void CPad::Initialise(void)
{
#ifdef GTA_PS2
	scePadInit(0);

	scePadPortOpen(0, 0, pad_dma_buf );
	scePadPortOpen(1, 0, pad2_dma_buf );
#endif
	for (int i = 0; i < MAX_PADS; i++)
	{
		CPad::GetPad(i)->Clear(true);
		CPad::GetPad(i)->Mode = 0;
	}

	bObsoleteControllerMessage	   = false;
	bOldDisplayNoControllerMessage = false;
	bDisplayNoControllerMessage	   = false;
}
#endif

void CPad::Clear(bool bResetPlayerControls)
{
	NewState.Clear();
	OldState.Clear();

	PCTempKeyState.Clear();
	PCTempJoyState.Clear();
	PCTempMouseState.Clear();

	NewKeyState.Clear();
	OldKeyState.Clear();
	TempKeyState.Clear();

	NewMouseControllerState.Clear();
	OldMouseControllerState.Clear();
	PCTempMouseControllerState.Clear();

	Phase = 0;
	ShakeFreq = 0;
	ShakeDur = 0;

	if ( bResetPlayerControls )
		DisablePlayerControls = PLAYERCONTROL_ENABLED;

	bApplyBrakes = false;

	for ( int32 i = 0; i < HORNHISTORY_SIZE; i++ )
		bHornHistory[i] = false;

	iCurrHornHistory = 0;

	for ( int32 i = 0; i < ARRAY_SIZE(CheatString); i++ )
		CheatString[i] = ' ';

	LastTimeTouched = CTimer::GetTimeInMilliseconds();
	AverageWeapon = 0;
	AverageEntries = 0;
}

void CPad::ClearMouseHistory()
{
	PCTempMouseControllerState.Clear();
	NewMouseControllerState.Clear();
	OldMouseControllerState.Clear();
}

CMouseControllerState::CMouseControllerState()
{
	LMB = 0;
	RMB = 0;
	MMB = 0;
	WHEELUP = 0;
	WHEELDN = 0;
	MXB1 = 0;
	MXB2 = 0;

	x = 0.0f;
	y = 0.0f;
}

void CMouseControllerState::Clear()
{
	LMB = 0;
	RMB = 0;
	MMB = 0;
	WHEELUP = 0;
	WHEELDN = 0;
	MXB1 = 0;
	MXB2 = 0;
}

CMouseControllerState CMousePointerStateHelper::GetMouseSetUp()
{
	CMouseControllerState state;

#if defined RW_D3D9 || defined RWLIBS
	if ( PSGLOBAL(mouse) == nil )
		_InputInitialiseMouse();

	if ( PSGLOBAL(mouse) != nil )
	{
		DIDEVCAPS devCaps;
		devCaps.dwSize = sizeof(DIDEVCAPS);

		PSGLOBAL(mouse)->GetCapabilities(&devCaps);
		switch ( devCaps.dwButtons )
		{
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
				state.MMB = true;

			case 2:
				state.RMB = true;

			case 1:
				state.LMB = true;
		}

		if ( devCaps.dwAxes == 3 )
		{
			state.WHEELDN = true;
			state.WHEELUP = true;
		}
	}
#else
	// It seems there is no way to get number of buttons on mouse, so assign all buttons if we have mouse.
	double xpos = 1.0f, ypos;
	glfwGetCursorPos(PSGLOBAL(window), &xpos, &ypos);

	if (xpos != 0.f) {
		state.MMB = true;
		state.RMB = true;
		state.LMB = true;
		state.WHEELDN = true;
		state.WHEELUP = true;
	}
#endif

	return state;
}

void CPad::UpdateMouse()
{
#if defined RW_D3D9 || defined RWLIBS
	if ( IsForegroundApp() )
	{
		if ( PSGLOBAL(mouse) == nil )
			_InputInitialiseMouse();

		DIMOUSESTATE2 state;

		if ( PSGLOBAL(mouse) != nil && SUCCEEDED(_InputGetMouseState(&state)) )
		{
			int32 signX = 1;
			int32 signy = 1;

			if ( !FrontEndMenuManager.m_bMenuActive )
			{
				if ( MousePointerStateHelper.bInvertVertically )
					signy = -1;
				if ( MousePointerStateHelper.bInvertHorizontally )
					signX = -1;
			}

			PCTempMouseControllerState.Clear();

			PCTempMouseControllerState.x = (float)(signX * state.lX);
			PCTempMouseControllerState.y = (float)(signy * state.lY);
			PCTempMouseControllerState.LMB = state.rgbButtons[0] & 128;
			PCTempMouseControllerState.RMB = state.rgbButtons[1] & 128;
			PCTempMouseControllerState.MMB = state.rgbButtons[2] & 128;
			PCTempMouseControllerState.MXB1 = state.rgbButtons[3] & 128;
			PCTempMouseControllerState.MXB2 = state.rgbButtons[4] & 128;

			if ( state.lZ > 0 )
				PCTempMouseControllerState.WHEELUP = 1;
			else if ( state.lZ < 0 )
				PCTempMouseControllerState.WHEELDN = 1;

			OldMouseControllerState = NewMouseControllerState;
			NewMouseControllerState = PCTempMouseControllerState;
		}
	}
#else
	if ( IsForegroundApp() && PSGLOBAL(cursorIsInWindow) )
	{
		double xpos = 1.0f, ypos;
		glfwGetCursorPos(PSGLOBAL(window), &xpos, &ypos);
		if (xpos == 0.f)
			return;

		int32 signX = 1;
		int32 signy = 1;

		if (!FrontEndMenuManager.m_bMenuActive)
		{
			if (MousePointerStateHelper.bInvertVertically)
				signy = -1;
			if (MousePointerStateHelper.bInvertHorizontally)
				signX = -1;
		}

		PCTempMouseControllerState.Clear();

		PCTempMouseControllerState.x = (float)(signX * (xpos - PSGLOBAL(lastMousePos.x)));
		PCTempMouseControllerState.y = (float)(signy * (ypos - PSGLOBAL(lastMousePos.y)));
		PCTempMouseControllerState.LMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_LEFT);
		PCTempMouseControllerState.RMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_RIGHT);
		PCTempMouseControllerState.MMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_MIDDLE);
		PCTempMouseControllerState.MXB1 = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_4);
		PCTempMouseControllerState.MXB2 = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_5);

		if (PSGLOBAL(mouseWheel) > 0)
			PCTempMouseControllerState.WHEELUP = 1;
		else if (PSGLOBAL(mouseWheel) < 0)
			PCTempMouseControllerState.WHEELDN = 1;

		PSGLOBAL(lastMousePos.x) = xpos;
		PSGLOBAL(lastMousePos.y) = ypos;
		PSGLOBAL(mouseWheel) = 0.0f;

		OldMouseControllerState = NewMouseControllerState;
		NewMouseControllerState = PCTempMouseControllerState;
	}
#endif
}

CControllerState CPad::ReconcileTwoControllersInput(CControllerState const &State1, CControllerState const &State2)
{
	static CControllerState ReconState;

	ReconState.Clear();

#define _RECONCILE_BUTTON(button) \
	{ if ( State1.button || State2.button ) ReconState.button = 255; }

#define _RECONCILE_AXIS_POSITIVE(axis) \
	{ if ( State1.axis >= 0 && State2.axis >= 0 ) ReconState.axis = Max(State1.axis, State2.axis); }

#define _RECONCILE_AXIS_NEGATIVE(axis) \
	{ if ( State1.axis <= 0 && State2.axis <= 0 ) ReconState.axis = Min(State1.axis, State2.axis); }

#define _RECONCILE_AXIS(axis) \
	{ _RECONCILE_AXIS_POSITIVE(axis); _RECONCILE_AXIS_NEGATIVE(axis); }

#define _FIX_AXIS_DIR(axis) \
	{ if ( State1.axis > 0 && State2.axis < 0 || State1.axis < 0 && State2.axis > 0 ) ReconState.axis = 0; }

#define _FIX_RECON_DIR(pos, neg, axis) \
	{ if ( (ReconState.pos || ReconState.axis < 0) && (ReconState.neg || ReconState.axis > 0) ) { ReconState.pos = 0; ReconState.neg = 0; ReconState.axis = 0; } }

	_RECONCILE_BUTTON(LeftShoulder1);
	_RECONCILE_BUTTON(LeftShoulder2);
	_RECONCILE_BUTTON(RightShoulder1);
	_RECONCILE_BUTTON(RightShoulder2);
	_RECONCILE_BUTTON(Start);
	_RECONCILE_BUTTON(Select);
	_RECONCILE_BUTTON(Square);
	_RECONCILE_BUTTON(Triangle);
	_RECONCILE_BUTTON(Cross);
	_RECONCILE_BUTTON(Circle);
	_RECONCILE_BUTTON(LeftShock);
	_RECONCILE_BUTTON(RightShock);
	_RECONCILE_BUTTON(NetworkTalk);
	_RECONCILE_AXIS(LeftStickX);
	_RECONCILE_AXIS(LeftStickY);
	_FIX_AXIS_DIR(LeftStickX);
	_FIX_AXIS_DIR(LeftStickY);
	_RECONCILE_AXIS(RightStickX);
	_RECONCILE_AXIS(RightStickY);
	_FIX_AXIS_DIR(RightStickX);
	_FIX_AXIS_DIR(RightStickY);
	_RECONCILE_BUTTON(DPadUp);
	_RECONCILE_BUTTON(DPadDown);
	_RECONCILE_BUTTON(DPadLeft);
	_RECONCILE_BUTTON(DPadRight);
	_FIX_RECON_DIR(DPadUp, DPadDown, LeftStickY);
	_FIX_RECON_DIR(DPadLeft, DPadRight, LeftStickX);

	return ReconState;

#undef _RECONCILE_BUTTON
#undef _RECONCILE_AXIS_POSITIVE
#undef _RECONCILE_AXIS_NEGATIVE
#undef _RECONCILE_AXIS
#undef _FIX_AXIS_DIR
#undef _FIX_RECON_DIR
}

void CPad::StartShake(int16 nDur, uint8 nFreq)
{
	if ( !CMenuManager::m_PrefsUseVibration )
		return;

	if ( CCutsceneMgr::IsRunning() || CGame::playingIntro )
		return;

	if ( nFreq == 0 )
	{
		ShakeDur = 0;
		ShakeFreq = 0;
		return;
	}

	if ( nDur > ShakeDur )
	{
		ShakeDur = nDur;
		ShakeFreq = nFreq;
	}
}

void CPad::StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fZ)
{
	if ( !CMenuManager::m_PrefsUseVibration )
		return;

	if ( CCutsceneMgr::IsRunning() || CGame::playingIntro )
		return;

	float fDist = ( TheCamera.GetPosition() - CVector(fX, fY, fZ) ).Magnitude();

	if ( fDist < 70.0f )
	{
		if ( nFreq == 0 )
		{
			ShakeDur = 0;
			ShakeFreq = 0;
			return;
		}

		if ( nDur > ShakeDur )
		{
			ShakeDur = nDur;
			ShakeFreq = nFreq;
		}
	}
}

void CPad::StartShake_Train(float fX, float fY)
{
	if ( !CMenuManager::m_PrefsUseVibration )
		return;

	if ( CCutsceneMgr::IsRunning() || CGame::playingIntro )
		return;

	if (FindPlayerVehicle() != nil && FindPlayerVehicle()->IsTrain() )
		return;

	float fDist = ( TheCamera.GetPosition() - CVector(fX, fY, 0.0f) ).Magnitude2D();

	if ( fDist < 70.0f )
	{
		int32 freq = (int32)((70.0f - fDist) * 70.0f / 70.0f + 30.0f);

		if ( ShakeDur < 100 )
		{
			ShakeDur = 100;
			ShakeFreq = freq;
		}
	}
}

#ifdef GTA_PS2_STUFF
void CPad::AddToCheatString(char c)
{
	for ( int32 i = ARRAY_SIZE(CheatString) - 2; i >= 0; i-- )
		CheatString[i + 1] = CheatString[i];

	CheatString[0] = c;

#define _CHEATCMP(str)	strncmp(str, CheatString, sizeof(str)-1)
	// "4414LDRULDRU"	-	R2 R2 L1 R2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP
	if ( !_CHEATCMP("URDLURDL4144") )
		WeaponCheat();

	// "4411LDRULDRU"	-	R2 R2 L1 L1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP
	else if ( !_CHEATCMP("URDLURDL1144") )
		MoneyCheat();

	// "4412LDRULDRU"	-	R2 R2 L1 L2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP
	else if ( !_CHEATCMP("URDLURDL2144") )
		ArmourCheat();

	// "4413LDRULDRU"	-	R2 R2 L1 R1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP
	else if ( !_CHEATCMP("URDLURDL3144") )
		HealthCheat();

	// "4414LRLRLR"		-	R2 R2 L1 R2 LEFT RIGHT LEFT RIGHT LEFT RIGHT
	else if ( !_CHEATCMP("RLRLRL4144") )
		WantedLevelUpCheat();

	// "4414UDUDUD"		-	R2 R2 L1 R2 UP DOWN UP DOWN UP DOWN
	else if ( !_CHEATCMP("DUDUDU4144") )
		WantedLevelDownCheat();

	// "1234432T"		-	L1 L2 R1 R2 R2 R1 L2 TRIANGLE
	else if ( !_CHEATCMP("T2344321") )
		SunnyWeatherCheat();

	// "1234432S"		-	L1 L2 R1 R2 R2 R1 L2 SQUARE
	else if ( !_CHEATCMP("S2344321") )
		CloudyWeatherCheat();

	// "1234432C"		-	L1 L2 R1 R2 R2 R1 L2 CIRCLE
	else if ( !_CHEATCMP("C2344321") )
		RainyWeatherCheat();

	// "1234432X"		-	L1 L2 R1 R2 R2 R1 L2 CROSS
	else if ( !_CHEATCMP("X2344321") )
		FoggyWeatherCheat();

	// "CCCCCC321TCT"	-	CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE R1 L2 L1 TRIANGLE CIRCLE TRIANGLE
	else if ( !_CHEATCMP("TCT123CCCCCC") )
		TankCheat();

	// "CCCSSSSS1TCT"	-	CIRCLE CIRCLE CIRCLE SQUARE SQUARE SQUARE SQUARE SQUARE L1 TRIANGLE CIRCLE TRIANGLE
	else if ( !_CHEATCMP("TCT1SSSSSCCC") )
		FastWeatherCheat();

	// "241324TSCT21"	-	L2 R2 L1 R1 L2 R2 TRIANGLE SQUARE CIRCLE TRIANGLE L2 L1
	else if ( !_CHEATCMP("12TCST423142") )
		BlowUpCarsCheat();

	// "RDLU12ULDR"		-	RIGHT DOWN LEFT UP L1 L2 UP LEFT DOWN RIGHT
	else if ( !_CHEATCMP("RDLU21ULDR") )
		ChangePlayerCheat();

	// "DULUX3421"		-	DOWN UP LEFT UP CROSS R1 R2 L2 L1
	else if ( !_CHEATCMP("1243XULUD") )
		MayhemCheat();

	// "DULUX3412"		-	DOWN UP LEFT UP CROSS R1 R2 L1 L2
	else if ( !_CHEATCMP("2143XULUD") )
		EverybodyAttacksPlayerCheat();

	// "43TX21UD"		-	R2 R1 TRIANGLE CROSS L2 L1 UP DOWN
	else if ( !_CHEATCMP("DU12XT34") )
		WeaponsForAllCheat();

	// "TURDS12"		-	TRIANGLE UP RIGHT DOWN SQUARE L1 L2
	else if ( !_CHEATCMP("21SDRUT") )
		FastTimeCheat();

	// "TURDS34"		-	TRIANGLE UP RIGHT DOWN SQUARE R1 R2
	else if ( !_CHEATCMP("43SDRUT") )
		SlowTimeCheat();

	// "11S4T1T"		-	L1 L1 SQUARE R2 TRIANGLE L1 TRIANGLE
	else if ( !_CHEATCMP("T1T4S11") )
		OnlyRenderWheelsCheat();

	// "R4C32D13"		-	RIGHT R2 CIRCLE R1 L2 DOWN L1 R1
	else if ( !_CHEATCMP("31D23C4R") )
		ChittyChittyBangBangCheat();

	// "3141L33T"		-	R1 L1 R2 L1 LEFT R1 R1 TRIANGLE
	else if ( !_CHEATCMP("T33L1413") )
		StrongGripCheat();

	// "S1CD13TR1X"		-	SQUARE L1 CIRCLE DOWN L1 R1 TRIANGLE RIGHT L1 CROSS
	else if ( !_CHEATCMP("X1RT31DC1S") )
		NastyLimbsCheat();

#ifdef KANGAROO_CHEAT
	// "X1DUC3RLS3"		-	R1 SQUARE LEFT RIGHT R1 CIRCLE UP DOWN L1 CROSS
	else if (!_CHEATCMP("X1DUC3RLS3"))
		KangarooCheat();
#endif

#ifndef MASTER
	// "31UD13XUD"		-	DOWN UP CROSS R1 L1 DOWN UP L1 R1
	else if (!_CHEATCMP("31UD13XUD"))
		CPed::SwitchDebugDisplay();
#endif

#ifdef ALLCARSHELI_CHEAT
	// "UCCL3R1TT"		-	TRIANGLE TRIANGLE L1 RIGHT R1 LEFT CIRCLE CIRCLE UP
	else if (!_CHEATCMP("UCCL3R1TT"))
		AllCarsHeliCheat();
#endif

#ifdef ALT_DODO_CHEAT
	// "DUU31XX13"		-	R1 L1 CROSS CROSS L1 R1 UP UP DOWN
	else if (!_CHEATCMP("DUU31XX13"))
		AltDodoCheat();
#endif
#undef _CHEATCMP
}
#endif

void CPad::AddToPCCheatString(char c)
{
	for ( int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i-- )
		KeyBoardCheatString[i + 1] = KeyBoardCheatString[i];

	KeyBoardCheatString[0] = c;

	#define _CHEATCMP(str) strncmp(str, KeyBoardCheatString, sizeof(str)-1)

	// "GUNSGUNSGUNS"
	if ( !_CHEATCMP("SNUGSNUGSNUG") )
		WeaponCheat();

	// "IFIWEREARICHMAN"
	if ( !_CHEATCMP("NAMHCIRAEREWIFI") )
		MoneyCheat();

	// "GESUNDHEIT"
	if ( !_CHEATCMP("TIEHDNUSEG") )
		HealthCheat();

	// "MOREPOLICEPLEASE"
	if ( !_CHEATCMP("ESAELPECILOPEROM") )
		WantedLevelUpCheat();

	// "NOPOLICEPLEASE"
	if ( !_CHEATCMP("ESAELPECILOPON") )
		WantedLevelDownCheat();

	// "GIVEUSATANK"
	if ( !_CHEATCMP("KNATASUEVIG") )
		TankCheat();

	// "BANGBANGBANG"
	if ( !_CHEATCMP("GNABGNABGNAB") )
		BlowUpCarsCheat();

	// "ILIKEDRESSINGUP"
	if ( !_CHEATCMP("PUGNISSERDEKILI") )
		ChangePlayerCheat();

	// "ITSALLGOINGMAAAD"
	if ( !_CHEATCMP("DAAAMGNIOGLLASTI") )
		MayhemCheat();

	// "NOBODYLIKESME"
	if ( !_CHEATCMP("EMSEKILYDOBON") )
		EverybodyAttacksPlayerCheat();

	// "WEAPONSFORALL"
	if ( !_CHEATCMP("LLAROFSNOPAEW") )
		WeaponsForAllCheat();

	// "TIMEFLIESWHENYOU"
	if ( !_CHEATCMP("UOYNEHWSEILFEMIT") )
		FastTimeCheat();

	// "BOOOOORING"
	if ( !_CHEATCMP("GNIROOOOOB") )
		SlowTimeCheat();

#if GTA_VERSION < GTA3_PC_11
	// "TURTOISE"
	if ( !_CHEATCMP("ESIOTRUT") )
		ArmourCheat();
#else
	// "TORTOISE"
	if ( !_CHEATCMP("ESIOTROT") )
		ArmourCheat();
#endif

	// "SKINCANCERFORME"
	if ( !_CHEATCMP("EMROFRECNACNIKS") )
		SunnyWeatherCheat();

	// "ILIKESCOTLAND"
	if ( !_CHEATCMP("DNALTOCSEKILI") )
		CloudyWeatherCheat();

	// "ILOVESCOTLAND"
	if ( !_CHEATCMP("DNALTOCSEVOLI") )
		RainyWeatherCheat();

	// "PEASOUP"
	if ( !_CHEATCMP("PUOSAEP") )
		FoggyWeatherCheat();

	// "MADWEATHER"
	if ( !_CHEATCMP("REHTAEWDAM") )
		FastWeatherCheat();

	// "ANICESETOFWHEELS"
	if ( !_CHEATCMP("SLEEHWFOTESECINA") )
		OnlyRenderWheelsCheat();

	// "CHITTYCHITTYBB"
	if ( !_CHEATCMP("BBYTTIHCYTTIHC") )
		ChittyChittyBangBangCheat();

	// "CORNERSLIKEMAD"
	if ( !_CHEATCMP("DAMEKILSRENROC") )
		StrongGripCheat();

	// "NASTYLIMBSCHEAT"
	if ( !_CHEATCMP("TAEHCSBMILYTSAN") )
		NastyLimbsCheat();

#ifdef KANGAROO_CHEAT
	// "KANGAROO"
	if (!_CHEATCMP("OORAGNAK"))
		KangarooCheat();
#endif

#ifndef MASTER
	// "PEDDEBUG"
	if (!_CHEATCMP("GUBEDDEP"))
		CPed::SwitchDebugDisplay();
#endif

#ifdef ALLCARSHELI_CHEAT
	// "CARSAREHELI"
	if (!_CHEATCMP("ILEHERASRAC"))
		AllCarsHeliCheat();
#endif

#ifdef ALT_DODO_CHEAT
	// "IWANTTOMASTERDODO"
	if (!_CHEATCMP("ODODRETSAMOTTNAWI"))
		AltDodoCheat();
#endif

	#undef _CHEATCMP
}

#ifdef XINPUT
int CPad::XInputJoy1 = 0;
int CPad::XInputJoy2 = 1;
void CPad::AffectFromXinput(uint32 pad)
{
	pad = pad == 0 ? XInputJoy1 : XInputJoy2;
	if (pad == -1) // LoadINIControllerSettings can set it to -1
		return;

	XINPUT_STATE xstate;
	memset(&xstate, 0, sizeof(XINPUT_STATE));
	if (XInputGetState(pad, &xstate) == ERROR_SUCCESS)
	{
		PCTempJoyState.Circle = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_B) ? 255 : 0;
		PCTempJoyState.Cross = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_A) ? 255 : 0;
		PCTempJoyState.Square = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_X) ? 255 : 0;
		PCTempJoyState.Triangle = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_Y) ? 255 : 0;
		PCTempJoyState.DPadDown = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) ? 255 : 0;
		PCTempJoyState.DPadLeft = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) ? 255 : 0;
		PCTempJoyState.DPadRight = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) ? 255 : 0;
		PCTempJoyState.DPadUp = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) ? 255 : 0;
		PCTempJoyState.LeftShock = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) ? 255 : 0;
		PCTempJoyState.LeftShoulder1 = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? 255 : 0;
		PCTempJoyState.LeftShoulder2 = xstate.Gamepad.bLeftTrigger;
		PCTempJoyState.RightShock = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) ? 255 : 0;
		PCTempJoyState.RightShoulder1 = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) ? 255 : 0;
		PCTempJoyState.RightShoulder2 = xstate.Gamepad.bRightTrigger;

		PCTempJoyState.Select = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) ? 255 : 0;
#ifdef REGISTER_START_BUTTON
		PCTempJoyState.Start = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_START) ? 255 : 0;
#endif
		float lx = (float)xstate.Gamepad.sThumbLX / (float)0x7FFF;
		float ly = (float)xstate.Gamepad.sThumbLY / (float)0x7FFF;
		float rx = (float)xstate.Gamepad.sThumbRX / (float)0x7FFF;
		float ry = (float)xstate.Gamepad.sThumbRY / (float)0x7FFF;

		if (Abs(lx) > 0.3f || Abs(ly) > 0.3f) {
			PCTempJoyState.LeftStickX = (int32)(lx * 128.0f);
			PCTempJoyState.LeftStickY = (int32)(-ly * 128.0f);
		}

		if (Abs(rx) > 0.3f || Abs(ry) > 0.3f) {
			PCTempJoyState.RightStickX = (int32)(rx * 128.0f);
			PCTempJoyState.RightStickY = (int32)(-ry * 128.0f);
		}

		XINPUT_VIBRATION VibrationState;

		memset(&VibrationState, 0, sizeof(XINPUT_VIBRATION));

		uint16 iLeftMotor = (uint16)((float)ShakeFreq / 255.0f * (float)0xffff);
		uint16 iRightMotor = (uint16)((float)ShakeFreq / 255.0f * (float)0xffff);

		if (ShakeDur < CTimer::GetTimeStepInMilliseconds())
			ShakeDur = 0;
		else
			ShakeDur -= CTimer::GetTimeStepInMilliseconds();
		if (ShakeDur == 0) ShakeFreq = 0;

		VibrationState.wLeftMotorSpeed = iLeftMotor;
		VibrationState.wRightMotorSpeed = iRightMotor;

		XInputSetState(pad, &VibrationState);
	}
}
#endif

void CPad::UpdatePads(void)
{
	bool bUpdate = true;

	GetPad(0)->UpdateMouse();
#ifdef XINPUT
	GetPad(0)->AffectFromXinput(m_bMapPadOneToPadTwo ? 1 : 0);
	GetPad(1)->AffectFromXinput(m_bMapPadOneToPadTwo ? 0 : 1);
#else
	CapturePad(0);
#endif

	// Improve keyboard input latency part 1
#ifdef FIX_BUGS
	OldKeyState = NewKeyState;
	NewKeyState = TempKeyState;
#endif

#ifdef DETECT_PAD_INPUT_SWITCH
	if (GetPad(0)->PCTempJoyState.CheckForInput())
		IsAffectedByController = true;
	else {
#endif
		ControlsManager.ClearSimButtonPressCheckers();
		ControlsManager.AffectPadFromKeyBoard();
		ControlsManager.AffectPadFromMouse();

#ifdef DETECT_PAD_INPUT_SWITCH
	}
	if (IsAffectedByController && (GetPad(0)->PCTempKeyState.CheckForInput() || GetPad(0)->PCTempMouseState.CheckForInput()))
		IsAffectedByController = false;
#endif

	if ( CReplay::IsPlayingBackFromFile() )
		bUpdate = false;

	if ( bUpdate )
		GetPad(0)->Update(0);

#ifndef MASTER
	GetPad(1)->Update(1);
#else
	GetPad(1)->NewState.Clear();
	GetPad(1)->OldState.Clear();
#endif

	// Improve keyboard input latency part 2
#ifndef FIX_BUGS
	OldKeyState = NewKeyState;
	NewKeyState = TempKeyState;
#endif
}

void CPad::ProcessPCSpecificStuff(void)
{
	;
}

void CPad::Update(int16 pad)
{
	OldState = NewState;

#ifdef GTA_PS2
	bObsoleteControllerMessage = false;

	//int iPressureBtn;
	int id;
	int ext_id=0;
	int state;
	int rterm_id = 0;
	unsigned short paddata, tpad;
	unsigned char rdata[32];

	state = scePadGetState(pad, 0);

	switch(Phase)
	{
	case 0:
		if (state != scePadStateStable && state != scePadStateFindCTP1)
			break;
		id = scePadInfoMode(pad, 0, InfoModeCurID, 0);
		if (id==0) break;

		ext_id = scePadInfoMode(pad, 0, InfoModeCurExID, 0);
		if (ext_id>0) id = ext_id;

		switch(id)
		{
		case 4: // Digital controller
			Phase = 40; // Try for analog(dualshock)
			break;
		case 7: // Dualshock2 controller
			Phase = 50;
			break;
		default:
			Phase = 99;
			break;
		}
		break;

		// Analog Controller (old dualshock)
	case 40: // Analog Contoller check valid (otherwise fail phase)
		if (scePadInfoMode(pad, 0, InfoModeIdTable, -1)==0)
		{
			Phase = 99;
			break;
		}
		Phase++;

	case 41: // Analog controller: Request Lock analog mode (asynchronous)
		if (scePadSetMainMode(pad, 0, 1, 3)==1) Phase++;
		break;

	case 42: // Analog controller: Check state of previous request
		if (scePadGetReqState(pad, 0)==scePadReqStateFaild)
		{
			Phase--;
		}

		if (scePadGetReqState(pad, 0)==scePadReqStateComplete)
		{
			// Lock mode complete
			Phase=0; // Accept normal dualshock
		}
		break;

		// DualShock 2 Controller
	case 50: // Analog Contoller check valid (otherwise fail phase)
		if (scePadInfoMode(pad, 0, InfoModeIdTable, -1)==0)
		{
			Phase = 99;
			break;
		}
		Phase++;

	case 51: // Analog controller: Request Lock analog mode (asynchronous)
		if (scePadSetMainMode(pad, 0, 1, 3)==1) Phase++;
		break;

	case 52: // Analog controller: Check state of previous request
		if (scePadGetReqState(pad, 0)==scePadReqStateFaild)
		{
			Phase--;
		}

		if (scePadGetReqState(pad, 0)==scePadReqStateComplete)
		{
			// Lock mode complete
			Phase=0; // Accept normal dualshock
		}
		break;

	case 70: // DualShock 2 check pressure sensitive possible
		if (scePadInfoPressMode(pad, 0)==1)
		{
			Phase = 76;
			break;
		}
		Phase = 99;
		break;

	case 76: // DualShock2 enable pressure sensitive mode (asynchronous function)
		if (scePadEnterPressMode(pad, 0)==1) Phase++;
		break;

	case 77: // Dualshock2 check status of request pressure sensitive mode
		if (scePadGetReqState(pad, 0)==scePadReqStateFaild) Phase--;
		if (scePadGetReqState(pad, 0)==scePadReqStateComplete)
		{
			Phase=80;
		}
		break;

		// DualShock 2 Controller
	case 80: // Set motors
		if (scePadInfoAct(pad, 0, -1, 0)==0)
		{
			Phase = 99;
		}

		act_align[0] = 0; // Offset 0 for motor0
		act_align[1] = 1; // Offset 1 for motor1

		act_align[2] = 0xff;
		act_align[3] = 0xff;
		act_align[4] = 0xff;
		act_align[5] = 0xff;

		// Asynchronous function
		if (scePadSetActAlign(pad, 0, act_align)==0) break;
		Phase++;
		break;

	case 81:
		if ( scePadGetState(pad, 0) != scePadStateExecCmd )
		{
			Phase = 99;
		}

		break;

	default:
		if ( state == scePadStateError ) break;

		if ( state == scePadStateStable || state == scePadStateFindCTP1 )
		{
			if ( ShakeDur )
			{
				ShakeDur = Max(ShakeDur - (int32)CTimer::GetTimeStepInMilliseconds(), 0);

				if ( ShakeDur == 0 )
				{
					act_direct[0] = 0;
					act_direct[1] = 0;
					scePadSetActDirect(pad, 0, act_direct);
				}
				else
				{
					act_direct[0] = 0;
					act_direct[1] = (unsigned char) ShakeFreq;
					scePadSetActDirect(pad, 0, act_direct);
				}
			}

			if (scePadRead( pad, 0, rdata )==0)
			{
				NewState.Clear();
				break;
			}

			if ((rdata[0] == 0))
			{
				paddata = (unsigned short) ( 0xffff ^ ((rdata[2]<<8)|rdata[3]) );
				rterm_id = (rdata[1]);

				if ( (rterm_id>>4) == 7 ) // DUALSHOCK
				{
					if (!CRecordDataForGame::IsPlayingBack() && !CRecordDataForChase::ShouldThisPadBeLeftAlone(pad))
					{
						tpad = paddata;

						NewState.DPadUp			= ( tpad & SCE_PADLup )	   ? 255 : 0;
						NewState.DPadDown		= ( tpad & SCE_PADLdown )  ? 255 : 0;
						NewState.DPadLeft		= ( tpad & SCE_PADLleft )  ? 255 : 0;
						NewState.DPadRight		= ( tpad & SCE_PADLright ) ? 255 : 0;
						NewState.Triangle		= ( tpad & SCE_PADRup )	   ? 255 : 0;
						NewState.Cross			= ( tpad & SCE_PADRdown )  ? 255 : 0;
						NewState.Square			= ( tpad & SCE_PADRleft )  ? 255 : 0;
						NewState.Circle			= ( tpad & SCE_PADRright ) ? 255 : 0;
						NewState.Start			= ( tpad & SCE_PADstart )  ? 255 : 0;
						NewState.Select			= ( tpad & SCE_PADselect ) ? 255 : 0;
						NewState.LeftShoulder1	= ( tpad & SCE_PADL1 )	   ? 255 : 0;
						NewState.LeftShoulder2	= ( tpad & SCE_PADL2 )	   ? 255 : 0;
						NewState.RightShoulder1 = ( tpad & SCE_PADR1 )	   ? 255 : 0;
						NewState.RightShoulder2 = ( tpad & SCE_PADR2 )	   ? 255 : 0;
						NewState.LeftShock		= ( tpad & SCE_PADi )	   ? 255 : 0;
						NewState.RightShock		= ( tpad & SCE_PADj )	   ? 255 : 0;
						NewState.RightStickX	= (short)rdata[4];
						NewState.RightStickY	= (short)rdata[5];
						NewState.LeftStickX		= (short)rdata[6];
						NewState.LeftStickY		= (short)rdata[7];

						#define CLAMP_AXIS(x) (((x) < 43 && (x) >= -42) ? 0 : (((x) > 0) ? (Max((x)-42, 0)*127/85) : Min((x)+42, 0)*127/85))
						#define FIX_AXIS(x) CLAMP_AXIS((x)-128)

						NewState.RightStickX = FIX_AXIS(NewState.RightStickX);
						NewState.RightStickY = FIX_AXIS(NewState.RightStickY);
						NewState.LeftStickX	 = FIX_AXIS(NewState.LeftStickX);
						NewState.LeftStickY	 = FIX_AXIS(NewState.LeftStickY);

						#undef FIX_AXIS
						#undef CLAMP_AXIS
					}
				}
				else if ( (rterm_id>>4) == 4 ) // Controller (digital)
				{
					if ( pad == 0 )
						bObsoleteControllerMessage = true;
					NewState.Clear();
				}

				if ( NewState.IsAnyButtonPressed() )
					LastTimeTouched = CTimer::GetTimeInMilliseconds();

				break;
			}

			if ( ++iCurrHornHistory >= HORNHISTORY_SIZE )
				iCurrHornHistory = 0;

			bHornHistory[iCurrHornHistory] = GetHorn();
			NewState.Clear();
			return;
		}
		break;
	}

	if ( pad == 0 )
	{
		bOldDisplayNoControllerMessage = bDisplayNoControllerMessage;
		if ( state == scePadStateDiscon )
		{
			bDisplayNoControllerMessage = true;
			Phase = 0;
		}
		else
			bDisplayNoControllerMessage = false;
	}

	if ( ++iCurrHornHistory >= HORNHISTORY_SIZE )
		iCurrHornHistory = 0;

	bHornHistory[iCurrHornHistory] = GetHorn();

	if ( !bDisplayNoControllerMessage )
		CGame::bDemoMode = false;
#endif

#if (defined GTA_PS2 || defined FIX_BUGS)
	if (!CRecordDataForGame::IsPlayingBack() && !CRecordDataForChase::ShouldThisPadBeLeftAlone(pad))
#endif
	{
		NewState = ReconcileTwoControllersInput(PCTempKeyState, PCTempJoyState);
		NewState = ReconcileTwoControllersInput(PCTempMouseState, NewState);
	}

	PCTempJoyState.Clear();
	PCTempKeyState.Clear();
	PCTempMouseState.Clear();

	ProcessPCSpecificStuff();

	if ( ++iCurrHornHistory >= HORNHISTORY_SIZE )
		iCurrHornHistory = 0;

	bHornHistory[iCurrHornHistory] = GetHorn();

	if ( !bDisplayNoControllerMessage )
		CGame::bDemoMode = false;
}

void CPad::DoCheats(void)
{
#ifdef DETECT_PAD_INPUT_SWITCH
	if (IsAffectedByController)
#endif
		GetPad(0)->DoCheats(0);
}

void CPad::DoCheats(int16 unk)
{
#ifdef GTA_PS2_STUFF
	if ( GetTriangleJustDown() )
		AddToCheatString('T');

	if ( GetCircleJustDown() )
		AddToCheatString('C');

	if ( GetCrossJustDown() )
		AddToCheatString('X');

	if ( GetSquareJustDown() )
		AddToCheatString('S');

	if ( GetDPadUpJustDown() )
		AddToCheatString('U');

	if ( GetDPadDownJustDown() )
		AddToCheatString('D');

	if ( GetDPadLeftJustDown() )
		AddToCheatString('L');

	if ( GetDPadRightJustDown() )
		AddToCheatString('R');

	if ( GetLeftShoulder1JustDown() )
		AddToCheatString('1');

	if ( GetLeftShoulder2JustDown() )
		AddToCheatString('2');

	if ( GetRightShoulder1JustDown() )
		AddToCheatString('3');

	if ( GetRightShoulder2JustDown() )
		AddToCheatString('4');
#endif
}

void CPad::StopPadsShaking(void)
{
	GetPad(0)->StopShaking(0);
}

void CPad::StopShaking(int16 pad)
{
#ifdef GTA_PS2_STUFF
	ShakeFreq = 0;
	ShakeDur = 0;

#ifdef GTA_PS2
	if ( Phase == 99 )
	{
		act_direct[0] = 0;
		act_direct[1] = 0;
		scePadSetActDirect(pad, 0, act_direct);
	}
#endif

#endif
}

CPad *CPad::GetPad(int32 pad)
{
	return &Pads[pad];
}
#ifdef DETECT_PAD_INPUT_SWITCH
#define CURMODE (IsAffectedByController ? Mode : 0)
#else
#define CURMODE (Mode)
#endif

int16 CPad::GetSteeringLeftRight(void)
{
	if ( ArePlayerControlsDisabled() )
		return 0;

	switch (CURMODE)
	{
		case 0:
		case 2:
		{
			int16 axis = NewState.LeftStickX;
			int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2;

			if ( Abs(axis) > Abs(dpad) )
				return axis;
			else
				return dpad;

			break;
		}

		case 1:
		case 3:
		{
			return NewState.LeftStickX;

			break;
		}
	}

	return 0;
}

int16 CPad::GetSteeringUpDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return 0;

	switch (CURMODE)
	{
		case 0:
		case 2:
		{
			int16 axis = NewState.LeftStickY;
			int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2;

			if ( Abs(axis) > Abs(dpad) )
				return axis;
			else
				return dpad;

			break;
		}

		case 1:
		case 3:
		{
			return NewState.LeftStickY;

			break;
		}
	}

	return 0;
}

int16 CPad::GetCarGunUpDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return 0;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 2:
		{
			return NewState.RightStickY;

			break;
		}

		case 3:
		{
			return (NewState.DPadUp - NewState.DPadDown) / 2;

			break;
		}
	}

	return 0;
}

int16 CPad::GetCarGunLeftRight(void)
{
	if ( ArePlayerControlsDisabled() )
		return 0;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 2:
		{
			return NewState.RightStickX;

			break;
		}

		case 3:
		{
			return (NewState.DPadRight - NewState.DPadLeft) / 2;

			break;
		}
	}

	return 0;
}

int16 CPad::GetPedWalkLeftRight(void)
{
	if ( ArePlayerControlsDisabled() )
		return 0;

	switch (CURMODE)
	{
		case 0:
		case 2:
		{
			int16 axis = NewState.LeftStickX;
			int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2;

			if ( Abs(axis) > Abs(dpad) )
				return axis;
			else
				return dpad;

			break;
		}

		case 1:
		case 3:
		{
			return NewState.LeftStickX;

			break;
		}
	}

	return 0;
}

int16 CPad::GetPedWalkUpDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return 0;

	switch (CURMODE)
	{
		case 0:
		case 2:
		{
			int16 axis = NewState.LeftStickY;
			int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2;

			if ( Abs(axis) > Abs(dpad) )
				return axis;
			else
				return dpad;

			break;
		}

		case 1:
		case 3:
		{
			return NewState.LeftStickY;

			break;
		}
	}

	return 0;
}

int16 CPad::GetAnalogueUpDown(void)
{
	switch (CURMODE)
	{
		case 0:
		case 2:
		{
			int16 axis = NewState.LeftStickY;
			int16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2;

			if ( Abs(axis) > Abs(dpad) )
				return axis;
			else
				return dpad;

			break;
		}

		case 1:
		case 3:
		{
			return NewState.LeftStickY;

			break;
		}
	}

	return 0;
}

bool CPad::GetLookLeft(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	return !!(NewState.LeftShoulder2 && !NewState.RightShoulder2);
}

bool CPad::GetLookRight(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	return !!(NewState.RightShoulder2 && !NewState.LeftShoulder2);
}

bool CPad::GetLookBehindForCar(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	return !!(NewState.RightShoulder2 && NewState.LeftShoulder2);
}

bool CPad::GetLookBehindForPed(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	return !!NewState.RightShock;
}

bool CPad::GetHorn(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		{
			return !!NewState.LeftShock;

			break;
		}

		case 1:
		{
			return !!NewState.LeftShoulder1;

			break;
		}

		case 2:
		{
			return !!NewState.RightShoulder1;

			break;
		}

		case 3:
		{
			return !!NewState.LeftShock;

			break;
		}
	}

	return false;
}

bool CPad::HornJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		{
			return !!(NewState.LeftShock && !OldState.LeftShock);

			break;
		}

		case 1:
		{
			return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1);

			break;
		}

		case 2:
		{
			return !!(NewState.RightShoulder1 && !OldState.RightShoulder1);

			break;
		}

		case 3:
		{
			return !!(NewState.LeftShock && !OldState.LeftShock);

			break;
		}
	}

	return false;
}

bool CPad::GetCarGunFired(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 2:
		{
			return !!NewState.Circle;

			break;
		}

		case 3:
		{
			return !!NewState.RightShoulder1;

			break;
		}
	}

	return false;
}

bool CPad::CarGunJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 2:
		{
			return !!(NewState.Circle && !OldState.Circle);

			break;
		}

		case 3:
		{
			return !!(NewState.RightShoulder1 && !OldState.RightShoulder1);

			break;
		}
	}

	return false;
}

int16 CPad::GetHandBrake(void)
{
	if ( ArePlayerControlsDisabled() )
		return 0;

	switch (CURMODE)
	{
		case 0:
		case 1:
		{
			return NewState.RightShoulder1;

			break;
		}

		case 2:
		{
			return NewState.Triangle;

			break;
		}

		case 3:
		{
			return NewState.LeftShoulder1;

			break;
		}
	}

	return 0;
}

int16 CPad::GetBrake(void)
{
	if ( ArePlayerControlsDisabled() )
		return 0;

	switch (CURMODE)
	{
		case 0:
		case 2:
		{
			return NewState.Square;

			break;
		}

		case 1:
		{
			return NewState.Square;

			break;
		}

		case 3:
		{
			int16 axis = 2 * NewState.RightStickY;

			if ( axis < 0 )
				return 0;
			else
				return axis;

			break;
		}
	}

	return 0;
}

bool CPad::GetExitVehicle(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 3:
		{
			return !!NewState.Triangle;

			break;
		}

		case 2:
		{
			return !!NewState.LeftShoulder1;

			break;
		}
	}

	return false;
}

bool CPad::ExitVehicleJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 3:
		{
			return !!(NewState.Triangle && !OldState.Triangle);

			break;
		}

		case 2:
		{
			return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1);

			break;
		}
	}

	return false;
}

int32 CPad::GetWeapon(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		{
			return NewState.Circle;

			break;
		}

		case 2:
		{
			return NewState.Cross;

			break;
		}

		case 3:
		{
			return NewState.RightShoulder1;

			break;
		}
	}

	return false;
}

bool CPad::WeaponJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		{
			return !!(NewState.Circle && !OldState.Circle);

			break;
		}

		case 2:
		{
			return !!(NewState.Cross && !OldState.Cross);

			break;
		}

		case 3:
		{
			return !!(NewState.RightShoulder1 && !OldState.RightShoulder1);

			break;
		}
	}

	return false;
}

int16 CPad::GetAccelerate(void)
{
	if ( ArePlayerControlsDisabled() )
		return 0;

	switch (CURMODE)
	{
		case 0:
		case 2:
		{
			return NewState.Cross;

			break;
		}

		case 1:
		{
			return NewState.Cross;

			break;
		}

		case 3:
		{
			int16 axis = -2 * NewState.RightStickY;

			if ( axis < 0 )
				return 0;
			else
				return axis;

			break;
		}
	}

	return 0;
}

bool CPad::CycleCameraModeUpJustDown(void)
{
	switch (CURMODE)
	{
		case 0:
		case 2:
		case 3:
		{
			return !!(NewState.Select && !OldState.Select);

			break;
		}

		case 1:
		{
			return !!(NewState.DPadUp && !OldState.DPadUp);

			break;
		}
	}

	return false;
}

bool CPad::CycleCameraModeDownJustDown(void)
{
	switch (CURMODE)
	{
		case 0:
		case 2:
		case 3:
		{
			return false;

			break;
		}

		case 1:
		{
			return !!(NewState.DPadDown && !OldState.DPadDown);

			break;
		}
	}

	return false;
}

bool CPad::ChangeStationJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		{
			return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1);

			break;
		}

		case 1:
		{
			return !!(NewState.Select && !OldState.Select);

			break;
		}

		case 2:
		{
			return !!(NewState.LeftShock && !OldState.LeftShock);

			break;
		}

		case 3:
		{
			return !!(NewState.Circle && !OldState.Circle);

			break;
		}
	}

	return false;
}

bool CPad::CycleWeaponLeftJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2);
}

bool CPad::CycleWeaponRightJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	return !!(NewState.RightShoulder2 && !OldState.RightShoulder2);
}

bool CPad::GetTarget(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 2:
		{
			return !!NewState.RightShoulder1;

			break;
		}

		case 3:
		{
			return !!NewState.LeftShoulder1;

			break;
		}
	}

	return false;
}

bool CPad::TargetJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 2:
		{
			return !!(NewState.RightShoulder1 && !OldState.RightShoulder1);

			break;
		}

		case 3:
		{
			return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1);

			break;
		}
	}

	return false;
}

bool CPad::JumpJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	return !!(NewState.Square && !OldState.Square);
}

bool CPad::GetSprint(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 3:
		{
			return !!NewState.Cross;

			break;
		}

		case 2:
		{
			return !!NewState.Circle;

			break;
		}
	}

	return false;
}

bool CPad::ShiftTargetLeftJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2);
}

bool CPad::ShiftTargetRightJustDown(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	return !!(NewState.RightShoulder2 && !OldState.RightShoulder2);
}

#ifdef FIX_BUGS
// FIX: fixes from VC for the bug of double switching the controller setup
bool CPad::GetAnaloguePadUp(void)
{
	static int16 oldfStickY = 0;

	int16 leftStickY = CPad::GetPad(0)->GetLeftStickY();

	if ( leftStickY < -15 && oldfStickY >= -5 )
	{
		oldfStickY = leftStickY;
		return true;
	}
	else
	{
		oldfStickY = leftStickY;
		return false;
	}
}

bool CPad::GetAnaloguePadDown(void)
{
	static int16 oldfStickY = 0;

	int16 leftStickY = CPad::GetPad(0)->GetLeftStickY();

	if ( leftStickY > 15 && oldfStickY <= 5 )
	{
		oldfStickY = leftStickY;
		return true;
	}
	else
	{
		oldfStickY = leftStickY;
		return false;
	}
}

bool CPad::GetAnaloguePadLeft(void)
{
	static int16 oldfStickX = 0;

	int16 leftStickX = CPad::GetPad(0)->GetLeftStickX();

	if ( leftStickX < -15 && oldfStickX >= -5 )
	{
		oldfStickX = leftStickX;
		return true;
	}
	else
	{
		oldfStickX = leftStickX;
		return false;
	}
}

bool CPad::GetAnaloguePadRight(void)
{
	static int16 oldfStickX = 0;

	int16 leftStickX = CPad::GetPad(0)->GetLeftStickX();

	if ( leftStickX > 15 && oldfStickX <= 5 )
	{
		oldfStickX = leftStickX;
		return true;
	}
	else
	{
		oldfStickX = leftStickX;
		return false;
	}
}

bool CPad::GetAnaloguePadLeftJustUp(void)
{
	static int16 oldfStickX = 0;

	int16 X = GetPad(0)->GetPedWalkLeftRight();

	if ( X == 0 && oldfStickX < 0 )
	{
		oldfStickX = 0;

		return true;
	}
	else
	{
		oldfStickX = X;

		return false;
	}
}

bool CPad::GetAnaloguePadRightJustUp(void)
{
	static int16 oldfStickX = 0;

	int16 X = GetPad(0)->GetPedWalkLeftRight();

	if ( X == 0 && oldfStickX > 0 )
	{
		oldfStickX = 0;

		return true;
	}
	else
	{
		oldfStickX = X;

		return false;
	}
}

#else
bool CPad::GetAnaloguePadUp(void)
{
	static int16 oldfStickY = 0;

	int16 Y = CPad::GetPad(0)->GetAnalogueUpDown();

	if ( Y < 0 && oldfStickY >= 0 )
	{
		oldfStickY = Y;
		return true;
	}
	else
	{
		oldfStickY = Y;
		return false;
	}
}

bool CPad::GetAnaloguePadDown(void)
{
	static int16 oldfStickY = 0;

	int16 Y = CPad::GetPad(0)->GetAnalogueUpDown();

	if ( Y > 0 && oldfStickY <= 0 )
	{
		oldfStickY = Y;
		return true;
	}
	else
	{
		oldfStickY = Y;
		return false;
	}
}

bool CPad::GetAnaloguePadLeft(void)
{
	static int16 oldfStickX = 0;

	int16 X = CPad::GetPad(0)->GetPedWalkLeftRight();

	if ( X < 0 && oldfStickX >= 0 )
	{
		oldfStickX = X;
		return true;
	}
	else
	{
		oldfStickX = X;
		return false;
	}
}

bool CPad::GetAnaloguePadRight(void)
{
	static int16 oldfStickX = 0;

	int16 X = CPad::GetPad(0)->GetPedWalkLeftRight();

	if ( X > 0 && oldfStickX <= 0 )
	{
		oldfStickX = X;
		return true;
	}
	else
	{
		oldfStickX = X;
		return false;
	}
}

bool CPad::GetAnaloguePadLeftJustUp(void)
{
	static int16 oldfStickX = 0;

	int16 X = GetPad(0)->GetPedWalkLeftRight();

	if ( X == 0 && oldfStickX < 0 )
	{
		oldfStickX = 0;

		return true;
	}
	else
	{
		oldfStickX = X;

		return false;
	}
}

bool CPad::GetAnaloguePadRightJustUp(void)
{
	static int16 oldfStickX = 0;

	int16 X = GetPad(0)->GetPedWalkLeftRight();

	if ( X == 0 && oldfStickX > 0 )
	{
		oldfStickX = 0;

		return true;
	}
	else
	{
		oldfStickX = X;

		return false;
	}
}
#endif

bool CPad::ForceCameraBehindPlayer(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		{
			return !!NewState.LeftShoulder1;

			break;
		}

		case 2:
		{
			return !!NewState.Triangle;

			break;
		}

		case 3:
		{
			return !!NewState.Circle;

			break;
		}
	}

	return false;
}

bool CPad::SniperZoomIn(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 3:
		{
			return !!NewState.Square;

			break;
		}

		case 2:
		{
			return !!NewState.Triangle;

			break;
		}
	}

	return false;
}

bool CPad::SniperZoomOut(void)
{
	if ( ArePlayerControlsDisabled() )
		return false;

	switch (CURMODE)
	{
		case 0:
		case 1:
		case 3:
		{
			return !!NewState.Cross;

			break;
		}

		case 2:
		{
			return !!NewState.Square;

			break;
		}
	}

	return false;
}

#undef CURMODE

int16 CPad::SniperModeLookLeftRight(void)
{
	int16 axis = NewState.LeftStickX;
	int16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2;

	if ( Abs(axis) > Abs(dpad) )
		return axis;
	else
		return dpad;
}

int16 CPad::SniperModeLookUpDown(void)
{
	int16 axis = NewState.LeftStickY;
	int16 dpad;
#ifdef FIX_BUGS
	axis = -axis;
#endif
#ifndef INVERT_LOOK_FOR_PAD
	dpad = (NewState.DPadUp - NewState.DPadDown) / 2;
#else
	if (CPad::bInvertLook4Pad) {
		axis = -axis;
		dpad = (NewState.DPadDown - NewState.DPadUp) / 2;
	} else {
		dpad = (NewState.DPadUp - NewState.DPadDown) / 2;
	}
#endif

	if ( Abs(axis) > Abs(dpad) )
		return axis;
	else
		return dpad;
}

int16 CPad::LookAroundLeftRight(void)
{
	float axis = GetPad(0)->NewState.RightStickX;

	if ( Abs(axis) > 85 && !GetLookBehindForPed() )
		return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) )
							* (127.0f / 32.0f) ); // 3.96875f

	else if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 10 )
		return (int16) ( (axis + ( ( axis > 0 ) ? -10 : 10) )
							* (127.0f / 64.0f) ); // 1.984375f

	return 0;
}

int16 CPad::LookAroundUpDown(void)
{
	int16 axis = GetPad(0)->NewState.RightStickY;

#ifdef FIX_BUGS
	axis = -axis;
#endif
#ifdef INVERT_LOOK_FOR_PAD
	if (CPad::bInvertLook4Pad)
		axis = -axis;
#endif

	if ( Abs(axis) > 85 && !GetLookBehindForPed() )
		return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) )
							* (127.0f / 32.0f) ); // 3.96875f

	else if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 40 )
		return (int16) ( (axis + ( ( axis > 0 ) ? -40 : 40) )
							* (127.0f / 64.0f) ); // 1.984375f

	return 0;
}

void CPad::ResetAverageWeapon(void)
{
	AverageWeapon = GetWeapon();
	AverageEntries = 1;
}

void CPad::PrintErrorMessage(void)
{
	if ( bDisplayNoControllerMessage && !CGame::playingIntro && !FrontEndMenuManager.m_bMenuActive )
	{
#ifdef FIX_BUGS
		CFont::SetScale(SCREEN_SCALE_X(0.85f), SCREEN_SCALE_Y(1.0f));
#else
		CFont::SetScale(0.85f, 1.0f);
#endif
		CFont::SetJustifyOff();
		CFont::SetBackgroundOff();
#ifdef FIX_BUGS
		CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));
#else
		CFont::SetCentreSize(SCREEN_WIDTH - 20);
#endif
		CFont::SetCentreOn();
		CFont::SetPropOn();
		CFont::SetColor(CRGBA(255, 255, 200, 200));
		CFont::SetFontStyle(FONT_BANK);
		CFont::PrintString
		(
			SCREEN_WIDTH  / 2,
			SCREEN_HEIGHT / 2,
			TheText.Get("NOCONT") // Please reconnect an analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2). to controller port 1 to continue
		);
	}
	else if ( bObsoleteControllerMessage )
	{
#ifdef FIX_BUGS
		CFont::SetScale(SCREEN_SCALE_X(0.85f), SCREEN_SCALE_Y(1.0f));
#else
		CFont::SetScale(0.85f, 1.0f);
#endif
		CFont::SetJustifyOff();
		CFont::SetBackgroundOff();
#ifdef FIX_BUGS
		CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));
#else
		CFont::SetCentreSize(SCREEN_WIDTH - 20);
#endif
		CFont::SetCentreOn();
		CFont::SetPropOn();
		CFont::SetColor(CRGBA(255, 255, 200, 200));
		CFont::SetFontStyle(FONT_BANK);
		CFont::PrintString
		(
			SCREEN_WIDTH  / 2,
			SCREEN_HEIGHT / 2,
			TheText.Get("WRCONT") // The controller connected to controller port 1 is an unsupported controller. Grand Theft Auto III requires an analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2).
		);
	}

}

void LittleTest(void)
{
	static int32 Cunt = 0;

	Cunt++; // ???
}

void CPad::ResetCheats(void)
{
	CWeather::ReleaseWeather();

	CPopulation::ms_bGivePedsWeapons = false;

	CPed::bNastyLimbsCheat = false;
	CPed::bPedCheat2 = false;
	CPed::bPedCheat3 = false;

	CVehicle::bWheelsOnlyCheat = false;
	CVehicle::bAllDodosCheat = false;
	CVehicle::bCheat3 = false;
	CVehicle::bCheat4 = false;
	CVehicle::bCheat5 = false;

	gbFastTime = false;
	CTimer::SetTimeScale(1.0f);
}

char *CPad::EditString(char *pStr, int32 nSize)
{
	int32 pos = (int32)strlen(pStr);

	// letters
	for ( int32 i = 0; i < ('Z' - 'A' + 1); i++ )
	{
		if ( GetPad(0)->GetCharJustDown(i + 'A') && pos < nSize - 1 )
		{
			pStr[pos++] = i + 'A';
			pStr[pos] = '\0';
		}

		if ( GetPad(0)->GetCharJustDown(i + 'a') && pos < nSize - 1 )
		{
			pStr[pos++] = i + 'a';
			pStr[pos] = '\0';
		}
	}

	// numbers
	for ( int32 i = 0; i < ('9' - '0' + 1); i++ )
	{
		if ( GetPad(0)->GetCharJustDown(i + '0') && pos < nSize - 1 )
		{
			pStr[pos++] = i + '0';
			pStr[pos] = '\0';
		}
	}

	// space
	if ( GetPad(0)->GetCharJustDown(' ') && pos < nSize - 1 )
	{
		pStr[pos++] = ' ';
		pStr[pos] = '\0';
	}

	// del
	if ( GetPad(0)->GetDeleteJustDown() || GetPad(0)->GetBackspaceJustDown() )
	{
		if ( pos > 0 )
			pStr[pos - 1] = '\0';
	}

	// extenter/up/down
	if ( GetPad(0)->GetReturnJustDown() || GetPad(0)->GetUpJustDown() || GetPad(0)->GetDownJustDown() )
		return nil;

	return pStr;
}

int32 *CPad::EditCodesForControls(int32 *pRsKeys, int32 nSize)
{
	*pRsKeys = rsNULL;

	for ( int32 i = 0; i < 255; i++ )
	{
		if ( GetPad(0)->GetCharJustDown(i) )
			*pRsKeys = i;
	}

	for ( int32 i = 0; i < 12; i++ )
	{
		if ( GetPad(0)->GetFJustDown(i) )
			*pRsKeys = i + rsF1;
	}

	if ( GetPad(0)->GetEscapeJustDown() )
		*pRsKeys = rsESC;

	if ( GetPad(0)->GetInsertJustDown() )
		*pRsKeys = rsINS;

	if ( GetPad(0)->GetDeleteJustDown() )
		*pRsKeys = rsDEL;

	if ( GetPad(0)->GetHomeJustDown() )
		*pRsKeys = rsHOME;

	if ( GetPad(0)->GetEndJustDown() )
		*pRsKeys = rsEND;

	if ( GetPad(0)->GetPageUpJustDown() )
		*pRsKeys = rsPGUP;

	if ( GetPad(0)->GetPageDownJustDown() )
		*pRsKeys = rsPGDN;

	if ( GetPad(0)->GetUpJustDown() )
		*pRsKeys = rsUP;

	if ( GetPad(0)->GetDownJustDown() )
		*pRsKeys = rsDOWN;

	if ( GetPad(0)->GetLeftJustDown() )
		*pRsKeys = rsLEFT;

	if ( GetPad(0)->GetRightJustDown() )
		*pRsKeys = rsRIGHT;

	if ( GetPad(0)->GetScrollLockJustDown() )
		*pRsKeys = rsSCROLL;

	if ( GetPad(0)->GetPauseJustDown() )
		*pRsKeys = rsPAUSE;

	if ( GetPad(0)->GetNumLockJustDown() )
		*pRsKeys = rsNUMLOCK;

	if ( GetPad(0)->GetDivideJustDown() )
		*pRsKeys = rsDIVIDE;

	if ( GetPad(0)->GetTimesJustDown() )
		*pRsKeys = rsTIMES;

	if ( GetPad(0)->GetMinusJustDown() )
		*pRsKeys = rsMINUS;

	if ( GetPad(0)->GetPlusJustDown() )
		*pRsKeys = rsPLUS;

	if ( GetPad(0)->GetPadEnterJustDown() )
		*pRsKeys = rsPADENTER;

	if ( GetPad(0)->GetPadDelJustDown() )
		*pRsKeys = rsPADDEL;

	if ( GetPad(0)->GetPad1JustDown() )
		*pRsKeys = rsPADEND;

	if ( GetPad(0)->GetPad2JustDown() )
		*pRsKeys = rsPADDOWN;

	if ( GetPad(0)->GetPad3JustDown() )
		*pRsKeys = rsPADPGDN;

	if ( GetPad(0)->GetPad4JustDown() )
		*pRsKeys = rsPADLEFT;

	if ( GetPad(0)->GetPad5JustDown() )
		*pRsKeys = rsPAD5;

	if ( GetPad(0)->GetPad6JustDown() )
		*pRsKeys = rsPADRIGHT;

	if ( GetPad(0)->GetPad7JustDown() )
		*pRsKeys = rsPADHOME;

	if ( GetPad(0)->GetPad8JustDown() )
		*pRsKeys = rsPADUP;

	if ( GetPad(0)->GetPad9JustDown() )
		*pRsKeys = rsPADPGUP;

	if ( GetPad(0)->GetPad0JustDown() )
		*pRsKeys = rsPADINS;

	if ( GetPad(0)->GetBackspaceJustDown() )
		*pRsKeys = rsBACKSP;

	if ( GetPad(0)->GetTabJustDown() )
		*pRsKeys = rsTAB;

	if ( GetPad(0)->GetCapsLockJustDown() )
		*pRsKeys = rsCAPSLK;

	if ( GetPad(0)->GetReturnJustDown() )
		*pRsKeys = rsENTER;

	if ( GetPad(0)->GetLeftShiftJustDown() )
		*pRsKeys = rsLSHIFT;

	if ( GetPad(0)->GetShiftJustDown() )
		*pRsKeys = rsSHIFT;

	if ( GetPad(0)->GetRightShiftJustDown() )
		*pRsKeys = rsRSHIFT;

	if ( GetPad(0)->GetLeftCtrlJustDown() )
		*pRsKeys = rsLCTRL;

	if ( GetPad(0)->GetRightCtrlJustDown() )
		*pRsKeys = rsRCTRL;

	if ( GetPad(0)->GetLeftAltJustDown() )
		*pRsKeys = rsLALT;

	if ( GetPad(0)->GetRightAltJustDown() )
		*pRsKeys = rsRALT;

	if ( GetPad(0)->GetLeftWinJustDown() )
		*pRsKeys = rsLWIN;

	if ( GetPad(0)->GetRightWinJustDown() )
		*pRsKeys = rsRWIN;

	if ( GetPad(0)->GetAppsJustDown() )
		*pRsKeys = rsAPPS;

	return pRsKeys;
}

license: mit