//-----------------------------------------------------------------------------
// File: WMVCutScene.cpp
//
// Desc: This sample demonstrates how to play back WMV cut scenes using the
//       Direct3D overlay surface
//
// Hist: 10.10.01 - New for Novermber XDK
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#define DEBUG_KEYBOARD

#include <XBApp.h>
#include <XBFont.h>
#include <XBHelp.h>
#include <xgraphics.h>
#include <Dmusici.h>

#define XFONT_TRUETYPE
#include <xfont.h>

#include <assert.h>
#include <d3d8perf.h>
#include "SndXBOX.hxx"
#include <stdio.h>
#include <vector>
#include "zlib.h"
#include "unzip.h"
#include "debugclient.h"
#include "keyboard_api.h"

#include "bochs.h"

CDebugClient *g_debugClient ;

void bx_init_options ();

#ifdef __cplusplus
extern "C" {
#endif

int doscopy(int argc,char **argv) ;


char global_error_message[1024] ;

//SoundXBOX nothersound ;
//extern SoundXBOX nothersound ;

#ifdef __cplusplus
}
#endif

//WCHAR g_buf[1024];
// constants for controller dead zone / speed up banding etc.
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 = 3.0f;	// seconds (don`t worry for PAL NTSC dif xbapp handles that)
const float GAMESEL_cfFastestScrollMult = 10.0f;
const float GAMESEL_cfSpeedBandMedium = 2.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 = 1.0f;
const float GAMESEL_cfLowestScrollMult = 2.0f;


#define IN_GAME						0
#define IN_GAME_PAUSED				1
#define MAIN_MENU					2
#define INIT_SYSTEM					3
#define INIT_SYSTEM_SHOW_SCREEN     4

#define SOUND_1 0x01
#define SOUND_2 0x02
#define SOUND_3 0x04
#define SOUND_4 0x08
#define SOUND_5 0x10
#define SOUND_6 0x20

#define NAMES_PER_PAGE 25
#define MAX_RESIST 1000000.0


#define CONSOLE_MEMORY_SIZE 0x10000

unsigned char SCANGRID[256] = 
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x46, 0x48, 0xFF, 0xFF, 0xFF, 0x47, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0x4C, 0x11, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 
0x3A, 0x51, 0x52, 0x50, 0x4F, 0x62, 0x60, 0x63, 0x61, 0xFF, 0x4A, 0xFF, 0xFF, 0x4D, 0x4E, 0xFF, 
0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x67, 0x68, 0x69, 0xFF, 0xFF, 
0x5D, 0x55, 0x56, 0x57, 0x58, 0x5F, 0x59, 0x5A, 0x5B, 0x5C, 0x65, 0x53, 0x64, 0x54, 0x5E, 0x66, 
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0x12, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0x02, 0x10, 0x01, 0x0F, 0x13, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x40, 0x3C, 0x44, 0x3D, 0x3E, 
0x45, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x42, 0x43, 0x3B, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
} ;

byte keyboard_keystate[256] ;

//-----------------------------------------------------------------------------
// Callouts for labelling the gamepad on the help screen
//-----------------------------------------------------------------------------
XBHELP_CALLOUT g_HelpCallouts[] = 
{
    { XBHELP_BACK_BUTTON,  XBHELP_PLACEMENT_2, L"Display help" },
    { XBHELP_A_BUTTON,     XBHELP_PLACEMENT_1, L"Play video" },
    { XBHELP_B_BUTTON,     XBHELP_PLACEMENT_1, L"Stop playback" },
};

#define NUM_HELP_CALLOUTS ( sizeof( g_HelpCallouts ) / sizeof( g_HelpCallouts[0] ) )

SoundXBOX *g_sound ;
float     *g_apptime ;
UINT32    *g_numframes ;
D3DCOLOR  *g_palette ;
int       g_palchanged ;
DWORD     g_dwStartTime ;
DWORD     g_dwTimePaused ;
byte*				g_pBlitBuff ;
int					g_BuffPitch ;
int					g_slowdown ;

LPDIRECT3DTEXTURE8	g_Texture;
UINT32 g_theWidth;
UINT32 g_theHeight;
XFONT*      m_pConsoleTTF;    // Pointer to the Arial TrueTypeFont
D3DPalette			*m_pd3dPalette ;

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

    virtual HRESULT Initialize();
    virtual HRESULT InitializeWithScreen();
    virtual HRESULT Render();
    virtual HRESULT FrameMove();
	virtual void MoveCursor() ;
	virtual void    initConsole( UINT32 idx) ;
	virtual void    cleanupConsole( ) ;
	virtual void    handleEvents() ;
	virtual int     init_texture() ;
	virtual int		init_white_texture();
	virtual int		render_to_texture() ;
	virtual void	FindAvailRoms() ;
	virtual void    doStartSearchMenu() ;
	virtual void    doCodeListMenu() ;
	virtual void    doAddFoundCodes() ;
	virtual void    doContinueSearchMenu() ;
	virtual void    doCheatMenu() ;
	virtual void    doFontSize() ;
	virtual void    doSaveConfig() ;
	virtual void    doScreenSize() ;
	virtual void    doTextOffset() ;
	virtual void    doConfiguration() ;
	virtual void    updateCheats() ;
	virtual void    processEmu( BOOL render ) ;
	virtual void    cht_load() ;
	virtual void    cht_save() ;
	virtual void    deleteSaveFiles( int which ) ;
	virtual void    doEditCode( int which ) ;
	virtual BOOL    hasFiles( int which ) ;
	virtual int     rom_load_zip() ;
	virtual void    QuickSort( int start, int end ) ;
	void			MenuBar( int xpos, int ypos, int xlen, int ylen ) ;
	void			keyEvent( byte key, int updown) ;
	


	
	
	IDirectMusicSegment8 *m_pSegment;
	IDirectMusicPerformance8 *m_pPerf;
	IDirectMusicLoader8 *m_pLoader;
	
	
	float fGameSelect;
	float fCursorPos;
	float m_fFrameTime ;
	float fMaxCount;
	int   iGameSelect;
	int   iCursorPos;
	UINT32 m_numFrames ;


	UINT32 topIdx  ;
	UINT32 curr  ;
	CDebugClient m_debugClient ;

    CXBFont     m_Font;             // Font object
    CXBFont     m_FontSmall;             // Font object
    CXBHelp     m_Help;             // Help object
    BOOL        m_bDrawHelp;        // TRUE to draw help screen

    LPDIRECTSOUND8      m_pDSound;      // DirectSound object
    DWORD               m_dwCurrent;    // Current surface

	byte *m_memBuf1, *m_memBuf2, *m_consoleMemory, *m_memMatches ;
	UINT32 m_currentMemMatches ;

	typedef struct _filenamestruct {
		WCHAR name[200] ;
		unsigned char filename[200] ;
		byte tagged ;
	} FILENAME ;

	FILENAME *files ;
	unsigned long numfiles ;
	UINT32   m_iMaxWindowList;
	UINT32   m_iWindowMiddle ;
	UINT32   m_steps ;
	DWORD    m_dwStartPause ;
	int		m_nbytes ;
	int		m_nXOffset, m_nFontHeight ;
	int		m_namesPerPage ;
	CXBSocket m_sockListener ;
	CDebugClient m_sockKeyboard;

	LPDIRECT3DTEXTURE8	Texture;
	LPDIRECT3DTEXTURE8	WhiteTexture;
	LPD3DXSPRITE			Sprite;
	LPD3DXSPRITE			MenuSprite;
	byte*				g_pAlignBuff ;
	int					m_droppedFrames ;	
	
	UINT32				m_state ;
    WCHAR      m_strMessage[80];
	UINT32              m_msgDelay ;

	int					m_nScreenX, m_nScreenY, m_nScreenMaxX, m_nScreenMaxY ;

	SoundXBOX			m_sound;
	char				g_savePath[500] ;
	char				g_saveprefix[500] ;
	char				g_sramfile[500] ;
	char				g_statefile[500] ;
	char				g_chtfile[500] ;

// Indicates the width and height of the screen
	UINT32 theWidth;
	UINT32 theHeight;
    RECT SrcRect;
    RECT DestRect;

	typedef struct _cheat_code {
		char code[20] ;
		UINT32 adr ;
		UINT32 val ;
		byte   enabled ;
	} CHEAT_CODE;

	CHEAT_CODE *m_cheatCodes;

	UINT32 m_numCheats ;


};


CXBoxSample *g_app ;

//-----------------------------------------------------------------------------
// Name: main()
// Desc: Entry point to the program.
//-----------------------------------------------------------------------------
VOID __cdecl main()
{
	g_debugClient = NULL ;

    CXBoxSample xbApp;

	g_app = &xbApp ;

	//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)
			xbApp.m_d3dpp.FullScreen_RefreshRateInHz = 60 ;
		else
			xbApp.m_d3dpp.FullScreen_RefreshRateInHz = 50 ;
	}
	else
		xbApp.m_d3dpp.FullScreen_RefreshRateInHz = 60 ;

    if( FAILED( xbApp.Create() ) )
        return;
    xbApp.Run();
}



//-----------------------------------------------------------------------------
// Name: CXBoxSample (constructor)
// Desc: Constructor for CXBoxSample class
//-----------------------------------------------------------------------------
CXBoxSample::CXBoxSample() 
            :CXBApplication()
{
    m_bDrawHelp = FALSE;
	m_state = MAIN_MENU ;
	files = NULL ;
	global_error_message[0] = 0 ;
	g_sound = &m_sound ;
	g_apptime = &m_fAppTime ;
	g_numframes = &m_numFrames ;
}



int CXBoxSample::init_texture()
{


	//m_debugClient.Send( "init textur1\r\n", 14 ) ;
	
	//theWidth = 320+16 ;
	//theHeight = 240+16 ;

	//m_debugClient.Send( "init textur2\r\n", 14 ) ;
	
	//theWidth = 320+16 ;
	//theHeight = 224+16 ;
	//m_mdBitmap.bpp = 16 ;
	//m_mdBitmap.w = 320+16 ;
	//m_mdBitmap.h = 224+16 ;

	// Release any previous texture
	if (Texture) 
	{ 
		Texture->Release();
		Texture = NULL;
	}
	//m_debugClient.Send( "init textur3\r\n", 14 ) ;
	
	// Create the texture
	D3DXCreateTexture(m_pd3dDevice, VBE_DISPI_MAX_XRES, VBE_DISPI_MAX_YRES, 0, 0, D3DFMT_P8, D3DPOOL_DEFAULT, &Texture);
	//D3DXCreateTexture(m_pd3dDevice, theWidth, theHeight, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &Texture);
//	D3DXCreateTexture(m_pd3dDevice, theWidth, theHeight, 0, 0, D3DFMT_LIN_A8R8G8B8, D3DPOOL_DEFAULT, &Texture);
	//m_debugClient.Send( "init textur4\r\n", 14 ) ;
	
	D3DSURFACE_DESC desc;
    Texture->GetLevelDesc(0, &desc);

	g_Texture = Texture ;

	//m_debugClient.Send( "init textur5\r\n", 14 ) ;

	if (g_pBlitBuff != NULL)
	{
	//m_debugClient.Send( "init texturz\r\n", 14 ) ;
		delete [] g_pBlitBuff;
		g_pBlitBuff = NULL;
	//m_debugClient.Send( "init textury\r\n", 14 ) ;
	}
	
	//m_debugClient.Send( "init texturx\r\n", 14 ) ;
	// Allocate a buffer to blit our frames to
	g_pBlitBuff = new byte[desc.Size];
	//m_debugClient.Send( "init texturw\r\n", 14 ) ;

/*
	if (g_pAlignBuff != NULL)
	{
		delete [] g_pAlignBuff;
		g_pAlignBuff = NULL;
	}
	
	// Allocate a buffer to blit our frames to
	g_pAlignBuff = new byte[desc.Size];
*/
	
	RECT rectSource;
	rectSource.top = 0;
	rectSource.left = 0;
	rectSource.bottom = theHeight-1 ;
	rectSource.right  = theWidth-1 ;

	D3DLOCKED_RECT d3dlr;
	//m_debugClient.Send( "init textur9\r\n", 14 ) ;
	//Texture->LockRect(0, &d3dlr, &rectSource, 0);

	//m_debugClient.Send( "init texturA\r\n", 14 ) ;

	// Unlock our texture
	//Texture->UnlockRect(0);

	//m_debugClient.Send( "init texturB\r\n", 14 ) ;

	D3DCOLOR *palette ;

	m_pd3dDevice->CreatePalette( D3DPALETTE_256 , &m_pd3dPalette ) ;
	
	m_pd3dPalette->Lock( &palette, 0 ) ;
	memset( palette, 0xFF, 256* sizeof( D3DCOLOR ) ) ;
	m_pd3dPalette->Unlock() ;

	m_pd3dDevice->SetPalette( 0, m_pd3dPalette ) ;

	//m_debugClient.Send( "init texturC\r\n", 14 ) ;

	return 0;
}

int CXBoxSample::init_white_texture()
{
	// Release any previous texture
	if (WhiteTexture) 
	{ 
		WhiteTexture->Release();
		WhiteTexture = NULL;
	}
	
	// Create the texture
	D3DXCreateTexture(m_pd3dDevice, 16, 16, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &WhiteTexture);
	
	D3DSURFACE_DESC desc;
    WhiteTexture->GetLevelDesc(0, &desc);


	RECT rectSource;
	rectSource.top = 0;
	rectSource.left = 0;
	rectSource.bottom = 15;
	rectSource.right  = 15 ;

	D3DLOCKED_RECT d3dlr;
	WhiteTexture->LockRect(0, &d3dlr, &rectSource, 0);

	memset( d3dlr.pBits, 0xFF, desc.Size ) ;

	// Unlock our texture
	WhiteTexture->UnlockRect(0);

	if ( MenuSprite == NULL )
		D3DXCreateSprite(m_pd3dDevice, &MenuSprite);

	return 0;
}


//-----------------------------------------------------------------------------
// Name: Initialize
// Desc: Peforms initialization
//-----------------------------------------------------------------------------
HRESULT CXBoxSample::Initialize()
{
    // Size of the Font Cache in Bytes
    DWORD dwFontCacheSize = 16 * 1024;

    // Create a font
    if( FAILED( m_Font.Create( m_pd3dDevice, "Font.xpr" ) ) )
        return XBAPPERR_MEDIANOTFOUND;

    // Create a font
    if( FAILED( m_FontSmall.Create( m_pd3dDevice, "Font12.xpr" ) ) )
        return XBAPPERR_MEDIANOTFOUND;

    // Create the Arial TrueTypeFont
    if( FAILED( XFONT_OpenTrueTypeFont( L"D:\\media\\fonts\\lucon.ttf",
                                        dwFontCacheSize,&m_pConsoleTTF ) ) )
        return XBAPPERR_MEDIANOTFOUND;


//SetObjectFromResource(CLSID_DirectMusicSegment, 101, "MIDI", "canyon");


	m_pConsoleTTF->SetTextHeight( 13 );

    // Change Font Style - XFONT_NORMAL, XFONT_BOLD, 
	//                     XFONT_ITALICS, XFONT_BOLDITALICS
	m_pConsoleTTF->SetTextStyle( XFONT_NORMAL );

    // Anti-Alias the font -- 0 for no anti-alias, 2 for some, 4 for MAX!
	m_pConsoleTTF->SetTextAntialiasLevel( 0 );
	m_pConsoleTTF->SetTextColor( 0xFFFFFFFF ) ;
	m_pConsoleTTF->SetBkColor( 0x00000000 ) ;


    // Create DirectSound
    if( FAILED( DirectSoundCreate( NULL, &(m_sound.dsound),  NULL ) ) )
        return E_FAIL;

	if ( ( XCreateSaveGame( "U:\\", L"BOCHSSAV", OPEN_ALWAYS, 0, g_savePath, 500 ) ) != ERROR_SUCCESS )
        return E_FAIL;

	m_sound.dsound_init() ;

	m_sound.m_fps = m_d3dpp.FullScreen_RefreshRateInHz ;

	m_state = INIT_SYSTEM ;


	return S_OK ;
}

HRESULT CXBoxSample::InitializeWithScreen()
{
	FILE *inifile ;
	char initext[100] ;
	char *fpos, *epos ;
	int numread ;

	m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
						 0x00000000, 1.0f, 0L );
	RenderGradientBackground( 0xFF000000, 0xFF000000 );
	m_Font.Begin();
	m_Font.DrawText( m_nXOffset+ 32, 16*2, 0xffffffff, L"Reading bochs directory...please wait." ) ;
	m_Font.End();
	m_pd3dDevice->Present( NULL, NULL, NULL, NULL );



	
	
	if ( m_sockKeyboard.Init( ) == 0 )
	{
	}

	//if ( m_debugClient.Connect( "192.168.123.99", 7654, 1 ) == 0 )
	//{
		//strcpy( global_error_message, "*debugclientinit" ) ;
		//return 0 ;
	//}

	g_debugClient = &m_debugClient ;


    m_sockListener.Open( CXBSocket::Type_TCP );
    CXBSockAddr directAddr( INADDR_ANY, 8989 );
    INT iResult = m_sockListener.Bind( directAddr.GetPtr() );

	if ( iResult == SOCKET_ERROR )
	{
		return 0;
	}

    iResult = m_sockListener.Listen( 1 ) ;

	if ( iResult == SOCKET_ERROR )
	{
		return 0;
	}

	DWORD dwNonBlocking = 1 ;
	iResult = m_sockListener.IoCtlSocket( FIONBIO, &dwNonBlocking );



	/*
	m_debugClient.WaitKey() ;

    IDirectMusicHeap* pNormalHeap;
    DirectMusicCreateDefaultHeap( &pNormalHeap );

    IDirectMusicHeap* pPhysicalHeap;
    DirectMusicCreateDefaultPhysicalHeap( &pPhysicalHeap );

    DirectMusicInitializeEx( pNormalHeap, pPhysicalHeap, &DirectMusicDefaultFactory  );

    pNormalHeap->Release();
    pPhysicalHeap->Release();

	if (FAILED(DirectMusicCreateInstance(
        CLSID_DirectMusicPerformance,
        NULL,
        IID_IDirectMusicPerformance8,
        (void**)&m_pPerf
    )))
	{
	    m_pPerf = NULL;
	}

	m_debugClient.WaitKey() ;

	if (SUCCEEDED(m_pPerf->InitAudioX(DMUS_APATH_SHARED_STEREOPLUSREVERB, 16, 0, 0)))
	{
	    // Performance initialized.
	}

	m_debugClient.WaitKey() ;

	if (FAILED(DirectMusicCreateInstance(
        CLSID_DirectMusicLoader,
        NULL,
        IID_IDirectMusicLoader8,
        (void**)&m_pLoader
    )))
	{
	    m_pLoader = NULL;
	}

	m_debugClient.WaitKey() ;

    m_pLoader->SetSearchDirectory( GUID_DirectMusicAllTypes, 
                                   "D:\\media\\sounds", FALSE );

	HRESULT hr = m_pLoader->LoadObjectFromFile(
				CLSID_DirectMusicSegment,
				IID_IDirectMusicSegment8,
				"canyon.mid",
				(void**) &m_pSegment);

	if ( hr != S_OK )
	{
		switch (hr)
		{
		case E_FAIL : m_debugClient.Send( "fail\r\n", 6 ) ; break ;
		case E_INVALIDARG : m_debugClient.Send( "iarg\r\n", 6 ) ; break ;
		case E_OUTOFMEMORY : m_debugClient.Send( "memo\r\n", 6 ) ; break ;
		case E_POINTER : m_debugClient.Send( "poin\r\n", 6 ) ; break ;
		case DMUS_E_LOADER_FAILEDCREATE : m_debugClient.Send( "failcr\r\n", 8 ) ; break ;
		default : m_debugClient.Send( "other\r\n", 7 ) ; break ;
		}
		m_debugClient.WaitKey() ;
	}

	m_debugClient.WaitKey() ;

	m_pPerf->PlaySegmentEx(m_pSegment, NULL, NULL, 0, 0, NULL, NULL, NULL);

	m_debugClient.WaitKey() ;
*/
	fGameSelect = 0.0f;
	iGameSelect = 0;
	fCursorPos = 0.0f;
	iCursorPos = 0;
	fMaxCount = 0.0f;
	curr = 0 ;
	topIdx = 0 ;
	numfiles = 0 ;

	int *iparams[6] ;

	m_nXOffset = 0 ;
	m_nFontHeight = 12 ;
	m_nScreenX = 50 ;
	m_nScreenY = 50 ;
	m_nScreenMaxX = 600 ;
	m_nScreenMaxY = 400 ;

	iparams[0] = &m_nXOffset ;
	iparams[1] = &m_nFontHeight ;
	iparams[2] = &m_nScreenX ;
	iparams[3] = &m_nScreenY ;
	iparams[4] = &m_nScreenMaxX ;
	iparams[5] = &m_nScreenMaxY ;

	int paramnum ;
	paramnum =0 ;

	inifile = fopen( "D:\\bochs.ini", "r" ) ;

	if ( inifile != NULL )
	{
		numread = fread( initext, sizeof(char), 100, inifile ) ;
		fclose( inifile ) ;

		fpos = initext ;

		while ( ( paramnum < 6 ) && ( ( epos = strchr( fpos, ' ' ) ) != NULL )  )
		{
			*epos = 0 ;

			*iparams[paramnum] = atoi( fpos ) ;

			fpos = epos + 1 ;

			if ( fpos - initext > 99 )
				break ;
			paramnum++ ;
		}

	}

	if ( m_nFontHeight < 1 )
		m_nFontHeight = 12 ;


	m_namesPerPage =  (25*14 ) / ( m_nFontHeight+2) ;


	m_msgDelay = 0 ;
	wcscpy( m_strMessage, L" " ) ;
	
	g_pBlitBuff = NULL ;
	g_pAlignBuff = NULL ;
	WhiteTexture = NULL ;
	Texture = NULL ;
	Sprite = NULL ;
	MenuSprite = NULL ;
	m_cheatCodes = NULL ;
	m_numCheats = 0 ;

	init_white_texture();

	g_saveprefix[0] = 0 ;

	FindAvailRoms() ;


	m_memBuf1 = (byte*)malloc( CONSOLE_MEMORY_SIZE ) ;
	m_memBuf2 = (byte*)malloc( CONSOLE_MEMORY_SIZE ) ;
	m_memMatches = (byte*)malloc( CONSOLE_MEMORY_SIZE ) ;
	m_consoleMemory = NULL ;

	g_palette = (D3DCOLOR*)malloc( sizeof(D3DCOLOR) * 256 ) ;


//BEGIN ONE TIME
	g_slowdown = 0 ;

	//m_debugClient.Send( "init texture\r\n", 14 ) ;


	// Create our texture
	init_texture();

	//m_debugClient.Send( "init texture2\r\n", 15 ) ;
	// Create our sprite driver
	if ( Sprite == NULL )
		D3DXCreateSprite(m_pd3dDevice, &Sprite);


  init_siminterface ();
	//m_debugClient.Send( "init2\r\n", 7 ) ;
  bx_control_panel (BX_CPANEL_INIT);
	//m_debugClient.Send( "init3\r\n", 7 ) ;
  bx_init_options ();
	//m_debugClient.Send( "init4\r\n", 7 ) ;
    SIM->set_enabled (0);
	//m_debugClient.Send( "init5\r\n", 7 ) ;
      bx_read_configuration ("d:\\bochsxbox");
	//m_debugClient.Send( "init6\r\n", 7 ) ;

	//BX_VGA_THIS set_update_interval( 200000 ) ;
	//bx_options.Oips->set (1500000) ;

  bx_init_hardware();
  if (bx_options.load32bitOSImage.OwhichOS->get ()) {
    void bx_load32bitOSimagehack(void);
    bx_load32bitOSimagehack();
    }
	//m_debugClient.Send( "init7\r\n", 7 ) ;

  SIM->set_init_done (1);
	//m_debugClient.Send( "init8\r\n", 7 ) ;
  bx_options.Omouse_enabled->set (bx_options.Omouse_enabled->get ());

	//m_debugClient.Send( "init9\r\n", 7 ) ;

	theHeight = BX_VGA_THIS s.vbe_yres; 
	theWidth = BX_VGA_THIS s.vbe_xres;

  if(bx_options.keyboard.OuseMapping->get()) {
    bx_keymap.loadKeymap(NULL);  // I have no function to convert X windows symbols
    }

	bx_devices.vga->set_update_interval( 200000 ) ;


//END ONE TIME	
	
	
	m_state = MAIN_MENU ;

    return S_OK;
}


void CXBoxSample::doSaveConfig()
{
	FILE *inifile ;

	inifile = fopen( "D:\\bochs.ini", "wb" ) ;

	if ( inifile != NULL )
	{
		fprintf( inifile, "%u %u %u %u %u %u  \r\n", m_nXOffset, m_nFontHeight, m_nScreenX, m_nScreenY, m_nScreenMaxX, m_nScreenMaxY ) ;
		fclose( inifile ) ;
	}

}


void CXBoxSample::doStartSearchMenu()
{

	memcpy( m_memBuf1, m_consoleMemory, CONSOLE_MEMORY_SIZE ) ;
	memset( m_memMatches, 1, CONSOLE_MEMORY_SIZE ) ;
	m_currentMemMatches = CONSOLE_MEMORY_SIZE ;

	while ( 1 )
	{
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+ 32, 16*2, 0xffffffff, L"The search has begun.  " );
		m_Font.DrawText(  m_nXOffset+32, 16*4, 0xffffffff, L"Press B to go back to the Options menu." );
		m_Font.End();

		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

        XBInput_GetInput();
		if ( g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_B ] ) 
		{
			break ;
		}
	}
}

void CXBoxSample::doEditCode( int which )
{
	CHEAT_CODE code ;
	int curr_pos ;
	int val1, val2 ;

	if ( which < 0 )
	{
		strcpy( code.code, "01000000" ) ;
		code.enabled = 1 ;
		code.adr = 0x0000 ;
		code.val = 0 ;
	}
	else
	{
		memcpy( &code, &(m_cheatCodes[which]), sizeof(CHEAT_CODE) ) ;
	}


	curr_pos = 0 ;

	while ( 1 )
	{
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		m_Font.Begin();

		if ( which < 0 )
			m_Font.DrawText(m_nXOffset+  32, 16*2, 0xffffffff, L"Add New Cheat Code" );
		else
			m_Font.DrawText( m_nXOffset+ 32, 16*2, 0xffffffff, L"Edit Cheat Code" );

		m_Font.DrawText( m_nXOffset+ 32, 16*4, 0xffffffff, L"Press B to cancel." );
		m_Font.DrawText( m_nXOffset+ 32, 16*5, 0xffffffff, L"Press A to save." );
		m_Font.DrawText( m_nXOffset+ 32, 16*6, 0xffffffff, L"Use DPAD to select/change values." );

		WCHAR str[200];

		for ( int i = 0 ; i < 8 ; i++ )
		{
			swprintf( str, L"%c", (code.code)[i] ) ;
			if ( i == curr_pos+2 )
				m_Font.DrawText( m_nXOffset+  50 + ( i * 16 ), 16*9, 0xff00ff00, str ) ;
			else
				m_Font.DrawText( m_nXOffset+  50 + ( i * 16 ), 16*9, 0xffffffff, str ) ;
		}

		swprintf( str, L"Address : %04.4X", code.adr ) ;
		m_Font.DrawText( m_nXOffset+  50 , 16*11, 0xffffffff, str ) ;
		swprintf( str, L"Value : %u", code.val ) ;
		m_Font.DrawText( m_nXOffset+  50 , 16*12, 0xffffffff, str ) ;
		
		m_Font.End();

		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

        XBInput_GetInput();
		if ( g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_B ] ) 
		{
			break ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_A ] ) 
		{
			if ( ( code.adr > 0xFFFF ) )
			{
				while ( 1 )
				{
					m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
										 0x00000000, 1.0f, 0L );
					RenderGradientBackground( 0xFF000000, 0xFF000000 );

					m_Font.Begin();
					m_Font.DrawText( m_nXOffset+  32, 16*2, 0xffffffff, L"The Address must be between 0x0000 and 0x7FFF" );
					m_Font.DrawText( m_nXOffset+  32, 16*4, 0xffffffff, L"Press B to try again." );
					m_Font.End();

					m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

					XBInput_GetInput();
					if ( g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_B ] ) 
					{
						break ;
					}
				}
			}
			else
			{
				if ( which < 0 )
				{
					m_cheatCodes = (CHEAT_CODE*)realloc( m_cheatCodes, sizeof(CHEAT_CODE) * ( m_numCheats  + 1 ) ) ;
					memcpy( &(m_cheatCodes[m_numCheats]),&code, sizeof(CHEAT_CODE) ) ;
					m_numCheats++ ;
				}
				else
				{
					memcpy( &(m_cheatCodes[which]), &code, sizeof(CHEAT_CODE) ) ;
				}
				break ;
			}
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN ) 
		{
			switch ( curr_pos )
			{
				case 0 :
				{
					if ( ( ( code.val >> 4 ) &  0x0F ) == 0 )
						code.val = 0xF0 + ( code.val & 0x0F ) ;
					else
						code.val = ( code.val - 0x10 ) & 0xFF ;
					break ;
				}
				case 1 :
				{
					if ( ( code.val & 0x0F ) == 0x00 )
						code.val = 0x0F + ( code.val & 0xF0 ) ;
					else
						code.val = ( code.val - 0x01 ) & 0xFF ;
					break ;
				}
				case 2 :
				{
					if ( ( ( code.adr >> 4 ) &  0x0F ) == 0 )
						code.adr = 0xF0 + ( code.adr & 0xFF0F ) ;
					else
						code.adr = ( code.adr - 0x10 ) & 0xFFFF ;
					break ;
				}
				case 3 :
				{
					if ( ( ( code.adr ) &  0x0F ) == 0 )
						code.adr = 0x0F + ( code.adr & 0xFFF0 ) ;
					else
						code.adr = ( code.adr - 0x01 ) & 0xFFFF ;
					break ;
				}
				case 4 :
				{
					if ( ( ( code.adr >> 12 ) &  0x0F ) == 0 )
						code.adr = 0xF000 + ( code.adr & 0x0FFF ) ;
					else
						code.adr = ( code.adr - 0x1000 ) & 0xFFFF ;
					break ;
				}
				case 5 :
				{
					if ( ( ( code.adr >> 8 ) &  0x0F ) == 0 )
						code.adr = 0x0F00 + ( code.adr & 0xF0FF ) ;
					else
						code.adr = ( code.adr - 0x100 ) & 0xFFFF ;
					break ;
				}
				default : break ;
			}
			sprintf( code.code, "01%02.2X%02.2X%02.2X", code.val, code.adr & 0xFF, (code.adr >> 8 ) & 0xFF ) ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_UP ) 
		{
			switch ( curr_pos )
			{
				case 0 :
				{
					if ( ( ( code.val >> 4 ) &  0x0F ) == 0x0F )
						code.val = 0x00 + ( code.val & 0x0F ) ;
					else
						code.val = ( code.val + 0x10 ) & 0xFF ;
					break ;
				}
				case 1 :
				{
					if ( ( code.val & 0x0F ) == 0x0F )
						code.val = 0x00 + ( code.val & 0xF0 ) ;
					else
						code.val = ( code.val + 0x01 ) & 0xFF ;
					break ;
				}
				case 2 :
				{
					if ( ( ( code.adr >> 4 ) &  0x0F ) == 0x0F )
						code.adr = 0x00 + ( code.adr & 0xFF0F ) ;
					else
						code.adr = ( code.adr + 0x10 ) & 0xFFFF ;
					break ;
				}
				case 3 :
				{
					if ( ( ( code.adr ) &  0x0F ) == 0x0F )
						code.adr = 0x00 + ( code.adr & 0xFFF0 ) ;
					else
						code.adr = ( code.adr + 0x01 ) & 0xFFFF ;
					break ;
				}
				case 4 :
				{
					if ( ( ( code.adr >> 12 ) &  0x0F ) == 0x0F )
						code.adr = 0x0000 + ( code.adr & 0x0FFF ) ;
					else
						code.adr = ( code.adr + 0x1000 ) & 0xFFFF ;
					break ;
				}
				case 5 :
				{
					if ( ( ( code.adr >> 8 ) &  0x0F ) == 0x0F )
						code.adr = 0x0000 + ( code.adr & 0xF0FF ) ;
					else
						code.adr = ( code.adr + 0x100 ) & 0xFFFF ;
					break ;
				}
				default : break ;
			}
			sprintf( code.code, "01%02.2X%02.2X%02.2X", code.val, code.adr & 0xFF, (code.adr >> 8 ) & 0xFF ) ;

		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT ) 
		{
			if ( curr_pos == 0 )
				curr_pos = 5 ;
			else
				curr_pos-- ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) 
		{
			if ( curr_pos == 5 )
				curr_pos = 0 ;
			else
				curr_pos++ ;
		}
	}


}

void CXBoxSample::doCodeListMenu()
{

	int selected  ;
	int cheatTopIdx ;
	WCHAR str[400];
	CHEAT_CODE *tempbuf ;

	selected = cheatTopIdx = 0 ;

	if ( m_numCheats == 0 )
	{
		while ( 1 )
		{
			m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
								 0x00000000, 1.0f, 0L );
			RenderGradientBackground( 0xFF000000, 0xFF000000 );

			m_Font.Begin();
			m_Font.DrawText( m_nXOffset+  32, 16*2, 0xffffffff, L"Search Code List" );
			m_Font.DrawText( m_nXOffset+  32, 16*4, 0xffffffff, L"Press B to go back to the Options menu." );
			m_Font.DrawText( m_nXOffset+  32, 16*6, 0xffffffff, L"There are no cheat codes in the list." ) ;

			m_Font.End();

			m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

			XBInput_GetInput();
			if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_B])
			{
				return ;
			}
		}
	}
	while ( 1 )
	{
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+  32, 16*2, 0xffffffff, L"Search Code List" );
		m_Font.DrawText( m_nXOffset+  32, 16*4, 0xffffffff, L"Press B to go back to the Options menu." );
		m_Font.DrawText( m_nXOffset+  32, 16*5, 0xffffffff, L"Press A to add a new code." );
		m_Font.DrawText( m_nXOffset+  32, 16*6, 0xffffffff, L"Press X to edit the selected code." );
		m_Font.DrawText( m_nXOffset+  32, 16*7, 0xffffffff, L"Press Y to enable/disable the selected code." );
		m_Font.DrawText( m_nXOffset+  32, 16*8, 0xffffffff, L"Press BLACK to delete the selected code." );
		m_Font.DrawText( m_nXOffset+  32, 16*9, 0xffffffff, L"Press UP/DOWN/LS/RS to select code." );

		MenuBar( m_nXOffset+32, 16*(11+selected) + 3, 600, 19 ) ;

		for ( unsigned int idx = cheatTopIdx ; ( idx < m_numCheats ) && ( idx < cheatTopIdx+10) ; idx++ )
		{
			CHEAT_CODE *code = &(m_cheatCodes[idx]) ;

			swprintf( str, L"%S Adr:0x%04.4X val:%u %S", code->code, code->adr, code->val, code->enabled ? "ON" : "OFF" ) ;
			
			if ( selected == idx )
				m_Font.DrawText( m_nXOffset+32, 16*(11+idx), 0xff000000, str );
			else
				m_Font.DrawText( m_nXOffset+32, 16*(11+idx), 0xffffffff, str );
		}
		
		m_Font.End();

		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

        XBInput_GetInput();
		if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_B])
		{
			break ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_A])
		{
			doEditCode( -1 ) ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_X])
		{
			doEditCode( selected ) ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_Y])
		{
			if ( m_cheatCodes[selected].enabled )
				m_cheatCodes[selected].enabled = 0 ;
			else
				m_cheatCodes[selected].enabled = 1 ;
		}
		else if (g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_BLACK]) 
		{
			tempbuf = (CHEAT_CODE*)malloc( sizeof(CHEAT_CODE) * ( m_numCheats - 1 ) ) ;

			memcpy( tempbuf, m_cheatCodes, sizeof(CHEAT_CODE) * selected ) ;

			if ( selected < m_numCheats-1 )
			{
				memcpy( &(tempbuf[selected]), &(m_cheatCodes[selected+1]), sizeof(CHEAT_CODE) * ( (m_numCheats - selected ) - 1) ) ;
			}

			free( m_cheatCodes ) ;

			m_cheatCodes = tempbuf ;
			m_numCheats-- ;
			if ( m_numCheats == 0 )
				break ;

			if ( selected >= (m_numCheats) )
				selected = m_numCheats - 1 ;

		}
		if (g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER])
		{
			if ( cheatTopIdx + 10 < m_numCheats )
			{
				cheatTopIdx += 10 ;
				selected = cheatTopIdx ;
			}
		}
		else if (g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER])
		{
			if ( cheatTopIdx >= 10 )
			{
				cheatTopIdx -= 10 ;
				selected = cheatTopIdx ;
			}
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN ) 
		{
			if ( selected == cheatTopIdx + (10-1) )
			{
				if ( selected < m_numCheats - 1 )
				{
					cheatTopIdx++ ;
					selected++ ;
				}
			}
			else
			{
				if ( selected < m_numCheats-1 )
					selected++ ;
			}
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_UP ) 
		{
			if ( selected == cheatTopIdx )
			{
				if ( selected > 0 )
				{
					cheatTopIdx-- ;
					selected-- ;
				}
			}
			else
			{
				if ( selected > 0 )
					selected-- ;
			}
		}

		
		
		
		
	}
}

void CXBoxSample::doAddFoundCodes()
{
	CHEAT_CODE code ;

	for ( int i = 0 ; i < CONSOLE_MEMORY_SIZE ; i++ )
	{
		if ( m_memMatches[i] )
		{
			code.adr = i ;
			code.val = m_memBuf1[i] ;
			code.enabled = 0 ;
			sprintf( code.code, "01%02.2X%02.2X%02.2X", code.val, code.adr & 0xFF, (code.adr >> 8 ) & 0xFF ) ;

			m_cheatCodes = (CHEAT_CODE*)realloc( m_cheatCodes, sizeof(CHEAT_CODE) * ( m_numCheats  + 1 ) ) ;

			memcpy( &(m_cheatCodes[m_numCheats]),&code, sizeof(CHEAT_CODE) ) ;
			m_numCheats++ ;

		}
	}

	memset( m_memMatches, 0, CONSOLE_MEMORY_SIZE ) ;
	m_currentMemMatches = 0 ;

	while ( 1 )
	{
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+  32, 16*2, 0xffffffff, L"The search found 1 to 4 possible matches for your search." );
		m_Font.DrawText( m_nXOffset+  32, 16*3, 0xffffffff, L"They have been added to your list." );
		m_Font.DrawText( m_nXOffset+  32, 16*5, 0xffffffff, L"Press B to go back to the Options menu." );
		m_Font.End();

		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

        XBInput_GetInput();
		if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_B])
		{
			break ;
		}
	}
}

void CXBoxSample::doContinueSearchMenu()
{

	WCHAR str[200];
	int value ;

	memcpy( m_memBuf2, m_consoleMemory, CONSOLE_MEMORY_SIZE ) ;
	value = 0 ;

	while ( 1 )
	{
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+  32, 16*2, 0xffffffff, L"Search Options" );
		m_Font.DrawText( m_nXOffset+  32, 16*4, 0xffffffff, L"Press B to go back to the Options menu." );

		swprintf( str, L"Press X to search for this value : %u", value );
		m_Font.DrawText( m_nXOffset+  32, 16*5, 0xffffffff, str );

		m_Font.DrawText( m_nXOffset+  32, 16*6, 0xffffffff, L"Press Y to search for values less than before." );
		m_Font.DrawText( m_nXOffset+  32, 16*7, 0xffffffff, L"Press A to search for values greater than before." );
		m_Font.DrawText( m_nXOffset+  32, 16*8, 0xffffffff, L"Press BLACK to search for values equal to before." );
		m_Font.DrawText( m_nXOffset+  32, 16*9, 0xffffffff, L"Press WHITE to search for values not equal to before." );
		m_Font.DrawText( m_nXOffset+  32, 16*10, 0xffffffff, L"Press DPAD-UP to add 1 to the value" ) ;
		m_Font.DrawText( m_nXOffset+  32, 16*11, 0xffffffff, L"Press DPAD-DOWN to subtract 1 from the value" ) ;
		m_Font.DrawText( m_nXOffset+  32, 16*12, 0xffffffff, L"Press DPAD-RIGHT to add 10 to the value" ) ;
		m_Font.DrawText( m_nXOffset+  32, 16*13, 0xffffffff, L"Press DPAD-LEFT to subtract 10 from the value" ) ;
		m_Font.DrawText( m_nXOffset+  32, 16*14, 0xffffffff, L"Press LS+RS to add the found codes to your list" ) ;

		swprintf( str, L"Number of hits from last search : %u", m_currentMemMatches );
		m_Font.DrawText( m_nXOffset+  32, 16*16, 0xffffffff, str );

		m_Font.End();

		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

        XBInput_GetInput();
		if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_B])
		{
			break ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_A])
		{
			m_currentMemMatches = 0 ;
			for ( int i = 0 ; i < CONSOLE_MEMORY_SIZE ; i++ )
			{
				if ( m_memMatches[i] )
					if ( m_memBuf1[i] < m_memBuf2[i] )
					{
						m_memMatches[i] = 1 ;
						m_currentMemMatches++ ;
					}
					else
						m_memMatches[i] = 0 ;
			}

			if ( m_currentMemMatches == 1 )
			{
				doAddFoundCodes() ;
				break ;
			}
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_X])
		{
			m_currentMemMatches = 0 ;
			for ( int i = 0 ; i < CONSOLE_MEMORY_SIZE ; i++ )
			{
				if ( m_memMatches[i] )
					if ( m_memBuf2[i] == value )
					{
						m_memMatches[i] = 1 ;
						m_currentMemMatches++ ;
					}
					else
						m_memMatches[i] = 0 ;
			}
			if ( m_currentMemMatches == 1 )
			{
				doAddFoundCodes() ;
				break ;
			}
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_Y])
		{
			m_currentMemMatches = 0 ;
			for ( int i = 0 ; i < CONSOLE_MEMORY_SIZE ; i++ )
			{
				if ( m_memMatches[i] )
					if ( m_memBuf1[i] > m_memBuf2[i] )
					{
						m_memMatches[i] = 1 ;
						m_currentMemMatches++ ;
					}
					else
						m_memMatches[i] = 0 ;
			}
			if ( m_currentMemMatches == 1 )
			{
				doAddFoundCodes() ;
				break ;
			}
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_BLACK])
		{
			m_currentMemMatches = 0 ;
			for ( int i = 0 ; i < CONSOLE_MEMORY_SIZE ; i++ )
			{
				if ( m_memMatches[i] )
					if ( m_memBuf1[i] == m_memBuf2[i] )
					{
						m_memMatches[i] = 1 ;
						m_currentMemMatches++ ;
					}
					else
						m_memMatches[i] = 0 ;
			}
			if ( m_currentMemMatches == 1 )
			{
				doAddFoundCodes() ;
				break ;
			}
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_WHITE])
		{
			m_currentMemMatches = 0 ;
			for ( int i = 0 ; i < CONSOLE_MEMORY_SIZE ; i++ )
			{
				if ( m_memMatches[i] )
					if ( m_memBuf1[i] != m_memBuf2[i] )
					{
						m_memMatches[i] = 1 ;
						m_currentMemMatches++ ;
					}
					else
						m_memMatches[i] = 0 ;
			}
			if ( m_currentMemMatches == 1 )
			{
				doAddFoundCodes() ;
				break ;
			}
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN ) 
		{
			value = ( value - 1 ) & 0xFF ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_UP ) 
		{
			value = ( value + 1 ) & 0xFF ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT ) 
		{
			value = ( value - 10 ) & 0xFF ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) 
		{
			value = ( value + 10  ) & 0xFF ;
		}
		else if ( (g_Gamepads[0].hDevice && g_Gamepads[0].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) && (g_Gamepads[0].hDevice && g_Gamepads[0].bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER]) )
		{
			if ( ( m_currentMemMatches > 0 ) && ( m_currentMemMatches < 5 ) )
			{
				doAddFoundCodes() ;
				break ;
			}
			else
			{
				while ( 1 )
				{
					m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
										 0x00000000, 1.0f, 0L );
					RenderGradientBackground( 0xFF000000, 0xFF000000 );

					m_Font.Begin();
					m_Font.DrawText( m_nXOffset+  32, 16*2, 0xffffffff, L"You can only add when you have narrowed " ) ;
					m_Font.DrawText( m_nXOffset+  32, 16*3, 0xffffffff, L"it down to less than 5 matches." );
					m_Font.DrawText( m_nXOffset+  32, 16*5, 0xffffffff, L"Press B to go back." );
					m_Font.End();

					m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

					XBInput_GetInput();
					if ( g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_B ] ) 
					{
						break ;
					}
				}
			}
		}
	}
	memcpy( m_memBuf1, m_memBuf2, CONSOLE_MEMORY_SIZE ) ;
}

void CXBoxSample::doCheatMenu()
{

	while ( 1 )
	{
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+  32, 16*2, 0xffffffff, L"OPTIONS MENU" );
		m_Font.DrawText( m_nXOffset+  32, 16*4, 0xffffffff, L"B - Return to Game" );
		m_Font.DrawText( m_nXOffset+  32, 16*5, 0xffffffff, L"START+BACK - Quit Game" );
		//m_Font.DrawText( m_nXOffset+  32, 16*6, 0xffffffff, L"BLACK - Start Search for Cheat Code" );
		//m_Font.DrawText( m_nXOffset+  32, 16*7, 0xffffffff, L"A - Continue Cheat Search" );
		//m_Font.DrawText( m_nXOffset+  32, 16*8, 0xffffffff, L"RS+LS - Cheat Code List" );


		m_Font.End();

		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

        XBInput_GetInput();
		if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_B])
		{
			m_sound.pause( FALSE ) ;
			m_state = IN_GAME ;
			break ;
		}
		else if ( ( g_Gamepads[0].hDevice && g_Gamepads[0].wButtons & XINPUT_GAMEPAD_START )  &&
			      ( g_Gamepads[0].hDevice && g_Gamepads[0].wButtons & XINPUT_GAMEPAD_BACK )  )
		{
			m_sound.cleanup() ;
			cleanupConsole() ;
			m_state = MAIN_MENU ;
			break ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_A])
		{
			//doContinueSearchMenu() ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_BLACK])
		{
			//doStartSearchMenu() ;
		}
		else if ( (g_Gamepads[0].hDevice && g_Gamepads[0].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) && (g_Gamepads[0].hDevice && g_Gamepads[0].bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER]) )
		{
			//doCodeListMenu() ;
		}


	}

}

void CXBoxSample::doConfiguration()
{

	int menuChoice = 0 ;

	while ( 1 )
	{
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		MenuBar( 32, 16*(6+menuChoice)+3, 600, 19 ) ;

		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+  32, 16*4, 0xffffffff, L"CONFIGURATION" );
		m_Font.DrawText( m_nXOffset+  32, 16*6, menuChoice==0 ? 0xff000000 : 0xffffffff, L"Set Game List Font Size" );
		m_Font.DrawText( m_nXOffset+  32, 16*7, menuChoice==1 ? 0xff000000 : 0xffffffff, L"Set Text Offset (push menu text to the right)" );
		m_Font.DrawText( m_nXOffset+  32, 16*8, menuChoice==2 ? 0xff000000 : 0xffffffff, L"Set Game Screen Size/Position" );
		m_Font.DrawText( m_nXOffset+  32, 16*10, 0xffffffff, L"Press B to go back" );
		m_Font.End();

		
		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

        XBInput_GetInput();
		if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_B])
		{
			break ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN )
		{
			menuChoice = (menuChoice+1)%3 ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_UP )
		{
			menuChoice = (menuChoice-1)%3 ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_A])
		{
			switch ( menuChoice )
			{
				case 0 : doFontSize() ; break ;
				case 1 : doTextOffset() ; break ;
				case 2 : doScreenSize() ; break ;
				default : break ;
			}
		}


	}

}

void CXBoxSample::doFontSize()
{
	WCHAR str[200];
	int value ;

	value = m_nFontHeight ;

	while ( 1 )
	{
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		swprintf( str, L"Use DPAD to adjust current value : %u", value ) ;

		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+  32, 16*4, 0xffffffff, L"Set Game List Font Size" );
		m_Font.DrawText( m_nXOffset+  32, 16*6, 0xffffffff, str) ;
		m_Font.DrawText( m_nXOffset+  32, 16*8, 0xffffffff, L"Press A to accept" );
		m_Font.DrawText( m_nXOffset+  32, 16*9, 0xffffffff, L"Press B to go back" );
		m_Font.End();

		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

        XBInput_GetInput();
		if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_B])
		{
			break ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN ) 
		{
			value = ( value - 1 ) & 0xFF ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_UP ) 
		{
			value = ( value + 1 ) & 0xFF ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT ) 
		{
			value = ( value - 10 ) & 0xFF ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) 
		{
			value = ( value + 10  ) & 0xFF ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_A])
		{
			m_nFontHeight = value ;
			m_namesPerPage =  (25*14 ) / ( m_nFontHeight+2) ;
			doSaveConfig() ;
			break ;
		}


	}

}

void CXBoxSample::doScreenSize()
{
	WCHAR str[200];
	int x, y, maxx, maxy ;
	float fx, fy, fmaxx, fmaxy ;

	x = m_nScreenX ;
	y = m_nScreenY ;
	maxx = m_nScreenMaxX;
	maxy = m_nScreenMaxY ;

	fx = x ;
	fy = y ;
	fmaxx = maxx ;
	fmaxy = maxy ;

	while ( 1 )
	{
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		x = fx ;
		y = fy ;
		maxx = fmaxx ;
		maxy = fmaxy ;
		MenuBar( x, y, maxx, maxy ) ;

		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+  132, 16*11, 0xff00ff00, L"Set Game Screen Size" );

		m_Font.DrawText( m_nXOffset+  132, 16*13, 0xff00ff00, L"Use RThumb and LThumb to adjust screen size/pos" );
		m_Font.DrawText( m_nXOffset+  132, 16*14, 0xff00ff00, L"Press A to accept" );
		m_Font.DrawText( m_nXOffset+  132, 16*15, 0xff00ff00, L"Press B to go back" );

		swprintf( str, L"X=%u Y=%u MAXX=%u MAXY=%u", x, y, maxx, maxy ) ;
		m_Font.DrawText( m_nXOffset+  132, 16*17, 0xff00ff00, str );

		m_Font.End();

		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

        XBInput_GetInput();
		if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_B])
		{
			break ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_A])
		{
			m_nScreenX = x ;
			m_nScreenY = y ;
			m_nScreenMaxX = maxx ;
			m_nScreenMaxY = maxy ;
			doSaveConfig() ;
			break ;
		}
		else
		{
			if ( g_Gamepads[0].hDevice )
			{
				fx += g_Gamepads[0].fX1 ;
				fy -= g_Gamepads[0].fY1 ;
				fmaxx += g_Gamepads[0].fX2 ;
				fmaxy -= g_Gamepads[0].fY2 ;
			}
		}
	}

}

void CXBoxSample::doTextOffset()
{
	WCHAR str[200];
	int value ;

	value = m_nXOffset ;

	while ( 1 )
	{
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		swprintf( str, L"Use DPAD to adjust current value : %u", value ) ;

		m_Font.Begin();
		m_Font.DrawText( value+  32, 16*4, 0xffffffff, L"Set Menu Text Offset" );
		m_Font.DrawText( value+  32, 16*6, 0xffffffff, str) ;
		m_Font.DrawText( value+  32, 16*8, 0xffffffff, L"Press A to accept" );
		m_Font.DrawText( value+  32, 16*9, 0xffffffff, L"Press B to go back" );
		m_Font.End();

		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

        XBInput_GetInput();
		if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_B])
		{
			break ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN ) 
		{
			value = ( value - 1 ) & 0xFF ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_UP ) 
		{
			value = ( value + 1 ) & 0xFF ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT ) 
		{
			value = ( value - 10 ) & 0xFF ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) 
		{
			value = ( value + 10  ) & 0xFF ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_A])
		{
			m_nXOffset = value ;
			break ;
		}


	}

}

//-----------------------------------------------------------------------------
// Name: FrameMove
// Desc: Performs per-frame updates
//-----------------------------------------------------------------------------
HRESULT CXBoxSample::FrameMove()
{

	m_bPaused =  ( m_state != IN_GAME ) ;

	if ( m_state == IN_GAME )
	{
		if ( m_dwStartPause > 0 )
		{
			g_dwTimePaused += ( GetTickCount() - m_dwStartPause ) ;
			m_dwStartPause = 0;
		}

		if ( (m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER]) && 
			 (m_DefaultGamepad.wButtons & XINPUT_GAMEPAD_BACK) )
		{
			m_sound.pause( TRUE ) ;
			m_state = IN_GAME_PAUSED ;
			m_dwStartPause = GetTickCount();
			return S_OK ;
		}
	}
	else if ( m_state == MAIN_MENU )
	{
		if(m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_Y])
		{
		}
		else if ( ( g_Gamepads[0].hDevice && g_Gamepads[0].wButtons & XINPUT_GAMEPAD_START )  &&
			      ( g_Gamepads[0].hDevice && g_Gamepads[0].wButtons & XINPUT_GAMEPAD_BACK )  &&
				  ( g_Gamepads[0].hDevice && g_Gamepads[0].bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER]) &&
				  ( g_Gamepads[0].hDevice && g_Gamepads[0].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) )
		{
			LD_LAUNCH_DASHBOARD LaunchData = { XLD_LAUNCH_DASHBOARD_MAIN_MENU };
			XLaunchNewImage( NULL, (LAUNCH_DATA*)&LaunchData );
		}
		else if ( ( g_Gamepads[0].hDevice && g_Gamepads[0].wButtons & XINPUT_GAMEPAD_LEFT_THUMB )  &&
			      ( g_Gamepads[0].hDevice && g_Gamepads[0].wButtons & XINPUT_GAMEPAD_RIGHT_THUMB )  )
		{
			LD_LAUNCH_DASHBOARD LaunchData = { XLD_LAUNCH_DASHBOARD_MAIN_MENU };

			FILE *xbefile ;

			xbefile = fopen( "D:\\default.xbe", "rb" ) ;
			if ( xbefile != NULL )
			{
				fclose(xbefile) ;
				XLaunchNewImage( "D:\\default.xbe", (LAUNCH_DATA*)&LaunchData );
			}
			else
				XLaunchNewImage( "D:\\bochs.xbe", (LAUNCH_DATA*)&LaunchData );
		}
		else if ( (m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_X]) && (m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_B]) )
		{
			m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
								 0x00000000, 1.0f, 0L );
			RenderGradientBackground( 0xFF000000, 0xFF000000 );
			m_Font.Begin();
			m_Font.DrawText( m_nXOffset+  32, 16*2, 0xffffffff, L"Reloading game list..." ) ;
			m_Font.End();
			m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

			if ( numfiles > 0 )
			{
				delete [] files;
				files = NULL;
			}

			numfiles = 0 ;
			FindAvailRoms() ;
		}
		else
		{
			// check for cursor select movement and move
			MoveCursor();

			// check for selection of game and do something (anything!)
			if(m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_A])
			{
				m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
									 0x00000000, 1.0f, 0L );
				RenderGradientBackground( 0xFF000000, 0xFF000000 );
				m_Font.Begin();
				m_Font.DrawText( m_nXOffset+  32, 16*2, 0xffffffff, L"Loading game...please wait." ) ;
				m_Font.End();
				m_pd3dDevice->Present( NULL, NULL, NULL, NULL );

				do
				{
					XBInput_GetInput();
				}
				while( g_Gamepads[0].hDevice && g_Gamepads[0].bAnalogButtons[ XINPUT_GAMEPAD_A] ) ;

		        XBInput_GetInput();
				initConsole(curr) ;
				m_state = IN_GAME ;
				return S_OK ;
			}
			else if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_LEFT_THUMB )
			{
				doConfiguration() ;
				return S_OK ;
			}
			else if(m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_B])
			{
				files[curr].tagged = !files[curr].tagged ;
			}
		}
	}
	else if ( m_state == IN_GAME_PAUSED )
	{
		m_sound.pause( TRUE ) ;
		m_bPaused =  TRUE ;
		doCheatMenu() ;

		return S_OK ;
	}
	else
	{
	}

    return S_OK;
}


int CXBoxSample::render_to_texture()
{
	RECT src, dst;
	byte *curr1, *curr2 ;
	D3DCOLOR *palette ;

	
	if ( g_palchanged )
	{
		//BX_INFO( ( "palupdate\r\n" ) ) ;
		m_pd3dDevice->GetPalette( 0, &m_pd3dPalette ) ;

		m_pd3dPalette->Lock( &palette, 0 ) ;
		memcpy( palette, g_palette, sizeof(D3DCOLOR)*256) ;
		m_pd3dPalette->Unlock() ;

		m_pd3dDevice->SetPalette( 0, m_pd3dPalette ) ;

		g_palchanged = 0 ;
	}

	// Get a description of our level 0 texture so we can figure
	// out the pitch of the texture
	D3DSURFACE_DESC desc;
    Texture->GetLevelDesc(0, &desc);
	
	
	// Allocate a buffer to blit our frames to

	// Figure out how big of a rect to lock in our texture
	RECT rectSource;
	rectSource.top = 0;
	rectSource.left = 0;
	rectSource.bottom = g_theHeight - 1;
	rectSource.right  = g_theWidth  - 1 ;
	//rectSource.top = 8;
	//rectSource.left = 8;
	//rectSource.bottom = (theHeight-1)+8 ;
	//rectSource.right  = (theWidth-1)+8 ;

	// Lock the rect in our texture
	D3DLOCKED_RECT d3dlr;
	Texture->LockRect(0, &d3dlr, &rectSource, 0);

	//FILE *tfile ;
	//tfile = fopen("d:\\bochscreen.raw", "wb") ;
	//fwrite( BX_VGA_THIS s.vbe_memory, BX_VGA_THIS s.vbe_yres * BX_VGA_THIS s.vbe_xres, 1, tfile) ;
	//fclose(tfile) ;
	
	//curr1 = BX_VGA_THIS s.vbe_memory ;
	//curr2 = g_pBlitBuff ;

	//for ( int y = 0 ; y < BX_VGA_THIS s.vbe_yres ; y++ )
	//{
		//curr1 = ((byte*)BX_VGA_THIS s.vbe_memory) + ( y*BX_VGA_THIS s.vbe_xres ) ;
		//curr2 = ((byte*)g_pBlitBuff) + ( y*d3dlr.Pitch ) ;
		//memcpy( curr2, curr1, BX_VGA_THIS s.vbe_xres ) ;
	//}

	
	// Swizzle the blittled surface back to the texture
	XGSwizzleRect(g_pBlitBuff, 0, NULL, d3dlr.pBits, desc.Width, desc.Height, NULL, 1);

	// Swizzle the blittled surface back to the texture
	//XGSwizzleRect(m_mdBitmap.data+16 + ( 8*m_mdBitmap.pitch ), 0, NULL, d3dlr.pBits, desc.Width, desc.Height, NULL, m_mdBitmap.bpp / 8 );

	// Unlock our texture
	Texture->UnlockRect(0);

	//delete [] g_pBlitBuff;
	//g_pBlitBuff = NULL;


	src.left   = 0;
	src.top    = 0;
	src.right  = theWidth  + 0;
	src.bottom = theHeight + 1;

	UINT iWidth  = theWidth;
	UINT iHeight = theHeight;
	
	// win_start_maximized the rect, constraining to the aspect ratio
	dst.left   = dst.top = 0;
	dst.right  = iWidth;
	dst.bottom = iHeight;
	
	// center
	//dst.left   += ((iWidth - (dst.right - dst.left)) / 2)  + ((640-iWidth)/2);
	//dst.top    += ((iHeight - (dst.bottom - dst.top)) / 2) + ((480-iHeight)/2);
	//dst.right  += dst.left;
	//dst.bottom += dst.top;
	
    // Clear the viewport
//	if ( ( m_DefaultGamepad.bAnalogButtons[ XINPUT_GAMEPAD_A ] ) || ( m_DefaultGamepad.bAnalogButtons[ XINPUT_GAMEPAD_X ] ) )  
	    g_pd3dDevice->Clear(0L, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0L);
	
	// Begin the Scene
	g_pd3dDevice->BeginScene();

	// Compute the source and dest image sizes
	const float dw = dst.right-dst.left;
	const float dh = dst.bottom-dst.top;
	const float sw = src.right-src.left;
	const float sh = src.bottom-src.top;
	float mx, my ;

	mx = (float)m_nScreenMaxX / (float)g_theWidth ;
	my = (float)m_nScreenMaxY / (float)g_theHeight ;

	// Compute the scale and transform vectors
	//D3DXVECTOR2 vecScale(dw/sw, dh/sh);
	D3DXVECTOR2 vecScale(mx, my);
	D3DXVECTOR2 vecTranslate(m_nScreenX, m_nScreenY );
	//D3DXVECTOR2 vecTranslate( ( 640.0f - ( (float)320.0f * ( mx ) ) )/2,
		                      //( 480.0f - ( (float)240.0f * ( my ) ) )/2 );
	//D3DXVECTOR2 vecTranslate(50, 50 );
	//D3DXVECTOR2 vecTranslate(dst.left, dst.top);
	
	D3DXCOLOR d3color(1.0, 1.0, 1.0, 1.0);
	
	// Draw the sprite
	//if ( ( m_DefaultGamepad.bAnalogButtons[ XINPUT_GAMEPAD_A ] ) || ( m_DefaultGamepad.bAnalogButtons[ XINPUT_GAMEPAD_Y ] ) )  
		Sprite->Draw(Texture, &rectSource, &vecScale, NULL, 0, &vecTranslate, d3color);
	
	// End the scene.
	g_pd3dDevice->EndScene();
	
	// Present the scene
	//if ( ( m_DefaultGamepad.bAnalogButtons[ XINPUT_GAMEPAD_A ] ) || ( m_DefaultGamepad.bAnalogButtons[ XINPUT_GAMEPAD_BLACK ] ) )  
		//g_pd3dDevice->Present(NULL, NULL, NULL, NULL);

	return 1;
}

void CXBoxSample::MenuBar( int xpos, int ypos, int xlen, int ylen )
{
	D3DXVECTOR2 vecScale( 1, 1 ) ;
	D3DXVECTOR2 vecTranslate( xpos, ypos ) ;
	D3DXCOLOR d3color(1.0, 1.0, 1.0, 1.0);
	RECT rectSource;

	rectSource.top = 0;
	rectSource.left = 0;
	rectSource.bottom = ylen - 1 ;
	rectSource.right  = xlen - 1;
	
	MenuSprite->Draw(WhiteTexture, &rectSource, &vecScale, NULL, 0, &vecTranslate, d3color);
}


//-----------------------------------------------------------------------------
// Name: Render
// Desc: Renders the scene
//-----------------------------------------------------------------------------
HRESULT CXBoxSample::Render()
{
	m_bPaused =  ( m_state != IN_GAME ) ;


	if ( m_state == IN_GAME )
	{
		//if ( m_dwStartPause > 0 )
		//{
			//g_dwTimePaused += ( GetTickCount() - m_dwStartPause ) ;
			//m_dwStartPause = 0;
		//}

		// Clear the zbuffer
		//m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 //0x00000000, 1.0f, 0L );

		// Draw a gradient filled background
		//RenderGradientBackground( 0xff404040, 0xff404080 );

		if ( global_error_message[0] != 0 )
		{
			WCHAR str[5000];

			m_Font.Begin();
			//swprintf( str, L"%S", global_error_message );
			//m_Font.DrawText( 32, 48, 0x40ffffff, str );
			m_Font.DrawText( m_nXOffset+ 32, 48, 0xffffffff, L"ERROR" );
			m_Font.End();
		}
		else
		{

			processEmu( TRUE ) ;

			if ( m_msgDelay > 0 )
			{
				m_msgDelay-- ;
				m_Font.Begin();
				m_Font.DrawText( m_nXOffset+  32, 32, 0xffffff00, m_strMessage );
				m_Font.End();
			}
			else
			{
				//float elapsedTime ;
				//m_Font.Begin();
				//WCHAR str[2000];
				//swprintf( str, L"width = %u, height = %u", io.screen_w, io.screen_h ) ;
				//elapsedTime = ( (float)GetTickCount() - (float)g_dwStartTime - (float)g_dwTimePaused ) / 1000.0f ;
				//swprintf( str, L"numbytes apptime %5.5f, sndbytes %u, avg %6.5f, fps %5.5f cfps %5.5f", elapsedTime, m_sound.m_totalBytesWritten, 
					//((float)m_sound.m_totalBytesWritten) / elapsedTime, m_fFPS, ((float)m_numFrames) / m_fAppTime );
				//m_Font.DrawText( 30, 320, 0xFFffffff, str );
				//m_Font.End();
			}
		}
		
		// Present the scene
		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
	}
	else if ( m_state == IN_GAME_PAUSED )
	{
	}
	else if ( m_state == MAIN_MENU )
	{
		// Clear the zbuffer
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
							 0x00000000, 1.0f, 0L );
		RenderGradientBackground( 0xFF000000, 0xFF000000 );

		if(m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_Y])
		{
			m_Font.Begin(); 
			m_Font.DrawText( m_nXOffset+32, 16*2,  0xffffffff, L"BOCHS for XBOX");
			m_Font.DrawText( m_nXOffset+32, 16*4,  0xffffffff, L"Main Menu Controls");
			m_Font.DrawText( m_nXOffset+32, 16*5,  0xffffffff, L"A - Start emulation");
			m_Font.DrawText( m_nXOffset+32, 16*6,  0xffffffff, L"B - Flag files to copy to HD");
			m_Font.DrawText( m_nXOffset+32, 16*7,  0xffffffff, L"Y - Show This Help Screen");
			m_Font.DrawText( m_nXOffset+32, 16*8,  0xffffffff, L"UP/DOWN - Select File");
			m_Font.DrawText( m_nXOffset+32, 16*9,  0xffffffff, L"RIGHT/LEFT - Next/Prev Page");
			m_Font.DrawText( m_nXOffset+32, 16*10,  0xffffffff, L"LS/RS - Next/Prev Letter");
			m_Font.DrawText( m_nXOffset+32, 16*11,  0xffffffff, L"START+BACK+LS+RS - Exit to dashboard");
			m_Font.DrawText( m_nXOffset+32, 16*12,  0xffffffff, L"X+B - Reload list");
			m_Font.DrawText( m_nXOffset+32, 16*13,  0xffffffff, L"LThumb - Configuration");

			m_Font.DrawText( m_nXOffset+32, 16*15, 0xffffffff, L"In-Emu Controls");
			m_Font.DrawText( m_nXOffset+32, 16*16, 0xffffffff, L"Configure the buttons in the xboxkey.map file");
			m_Font.DrawText( m_nXOffset+32, 16*17, 0xffffffff, L"LThumb - Move mouse");
			m_Font.DrawText( m_nXOffset+32, 16*18, 0xffffffff, L"RThumb - L/R = L/R Mouse Click");
			m_Font.DrawText( m_nXOffset+32, 16*19, 0xffffffff, L"RS+BACK - Options Menu");
			m_Font.End();
		}
		else if ( ( m_DefaultGamepad.bAnalogButtons[ XINPUT_GAMEPAD_BLACK ] ) &&
				  ( m_DefaultGamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ) &&
				  ( m_DefaultGamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ) )
		{
			m_Font.Begin(); 
			m_Font.DrawText( m_nXOffset+48, 32, 0xffffffff, L"BOCHS for XBOX - made by me");
			m_Font.End();
		}
		else if ( ( m_DefaultGamepad.bAnalogButtons[ XINPUT_GAMEPAD_BLACK ] ) &&
				  ( m_DefaultGamepad.bAnalogButtons[ XINPUT_GAMEPAD_WHITE ] ) )
		{
			//deleteSaveFiles( curr ) ;
		}
		else
		{
			WCHAR str[2000];
			swprintf( str, L"BOCHS for XBOX  Y-Help Screen  Found %u files", numfiles);

			m_Font.Begin(); 
			m_FontSmall.Begin(); 
			m_Font.DrawText( m_nXOffset+ 48, 32, 0xffffffff, str );
			//m_Font.DrawText(48, 32, 0x40ffffff, L"Gnuboy for XBOX  Y-Help Screen");


			
			
			float fWinX = 32, fWinY = 64;

			MenuBar( m_nXOffset+fWinX, fWinY+ (( m_nFontHeight+2)*(curr-topIdx)) + 3, 600, m_nFontHeight+3 ) ;

			for ( unsigned int idx = topIdx ; ( idx < numfiles ) && ( idx < topIdx+m_namesPerPage) ; idx++ )
			{
				if ( files[idx].tagged )
					swprintf( str, L"<*>%S", files[idx].filename);
				else
					swprintf( str, L"%S", files[idx].filename ) ;

				if ( curr == idx )
				{
					if ( hasFiles( idx ) )
						m_FontSmall.DrawText( m_nXOffset+fWinX  , fWinY, 0xffff00ff, str );
					else
						m_FontSmall.DrawText( m_nXOffset+fWinX , fWinY, 0xff000000, str);
				}
				else
				{
					if ( hasFiles( idx ) )
						m_FontSmall.DrawText( m_nXOffset+fWinX, fWinY, 0xff00ff00, str);
					else
						m_FontSmall.DrawText( m_nXOffset+fWinX, fWinY, 0xffffffff, str );
				}
				fWinY += (m_nFontHeight + 2);
			}
			

			// end font drawing
			m_Font.End();
			m_FontSmall.End();


		}

		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
	}
	else if ( m_state == INIT_SYSTEM )
	{
		InitializeWithScreen() ;
	}
	else if ( m_state == INIT_SYSTEM_SHOW_SCREEN )
	{
	}
	else
	{
	}



    return S_OK;
}

void CXBoxSample::keyEvent( byte key, int updown)
{
	if ( updown )
	{
		BXKeyEntry *entry = bx_keymap.getKeyASCII (key);
		if (entry)
		{
			if (entry->modKey != BX_KEYMAP_UNKNOWN)
				bx_devices.keyboard->gen_scancode(entry->modKey);

			bx_devices.keyboard->gen_scancode(entry->baseKey);
		}
	}
	else
	{
		BXKeyEntry *entry = bx_keymap.getKeyASCII (key);
		if (entry)
		{
			bx_devices.keyboard->gen_scancode(entry->baseKey | BX_KEY_RELEASED);

			if (entry->modKey != BX_KEYMAP_UNKNOWN)
				bx_devices.keyboard->gen_scancode(entry->modKey | BX_KEY_RELEASED);
		}
	}
}

/**
  This routine should be called regularly to handle events
*/
void g_handleevents()
{
	g_app->handleEvents() ;
}

void CXBoxSample::handleEvents()
{

	unsigned char keybuf[100] ;
	byte lookup ;
	int  numread ;
	SOCKET connection ;
	XINPUT_DEBUG_KEYSTROKE   keystroke ;
	static byte last_mouse_state = 0 ;
	byte curr_state[256] ;
	byte mouse_state ;


	if ( m_sockKeyboard.m_debugClientSock.m_Socket == INVALID_SOCKET )
	{
		if ( ( connection = m_sockListener.Accept( NULL ) ) != INVALID_SOCKET )
		{
			m_sockKeyboard.m_debugClientSock.m_Socket = connection ;
		}
	}

	if ( m_sockKeyboard.m_debugClientSock.m_Socket != INVALID_SOCKET )
	{
		while ( ( numread = m_sockKeyboard.Recv( keybuf, 1 ) ) > 0 )
		{
			bx_devices.keyboard->put_scancode( keybuf, 1 ) ;
			//bx_devices.keyboard->paste_bytes( keybuf, 1);

		}
	}


	while( ERROR_SUCCESS == XInputDebugGetKeystroke( &keystroke ) )
	{
		//sprintf((char*)keybuf, "gotkey %02.2X %02.2X %02.2X\r\n", keystroke.VirtualKey, keystroke.Ascii, keystroke.Flags) ;
		//m_debugClient.Send( keybuf, strlen((char*)keybuf) ) ;

		lookup = SCANGRID[keystroke.VirtualKey] -1 ;
		if ( lookup != 0xFE )
		{
			if ( keystroke.Flags & XINPUT_DEBUG_KEYSTROKE_FLAG_KEYUP )
			{
				bx_devices.keyboard->gen_scancode( lookup | BX_KEY_RELEASED);
				keyboard_keystate[lookup] = 0 ;
			}
			else
			{
				if ( keystroke.Flags & XINPUT_DEBUG_KEYSTROKE_FLAG_REPEAT )
				{
					if ( keyboard_keystate[lookup] == 1 )
					{
						bx_devices.keyboard->gen_scancode(lookup);
						keyboard_keystate[lookup] = 1 ;
					}
				}
				else
				{
					bx_devices.keyboard->gen_scancode(lookup);
					keyboard_keystate[lookup] = 1 ;
				}
			}
		}
	}


	//for ( int i = 0 ; i < 256 ; i++ )
	//{
		//if ( ( curr_state[i] == 0 ) && ( keyboard_keystate[i] == 1 ) )
		//{
			////bx_devices.keyboard->gen_scancode( i | BX_KEY_RELEASED);
		//}
	//}

	//memcpy( keyboard_keystate, curr_state, 256 ) ;

	if ( g_Gamepads[0].hDevice )
	{
		if ( g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT  ) 
		{
			keyEvent( '0',1 ) ;
		}
		if ( g_Gamepads[0].wReleasedButtons & XINPUT_GAMEPAD_DPAD_LEFT  ) 
		{
			keyEvent( '0',0 ) ;
		}

		if ( g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT  ) 
		{
			keyEvent( '1',1 ) ;
		}
		if ( g_Gamepads[0].wReleasedButtons & XINPUT_GAMEPAD_DPAD_RIGHT  ) 
		{
			keyEvent( '1',0 ) ;
		}

		if ( g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_UP  ) 
		{
			keyEvent( '2',1 ) ;
		}
		if ( g_Gamepads[0].wReleasedButtons & XINPUT_GAMEPAD_DPAD_UP  ) 
		{
			keyEvent( '2',0 ) ;
		}

		if ( g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN  ) 
		{
			keyEvent( '3',1 ) ;
		}
		if ( g_Gamepads[0].wReleasedButtons & XINPUT_GAMEPAD_DPAD_DOWN  ) 
		{
			keyEvent( '3',0 ) ;
		}

		if ( g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_A ] ) 
		{
			keyEvent( '4',1 ) ;
		}
		if ( g_Gamepads[0].bReleasedAnalogButtons[ XINPUT_GAMEPAD_A ] ) 
		{
			keyEvent( '4',0 ) ;
		}

		if ( g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_B ] ) 
		{
			keyEvent( '5',1 ) ;
		}
		if ( g_Gamepads[0].bReleasedAnalogButtons[ XINPUT_GAMEPAD_B ] ) 
		{
			keyEvent( '5',0 ) ;
		}

		if ( g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_X ] ) 
		{
			keyEvent( '6',1 ) ;
		}
		if ( g_Gamepads[0].bReleasedAnalogButtons[ XINPUT_GAMEPAD_X ] ) 
		{
			keyEvent( '6',0 ) ;
		}

		if ( g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_Y ] ) 
		{
			keyEvent( '7',1 ) ;
		}
		if ( g_Gamepads[0].bReleasedAnalogButtons[ XINPUT_GAMEPAD_Y ] ) 
		{
			keyEvent( '7',0 ) ;
		}

		if ( g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_BLACK ] ) 
		{
			keyEvent( '8',1 ) ;
		}
		if ( g_Gamepads[0].bReleasedAnalogButtons[ XINPUT_GAMEPAD_BLACK ] ) 
		{
			keyEvent( '8',0 ) ;
		}

		if ( g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_WHITE ] ) 
		{
			keyEvent( '9',1 ) ;
		}
		if ( g_Gamepads[0].bReleasedAnalogButtons[ XINPUT_GAMEPAD_WHITE ] ) 
		{
			keyEvent( '9',0 ) ;
		}

		if ( g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_START  ) 
		{
			keyEvent( 'a',1 ) ;
		}
		if ( g_Gamepads[0].wReleasedButtons & XINPUT_GAMEPAD_START  ) 
		{
			keyEvent( 'a',0 ) ;
		}

		if ( g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_BACK  ) 
		{
			keyEvent( 'b',1 ) ;
		}
		if ( g_Gamepads[0].wReleasedButtons & XINPUT_GAMEPAD_BACK  ) 
		{
			keyEvent( 'b',0 ) ;
		}

		if ( g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_LEFT_THUMB  ) 
		{
			keyEvent( 'e',1 ) ;
		}
		if ( g_Gamepads[0].wReleasedButtons & XINPUT_GAMEPAD_LEFT_THUMB  ) 
		{
			keyEvent( 'e',0 ) ;
		}

		if ( g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_RIGHT_THUMB  ) 
		{
			keyEvent( 'f',1 ) ;
		}
		if ( g_Gamepads[0].wReleasedButtons & XINPUT_GAMEPAD_RIGHT_THUMB  ) 
		{
			keyEvent( 'f',0 ) ;
		}

		if ( g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_LEFT_TRIGGER ] ) 
		{
			keyEvent( 'c',1 ) ;
			if ( g_slowdown == 0 )
				g_slowdown = 255 ;
			else
				g_slowdown-- ;

			//bx_pc_system.init_ips( 1000000 + ( 100000 * g_slowdown ) ) ;

		}
		if ( g_Gamepads[0].bReleasedAnalogButtons[ XINPUT_GAMEPAD_LEFT_TRIGGER ] ) 
		{
			keyEvent( 'c',0 ) ;
		}

		if ( g_Gamepads[0].bPressedAnalogButtons[ XINPUT_GAMEPAD_RIGHT_TRIGGER ] ) 
		{
			keyEvent( 'd',1 ) ;
			if ( g_slowdown == 255 )
				g_slowdown = 0 ;
			else
				g_slowdown++ ;
			//bx_pc_system.init_ips( 1000000 + ( 100000 * g_slowdown ) ) ;
		}
		if ( g_Gamepads[0].bReleasedAnalogButtons[ XINPUT_GAMEPAD_RIGHT_TRIGGER ] ) 
		{
			keyEvent( 'd',0 ) ;
		}


	
		mouse_state = ( ( g_Gamepads[0].fX2 < 0 ) ? 1 : 0 ) + ( ( g_Gamepads[0].fX2 > 0 ) ? 2 : 0);

		if ( ( g_Gamepads[0].fX1 != 0 ) || ( g_Gamepads[0].fY1 != 0 ) )
		{
			bx_devices.keyboard->mouse_motion( g_Gamepads[0].fX1 * 25, g_Gamepads[0].fY1 * 25, mouse_state ) ;
		}
		else if ( mouse_state != last_mouse_state )
		{
			bx_devices.keyboard->mouse_motion( 0, 0, mouse_state ) ;
		}

		last_mouse_state = mouse_state ;

	}

/*
	for ( int i = 0 ; i < 2 ; i++ )
	{
		megad->pad[i] = 0x000f303f; // 0x000f303f; = untouched pad  11110011000000111111
	//                                                              XXXX  XX      XXXXXX
	//                                                                    SA      CBRLDU

		if ( g_Gamepads[i].hDevice && g_Gamepads[i].bAnalogButtons[ XINPUT_GAMEPAD_A ] ) 
			megad->pad[i] &= PAD_A ;

		if ( g_Gamepads[i].hDevice && g_Gamepads[i].bAnalogButtons[ XINPUT_GAMEPAD_X ] ) 
			megad->pad[i] &= PAD_X ;

		if ( g_Gamepads[i].hDevice && g_Gamepads[i].bAnalogButtons[ XINPUT_GAMEPAD_B ] ) 
			megad->pad[i] &= PAD_B ;

		if ( g_Gamepads[i].hDevice && g_Gamepads[i].bAnalogButtons[ XINPUT_GAMEPAD_Y ] ) 
			megad->pad[i] &= PAD_Y ;

		if ( g_Gamepads[i].hDevice && g_Gamepads[i].wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) 
			megad->pad[i] &= PAD_LEFT ;

		if ( g_Gamepads[i].hDevice && g_Gamepads[i].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) 
			megad->pad[i] &= PAD_RIGHT ;

		if ( g_Gamepads[i].hDevice && g_Gamepads[i].wButtons & XINPUT_GAMEPAD_DPAD_UP ) 
			megad->pad[i] &= PAD_UP ;
		
		if ( g_Gamepads[i].hDevice && g_Gamepads[i].wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) 
			megad->pad[i] &= PAD_DOWN ;

		if ( g_Gamepads[i].hDevice && g_Gamepads[i].wButtons & XINPUT_GAMEPAD_START )  
			megad->pad[i] &= PAD_START ;
	
		if ( g_Gamepads[i].hDevice && g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_BLACK]) 
			megad->pad[i] &= PAD_C ;
	
		if ( g_Gamepads[i].hDevice && g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_WHITE]) 
			megad->pad[i] &= PAD_Z ;

		megad->pad[i] &= PAD_6_OR_3 ; 

		if ( ( g_Gamepads[i].hDevice && g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) && 
			 (g_Gamepads[i].hDevice && g_Gamepads[i].bPressedAnalogButtons[XINPUT_GAMEPAD_WHITE]) )
		{
		}
		else if ( ( g_Gamepads[i].hDevice && g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) && 
			 (g_Gamepads[i].hDevice && g_Gamepads[i].bPressedAnalogButtons[XINPUT_GAMEPAD_BLACK]) )
		{
		}
	}

*/	

}

void CXBoxSample::QuickSort( int lo, int hi )
{
	int i = lo;
	int j = hi;
	char partitionStr[200];
	FILENAME tmpf;

	strcpy( partitionStr, (const char*)files[(i+j)/2].filename ) ;
	do
	{
		while ( strcmp( (const char*)files[i].filename, partitionStr ) < 0 ) i++ ;
		while ( strcmp( partitionStr, (const char*)files[j].filename ) < 0 ) j-- ;

		if (i <= j)
		{
			memcpy( &tmpf, &(files[i]), sizeof(tmpf) ) ;
			memcpy( &(files[i]), &(files[j]), sizeof(tmpf) ) ;
			memcpy( &(files[j]), &tmpf, sizeof(tmpf) ) ;
			i++;
			j--;
		}
	} while (i <= j);

	if (lo < j) QuickSort(lo, j);
	if (i < hi) QuickSort(i, hi);

	
}


void CXBoxSample::FindAvailRoms()
{
	// Search for all files in our rom directory
	HANDLE hFind;	
	WIN32_FIND_DATAA oFindData;
	hFind = FindFirstFile( "D:\\bochs\\*", &oFindData);
	
	// If we didn't find any just return
	if (hFind == INVALID_HANDLE_VALUE)
	{
		return;
	}
	
	do 
	{
		numfiles++ ;
	} while (FindNextFile(hFind, &oFindData));

	FindClose( hFind );

	if (files != NULL)
	{
		delete [] files;
		files = NULL;
	}
	
	// Allocate a buffer to blit our frames to
	files = new FILENAME[numfiles];

	numfiles = 0 ;

	hFind = FindFirstFile( "D:\\bochs\\*", &oFindData);
	
	// If we didn't find any just return
	if (hFind == INVALID_HANDLE_VALUE)
	{
		return;
	}
	
	do 
	{
		// Mame's games are in 8-bit ansi convert them to unicode for display
		//WCHAR wcName[200];
		//mbsrtowcs(wcName, &pName, 200, NULL);

		files[numfiles].name[0] = 0 ;
		files[numfiles].tagged = 0 ;
		strcpy( (char*)(files[numfiles].filename), oFindData.cFileName ) ;
		strlwr( (char*)( files[numfiles].filename )) ;
        swprintf( files[numfiles].name, L"%S", files[numfiles].filename );
//		mbsrtowcs(files[numfiles].name, (const char**)( &(oFindData.cFileName) ), 30, NULL);
		numfiles++ ;
	} while (FindNextFile(hFind, &oFindData));

	FindClose( hFind );
	QuickSort( 0, numfiles-1 ) ;
}

// check for move cursor and move accordingly (with clamp etc)
void CXBoxSample::MoveCursor()
{
	char c ;
	int  lcv ;

		if (m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER])
		{
			c = tolower(files[curr].filename[0]) ;

			lcv = curr ;

			while ( ( lcv < numfiles ) && ( tolower(files[lcv].filename[0]) <= c ) )
				lcv++ ;

			if ( lcv < numfiles )
			{
				topIdx = lcv ;
				curr = lcv ;
			}
			else
			{
				topIdx = numfiles - 1 ;
				curr = numfiles - 1 ;
			}
		}
		else if (m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER])
		{
			c = tolower(files[curr].filename[0]) ;

			lcv = curr ;

			while ( ( lcv >= 0 ) && ( tolower(files[lcv].filename[0]) >= c ) )
				lcv-- ;

			if ( lcv >= 0 )
			{
				topIdx = lcv ;
				curr = lcv ;
			}
			else
			{
				topIdx = 0 ;
				curr = 0 ;
			}
		}
		else if ( m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT ) 
		{
			if ( topIdx >= m_namesPerPage )
			{
				topIdx -= m_namesPerPage ;
				curr = topIdx ;
			}
			else
			{
				topIdx = 0 ;
				curr = 0 ;
			}
		}
		else if ( m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) 
		{
			if ( topIdx + m_namesPerPage < numfiles )
			{
				topIdx += m_namesPerPage ;
				curr = topIdx ;
			}
			else
			{
				topIdx = numfiles - 1 ;
				curr = numfiles - 1 ;
			}
		}
		else if ( m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN ) 
		{
			if ( curr == topIdx + (m_namesPerPage-1) )
			{
				if ( curr < numfiles - 1 )
				{
					topIdx++ ;
					curr++ ;
				}
			}
			else
			{
				if ( curr < numfiles-1 )
					curr++ ;
			}
		}
		else if ( m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_DPAD_UP ) 
		{
			if ( curr == topIdx )
			{
				if ( curr > 0 )
				{
					topIdx-- ;
					curr-- ;
				}
			}
			else
			{
				if ( curr > 0 )
					curr-- ;
			}
		}

}



void CXBoxSample::initConsole( UINT32 idx )
{
	char                filename[500] ;
	unsigned char       *gimage ;
	FILE				*infile ;
	UINT32				fsize ;
	char                *argv[3] ;
	char *forcebuf ;
	char *p;

	Keyboard_Init( 32, 400, 150 )  ;

	memset(keyboard_keystate, 0, 256 ) ;

	global_error_message[0] = 0 ;
	g_palchanged = 0 ;

	m_numFrames = 0 ;

	memset( m_memMatches, 1, CONSOLE_MEMORY_SIZE ) ;
	m_currentMemMatches = CONSOLE_MEMORY_SIZE ;
	m_numCheats = 0 ;

	argv[0] = "mcopy.exe"  ;
	argv[1] = filename ;
	argv[2] = "s:\\incoming"  ;

	for ( int tlcv = 0 ; tlcv < numfiles ; tlcv++ )
	{
		if ( files[tlcv].tagged )
		{
			strcpy((char*)filename, "D:\\bochs\\" ) ;
			strcat( (char*)filename, (const char*)files[tlcv].filename ) ;
		
			doscopy( 3, argv ) ;

			files[tlcv].tagged = 0 ;
		}
		
	}

	strcpy( g_saveprefix, g_savePath ) ;
	strcat( g_saveprefix, "\\" ) ;
	strcat( g_saveprefix, (const char*)(files[idx].filename) ) ;
	//sprintf(saveprefix, "%s\\%s", savedir, (const char*)files[idx].filename);
	p = strchr(g_saveprefix, '.');
	if (p) *p = 0;

	strcpy(g_sramfile, g_saveprefix);
	strcat(g_sramfile, ".sav");

	strcpy(g_chtfile, g_saveprefix);
	strcat(g_chtfile, ".cht");

	strcpy(g_statefile, g_saveprefix);
	strcat(g_statefile, ".sta");


	

	//m_debugClient.Send( "init sound\r\n", 12 ) ;

	m_sound.init() ;

	//m_debugClient.Send( "init1\r\n", 7 ) ;


	//m_debugClient.Send( "loadch\r\n", 8 ) ;

	//cht_load();

	//m_debugClient.Send( "ldsram\r\n", 8 ) ;



	//BEGIN EACH TIME
	m_fAppTime = 0.0f ;

	g_dwStartTime = GetTickCount() ;
	g_dwTimePaused = 0 ;
	m_dwStartPause = 0 ;

	m_steps = 0 ;

	//m_debugClient.Send( "procem\r\n", 8 ) ;

	//put 3 frames of data in the audio buffer
	//m_debugClient.Send( "initA\r\n", 7 ) ;
	//processEmu(FALSE) ;
	//m_debugClient.Send( "initB\r\n", 7 ) ;
	//processEmu(FALSE) ;
	//processEmu(FALSE) ;
	//m_debugClient.Send( "initC\r\n", 7 ) ;

	//Then start it up
	m_sound.pause( FALSE ) ;

	//m_debugClient.Send( "initdn\r\n", 8 ) ;

}

void CXBoxSample::cleanupConsole( )
{
	FILE *infile ;

	
	//cht_save() ;


	//if (m_cheatCodes != NULL)
	//{
		//free(m_cheatCodes);
		//m_cheatCodes = NULL;
	//}


  //bx_pc_system.ResetSignal( PCS_SET ); /* XXX is this right? */
  //for (int i=0; i<BX_SMP_PROCESSORS; i++)
      //BX_CPU(i)->reset(BX_RESET_HARDWARE);



}

void CXBoxSample::cht_load()
{
	FILE *f;
	CHEAT_CODE code ;
	int fsize ;
	int numread ;

	if (m_cheatCodes != NULL)
	{
		free(m_cheatCodes);
		m_cheatCodes = NULL;
	}
	

	f = fopen(g_chtfile, "rb");
	if (!f) return ;

	fseek( f, 0, SEEK_END ) ;
	fsize = ftell( f ) ;
	fseek( f, 0, SEEK_SET ) ;

	m_numCheats = fsize / sizeof(CHEAT_CODE) ;

	m_cheatCodes = (CHEAT_CODE*)malloc( sizeof(CHEAT_CODE) *  m_numCheats );


	numread = 0 ;
	fread(m_cheatCodes, sizeof(CHEAT_CODE), m_numCheats, f);

	fclose(f);
}

void CXBoxSample::cht_save()
{
	FILE *f;
	CHEAT_CODE code ;

	if ( m_numCheats == 0 )
	{
		DeleteFile( g_chtfile ) ;
		return ;
	}

	f = fopen(g_chtfile, "wb");
	if (!f) return ;

	fwrite(m_cheatCodes, sizeof(CHEAT_CODE), m_numCheats, f);

	fclose(f);
	
}

BOOL CXBoxSample::hasFiles( int idx )
{
	char                filename[500] ;
	unsigned char       *gimage ;
	FILE				*infile ;
	UINT32				fsize ;
	char *forcebuf ;
	char *p;

/*
	strcpy( g_saveprefix, g_savePath ) ;
	strcat( g_saveprefix, "\\" ) ;
	strcat( g_saveprefix, (const char*)(files[idx].filename) ) ;
	//sprintf(saveprefix, "%s\\%s", savedir, (const char*)files[idx].filename);
	p = strchr(g_saveprefix, '.');
	if (p) *p = 0;

	strcpy(g_sramfile, g_saveprefix);
	strcat(g_sramfile, ".sav");

	strcpy(g_chtfile, g_saveprefix);
	strcat(g_chtfile, ".cht");

	strcpy(g_statefile, g_saveprefix);
	strcat(g_statefile, ".cht");

	infile = fopen( g_sramfile, "rb" ) ;

	if ( infile )
	{
		fclose(infile) ;
		return TRUE ;
	}

	infile = fopen( g_statefile, "rb" ) ;

	if ( infile )
	{
		fclose(infile) ;
		return TRUE ;
	}

	infile = fopen( g_chtfile, "rb" ) ;

	if ( infile )
	{
		fclose(infile) ;
		return TRUE ;
	}
*/
	return FALSE ;

}
void CXBoxSample::updateCheats( )
{
	for ( int i = 0 ; i < m_numCheats ; i++ )
	{
		if ( m_cheatCodes[i].enabled )
			m_consoleMemory[ m_cheatCodes[i].adr ] = ( m_cheatCodes[i].val & 0xFF ) ;
	}
}

void CXBoxSample::deleteSaveFiles( int idx )
{
	char                filename[500] ;
	unsigned char       *gimage ;
	FILE				*infile ;
	UINT32				fsize ;
	char *forcebuf ;
	char *p;


	strcpy( g_saveprefix, g_savePath ) ;
	strcat( g_saveprefix, "\\" ) ;
	strcat( g_saveprefix, (const char*)(files[idx].filename) ) ;
	//sprintf(saveprefix, "%s\\%s", savedir, (const char*)files[idx].filename);
	p = strchr(g_saveprefix, '.');
	if (p) *p = 0;

	strcpy(g_sramfile, g_saveprefix);
	strcat(g_sramfile, ".sav");

	strcpy(g_chtfile, g_saveprefix);
	strcat(g_chtfile, ".cht");

	strcpy(g_statefile, g_saveprefix);
	strcat(g_statefile, ".cht");

	DeleteFile( g_sramfile ) ;
	DeleteFile( g_statefile ) ;
	DeleteFile( g_chtfile ) ;

}
#ifdef __cplusplus
extern "C" {
#endif

void audio_callback()
{
	//g_sound->process( *g_apptime, *g_numframes ) ;

}

void netmessageC( char *str)
{
	//g_debugClient->Send( str, strlen(str)) ;
}

void netmessageH( char *str)
{
	//g_debugClient->Send( str, strlen(str)) ;
	//g_debugClient->WaitKey() ;
}

#ifdef __cplusplus
}
#endif

void netmessage( char *str)
{
	//g_debugClient->Send( str, strlen(str)) ;
}

void netmessageI( const char *fmt, ...)
{
	/*
	va_list ap;
	char msg[10240] ;


	va_start(ap, fmt);
	vsprintf(msg, fmt, ap);
	va_end(ap);

	if ( g_debugClient )
		g_debugClient->Send( (void*)msg, strlen(msg)) ;
		*/
}

void netmessageD( const char *fmt, ...)
{
	//va_list ap;
	//char msg[10240] ;


	//va_start(ap, fmt);
	//vsprintf(msg, fmt, ap);
	//va_end(ap);

	//if ( g_debugClient )
		//g_debugClient->Send( (void*)msg, strlen(msg)) ;
}
void netmessageE( const char *fmt, ...)
{
	/*
	va_list ap;
	char msg[10240] ;


	va_start(ap, fmt);
	vsprintf(msg, fmt, ap);
	va_end(ap);

	//if ( g_debugClient )
		//g_debugClient->Send( (void*)msg, strlen(msg)) ;
		*/
}
void netmessageP( const char *fmt, ...)
{
	/*
	va_list ap;
	char msg[10240] ;


	va_start(ap, fmt);
	vsprintf(msg, fmt, ap);
	va_end(ap);

	if ( g_debugClient )
		g_debugClient->Send( (void*)msg, strlen(msg)) ;
		*/
}


void CXBoxSample::processEmu( BOOL render )
{
			
	//m_debugClient.Send( "cheat\r\n", 7 ) ;

	//updateCheats() ;

	//m_debugClient.Send( "frame\r\n", 7 ) ;

    BX_CPU(0)->cpu_loop(100000000);  //execute 1000000 instructions

	//m_debugClient.Send( "frame2\r\n", 8 ) ;

	if ( render )
	{
		//m_debugClient.Send( "drawf\r\n", 8 ) ;
		render_to_texture();
		m_numFrames++ ;
	}

	//m_debugClient.Send( "sound\r\n", 7 ) ;
	//m_sound.process( m_mdSound.l, m_mdSound.r, m_mdSound.len ) ;
	handleEvents();

//	while ( m_sound.m_bDanger )
	//{
	//m_debugClient.Send( "even2\r\n", 7 ) ;
		//megad->one_frame(NULL,NULL,NULL);
		//megad->one_frame(NULL,NULL,&m_mdSound);
		//m_sound.process( m_mdSound.l, m_mdSound.r, m_mdSound.len ) ;
		//handleEvents();
	//}
	///m_debugClient.Send( "event\r\n", 7 ) ;

			

}


int CXBoxSample::rom_load_zip()
{
	byte c, *data, *header;
	int len = 0, rlen;
/*
    unzFile file = unzOpen(romfile);

    if(file == NULL)
		die("cannot open rom file: %s\n", romfile);


    char filename[132];
    int filesize = 0;
    int port = unzGoToFirstFile(file);
    unz_file_info info;

    while(port == UNZ_OK)
    {
		char name[132];
		unzGetCurrentFileInfo(file, &info, name,128, NULL,0, NULL,0);

		if ((int) info.uncompressed_size > filesize)
		{
			strcpy(filename,name);
			filesize = info.uncompressed_size;
		}
		port = unzGoToNextFile(file);
    }

    if( !(port == UNZ_END_OF_LIST_OF_FILE || port == UNZ_OK) || filesize == 0)
    {
		unzClose(file) ;
		die("cannot open rom file: %s\n", romfile);
    }

    unzLocateFile(file,filename,1);
    unzGetCurrentFileInfo(file, &info, filename,128, NULL,0, NULL,0);
    
    if( unzOpenCurrentFile(file) != UNZ_OK )
    {
		unzClose(file);
		die("cannot open rom file: %s\n", romfile);
    }

	data = (byte*)malloc( info.uncompressed_size ) ;

	int l = unzReadCurrentFile(file,data,info.uncompressed_size);
	if(unzCloseCurrentFile(file) == UNZ_CRCERROR)
	{
		free(data) ;
	    unzClose(file);
		die("cannot open rom file: %s\n", romfile);
	}

    unzClose(file);

	len = info.uncompressed_size ;

	header = data ;
	
	memcpy(rom.name, header+0x0134, 16);
	if (rom.name[14] & 0x80) rom.name[14] = 0;
	if (rom.name[15] & 0x80) rom.name[15] = 0;
	rom.name[16] = 0;

	c = header[0x0147];
	mbc.type = mbc_table[c];
	mbc.batt = (batt_table[c] && !nobatt) || forcebatt;
	rtc.batt = rtc_table[c];
	mbc.romsize = romsize_table[header[0x0148]];
	mbc.ramsize = ramsize_table[header[0x0149]];

	if (!mbc.romsize) die("unknown ROM size %02X\n", header[0x0148]);
	if (!mbc.ramsize) die("unknown SRAM size %02X\n", header[0x0149]);

	rlen = 16384 * mbc.romsize;
	rom.bank = (byte(*)[16384])realloc(data, rlen);
	if (rlen > len) memset(rom.bank[0]+len, 0xff, rlen - len);
	
	ram.sbank = (byte(*)[8192])malloc(8192 * mbc.ramsize);

	//initmem(ram.sbank, 8192 * mbc.ramsize);
	//initmem(ram.ibank, 4096 * 8);

	mbc.rombank = 1;
	mbc.rambank = 0;

	c = header[0x0143];
	hw.cgb = ((c == 0x80) || (c == 0xc0)) && !forcedmg;
	hw.gba = (hw.cgb && gbamode);
*/
	return 0;
}

//sometimes items are just gone
//re-load list
//pAL/ntsc
//quit app to return to dashboard
