/*-----------------------------------------------------------------------------
FBA XBox port.

Ported from the windows version by TMaul and Lantus

CONTACT EMAIL: xboxfba@yahoo.co.uk

Thanks to the FBA team, the Mame team, Dave @ finalburn.com and the zlib team for 
making this port possible.

Tiny parts of the video code and menu code were taken from Mame-x so credit to them 
for releasing the source.

This source is provided for educational perposes only. No warranty is offered,
implied or given. If this breaks something then its noones fault but your own.
Remember to be careful.

Remember: Compiling this source without appropriate licenses is illegal.

-----------------------------------------------------------------------------*/
#include "fba.h"
 
//state defines
#define GAMESELECT 1
#define CONFIGSCREEN 2
#define EMULATING 3
#define STRETCH 4
#define CONFIGSCREENMAPPINGS 5

static int controlmode=0;
static int firemode=0;

struct VERTEX { D3DXVECTOR4 p; D3DCOLOR vbColor; FLOAT tu, tv; };

static int nRedAdjust = 0xFF;
static int nGreenAdjust = 0xFF;
static int nBlueAdjust = 0xFF;
static int nAlphaAdjust = 0xFF;
static int LastPos=0;

static int nLogoAlpha = 0x9F;

CRoms m_Roms;
CConfiguration m_Config;
SScreenScale d3dScale;
static DWORD dwVertexColor;

 
int bStretchMode = 0;
int isPAL50=0;
int nPause=0;
int bDecreasing=0;

// Rom List Movement 

float fGameSelect;
float fCursorPos;
float fMaxCount;
float m_fFrameTime;			// amount of time per frame

int   iGameSelect;
int   iCursorPos;
int   iNumGames;

int   m_iMaxWindowList;
int   m_iWindowMiddle;

const int GAMESEL_MaxWindowList = 11;		 
const int GAMESEL_WindowMiddle = 5;	
const float GAMESEL_cfDeadZone = 0.3f;
const float GAMESEL_cfMaxThresh = 0.93f;
const float GAMESEL_cfMaxPossible = 1.0f;
const float GAMESEL_cfRectifyScale = GAMESEL_cfMaxPossible/(GAMESEL_cfMaxPossible-GAMESEL_cfDeadZone);
const float GAMESEL_cfSpeedBandFastest = 2.0f;	// seconds (don`t worry for PAL NTSC dif xbapp handles that)
const float GAMESEL_cfFastestScrollMult = 6.0f;
const float GAMESEL_cfSpeedBandMedium = 1.0f;	// if the pad is held at max for given seconds list will move faster
const float GAMESEL_cfMediumScrollMult = 5.0f;
const float GAMESEL_cfSpeedBandLowest = 0.5f;
const float GAMESEL_cfLowestScrollMult = 2.0f;	 
 

//-----------------------------------------------------------------------------
// Name: class CXBoxSample
// Desc: Main class to run this application. Most functionality is inherited
//       from the CXBApplication base class.
//-----------------------------------------------------------------------------

CXBFont     m_Font;                 // Font for text display
LPDIRECT3DTEXTURE8	pBackgroundTexture;
LPDIRECT3DVERTEXBUFFER8 pVB;


class CXBoxSample : public CXBApplication
{
    
public:

    HRESULT Initialize();       // Initialize the sample
    HRESULT Render();           // Render the scene
    HRESULT FrameMove();        // Perform per-frame updates
	int FBAState;
    CXBoxSample();
	HRESULT DrawLogo();
	HRESULT LoadingRomMsg();

	LPDIRECT3DTEXTURE8      m_pBackgroundTexture;
	CXBPackedResource       m_xprResource;
	LPDIRECT3DVERTEXBUFFER8 m_pVB;

private:
	void MoveCursor();
	CIoSupport m_IOSupport;

};




//-----------------------------------------------------------------------------
// Name: main()
// Desc: Entry point to the program.
//-----------------------------------------------------------------------------
VOID __cdecl main()
{
    CXBoxSample xbApp;
    if( FAILED( xbApp.Create() ) )
        return;
    xbApp.Run();
	BurnLibExit();
}




//-----------------------------------------------------------------------------
// Name: CXBoxSample (constructor)
// Desc: Constructor for CXBoxSample class
//-----------------------------------------------------------------------------
CXBoxSample::CXBoxSample() 
            :CXBApplication()
{

		//check for pal60 mode
	if(XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I)
	{
		//get supported video flags
		DWORD videoFlags = XGetVideoFlags();
		
		//set pal60 if available.
		if(videoFlags & XC_VIDEO_FLAGS_PAL_60Hz)
			m_d3dpp.FullScreen_RefreshRateInHz = 60;
		else
		{
			m_d3dpp.FullScreen_RefreshRateInHz = 50;
			isPAL50 = 1;
		}
	}

	{
	m_d3dpp.BackBufferWidth        = 640;
	m_d3dpp.BackBufferHeight       = 480;
	m_d3dpp.BackBufferFormat       = D3DFMT_A8R8G8B8;
	m_d3dpp.BackBufferCount        = 1;
	m_d3dpp.EnableAutoDepthStencil = TRUE;
	m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
	m_d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
	}

	nScrnWidth=m_d3dpp.BackBufferWidth;
	nScrnHeight=m_d3dpp.BackBufferHeight;


	fGameSelect = 0.0f;
	iGameSelect = 0;
	fCursorPos = 0.0f;
	iCursorPos = 0;
	fMaxCount = 0.0f;

	//set frame time
	m_fFrameTime = 1.0f / m_d3dpp.FullScreen_RefreshRateInHz;
}




//-----------------------------------------------------------------------------
// Name: Initialize
// Desc: Performs initialization
//-----------------------------------------------------------------------------
HRESULT CXBoxSample::Initialize()
{
    // Create the font
    if( FAILED( m_Font.Create(m_pd3dDevice,"Font.xpr" ) ) )
        return XBAPPERR_MEDIANOTFOUND;
    // Create help
    
	if( FAILED( m_xprResource.Create(m_pd3dDevice,"Gamepad.xpr", 1 ) ) )
        return XBAPPERR_MEDIANOTFOUND;

	m_pBackgroundTexture = m_xprResource.GetTexture( 0UL );


    m_pd3dDevice->CreateVertexBuffer( 4*(6*sizeof(FLOAT) + sizeof(DWORD)), D3DUSAGE_WRITEONLY, 
                                      0L, D3DPOOL_DEFAULT, &m_pVB );


	memset (&d3dScale, 0, sizeof (d3dScale)); 

	// Mount F: just incase people have roms there

	m_IOSupport.Mount("F:","Harddisk0\\Partition6"); // F

	// Set some pointers
	pBackgroundTexture = m_pBackgroundTexture;
	pVB = m_pVB;

	bCheatsAllowed=false;
	BurnLibInit();
	nBurnDrvSelect=0; //The Punsiher (World)
	FBAState=GAMESELECT;

	ConfigAppLoad();
	m_Roms.RefreshRomList();

	iNumGames = m_Roms.m_vecAvailRomList.size();

	if (iNumGames < GAMESEL_MaxWindowList)
	{
		m_iMaxWindowList = iNumGames;
		m_iWindowMiddle  = iNumGames/2;
	}
	else
	{
		m_iMaxWindowList = GAMESEL_MaxWindowList;
		m_iWindowMiddle  = GAMESEL_WindowMiddle;
	}


    return S_OK;
}

//-----------------------------------------------------------------------------
// Name: FrameMove
// Desc: Performs per-frame updates
//-----------------------------------------------------------------------------

HRESULT CXBoxSample::FrameMove()
{ 
	static int upclip=0,downclip=0;
	if (FBAState==GAMESELECT){
		
		MoveCursor();

		if( m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
		{
		
			char currName[200];
			char c;
			int oCursorPos;
			int tmp;

			// default don`t clamp cursor
			bool bClampCursor = FALSE;

			oCursorPos = fCursorPos;
			tmp = fCursorPos;
							
			strcpy(currName, m_Roms.m_vecAvailRomList[fCursorPos+fGameSelect].c_str());

			c = currName[0];

			while((fGameSelect + tmp) < iNumGames - 1)
			{
				char name[200];
				char n;

				tmp ++;

				strcpy(name, m_Roms.m_vecAvailRomList[fGameSelect + tmp].c_str());
				
				n = name[0];
				
				if(n > c)
				{
					fCursorPos = tmp; //(iGameidx - oGameidx);

					if( fCursorPos > m_iWindowMiddle )
					{
						// clamp cursor position
						bClampCursor = TRUE;
				
						// advance gameselect
						if(fGameSelect == 0) fGameSelect += (fCursorPos - m_iWindowMiddle);
						else  fGameSelect += (fCursorPos - oCursorPos);

						// clamp game window range (high)
						if((fGameSelect + m_iMaxWindowList) > iNumGames)
						{						
							fCursorPos = oCursorPos + (fGameSelect - (iNumGames - m_iMaxWindowList));
							
							// clamp to end
							fGameSelect = iNumGames - m_iMaxWindowList;
					
							// advance cursor pos after all!
							bClampCursor = FALSE;
					
							// clamp cursor to end
							if(fCursorPos > m_iMaxWindowList-1)
							fCursorPos = m_iMaxWindowList-1;
						}
					}
					
				// check for cursor clamp
				if( bClampCursor )
				fCursorPos = m_iWindowMiddle;	
		
				break;
				}
			}

		}
		else if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT)
		{
			char currName[200];
			char c;
			int oCursorPos;
			int tmp;

			// default don`t clamp cursor
			bool bClampCursor = FALSE;

			oCursorPos = fCursorPos;
			tmp = fCursorPos;
			
			strcpy(currName, m_Roms.m_vecAvailRomList[fCursorPos+fGameSelect].c_str());
			
			c = currName[0];

			while(fGameSelect + tmp > 0)
			{
				char name[200];
				char n;

				tmp --;
		
				strcpy(name, m_Roms.m_vecAvailRomList[fGameSelect+tmp].c_str());

				n = name[0];
				
				if(n < c)
				{
					fCursorPos = tmp;

					if( fCursorPos < m_iWindowMiddle )
					{
						// clamp cursor position
						bClampCursor = TRUE;
				
						// backup window pos
						fGameSelect -= (oCursorPos - fCursorPos);
				
						// clamp game window range (low)
						if(fGameSelect < 0)
						{
							// clamp to start
							fGameSelect = 0;
					
							// backup cursor pos after all!
							bClampCursor = FALSE;
					
							// clamp cursor to end
							if( fCursorPos < 0 )
								fCursorPos = 0;
						}
					}
					
				// check for cursor clamp
				if( bClampCursor )
				fCursorPos = m_iWindowMiddle;	

				break;
				}

			}

		}
		else if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN)
		{
			// default don`t clamp cursor
			bool bClampCursor = FALSE;

				fCursorPos ++;

					if( fCursorPos > m_iWindowMiddle )
					{
						// clamp cursor position
						bClampCursor = TRUE;
				
						// advance gameselect
						if(fGameSelect == 0) fGameSelect += (fCursorPos - m_iWindowMiddle);
						else fGameSelect ++;
				
						// clamp game window range (high)
						// clamp game window range (high)
						if((fGameSelect + m_iMaxWindowList) > iNumGames)
						{

							// clamp to end
							fGameSelect = iNumGames - m_iMaxWindowList;
					
							// advance cursor pos after all!
							bClampCursor = FALSE;
					
							// clamp cursor to end
							if((fGameSelect + fCursorPos) >= iNumGames)
							fCursorPos = m_iMaxWindowList-1;
						}
					}
					
					// check for cursor clamp
					if( bClampCursor )
					fCursorPos = m_iWindowMiddle;	

					 

		}
		else if( m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_UP)
		{
			// default don`t clamp cursor
			bool bClampCursor = FALSE;

				fCursorPos --;
					if( fCursorPos < m_iWindowMiddle )
					{
						// clamp cursor position
						bClampCursor = TRUE;
				
						// backup window pos
						fGameSelect --;
				
						// clamp game window range (low)
						if(fGameSelect < 0)
						{
							// clamp to start
							fGameSelect = 0;
					
							// backup cursor pos after all!
							bClampCursor = FALSE;
					
							// clamp cursor to end
							if( fCursorPos < 0 )
								fCursorPos = 0;
						}
					}
					
					// check for cursor clamp
					if( bClampCursor )
					fCursorPos = m_iWindowMiddle;	

					 

		}
		if(m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_Y])
			{
			FBAState=CONFIGSCREEN;
			}
		if( nBurnDrvSelect >= m_Roms.m_vecAvailRomIndex.size() )
		    nBurnDrvSelect = m_Roms.m_vecAvailRomIndex.size()-1;
		if( nBurnDrvSelect < 0 )
		    nBurnDrvSelect = 0;
		if (m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_B])
			{
			m_Roms.RefreshRomList();
			}
		if( (m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_START)||(m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_A]))
			{
			// initalise emulation here and set emulating to true

				int entryselected = iGameSelect + iCursorPos;

				//LastPos=nBurnDrvSelect;
				LoadingRomMsg();

				if (!DrvInit(m_Roms.m_vecAvailRomIndex[entryselected]))
					{
					m_Roms.FreeRomList();
					FBAState=EMULATING;
					}
			}
		}
	else if (FBAState==EMULATING)
		{
		
			InputMake(true);	
			AudSoundCheck();		
			VidFrame();
		
			// Back + Start to exit emulation on gamepad
			// Rtrig + Start to exit emulation on XArcade stick
			// use wButtons instead of wPressedButtons for this

			if (m_Config.GetJoyType(0) != 2 && 
				m_Config.GetJoyType(1) != 2 &&
				m_Config.GetJoyType(2) != 2 && 
				m_Config.GetJoyType(3) != 2)	// Xbox gamepad
			{	
				if (m_DefaultGamepad.wButtons & XINPUT_GAMEPAD_BACK && m_DefaultGamepad.wButtons & XINPUT_GAMEPAD_START)
					FBAState=GAMESELECT;

			}
			else // XArcade
			{
				if (m_DefaultGamepad.wButtons & XINPUT_GAMEPAD_START && m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] > 0 )
					FBAState=GAMESELECT;
					
			}
			if (m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_A] && m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] > 0 )
			{
				bStretchMode = !bStretchMode;

			}
			if (FBAState==GAMESELECT)
			{
				DrvExit();
				m_Roms.RefreshRomList();
				nBurnDrvSelect=LastPos;
			}
		}
	else if (FBAState==CONFIGSCREEN)
		{
		if(m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_Y])
			{
			ConfigAppSave();
			FBAState=GAMESELECT;
			}

		if(m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_A])
			FBAState=CONFIGSCREENMAPPINGS;
			 

		if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN)
			{
				m_Config.m_nPlayerNumPos++;
			if (m_Config.m_nPlayerNumPos > 3)
				m_Config.m_nPlayerNumPos = 0;
			}

		if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_UP)
			{
				m_Config.m_nPlayerNumPos--;
			if (m_Config.m_nPlayerNumPos < 0)
				m_Config.m_nPlayerNumPos = 3;
			}

		if (m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
			{

			controlmode = m_Config.GetJoyType(m_Config.m_nPlayerNumPos);

			controlmode++;
			if (controlmode > 2)
				controlmode =0;
		
			m_Config.SetJoyType(m_Config.m_nPlayerNumPos,controlmode);		 	
		}

		if (m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT)
			{
			controlmode = m_Config.GetJoyType(m_Config.m_nPlayerNumPos);

			controlmode--;
			if (controlmode < 0)
				controlmode =2;

			m_Config.SetJoyType(m_Config.m_nPlayerNumPos,controlmode);		 	
				 
			}
			
		}
		else if (FBAState==CONFIGSCREENMAPPINGS)
		{
		if(m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_A])
			FBAState=CONFIGSCREEN;

		if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN)
			{
				m_Config.m_nButtonPos++;
			if (m_Config.m_nButtonPos > 5)
				m_Config.m_nButtonPos = 0;
			}

		if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_UP)
			{
				m_Config.m_nButtonPos--;
			if (m_Config.m_nButtonPos < 0)
				m_Config.m_nButtonPos = 5;
			}

		if (m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
			{

			firemode = m_Config.GetFireType(m_Config.m_nPlayerNumPos, m_Config.m_nButtonPos);

			firemode++;
			if (firemode > 7)
				firemode =0;
		
			m_Config.SetFireMapping(m_Config.m_nPlayerNumPos,m_Config.m_nButtonPos, m_Config.m_LookupMap[firemode]);		 	
		}

		if (m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT)
			{
			firemode = m_Config.GetFireType(m_Config.m_nPlayerNumPos, m_Config.m_nButtonPos);

			firemode--;
			if (firemode < 0)
				firemode = 7;

			m_Config.SetFireMapping(m_Config.m_nPlayerNumPos,m_Config.m_nButtonPos, m_Config.m_LookupMap[firemode]);
				 
			}
			
		}

    return S_OK;
}


HRESULT CXBoxSample::DrawLogo()
// draws the FBA logo / background screen + burn lib version
	{

		WCHAR      m_currentversion[30];  // current version number
		swprintf( m_currentversion, L"Burn V%d.%d.%d.%d\n", VER_MAJOR,VER_MINOR,VER_BETA,VER_ALPHA );
		//pring Current game selection 

		VERTEX* v;
		m_pVB->Lock( 0, 0, (BYTE**)&v, 0L );
		v[0].p = D3DXVECTOR4(   0 - 0.5f,   0 - 0.5f, 0, 0 ); v[0].vbColor = 0xFFFFFFFF; v[0].tu =   0; v[0].tv =   0;
		v[1].p = D3DXVECTOR4( 640 - 0.5f,   0 - 0.5f, 0, 0 ); v[1].vbColor = 0xFFFFFFFF; v[1].tu = 640; v[1].tv =   0;
		v[2].p = D3DXVECTOR4( 640 - 0.5f, 480 - 0.5f, 0, 0 ); v[2].vbColor = 0xFFFFFFFF; v[2].tu = 640; v[2].tv = 480;
		v[3].p = D3DXVECTOR4(   0 - 0.5f, 480 - 0.5f, 0, 0 ); v[3].vbColor = 0xFFFFFFFF; v[3].tu =   0; v[3].tv = 480;
		m_pVB->Unlock();


		m_pd3dDevice->SetTexture( 0, m_pBackgroundTexture );
		m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
		m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
		m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
		m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
		m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
		m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
		m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_DISABLE );
		m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
		m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU,  D3DTADDRESS_CLAMP );
		m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV,  D3DTADDRESS_CLAMP );
		m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,      TRUE );
		m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,    FALSE );
		m_pd3dDevice->SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_NONE );
		m_pd3dDevice->SetRenderState( D3DRS_FILLMODE,     D3DFILL_SOLID );
		m_pd3dDevice->SetRenderState( D3DRS_CULLMODE,     D3DCULL_CCW );
		m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
		m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
		m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
		m_pd3dDevice->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_TEX1|D3DFVF_DIFFUSE  );
		m_pd3dDevice->SetStreamSource( 0, m_pVB, 6*sizeof(FLOAT) + sizeof(DWORD) );
		m_pd3dDevice->DrawPrimitive( D3DPT_QUADLIST, 0, 1 );
		m_Font.Begin();
		m_Font.DrawText( 440, 460, 0xff000000, m_currentversion);
		m_Font.End();
		return S_OK;
	}

//-----------------------------------------------------------------------------
// Name: Render
// Desc: Renders the scene
//-----------------------------------------------------------------------------
HRESULT CXBoxSample::Render()
{
	 
	// Clear the zbuffer

 	if (FBAState==GAMESELECT){
		WCHAR      m_currentname[120];  // Game name written to a string
		WCHAR      m_numRoms[40];

		nPause++;

		if (nPause==2)
		{
			if (nLogoAlpha==0xFF)
			{
				nLogoAlpha-=0x0A;
				bDecreasing=1;
			}
			else if (nLogoAlpha==0x9F)
			{
				nLogoAlpha+=0x0A;
				bDecreasing=0;
			}
			
			if (bDecreasing)
				nLogoAlpha-=0x0A;
			else
				nLogoAlpha+=0x0A;

			nPause=0;
		}

		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,0x00000000, 1.0f, 0L );
		
		// printf Gamelist
		DrawLogo();

		m_Font.Begin();
	 	
		// draw game list entries

		int iGameidx;
		iGameSelect = fGameSelect;
		iCursorPos = fCursorPos;
		int iTempGameSel = iGameSelect;

		swprintf( m_numRoms, L"");
		swprintf( m_numRoms, L"[%d/%d Available Roms]", iNumGames, nBurnDrvCount );
		m_Font.DrawText(320, 430, 0x99343545, m_numRoms, XBFONT_CENTER_X);

		DWORD LogoColor = D3DCOLOR_ARGB(0xEE,0x34, 0x35 , 0x45);
		m_Font.DrawText(320, 25, LogoColor, L"Final Burn Alpha X Beta 2", XBFONT_CENTER_X);

		DWORD SelectionColor = D3DCOLOR_ARGB(nLogoAlpha,0xFF , 0x1C , 0x24);

		for (iGameidx=0; iGameidx<m_iMaxWindowList; iGameidx++)
		{
			 
			if (iNumGames == 0) 
				m_Font.DrawText(320, 202, 0xffFF0000, L"No Roms Found", XBFONT_CENTER_X);	 
			else
			{
 				swprintf( m_currentname, L"");
				swprintf( m_currentname, L"%S\n", m_Roms.m_vecAvailRomList[iTempGameSel++].c_str() );

				if (iGameidx==iCursorPos){
					m_Font.DrawText( 60, 195+(20*iGameidx), SelectionColor, m_currentname, XBFONT_TRUNCATED, 530);
				}
				else if (iGameidx==0 || iGameidx==m_iMaxWindowList - 1)
					m_Font.DrawText( 60, 195+(20*iGameidx), 0x33003471, m_currentname, XBFONT_TRUNCATED, 530);
				else if (iGameidx==1 || iGameidx==m_iMaxWindowList - 2)
					m_Font.DrawText( 60, 195+(20*iGameidx), 0x66003471, m_currentname, XBFONT_TRUNCATED, 530);
				else if (iGameidx==2 || iGameidx==m_iMaxWindowList - 3)
					m_Font.DrawText( 60, 195+(20*iGameidx), 0x99003471, m_currentname, XBFONT_TRUNCATED, 530);
				else if (iGameidx==3 || iGameidx==m_iMaxWindowList - 4)
					m_Font.DrawText( 60, 195+(20*iGameidx), 0xBB003471, m_currentname, XBFONT_TRUNCATED, 530);
				else
				{
					m_Font.DrawText( 60, 195+(20*iGameidx), 0xDD003471, m_currentname, XBFONT_TRUNCATED, 530);
				}
			}
		 
		}

		m_Font.End();

		}
	else if (FBAState==EMULATING)
		{
		VidRender();
#if _DEBUG
		m_Font.Begin();
		m_Font.DrawText( 300, 50, 0xffFF0000, m_strFrameRate );
		m_Font.End();
#endif
		}
	else if (FBAState==CONFIGSCREEN)
		{
			DrawLogo();
			m_Config.ShowPlayerGamepadType();

		}
	else if (FBAState==CONFIGSCREENMAPPINGS)
	{
		DrawLogo();
		m_Config.ShowPlayerMappings(m_Config.m_nPlayerNumPos);
	}

    m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
    return S_OK;
}


HRESULT CXBoxSample::LoadingRomMsg(void)
{

	// Render a nice Loading Message so users dont think FBA has crashed.

	char buff[120];

	WCHAR wcBuff[120];
	memset(buff, 0, 120);

	int nFadeShift = 0;

	if (m_Roms.m_vecAvailRomIndex[iGameSelect + iCursorPos])
	{
		nBurnDrvSelect = m_Roms.m_vecAvailRomIndex[iGameSelect + iCursorPos];
		sprintf(buff, "Loading %s", BurnDrvText(1));
	}
	else
		return S_OK;

	
	const char* cb = buff;
	
	mbsrtowcs(wcBuff, &cb, 120, NULL);
	
	while (nAlphaAdjust != 0)
	{
		g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,0x00000000, 1.0f, 0L );

		dwVertexColor = D3DCOLOR_ARGB(nAlphaAdjust,nRedAdjust, nBlueAdjust, nGreenAdjust);

		 		 
		VERTEX* v;
		pVB->Lock( 0, 0, (BYTE**)&v, 0L );
		v[0].p = D3DXVECTOR4(   0 - 0.5f,   0 - 0.5f, 0, 0 ); v[0].vbColor = dwVertexColor; v[0].tu =   0; v[0].tv =   0;
		v[1].p = D3DXVECTOR4( 640 - 0.5f,   0 - 0.5f, 0, 0 ); v[1].vbColor = dwVertexColor; v[1].tu = 640; v[1].tv =   0;
		v[2].p = D3DXVECTOR4( 640 - 0.5f, 480 - 0.5f, 0, 0 ); v[2].vbColor = dwVertexColor; v[2].tu = 640; v[2].tv = 480;
		v[3].p = D3DXVECTOR4(   0 - 0.5f, 480 - 0.5f, 0, 0 ); v[3].vbColor = dwVertexColor; v[3].tu =   0; v[3].tv = 480;
		pVB->Unlock();

		if (pBackgroundTexture)
		{
			g_pd3dDevice->SetTexture( 0, pBackgroundTexture );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
			g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_DISABLE );
			g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU,  D3DTADDRESS_CLAMP );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV,  D3DTADDRESS_CLAMP );
			g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,      TRUE );
			g_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,    FALSE );
			g_pd3dDevice->SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_NONE );
			g_pd3dDevice->SetRenderState( D3DRS_FILLMODE,     D3DFILL_SOLID );
			g_pd3dDevice->SetRenderState( D3DRS_CULLMODE,     D3DCULL_CCW );
			g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
			g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
			g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
			g_pd3dDevice->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_TEX1|D3DFVF_DIFFUSE  );
			g_pd3dDevice->SetStreamSource( 0, pVB, 6*sizeof(FLOAT) + sizeof(DWORD) );
			g_pd3dDevice->DrawPrimitive( D3DPT_QUADLIST, 0, 1 );
		}

		m_Font.DrawText(320, 200, 0xFAED1C24, L"Please Wait", XBFONT_RIGHT|XBFONT_CENTER_X);
		m_Font.DrawText(320, 220, 0xFAED1C24, wcBuff, XBFONT_RIGHT|XBFONT_CENTER_X);

		g_pd3dDevice->Present(0, 0, 0, 0);

		nAlphaAdjust -= 1;
		nFadeShift -= 1;

	}

	nAlphaAdjust = 0xFF;		// reset alpha channel back to normal
	return S_OK;
}


// check for move cursor and move accordingly (with clamp etc)
void CXBoxSample::MoveCursor()
{
	
	// get right trigger state (convert to float & scale to 0.0f - 1.0f)
	float fWindowVelocity = (float)(m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER])/256.0f;
	
	// subract in left trigger state (convert to float)
	fWindowVelocity -= (float)(m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER])/256.0f;

	//setup static locals
	static float fFastestThresh = m_d3dpp.FullScreen_RefreshRateInHz*GAMESEL_cfSpeedBandFastest;
	static float fMediumThresh = m_d3dpp.FullScreen_RefreshRateInHz*GAMESEL_cfSpeedBandMedium;
	static float fLowestThresh = m_d3dpp.FullScreen_RefreshRateInHz*GAMESEL_cfSpeedBandLowest;

	// do dead zone and gamma curve
	if(( fWindowVelocity  > -GAMESEL_cfDeadZone ) && ( fWindowVelocity < GAMESEL_cfDeadZone ))
	{
		// zero dead zone (for spring slack & noise)
		fWindowVelocity = 0.0f;
		fMaxCount = 0.0f;
	}
	else
	{
		//start at 0.0f after deadzone
		if( fWindowVelocity < 0.0f )
			//adjust for deadzone
			fWindowVelocity += GAMESEL_cfDeadZone;
		else
			//adjust for deadzone
			fWindowVelocity -= GAMESEL_cfDeadZone;

		//rescale to correct range
		fWindowVelocity *= GAMESEL_cfRectifyScale;

		//increase max held count (for speed up bands)
		if( fabs(fWindowVelocity) > GAMESEL_cfMaxThresh )
		{
			//increase count by frame time and clamp count (if necc.)
			if(fMaxCount += m_fFrameTime)
				fMaxCount = fFastestThresh;
		}

		//check for speed scale banding
		if( fMaxCount > fFastestThresh)
			fWindowVelocity *= GAMESEL_cfFastestScrollMult;
		else if( fMaxCount > fMediumThresh)
			fWindowVelocity *= GAMESEL_cfMediumScrollMult;
		else if( fMaxCount > fLowestThresh)
			fWindowVelocity *= GAMESEL_cfLowestScrollMult;
	}
	
	// default don`t clamp cursor
	bool bClampCursor = FALSE;
	
	// check if triggers pressed and move window
	fCursorPos += fWindowVelocity;
	if( fWindowVelocity > 0.0f )
	{
		if( fCursorPos > m_iWindowMiddle )
		{
			// clamp cursor position
			bClampCursor = TRUE;
			
			// advance gameselect
			fGameSelect += fWindowVelocity;
			
			// clamp game window range (high)
			if((fGameSelect + m_iMaxWindowList) > iNumGames)
			{
				// clamp to end
				fGameSelect = iNumGames - m_iMaxWindowList;
				
				// advance cursor pos after all!
				bClampCursor = FALSE;
				
				// clamp cursor to end
				if(fCursorPos > m_iMaxWindowList -1)
				fCursorPos = m_iMaxWindowList-1;
			}
		}

	}
	else if( fWindowVelocity < 0.0f )	// ok to do this! because of deadzone clamp
	{
		if( fCursorPos < m_iWindowMiddle )
		{
			// clamp cursor position
			bClampCursor = TRUE;
			
			// backup window pos
			fGameSelect += fWindowVelocity;
			
			// clamp game window range (low)
			if(fGameSelect < 0)
			{
				// clamp to start
				fGameSelect = 0;
				
				// backup cursor pos after all!
				bClampCursor = FALSE;
				
				// clamp cursor to end
				if( fCursorPos < 0 )
					fCursorPos = 0;
			}
		}
	}

	// check for cursor clamp
	if( bClampCursor )
		fCursorPos = m_iWindowMiddle;	

}
