// autoconfigDlg.cpp : implementation file
//

#include "stdafx.h"
#include "autoconfig.h"
#include "autoconfigDlg.h"
#include "ConfigError.h"

#include "Stuff\NotationFile.hpp"
#include "..\..\code\buildnum\buildnum.h" // get the current build number

#if !defined(STUFF_STUFF_HPP)
	#include "Stuff\Stuff.hpp"
#endif


#include <GameOS\GameOS.hpp>
#include <MFCPlatform\MFCPlatform.hpp>
#include <Stuff\NotationFile.hpp>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


#define PROC_SPEED_SLOP	20
#define PROC_SPEED_MIN	(300-PROC_SPEED_SLOP)
#define PROC_SPEED_LOW	(400-PROC_SPEED_SLOP)
#define PROC_SPEED_MED	(566-PROC_SPEED_SLOP)
#define PROC_SPEED_HIGH	(750-PROC_SPEED_SLOP)


#define VMEM_SLOP_FACTOR (1024*1024)
#define LOWVMEM	 (6*1024*1024-VMEM_SLOP_FACTOR)
#define MIDVMEM	 (16*1024*1024-VMEM_SLOP_FACTOR)
#define HIGHVMEM (32*1024*1024-VMEM_SLOP_FACTOR)

#define SYSMEM_MIN 64
#define SYSMEM_INC 32
#define SYSMEM_SLOP_FACTOR (SYSMEM_INC/2)

HGOSHEAP Heap;

#define PERDEVCOUNT 1
const char *PerferedDeviceList[PERDEVCOUNT]={"PLACEHOLDER DEVICE"};

enum LEVEL {
		L_Low = 0,
		L_Med = 1,
		L_High = 2,
		L_XHigh = 3
	} ;


#define SYSMEM_INDEXCAP 15

LEVEL LevelMat[4][4][SYSMEM_INDEXCAP]=
{
// Smem			 64		 96		 128	 160	 192	 224	 256	 288	 320	 352	 384	 416	 448	 480	 512
// 300-400Mhz
	{
/* vmem  8MB */ {L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low,  L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low},
/* vmem 16MB */	{L_Low  ,L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_Med,  L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med},
/* vmem 32MB */	{L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med,  L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med},
/* vmem 64MB */	{L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med,  L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med},
	},
// 400-566Mhz
	{
/* vmem  8MB */ {L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low,  L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med},
/* vmem 16MB */ {L_Low  ,L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_Med,  L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med},
/* vmem 32MB */ {L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med,  L_High ,L_High ,L_High ,L_High ,L_High ,L_High ,L_High ,L_High ,L_High},
/* vmem 64MB */ {L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med,  L_High ,L_High ,L_High ,L_High ,L_High ,L_High ,L_High ,L_High ,L_High},
	},
// 566-750Mhz
	{
/* vmem  8MB */ {L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low,  L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med},
/* vmem 16MB */ {L_Low  ,L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_Med,  L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med},
/* vmem 32MB */ {L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_High ,L_High, L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh},
/* vmem 64MB */ {L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_High ,L_High, L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh},
	},
// 750Mhz-1Ghz
	{
/* vmem  8MB */ {L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low  ,L_Low,  L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med},
/* vmem 16MB */ {L_Low  ,L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_Med,  L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med  ,L_Med},
/* vmem 32MB */ {L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_High ,L_High, L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh},
/* vmem 64MB */ {L_Low  ,L_Med  ,L_Med  ,L_Med  ,L_High ,L_High, L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh,L_XHigh},
	}
};

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();
	

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	CString	m_Str1;
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	m_Str1 = _T("");
	//}}AFX_DATA_INIT
	m_Str1.Format("AutoConfig Version %s",VER_PRODUCTVERSION_STR);

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	DDX_Text(pDX, IDC_STR1, m_Str1);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAutoconfigDlg dialog

LRESULT CALLBACK WinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	return GameOSWinProc( hWnd, uMsg, wParam, lParam );
}



CAutoconfigDlg::CAutoconfigDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CAutoconfigDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CAutoconfigDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);


	gosCreated = false;
	for(int i=0;i<16;i++) BadCard[i]=false;

	
}

CAutoconfigDlg::~CAutoconfigDlg()
{

	if (gosCreated)
	{
		TerminateGameEngine();

		gos_PopCurrentHeap();

		ExitGameOS();


		::DestroyWindow(Window);
		gosCreated = false;
	}

}

void CAutoconfigDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAutoconfigDlg)
	DDX_Control(pDX, IDC_TEXTSIZE, m_FontSize);
	DDX_Control(pDX, IDC_ANTIALIAS, m_AntiAliasList);
	DDX_Control(pDX, IDC_MACHINE, m_MachineList);
	DDX_Control(pDX, IDC_SIMPLE, m_SimBut);
	DDX_Control(pDX, IDC_ADVANCED, m_AdvBut);
	DDX_Control(pDX, IDC_SHADOWLEVEL, m_ShadowList);
	DDX_Control(pDX, IDC_WATER, m_WaterList);
	DDX_Control(pDX, IDC_VIDEOCARD, m_VideCardList);
	DDX_Control(pDX, IDC_VERTEXLIGHT, m_VertexLightList);
	DDX_Control(pDX, IDC_TEXTURE_LEVEL, m_TextureLevelList);
	DDX_Control(pDX, IDC_TERRAIN_LEVEL, m_TerrainLevelList);
	DDX_Control(pDX, IDC_SOUNDDETAIL, m_SDetailList);
	DDX_Control(pDX, IDC_SCREENRES, m_ScreenResList);
	DDX_Control(pDX, IDC_NOBLEND, m_NoBlendList);
	DDX_Control(pDX, IDC_MUSIC, m_MusicList);
	DDX_Control(pDX, IDC_MULTI_TEXTURE, m_MultiTextureList);
	DDX_Control(pDX, IDC_MAXLIGHTS, m_MaxLightsList);
	DDX_Control(pDX, IDC_LOD_LEVEL, m_LODLevelList);
	DDX_Control(pDX, IDC_LIGHTMAP, m_LightMapList);
	DDX_Control(pDX, IDC_FOOTSTEPS, m_FootStepList);
	DDX_Control(pDX, IDC_EFFECT_LEVEL, m_EffectList);
	DDX_Control(pDX, IDC_DETAIL_TEXTURE, m_DetailList);
	DDX_Control(pDX, IDC_CULTURAL, m_CultList);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAutoconfigDlg, CDialog)
	//{{AFX_MSG_MAP(CAutoconfigDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_TEST, OnTest)
	ON_WM_CLOSE()
	ON_BN_CLICKED(IDC_TEST2, OnExit)
	ON_CBN_SELCHANGE(IDC_VIDEOCARD, OnSelchangeVideocard)
	ON_BN_CLICKED(IDC_ADVANCED, OnAdvanced)
	ON_BN_CLICKED(IDC_SIMPLE, OnSimple)
	ON_CBN_SELCHANGE(IDC_MACHINE, OnSelchangeMachine)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAutoconfigDlg message handlers

BOOL CAutoconfigDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	



	InitGos();

	::ShowWindow(Window,SW_HIDE);
	InitComboBoxes();
	SetDlgMode(true);
	AutoDetectLevel(BestDevice());


	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CAutoconfigDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CAutoconfigDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CAutoconfigDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

DWORD CAutoconfigDlg::GetDeviceMemory(int device)
{


	DWORD did=gos_GetMachineInformation(gos_Info_GetDeviceDeviceID,device);
	if( gos_GetMachineInformation(gos_Info_GetDeviceVendorID,device)==0x121a)
			{	// Fake it for Voodoods
			if(did==1) return 0;
			if(did==2) return LOWVMEM+VMEM_SLOP_FACTOR;
			if(did==5) return MIDVMEM+VMEM_SLOP_FACTOR;
			if(did==9) return HIGHVMEM+VMEM_SLOP_FACTOR;
			}
			

	DWORD agp_memory=(DWORD)gos_GetMachineInformation( gos_Info_GetDeviceAGPMemory,device );
	DWORD texture_memory=(DWORD)gos_GetMachineInformation(gos_Info_GetDeviceLocalMemory,device);
	DWORD vid_card_memory=texture_memory>agp_memory?texture_memory:agp_memory;
	return vid_card_memory;
}




void CAutoconfigDlg::AutoDetectLevel(int device)
{
	int systemLevel;

	DWORD system_memory		= (DWORD)gos_GetMachineInformation( gos_Info_GetMemorySize ) ;
	DWORD proc_speed		= (DWORD)gos_GetMachineInformation( gos_Info_GetProcessorSpeed );
	DWORD vid_card_memory	= GetDeviceMemory(device);


int proc_index,vmem_index,smem_index;

	system_memory>>=20;											// convert to MB
	system_memory+=SYSMEM_SLOP_FACTOR;							// Add some Slop
	
	if(system_memory<SYSMEM_MIN)
	{
		smem_index=0;
	}
	else
	{
	smem_index=(system_memory-SYSMEM_MIN)/SYSMEM_INC;			//convert to index
	if(smem_index>=SYSMEM_INDEXCAP) smem_index=SYSMEM_INDEXCAP-1;	//cap it
	}

if(proc_speed<=PROC_SPEED_LOW)
{
proc_index=0;
}
else if(proc_speed<=PROC_SPEED_MED)
{
proc_index=1;
}
else if(proc_speed<=PROC_SPEED_HIGH)
{
proc_index=2;
}
else	
{
proc_index=3;
}

	if (vid_card_memory <= LOWVMEM)
	{
		vmem_index = 0;
	}
	else if (vid_card_memory <= MIDVMEM)
	{
		vmem_index = 1;
	}
	else if (vid_card_memory <= HIGHVMEM)
	{
		vmem_index = 2;
	}
	else 
	{
		vmem_index = 3;
	}




	systemLevel = LevelMat[proc_index][vmem_index][smem_index];


	DefaultToLevel(systemLevel);

}


void CAutoconfigDlg::Save(bool killgame)
{
	
		// save it out....
		Stuff::NotationFile notefile("options.ini");

		Stuff::Page *page = notefile.SetPage("Graphics Options");
		Check_Object(page);

		Stuff::Page *spage = notefile.SetPage("Sound Options");
		Check_Object(spage);

		Stuff::Page *compage = notefile.SetPage("Special Commands");
		Check_Object(compage);
		compage->SetEntry("KillGame",killgame);
		
		page->SetEntry("VideoDriverIndex", m_VideCardList.GetCurSel() );
		page->SetEntry("DetailTexture", m_SDetailList.GetCurSel()==0?false:true);
		page->SetEntry("MultiTexture", m_MultiTextureList.GetCurSel()==0?false:true);
		page->SetEntry("LightMaps", m_LightMapList.GetCurSel()==0?false:true);
		page->SetEntry("Culturals", m_CultList.GetCurSel()==0?false:true);
		page->SetEntry("Footsteps",m_FootStepList.GetCurSel()==0?false:true);
		page->SetEntry("MissionMusic", m_MusicList.GetCurSel()==0?false:true);
		page->SetEntry("NoBlend", m_NoBlendList.GetCurSel()==0?false:true);
		page->SetEntry("AntiAlias", m_AntiAliasList.GetCurSel()==0?false:true);

		page->SetEntry("VertexLighting", m_VertexLightList.GetCurSel()==0?false:true);
		page->SetEntry("SimpleLighting", m_VertexLightList.GetCurSel()==0?true:false);
		

		page->SetEntry("MipBias",m_TextureLevelList.GetCurSel());
		page->SetEntry("ShadowMode", m_ShadowList.GetCurSel());

		int fontval=0;
		switch(m_FontSize.GetCurSel())
		{
		case 0: fontval=2; break;
		case 1: fontval=0; break;
		case 2: fontval=-2; break;
		}

		page->SetEntry("fontsmall",fontval);
		page->SetEntry("fontmedium",fontval);
		page->SetEntry("fontlarge",fontval);
		page->SetEntry("fontlarge2",fontval);
		page->SetEntry("fontlarge3",fontval);

		DWORD sresval=m_ScreenResList.GetItemData(m_ScreenResList.GetCurSel());
		int device=m_VideCardList.GetItemData(m_VideCardList.GetCurSel());
		DWORD screenval=gos_GetMachineInformation(gos_Info_GetValidMode,device,sresval>>16,sresval&0xffff);

		int x,y,d;
		x=screenval>>16;;
		y=screenval&0xffff;
		d=sresval>>16;
			page->SetEntry("screenwidth",x);	
			page->SetEntry("screenheight",y);	
			page->SetEntry("bitdepth",d);	


		switch (m_SDetailList.GetCurSel())
		{
			case L_Low:
				spage->SetEntry("LowEndSound",true);
				spage->SetEntry("Radius",0.25f);
				break;

			case L_Med:
			case L_XHigh:
			case L_High:
			default:
				spage->SetEntry("LowEndSound",false);
				spage->SetEntry("Radius",1.0f);
				break;

		}

		switch (m_WaterList.GetCurSel())
		{
			case L_Low:
				page->SetEntry("FancyWater",false);
				page->SetEntry("MovieTextures",false);
				break;

			case L_Med:
				page->SetEntry("FancyWater",false);
				page->SetEntry("MovieTextures",true);
				break;

			case L_High:
			case L_XHigh:
			default:
				page->SetEntry("FancyWater",true);
				page->SetEntry("MovieTextures",true);
				break;
		}



		switch (m_MaxLightsList.GetCurSel())
		{
			case L_Low:
				page->SetEntry("MaxLights",2);
				break;

			case L_Med:
				page->SetEntry("MaxLights",4);
				break;

			case L_High:
				page->SetEntry("MaxLights",8);
				break;

			default:
			case L_XHigh:
				page->SetEntry("MaxLights",8);
				break;
		}
		


		switch (m_TerrainLevelList.GetCurSel())
		{
			case L_Low:
				page->SetEntry("Compositing",0);
				break;

			case L_Med:
				page->SetEntry("Compositing", 1);
				break;

			case L_High:
				page->SetEntry("Compositing", 2);
				break;

			default:
			case L_XHigh:
				page->SetEntry("Compositing", 3);
				break;
		}
		
		switch (m_EffectList.GetCurSel())
		{
			case L_Low:
				page->SetEntry("EffectLOD",250000.0f );
				break;

			case L_Med:
				page->SetEntry("EffectLOD",  62500.0f);
				break;

			case L_High:
				page->SetEntry("EffectLOD",10000.0f );
				break;

			case L_XHigh:
				page->SetEntry("EffectLOD",0.0f );
				break;
		}

		switch (m_LODLevelList.GetCurSel())
		{
			case L_Low:
					page->SetEntry("LOD", 2500.0f);
				break;

			case L_Med:
					page->SetEntry("LOD", 900.0f);
				break;

			case L_High:
					page->SetEntry("LOD", 400.0f);
				break;

			case L_XHigh:
					page->SetEntry("LOD", 0.0f );
				break;
		}

	
		
	DWORD system_memory		= (DWORD)gos_GetMachineInformation( gos_Info_GetMemorySize ) ;
	system_memory>>=20;											// convert to MB
	system_memory+=SYSMEM_SLOP_FACTOR;							// Add some Slop

	if(system_memory>=256)
		page->SetEntry("LoadRadius", 4 );
	else
		page->SetEntry("LoadRadius", 1 );



	Stuff::Page *serverpage = notefile.SetPage("server");
	Check_Object(serverpage);

	bool temp_bool = false;
	if (!serverpage->GetEntry("AllowDecalTransfer", &temp_bool))
	{
		serverpage->SetEntry("AllowDecalTransfer", 0 );
	}



		notefile.Save();
}

void CAutoconfigDlg::InitGos()
{

	if (!gosCreated)
	{
		HINSTANCE	hInstance;
		hInstance = AfxGetResourceHandle();

		
		WNDCLASS	wc;
		wc.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
		wc.lpfnWndProc = (WNDPROC) WinProc;
		wc.cbClsExtra = 0;
		wc.cbWndExtra = 0;
		wc.hInstance = hInstance;
		wc.hIcon = NULL;
		wc.hCursor = LoadCursor( NULL, IDC_ARROW );
		wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
		wc.lpszMenuName = "Test MFC";
		wc.lpszClassName = "Test MFC";
		RegisterClass(&wc);

		RECT WindowRect;
		WindowRect.left=0;
		WindowRect.top=0;
		WindowRect.right=640;
		WindowRect.bottom=480;
		AdjustWindowRect( &WindowRect,WS_OVERLAPPED,0 );

		Window = CreateWindow( "Test MFC", "Test MFC",
								WS_OVERLAPPEDWINDOW,
								CW_USEDEFAULT, CW_USEDEFAULT,
								WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top,
								NULL, NULL, hInstance, NULL);

		//::ShowWindow( Window, SW_SHOWDEFAULT );

		//
		// Init GameOS with window created
		//
		InitGameOS( hInstance, Window, NULL );

		gosCreated = true;
	}
}



void CAutoconfigDlg::OnTest() 
{

	Stuff::ArmorLevel = 4;

	
	InitGos();

	int bestdev=BestDevice();
	for(int i=0;i<m_VideCardList.GetCount();i++)
	 if(m_VideCardList.GetItemData(i)==bestdev)
		m_VideCardList.SetCurSel(i);

	AutoDetectLevel(bestdev);
}

int CAutoconfigDlg::BestDevice()
{
	int lowdev=PERDEVCOUNT,dsel=-1,devmem=-1;
	int devcount=gos_GetMachineInformation( gos_Info_NumberDevices);
	int i,j;
	
	if(devcount<=0)
		STOP(("No Rendering Devices Found"));
	

	for(i=0;i<devcount;i++)
		for(j=0;j<lowdev;j++)
		{
		if(!strcmpi(PerferedDeviceList[j],(char *)gos_GetMachineInformation( gos_Info_GetDeviceName,i)))
			{
			dsel=i;
			lowdev=j;
			devmem=GetDeviceMemory(i);
			break;
			}
		}


		int himem=-1,hidev=-1;
		for(i=0;i<devcount;i++)
		{	
			if(himem<(int)GetDeviceMemory(i))
			{
				himem=(int)GetDeviceMemory(i);
				hidev=i;
			}
		}
			
		if(dsel>=0 && hidev>=0)
		{
			dsel=GetDeviceMemory(dsel)>GetDeviceMemory(himem)?dsel:himem;
		}
		else
			dsel=hidev;

	Verify(dsel>=0 && dsel<devcount);
	return dsel;
}

void CAutoconfigDlg::InitComboBoxes()
{
	CString string;
	int itm;


	int devcount=gos_GetMachineInformation( gos_Info_NumberDevices);
	int i;
	
	if(devcount<=0)
		STOP(("No Rendering Devices Found"));
	
	for(i=0;i<devcount && i<16;i++)
	{
	CString str=(char *)gos_GetMachineInformation( gos_Info_GetDeviceName,i);

	if(GetDeviceMemory(i)<LOWVMEM)
		{
		BadCard[i]=true;
		str+=": UnSupported";
		}
		else
		{
		BadCard[i]=false;
		}
	
	itm=m_VideCardList.AddString(str);
	m_VideCardList.SetItemData(itm,i);
	
	}
	
				

	int bestdev=BestDevice();
	for(i=0;i<m_VideCardList.GetCount();i++)
	 if(m_VideCardList.GetItemData(i)==bestdev)
		m_VideCardList.SetCurSel(i);
	GetResList();	
 
}

void CAutoconfigDlg::GetResList()
{
m_ScreenResList.ResetContent();
	int device=m_VideCardList.GetItemData(m_VideCardList.GetCurSel());

DWORD nummodes,depth,screenval,sx,sy;

depth=16;
for(int modepass=0;modepass<2;modepass++)
{
nummodes=gos_GetMachineInformation(gos_Info_NumberValidModes,device,depth);
for(int modenum=0;modenum<nummodes;modenum++)
{
	screenval=gos_GetMachineInformation(gos_Info_GetValidMode,device,depth,modenum);
	sy=screenval&0xffff;
	sx=screenval>>16;
	if( (sx>=640 && sy>=480) &&
		(
		(sx==640 && sy==480) ||
		(sx==800 && sy==600) ||
		(sx==1024 && sy==768) ||
		(sx==1280 && sy==1024) ||
		(sx==1600 && sy==1200) 
		)
	  )
	{
	CString modestr;
	modestr.Format("%ix%ix%i",sx,sy,depth);
	int itm=m_ScreenResList.AddString(modestr);
	m_ScreenResList.SetItemData(itm,(depth<<16)|modenum);
	}
}
depth=32;
}

m_ScreenResList.SetCurSel(0);

}

int CAutoconfigDlg::GetModeInList(int xval,int yval,int dep)
{
int mode=-1;
	for(int i=0;i<m_ScreenResList.GetCount() && mode==-1;i++)
		{
		DWORD sresval=m_ScreenResList.GetItemData(i);
		int device=m_VideCardList.GetItemData(m_VideCardList.GetCurSel());
		DWORD screenval=gos_GetMachineInformation(gos_Info_GetValidMode,device,sresval>>16,sresval&0xffff);

		int x,y,d;
		x=screenval>>16;	
		y=screenval&0xffff;
		d=sresval>>16;	
		if(x==xval && y==yval && d==dep) mode=i;
		}
return mode;
}

void CAutoconfigDlg::DefaultToLevel(int syslev)
{
		m_MachineList.SetCurSel(syslev);
int mode;
	switch (syslev)
	{
	case L_Low:
		m_DetailList.SetCurSel(0);
		m_MultiTextureList.SetCurSel(0);
		m_LightMapList.SetCurSel(0);
		m_VertexLightList.SetCurSel(0);
		m_CultList.SetCurSel(0);
		m_FootStepList.SetCurSel(0);
		m_MusicList.SetCurSel(0);
		m_NoBlendList.SetCurSel(1);
		
		m_TextureLevelList.SetCurSel(2);

		m_ShadowList.SetCurSel(0);
		m_WaterList.SetCurSel(0);
		m_TerrainLevelList.SetCurSel(0);
		m_SDetailList.SetCurSel(0);
		m_MaxLightsList.SetCurSel(0);
		m_LODLevelList.SetCurSel(0);
		m_EffectList.SetCurSel(0);
		m_AntiAliasList.SetCurSel(0);
		m_FontSize.SetCurSel(2);

		mode=GetModeInList(640,480,16);
		m_ScreenResList.SetCurSel(mode>=0?mode:0);
		break;

	case L_Med:
		m_DetailList.SetCurSel(1);
		m_MultiTextureList.SetCurSel(1);
		m_LightMapList.SetCurSel(1);
		m_VertexLightList.SetCurSel(1);
		m_CultList.SetCurSel(1);
		m_FootStepList.SetCurSel(1);
		m_MusicList.SetCurSel(1);
		m_NoBlendList.SetCurSel(0);
		
		m_TextureLevelList.SetCurSel(1);

		m_WaterList.SetCurSel(1);
		m_MaxLightsList.SetCurSel(1);
		m_SDetailList.SetCurSel(1);

		m_ShadowList.SetCurSel(1);
		m_TerrainLevelList.SetCurSel(1);
		m_LODLevelList.SetCurSel(1);
		m_EffectList.SetCurSel(1);
		m_AntiAliasList.SetCurSel(0);
		m_FontSize.SetCurSel(2);

		mode=GetModeInList(800,600,16);
		m_ScreenResList.SetCurSel(mode>=0?mode:0);
		break;

	default:
	case L_High:
		m_DetailList.SetCurSel(1);
		m_MultiTextureList.SetCurSel(1);
		m_LightMapList.SetCurSel(1);
		m_VertexLightList.SetCurSel(1);
		m_CultList.SetCurSel(1);
		m_FootStepList.SetCurSel(1);
		m_MusicList.SetCurSel(1);
		m_NoBlendList.SetCurSel(0);
		
		m_TextureLevelList.SetCurSel(0);

		m_WaterList.SetCurSel(2);
		m_MaxLightsList.SetCurSel(2);
		m_SDetailList.SetCurSel(2);

		m_ShadowList.SetCurSel(2);
		m_TerrainLevelList.SetCurSel(2);
		m_LODLevelList.SetCurSel(2);
		m_EffectList.SetCurSel(2);
		m_AntiAliasList.SetCurSel(0);
		m_FontSize.SetCurSel(2);

		mode=GetModeInList(800,600,16);
		m_ScreenResList.SetCurSel(mode>=0?mode:0);
		break;
	
	case L_XHigh:
		m_DetailList.SetCurSel(1);
		m_MultiTextureList.SetCurSel(1);
		m_LightMapList.SetCurSel(1);
		m_VertexLightList.SetCurSel(1);
		m_CultList.SetCurSel(1);
		m_FootStepList.SetCurSel(1);
		m_MusicList.SetCurSel(1);
		m_NoBlendList.SetCurSel(0);
		
		m_TextureLevelList.SetCurSel(0);

		m_WaterList.SetCurSel(2);
		m_MaxLightsList.SetCurSel(2);
		m_SDetailList.SetCurSel(3);

		m_ShadowList.SetCurSel(2);
		m_TerrainLevelList.SetCurSel(3);
		m_LODLevelList.SetCurSel(3);
		m_EffectList.SetCurSel(3);
		m_AntiAliasList.SetCurSel(0);
		m_FontSize.SetCurSel(2);

		mode=GetModeInList(800,600,16);
		m_ScreenResList.SetCurSel(mode>=0?mode:0);
		break;

	}



}

void CAutoconfigDlg::OnClose() 
{
if(BadCard[m_VideCardList.GetCurSel()])
{	
CConfigError dlg(m_VideCardList.GetCount()>1,this);
dlg.DoModal();

switch(dlg.retval)
{
case -1: Save(true); CDialog::OnClose(); return; break;
case 0: return; break;
case 1: Save(false); CDialog::OnClose(); break;
}
return;

}
	Save(false); 
	CDialog::OnClose();
}

void CAutoconfigDlg::OnExit() 
{
if(BadCard[m_VideCardList.GetCurSel()])
{	
CConfigError dlg(m_VideCardList.GetCount()>1,this);
dlg.DoModal();

switch(dlg.retval)
{
case -1: Save(true); CDialog::OnOK(); return; break;
case 0: return; break;
case 1: Save(false); CDialog::OnOK(); return; break;
}
return;
}

	Save(false); 

	CDialog::OnOK();

}




void CAutoconfigDlg::OnSelchangeVideocard() 
{
	// TODO: Add your control notification handler code here
		GetResList();	
		AutoDetectLevel(m_VideCardList.GetItemData(m_VideCardList.GetCurSel()));
}

LRESULT CAutoconfigDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	// TODO: Add your specialized code here and/or call the base class
LRESULT res=NULL;
			__try
			{
			res=CDialog::WindowProc(message, wParam, lParam);
			}
			__except(ProcessException(GetExceptionInformation()))
			{
			}

return res;
}

void CAutoconfigDlg::SetDlgMode(bool simple)
{

	m_ShadowList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_WaterList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_VideCardList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_VertexLightList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_TextureLevelList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_TerrainLevelList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_SDetailList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_ScreenResList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_NoBlendList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_MusicList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_MultiTextureList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_MaxLightsList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_LODLevelList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_LightMapList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_FootStepList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_EffectList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_DetailList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_CultList.ShowWindow(simple?SW_HIDE:SW_SHOW);
	m_AdvBut.ShowWindow(simple?SW_SHOW:SW_HIDE);
	
	m_SimBut.ShowWindow(simple?SW_HIDE:SW_SHOW);

	if(simple)
	{
		GetWindowRect(&OrgRect);
		CRect rct;	
		m_MachineList.GetWindowRect(&rct);
		ScreenToClient(&rct);
		SetWindowPos(NULL,0,0,OrgRect.Width(),rct.bottom+50,SWP_NOMOVE|SWP_NOZORDER);	
	}
	else
	
		SetWindowPos(NULL,0,0,OrgRect.Width(),OrgRect.Height(),SWP_NOMOVE|SWP_NOZORDER);	

}	


void CAutoconfigDlg::OnAdvanced() 
{
	SetDlgMode(false);
}

void CAutoconfigDlg::OnSimple() 
{
	SetDlgMode(true);
}

void CAutoconfigDlg::OnSelchangeMachine() 
{
	// TODO: Add your control notification handler code here
DefaultToLevel(m_MachineList.GetCurSel());

}
