#define RELAXCASE
#define CHEAT5000
#define DEBUG_KEYBOARD

#include <XBApp.h>
#include <XBFont.h>
#include <XBHelp.h>
#include <xgraphics.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 "Mp3Player.h"
#include "src\includes\winston.h"
#include "src\includes\memorysnapshot.h"
#include "src\includes\keymap.h"
#include "src\includes\ikbd.h"
#include "src\includes\decode.h"
#include "src\includes\floppy.h"
#include "src\includes\screen.h"
//#include "src\includes\dialogconfigure.h"
#include "src\includes\dialog.h"
#include "keyboard_api.h"

#ifdef __cplusplus
extern "C" {
#endif


#ifdef __cplusplus
}
#endif

int PASCAL winston_main( char *stfilename);
void WinSTon_SetVBLEvent(void);
void Screen_SetFullUpdateMask(void);


#define PLATFORM_SAV L"STSAV"
#define READING_ROMS_STRING L"Reading stdisks directory...please wait."
#define PLATFORM_INI "st.ini"
#define PLATFORM_SPEC_INI "stspec.ini"
#define PLATFORM_MEMORY_POINTER STRam
#define THEMEMUSIC "D:\\STDISKS\\STTHEME.MP3"
#define PLATFORM_FILE_DIR "D:\\stdisks\\*"
#define CONSOLE_MEMORY_SIZE 0x420000
#define DEFAULT_PARENT_DIR "D:\\stdisks\\"

byte keyboard_keystate[256] ;

//-----------------------------------------------------------------------------
// 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, int forceUS, int whichCard ) ;
	virtual void    cleanupConsole( ) ;
	virtual int     handleEvents(int port) ;
	virtual int     init_texture() ;
	virtual int		init_white_texture();
	virtual int		render_to_texture() ;
	virtual void	FindAvailRoms(char *parentdir) ;
	virtual void    doStartSearchMenu() ;
	virtual void    doCodeListMenu() ;
	virtual void    doCodeListMenu2() ;
	virtual void    doAddFoundCodes() ;
	virtual void    doAddFoundCodes2() ;
	virtual void    doContinueSearchMenu() ;
	virtual void    doContinueSearchMenu2() ;
	virtual void    doCheatMenu() ;
	virtual void    doFontSize() ;
	virtual void    doSaveConfig() ;
	virtual void    doScreenSize() ;
	void            handleScreenKeyboard( );
	void            renderScreenKeyboard( );
	virtual void    getKeyboardString( char *buf, int bufsize ) ;
	void            musicControlMenu( CPanel *panel );
	void            doDefaultDirs();
	virtual void    doLoadNewDisk() ;
	virtual void    doEmulatorOptions() ;
	virtual void    doTextOffset() ;
	virtual void    doConfiguration() ;
	virtual void    updateCheats() ;
	virtual void    processEmu( BOOL render ) ;
	virtual void    cht_load() ;
	virtual void    cht_save() ;
	virtual void    doUtilities( );
	virtual void    doHelp( );
	virtual void    doSettings( );
	virtual void    doCheatCodes( );
	virtual void    doGameUtilities( );
	virtual int     selectState( );
	virtual void    deleteSaveFiles( int which, int onlyFavorites ) ;
	virtual void    doEditCode( int which ) ;
	virtual void    doEditCode2( int which ) ;
	virtual BOOL    hasFiles( int which ) ;
	virtual int     rom_load_zip( char *hugozipfile ) ;
	virtual void    QuickSort( int start, int end ) ;
	void			MenuBar( int xpos, int ypos, int xlen, int ylen ) ;
	

	float fGameSelect;
	float fCursorPos;
	float m_fFrameTime ;
	float fMaxCount;
	int   iGameSelect;
	int   iCursorPos;
	UINT32 m_numFrames ;
	int   keyTime ;
	int   m_mousePosX, m_mousePosY ;
	unsigned int   m_bMappingB ;
	unsigned int   m_bMappingX ;
	unsigned int   m_bMappingSTART ;
	unsigned int   m_bMappingBACK ;
	unsigned int   m_bMappingBLACK ;
	unsigned int   m_bMappingWHITE ;
	char    m_szCurrentDir[MAX_PATH] ;


	UINT32 topIdx  ;
	UINT32 curr  ;
	CDebugClient m_debugClient ;
	D3DPalette			*m_pd3dPalette ;
	unsigned int g_pitch ;

    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] ;
		char flagged ;
		char isDir ;
	} 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 ;

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


	SoundXBOX			m_sound;
	Mp3Player			m_mp3player;
	char				g_savePath[500] ;
	char				g_saveprefix[500] ;
	char				g_sramfile[500] ;
	char				g_bramfile[500] ;
	char				g_cuefile[500] ;
	char				g_rtcfile[500] ;
	char				g_chtfile[500] ;
	char				g_statefile[500] ;
	FILE                *m_logfile ;

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

	int					m_nScreenX, m_nScreenY, m_nScreenMaxX, m_nScreenMaxY ;

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

	CHEAT_CODE *m_cheatCodes;

	UINT32 m_numCheats ;


};


#include "..\common\commonfuncs.cpp"






struct { char *keyname ; int keynum ; } validKeys[75] = 
{
	{ "Space", 0x20 },
	{ "Enter", 0x0D },
	{ "Backspace", 0x08 },
	{ "Tab", 0x09 },
	{ "Escape", 0x1B },
	{ "PgUp", 0x21 },
	{ "PgDn", 0x22 },
	{ "End", 0x23 },
	{ "Home", 0x24 },
	{ "Left", 0x25 },
	{ "Up", 0x26 },
	{ "Right", 0x27 },
	{ "Down", 0x28 },
	{ "Insert", 0x2d },
	{ "Delete", 0x2e },
	{ "0", 0x30 },
	{ "1", 0x31 },
	{ "2", 0x32 },
	{ "3", 0x33 },
	{ "4", 0x34 },
	{ "5", 0x35 },
	{ "6", 0x36 },
	{ "7", 0x37 },
	{ "8", 0x38 },
	{ "9", 0x39 },
	{ "A", 0x41 },
	{ "B", 0x42 },
	{ "C", 0x43 },
	{ "D", 0x44 },
	{ "E", 0x45 },
	{ "F", 0x46 },
	{ "G", 0x47 },
	{ "H", 0x48 },
	{ "I", 0x49 },
	{ "J", 0x4A },
	{ "K", 0x4B },
	{ "L", 0x4C },
	{ "M", 0x4D },
	{ "N", 0x4E },
	{ "O", 0x4F },
	{ "P", 0x50 },
	{ "Q", 0x51 },
	{ "R", 0x52 },
	{ "S", 0x53 },
	{ "T", 0x54 },
	{ "U", 0x55 },
	{ "V", 0x56 },
	{ "W", 0x57 },
	{ "X", 0x58 },
	{ "Y", 0x59 },
	{ "Z", 0x5A },
	{ "F1", 0x70 },
	{ "F2", 0x71 },
	{ "F3", 0x72 },
	{ "F4", 0x73 },
	{ "F5", 0x74 },
	{ "F6", 0x75 },
	{ "F7", 0x76 },
	{ "F8", 0x77 },
	{ "F9", 0x78 },
	{ "F10", 0x79 },
	{ "LShift", 0xA0 },
	{ "RShift", 0xA1 },
	{ "LCtrl", 0xA2 },
	{ "RCtrl", 0xA3 },
	{ ";", 0xBA },
	{ "+", 0xBB },
	{ ",", 0xBC },
	{ "-", 0xBD },
	{ ".", 0xBE },
	{ "/", 0xBF },
	{ "[", 0xDB },
	{ "\\", 0xDC },
	{ "]", 0xDD },
	{ "'", 0xDE }
} ;


int CXBoxSample::init_texture()
{
	// Release any previous texture
	if (Texture) 
	{ 
		Texture->Release();
		Texture = NULL;
	}
	
	theWidth = 640 ;
	theHeight = 480 ;

	// Create the texture
	//D3DXCreateTexture(m_pd3dDevice, theWidth, theHeight, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &Texture);
	D3DXCreateTexture(m_pd3dDevice, theWidth, theHeight, 0, 0, D3DFMT_X1R5G5B5, D3DPOOL_DEFAULT, &Texture);
	
	D3DSURFACE_DESC desc;
    Texture->GetLevelDesc(0, &desc);

	if (g_pBlitBuff != NULL)
	{
		delete [] g_pBlitBuff;
		g_pBlitBuff = NULL;
	}
	
	// Allocate a buffer to blit our frames to
	g_pBlitBuff = new byte[desc.Size];


	if (g_pAlignBuff != NULL)
	{
		delete [] g_pAlignBuff;
		g_pAlignBuff = NULL;
	}
	
	// Allocate a buffer to blit our frames to
	g_pAlignBuff = new byte[desc.Size];


	D3DCOLOR			*color_palette;
	


	RECT rectSource;
	rectSource.top = 0;
	rectSource.left = 0;
	rectSource.bottom = theHeight-1 ;
	rectSource.right  = theWidth-1 ;

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

	g_pitch = d3dlr.Pitch ;

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

	m_pd3dDevice->CreatePalette( D3DPALETTE_256 , &m_pd3dPalette ) ;
	m_pd3dPalette->Lock( &color_palette, 0 ) ;

/*
  osd_gfx_set_color (255, 0x3f, 0x3f, 0x3f);

  for (i = 0; i < 255; i++)
    {
      osd_gfx_set_color (i,
			 (i & 0x1C) << 1, (i & 0xe0) >> 2, (i & 0x03) << 4);
    }
*/

	color_palette[255] = 0xFFFFFFFF ;


	int r, g, b;
	for (int i = 0; i < 255; i++)
	{
		r = (i & 0x1C) << 1 ;
		g = (i & 0xe0) >> 2 ;
		b = (i & 0x03) << 4 ;

		r = r << 2 ;
		g = g << 2 ;
		b = b << 2 ;

		//r = (256*r) / 56 ;
		//g = (256*g) / 56 ;
		//b = (256*b) / 48 ;
		color_palette[i] = 	( 0xFF << 24 ) | ( (r) << 16 ) | ( (g) << 8 ) | (b)  ;
	}

	m_pd3dPalette->Unlock() ;

	m_pd3dDevice->SetPalette( 0, m_pd3dPalette ) ;

	return 0;
}







void CXBoxSample::doEmulatorOptions()
{

	int menuChoice = 0 ;
	WCHAR str[200] ;
	FILE *inifile ;
	char tmpfilename[MAX_PATH] ;

	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( (float)(m_nXOffset+  32), (float)(16*4), 0xffffffff, L"Emulator Configuration Options" );

		swprintf( str, L"Use DPAD to change mapping of B button : %S", validKeys[m_bMappingB].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*6, menuChoice==0 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD to change mapping of X button : %S", validKeys[m_bMappingX].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*7, menuChoice==1 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD to change mapping of START button : %S", validKeys[m_bMappingSTART].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*8, menuChoice==2 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD to change mapping of BACK button : %S", validKeys[m_bMappingBACK].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*9, menuChoice==3 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD to change mapping of BLACK button : %S", validKeys[m_bMappingBLACK].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*10, menuChoice==4 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD to change mapping of WHITE button : %S", validKeys[m_bMappingWHITE].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*11, menuChoice==5 ? 0xff000000 : 0xffffffff, str );

		m_Font.DrawText( (float)m_nXOffset+  32, 16*13, 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])
		{
			strcpy( tmpfilename, g_savePath ) ;
			strcat( tmpfilename, PLATFORM_SPEC_INI ) ;
			inifile = fopen( tmpfilename, "wb" ) ;
			if ( inifile )
			{
				fwrite( &m_bMappingB, sizeof(m_bMappingB), 1, inifile ) ;
				fwrite( &m_bMappingX, sizeof(m_bMappingX), 1, inifile ) ;
				fwrite( &m_bMappingBLACK, sizeof(m_bMappingBLACK), 1, inifile ) ;
				fwrite( &m_bMappingWHITE, sizeof(m_bMappingWHITE), 1, inifile ) ;
				fwrite( &m_bMappingSTART, sizeof(m_bMappingSTART), 1, inifile ) ;
				fwrite( &m_bMappingBACK, sizeof(m_bMappingBACK), 1, inifile ) ;
				fclose( inifile ) ;
			}
	        XBInput_GetInput();
			break ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN )
		{
			menuChoice = (menuChoice+1)%6 ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_UP )
		{
			if ( menuChoice == 0 )
				menuChoice = 5 ;
			else
				menuChoice = (menuChoice-1)%6 ;
		}
		else if ( (g_Gamepads[0].hDevice ) && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT )
		{
			switch ( menuChoice )
			{
				case 0 : m_bMappingB = (m_bMappingB+1)%75; break ;
				case 1 : m_bMappingX = (m_bMappingX+1)%75; break ;
				case 2 : m_bMappingSTART = (m_bMappingSTART+1)%75; break ;
				case 3 : m_bMappingBACK = (m_bMappingBACK+1)%75; break ;
				case 4 : m_bMappingBLACK = (m_bMappingBLACK+1)%75; break ;
				case 5 : m_bMappingWHITE = (m_bMappingWHITE+1)%75; break ;
				default : break ;
			}
		}
		else if ( (g_Gamepads[0].hDevice ) && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT )
		{
			switch ( menuChoice )
			{
				case 0 : if ( m_bMappingB == 0 ) m_bMappingB = 74 ; else m_bMappingB = (m_bMappingB-1)%75; break ;
				case 1 : if ( m_bMappingX == 0 ) m_bMappingX = 74 ; else m_bMappingX = (m_bMappingX-1)%75; break ;
				case 2 : if ( m_bMappingSTART == 0 ) m_bMappingSTART = 74 ; else m_bMappingSTART = (m_bMappingSTART-1)%75; break ;
				case 3 : if ( m_bMappingBACK == 0 ) m_bMappingBACK = 74 ; else m_bMappingBACK = (m_bMappingBACK-1)%75; break ;
				case 4 : if ( m_bMappingBLACK == 0 ) m_bMappingBLACK = 74 ; else m_bMappingBLACK = (m_bMappingBLACK-1)%75; break ;
				case 5 : if ( m_bMappingWHITE == 0 ) m_bMappingWHITE = 74 ; else m_bMappingWHITE = (m_bMappingWHITE-1)%75; break ;
				default : break ;
			}
		}


	}

}


void CXBoxSample::doContinueSearchMenu2()
{

	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( (float)m_nXOffset+  32, 16*2, 0xffffffff, L"Search Options" );
		m_Font.DrawText( (float)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( (float)m_nXOffset+  32, 16*5, 0xffffffff, str );

		m_Font.DrawText( (float)m_nXOffset+  32, 16*6, 0xffffffff, L"Press Y to search for values less than before." );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*7, 0xffffffff, L"Press A to search for values greater than before." );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*8, 0xffffffff, L"Press BLACK to search for values equal to before." );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*9, 0xffffffff, L"Press WHITE to search for values not equal to before." );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*10, 0xffffffff, L"Press DPAD-UP to add 1 to the value" ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*11, 0xffffffff, L"Press DPAD-DOWN to subtract 1 from the value" ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*12, 0xffffffff, L"Press DPAD-RIGHT to add 10 to the value" ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*13, 0xffffffff, L"Press DPAD-LEFT to subtract 10 from the value" ) ;
		m_Font.DrawText( (float)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( (float)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 )
			{
				doAddFoundCodes2() ;
				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 )
			{
				doAddFoundCodes2() ;
				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 )
			{
				doAddFoundCodes2() ;
				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 )
			{
				doAddFoundCodes2() ;
				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 )
			{
				doAddFoundCodes2() ;
				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 < 10 ) )
			{
				doAddFoundCodes2() ;
				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( (float)m_nXOffset+  32, 16*2, 0xffffffff, L"You can only add when you have narrowed " ) ;
					m_Font.DrawText( (float)m_nXOffset+  32, 16*3, 0xffffffff, L"it down to less than 5 matches." );
					m_Font.DrawText( (float)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::doLoadNewDisk()
{
	WCHAR str[2000];
	swprintf( str, L"WinSTon for XBOX  B-Abort  Found %u games", numfiles);


	while ( 1 )
	{
		MoveCursor();

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

		m_Font.Begin();


		m_FontSmall.Begin(); 
		m_Font.DrawText( (float)m_nXOffset+ 48, 32, 0xffffffff, str );
			
		float fWinX = 32, fWinY = 64;

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

		for ( unsigned int idx = topIdx ; ( idx < numfiles ) && ( idx < topIdx+m_namesPerPage) ; idx++ )
		{
			if ( curr == idx )
			{
				if ( hasFiles( idx ) )
					m_FontSmall.DrawText( (float)m_nXOffset+fWinX  , fWinY, 0xffff00ff, files[idx].name );
				else
					m_FontSmall.DrawText( (float)m_nXOffset+fWinX , fWinY, 0xff000000, files[idx].name );
			}
			else
			{
				if ( hasFiles( idx ) )
					m_FontSmall.DrawText( (float)m_nXOffset+fWinX, fWinY, 0xff00ff00, files[idx].name );
				else
					m_FontSmall.DrawText( (float)m_nXOffset+fWinX, fWinY, 0xffffffff, files[idx].name );
			}
			fWinY += (m_nFontHeight + 2);
		}
		

		// end font drawing
		m_Font.End();
		m_FontSmall.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 ] ) 
		{
			char filename[MAX_PATH] ;

			strcpy((char*)filename, "D:\\stdisks\\" ) ;
			//wcsrtombs( (char*)gfilename, (const wchar_t**)(&(files[idx].name)), 100, NULL ) ;
			strcat( (char*)filename, (const char*)files[curr].filename ) ;


			char *p;

			strcpy( g_saveprefix, g_savePath ) ;
			strcat( g_saveprefix, "\\" ) ;
			strcat( g_saveprefix, strrchr( filename, '\\' )+1 ) ;
			//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");

			sprintf( g_statefile, "%s.sta", g_saveprefix ) ;

			Floppy_InsertDiscIntoDrive(0,filename) ;
			break ;
		}
	}
}

void CXBoxSample::doAddFoundCodes2()
{
	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%05.5X", code.val, code.adr ) ;

			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( (float)m_nXOffset+  32, 16*2, 0xffffffff, L"The search found 1 to 4 possible matches for your search." );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*3, 0xffffffff, L"They have been added to your list." );
		m_Font.DrawText( (float)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::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( (float)m_nXOffset+  32, 16*2, 0xffffffff, L"OPTIONS MENU" );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*4, 0xffffffff, L"B - Return to Game" );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*5, 0xffffffff, L"START+BACK - Quit Game" );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*6, 0xffffffff, L"BLACK - Start Search for Cheat Code" );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*7, 0xffffffff, L"A - Continue Cheat Search" );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*8, 0xffffffff, L"RS+LS - Cheat Code List" );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*9, 0xffffffff, L"X - Emulator Configuration" );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*10, 0xffffffff, L"WHITE - Load a new Atari ST Disk into drive A" );


		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_mp3player.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() ;
			m_mp3player.cleanup() ;
			//cleanupConsole() ;
			m_state = MAIN_MENU ;
	        XBInput_GetInput();
			break ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_A])
		{
			doContinueSearchMenu2() ;
		}
		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]) )
		{
			doCodeListMenu2() ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_X])
		{
			doEmulatorOptions() ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_WHITE])
		{
			doLoadNewDisk() ;
		}


	}

}

void CXBoxSample::doCodeListMenu2()
{

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

		MenuBar( m_nXOffset+32, 16*(11+(selected-cheatTopIdx)) + 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%05.5X val:%u %S", code->code, code->adr, code->val, code->enabled ? "ON" : "OFF" ) ;
			
			if ( selected == idx )
				m_Font.DrawText( (float)m_nXOffset+32, (float)(16*(11+(idx-cheatTopIdx))), 0xff000000, str );
			else
				m_Font.DrawText( (float)m_nXOffset+32, (float)(16*(11+(idx-cheatTopIdx))), 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])
		{
			doEditCode2( -1 ) ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_X])
		{
			doEditCode2( 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].wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT )
		{
			if ( cheatTopIdx + 10 < m_numCheats )
			{
				cheatTopIdx += 10 ;
				selected = cheatTopIdx ;
			}
		}
		else if (g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT)
		{
			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::doEditCode2( int which )
{
	CHEAT_CODE code ;
	int curr_pos ;

	if ( which < 0 )
	{
		strcpy( code.code, "010000000" ) ;
		code.enabled = 1 ;
		code.adr = 0x00000 ;
		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((float)m_nXOffset+  32, 16*2, 0xffffffff, L"Add New Cheat Code" );
		else
			m_Font.DrawText( (float)m_nXOffset+ 32, 16*2, 0xffffffff, L"Edit Cheat Code" );

		m_Font.DrawText( (float)m_nXOffset+ 32, 16*4, 0xffffffff, L"Press B to cancel." );
		m_Font.DrawText( (float)m_nXOffset+ 32, 16*5, 0xffffffff, L"Press A to save." );
		m_Font.DrawText( (float)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( (float)m_nXOffset+  50 + ( i * 16 ), 16*9, 0xff00ff00, str ) ;
			else
				m_Font.DrawText( (float)m_nXOffset+  50 + ( i * 16 ), 16*9, 0xffffffff, str ) ;
		}

		swprintf( str, L"Address : %05.5X", code.adr ) ;
		m_Font.DrawText( (float)m_nXOffset+  50 , 16*11, 0xffffffff, str ) ;
		swprintf( str, L"Value : %u", code.val ) ;
		m_Font.DrawText( (float)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 > 0xFFFFF ) )
			{
				while ( 1 )
				{
					m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
										 0x00000000, 1.0f, 0L );
					RenderGradientBackground( 0xFF000000, 0xFF000000 );

					m_Font.Begin();
					m_Font.DrawText( (float)m_nXOffset+  32, 16*2, 0xffffffff, L"The Address must be between 0x0000 and 0xFFFFF" );
					m_Font.DrawText( (float)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 >> 16 ) &  0x0F ) == 0 )
						code.adr = 0xF0000 + ( code.adr & 0x0FFFF ) ;
					else
						code.adr = ( code.adr - 0x10000 ) & 0xFFFFF ;
					break ;
				}
				case 3 :
				{
					if ( ( ( code.adr >> 12 ) &  0x0F ) == 0 )
						code.adr = 0x0F000 + ( code.adr & 0xF0FFF ) ;
					else
						code.adr = ( code.adr - 0x1000 ) & 0xFFFFF ;
					break ;
				}
				case 4 :
				{
					if ( ( ( code.adr >> 8 ) &  0x0F ) == 0 )
						code.adr = 0x0F00 + ( code.adr & 0xFF0FF ) ;
					else
						code.adr = ( code.adr - 0x100 ) & 0xFFFFF ;
					break ;
				}
				case 5 :
				{
					if ( ( ( code.adr >> 4 ) &  0x0F ) == 0 )
						code.adr = 0xF0 + ( code.adr & 0xFFF0F ) ;
					else
						code.adr = ( code.adr - 0x10 ) & 0xFFFFF ;
					break ;
				}
				case 6 :
				{
					if ( ( ( code.adr ) &  0x0F ) == 0 )
						code.adr = 0x0F + ( code.adr & 0xFFFF0 ) ;
					else
						code.adr = ( code.adr - 0x01 ) & 0xFFFFF ;
					break ;
				}
				default : break ;
			}
			sprintf( code.code, "01%02.2X%05.5X", code.val, code.adr ) ;
		}
		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 >> 16 ) &  0x0F ) == 0x0F )
						code.adr = 0x0000 + ( code.adr & 0x0FFFF ) ;
					else
						code.adr = ( code.adr + 0x10000 ) & 0xFFFFF ;
					break ;
				}
				case 3 :
				{
					if ( ( ( code.adr >> 12 ) &  0x0F ) == 0x0F )
						code.adr = 0x0000 + ( code.adr & 0xF0FFF ) ;
					else
						code.adr = ( code.adr + 0x1000 ) & 0xFFFFF ;
					break ;
				}
				case 4 :
				{
					if ( ( ( code.adr >> 8 ) &  0x0F ) == 0x0F )
						code.adr = 0x0000 + ( code.adr & 0xFF0FF ) ;
					else
						code.adr = ( code.adr + 0x100 ) & 0xFFFFF ;
					break ;
				}
				case 5 :
				{
					if ( ( ( code.adr >> 4 ) &  0x0F ) == 0x0F )
						code.adr = 0x00 + ( code.adr & 0xFFF0F ) ;
					else
						code.adr = ( code.adr + 0x10 ) & 0xFFFFF ;
					break ;
				}
				case 6 :
				{
					if ( ( ( code.adr ) &  0x0F ) == 0x0F )
						code.adr = 0x00 + ( code.adr & 0xFFFF0 ) ;
					else
						code.adr = ( code.adr + 0x01 ) & 0xFFFFF ;
					break ;
				}
				default : break ;
			}
			sprintf( code.code, "01%02.2X%05.5X", code.val, code.adr ) ;

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


}

//-----------------------------------------------------------------------------
// 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.bPressedAnalogButtons[XINPUT_GAMEPAD_Y])
		{
			m_sound.pause( TRUE ) ;
			m_mp3player.pause( TRUE ) ;
			m_state = IN_GAME_PAUSED ;
			m_dwStartPause = GetTickCount();
			return S_OK ;
		}
	}
	else if ( m_state == MAIN_MENU )
	{
		m_mp3player.process() ;

		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 ( (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( (float)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 ;

			char tmpdir[MAX_PATH] ;
			sprintf( tmpdir, "%s*", m_szCurrentDir ) ;

			FindAvailRoms(tmpdir) ;
			curr = 0 ;
			topIdx = 0 ;


		}
		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])
			{
				if ( files[curr].isDir )
				{
					numfiles = 0 ;

					char tmpdir[MAX_PATH] ;
					char *p ;

					if ( curr )
						sprintf( tmpdir, "%s%s\\*", m_szCurrentDir, (char*)files[curr].filename ) ;
					else
					{
						strcpy( tmpdir, m_szCurrentDir ) ;

						p = strrchr( tmpdir, '\\' ) ;
						if ( p )
							*p = 0 ;
						p = strrchr( tmpdir, '\\' ) ;
						if ( p )
							*p = 0 ;
						strcat( tmpdir, "\\*" ) ;
					}

					FindAvailRoms( tmpdir ) ;
					curr = 0 ;
					topIdx = 0 ;
				}
				else
				{
					m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
										 0x00000000, 1.0f, 0L );
					RenderGradientBackground( 0xFF000000, 0xFF000000 );
					m_Font.Begin();
					m_Font.DrawText( (float)m_nXOffset+  32, 16*2, 0xffffffff, L"Loading game...please wait." ) ;
					m_Font.End();
					m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
					m_state = IN_GAME ;
					initConsole(curr, 0, 0) ;
				}
				return S_OK ;
			}
			else if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_LEFT_THUMB )
			{
				doConfiguration() ;
				return S_OK ;
			}
			else if ( m_DefaultGamepad.wButtons & XINPUT_GAMEPAD_BACK )  
			{
				m_mp3player.stop() ;
			}
		}
	}
	else if ( m_state == IN_GAME_PAUSED )
	{
		m_sound.pause( TRUE ) ;
		m_mp3player.pause( TRUE ) ;
		m_bPaused =  TRUE ;
		doCheatMenu() ;

		if ( m_state == MAIN_MENU )
		{
		}

		return S_OK ;
	}
	else
	{
	}

    return S_OK;
}


int CXBoxSample::render_to_texture()
{

	//DOXXX
	RECT src, dst;
	byte *curr1, *curr2 ;
	
	// 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 = theHeight - 1 ;
	rectSource.right  = theWidth  - 1;

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

	//sprintf(xmsg, "h=%u,w=%u\r\n", io.screen_h, io.screen_w) ;
	//writexbox( xmsg) ;

	curr1 = g_pBlitBuff ;
	//DOXXX
	curr2 = NULL ;

	//for ( unsigned int y = 0 ; y < theHeight ; y++ )
	//{
		//curr1 = ((byte*)g_pBlitBuff) + ( y*d3dlr.Pitch ) ;
		//curr2 = ((byte*)osd_gfx_buffer) + ( y*(320+64+40) ) + ( ( (320+64+40)-io.screen_w ) /2 )  ;
		//memcpy( curr1, curr2, io.screen_w ) ;
	//}
	
	// Swizzle the blittled surface back to the texture
	XGSwizzleRect(g_pBlitBuff, 0, NULL, d3dlr.pBits, desc.Width, desc.Height, NULL, 2);


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

	// 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 = (float)dst.right-dst.left;
	const float dh = (float)dst.bottom-dst.top;
	const float sw = (float)src.right-src.left;
	const float sh = (float)src.bottom-src.top;
	float mx, my ;



	mx = (float)m_nScreenMaxX / (float)theWidth ;
	my = (float)m_nScreenMaxY / (float)theHeight;

	// Compute the scale and transform vectors
	//D3DXVECTOR2 vecScale(dw/sw, dh/sh);
	D3DXVECTOR2 vecScale(mx, my);
	D3DXVECTOR2 vecTranslate((float)m_nScreenX, (float)m_nScreenY );


	//mx = 640.0f / io.screen_w ;
	//my = 480.0f / io.screen_h ;
	//mx = 580.0f / io.screen_w ;
	//my = 400.0f / io.screen_h ;



	// Compute the scale and transform vectors
	//D3DXVECTOR2 vecScale(dw/sw, dh/sh);
	//D3DXVECTOR2 vecScale( mx,my ) ;
	//D3DXVECTOR2 vecScale( min(mx,my), min(mx,my) ) ;
	//D3DXVECTOR2 vecScale( (io.screen_w <= 320) ? 2 : 1 , (io.screen_w <= 320) ? 2 : 1);
	//D3DXVECTOR2 vecTranslate( 10, 20 ) ;
	//D3DXVECTOR2 vecTranslate( ( 640.0f - ( (float)io.screen_w * ( min(mx,my) ) ) )/2,
		                      //( 480.0f - ( (float)io.screen_h * ( min(mx,my) ) ) )/2 );
	//D3DXVECTOR2 vecTranslate( ( 640.0f - ( (float)io.screen_w * ( mx ) ) )/2,
		                      //( 480.0f - ( (float)io.screen_h * ( my ) ) )/2 );
	//D3DXVECTOR2 vecTranslate( (io.screen_w <= 320) ? 320 - io.screen_w : 320 - ( io.screen_w/2), 
	//	                      (io.screen_w <= 320) ? 240 - io.screen_h : 240 - ( io.screen_h/2)  );
	//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;
}



//-----------------------------------------------------------------------------
// 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 )
		{

			m_Font.Begin();
			//swprintf( str, L"%S", global_error_message );
			//m_Font.DrawText( 32, 48, 0x40ffffff, str );
			m_Font.DrawText( (float)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( (float)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( (float)m_nXOffset+32, 16*3,  0xffffffff, L"WinSTon for XBOX");
			m_Font.DrawText( (float)m_nXOffset+32, 16*5,  0xffffffff, L"Main Menu Controls");
			m_Font.DrawText( (float)m_nXOffset+32, 16*6,  0xffffffff, L"A - Play Selected Game");
			m_Font.DrawText( (float)m_nXOffset+32, 16*7,  0xffffffff, L"Y - Show This Help Screen");
			m_Font.DrawText( (float)m_nXOffset+32, 16*8,  0xffffffff, L"UP/DOWN - Select Game");
			m_Font.DrawText( (float)m_nXOffset+32, 16*9,  0xffffffff, L"RIGHT/LEFT - Next/Prev Page");
			m_Font.DrawText( (float)m_nXOffset+32, 16*10,  0xffffffff, L"LS/RS - Next/Prev Letter");
			m_Font.DrawText( (float)m_nXOffset+32, 16*11,  0xffffffff, L"START+BACK+LS+RS - Exit to dashboard");
			m_Font.DrawText( (float)m_nXOffset+32, 16*12,  0xffffffff, L"X+B - Reload list");
			m_Font.DrawText( (float)m_nXOffset+32, 16*13,  0xff00ff00, L"Lines colored like this have save files on the HD.");

			m_Font.DrawText( (float)m_nXOffset+32, 16*15, 0xffffffff, L"In-Game Controls");
			m_Font.DrawText( (float)m_nXOffset+32, 16*16, 0xffffffff, L"A - Joystick fire button");
			m_Font.DrawText( (float)m_nXOffset+32, 16*17, 0xffffffff, L"DPAD - Joystick Movement");
			m_Font.DrawText( (float)m_nXOffset+32, 16*18, 0xffffffff, L"LANALOG - Mouse movement");
			m_Font.DrawText( (float)m_nXOffset+32, 16*19, 0xffffffff, L"RANALOG - Mouse buttons");
			m_Font.DrawText( (float)m_nXOffset+32, 16*20, 0xffffffff, L"RTRIGGER - Speed up");
			m_Font.DrawText( (float)m_nXOffset+32, 16*21, 0xffffffff, L"Y - Options Menu");
			m_Font.DrawText( (float)m_nXOffset+32, 16*22, 0xffffffff, L"LS+BLACK - Save state");
			m_Font.DrawText( (float)m_nXOffset+32, 16*23, 0xffffffff, L"LS+WHITE - Load state");
			m_Font.DrawText( (float)m_nXOffset+32, 16*24, 0xffffffff, L"WHITE/BLACK/X/B/START/BACK-Customizable");
			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( (float)m_nXOffset+48, 32, 0xffffffff, L"WinSTon 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"WinSTon for XBOX  Y-Help Screen  Found %u games", numfiles);

			m_Font.Begin(); 
			m_FontSmall.Begin(); 
			m_Font.DrawText( (float)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+(int)fWinX, (int)fWinY+ (( m_nFontHeight+2)*(curr-topIdx)) + 3, 600, m_nFontHeight+3 ) ;

			for ( unsigned int idx = topIdx ; ( idx < numfiles ) && ( idx < topIdx+m_namesPerPage) ; idx++ )
			{
				if ( curr == idx )
				{
					if ( hasFiles( idx ) )
						m_FontSmall.DrawText( (float)m_nXOffset+fWinX  , fWinY, 0xffff00ff, files[idx].name );
					else
						m_FontSmall.DrawText( (float)m_nXOffset+fWinX , fWinY, 0xff000000, files[idx].name );
				}
				else
				{
					if ( hasFiles( idx ) )
						m_FontSmall.DrawText( (float)m_nXOffset+fWinX, fWinY, 0xff00ff00, files[idx].name );
					else
						m_FontSmall.DrawText( (float)m_nXOffset+fWinX, fWinY, 0xffffffff, files[idx].name );
				}
				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 )
	{
		char tmpfilename[MAX_PATH] ;
		FILE *inifile ;

		InitializeWithScreen() ;
		m_bMappingB = 0 ;
		m_bMappingX = 1 ;
		m_bMappingBACK = 16 ;
		m_bMappingSTART = 17 ;
		m_bMappingBLACK = 18 ;
		m_bMappingWHITE = 19 ;

		strcpy( tmpfilename, g_savePath ) ;
		strcat( tmpfilename, PLATFORM_SPEC_INI ) ;
		inifile = fopen( tmpfilename, "rb" ) ;
		if ( inifile )
		{
			fread( &m_bMappingB, sizeof(m_bMappingB), 1, inifile ) ;
			fread( &m_bMappingX, sizeof(m_bMappingX), 1, inifile ) ;
			fread( &m_bMappingBLACK, sizeof(m_bMappingBLACK), 1, inifile ) ;
			fread( &m_bMappingWHITE, sizeof(m_bMappingWHITE), 1, inifile ) ;
			fread( &m_bMappingSTART, sizeof(m_bMappingSTART), 1, inifile ) ;
			fread( &m_bMappingBACK, sizeof(m_bMappingBACK), 1, inifile ) ;
			fclose( inifile ) ;
		}
	}
	else if ( m_state == INIT_SYSTEM_SHOW_SCREEN )
	{
	}
	else
	{
	}



    return S_OK;
}

/**
  This routine should be called regularly to handle events
*/

int CXBoxSample::handleEvents(int port)
{

	int value ;
	XINPUT_DEBUG_KEYSTROKE   keystroke ;
	char stkey ;
	char xmsg[100] ;
	char vcode ;

	value = 0 ;

	if ( port )
		port = 0 ;
	else
		port = 1;

	updateCheats() ;

	XBInput_GetInput();

	if ( g_Gamepads[port].hDevice )
	{
		if ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_A ] ) 
			value |= 0x80 ;
		if ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) 
			value |= 0x04 ;
		if ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_DPAD_UP ) 
			value |= 0x01 ;
		if ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) 
			value |= 0x08 ;
		if ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) 
			value |= 0x02 ;
	}

	for ( int i = 0 ; i < 4 ; i++ )
	{
		if(g_Gamepads[i].hDevice )
		{
			if(g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_Y])
			{
				m_state = IN_GAME_PAUSED ;
				bAppActive = FALSE ;
				m_sound.pause( TRUE ) ;
				m_mp3player.pause( TRUE ) ;
				m_dwStartPause = GetTickCount();
				doCheatMenu() ;

				bAppActive = TRUE ;
				if ( m_state == MAIN_MENU )
				{
					bQuitProgram = TRUE ;
				}
			}


			if ( ( g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) && 
				 (g_Gamepads[i].bPressedAnalogButtons[XINPUT_GAMEPAD_WHITE]) )
			{
				bRestoreMemoryState = TRUE ;
			}
			else if ( ( g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) && 
				 (g_Gamepads[i].bPressedAnalogButtons[XINPUT_GAMEPAD_BLACK]) )
			{
				bSaveMemoryState = TRUE ;
			}


			vcode = validKeys[m_bMappingB].keynum ;
			stkey = Keymap_RemapWindowsKeyToSTScanCode2(vcode) ;

			if ( g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_B]) 
			{
				if ( keyboard_keystate[vcode]==0 )
				{
					IKBD_PressSTKey(stkey,TRUE);
					keyboard_keystate[vcode] = 1 ;
				}
			}
			else
			{
				if ( keyboard_keystate[vcode]==1 )
				{
					IKBD_PressSTKey(stkey,FALSE);
					keyboard_keystate[vcode] = 0 ;
				}
			}


			vcode = validKeys[m_bMappingX].keynum ;
			stkey = Keymap_RemapWindowsKeyToSTScanCode2(vcode) ;

			if ( g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_X]) 
			{
				if ( keyboard_keystate[vcode]==0 )
				{
					IKBD_PressSTKey(stkey,TRUE);
					keyboard_keystate[vcode] = 1 ;
				}
			}
			else
			{
				if ( keyboard_keystate[vcode]==1 )
				{
					IKBD_PressSTKey(stkey,FALSE);
					keyboard_keystate[vcode] = 0 ;
				}
			}

			vcode = validKeys[m_bMappingBLACK].keynum ;
			stkey = Keymap_RemapWindowsKeyToSTScanCode2(vcode) ;

			if ( g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_BLACK]) 
			{
				if ( keyboard_keystate[vcode]==0 )
				{
					IKBD_PressSTKey(stkey,TRUE);
					keyboard_keystate[vcode] = 1 ;
				}
			}
			else
			{
				if ( keyboard_keystate[vcode]==1 )
				{
					IKBD_PressSTKey(stkey,FALSE);
					keyboard_keystate[vcode] = 0 ;
				}
			}

			vcode = validKeys[m_bMappingWHITE].keynum ;
			stkey = Keymap_RemapWindowsKeyToSTScanCode2(vcode) ;

			if ( g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_WHITE]) 
			{
				if ( keyboard_keystate[vcode]==0 )
				{
					IKBD_PressSTKey(stkey,TRUE);
					keyboard_keystate[vcode] = 1 ;
				}
			}
			else
			{
				if ( keyboard_keystate[vcode]==1 )
				{
					IKBD_PressSTKey(stkey,FALSE);
					keyboard_keystate[vcode] = 0 ;
				}
			}



			vcode = validKeys[m_bMappingSTART].keynum ;
			stkey = Keymap_RemapWindowsKeyToSTScanCode2(vcode) ;

			if ( g_Gamepads[i].wButtons & XINPUT_GAMEPAD_START )  
			{
				if ( keyboard_keystate[vcode]==0 )
				{
					IKBD_PressSTKey(stkey,TRUE);
					keyboard_keystate[vcode] = 1 ;
				}
			}
			else
			{
				if ( keyboard_keystate[vcode]==1 )
				{
					IKBD_PressSTKey(stkey,FALSE);
					keyboard_keystate[vcode] = 0 ;
				}
			}

			vcode = validKeys[m_bMappingBACK].keynum ;
			stkey = Keymap_RemapWindowsKeyToSTScanCode2(vcode) ;

			if ( g_Gamepads[i].wButtons & XINPUT_GAMEPAD_BACK )  
			{
				if ( keyboard_keystate[vcode]==0 )
				{
					IKBD_PressSTKey(stkey,TRUE);
					keyboard_keystate[vcode] = 1 ;
				}
			}
			else
			{
				if ( keyboard_keystate[vcode]==1 )
				{
					IKBD_PressSTKey(stkey,FALSE);
					keyboard_keystate[vcode] = 0 ;
				}
			}




			KeyboardProcessor.Rel.X += g_Gamepads[i].fX1*8.5;
			KeyboardProcessor.Rel.Y -= g_Gamepads[i].fY1*8.5;


			if ( i==0)
			{
				if ( g_Gamepads[i].fX2 > 0.10 )
				{
					Keyboard.bRButtonDown |= BUTTON_MOUSE;	// Set button down flag
				}
				else
				{
					Keyboard.bRButtonDown &= ~BUTTON_MOUSE;
				}

				if ( g_Gamepads[i].fX2 < -0.10 )
				{
					Keyboard.bLButtonDown |= BUTTON_MOUSE;	// Set button down flag
				}
				else
				{
					Keyboard.bLButtonDown &= ~BUTTON_MOUSE;
				}
			}

		}



	
	}

	if ( ( g_Gamepads[0].hDevice && g_Gamepads[0].bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER]) ||
		 ( g_Gamepads[1].hDevice && g_Gamepads[1].bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER]) )
	{
		throttle = 1 ;

	}
	else
	{
		throttle = 0 ;
	}

	while( ERROR_SUCCESS == XInputDebugGetKeystroke( &keystroke ) )
	{
		stkey = (char)Keymap_RemapWindowsKeyToSTScanCode2(keystroke.VirtualKey) ;

		if ( stkey != -1 )
		{
			if ( keystroke.Flags & XINPUT_DEBUG_KEYSTROKE_FLAG_KEYUP )
			{
				if ( keyboard_keystate[keystroke.VirtualKey] )
				{
					sprintf(xmsg, "keyup %u,%u\r\n", keystroke.VirtualKey, stkey ) ;
					writexbox(xmsg) ;
					IKBD_PressSTKey(stkey,FALSE);
					keyboard_keystate[keystroke.VirtualKey] = 0 ;
				}
			}
			else
			{
				if ( keystroke.Flags & XINPUT_DEBUG_KEYSTROKE_FLAG_REPEAT )
				{
					if ( keyboard_keystate[keystroke.VirtualKey] == 1 )
					{
					//sprintf(xmsg, "keydown %u,%u port=%u\r\n", keystroke.VirtualKey, stkey,port ) ;
					//writexbox(xmsg) ;
						IKBD_PressSTKey(stkey,TRUE);
						keyboard_keystate[keystroke.VirtualKey] = 1 ;
					}
				}
				else
				{
					if ( !keyboard_keystate[keystroke.VirtualKey] )
					{
					sprintf(xmsg, "keydown %u,%u\r\n", keystroke.VirtualKey, stkey ) ;
					writexbox(xmsg) ;
						IKBD_PressSTKey(stkey,TRUE);
						keyboard_keystate[keystroke.VirtualKey] = 1 ;
					}
				}
			}
		}

	}


	return value ;
}

/*
int ReadJoypad( int port )
{

	int value ;
	char xmsg[100] ;


	value = 0 ;
#define	JOY_A		0x01
#define	JOY_B		0x02
#define	JOY_SELECT	0x04
#define	JOY_START	0x08
#define	JOY_UP		0x10
#define	JOY_RIGHT	0x20
#define	JOY_DOWN	0x40
#define	JOY_LEFT	0x80
#define JOY_AUTOI	0x100
#define JOY_AUTOII	0x200

	updateCheats() ;

	XBInput_GetInput();

	if ( g_Gamepads[port].hDevice )
	{

		if ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_A ] ) 
			value |= JOY_A ;
		if ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_X ] ) 
			value |= JOY_B ;
		if ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) 
			value |= JOY_LEFT ;
		if ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_DPAD_UP ) 
			value |= JOY_UP ;
		if ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) 
			value |= JOY_RIGHT ;
		if ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) 
			value |= JOY_DOWN ;
		if ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_START )  
			value |= JOY_START ;
		if ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_BACK )  
			value |= JOY_SELECT ;

		if ( g_Gamepads[port].bPressedAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER])
		{
			//bkgHalt = bkgHalt ^ 1 ;
		}

		if ( ( g_Gamepads[port].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) && 
			 (g_Gamepads[port].bPressedAnalogButtons[XINPUT_GAMEPAD_WHITE]) )
		{
			loadgame() ;
		}
		else if ( ( g_Gamepads[port].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) && 
			 (g_Gamepads[port].bPressedAnalogButtons[XINPUT_GAMEPAD_BLACK]) )
		{
			savegame() ;
		}

		//sprintf( xmsg, "x=%d,y=%d,x=%d,y=%d\r\n", g_Gamepads[port].sThumbRX, g_Gamepads[port].sThumbRX, g_Gamepads[port].fX2, g_Gamepads[port].fY2 ) ;

		if ( g_Gamepads[port].fX2 )
		{
			m_sound.adjust_volume( (int) ( g_Gamepads[port].fX2 * 25.0 ) ) ;
		}
		if ( g_Gamepads[port].fY2 )
		{
			m_mp3player.adjust_volume( (int) ( g_Gamepads[port].fY2 * 25.0 ) ) ;
		}
	
	}

	return value ;
}

*/




void CXBoxSample::initConsole( UINT32 idx, int forceUS, int whichCard )
{
	char                filename[500] ;
	char systemcard[200] ;

	global_error_message[0] = 0 ;

	m_numFrames = 0 ;
	m_droppedFrames = 0 ;
//	soundChannels = 0xFF ;
//	bkgHalt = 0 ;

	Keyboard_Init( 32, 400, 150 )  ;
	memset(keyboard_keystate, 0, 256 ) ;

	m_mousePosX = 0 ;
	m_mousePosY = 0 ;

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

	writexbox( "init1" ) ;

	//strcpy((char*)filename, "D:\\stdisks\\" ) ;
	strcpy((char*)filename, m_szCurrentDir ) ;
	//wcsrtombs( (char*)gfilename, (const wchar_t**)(&(files[idx].name)), 100, NULL ) ;
	strcat( (char*)filename, (const char*)files[idx].filename ) ;



	strcpy( g_cuefile, "" ) ;

	if (strstr (strupr(filename), ".MP3"))
	{
		if ( m_mp3player.loadFile( filename, 1, 0, 70*60*75 ) )
		{
			//writexbox( "nonomp3\r\n") ;
		}
		else
		{
			m_mp3player.insertSilence( 22050 ) ;
			m_mp3player.pause( FALSE ) ;
			m_state = MAIN_MENU ;
			return  ;
		}
	}

	char *p;


	//writexbox( "init1" ) ;

	strcpy( g_saveprefix, g_savePath ) ;
	strcat( g_saveprefix, "\\" ) ;
	strcat( g_saveprefix, strrchr( filename, '\\' )+1 ) ;
	//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");

	sprintf( g_statefile, "%s.sta", g_saveprefix ) ;

//	nonoise = 0 ;
	
	//writexbox( "init1" ) ;

	m_sound.init() ;
	//m_mp3player.init() ;

	//writexbox( "init1" ) ;
	cht_load() ;
	writexbox( "init1" ) ;

	// Create our texture
	init_texture();

	writexbox( "init1" ) ;

	// Create our sprite driver
	if ( Sprite == NULL )
		D3DXCreateSprite(m_pd3dDevice, &Sprite);
	
	//writexbox( "init1" ) ;





	m_fAppTime = 0.0f ;

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

	m_steps = 0 ;

	//writexbox( "init4" ) ;
	//Then start it up

	m_sound.insertSilence( 22050 ) ;
	m_sound.pause( FALSE ) ;
	//m_mp3player.insertSilence( 22050 ) ;
	//m_mp3player.pause( FALSE ) ;

	writexbox( "init5" ) ;
	bAppActive = TRUE ;
	winston_main(filename) ;
//	hugomain( filename, g_sramfile, g_saveprefix, systemcard, 0, forceUS ) ;

	//writexbox( "initout" ) ;
	m_state=MAIN_MENU ;
	cleanupConsole( ) ;

	//put 3 frames of data in the audio buffer
	//processEmu(FALSE) ;
	//processEmu(FALSE) ;
	//processEmu(FALSE) ;


}

void CXBoxSample::cleanupConsole( )
{
	//sram_save();
	//rtc_save();
	cht_save() ;


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


}



#ifdef __cplusplus
extern "C" {
#endif

unsigned int xbox_get_pitch() 
{
	return g_app->g_pitch ;
}

unsigned char* xbox_get_screenbuf()
{
	return (unsigned char*)g_app->g_pBlitBuff ;
}


char* xbox_get_statefile()
{
	return g_app->g_statefile ;
}

int xbox_read_input(int port) 
{
	//writexbox( "before readinput") ;
	//return g_app->ReadJoypad( port ) ;
	//writexbox( "after readinput") ;
	return 0 ;
}

int xbox_check_events( int id)
{
	//writexbox( "before events") ;
	return g_app->handleEvents(id) ;
	//writexbox( "after events") ;
	return 0 ;
}

void xbox_put_image()
{
	//writexbox( "before render") ;
	//g_sound->process() ;
	//g_mp3player->process() ;
	g_app->render_to_texture() ;
	//writexbox( "after render") ;
}

void xbox_process_audio( char *buf, int index, int length )
{
	g_sound->process( buf, index, length ) ;

}
void xbox_open_zip( char *hugozipfile )
{
	//writexbox( "before zip") ;
	//g_app->rom_load_zip( hugozipfile ) ;
	//writexbox( "after zip") ;
}

#ifdef __cplusplus
}
#endif

void CXBoxSample::processEmu( BOOL render )
{
			
//			handleEvents();
			updateCheats() ;


//			doneFrame = 0 ;

			//m_nbytes = update_sound_main() ;



			if ( render )
			{
				render_to_texture();
				m_numFrames++ ;
			}


//			m_droppedFrames += m_sound.process( (byte**)sbuf, m_nbytes, soundChannels ) ;

			while ( m_sound.m_bDanger )
			{
//				handleEvents();
				updateCheats() ;
//				doneFrame = 0 ;
				//m_nbytes = update_sound_main() ;


				//m_droppedFrames += m_sound.process( (byte**)sbuf, m_nbytes, soundChannels ) ;
			}



}


int CXBoxSample::rom_load_zip( char *hugozipfile )
{
	byte *data ;
	int len = 0;

    unzFile file = unzOpen(hugozipfile);

    if(file == NULL)
		return 0 ;


    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) ;
		return 0 ;
    }

    unzLocateFile(file,filename,1);
    unzGetCurrentFileInfo(file, &info, filename,128, NULL,0, NULL,0);
    
    if( unzOpenCurrentFile(file) != UNZ_OK )
    {
		unzClose(file);
		return 0 ;
    }


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


	int l = unzReadCurrentFile(file,data,info.uncompressed_size);
	if(unzCloseCurrentFile(file) == UNZ_CRCERROR)
	{
		free(data) ;
	    unzClose(file);
		return 0 ;
	}

    unzClose(file);


	filesize = info.uncompressed_size ;
	filesize &= ~0x1fff;  //524288  524800


	free(data) ;


	return 1;
}

