#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 "cstring.h"
#include "carray.h"

#include "src\Gens\io.h"
#include "src\Gens\vdp_io.h"
#include "src\Gens\blit.h"
#include "src\Gens\save.h"
#include "src\Gens\Mem_M68k.h" 
#include "src\Gens\cd_sys.h"

extern int Gens_Running ;

//const CString EMPTY_ANNOUNCER_NAME = "Empty"  ;
//CMap<int,int,int,int> mapDanceNoteToNoteDataColumn;
//CStringArray asPackagePaths;
//CRect rect(1,1,1,1) ;
//CToken tok( "yayaya", "a" ) ;
//CFixedAlloc fixaloc(1024) ;
//CPlex* newBlock = CPlex::Create(m_pBlocks, m_nBlockSize, sizeof(CMap::CAssoc));

int PASCAL gensmain( char *romfilename, int country, int whichCD, int realCD );

#ifdef __cplusplus
extern "C" {
#endif

int throttle ;
int loaded_cue ;
int blittermode ;
int changedblit ;
int multiport =0;
int sleepamount ;

#ifdef __cplusplus
}
#endif

#include "undocumented.h"
#include "iosupport.h"
#include "CDDAXbox.h"


#define PLATFORM_SAV L"SGENSAV"
#define READING_ROMS_STRING L"Reading sgenroms directory...please wait."
#define PLATFORM_INI "sgen2.ini"
#define PLATFORM_SPEC_INI "sgenspec.ini"
#define PLATFORM_MEMORY_POINTER Ram_68k
#define THEMEMUSIC "D:\\SGENROMS\\SGENTHEME.MP3"
#define PLATFORM_FILE_DIR "D:\\sgenroms\\*"
#define CONSOLE_MEMORY_SIZE 0x10000
#define DEFAULT_PARENT_DIR "D:\\sgenroms\\"

//-----------------------------------------------------------------------------
// 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() ;
	virtual int     init_texture() ;
	virtual int		init_white_texture();
	virtual int		render_to_texture() ;
	virtual void	FindAvailRoms( char *parentdir ) ;
	virtual void    loadCueSheet( char *cuefile ) ;
	virtual void    doStartSearchMenu() ;
	virtual void    doCodeListMenu() ;
	virtual BOOL    SetRefreshRate(INT iRefreshRate);
	virtual void    doCDGame() ;
	virtual void    doEmulatorOptions();
	virtual void    doAddFoundCodes() ;
	virtual void    doLoadNewDisk();
	virtual void    doContinueSearchMenu() ;
	virtual void    doCheatMenu() ;
	virtual void    fillPresentationParams() ;
	virtual void    doFontSize() ;
	virtual void    doSaveConfig() ;
	virtual void    doScreenSize() ;
	virtual void    doTextOffset() ;
	virtual void    doConfiguration() ;
	virtual void    updateCheats() ;
	virtual void	saveKeys( char *keyfile ) ;
	virtual void	loadKeys( char *keyfile ) ;
	virtual void    processEmu( BOOL render ) ;
	virtual void    cht_load() ;
	virtual int     getButtonState( int port, int mapping);
	virtual int     getButtonValue( int port, int mapping);
	virtual void    cht_save() ;
	virtual void    deleteSaveFiles( int which ) ;
	virtual void    doEditCode( 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   nb_max_track ;
	CIoSupport m_io ;
	HANDLE m_hCdrom ;


	UINT32 topIdx  ;
	UINT32 curr  ;
	CDebugClient m_debugClient ;
	D3DPalette			*m_pd3dPalette ;

    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 ;


typedef struct
    {
     unsigned char beg_min;
     unsigned char beg_sec;
     unsigned char beg_fra;

     unsigned char type;

     unsigned int beg_lsn;
     unsigned int length;

     char filename[256];


     } Track;

	Track CD_track[0x100];

	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 ;
	char    m_szCurrentDir[MAX_PATH] ;

	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_keysfile[500] ;
	char				g_bramfile[500] ;
	char				g_cuefile[500] ;
	char				g_rtcfile[500] ;
	char				g_chtfile[500] ;
	char				g_statefile[500] ;
	FILE                *m_logfile ;
	CDDAXbox			m_cdda;
	D3DPRESENT_PARAMETERS m_origPP ;




// 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 ;

	int m_bMappingA ;
	int m_bMappingB ;
	int m_bMappingC ;
	int m_bMappingX ;
	int m_bMappingY ;
	int m_bMappingZ ;
	int m_bMappingSTART ;
	int m_bMappingMODE ;
	int m_bMappingThrottle ;



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

	CHEAT_CODE *m_cheatCodes;

	UINT32 m_numCheats ;


};

CDDAXbox  *g_cdda ;

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

struct { char *keyname ; int keynum ; } validKeys[10] = 
{
	{ "XBOX A", 0 },
	{ "XBOX B", 1 },
	{ "XBOX X", 2 },
	{ "XBOX Y", 3 },
	{ "XBOX BLACK", 4 },
	{ "XBOX WHITE", 5 },
	{ "XBOX START", 6 },
	{ "XBOX BACK", 7 },
	{ "XBOX LTRIGGER", 8 },
	{ "XBOX RTRIGGER", 9 },
};

struct blitters
{
	void (*blitfunc)(unsigned char *Dest, int pitch, int x, int y, int offset ) ;
	int multiplier ;
	WCHAR name[100] ;
} BLITTERS[] = 
{
	{ Blit_X1_MMX, 0, L"Normal" },
	{ Blit_2xSAI_MMX, 1, L"2xSai"},
	{ Blit_Scanline_MMX, 1, L"Scanline" },
	{ Blit_Scanline_Int_MMX, 1, L"Scanline Interpolated" },
	{ Blit_Scanline_50_MMX, 1, L"Scanline 50" },
	{ Blit_Scanline_50_Int_MMX, 1,L"Scanline 50 Interpolated" },
	{ Blit_Scanline_25_MMX, 1, L"Scanline 25" },
	{ Blit_Scanline_25_Int_MMX, 1, L"Scanline 25 Interpolated" }
} ;




unsigned long TAB_CONST2[256] = {
   0X0,
   0X77073096,
   0XEE0E612C,
   0X990951BA,
   0X76DC419,
   0X706AF48F,
   0XE963A535,
   0X9E6495A3,
   0XEDB8832,
   0X79DCB8A4,
   0XE0D5E91E,
   0X97D2D988,
   0X9B64C2B,
   0X7EB17CBD,
   0XE7B82D07,
   0X90BF1D91,
   0X1DB71064,
   0X6AB020F2,
   0XF3B97148,
   0X84BE41DE,
   0X1ADAD47D,
   0X6DDDE4EB,
   0XF4D4B551,
   0X83D385C7,
   0X136C9856,
   0X646BA8C0,
   0XFD62F97A,
   0X8A65C9EC,
   0X14015C4F,
   0X63066CD9,
   0XFA0F3D63,
   0X8D080DF5,
   0X3B6E20C8,
   0X4C69105E,
   0XD56041E4,
   0XA2677172,
   0X3C03E4D1,
   0X4B04D447,
   0XD20D85FD,
   0XA50AB56B,
   0X35B5A8FA,
   0X42B2986C,
   0XDBBBC9D6,
   0XACBCF940,
   0X32D86CE3,
   0X45DF5C75,
   0XDCD60DCF,
   0XABD13D59,
   0X26D930AC,
   0X51DE003A,
   0XC8D75180,
   0XBFD06116,
   0X21B4F4B5,
   0X56B3C423,
   0XCFBA9599,
   0XB8BDA50F,
   0X2802B89E,
   0X5F058808,
   0XC60CD9B2,
   0XB10BE924,
   0X2F6F7C87,
   0X58684C11,
   0XC1611DAB,
   0XB6662D3D,
   0X76DC4190,
   0X1DB7106,
   0X98D220BC,
   0XEFD5102A,
   0X71B18589,
   0X6B6B51F,
   0X9FBFE4A5,
   0XE8B8D433,
   0X7807C9A2,
   0XF00F934,
   0X9609A88E,
   0XE10E9818,
   0X7F6A0DBB,
   0X86D3D2D,
   0X91646C97,
   0XE6635C01,
   0X6B6B51F4,
   0X1C6C6162,
   0X856530D8,
   0XF262004E,
   0X6C0695ED,
   0X1B01A57B,
   0X8208F4C1,
   0XF50FC457,
   0X65B0D9C6,
   0X12B7E950,
   0X8BBEB8EA,
   0XFCB9887C,
   0X62DD1DDF,
   0X15DA2D49,
   0X8CD37CF3,
   0XFBD44C65,
   0X4DB26158,
   0X3AB551CE,
   0XA3BC0074,
   0XD4BB30E2,
   0X4ADFA541,
   0X3DD895D7,
   0XA4D1C46D,
   0XD3D6F4FB,
   0X4369E96A,
   0X346ED9FC,
   0XAD678846,
   0XDA60B8D0,
   0X44042D73,
   0X33031DE5,
   0XAA0A4C5F,
   0XDD0D7CC9,
   0X5005713C,
   0X270241AA,
   0XBE0B1010,
   0XC90C2086,
   0X5768B525,
   0X206F85B3,
   0XB966D409,
   0XCE61E49F,
   0X5EDEF90E,
   0X29D9C998,
   0XB0D09822,
   0XC7D7A8B4,
   0X59B33D17,
   0X2EB40D81,
   0XB7BD5C3B,
   0XC0BA6CAD,
   0XEDB88320,
   0X9ABFB3B6,
   0X3B6E20C,
   0X74B1D29A,
   0XEAD54739,
   0X9DD277AF,
   0X4DB2615,
   0X73DC1683,
   0XE3630B12,
   0X94643B84,
   0XD6D6A3E,
   0X7A6A5AA8,
   0XE40ECF0B,
   0X9309FF9D,
   0XA00AE27,
   0X7D079EB1,
   0XF00F9344,
   0X8708A3D2,
   0X1E01F268,
   0X6906C2FE,
   0XF762575D,
   0X806567CB,
   0X196C3671,
   0X6E6B06E7,
   0XFED41B76,
   0X89D32BE0,
   0X10DA7A5A,
   0X67DD4ACC,
   0XF9B9DF6F,
   0X8EBEEFF9,
   0X17B7BE43,
   0X60B08ED5,
   0XD6D6A3E8,
   0XA1D1937E,
   0X38D8C2C4,
   0X4FDFF252,
   0XD1BB67F1,
   0XA6BC5767,
   0X3FB506DD,
   0X48B2364B,
   0XD80D2BDA,
   0XAF0A1B4C,
   0X36034AF6,
   0X41047A60,
   0XDF60EFC3,
   0XA867DF55,
   0X316E8EEF,
   0X4669BE79,
   0XCB61B38C,
   0XBC66831A,
   0X256FD2A0,
   0X5268E236,
   0XCC0C7795,
   0XBB0B4703,
   0X220216B9,
   0X5505262F,
   0XC5BA3BBE,
   0XB2BD0B28,
   0X2BB45A92,
   0X5CB36A04,
   0XC2D7FFA7,
   0XB5D0CF31,
   0X2CD99E8B,
   0X5BDEAE1D,
   0X9B64C2B0,
   0XEC63F226,
   0X756AA39C,
   0X26D930A,
   0X9C0906A9,
   0XEB0E363F,
   0X72076785,
   0X5005713,
   0X95BF4A82,
   0XE2B87A14,
   0X7BB12BAE,
   0XCB61B38,
   0X92D28E9B,
   0XE5D5BE0D,
   0X7CDCEFB7,
   0XBDBDF21,
   0X86D3D2D4,
   0XF1D4E242,
   0X68DDB3F8,
   0X1FDA836E,
   0X81BE16CD,
   0XF6B9265B,
   0X6FB077E1,
   0X18B74777,
   0X88085AE6,
   0XFF0F6A70,
   0X66063BCA,
   0X11010B5C,
   0X8F659EFF,
   0XF862AE69,
   0X616BFFD3,
   0X166CCF45,
   0XA00AE278,
   0XD70DD2EE,
   0X4E048354,
   0X3903B3C2,
   0XA7672661,
   0XD06016F7,
   0X4969474D,
   0X3E6E77DB,
   0XAED16A4A,
   0XD9D65ADC,
   0X40DF0B66,
   0X37D83BF0,
   0XA9BCAE53,
   0XDEBB9EC5,
   0X47B2CF7F,
   0X30B5FFE9,
   0XBDBDF21C,
   0XCABAC28A,
   0X53B39330,
   0X24B4A3A6,
   0XBAD03605,
   0XCDD70693,
   0X54DE5729,
   0X23D967BF,
   0XB3667A2E,
   0XC4614AB8,
   0X5D681B02,
   0X2A6F2B94,
   0XB40BBE37,
   0XC30C8EA1,
   0X5A05DF1B,
   0X2D02EF8D
};



#define METHOD_BUFFERED                   0
#define METHOD_OUT_DIRECT     2
//#define FILE_READ_ACCESS                  0x00000001
#define FILE_DEVICE_CD_ROM                0x00000002

#define IOCTL_CDROM_BASE                FILE_DEVICE_CD_ROM
//#define CTL_CODE(DeviceType,Function,Method,Access) (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))

#define IOCTL_CDROM_READ_TOC         CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
//#define IOCTL_CDROM_RAW_READ         CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT,  FILE_READ_ACCESS)
#define IOCTL_CDROM_COOKED_READ         CTL_CODE(IOCTL_CDROM_BASE, 0x0010, METHOD_OUT_DIRECT,  FILE_READ_ACCESS)
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY  CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)

#define PACKED

#pragma pack(1)

typedef struct
{
  BYTE rsvd;
  BYTE ADR;
  BYTE trackNumber;
  BYTE rsvd2;
  BYTE addr[4];
}
PACKED TOCTRACK;

typedef struct
{
  WORD tocLen;
  BYTE firstTrack;
  BYTE lastTrack;
  TOCTRACK tracks[100];
}
PACKED TOC, *PTOC, FAR * LPTOC;





#define CD_SECS 60
#define CD_FRAMES 75


void CXBoxSample::doCDGame()
{
	int fResult ;
	TOC toc;
	char xmsg[100] ;
	int sectorA, sectorB ;
	int menuChoice = 0 ;
	int  whichCard ;
	int bdone ;
	int country, whichCD, realCD ;
	WCHAR linemsg[200] ;
	char *countries[] = { "Auto-detect", "USA", "Japan", "Europe", "Other" } ;


	country = 0 ;
	whichCD = 0 ;
	realCD = 0 ;
	bdone = 0 ;


	while ( !bdone )
	{
		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"CD Menu" );
		swprintf( linemsg, L"Country : %S", countries[country] ) ;
		m_Font.DrawText( m_nXOffset+  32, 16*6, menuChoice==0 ? 0xff000000 : 0xffffffff, linemsg );
		swprintf( linemsg, L"Play %S as above country in regular CD mode", files[curr].filename ) ;
		m_Font.DrawText( m_nXOffset+  32, 16*7, menuChoice==1 ? 0xff000000 : 0xffffffff, linemsg );
		swprintf( linemsg, L"Play %S as above country in alternate CD mode", files[curr].filename ) ;
		m_Font.DrawText( m_nXOffset+  32, 16*8, menuChoice==2 ? 0xff000000 : 0xffffffff, linemsg );
		m_Font.DrawText( m_nXOffset+  32, 16*9, menuChoice==3 ? 0xff000000 : 0xffffffff, L"Load CD as above country in regular CD mode" );
		m_Font.DrawText( m_nXOffset+  32, 16*10, menuChoice==4 ? 0xff000000 : 0xffffffff, L"Load CD as above country in alternate CD mode" );
		m_Font.DrawText( m_nXOffset+  32, 16*11, menuChoice==5 ? 0xff000000 : 0xffffffff, L"Eject CD Tray (reboots XBox if Gens was not loaded from DVD/CDRW)" );
		m_Font.DrawText( m_nXOffset+  32, 16*12, menuChoice==6 ? 0xff000000 : 0xffffffff, L"Close CD Tray" );
		m_Font.DrawText( m_nXOffset+  32, 16*14, 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])
		{
	        XBInput_GetInput();
			return  ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN )
		{
			menuChoice = (menuChoice+1)%7 ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_UP )
		{
			if ( menuChoice == 0 )
				menuChoice = 6 ;
			else
				menuChoice-- ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_A])
		{
			switch ( menuChoice )
			{
				case 0 : country = (country+1)%5 ; break ;
				case 1 :
				{
					if ( files[curr].isDir ) 
						return ; 
					else
					{
						whichCD = 0 ; 
						realCD = 0 ;
						bdone = 1 ;
					}
					break ;
				}
				case 2 :
				{
					if ( files[curr].isDir ) 
						return ; 
					else
					{
						whichCD = 1 ; 
						realCD = 0 ;
						bdone = 1 ;
					}
					break ;
				}
				case 3 :
				{
					whichCD = 0 ; 
					realCD = 1 ;
					bdone = 1 ;
					break ;
				}
				case 4 :
				{
					whichCD = 1 ; 
					realCD = 1 ;
					bdone = 1 ;
					break ;
				}
				case 5 : m_io.EjectTray() ; break ;
				case 6 : m_io.CloseTray() ; break ;
				default : break ;
			}
		}


	}




	switch( country )
	{
		case 0 : country = -1 ; break ;
		case 1 : country = 1 ;break ;
		case 2 : country = 0 ;break ;
		case 3 : country = 2 ;break ;
		case 4 : country = 3 ;break ;
		default : country = -1 ; break ;
	}


	if ( realCD == 0 )
	{
		initConsole(curr, country, whichCD) ;
		return ;
	}




	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"Attempting to load CD game...please wait." ) ;
	m_Font.End();
	m_pd3dDevice->Present( NULL, NULL, NULL, NULL );


//use flags to turn off eject thingy - xbox image -> project options
	//    /TestMediaTypes:0x80000007 


	ANSI_STRING filename;
	OBJECT_ATTRIBUTES attributes;
	IO_STATUS_BLOCK status;
	HANDLE hDevice;
	NTSTATUS error;
	DWORD dummy;
	DWORD byteCount ;

	RtlInitAnsiString(&filename, "\\Device\\Cdrom0" );

	InitializeObjectAttributes(&attributes, &filename, OBJ_CASE_INSENSITIVE, NULL);

	if (NT_SUCCESS(error = NtCreateFile(&m_hCdrom, GENERIC_READ |
		SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attributes, &status, NULL, 0,
		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN,
		FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT)))
	{
	}
	else
	{
		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+  32, 16*5, 0xffffffff, L"Could not access CD - aborting." ) ;
		m_Font.End();
		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
		Sleep(2000) ;
		return ;
	}



	if ( m_hCdrom == INVALID_HANDLE_VALUE )
	{
		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+  32, 16*5, 0xffffffff, L"Could not access CD - aborting." ) ;
		m_Font.End();
		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
		Sleep(2000) ;
		return ;
	}

	if ( ! DeviceIoControl(m_hCdrom, IOCTL_CDROM_READ_TOC, NULL, 0,	&toc, sizeof(TOC), &byteCount, NULL ) )
	{
		CloseHandle( m_hCdrom ) ;
		m_Font.Begin();
		m_Font.DrawText( m_nXOffset+  32, 16*5, 0xffffffff, L"Could not read TOC from CD - aborting." ) ;
		m_Font.End();
		m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
		Sleep(2000) ;
		return  ;
	}

	nb_max_track = toc.lastTrack ;
	memset( CD_track, 0, sizeof(CD_track) ) ;




	SCD.TOC.First_Track = toc.firstTrack;
	SCD.TOC.Last_Track = toc.lastTrack;

	unsigned char numTracks = toc.lastTrack - toc.firstTrack + 1;
	TOCTRACK *t;

	for(int i = 0; i < numTracks; i++)
	{
		t = &(toc.tracks[i]);

		SCD.TOC.Tracks[i].Num = t->trackNumber;
		SCD.TOC.Tracks[i].Type = (t->ADR & 0x04) >> 2;		// DATA flag

		SCD.TOC.Tracks[i].MSF.M = t->addr[1];
		SCD.TOC.Tracks[i].MSF.S = t->addr[2];
		SCD.TOC.Tracks[i].MSF.F = t->addr[3];

	}

	SCD.TOC.Tracks[numTracks].Num = toc.tracks[numTracks].trackNumber;
	SCD.TOC.Tracks[numTracks].Type = 0;

	SCD.TOC.Tracks[numTracks].MSF.M = toc.tracks[numTracks].addr[1];
	SCD.TOC.Tracks[numTracks].MSF.S = toc.tracks[numTracks].addr[2];
	SCD.TOC.Tracks[numTracks].MSF.F = toc.tracks[numTracks].addr[3];




	for ( int i = toc.firstTrack; i <= toc.lastTrack; i++)
	{
		int val = 	( toc.tracks[i-1].addr[1] * 60 * 75 ) + 
					( toc.tracks[i-1].addr[2] * 75 ) +
					( toc.tracks[i-1].addr[3]  ) ;
		int frms, mins, secs ;

		mins = toc.tracks[i-1].addr[1] ;
		secs = toc.tracks[i-1].addr[2] ;
		frms = toc.tracks[i-1].addr[3] ;

		/*
		if ( secs < 2 )  //account for standard gap that seems to appear on all cue sheets
		{
			secs = 60 - secs ;
			mins-- ;
		}
		else
		{
			secs -= 2 ;
		}
*/

		CD_track[i].beg_min = mins ;
		CD_track[i].beg_sec = secs ;
		CD_track[i].beg_fra = frms ;
		CD_track[i].type = (((TOCTRACK)(toc.tracks[i-1])).ADR ) & 0x0F ;
		strcpy( CD_track[i].filename, "D:\\blank" ) ;



		sprintf( xmsg, "track #%u, type=%s, size=%u\r\n", i, CD_track[i].type ? "data" : "audio", val ) ;
		writexbox(xmsg) ;

	}




	for ( int i = 1 ; i <= nb_max_track ; i++ )
	{

		if ( i == nb_max_track )
		{
			sectorB = 73 * CD_SECS * CD_FRAMES ; 
	
			sectorA = ( CD_track[i].beg_min * CD_SECS * CD_FRAMES ) +
					  ( CD_track[i].beg_sec * CD_FRAMES ) +
					  ( CD_track[i].beg_fra  )  ;
	
			CD_track[i].length = sectorB - sectorA ;
		}
		else
		{
			sectorB = ( CD_track[i+1].beg_min * CD_SECS * CD_FRAMES ) +
					  ( CD_track[i+1].beg_sec * CD_FRAMES ) +
					  ( CD_track[i+1].beg_fra  )  ;
	
			sectorA = ( CD_track[i].beg_min * CD_SECS * CD_FRAMES ) +
					  ( CD_track[i].beg_sec * CD_FRAMES ) +
					  ( CD_track[i].beg_fra  )  ;
	
			CD_track[i].length = sectorB - sectorA ;
		}

	}



	unsigned char tmp_data[2048*2] ;
	unsigned int CRC ;

	CRC = -1 ;

	sectorA = ( CD_track[1].beg_min * CD_SECS * CD_FRAMES ) +
			  ( CD_track[1].beg_sec * CD_FRAMES ) +
			  ( CD_track[1].beg_fra  )  ;

	m_io.ReadSector( m_hCdrom, sectorA+1, (LPSTR)tmp_data ) ;

	for (int index = 0; index < 2048; index++)
	{
		tmp_data[index] ^= CRC;
		CRC >>= 8;
		CRC ^= TAB_CONST2[tmp_data[index]];
	}
	CRC = ~CRC;


	
	m_state = IN_GAME ;

	

	





	char cd_filename[500] ;

	global_error_message[0] = 0 ;

	m_numFrames = 0 ;
	m_droppedFrames = 0 ;


	sleepamount = 0 ;
	throttle = 0 ;
	blittermode = 1 ;

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

	nb_max_track = 0 ;


	sprintf( cd_filename, "D:\\SGENROMS\\%02.2X%02.2X%02.2X%02.2X.IMG", (CRC>>24)&0xFF, (CRC>>16)&0xFF, (CRC>>8)&0xFF, CRC&0xFF ) ;

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


	loaded_cue = 0 ;


	char *p;


	//writexbox( "init1" ) ;

	strcpy( g_saveprefix, g_savePath ) ;
	strcat( g_saveprefix, "\\" ) ;
	strcat( g_saveprefix, strrchr( cd_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, ".srm");

	strcpy(g_keysfile, g_saveprefix);
	strcat(g_keysfile, ".key");

	strcpy(g_bramfile, g_saveprefix);
	strcat(g_bramfile, ".brm");

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

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

	loadKeys( g_keysfile ) ;

//	nonoise = 0 ;
	

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

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

	// Create our texture
	init_texture();


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





	m_fAppTime = 0.0f ;

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

	m_steps = 0 ;

	m_sound.pause( FALSE ) ;
	m_cdda.pause( FALSE ) ;

	gensmain(cd_filename,country,whichCD,1) ;

	m_state=MAIN_MENU ;
	saveKeys( g_keysfile ) ;
	cleanupConsole() ;






	//last thing after finishing game
	CloseHandle( m_hCdrom ) ;
	m_hCdrom = INVALID_HANDLE_VALUE ;






	


}







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

	// Create the 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);

	// 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::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 - Configuration" );
		m_Font.DrawText( (float)m_nXOffset+  32, 16*10, 0xffffffff, L"WHITE - Change Sega CD" );


		m_Font.End();

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

        XBInput_GetInput();
		if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_B])
		{
			while(g_Gamepads[0].hDevice && g_Gamepads[0].bAnalogButtons[XINPUT_GAMEPAD_B])
				XBInput_GetInput();
			m_sound.pause( FALSE ) ;
			m_mp3player.pause( FALSE ) ;
			m_cdda.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_cdda.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])
		{
			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() ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_X])
		{
			doConfiguration() ;
		}
		else if(g_Gamepads[0].hDevice && g_Gamepads[0].bPressedAnalogButtons[XINPUT_GAMEPAD_WHITE])
		{
			doLoadNewDisk() ;
		}


	}

}




void CXBoxSample::doLoadNewDisk()
{
	WCHAR str[2000];
	swprintf( str, L"GENS for XBOX  B-Abort  Found %u games", numfiles);

	if ( !SegaCD_Started )
	{
		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 are not currently playing a Sega CD game." );
			m_Font.DrawText( (float)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])
			{
				return ;
			}
		}
	}
	else
	{

		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 ] ) 
			{
				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
				{
					char                filename[500] ;

					nb_max_track = 0 ;

					strcpy((char*)filename, m_szCurrentDir ) ;
					strcat( (char*)filename, (const char*)files[curr].filename ) ;


					loaded_cue = 0 ;

					memset( CD_track, 0, sizeof(CD_track) ) ;


					strcpy( g_cuefile, "" ) ;

					if (strstr (strupr(filename), ".CUE"))
					{
						writexbox( "processing cue\r\n" ) ;

						strcpy( g_cuefile, filename ) ;
						loadCueSheet( g_cuefile ) ;
						filename[0] = 0 ;

						for ( int i = 0 ; i < nb_max_track ; i++ )
						{
							if ( CD_track[i].type == 4 )
							{
								strcpy( filename, CD_track[i].filename ) ;
								break ;
							}
						}


						if ( filename[0] != 0 )
						{
							loaded_cue = 1 ;
						}

					}


					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, ".srm");

					strcpy(g_keysfile, g_saveprefix);
					strcat(g_keysfile, ".key");

					strcpy(g_bramfile, g_saveprefix);
					strcat(g_bramfile, ".brm");

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

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

					Change_CD( filename ) ;
				}
				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.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, -1, 0) ;
				}
				return S_OK ;
			}
			else if(m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_X])
			{
				if ( files[curr].isDir )
				{
				}
				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.bPressedAnalogButtons[XINPUT_GAMEPAD_B])
			{
				if ( files[curr].isDir )
				{
				}
				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, 1, 0) ;
				}
				return S_OK ;
			}
			else if(m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_BLACK])
			{
				if ( files[curr].isDir )
				{
				}
				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, 2, 0) ;
				}
				return S_OK ;
			}
			else if(m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_WHITE])
			{
				if ( files[curr].isDir )
				{
				}
				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, 3, 0) ;
				}
				return S_OK ;
			}
			else if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_LEFT_THUMB )
			{
				doConfiguration() ;
				return S_OK ;
			}
			else if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_BACK  )
			{
				m_mp3player.stop() ;
				return S_OK ;
			}
			else if(m_DefaultGamepad.wPressedButtons & XINPUT_GAMEPAD_RIGHT_THUMB )
			{
				doCDGame();
				return S_OK ;
			}
		}
	}
	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 ;
	int Dep ;
	
	// 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);
	
	if ((VDP_Reg.Set4 & 0x1) )
	{
		//width = 320 ;
		Dep = 0;
	}
	else
	{
		//width = 256
		Dep = 64;
	}
	
	// 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 = (VDP_Num_Vis_Lines<<BLITTERS[blittermode].multiplier)  - 1 ;
	rectSource.right  = ((320-Dep) << BLITTERS[blittermode].multiplier ) - 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) ;

//Blit_Scanline_MMX(unsigned char *Dest, int pitch, int x, int y, int offset);
//Blit_Scanline_Int_MMX(unsigned char *Dest, int pitch, int x, int y, int offset);
//Blit_Scanline_50_MMX(unsigned char *Dest, int pitch, int x, int y, int offset);
//Blit_Scanline_50_Int_MMX(unsigned char *Dest, int pitch, int x, int y, int offset);
//Blit_Scanline_25_MMX(unsigned char *Dest, int pitch, int x, int y, int offset);
//Blit_Scanline_25_Int_MMX(unsigned char *Dest, int pitch, int x, int y, int offset);


	BLITTERS[blittermode].blitfunc(g_pBlitBuff, d3dlr.Pitch, 320-Dep, VDP_Num_Vis_Lines, 32 + Dep * 2 ) ;

	
	//if ( saimode )
		//Blit_2xSAI_MMX(g_pBlitBuff, d3dlr.Pitch, 320-Dep, VDP_Num_Vis_Lines, 32 + Dep * 2 ) ;
	//else
		//Blit_X1_MMX( g_pBlitBuff, d3dlr.Pitch, 320-Dep, VDP_Num_Vis_Lines, 32 + Dep * 2 ) ;


	//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)(((320-Dep) << BLITTERS[blittermode].multiplier ) - 1)) ;
	my = (float)m_nScreenMaxY / ((float)((VDP_Num_Vis_Lines<<BLITTERS[blittermode].multiplier)  - 1));

	// 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();
	
	if ( changedblit )
	{
		changedblit-- ;
		m_Font.Begin();
		//swprintf( str, L"%S", global_error_message );
		//m_Font.DrawText( 32, 48, 0x40ffffff, str );
		m_Font.DrawText( (float)m_nXOffset+ 32, 32, 0xffffffff, BLITTERS[blittermode].name );
		m_Font.End();

	}
	// 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"GENS for XBOX by XPort");
			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/B/X/BLACK/WHITE - Play Selected Game");
			m_Font.DrawText( (float)m_nXOffset+32, 16*7,  0xffffffff, L"  A=Auto,B=USA,X=JAP,BLK=EUE,WHT=Other");
			m_Font.DrawText( (float)m_nXOffset+32, 16*8,  0xffffffff, L"Y - Show This Help Screen");
			m_Font.DrawText( (float)m_nXOffset+32, 16*9,  0xffffffff, L"UP/DOWN - Select Game");
			m_Font.DrawText( (float)m_nXOffset+32, 16*10,  0xffffffff, L"RIGHT/LEFT - Next/Prev Page");
			m_Font.DrawText( (float)m_nXOffset+32, 16*11,  0xffffffff, L"LS/RS - Next/Prev Letter");
			m_Font.DrawText( (float)m_nXOffset+32, 16*12,  0xffffffff, L"START+BACK+LS+RS - Exit to dashboard");
			m_Font.DrawText( (float)m_nXOffset+32, 16*13,  0xffffffff, L"X+B - Reload list");
			m_Font.DrawText( (float)m_nXOffset+32, 16*14,  0xffffffff, L"BACK - Stop MP3");
			m_Font.DrawText( (float)m_nXOffset+32, 16*15,  0xffffffff, L"LTHUMB - Press for configutation menu");
			m_Font.DrawText( (float)m_nXOffset+32, 16*16,  0xffffffff, L"RTHUMB - Press for CD menu");
			m_Font.DrawText( (float)m_nXOffset+32, 16*17,  0xff00ff00, L"Lines colored like this have save files on the HD.");

			m_Font.DrawText( (float)m_nXOffset+32, 16*18, 0xffffffff, L"In-Game Controls");
			m_Font.DrawText( (float)m_nXOffset+32, 16*19, 0xffffffff, L"A/B/X/Y/WHT/BLK/START/BACK - Remappable");
			m_Font.DrawText( (float)m_nXOffset+32, 16*20, 0xffffffff, L"DPAD/LTHUMB - Joystick Movement");
			m_Font.DrawText( (float)m_nXOffset+32, 16*21, 0xffffffff, L"LTHUMB - Press to toggle 2xSai");
			m_Font.DrawText( (float)m_nXOffset+32, 16*22, 0xffffffff, L"RTHUMB - Press for options menu");
			m_Font.DrawText( (float)m_nXOffset+32, 16*23, 0xffffffff, L"RTHUMB - U/D/L/R - SFX/MP3 volume");
			m_Font.DrawText( (float)m_nXOffset+32, 16*24, 0xffffffff, L"LS+BLACK - Save State");
			m_Font.DrawText( (float)m_nXOffset+32, 16*25, 0xffffffff, L"LS+WHITE - Load State");
			m_Font.DrawText( (float)m_nXOffset+32, 16*26, 0xffffffff, L"RTRIGGER - Speed Up");
			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"GENS for XBOX - made by XPort");
			m_Font.End();
		}
		else
		{
			WCHAR str[2000];
			swprintf( str, L"GENS 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 )
	{

		m_hCdrom = INVALID_HANDLE_VALUE ;

	    if( FAILED( DirectSoundCreate( NULL, &(m_cdda.dsound),  NULL ) ) )
			return E_FAIL;
		
		m_cdda.dsound_init() ;
		m_cdda.m_fps = m_d3dpp.FullScreen_RefreshRateInHz ;

		g_cdda = &m_cdda ;
		
		InitializeWithScreen() ;


		m_bMappingA = 0 ;
		m_bMappingB = 1 ;
		m_bMappingC = 4 ;
		m_bMappingX = 2 ;
		m_bMappingY = 3 ;
		m_bMappingZ = 5 ;
		m_bMappingSTART = 6 ;
		m_bMappingMODE = 7 ;
		m_bMappingThrottle = 9 ;

	}
	else if ( m_state == INIT_SYSTEM_SHOW_SCREEN )
	{
	}
	else
	{
	}



    return S_OK;
}

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 : Genesis A button : %S", validKeys[m_bMappingA].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*6, menuChoice==0 ? 0xff000000 : 0xffffffff, str );

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

		swprintf( str, L"Use DPAD : Genesis C button : %S", validKeys[m_bMappingC].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*8, menuChoice==2 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD : Genesis X button : %S", validKeys[m_bMappingX].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*9, menuChoice==3 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD : Genesis Y button : %S", validKeys[m_bMappingY].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*10, menuChoice==4 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD : Genesis Z button : %S", validKeys[m_bMappingZ].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*11, menuChoice==5 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD : Genesis START button : %S", validKeys[m_bMappingSTART].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*12, menuChoice==6 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD : Genesis MODE button : %S", validKeys[m_bMappingMODE].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*13, menuChoice==7 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Use DPAD : Genesis Throttle : %S", validKeys[m_bMappingThrottle].keyname ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*14, menuChoice==8 ? 0xff000000 : 0xffffffff, str );

		swprintf( str, L"Enable 4-player support?  %S", multiport ? ( (multiport==1) ? "Yes, port 1" : "Yes, port 2" ) : "No" ) ;
		m_Font.DrawText( (float)m_nXOffset+  32, 16*15, menuChoice==9 ? 0xff000000 : 0xffffffff, str );

		m_Font.DrawText( (float)m_nXOffset+  32, 16*17, 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])
		{
	        XBInput_GetInput();
			break ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_DOWN )
		{
			menuChoice = (menuChoice+1)%10 ;
		}
		else if ( g_Gamepads[0].hDevice && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_UP )
		{
			if ( menuChoice == 0 )
				menuChoice = 9 ;
			else
				menuChoice = (menuChoice-1)%10 ;
		}
		else if ( (g_Gamepads[0].hDevice ) && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_RIGHT )
		{
			switch ( menuChoice )
			{
				case 0 : m_bMappingA = (m_bMappingA+1)%10; break ;
				case 1 : m_bMappingB = (m_bMappingB+1)%10; break ;
				case 2 : m_bMappingC = (m_bMappingC+1)%10; break ;
				case 3 : m_bMappingX = (m_bMappingX+1)%10; break ;
				case 4 : m_bMappingY = (m_bMappingY+1)%10; break ;
				case 5 : m_bMappingZ = (m_bMappingZ+1)%10; break ;
				case 6 : m_bMappingSTART = (m_bMappingSTART+1)%10; break ;
				case 7 : m_bMappingMODE = (m_bMappingMODE+1)%10; break ;
				case 8 : m_bMappingThrottle = (m_bMappingThrottle+1)%10; break ;
				case 9 : multiport = (multiport+1)%3 ; break ;
				default : break ;
			}
		}
		else if ( (g_Gamepads[0].hDevice ) && g_Gamepads[0].wPressedButtons & XINPUT_GAMEPAD_DPAD_LEFT )
		{
			switch ( menuChoice )
			{
				case 0 : if ( m_bMappingA == 0 ) m_bMappingA = 9 ; else m_bMappingA = (m_bMappingA-1)%10; break ;
				case 1 : if ( m_bMappingB == 0 ) m_bMappingB = 9 ; else m_bMappingB = (m_bMappingB-1)%10; break ;
				case 2 : if ( m_bMappingC == 0 ) m_bMappingC = 9 ; else m_bMappingC = (m_bMappingC-1)%10; break ;
				case 3 : if ( m_bMappingX == 0 ) m_bMappingX = 9 ; else m_bMappingX = (m_bMappingX-1)%10; break ;
				case 4 : if ( m_bMappingY == 0 ) m_bMappingY = 9 ; else m_bMappingY = (m_bMappingY-1)%10; break ;
				case 5 : if ( m_bMappingZ == 0 ) m_bMappingZ = 9 ; else m_bMappingZ = (m_bMappingZ-1)%10; break ;
				case 6 : if ( m_bMappingSTART == 0 ) m_bMappingSTART = 9 ; else m_bMappingSTART = (m_bMappingSTART-1)%10; break ;
				case 7 : if ( m_bMappingMODE == 0 ) m_bMappingMODE = 9 ; else m_bMappingMODE = (m_bMappingMODE-1)%10; break ;
				case 8 : if ( m_bMappingThrottle == 0 ) m_bMappingThrottle = 9 ; else m_bMappingThrottle = (m_bMappingThrottle-1)%10; break ;
				case 9 : multiport = (multiport+1)%3 ; ; break ;
				default : break ;
			}
		}


	}

}


/**
  This routine should be called regularly to handle events
*/
int CXBoxSample::getButtonState( int port, int mapping)
{
	switch ( mapping )
	{
		case 0 : return ( ! ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_A ] ) ) ;
		case 1 : return ( ! ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_B ] ) ) ;
		case 2 : return ( ! ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_X ] ) ) ;
		case 3 : return ( ! ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_Y ] ) ) ;
		case 4 : return ( ! ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_BLACK ] ) ) ;
		case 5 : return ( ! ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_WHITE ] ) ) ;
		case 6 : return ( ! ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_START ) ) ;
		case 7 : return ( ! ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_BACK ) ) ;
		case 8 : return ( ! ( g_Gamepads[port].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] ) ) ;
		case 9 : return ( ! ( g_Gamepads[port].bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] ) ) ;
		default : return 1 ;
	}
}

int CXBoxSample::getButtonValue( int port, int mapping)
{
	switch ( mapping )
	{
		case 0 : return ( ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_A ] ) ) ;
		case 1 : return ( ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_B ] ) ) ;
		case 2 : return ( ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_X ] ) ) ;
		case 3 : return ( ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_Y ] ) ) ;
		case 4 : return ( ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_BLACK ] ) ) ;
		case 5 : return ( ( g_Gamepads[port].bAnalogButtons[ XINPUT_GAMEPAD_WHITE ] ) ) ;
		case 6 : return ( ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_START ) ) ;
		case 7 : return ( ( g_Gamepads[port].wButtons & XINPUT_GAMEPAD_BACK ) ) ;
		case 8 : return ( ( g_Gamepads[port].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] ) ) ;
		case 9 : return ( ( g_Gamepads[port].bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] ) ) ;
		default : return 1 ;
	}
}

int CXBoxSample::handleEvents()
{

	updateCheats() ;

	XBInput_GetInput();

	for ( int i = 0 ; i < 4 ; i++ )
	{
		if(g_Gamepads[i].hDevice && g_Gamepads[i].wButtons & XINPUT_GAMEPAD_RIGHT_THUMB)
		{
			m_state = IN_GAME_PAUSED ;
			m_sound.pause( TRUE ) ;
			m_cdda.pause( TRUE ) ;
			m_mp3player.pause( TRUE ) ;
			m_dwStartPause = GetTickCount();
			doCheatMenu() ;

			if ( m_state == MAIN_MENU )
			{
				Gens_Running = 0 ;
				return 1 ;
			}
			return 0 ;
		}

		if(g_Gamepads[i].hDevice && g_Gamepads[i].wPressedButtons & XINPUT_GAMEPAD_LEFT_THUMB)
		{
			blittermode = (blittermode+1)%2 ;
			changedblit = 60 ;
		}

		if ( ( g_Gamepads[i].hDevice && g_Gamepads[i].bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER]) && 
			 (g_Gamepads[i].hDevice && g_Gamepads[i].bPressedAnalogButtons[XINPUT_GAMEPAD_WHITE]) )
		{
			Load_State( g_statefile ) ;
		}
		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]) )
		{
			Save_State( g_statefile ) ;
		}

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

	}

	if ( g_Gamepads[0].hDevice )
	{
		Controller_1_A = getButtonState( 0, m_bMappingA ) ;
		Controller_1_B = getButtonState( 0, m_bMappingB ) ;
		Controller_1_C = getButtonState( 0, m_bMappingC ) ;
		Controller_1_X = getButtonState( 0, m_bMappingX ) ;
		Controller_1_Y = getButtonState( 0, m_bMappingY ) ;
		Controller_1_Z = getButtonState( 0, m_bMappingZ ) ;

		Controller_1_Start = getButtonState( 0, m_bMappingSTART ) ;
		Controller_1_Mode = getButtonState( 0, m_bMappingMODE ) ;


		if ( g_Gamepads[0].fX1 || g_Gamepads[0].fY1 )
		{
			Controller_1_Left = ( g_Gamepads[0].fX1 >= 0 ) ;
			Controller_1_Right = ( g_Gamepads[0].fX1 <= 0 ) ;
			Controller_1_Up = ( g_Gamepads[0].fY1 <= 0 ) ;
			Controller_1_Down = ( g_Gamepads[0].fY1 >= 0 ) ;

		}
		else
		{
			Controller_1_Left = ( ! ( g_Gamepads[0].wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) ) ;
			Controller_1_Right = ( ! ( g_Gamepads[0].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) ) ;
			Controller_1_Up = ( ! ( g_Gamepads[0].wButtons & XINPUT_GAMEPAD_DPAD_UP ) ) ;
			Controller_1_Down = ( ! ( g_Gamepads[0].wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) ) ;

		}

	}
	else
	{
		Controller_1_Left = 1 ;
		Controller_1_Right = 1 ;
		Controller_1_Up = 1 ;
		Controller_1_Down = 1 ;
		Controller_1_A = 1 ;
		Controller_1_B = 1 ;
		Controller_1_C = 1 ;
		Controller_1_X = 1 ;
		Controller_1_Y = 1 ;
		Controller_1_Z = 1 ;
		Controller_1_Start = 1 ;
		Controller_1_Mode = 1 ;

	}

	if ( g_Gamepads[1].hDevice )
	{

		Controller_2_A = getButtonState( 1, m_bMappingA ) ;
		Controller_2_B = getButtonState( 1, m_bMappingB ) ;
		Controller_2_C = getButtonState( 1, m_bMappingC ) ;
		Controller_2_X = getButtonState( 1, m_bMappingX ) ;
		Controller_2_Y = getButtonState( 1, m_bMappingY ) ;
		Controller_2_Z = getButtonState( 1, m_bMappingZ ) ;

		Controller_2_Start = getButtonState( 1, m_bMappingSTART ) ;
		Controller_2_Mode = getButtonState( 1, m_bMappingMODE ) ;


		Controller_1B_A = getButtonState( 1, m_bMappingA ) ;
		Controller_1B_B = getButtonState( 1, m_bMappingB ) ;
		Controller_1B_C = getButtonState( 1, m_bMappingC ) ;
		Controller_1B_X = getButtonState( 1, m_bMappingX ) ;
		Controller_1B_Y = getButtonState( 1, m_bMappingY ) ;
		Controller_1B_Z = getButtonState( 1, m_bMappingZ ) ;

		Controller_1B_Start = getButtonState( 1, m_bMappingSTART ) ;
		Controller_1B_Mode = getButtonState( 1, m_bMappingMODE ) ;
		
		
		if ( g_Gamepads[1].fX1 || g_Gamepads[1].fY1 )
		{
			Controller_2_Left = ( g_Gamepads[1].fX1 >= 0 ) ;
			Controller_2_Right = ( g_Gamepads[1].fX1 <= 0 ) ;
			Controller_2_Up = ( g_Gamepads[1].fY1 <= 0 ) ;
			Controller_2_Down = ( g_Gamepads[1].fY1 >= 0 ) ;

			Controller_1B_Left = ( g_Gamepads[1].fX1 >= 0 ) ;
			Controller_1B_Right = ( g_Gamepads[1].fX1 <= 0 ) ;
			Controller_1B_Up = ( g_Gamepads[1].fY1 <= 0 ) ;
			Controller_1B_Down = ( g_Gamepads[1].fY1 >= 0 ) ;
		
		}
		else
		{
			Controller_2_Left = ( ! ( g_Gamepads[1].wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) ) ;
			Controller_2_Right = ( ! ( g_Gamepads[1].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) ) ;
			Controller_2_Up = ( ! ( g_Gamepads[1].wButtons & XINPUT_GAMEPAD_DPAD_UP ) ) ;
			Controller_2_Down = ( ! ( g_Gamepads[1].wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) ) ;

			Controller_1B_Left = ( ! ( g_Gamepads[1].wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) ) ;
			Controller_1B_Right = ( ! ( g_Gamepads[1].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) ) ;
			Controller_1B_Up = ( ! ( g_Gamepads[1].wButtons & XINPUT_GAMEPAD_DPAD_UP ) ) ;
			Controller_1B_Down = ( ! ( g_Gamepads[1].wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) ) ;
		
		}

	}
	else
	{
		Controller_2_Left = 1 ;
		Controller_2_Right = 1 ;
		Controller_2_Up = 1 ;
		Controller_2_Down = 1 ;
		Controller_2_A = 1 ;
		Controller_2_B = 1 ;
		Controller_2_C = 1 ;
		Controller_2_X = 1 ;
		Controller_2_Y = 1 ;
		Controller_2_Z = 1 ;
		Controller_2_Start = 1 ;
		Controller_2_Mode = 1 ;

		Controller_1B_Left = 1 ;
		Controller_1B_Right = 1 ;
		Controller_1B_Up = 1 ;
		Controller_1B_Down = 1 ;
		Controller_1B_A = 1 ;
		Controller_1B_B = 1 ;
		Controller_1B_C = 1 ;
		Controller_1B_X = 1 ;
		Controller_1B_Y = 1 ;
		Controller_1B_Z = 1 ;
		Controller_1B_Start = 1 ;
		Controller_1B_Mode = 1 ;
	}



	if ( g_Gamepads[2].hDevice )
	{
		Controller_1C_A = getButtonState( 2, m_bMappingA ) ;
		Controller_1C_B = getButtonState( 2, m_bMappingB ) ;
		Controller_1C_C = getButtonState( 2, m_bMappingC ) ;
		Controller_1C_X = getButtonState( 2, m_bMappingX ) ;
		Controller_1C_Y = getButtonState( 2, m_bMappingY ) ;
		Controller_1C_Z = getButtonState( 2, m_bMappingZ ) ;

		Controller_1C_Start = getButtonState( 2, m_bMappingSTART ) ;
		Controller_1C_Mode = getButtonState( 2, m_bMappingMODE ) ;


		
		Controller_2B_A = getButtonState( 2, m_bMappingA ) ;
		Controller_2B_B = getButtonState( 2, m_bMappingB ) ;
		Controller_2B_C = getButtonState( 2, m_bMappingC ) ;
		Controller_2B_X = getButtonState( 2, m_bMappingX ) ;
		Controller_2B_Y = getButtonState( 2, m_bMappingY ) ;
		Controller_2B_Z = getButtonState( 2, m_bMappingZ ) ;

		Controller_2B_Start = getButtonState( 2, m_bMappingSTART ) ;
		Controller_2B_Mode = getButtonState( 2, m_bMappingMODE ) ;
		
		if ( g_Gamepads[2].fX1 || g_Gamepads[2].fY1 )
		{
			Controller_1C_Left = ( g_Gamepads[2].fX1 >= 0 ) ;
			Controller_1C_Right = ( g_Gamepads[2].fX1 <= 0 ) ;
			Controller_1C_Up = ( g_Gamepads[2].fY1 <= 0 ) ;
			Controller_1C_Down = ( g_Gamepads[2].fY1 >= 0 ) ;

			Controller_2B_Left = ( g_Gamepads[2].fX1 >= 0 ) ;
			Controller_2B_Right = ( g_Gamepads[2].fX1 <= 0 ) ;
			Controller_2B_Up = ( g_Gamepads[2].fY1 <= 0 ) ;
			Controller_2B_Down = ( g_Gamepads[2].fY1 >= 0 ) ;
		
		}
		else
		{
			Controller_1C_Left = ( ! ( g_Gamepads[2].wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) ) ;
			Controller_1C_Right = ( ! ( g_Gamepads[2].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) ) ;
			Controller_1C_Up = ( ! ( g_Gamepads[2].wButtons & XINPUT_GAMEPAD_DPAD_UP ) ) ;
			Controller_1C_Down = ( ! ( g_Gamepads[2].wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) ) ;

			Controller_2B_Left = ( ! ( g_Gamepads[2].wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) ) ;
			Controller_2B_Right = ( ! ( g_Gamepads[2].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) ) ;
			Controller_2B_Up = ( ! ( g_Gamepads[2].wButtons & XINPUT_GAMEPAD_DPAD_UP ) ) ;
			Controller_2B_Down = ( ! ( g_Gamepads[2].wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) ) ;
		
		}

	}
	else
	{
		Controller_1C_Left = 1 ;
		Controller_1C_Right = 1 ;
		Controller_1C_Up = 1 ;
		Controller_1C_Down = 1 ;
		Controller_1C_A = 1 ;
		Controller_1C_B = 1 ;
		Controller_1C_C = 1 ;
		Controller_1C_X = 1 ;
		Controller_1C_Y = 1 ;
		Controller_1C_Z = 1 ;
		Controller_1C_Start = 1 ;
		Controller_1C_Mode = 1 ;

		Controller_2B_Left = 1 ;
		Controller_2B_Right = 1 ;
		Controller_2B_Up = 1 ;
		Controller_2B_Down = 1 ;
		Controller_2B_A = 1 ;
		Controller_2B_B = 1 ;
		Controller_2B_C = 1 ;
		Controller_2B_X = 1 ;
		Controller_2B_Y = 1 ;
		Controller_2B_Z = 1 ;
		Controller_2B_Start = 1 ;
		Controller_2B_Mode = 1 ;
	
	
	}

	if ( g_Gamepads[3].hDevice )
	{

		Controller_1D_A = getButtonState( 3, m_bMappingA ) ;
		Controller_1D_B = getButtonState( 3, m_bMappingB ) ;
		Controller_1D_C = getButtonState( 3, m_bMappingC ) ;
		Controller_1D_X = getButtonState( 3, m_bMappingX ) ;
		Controller_1D_Y = getButtonState( 3, m_bMappingY ) ;
		Controller_1D_Z = getButtonState( 3, m_bMappingZ ) ;

		Controller_1D_Start = getButtonState( 3, m_bMappingSTART ) ;
		Controller_1D_Mode = getButtonState( 3, m_bMappingMODE ) ;

		Controller_2C_A = getButtonState( 3, m_bMappingA ) ;
		Controller_2C_B = getButtonState( 3, m_bMappingB ) ;
		Controller_2C_C = getButtonState( 3, m_bMappingC ) ;
		Controller_2C_X = getButtonState( 3, m_bMappingX ) ;
		Controller_2C_Y = getButtonState( 3, m_bMappingY ) ;
		Controller_2C_Z = getButtonState( 3, m_bMappingZ ) ;

		Controller_2C_Start = getButtonState( 3, m_bMappingSTART ) ;
		Controller_2C_Mode = getButtonState( 3, m_bMappingMODE ) ;

		if ( g_Gamepads[3].fX1 || g_Gamepads[3].fY1 )
		{
			Controller_1D_Left = ( g_Gamepads[3].fX1 >= 0 ) ;
			Controller_1D_Right = ( g_Gamepads[3].fX1 <= 0 ) ;
			Controller_1D_Up = ( g_Gamepads[3].fY1 <= 0 ) ;
			Controller_1D_Down = ( g_Gamepads[3].fY1 >= 0 ) ;

			Controller_2C_Left = ( g_Gamepads[3].fX1 >= 0 ) ;
			Controller_2C_Right = ( g_Gamepads[3].fX1 <= 0 ) ;
			Controller_2C_Up = ( g_Gamepads[3].fY1 <= 0 ) ;
			Controller_2C_Down = ( g_Gamepads[3].fY1 >= 0 ) ;
		
		}
		else
		{
			Controller_2C_Left = ( ! ( g_Gamepads[3].wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) ) ;
			Controller_2C_Right = ( ! ( g_Gamepads[3].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) ) ;
			Controller_2C_Up = ( ! ( g_Gamepads[3].wButtons & XINPUT_GAMEPAD_DPAD_UP ) ) ;
			Controller_2C_Down = ( ! ( g_Gamepads[3].wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) ) ;

			Controller_1D_Left = ( ! ( g_Gamepads[3].wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) ) ;
			Controller_1D_Right = ( ! ( g_Gamepads[3].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ) ) ;
			Controller_1D_Up = ( ! ( g_Gamepads[3].wButtons & XINPUT_GAMEPAD_DPAD_UP ) ) ;
			Controller_1D_Down = ( ! ( g_Gamepads[3].wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) ) ;
		
		}

	}
	else
	{
		Controller_1D_Left = 1 ;
		Controller_1D_Right = 1 ;
		Controller_1D_Up = 1 ;
		Controller_1D_Down = 1 ;
		Controller_1D_A = 1 ;
		Controller_1D_B = 1 ;
		Controller_1D_C = 1 ;
		Controller_1D_X = 1 ;
		Controller_1D_Y = 1 ;
		Controller_1D_Z = 1 ;
		Controller_1D_Start = 1 ;
		Controller_1D_Mode = 1 ;

		Controller_2C_Left = 1 ;
		Controller_2C_Right = 1 ;
		Controller_2C_Up = 1 ;
		Controller_2C_Down = 1 ;
		Controller_2C_A = 1 ;
		Controller_2C_B = 1 ;
		Controller_2C_C = 1 ;
		Controller_2C_X = 1 ;
		Controller_2C_Y = 1 ;
		Controller_2C_Z = 1 ;
		Controller_2C_Start = 1 ;
		Controller_2C_Mode = 1 ;
	
	}


	if ( ( getButtonValue( 0, m_bMappingThrottle ) > 230 ) || ( getButtonValue( 1, m_bMappingThrottle ) > 230 ) )
	{
		if ( throttle <= 0 )
			throttle = 10 ;
	}
	else
	{
		throttle = 0 ;
	}



	return 0 ;
}

/*
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::loadKeys( char *keyfile ) 
{
	FILE *kfile ;

	if ( kfile = fopen( keyfile, "rb" ) )
	{
		fread( &m_bMappingA, sizeof(m_bMappingB), 1, kfile ) ;
		fread( &m_bMappingB, sizeof(m_bMappingB), 1, kfile ) ;
		fread( &m_bMappingC, sizeof(m_bMappingB), 1, kfile ) ;
		fread( &m_bMappingX, sizeof(m_bMappingB), 1, kfile ) ;
		fread( &m_bMappingY, sizeof(m_bMappingB), 1, kfile ) ;
		fread( &m_bMappingZ, sizeof(m_bMappingB), 1, kfile ) ;
		fread( &m_bMappingSTART, sizeof(m_bMappingB), 1, kfile ) ;
		fread( &m_bMappingMODE, sizeof(m_bMappingB), 1, kfile ) ;
		fclose( kfile ) ;

	}
}


void CXBoxSample::saveKeys( char *keyfile ) 
{
	FILE *kfile ;

	if ( kfile = fopen( keyfile, "wb" ) )
	{
		fwrite( &m_bMappingA, sizeof(m_bMappingB), 1, kfile ) ;
		fwrite( &m_bMappingB, sizeof(m_bMappingB), 1, kfile ) ;
		fwrite( &m_bMappingC, sizeof(m_bMappingB), 1, kfile ) ;
		fwrite( &m_bMappingX, sizeof(m_bMappingB), 1, kfile ) ;
		fwrite( &m_bMappingY, sizeof(m_bMappingB), 1, kfile ) ;
		fwrite( &m_bMappingZ, sizeof(m_bMappingB), 1, kfile ) ;
		fwrite( &m_bMappingSTART, sizeof(m_bMappingB), 1, kfile ) ;
		fwrite( &m_bMappingMODE, sizeof(m_bMappingB), 1, kfile ) ;
		fclose( kfile ) ;

	}
}


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

	global_error_message[0] = 0 ;

	sleepamount = 0 ;

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


	throttle = 0 ;
	blittermode = 1 ;

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

	nb_max_track = 0 ;

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


	loaded_cue = 0 ;

	memset( CD_track, 0, sizeof(CD_track) ) ;


	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  ;
		}
	}
	else if (strstr (strupr(filename), ".CUE"))
	{
		writexbox( "processing cue\r\n" ) ;

		strcpy( g_cuefile, filename ) ;
		loadCueSheet( g_cuefile ) ;
		filename[0] = 0 ;

		for ( int i = 0 ; i < nb_max_track ; i++ )
		{
			if ( CD_track[i].type == 4 )
			{
				strcpy( filename, CD_track[i].filename ) ;
				break ;
			}
		}

		//sprintf( xmsg, "filename fom cue=%s", filename ) ;
		//writexbox( xmsg ) ;

		if ( filename[0] == 0 )
		{
			m_state = MAIN_MENU ;
			return ;
		}

		loaded_cue = 1 ;
	}


	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, ".srm");

	strcpy(g_keysfile, g_saveprefix);
	strcat(g_keysfile, ".key");

	strcpy(g_bramfile, g_saveprefix);
	strcat(g_bramfile, ".brm");

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

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

	loadKeys( g_keysfile ) ;

//	nonoise = 0 ;
	

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

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

	// Create our texture
	init_texture();


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





	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_cdda.pause( FALSE ) ;
	//m_mp3player.insertSilence( 22050 ) ;
	//m_mp3player.pause( FALSE ) ;

//	hugomain( filename, g_sramfile, g_saveprefix, systemcard, 0, forceUS ) ;

	gensmain(filename,country,whichCD,0) ;

	//writexbox( "initout" ) ;
	m_state=MAIN_MENU ;
	saveKeys( g_keysfile ) ;
	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


void xbox_set_refreshrate( int rate ) 
{
	DWORD XVideoStandard = XGetVideoStandard();
	DWORD XVidMode = XGetVideoFlags();
	DWORD defaultRate ;
	DWORD addFlags ;
	char  xmsg[100] ;

	if ( XVideoStandard==XC_VIDEO_STANDARD_PAL_I)
	{
		if(XVidMode && XC_VIDEO_FLAGS_PAL_60Hz)
		{
			defaultRate = 60 ;
		}
		else
		{
			defaultRate = 50 ;
		}
	}
	else
	{
		defaultRate = 60 ;
	}

	sprintf(xmsg, "default=%u, new=%u\r\n", defaultRate, rate ) ;
	writexbox(xmsg) ;

	if ( defaultRate != rate )
	{
		g_app->m_d3dpp.Flags |= D3DPRESENTFLAG_EMULATE_REFRESH_RATE ;
	}
	else
	{
		g_app->m_d3dpp.Flags &= ~D3DPRESENTFLAG_EMULATE_REFRESH_RATE ;
	}

	if ( rate == 60 )
	{
		
		DWORD hr ;

		writexbox("scr1\r\n") ;
	    SAFE_RELEASE( g_app->m_pd3dDevice );
		//g_app->m_pd3dDevice->Release() ;

		writexbox("scr1\r\n") ;

		g_app->fillPresentationParams() ;
		writexbox("scr1\r\n") ;
		if( FAILED( hr = g_app->m_pD3D->CreateDevice( 0, D3DDEVTYPE_HAL, NULL, 
											   D3DCREATE_HARDWARE_VERTEXPROCESSING, 
											   &g_app->m_d3dpp, &g_app->m_pd3dDevice ) ) )
		{
		writexbox("scr2\r\n") ;
			OUTPUT_DEBUG_STRING( "XBApp: Could not create D3D device!\n" );
			return ;
		}
		writexbox("scr1\r\n") ;

		//memcpy( &g_app->m_d3dpp, &g_app->m_origPP, sizeof(g_app->m_origPP ) ) ;
		g_app->fillPresentationParams() ;
		//g_app->m_d3dpp.Flags |= D3DPRESENTFLAG_EMULATE_REFRESH_RATE ;
		//g_app->m_d3dpp.Flags &= ~D3DPRESENTFLAG_EMULATE_REFRESH_RATE ;
	}

	g_app->SetRefreshRate( rate == 60 ? D3DPRESENT_RATE_DEFAULT : 50 ) ;
	//g_app->SetRefreshRate( rate == 60 ? 60 : 50 ) ;

}

void xbox_stop_cd()
{
	g_cdda->stop() ;

}
void xbox_read_cd_sector( unsigned char *p, unsigned int sector ) 
{
	int result ;
	char xmsg[100] ;

	//sprintf(xmsg, "reading sector %u\r\n", sector) ;
	//writexbox(xmsg) ;
	result = g_app->m_io.ReadSector( g_app->m_hCdrom, sector, (LPSTR)p ) ;

	//if ( result < 2048 )
		//writexbox("FAILED\r\n" ) ;
}
void xbox_play_cdda( unsigned int sectorFrom, unsigned int sectorTo, unsigned char repeat ) 
{
	g_cdda->play_sectors( sectorFrom, sectorTo, repeat, g_app->m_hCdrom ) ;
}

char* xbox_get_track_name( int tnum ) 
{
	if ( tnum > g_app->nb_max_track )
		return "xxxx" ;
	else
		return g_app->CD_track[tnum].filename ;
}

int xbox_get_track_length( int tnum ) 
{
	if ( tnum > g_app->nb_max_track )
		return 0 ;
	else
		return g_app->CD_track[tnum].length ;
}

char* xbox_get_sramfile()
{
	return g_app->g_sramfile ;
}

char* xbox_get_bramfile()
{
	return g_app->g_bramfile ;
}

char* xbox_get_savepath()
{
	return g_app->g_savePath ;
}

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

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

void xbox_process_audio()
{
	g_sound->process() ;
	g_cdda->process() ;
	g_mp3player->process() ;
}

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

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



}

#define CD_SECS 60
#define CD_FRAMES 75

void CXBoxSample::loadCueSheet( char *cuefile ) 
{
	FILE  *infile ;
	char  *cuedata ;
	unsigned int filesize ;
	char  *line ;
	char  *rpos ;
	char  *npos ;
	char  *msf ;
	char  *stringpos ;
	byte  mins, secs, frms, track, tracktype ;
	char  trackfilename[256] ;
	char  *tok ;
	int   sectorA, sectorB ;
	char  *lastslashA ;
	char  *lastslashB ;
	//char  xmsg[100] ;
	int   totalsectors ;

	memset( trackfilename, 0, 256 ) ;
	memset( CD_track, 0, sizeof(CD_track) ) ;

	track = mins = secs = frms = 0 ;

	writexbox( "about to open cue\r\n" ) ;

	infile = fopen( cuefile, "rb" ) ;

	if ( !infile )
	{
		return ;
	}

	fseek( infile, 0, SEEK_END ) ;
	filesize = ftell( infile ) ;
	fseek( infile, 0, SEEK_SET ) ;

	//sprintf( xmsg, "cuesize=%u\r\n", filesize ) ;
	//writexbox( xmsg ) ;

	cuedata = (char*)malloc( filesize+1 ) ;
	memset( cuedata, 0, filesize+1 ) ;

	fread( cuedata, sizeof(char), filesize, infile ) ;

	fclose( infile ) ;

	writexbox( "allocated and closed file\r\n" ) ;

	line = cuedata ;


	while ( *line )
	{
		writexbox( "top loop\r\n" ) ;

		rpos = strchr( line, '\r' ) ;
		npos = strchr( line, '\n' ) ;

		if ( npos > rpos )
			rpos = npos ;

		if ( rpos )
			*rpos = 0 ;

		writexbox( "removed trailing line\r\n" ) ;

		strupr( line ) ;

		//writexbox( line ) ;
		//writexbox( "\r\n" ) ;

		if ( stringpos = strstr( line, "TRACK " ) )
		{
			writexbox( "gottrack\r\n" ) ;
			if ( strstr( line, "AUDIO" ) )
				tracktype = 0 ;
			else
				tracktype = 4 ;

			tok = strtok( stringpos+5, " \t\r\n" ) ;


			track = atoi( tok ) ;


			if ( ( track < 0 ) || ( track > 255 ) )
			{
				track = 255 ;
			}


		}
		else if ( ( stringpos = strstr( line, "INDEX 1 " ) ) || ( stringpos = strstr( line, "INDEX 01 " ) ) )
		{
			writexbox( "gotindex\r\n" ) ;
			msf = strtok( stringpos+8, " \t\r\n" ) ;
			if ( strlen(msf) >= 8 )
			{
				*(msf+2) = 0 ;
				*(msf+5) = 0 ;
				*(msf+8) = 0 ;

				mins = atoi( msf ) ;
				secs = atoi( msf+3 ) ;
				frms = atoi( msf+6 ) ;

				if ( secs > 57 )  //account for standard gap that seems to appear on all cue sheets
				{
					secs = secs + 2 - 60 ;
					mins++ ;
				}
				else
				{
					secs += 2 ;
				}
			}
			CD_track[track].beg_fra = frms ;
			CD_track[track].beg_min = mins ;
			CD_track[track].beg_sec = secs;  
			CD_track[track].type = tracktype ;
			strcpy( CD_track[track].filename, trackfilename ) ;
		}
		else if ( stringpos = strstr( line, "FILE " ) )
		{
			writexbox( "gotfile\r\n" ) ;
			tok = strtok( stringpos+4, " \r\n\t\"" ) ;

			lastslashA = strrchr( tok, '/' ) ;
			lastslashB = strrchr( tok, '\\' ) ;

			if ( lastslashB > lastslashA )
				lastslashA = lastslashB ;

			if ( lastslashB )
			{
				*lastslashB = 0 ;
				tok = lastslashB + 1 ;
			}
			
			strcpy( trackfilename, m_szCurrentDir ) ;
			strcat( trackfilename, tok ) ;

		}

		line = rpos + 1 ;

		if ( line - cuedata >= filesize )
			break ;

	}

	nb_max_track = track ;
	totalsectors = 0 ;


	for ( int i = 1 ; i <= nb_max_track ; i++ )
	{

		if ( i == nb_max_track )
		{
			sectorB = 73 * CD_SECS * CD_FRAMES ; 
	
			sectorA = ( CD_track[i].beg_min * CD_SECS * CD_FRAMES ) +
					  ( CD_track[i].beg_sec * CD_FRAMES ) +
					  ( CD_track[i].beg_fra  )  ;
	
			CD_track[i].length = sectorB - sectorA ;
		}
		else
		{
			sectorB = ( CD_track[i+1].beg_min * CD_SECS * CD_FRAMES ) +
					  ( CD_track[i+1].beg_sec * CD_FRAMES ) +
					  ( CD_track[i+1].beg_fra  )  ;
	
			sectorA = ( CD_track[i].beg_min * CD_SECS * CD_FRAMES ) +
					  ( CD_track[i].beg_sec * CD_FRAMES ) +
					  ( CD_track[i].beg_fra  )  ;
	
			CD_track[i].length = sectorB - sectorA ;
		}

		CD_track[i].beg_lsn = totalsectors;	

		totalsectors += CD_track[i].length ;

		//sprintf(xmsg, "trk=%u,type=%u,min=%u,sec=%u,fra=%u,lsn=%u,length=%ufilename=%s\r\n", i, CD_track[i].type, 
			//bcdbin[CD_track[i].beg_min], bcdbin[CD_track[i].beg_sec], bcdbin[CD_track[i].beg_fra], 
			//CD_track[i].beg_lsn, CD_track[i].length, CD_track[i].filename ) ;
		//writexbox( xmsg ) ;
	}

	free (cuedata) ;

	writexbox( "returning from cue\r\n" ) ;

}

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

	//writexbox( "ttt\r\n" ) ;
    unzFile file = unzOpen(hugozipfile);

    if(file == NULL)
		return 0 ;

	//writexbox( "ttt\r\n" ) ;

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

	//writexbox( "ttt\r\n" ) ;
    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);
    }

	//writexbox( "ttt\r\n" ) ;
    if( !(port == UNZ_END_OF_LIST_OF_FILE || port == UNZ_OK) || filesize == 0)
    {
		unzClose(file) ;
		return 0 ;
    }
	//writexbox( "ttt\r\n" ) ;

    unzLocateFile(file,filename,1);
    unzGetCurrentFileInfo(file, &info, filename,128, NULL,0, NULL,0);
    
	//writexbox( "ttt\r\n" ) ;
    if( unzOpenCurrentFile(file) != UNZ_OK )
    {
		unzClose(file);
		return 0 ;
    }

	//writexbox( "ttt\r\n" ) ;

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

	//writexbox( "ttt\r\n" ) ;

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

	//writexbox( "ttt\r\n" ) ;
    unzClose(file);

/*
	fsize = ftell (fp);

	fseek (fp, fsize & 0x1fff, SEEK_SET);
	fsize &= ~0x1fff;

	ROM = (UChar *) malloc (fsize);
	ROM_size = fsize / 0x2000;
	fread (ROM, 1, fsize, fp);
*/

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

	//writexbox( "ttt\r\n" ) ;

	//ROM = (UChar *) malloc (filesize);
	//ROM_size = filesize / 0x2000;
	//memcpy(ROM, data + (info.uncompressed_size & 0x1fff), filesize ) ;

	free(data) ;

	//writexbox( "ttt\r\n" ) ;

	return 1;
}

