#include <xtl.h>
#include <string>
#include <vector>
#include <algorithm>
#include <direct.h>
#include <tchar.h>
#include <fstream>
#include "Undocumented.h"
#include "xbinput.h"
#include "XBUtil.h"
#include "XBSound.h"
#include "gameinp.h"
#include <stdlib.h>
#include <sstream>
#include "Mp3Player.h"
using namespace std;
#define GIT_SWITCH			(0x02)
#define MAIN_MENU 0
#define ROM_SELECT 1
#define FAVORITE_SELECT 2
typedef unsigned char bool8;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef signed char int8;
typedef short int16;
typedef long int32;
typedef unsigned int uint32;
IDirect3D8 *Direct3D=NULL;
IDirect3DDevice8 *Device=NULL;
IDirect3DSurface8 *DirectBack=NULL;
IDirect3DVertexBuffer8 *VertexBuffer=NULL;
IDirect3DVertexBuffer8 *VertexBufferMainMenuOverlay1=NULL;
IDirect3DVertexBuffer8 *VertexBufferMainMenuOverlay2=NULL;
IDirect3DVertexBuffer8 *VertexBufferMainMenuOverlay3=NULL;
IDirect3DVertexBuffer8 *VertexBufferMainMenuOverlay4=NULL;
IDirect3DVertexBuffer8 *VertexBufferMainMenuOverlay5=NULL;
IDirect3DVertexBuffer8 *VertexBufferMainMenuOverlay6=NULL;
IDirect3DVertexBuffer8 *VertexBufferMenu=NULL;
IDirect3DVertexBuffer8 *VertexBufferPreview=NULL;
IDirect3DVertexBuffer8 *VertexBufferPreviewBorder=NULL;
IDirect3DVertexBuffer8 *VertexBufferPreviewVertical=NULL;
IDirect3DVertexBuffer8 *VertexBufferPreviewBorderVertical=NULL;
IDirect3DVertexBuffer8 *VertexBufferInfoBorder=NULL;
IDirect3DVertexBuffer8 *VertexBufferInfoBorderSimple=NULL;
IDirect3DVertexBuffer8 *VertexBufferVideoBorder=NULL;
IDirect3DVertexBuffer8 *VertexBufferDualVideoBorder=NULL;
IDirect3DVertexBuffer8 *VertexBufferROMBorder=NULL;
IDirect3DVertexBuffer8 *VertexBufferSelectBorder=NULL;
IDirect3DVertexBuffer8 *VertexBufferExitGame=NULL;
IDirect3DVertexBuffer8 *VertexBufferAlternatePreview=NULL;
IDirect3DVertexBuffer8 *VertexBufferAlternatePreviewBorder=NULL;
IDirect3DVertexBuffer8 *VertexBufferAlternatePreviewVertical=NULL;
IDirect3DVertexBuffer8 *VertexBufferAlternatePreviewBorderVertical=NULL;
IDirect3DVertexBuffer8 *VertexBufferAnimatedLogo=NULL;
IDirect3DVertexBuffer8 *VertexBufferAnimatedLogoMainMenu=NULL;
IDirect3DVertexBuffer8 *VertexBufferSplashScreen=NULL;
IDirect3DTexture8 *TexMainMenuOverlay=NULL;
IDirect3DTexture8 *TexScreen=NULL;
IDirect3DTexture8 *TexROMBrowser=NULL;
IDirect3DTexture8 *TexOption=NULL;
IDirect3DTexture8 *TexPreview=NULL;
IDirect3DTexture8 *TexPreviewBorder=NULL;
IDirect3DTexture8 *TexInfoBorder=NULL;
IDirect3DTexture8 *TexInfoBorderSimple=NULL;
IDirect3DTexture8 *TexVideoBorder=NULL;
IDirect3DTexture8 *TexROMBorder=NULL;
IDirect3DTexture8 *TexSelectedBorder=NULL;
IDirect3DTexture8 *TexAnimatedLogo=NULL;
IDirect3DTexture8 *TexMainMenu=NULL;
IDirect3DTexture8 *TexSplashScreen=NULL;
IDirect3DTexture8 *TexAnimatedLogoMainMenu=NULL;
D3DPRESENT_PARAMETERS d3dpp; 
struct CustomVertex
{
	float x,y,z; // Vertex cordinates
	unsigned int colour;
	float u,v; // Texture coordinates
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
CustomVertex VertexList[4];
CustomVertex VertexListMenu[4];
CustomVertex VertexListMainMenuOverlay1[4];
CustomVertex VertexListMainMenuOverlay2[4];
CustomVertex VertexListMainMenuOverlay3[4];
CustomVertex VertexListMainMenuOverlay4[4];
CustomVertex VertexListMainMenuOverlay5[4];
CustomVertex VertexListMainMenuOverlay6[4];
CustomVertex VertexListPreview[4];
CustomVertex VertexListPreviewBorder[4];
CustomVertex VertexListPreviewVertical[4];
CustomVertex VertexListPreviewBorderVertical[4];
CustomVertex VertexListInfoBorder[4];
CustomVertex VertexListInfoBorderSimple[4];
CustomVertex VertexListVideoBorder[4];
CustomVertex VertexListDualVideoBorder[4];
CustomVertex VertexListROMBorder[4];
CustomVertex VertexListSelectBorder[4];
CustomVertex VertexListExitGame[4];
CustomVertex VertexListAlternatePreview[4];
CustomVertex VertexListAlternatePreviewBorder[4];
CustomVertex VertexListAlternatePreviewVertical[4];
CustomVertex VertexListAlternatePreviewBorderVertical[4];
CustomVertex VertexListAnimatedLogo[4];
CustomVertex VertexListAnimatedLogoMainMenu[4];
CustomVertex VertexListSplashScreen[4];
int TexWidth=0,TexHeight=0;
struct GameDBEntry {
	std::string name;
	std::string displayName;
	std::string date;
	std::string manufacturer;
	std::string system;
	std::string genre;
	std::string parent;
};

struct guideDBEntry {
	string name;
	string path;
};
double slowGuide = 0;
int guideGameSelectedText = 0;
int guideGameSelected = 0;
vector<guideDBEntry> guideDatabase;
double analogSpeed = 0;
std::vector<GameDBEntry> GameDatabase;
std::vector<GameDBEntry> GameDatabaseTemp;
std::vector<GameDBEntry> FavoritesDatabase;
int GameFavoriteSelected = 0;
static FILE *DebugFile=NULL;
int MenuSelected = 0;
int OptionSelected = 0;
int FilterSelected = 0;
int OptionGUITextSelected = 0;
int OptionControllerSelected = 0;
int OptionControllerMacroSelected = 0;
int OptionGUISelected = 0;
int OptionControllerButtonSelected = 0;
bool Emulation = false;
int OptionVideoSelected = 0;
int OptionEmulationVideoSelected = 0;
int OptionSoundSelected = 0;
int OptionEmulationSoundSelected = 0;
int GameOptionSelected = 0;
int OptionGUIControllerItemsSelected = 0;
bool setDisplay = false;
bool m_bVideoModeChanged = false;
bool v720pAvailable = false; 
bool v480pAvailable = false; 
bool v1080iAvailable = false; 
int sWidth = 640;
int sHeight = 480;
bool exitGameMenu = false;
int resetGame = 0;
int dipSwitches = 0;
bool scale = false;
int SaveSlotSelected = 0;
int OptionGUIImageSelected = 0;
int OptionGUIImageSelectedPage2 = 0;
bool analogScroll = false;
int controller1Count = 0;
int GameInfoDetailSelected = 0;
int controller2Count = 0;
int controller3Count = 0;
int controller4Count = 0;
int TurboController = 0;
int ATurbo = 0;
int BTurbo = 0;
int XTurbo = 0;
int YTurbo = 0;
int WhiteTurbo = 0;
int BlackTurbo = 0;
int LeftTurbo = 0;
int RightTurbo = 0;
bool exitEmulation = false;
int ArcadeSettingSelected = 0;
struct Category {
	string name;
	string genre;
};
vector<string> FilterItems;
vector <string> FilterGenre;
vector <string> FilterCompany;
vector <string> FilterYear;
vector <string> FilterCustom;
vector<string> GameInfoDetail;
std::vector<string> OptionItems;
std::vector<string> OptionVideoItems;
std::vector<string> OptionVideoValueItems;
std::vector<string> OptionEmulationVideoItems;
std::vector<string> OptionEmulationVideoValueItems;
std::vector<string> OptionSoundItems;
std::vector<string> OptionSoundValueItems;
std::vector<string> OptionControllerItems;
std::vector<string> OptionControllerMacroItems;
std::vector<string> OptionGUIItems;
std::vector<string> OptionControllerButtonItems[4];
std::vector<string> OptionControllerButtonValueItems[4];
std::vector<string> GameOptionItems;
std::vector<string> OptionEmulationSoundItems;
std::vector<string> OptionEmulationSoundValueItems;
std::vector<string> SaveStateItems;
std::vector<string> LoadStateItems;
std::vector<string> OptionGUITextItems;
std::vector<string> OptionGUITextValueItems;
std::vector<string> OptionGUITextPage2Items;
std::vector<string> OptionGUITextPage2ValueItems;
std::vector<string> OptionGUIImageItems;
std::vector<string> OptionGUIImageValueItems;
std::vector<string> OptionGUIImageItemsPage2;
std::vector<string> OptionGUIImageValueItemsPage2;
std::vector<string> OptionGUIImageItemsPage3;
std::vector<string> OptionGUIImageValueItemsPage3;
std::vector<string> OptionGUIControllerItems;
std::vector<string> guide;
int slow = 0;
float zLeftScale=0;
float zRightScale=0;
float zTopScale=0;
float zBottomScale=0;
float leftMove = 0;
float rightMove = 0;
float topMove = 0;
float bottomMove = 0;
int zoomOver = 0;
int OptionGUITextPage2Selected = 0;
float zBaseLeft=-2.899998;
float zBaseRight=2.809998;
float zBaseTop=-0.620000;
float zBaseBottom=0.580000;
float zLeft=0;
float zRight=0;
float zTop=0;
float zBottom=0;
int GameSelected = 0;
bool resumeGUI = false;
WCHAR msg[1024]={0};
int CheatSelected = 0;
int CheatValueSelected = 0;
bool videoRender = false;
string activeMovie = "";
int SetAlpha = 0;
int DebugX = 40;
int DebugY = 20;
int turboControllerSelected = 0; 
float speedROMBrowserLogo = 0.0095;
float distanceROMBrowserLogo = 0.3;
float cMoveROMBrowserLogo = 0;
float lMoveROMBrowserLogo = -1 * distanceROMBrowserLogo;
float rMoveROMBrowserLogo = distanceROMBrowserLogo;
float tMoveROMBrowserLogo = distanceROMBrowserLogo;
float bMoveROMBrowserLogo = -1 * distanceROMBrowserLogo;
float lastTimeROMBrowserLogo = 0;
LARGE_INTEGER ticksPerSecondROMBrowserLogo;
LARGE_INTEGER tickROMBrowserLogo;
LARGE_INTEGER timeROMBrowserLogo;
float lastTimeSplashScreen = 0;
LARGE_INTEGER ticksPerSecondSplashScreen;
LARGE_INTEGER tickSplashScreen;
LARGE_INTEGER timeSplashScreen;
LARGE_INTEGER ticksPerSecondPreviewSwitch;
LARGE_INTEGER tickPreviewSwitch;
LARGE_INTEGER timePreviewSwitch;
float lastTimePreviewSwitch = 0;
LARGE_INTEGER ticksPerSecondDelay;
LARGE_INTEGER tickDelay;
LARGE_INTEGER timeDelay;
float lastTimeDelay = 0;
LARGE_INTEGER ScreenSaverDelay;
float ScreenSaverLastTimeDelay = 0;
int OptionControllerTurboSelected = 0;
vector<string> OptionControllerTurboItems;
vector<string> OptionControllerTurboValueItems;
float RotationDegrees = 0;
struct ArcadeSetting {
	std::string name;
	int code;
	int count;
};
std::vector<ArcadeSetting> arcadeSettings;
Mp3Player m_mp3player;
HANDLE g_hSoundThread;
DWORD g_dwSoundThreadId;
Mp3Player m_mp3playerSplash;
HANDLE g_hSoundThreadSplash;
DWORD g_dwSoundThreadIdSplash;
std::string RomPath1 = "D:\\roms";
std::string RomPath2 = "";
std::string RomPath3 = "";
std::string RomPath4 = "";
std::string RomPath5 = "";
std::string RomPath6 = "";
std::string RomPath7 = "";
std::string RomPath8 = "";
std::string ArtworkPath1="D:\\artwork\\Shots 1";
std::string ArtworkPath2="D:\\artwork\\Shots 2";
std::string ArtworkPath3="D:\\artwork\\Shots 3";
std::string ArtworkPath4="D:\\artwork\\Shots 4" ;
std::string ArtworkPath5="D:\\artwork\\Shots 5"; 
std::string ArtworkPath6="D:\\artwork\\Shots 6"; 
std::string ArtworkPath7="D:\\artwork\\Shots 7"; 
std::string ArtworkPath8="D:\\artwork\\Shots 8"; 
std::string NVRAMPath="D:\\nvram"; 
std::string IniPath="D:\\ini"; 
std::string SaveStatePath="D:\\savestates"; 
std::string ConfigPath="D:\\config";
std::string HiScorePath="D:\\hiscores";
std::string VideoPath="D:\\videos";
std::string SkinPath="arcade";
int UsePathINI = 0;
unsigned int m_performanceFreq[2];
unsigned int m_performanceFreqSplash[2];
bool SplashFinshed = false;
int CurrentArtwork = 1;
bool PreviewSwitch = false;
int GUIState = MAIN_MENU;
int GameListWidth=530;
int GameListX=55;
int GameListY=343;
int HDMode=0;
int vSpace=20;
int SoftwareFilter=1;
int HardwareFilter=2;
int vsyncEnabled=1;
int dimColor=1;
int pixelRatio=0;
int FlickerFilter=0;
int Soften=0;
int scrollSpeed=2;
int GameOptionPosX=470;
int GameOptionPosY=110;
float FontSize=1;
int GameListCount=6;
int DefaultController=0;
int MenuSpacing=401;
int MenuPosY=110;
int MenuPosX=320;
int MenuDetailPosX=74;
int MenuDetailPosY=82;
int ROMPosY=470;
float zLeftMenu=-2.899998;
float zRightMenu=2.809998;
float zTopMenu=-0.620000;
float zBottomMenu=0.580000;
float zLeftPreview=-1.290000;
float zRightPreview=-9.990133;
float zTopPreview=-1.749999;
float zBottomPreview=7.000066;
float zLeftPreviewBorder=-1.290000;
float zRightPreviewBorder=-9.990133;
float zTopPreviewBorder=-1.749999;
float zBottomPreviewBorder=7.000066;
float zLeftPreviewVertical=-1.290000;
float zRightPreviewVertical=-9.990133;
float zTopPreviewVertical=-1.749999;
float zBottomPreviewVertical=7.000066;
float zLeftPreviewBorderVertical=-1.290000;
float zRightPreviewBorderVertical=-9.990133;
float zTopPreviewBorderVertical=-1.749999;
float zBottomPreviewBorderVertical=7.000066;
float zLeftInfoBorder=-1.290000;
float zRightInfoBorder=-9.990133;
float zTopInfoBorder=-1.749999;
float zBottomInfoBorder=7.000066;
float zLeftInfoBorderSimple=-1.290000;
float zRightInfoBorderSimple=-9.990133;
float zTopInfoBorderSimple=-1.749999;
float zBottomInfoBorderSimple=7.000066;
float zLeftVideoBorder=-1.290000;
float zRightVideoBorder=-9.990133;
float zTopVideoBorder=-1.749999;
float zBottomVideoBorder=7.000066;
float zLeftDualVideoBorder=-1.290000;
float zRightDualVideoBorder=-9.990133;
float zTopDualVideoBorder=-1.749999;
float zBottomDualVideoBorder=7.000066;
float zLeftROMBorder=-1.290000;
float zRightROMBorder=-9.990133;
float zTopROMBorder=-1.749999;
float zBottomROMBorder=7.000066;
float zLeftSelectBorder=-1.290000;
float zRightSelectBorder=-9.990133;
float zTopSelectBorder=-1.749999;
float zBottomSelectBorder=7.000066;
float zLeftAlternatePreview=-1.290000;
float zRightAlternatePreview=-9.990133;
float zTopAlternatePreview=-1.749999;
float zBottomAlternatePreview=7.000066;
float zLeftAlternatePreviewBorder=-1.290000;
float zRightAlternatePreviewBorder=-9.990133;
float zTopAlternatePreviewBorder=-1.749999;
float zBottomAlternatePreviewBorder=7.000066;
float zLeftAlternatePreviewVertical=-1.290000;
float zRightAlternatePreviewVertical=-9.990133;
float zTopAlternatePreviewVertical=-1.749999;
float zBottomAlternatePreviewVertical=7.000066;
float zLeftAlternatePreviewBorderVertical=-1.290000;
float zRightAlternatePreviewBorderVertical=-9.990133;
float zTopAlternatePreviewBorderVertical=-1.749999;
float zBottomAlternatePreviewBorderVertical=7.000066;
float zLeftAnimatedLogo=-1.290000;
float zRightAnimatedLogo=-9.990133;
float zTopAnimatedLogo=-1.749999;
float zBottomAnimatedLogo=7.000066;
float zLeftAnimatedLogoTemp=-1.290000;
float zRightAnimatedLogoTemp=-9.990133;
float zTopAnimatedLogoTemp=-1.749999;
float zBottomAnimatedLogoTemp=7.000066;
int GameInfoPosX=337;
int GameInfoPosY=263;
float GameInfoFontSize=1;
int GameInfoVSpace=21;
int GameInfoDetailNumLines=10;
int GameInfoDetailPosX=337;
int GameInfoDetailPosY=263;
float GameInfoDetailFontSize=1;
int GameInfoDetailWidth=200;
int GameInfoDetailVSpace=21;
float zLeftExitGame=0.350000;
float zRightExitGame=-10.370142;
float zTopExitGame=-4.760014;
float zBottomExitGame=5.270026;
int zoomSpeed=25;
int GameGuideLines = 22;
int GameGuideColor = 0;
float GameGuideFontSize = 1;
int guideLeft = 50;
int GameGuideWidth = 590;
int GameGuideVSpace = 20;
int gameInfoListWidth = 200;
bool fade = false;
int fadeColor = 0;
int fadeSpeed = 17;
int fadeOption = 0;
int CustomSelected  = 0;
int CompanySelected = 0;
int YearSelected = 0;
int GenreSelected = 0;
int CustomSet = 0;
int CompanySet = 0;
int YearSet = 0;
int GenreSet = 0;
int GameInfoEnabled = 1;
int GameInfoDetailEnabled = 1;
int disableMenuSounds = 0;
int turboSpeed  = 7;
int BackgroundMusicVolume = DSBVOLUME_MAX;
std::vector<string> MainMenuItems;
float speedLogoMainMenu = 0.0095;
float distanceLogoMainMenu = 0.3;
float cMoveLogoMainMenu = 0;
float lMoveLogoMainMenu = -1 * distanceLogoMainMenu;
float rMoveLogoMainMenu = distanceLogoMainMenu;
float tMoveLogoMainMenu = distanceLogoMainMenu;
float bMoveLogoMainMenu = -1 * distanceLogoMainMenu;
float lastTimeLogoMainMenu = 0;
LARGE_INTEGER ticksPerSecondLogoMainMenu;
LARGE_INTEGER tickLogoMainMenu;
LARGE_INTEGER timeLogoMainMenu;
int MainMenuPosY=110;
int MainMenuPosX=320;
int MainMenuVSpace=20;
float MainMenuFontSize=1;
int MainMenuCentered=0;
float zLeftAnimatedLogoMainMenu=-1.290000;
float zRightAnimatedLogoMainMenu=-9.990133;
float zTopAnimatedLogoMainMenu=-1.749999;
float zBottomAnimatedLogoMainMenu=7.000066;
float zLeftAnimatedLogoMainMenuTemp=-1.290000;
float zRightAnimatedLogoMainMenuTemp=-9.990133;
float zTopAnimatedLogoMainMenuTemp=-1.749999;
float zBottomAnimatedLogoMainMenuTemp=7.000066;
struct Button  {
	std::string name;
	unsigned int code;
	int ControllerButton;
};

struct Controller {
	std::vector <Button> buttons;
};

Controller controllers[4];
int CommandLineLaunch = 0;
bool AlternatePreviewVerticalResize = false;
bool AlternatePreviewBorderVerticalResize = false;
bool PreviewVerticalResize = false;
bool PreviewBorderVerticalResize = false;
bool PreviewResize = false;
bool PreviewBorderResize = false;
bool AlternatePreviewResize = false;
bool AlternatePreviewBorderResize = false;
bool GameInfoDetailResize = false;
bool GameInfoResize = false;
bool VideoResize = false;
bool DualVideoResize = false;
bool DualVideoBorderResize = false;
int CursorSpeed = 7;
int ScrollSpeed = 30;
int ScrollSpeedCount = 0;
unsigned int SourceWidth = 0;
unsigned int SourceHeight = 0;
struct Macro {
	bool enabled;
	int buttonSet;
	std::vector<int> buttons;
	std::string desc;
};
std::vector<Macro> MacroSet[4];
int MacroSelected = 0;
int MacroModSelected = 0;
int SkinSelected = 0;
vector<string> Skin;
bool FPS = false;
unsigned char* _2xSaiBuffer = NULL;
void (*renderMethod[10])() = {NULL};
float zLeft0 = 1;
float zRight0 = 1;
float zTop0 = 1;
float zBottom0 = 1;
float zLeft90 = 1;
float zRight90 = 1;
float zTop90 = 1;
float zBottom90 = 1;
float zLeft180 = 1;
float zRight180 = 1;
float zTop180 = 1;
float zBottom180 = 1;
float zLeft270 = 1;
float zRight270 = 1;
float zTop270 = 1;
float zBottom270 = 1;
float zLeftMainMenuOverlay1 = 1;
float zRightMainMenuOverlay1 = 1;
float zTopMainMenuOverlay1 = 1;
float zBottomMainMenuOverlay1 = 1;
float zLeftMainMenuOverlay2 = 1;
float zRightMainMenuOverlay2 = 1;
float zTopMainMenuOverlay2 = 1;
float zBottomMainMenuOverlay2 = 1;
float zLeftMainMenuOverlay3 = 1;
float zRightMainMenuOverlay3 = 1;
float zTopMainMenuOverlay3 = 1;
float zBottomMainMenuOverlay3 = 1;
float zLeftMainMenuOverlay4 = 1;
float zRightMainMenuOverlay4 = 1;
float zTopMainMenuOverlay4 = 1;
float zBottomMainMenuOverlay4 = 1;
float zLeftMainMenuOverlay5 = 1;
float zRightMainMenuOverlay5 = 1;
float zTopMainMenuOverlay5 = 1;
float zBottomMainMenuOverlay5 = 1;
float zLeftMainMenuOverlay6 = 1;
float zRightMainMenuOverlay6 = 1;
float zTopMainMenuOverlay6 = 1;
float zBottomMainMenuOverlay6 = 1;
int OptionGUIImageSelectedPage3 = 0;
int screenSaverTime = 3;
int HiScoreSaving = 1;
unsigned char CPS1Difficulty = 0; //0 - 7
unsigned char CPS1FreePlay = 1; //1 or 0
int DisplayMode = 2;
int MovieEnabled = 1;
bool SetDips = true;
struct DIPItem {
	string description;
	vector<string> valueDescription;
	vector<unsigned char> value;
	vector<int> enabled;
	vector<unsigned char> mask;
};

struct DIPSetting {
	int dipID;
	unsigned char value;
	vector<DIPItem> dipItems;
};

vector<DIPSetting> arcradeSettings;

struct DipSwitchSetting {
		string description;
		string value;
};

vector <DipSwitchSetting> DipSwitchSettings;
int DipSwitchSelected = 0;
int DipEnabled = 1;
unsigned short CPUSpeed = 0x0100;
int GeneralOptionsSelected = 0;
vector<string> GeneralOptionsSettings;
vector<string> GeneralOptionsValueSettings;