//===========================================================================//
// File:	MW4Application.cpp													        //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 08/25/97  JMA  Infrastructure changes.                                    //
// 08/25/97  ECH  Infrastructure changes.                                    //
// 08/27/98  BDB  Made it MW4			                                     //
// 09/29/98  BDB  added gosFX shit		                                     //
//---------------------------------------------------------------------------//
// Copyright (C) 1995-97, Virtual World Entertainment, Inc.                  //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include "MW4AppHeaders.hpp"
#include "MW4Application.hpp"
#include <windows.h>
#include <MW4DedicatedUI\DedicatedUI.hpp>
#include <GameOS\GameOS.hpp>
#include <GameOS\Platform.hpp>
#include <GameOs\Network.hpp>
#include <gosFX\gosFX.hpp>
#include <gosFX\EffectLibrary.hpp>
#include <Adept\Application.hpp>
#include <MW4\MWApplication.hpp>
#include <gosScript\gosScriptHeaders.hpp>
#include <Adept\ResourceImagePool.hpp>
#include <MW4\MWMission.hpp>
#include <MW4\MWPlayer.hpp>
#include <Compost\Compost.hpp>
#include <mw4\gameinfo.hpp>
#include <Adept\ResourceEffectLibrary.hpp>
#include <mw4\ai_statistics.hpp>
#include "mw4\mw4shell.hpp"
#include "mw4\hudcomp.hpp"

#include <Adept\GlobalPointerManager.hpp>

#include <MW4\MWTool.hpp>
#include <Stuff\Random.hpp>

#include <MLR\MLR.hpp>
#include <MLR\MLRTexturePool.hpp>
#include <MLR\MLRTexture.hpp>
#include <adept\gamespy\gamespy.h>
#include <GameOS\GUNGameList.h>
#include <process.h>

#if 0
	extern MidLevelRenderer::MLRTexture *g_BergerName;
	extern bool s_NoAbzug;
#endif

#include "..\buildnum\buildnum.h" // current version and build number
#include "..\missionLang\resource.h" // current version and build number
#include "eula.h"

// jcem - start
#include "ctcls.h"
#include "ctcl.h" // jcem

extern Time g_fLastGameStart;
void CTCL_API CTCL_DoGame1st();

#pragma data_seg(".SHARED_DATA")
// all data in this section must be INITIALIZED!!!!!!!!!!!!!
BOOL g_bLaunched = FALSE;
#pragma data_seg()
#pragma comment(linker, "/section:.SHARED_DATA,RWS")

extern bool g_bTeslaIsCameraShip;
extern CamerashipParams g_CamerashipParams;
extern int g_bUseOrgJoy;
extern bool g_bNoWeaponRangeCheck;
extern bool g_bPRTest;
extern bool g_bMRTest;
extern int g_bNoPlasma;
extern bool g_bNoTOCKeys;
extern float g_fZoomMarginLR;
extern float g_fZoomFOVA;
extern float g_fZoomFOVB;
extern float g_fZoomTime;
extern Time g_PlasmaClearTime;
extern Time g_TOC_ADT;
extern Time g_AUX_ADT;
extern bool g_UseMSRSP;
extern int g_nTypeOfMFDs; // 0 - no MFDs, 1 - orginal(5+1=dual & single), 2 - B&W(3 + 1=1 dual), 3 - color(3 + 1=2 dual)
extern int g_nRIOType;
extern DWORD g_dwRIOBaud; // [tbaud]
extern LONG g_ThrottleDir;
extern bool g_bCanSuicideAllways;
extern bool g_f3dtarget;

extern char g_szTeslaAddr[128];
extern DWORD g_dwTeslaAddr;

extern void (__stdcall *g_pfnCTCL_Proc)();
extern int (_stdcall* g_pfnCTCL_GetType)();
int _stdcall __CTCL_GetType();

extern int _stdcall VehGetShutdownState();
extern int (_stdcall *g_pfnVehGetShutdownState)();

extern int g_nCTCL;
BOOL __stdcall CTCL_Before();
void __stdcall CTCL_After();
void __stdcall CTCL_Proc();

extern bool g_bCOOP; // COin OPeration
extern int g_nCoinCount;
extern int g_nCoinPerGame;
extern bool g_bUseCam;
extern bool g_bUseJPD; // Use Joystick as Pointing Device
extern bool g_bOldLOG;
extern int g_nMechViewType;
// jcem - end

extern void _stdcall ExitGameOS();

// ngLog addition
#include <mw4/nglog_mw4.hpp>

extern DWORD LogMode;
bool __stdcall AlreadyRunning();

#ifdef LAB_ONLY
extern bool
	saveMapBspDifference;
#endif



//#############################################################################
//#############################    GameEngine    ##############################
//#############################################################################

char *Command_Line;

extern void * __cdecl GetMech4SpecialGameData(int data_type, ...);


#ifdef LAB_ONLY
	bool Bloat = true;
#endif


int bloatSizeTable[8] = {
	16,
	32,
	64,
	128,
	256,
	1024,
	2048,
	4096
};

#define BLOAT_MEMORY_LAB_ONLY(heap)\
{\
	if (Bloat)\
	{\
		int total_bloat = Random::GetLessThan(8);\
		Min_Clamp(total_bloat, 4);\
		for (int i = 0; i < total_bloat; ++i)\
		{\
			int size_to_alloc = Random::GetLessThan(8);\
			gos_Malloc(bloatSizeTable[size_to_alloc], heap);\
		}\
	}\
}

#define BLOAT_MEMORY_REL(heap)\
{\
	int total_bloat = Random::GetLessThan(8);\
	Min_Clamp(total_bloat, 4);\
	for (int i = 0; i < total_bloat; ++i)\
	{\
		int size_to_alloc = Random::GetLessThan(8);\
		gos_Malloc(bloatSizeTable[size_to_alloc], heap);\
	}\
}

#ifdef LAB_ONLY
	#define BLOAT_MEMORY BLOAT_MEMORY_LAB_ONLY
#else
	#define BLOAT_MEMORY BLOAT_MEMORY_REL
#endif

extern bool(__cdecl *NoCDMessageFunction)(void);

extern bool gNoDialogs;
//sanghoon begin
extern bool use_shgui;
extern int SCREENS;
//sanghoon end

bool gRunEula=true;
bool gNoCD=false;
bool gNoAutoConfig=false;
extern bool gShowScriptErrors;

bool _cdecl NoCDWarning(void)
{
	return WinMessageBox(MWApplication::GetInstance()->GetLocString(IDS_INSERTCD),MWApplication::GetInstance()->GetLocString(IDS_PLAY_CD_MESSAGE));
}

bool IsPlayCDPresent()
{
if(gNoCD) return true;
	
	char cd_path[256];
		DWORD size=sizeof(cd_path);
		gos_LoadDataFromRegistry(
			"CDPath",
			cd_path,
			&size,
			TRUE
		);

		if (size>0)
		{
		char *tmpptr=cd_path;
		if(tmpptr[0]=='\\' && tmpptr[1]=='\\') tmpptr+=2;
		while(*tmpptr!='\\' && *tmpptr) tmpptr++;
		if(*tmpptr=='\0') tmpptr[0]='\\';
		tmpptr[1]='\0';
		char vlabel[256];
		bool res=gos_GetDriveLabel(cd_path,vlabel,256);

		if(!res) return false;
		if(strcmpi(vlabel,"MECHWARR_01") && strcmpi(vlabel,"MECHWARR_02"))
			return false;
		
		}
		else
		{
		STOP(("%s",MWApplication::GetInstance()->GetLocString(IDS_BADSETUP)));
		}

	return true;
}

bool IsFirstRun()
{
	DWORD frun=false;
		DWORD size=sizeof(frun);
		gos_LoadDataFromRegistry(
			"FIRSTRUN",
			&frun,
			&size,
			FALSE
		);

	return !frun;
}

bool RunAutoConfigIfNeeded()
{
#if 0 // jcem
		if (IsFirstRun())
		{
		if(!gos_DoesFileExist("autoconfig.exe"))
			return true;
			//STOP(("Cannot Locate Autoconfig.exe"));

		ExecuteAndWait("autoconfig.exe");
		}
#endif // jcem
	return true;
}


extern void __stdcall EnterWindowMode();
extern void __stdcall EnterFullScreenMode();


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void _stdcall InitializeGameEngine()
{
	// Set_Heap_Check(1, 100);

	//
	//---------------------
	// Initialize libraries
	//---------------------
	//



//	bool needflip=Environment.fullScreen && IsFirstRun();
	//sanghoon begin
	bool needflip=false;
	//sanghoon end
	if(needflip){ 
		//sanghoon begin
		//MessageBeep(MB_ICONEXCLAMATION);
		//sanghoon end

		EnterWindowMode();
	}
	
	Stuff::InitializeClasses(4800, 40000);

	#if defined(LAB_ONLY)
		if (!CallDebuggerMenuItem("Debugger\\Options\\Show percentages as milliseconds", gosMenu_CheckMark))
			CallDebuggerMenuItem("Debugger\\Options\\Show percentages as milliseconds", gosMenu_Activated);
	#endif

	
	BLOAT_MEMORY(Stuff::g_Heap);
	
	if(!gNoAutoConfig)
		RunAutoConfigIfNeeded();
	
	NotationFile startup_ini("options.ini", NotationFile::Standard, true);
	
    g_CamerashipParams.LoadOptions(startup_ini);

	Stuff::Page *compage = startup_ini.FindPage("special commands");
	if(compage!=NULL)
	{
		bool kill;
		if(compage->GetEntry("killgame",&kill) && kill)
		{
		compage->SetEntry("killgame",false);
		startup_ini.Save();
		ExitGameOS();
		}
	}	

	
	Page *page=startup_ini.FindPage("graphics options");
	if(page!=NULL)
	{
		//Original
		//page->GetEntry("videodriverindex",&Environment.FullScreenDevice);
		//sanghoon
		Environment.FullScreenDevice=0;
		page->GetEntry("antialias",&Environment.AntiAlias);
		page->GetEntry("bitdepth",&Environment.bitDepth);
	}

	page=startup_ini.FindPage("sound options");
	if(page!=NULL)
	{
		page->GetEntry("hardwaremixing",&Environment.soundMixInHardware);
	}

	page=startup_ini.FindPage("special commands");
	if(page!=NULL)
	{
		page->GetEntry("AutoTorsoCenter",&VehicleInterface::perminateTorsoMode);
		//Original
		//page->GetEntry("HudDamageMode",&VehicleInterface::hudDamageMode);
		//page->GetEntry("HudTargetDamageMode",&VehicleInterface::hudTargetDamageMode);
		//sanghoon
		VehicleInterface::hudDamageMode=false;
		VehicleInterface::hudTargetDamageMode=false;
	}

	MidLevelRenderer::InitializeClasses(&startup_ini, 2048, 2048);
	gosFX::InitializeClasses(&startup_ini);
	ElementRenderer::InitializeClasses(&startup_ini);
	Compost::InitializeClasses(&startup_ini);
	Adept::InitializeClasses(&startup_ini);
	BLOAT_MEMORY(Adept::g_Heap);
	MechWarrior4::InitializeClasses(&startup_ini);
	BLOAT_MEMORY(MechWarrior4::Heap);

	HUDText::LoadFontSizeDelta (&startup_ini);
	VehicleInterface::LoadMouseYFlag (&startup_ini);
	VehicleInterface::LoadMouseMinMax (&startup_ini);


#if 0
	WORD day, month, year;
	gos_GetUnformattedDate(&year, &month, &day);

	if (year > 2000)
	{
		// this is just to make it look a little less obvious!
		int port = 24000;
		gos_SaveDataToRegistry("proxyport",&port, 4);
		STOP(("MechWarrior4 Beta has expired"));
		gos_TerminateApplication();
	}
	if (year == 2000)
	{
		if (month >= 12)
		{
			int port = 24000;
			gos_SaveDataToRegistry("proxyport",&port, 4);
			STOP(("MechWarrior4 Beta has expired"));
			gos_TerminateApplication();
		}
	}
	
	int port = 0;
	DWORD size = 4;
	gos_LoadDataFromRegistry("proxyport",&port,&size);

	if (size > 0)
	{
		STOP(("MechWarrior4 Beta has expired"));
	}
#endif

	//
	//----------------------------------------------------------
	// Parse command line and verify that game name has been set
	//----------------------------------------------------------
	//
	if (Application::TestClasses)
		MW4Testall();

	//
	//--------------------------------------
	// Create and initialize the application
	//--------------------------------------
	//
	gos_PushCurrentHeap(MechWarrior4::Heap);
	MWApplication *MW_Application =
		new MWApplication(MWApplication::DefaultData,true);
	Check_Object(MW_Application);
	//Adept::Application::GetInstance() = MW_Application;
	GlobalPointers::AddGlobalPointer(MW_Application, ApplicationGlobalPointerIndex);
	MW_Application->Initialize();


	// Set the Localized No CD Message for Stuff DataBase
	NoCDMessageFunction=NoCDWarning;


	//
	//---------------------------------------------------------
	// If we have a resource build command, build the resources
	//---------------------------------------------------------
	//
	if (Adept::Application::BuildOK)
	{
		Verify(!NotationFile::s_cachedIncludes);
		NotationFile::s_cachedIncludes = new stlport::map<MString, FileStream*>;

		Tool::Instance = new MWTool();
		Check_Object(Tool::Instance);

		gos_PushCurrentHeap(gosFX::Heap);
		gosFX::EffectLibrary::Instance = new ResourceEffectLibrary(true);
		gos_PopCurrentHeap();
		Stuff::NotationFile build_script("Content\\MechWarrior4.build");
		FileDependencies deps;
		Tool::Instance->BuildResources(&build_script, VER_CONTENTVERSION, &deps);
		delete gosFX::EffectLibrary::Instance;
		Verify(!gosFX::EffectLibrary::Instance);
		Adept::Application::BuildOK = false;

		delete Tool::Instance;
		Tool::Instance = NULL;

		stlport::map<MString, FileStream*> *map = (stlport::map<MString, FileStream*>*)NotationFile::s_cachedIncludes;
		stlport::map<MString, FileStream*>::iterator seeker = map->begin();
		while (seeker != map->end())
		{
			FileStream *file = (*seeker).second;
			Check_Object(file);
			delete file;
			++seeker;
		}
		delete map;
		NotationFile::s_cachedIncludes = NULL;
	}
	else if (!gos_DoesFileExist("Resource\\Variants"))
		gos_CreateDirectory("Resource\\Variants");
	



	
	//--------------------------------------
	// Run the Eula
	//--------------------------------------

	
	if(gRunEula && Application::RunOK && !gNoDialogs)
	{
		bool gotlicense=false;
		while(!gotlicense)

		{
		MString ename,wname;
			ename=MWApplication::GetInstance()->GetLocString(IDS_EULA_FILENAME);
			wname=MWApplication::GetInstance()->GetLocString(IDS_WARRANTY_FILENAME);
		if(!FirstRunEula(ename,wname))
		{
		MString msg,cap;
			msg=MWApplication::GetInstance()->GetLocString(IDS_EULA_FAIL_MESSAGE);
			cap=MWApplication::GetInstance()->GetLocString(IDS_EULA_FAIL_CAPTION);
			if(EulaDeclineMsg(msg,cap))
			{
				ExitGameOS();
			}
		}
			else
			{
				gotlicense=true;
			}
		}
		
		//--------------------------------------
		// Verify the CD
		//--------------------------------------
		if(!gNoCD)		{
			bool res=true;
			while(!IsPlayCDPresent() && res)
			{
			res=NoCDWarning();
			if(!res)
				ExitGameOS();
			}
		
		}
	}
	
	if(needflip) EnterFullScreenMode();
	

	if (!MWApplication::AutoLaunchServerGame)
	{
		if(!gos_GetMachineInformation(gos_Info_UsingHardwareRenderer))
		{
		MString msg,cap;
		msg=MWApplication::GetInstance()->GetLocString(IDS_NOHARDWARE);
		cap=MWApplication::GetInstance()->GetLocString(IDS_HARDWAREERROR);
		WinMessageBox(cap,msg,1);
		ExitGameOS();
		}
	}
	
	//
	//------------------------------------------------------------------
	// Now that we are out of building mode, reset the file hooks to use
	// resources
	//------------------------------------------------------------------
	//
	Environment.HookGetFile = Application::GetFileForGOS;
	Environment.HookDoesFileExist = Application::FindFileForGOS;
	Environment.defaultPlayerName = NULL;

	//
	// Now that resources are built. Add another layer in the getfile and find file change that can
	// watch for .mw4 file requests and potentially remap them for 8.3 compatibility.
	//
//	Environment.HookGetFile = MWApplication::MW4GetFileForGOS;
//	Environment.HookDoesFileExist = MWApplication::MW4FindFileForGOS;

	//
	//-----------------------------------------------
	// Terminate the game if running is not permitted
	//-----------------------------------------------
	//
	if (!Adept::Application::RunOK)
	{
		gos_TerminateApplication();
	}
	else
	{

		// generate the keys...
		MWApplication::GetInstance()->localKey = MWApplication::GetInstance()->GetUniqueKey();
		

		//
		//--------------------------------------------------------
		// We have disabled building, so load up the required data
		//--------------------------------------------------------
		//
		ResourceManager::Instance->OpenResourceFile(
			"Resource\\textures.mw4",
			NULL,
			TexturesResourceFileID,
			VER_CONTENTVERSION,
			true,
			false
		);
		ResourceManager::Instance->OpenResourceFile(
			"Resource\\core.mw4",
			NULL,
			CoreResourceFileID,
			VER_CONTENTVERSION,
			true,
			false
		);
		ResourceManager::Instance->OpenResourceFile(
			"Resource\\props.mw4",
			NULL,
			PropsResourceFileID,
			VER_CONTENTVERSION,
			true,
			false
		);

		MWApplication::GetInstance()->LoadLookupTables();
	}



//#ifdef LAB_ONLY
//	g_BergerName = MidLevelRenderer::MLRTexturePool::Instance->Add ("bf");
//#endif

	BLOAT_MEMORY(MechWarrior4::Heap);


	gos_PopCurrentHeap();

    // jcem - begin
    if (!CTCL_Before()) {
        gos_TerminateApplication();
    }
    // jcem - end
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void _stdcall TerminateGameEngine()
{
	//
	//-------------------
	// Shut down the game
	//-------------------
	//
    // jcem - start
    CTCL_After();
    if ( ServerBrowser::GetGameList() ) {
        ServerBrowser::GetGameList()->ShutdownPing();
        ServerBrowser::DestroyGameList();
    }

    // jcem - end
	gos_PushCurrentHeap(MechWarrior4::Heap);
	Adept::Application::GetInstance()->StopGame();
	Adept::Application::GetInstance()->Terminate();
	Unregister_Object(Adept::Application::GetInstance());
	delete Adept::Application::GetInstance();
	GlobalPointers::ClearPointer(ApplicationGlobalPointerIndex);

	//
	//------------------------------------------------------
	// If we are shutting down a tool run, kill off the tool
	//------------------------------------------------------
	//
	if (Tool::Instance)
	{
		Unregister_Object(Tool::Instance);
		delete Tool::Instance;
	}
	gos_PopCurrentHeap();

	//
	//-----------------------
	// Shutdown the libraries
	//-----------------------
	//
	{
		NotationFile startup_ini("options.ini", NotationFile::Standard, true);
		MechWarrior4::TerminateClasses(&startup_ini);
		Adept::TerminateClasses(&startup_ini);
		Compost::TerminateClasses(&startup_ini);
		ElementRenderer::TerminateClasses(&startup_ini);
		gosFX::TerminateClasses(&startup_ini);
		MidLevelRenderer::TerminateClasses(&startup_ini);
		Page *page=startup_ini.SetPage("graphics options");
		Check_Object(page);
// MSL 5.02 Prevent Option Overwrite
//		page->SetEntry("bitdepth",Environment.bitDepth);
		page->SetEntry("videodriverindex",Environment.FullScreenDevice);
// MSL 5.02 Prevent Option Overwrite
//		page->SetEntry("antialias",Environment.AntiAlias);
		page=startup_ini.SetPage("sound options");
		Check_Object(page);
		page->SetEntry("hardwaremixing",Environment.soundMixInHardware);
		page=startup_ini.SetPage("special commands");
		Check_Object(page);
		page->SetEntry("AutoTorsoCenter",VehicleInterface::perminateTorsoMode);
		//Original
		//page->SetEntry("HudDamageMode",VehicleInterface::hudDamageMode);
		//page->SetEntry("HudTargetDamageMode",VehicleInterface::hudTargetDamageMode);
		startup_ini.Save();
	}
	Stuff::TerminateClasses();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

char *
	MakeArgumentString(char *start)
{

	char *current_pos = start;
	int length = -1;
	while (current_pos != NULL)
	{
		if (*current_pos == '-')
		{
			length = current_pos - start - 1;
			break;
		}

		if (*current_pos == '\0')
		{
			length = current_pos - start;
			break;
		}
		++current_pos;
	}

	// CHECK FOR NO PARAMETERS
	if (length == -1)
	{
		STOP(("INVALID PARAMETER : No parameter specified"));
	}

	// CHECK FOR A SPACE AT THE END OF THE PARAMETER
	if (start[length] != ' ' && start[length] != '\0')
	{
		STOP(("INVALID PARAMETER : No space after parameter"));
	}


	// CHECK FOR ALL SPACES
	{
		for (int i = 0; i < length; ++i)
		{
			if (start[i] != ' ')
				break;
		}

		if (i == length)
		{
			STOP(("INVALID PARAMETER : No parameter specified"));
		}
	}


	char *argument_string = new char [length+1];

	// can't use strcopy since we don't have a null after the parameter
	strncpy(argument_string, start, length);
	argument_string[length] = '\0';

	return argument_string;

}

//========================================================================
//========================================================================
#ifdef _DEBUG
//extern "C" void __stdcall RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, const DWORD *lpArguments);
//extern "C" DWORD __stdcall GetCurrentThreadId(void);
WINBASEAPI
VOID
WINAPI
RaiseException(
    DWORD dwExceptionCode,
    DWORD dwExceptionFlags,
    DWORD nNumberOfArguments,
    CONST DWORD *lpArguments
    );
WINBASEAPI
DWORD
WINAPI
GetCurrentThreadId(
    VOID
    );

typedef struct tagTHREADNAME_INFO
{
	DWORD	dwType;		// must be 0x1000
	char *	szName;		// pointer to name (in user addr space)
	DWORD	dwThreadID;	// thread ID (-1=caller thread)
	DWORD	dwFlags;	// reserved for future use, must be zero
} THREADNAME_INFO;

void __stdcall SetThreadName(DWORD dwThreadID, char *szThreadName)
{
	THREADNAME_INFO info;
	
	info.dwType		= 0x1000;
	info.szName		= szThreadName;
	info.dwThreadID	= dwThreadID;
	info.dwFlags	= 0;

	__try
	{
		RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
	}
	__except (-1)
	{
	}
}
#endif

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//extern "C" DWORD __stdcall GetEnvironmentVariableA(char * lpName, char * lpBuffer, DWORD nSize);
WINBASEAPI
DWORD
WINAPI
GetEnvironmentVariableA(
    LPCSTR lpName,
    LPSTR lpBuffer,
    DWORD nSize
    );
void __stdcall GetGameOSEnvironment(char* CommandLine)
{
#ifdef _DEBUG
	//
	// name that thread
	//
	SetThreadName(GetCurrentThreadId(), "MainThread");
#endif

	//
	//-----------------------------------------------
	// This is where to set GOS environment settings.
	//-----------------------------------------------
	//

	
	Command_Line = CommandLine;
	if (true)
	{
		static char szFullCommandLine[256];
		strcpy(szFullCommandLine, CommandLine);
		strcat(szFullCommandLine, " ");
		char szMech4EnvironmentVariable[256];
		szMech4EnvironmentVariable[0] = 0;
		GetEnvironmentVariableA("mw4", szMech4EnvironmentVariable, sizeof(szMech4EnvironmentVariable));
		strcat(szFullCommandLine, szMech4EnvironmentVariable);

		CommandLine = szFullCommandLine;
		Command_Line = szFullCommandLine;
	}

	Environment.applicationName			= "BattleTech Firestorm"; // "MechWarrior Vengeance";
	Environment.version					= VER_PRODUCTVERSION_STR;
	Environment.directoryPath			= "code\\MW4Application;Binaries\\MW4";
	

	Environment.screenWidth				= 800;
	Environment.screenHeight			= 600;
	Environment.bitDepth				= 16;
	
	Environment.FullScreenDevice		= 0;
	Environment.Renderer				= 0;
	Environment.disableZBuffer			= false;
	Environment.AntiAlias				= false;

	Environment.MegMemoryRequired		= 192;
	Environment.MinimumTextureMemory	= 5*1024;		// cards with less than this video memory - use Blade

	Environment.Key_FullScreen			= 0;
	Environment.Key_SwitchMonitors		= 0;
	Environment.Key_Exit				= 0;

	Environment.debugLog				= "Mechwarrior4.txt";
	Environment.spew					= "GameOS_Memory"; //GROUP_ADEPT_RESOURCE;
	#if defined(_ARMOR)
		Environment.memoryTraceLevel	= 5;
	#endif
	Environment.TimeStampSpew			= false;

	Environment.MaxTimeDelta			= 0.25f;
	Environment.MinimumTimeDelta		= 0.25f;

	Environment.soundHiFi				= false;
	Environment.soundDevice				= 0;
	Environment.soundChannels			= 32;

	Environment.allowMultipleApps		= false;
	Environment.AllowJoinInProgress		= true;
	Environment.NetworkGame				= true;
	Environment.NetworkMaxPlayers		= 16;
	Environment.NetworkGUID[0]			= 0x95;
	Environment.NetworkGUID[1]			= 0x78;
	Environment.NetworkGUID[2]			= 0xFF;
	Environment.NetworkGUID[3]			= 0xD5;
	Environment.NetworkGUID[4]			= 0x13;
	Environment.NetworkGUID[5]			= 0x81;
	Environment.NetworkGUID[6]			= 0x9F;
	Environment.NetworkGUID[7]			= 0x47;
	Environment.NetworkGUID[8]			= 0xBB;
	Environment.NetworkGUID[9]			= 0xD5;
	Environment.NetworkGUID[10]			= 0xD3;
	Environment.NetworkGUID[11]			= 0x95;
	Environment.NetworkGUID[12]			= 0xE5;
	Environment.NetworkGUID[13]			= 0x51;
	Environment.NetworkGUID[14]			= 0xD0;
	Environment.NetworkGUID[15]			= 0xA8;

	Environment.allowDoubleClicks = true;
	
#ifdef LAB_ONLY
	Environment.GetGameInformation		= GameInfo;
#else
	Environment.GetGameInformation		= NULL;
#endif

	Environment.RaidDataSource      = "MechWarrior 4:Raid4";
	Environment.RaidFilePath        = "\\\\cpaas2\\mw\\test\\goserrors";
	Environment.RaidCustomFields    = "AssignedTo=jmayo;Area=GOSRaid";
	Environment.RaidDescTemplate	= "Description:\n\nSteps to Repro:\n\nResult:\n\nExpected:\n\nNotes:\n\n";

	Environment.InitializeGameEngine	= InitializeGameEngine;
	Environment.DoGameLogic				= &MWApplication::StartUpDoShellLogic;
	Environment.UpdateRenderers			= &MWApplication::UpdateDisplay;
	Environment.TerminateGameEngine		= TerminateGameEngine;
	Environment.GetSpecialGameData		= GetMech4SpecialGameData;

	if (MWApplication::Win32DedicatedServer)
	{
		Environment.InitializeGameEngine	= CDedicatedServerUI::InitializeGameEngine;
		Environment.DoGameLogic				= &MWApplication::DoShellLogic;
		Environment.UpdateRenderers			= NULL;
		Environment.TerminateGameEngine		= CDedicatedServerUI::TerminateGameEngine;
	}
	gos_EnableSetting(gos_Set_IgnoreMaxUV, 1);

//
//
//
DWORD __stdcall gos_EnableSetting( gosSetting Setting, DWORD Value );

	//
	//-------------------------------------------------------------------
	// we need to parse out our commandline options, so convert it all to
	// lowercase
	//-------------------------------------------------------------------
	//
	static char all_lower[1024];
	strncpy(all_lower, CommandLine, sizeof(all_lower));
	all_lower[sizeof(all_lower)-1] = '\0';
	char *p;
	int i = strlen(all_lower);
	for (p=all_lower; i>0; ++p,--i)
		*p=(char)tolower(*p);

	//
	//--------------------------------------------------------------------------
	// Check the various options that don't affect debugging during log playback
	//--------------------------------------------------------------------------
	//
	Environment.allowMultipleApps = (strstr(all_lower, "-allowmultiple") != NULL);
	MWApplication::RunFromLobby = (strstr(all_lower, "-lobby") != NULL);

	char *token;

#ifdef LAB_ONLY	
	token = strstr(all_lower, "-game ");
	if (token && token[6])
	{
		MWApplication::GameFile = MakeArgumentString(&token[6]);
	}


	MWApplication::DemoMode = (strstr(all_lower, "-demo") != NULL);


#endif


	token = strstr(all_lower, "-gamename ");
	if (token && token[10])
	{
		MWApplication::NetGameName = MakeArgumentString(&token[10]);
	}

	token = strstr(all_lower, "-password ");
	if (token && token[10])
	{
		MWApplication::NetPassword = MakeArgumentString(&token[10]);
	}

	token = strstr(all_lower, "-playername ");
	if (token && token[12])
	{
		MWApplication::NetPlayerName = MakeArgumentString(&token[12]);
	}

    token = strstr(all_lower, "-advertiseport ");
    if ( token && token[15])
    {
        int port = atoi(&token[15]);
        if ( port <= 0 )
        {
    		STOP(("INVALID PARAMETER : Advertise port invalid."));
        }
        int valSize = sizeof(port);
        gos_SaveDataToRegistry( (char *) ZONE_ADVERTISE_PORT_KEY, &port, valSize);
        Environment.ZoneAdvertisePort = port;
    }


	MWApplication::SaveGameStats = (strstr(all_lower, "-gamestats") != NULL);

	MWApplication::AutoLaunchServerGame = (strstr(all_lower, "-serve") != NULL);
	//MWApplication::AutoLaunchClientGame = (strstr(all_lower, "-join") != NULL);
	Environment.DirectPlayProtocol = (strstr(all_lower, "-directplayprotocol") != NULL);

	if (MWApplication::AutoLaunchServerGame || MWApplication::AutoLaunchClientGame)
	{
		if (MWApplication::NetPlayerName == NULL)
		{
			STOP(("Cant autolaunch without -playername <name> specified"));
		}

		if (MWApplication::NetGameName == NULL)
		{
			STOP(("Cant autolaunch without -gamename <name> specified"));
		}
	}


	////////////////////////////////////////////////////////////////////////////
	// START - ngLog addition
	////////////////////////////////////////////////////////////////////////////
	// Set defaults
#if !defined(NO_LOG)
	MW4log_options_init();

	// Style of local logging
	// -zlogstyle:
	//				0 - Disable local logging (default)
	//				1 - Append/Create to specified logfile.
	//				2 - Create/overwrite any existing log file.
	//				3 - Rotate: If logname exists, create unique identifier
	//					and create new logfile with this unique name.
	//				4 - Use unique names and individual logs for each map.
	//					Also forces a call to the zStats backend processor
	//					(local zStats processing is currently not supported)
	//
	token = strstr(all_lower, "-zlogstyle ");
	if(token && token[11]) {
		z_style = atoi(&token[11]);
	}

	// Flushing semantics for local logging
	// -zlogflush:
	//				0 - Flush on every write (default).
	//				1 - Flush after "zlogbuffer" lines written.
	//				2 - Wait for system to write out buffer.
	token = strstr(all_lower, "-zlogflush ");
	if(token && token[11]) {
		z_flush = atoi(&token[11]);
	}

	// Size (in terms of lines) of internal buffer for local log flushing
	// (Default = 10 lines of buffer).
	token = strstr(all_lower, "-zlogbuffer ");
	if(token && token[12]) {
		z_buffer = atoi(&token[12]);
	}

	// Name of local log to generate (if not zStats-style log)
	// (Default = "MW4_log.log")
	token = strstr(all_lower, "-zlogname ");
	if(token && token[10]) {
		strcpy(z_logname, MakeArgumentString(&token[10]));
	}
#endif // !defined(NO_LOG)
	////////////////////////////////////////////////////////////////////////////
	// END - ngLog addition - END
	////////////////////////////////////////////////////////////////////////////


	//
	//-----------------------------------------------------------------------
	// If we aren't playing back a log file, allow setting these other things
	//-----------------------------------------------------------------------
	//
	if (!LogMode)
	{
		Environment.soundDisable = (strstr(all_lower, "-nosound") != NULL);
		Environment.fullScreen = (strstr(all_lower, "-window") == NULL);
		
		//sanghoon begin
		use_shgui=Environment.fullScreen?1:0;
        //sanghoon end
	
		gNoAutoConfig= (strstr(all_lower, "-noautoconfig") != NULL);

		Application::TestClasses = false;
		Application::RunOK = true;
		Application::BuildOK = false;
		gRunEula= true;
		MW4AI::Statistics::SetEnabled(false);
		Network::bUseNewUI = true;
		gNoCD= false;
		gShowScriptErrors = (strstr(all_lower, "-showscripterrors") != NULL);

#ifdef LAB_ONLY
		gShowScriptErrors = true;
		gNoCD = (strstr(all_lower, "-nocd") != NULL);
		if (strstr(all_lower, "-fullscreen")) Environment.fullScreen=1;
		Application::TestClasses = (strstr(all_lower, "-testclasses") != NULL);
		Application::RunOK = (strstr(all_lower, "-norun") == NULL);
		Application::BuildOK = (strstr(all_lower, "-build") != NULL);
		Application::ReportNotResourced = (strstr(all_lower, "-reportnotresourced") != NULL);
		gRunEula= (strstr(all_lower, "-noeula") == NULL);
		MW4AI::Statistics::SetEnabled(strstr(all_lower, "-aistats") != NULL);
		Network::bUseNewUI = (strstr(all_lower, "-oldmpui") == NULL);

		MWApplication::DplayNetGame = (strstr(all_lower, "-nodplay") == NULL);

		if (strstr(all_lower, "-set_internet") != NULL)
		{
			int port;

			gos_SaveStringToRegistry((char *)ZONE_SERVER_KEY, (char *)ZONE_SERVER_INTERNET_ADDRESS, strlen(ZONE_SERVER_INTERNET_ADDRESS)+1);
			gos_SaveStringToRegistry(GAMESPY_MASTER_SERVER_KEY, GAMESPY_MASTER_INTERNET_ADDR, strlen(GAMESPY_MASTER_INTERNET_ADDR)+1);
			port = GAMESPY_MASTER_INTERNET_HEARTBEAT_PORT;
			gos_SaveDataToRegistry(GAMESPY_MASTER_HEARTBEAT_PORT_KEY, &port, sizeof(port));
			port = GAMESPY_MASTER_INTERNET_QUERY_PORT;
			gos_SaveDataToRegistry(GAMESPY_MASTER_QUERY_PORT_KEY, &port, sizeof(port));
			port = GAMESPY_MASTER_INTERNET_SERVERLIST_PORT;
			gos_SaveDataToRegistry(GAMESPY_MASTER_SERVERLIST_PORT_KEY, &port, sizeof(port));
		}
		else if (strstr(all_lower, "-set_lan") != NULL)
		{
			int port;

			gos_SaveStringToRegistry((char *)ZONE_SERVER_KEY, (char *)ZONE_SERVER_LAN_ADDRESS, strlen(ZONE_SERVER_LAN_ADDRESS)+1);
			gos_SaveStringToRegistry(GAMESPY_MASTER_SERVER_KEY, GAMESPY_MASTER_LAN_ADDR, strlen(GAMESPY_MASTER_LAN_ADDR)+1);
			port = GAMESPY_MASTER_LAN_HEARTBEAT_PORT;
			gos_SaveDataToRegistry(GAMESPY_MASTER_HEARTBEAT_PORT_KEY, &port, sizeof(port));
			port = GAMESPY_MASTER_LAN_QUERY_PORT;
			gos_SaveDataToRegistry(GAMESPY_MASTER_QUERY_PORT_KEY, &port, sizeof(port));
			port = GAMESPY_MASTER_LAN_SERVERLIST_PORT;
			gos_SaveDataToRegistry(GAMESPY_MASTER_SERVERLIST_PORT_KEY, &port, sizeof(port));
		}

		saveMapBspDifference = (strstr(all_lower, "-bspmap") != NULL);;
#endif
        gNoCD = true; // jcem

		
		MWApplication::SecureNetGame = (strstr(all_lower, "-secure") != NULL);

		ServerBrowser::IPX = (strstr(all_lower, "-ipx") != NULL);


		Application::s_DiskFirst = false;

		#ifdef LAB_ONLY
			MWApplication::ReKeyResources = (strstr(all_lower, "-rekey") != NULL);
			Bloat = (strstr(all_lower, "-bloat") != NULL);
			token = strstr(all_lower, "-armorlevel ");
			if (token && token[12]>='0' && token[12]<='4')
			ArmorLevel = token[12]-'0';
			token = strstr(all_lower, "-leak ");
			if (token && token[6])
			{
			Environment.memoryTraceLevel = atoi(&token[6]);
			}
		#endif

		Application::s_DiskFirst = (strstr(all_lower, "-diskfirst") != NULL);

#if 0
		s_NoAbzug = (strstr(all_lower, "-noabzug") != NULL);
#endif
	}

	if (strstr(all_lower, "-help"))
	{
		SPEWALWAYS((NULL, "Command line options:\n"));
		SPEWALWAYS((NULL, "-allowmultiple"));
		SPEWALWAYS((NULL, "-lobby"));
		SPEWALWAYS((NULL, "-game <file>"));
		SPEWALWAYS((NULL, "-gamename <name>"));
		SPEWALWAYS((NULL, "-playername <name>"));
		SPEWALWAYS((NULL, "-serve"));
		SPEWALWAYS((NULL, "-join"));
		SPEWALWAYS((NULL, "-nosound"));
		SPEWALWAYS((NULL, "-window"));

		SPEWALWAYS((NULL, "-zlogstyle <value>"));
		SPEWALWAYS((NULL, "-zlogflush <value>"));
		SPEWALWAYS((NULL, "-zlogbuffer <size>"));
		SPEWALWAYS((NULL, "-zlogname <filename>"));
		
		SPEWALWAYS((NULL, "-secure"));

		SPEWALWAYS((NULL, "-ipx"));


		#ifdef LAB_ONLY
			SPEWALWAYS((NULL, "-nodplay"));
			SPEWALWAYS((NULL, "-dontuseipx"));
			SPEWALWAYS((NULL, "-dontusetcp"));
			SPEWALWAYS((NULL, "-dontusegamespy"));
			SPEWALWAYS((NULL, "-dontusegun"));
			SPEWALWAYS((NULL, "-aistats"));
			SPEWALWAYS((NULL, "-oldmpui"));
			SPEWALWAYS((NULL, "-testclasses"));
			SPEWALWAYS((NULL, "-build"));
			SPEWALWAYS((NULL, "-norun"));
			SPEWALWAYS((NULL, "-demo"));
			SPEWALWAYS((NULL, "-rekey"));
			SPEWALWAYS((NULL, "-bloat"));
			SPEWALWAYS((NULL, "-reportnotresourced"));
			SPEWALWAYS((NULL, "-armorlevel <n>"));
			SPEWALWAYS((NULL, "-leak <n>"));
			SPEWALWAYS((NULL, "-diskfirst"));
		#endif
	}


	if (MWApplication::AutoLaunchServerGame || MWApplication::Win32DedicatedServer)
	{
		Environment.soundDisable = true;
		Environment.fullScreen = false;
	}
}

Scalar GetNumber(const char* token, bool bAllowFloat = false)
{
    while((*token == ' ') || (*token == '\t')) {
        token++;
    }
    const char *tokenStart = token;
    char c;
    bool b1st = true;
    bool bsign = false;
    bool bDotExist = false;
    while(((c = *token) == '-') || (c == '+') || (('0' <= c) && (c <= '9')) || (bAllowFloat && (c == '.'))) {
        if ((c == '-') || (c == '+')) {
            if (!b1st)
                break;
            if (c == '-')
                bsign = !bsign;
            tokenStart = ++token;
        } else {
            b1st = false;
            if (c == '.') {
                if (bDotExist) {
                    break;
                }
                bDotExist = true;
            }
            token++;
        }
    }
    if (tokenStart < token) {
        char sz[256];
        memcpy(sz, tokenStart, token - tokenStart);
        sz[token - tokenStart] = '\0';
        Scalar f = atof(sz);
        if (bsign)
            return -f;
        return f;
    } else {
        return 0.0;
    }
}

HINSTANCE g_hInst;
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow )
{
#ifdef _DEBUG // jcem
    Vector3D::TestClass();
#endif // _DEBUG
#ifdef _ICECAP
	StopCAPAll ();
#endif
    // jcem - begin
    g_pfnVehGetShutdownState = VehGetShutdownState;
    if (g_bLaunched || (CTCL_GetApplType() != _EAT_None))
        return 0;
    g_bLaunched = TRUE;
    // jcem - end

	g_hInst = hInst;
	static char all_lower[1024];
	strncpy(all_lower, lpCmdLine, sizeof(all_lower));
	all_lower[sizeof(all_lower)-1] = '\0';
	char *p;
	int i = strlen(all_lower);
	for (p=all_lower; i>0; ++p,--i)
		*p=(char)tolower(*p);

    char *token;
    // jcem - begin
	token = strstr(all_lower, "-ctcltype ");
    if (token) {
        token = &token[10];
    } else {
        token = strstr(all_lower, "-ctcl ");
        if (token) {
            token = &token[6];
        }
    }
    if (token) {
        if (token[0]>='1' && token[0]<='3') {
            g_nCTCL = (token[0]-'0');
        } else {
            g_nCTCL = _ECTCL_Console;
        }
    } else {
        g_nCTCL = _ECTCL_Console;
    }

    // MechViewType : 0 - no mechview, 1 - on radar screen, 2 - on main screen
	token = strstr(all_lower, "-mechview ");
    if (token) {
        token = &token[10];
    } else {
        token = strstr(all_lower, "-mv ");
        if (token) {
            token = &token[4];
        }
    }
    if (token) {
        if (token[0]>='1' && token[0]<='2') {
            g_nMechViewType = (token[0]-'0');
        } else {
            g_nMechViewType = 0;
        }
    } else {
        g_nMechViewType = 0;
    }

	token = strstr(all_lower, "-#coop ");
    if (token) {
		g_bCOOP = true;
        g_nCoinPerGame = GetNumber(&token[7]);
        if (g_nCoinPerGame < 0) {
		    g_nCTCL = _ECTCL_CameraShip;
			g_nCoinPerGame = 0;
    } else {
		    g_nCTCL = _ECTCL_Game;
        }
    } else {
		g_bCOOP = (strstr(all_lower, "-coop") != NULL);
        if (g_bCOOP) {
		g_nCoinPerGame = 1;
		g_nCTCL = _ECTCL_Game;
        }
	}
	
    if (strstr(all_lower, "-dragon") != NULL)
        g_nCTCL = _ECTCL_None;
	
    if (g_nCTCL != _ECTCL_None) {
        g_pfnCTCL_Proc = CTCL_Proc;
    }
    g_pfnCTCL_GetType = __CTCL_GetType;

	g_bUseJPD = (strstr(all_lower, "-jpd") != NULL);

    g_bUseOrgJoy = (strstr(all_lower, "-useorgjoy") != NULL);
    if (!g_bUseOrgJoy) {
        g_bUseOrgJoy = (strstr(all_lower, "-ojoy") != NULL);
    }
    g_bNoWeaponRangeCheck = (strstr(all_lower, "-nowrc") != NULL);
    g_bPRTest = (strstr(all_lower, "-prtest") != NULL);
    g_bMRTest = (strstr(all_lower, "-mrtest") != NULL);
    g_bNoPlasma = (strstr(all_lower, "-noplasma") != NULL);
    g_bNoTOCKeys = (strstr(all_lower, "-usetockeys") == NULL);
    token = strstr(all_lower, "-zmmrgn ");
    if (token) {
        Scalar f = GetNumber(token, true);
        if ((0.01 <= fabs(f)) && (fabs(f) <= 0.49)) {
            g_fZoomMarginLR = f;
        }
    }
    float fZoomFOVA = g_fZoomFOVA;
    float fZoomFOVB = g_fZoomFOVB;
    token = strstr(all_lower, "-zmfova ");
    if (token) {
        Scalar f = GetNumber(token, true);
        if ((0.01 <= fabs(f)) && (fabs(f) <= 0.5)) {
            fZoomFOVA = f;
        }
    }
    token = strstr(all_lower, "-zmfovb ");
    if (token) {
        Scalar f = GetNumber(token, true);
        if ((0.01 <= fabs(f)) && (fabs(f) <= 0.5)) {
            fZoomFOVB = f;
        }
    }
    if (fZoomFOVA < fZoomFOVB) {
        float f;
        f = fZoomFOVB;
        fZoomFOVB = fZoomFOVA;
        fZoomFOVA = f;
    }
    g_fZoomFOVA = fZoomFOVA;
    g_fZoomFOVB = fZoomFOVB;

    token = strstr(all_lower, "-zmtime ");
    if (token) {
        Scalar f = GetNumber(token, true);
        if (Stuff::Close_Enough(f, 0.0)) {
            g_fZoomTime = 0.0f;
        } else {
            if ((0.05 <= fabs(f)) && (fabs(f) <= 3.0)) {
                g_fZoomTime = f;
            }
        }
    }
    token = strstr(all_lower, "-pctime ");
    if (token) {
        Scalar f = GetNumber(token, true);
        if (f >= 3.0) {
            g_PlasmaClearTime = f;
        }
    }
    token = strstr(all_lower, "-tocadt ");
    if (token) {
        Scalar f = GetNumber(token, true);
        if (f >= 5.0) {
            g_TOC_ADT = f;
        }
    }
    token = strstr(all_lower, "-auxadt ");
    if (token) {
        Scalar f = GetNumber(token, true);
        if (f >= 3.0) {
            g_AUX_ADT = f;
        }
    }
	token = strstr(all_lower, "-tmfds ");
	if (token && token[7])
	{
        int n = atoi(&token[7]);
		if ((0 <= n) && (n <= 4)) // 0 - no MFDs, 1 - orginal(5+1=dual & single), 2 - B&W(3 + 1=1 dual), 3 - color(3 + 1=2 dual), 4 - split dual 640x480
			g_nTypeOfMFDs = n;
	}
	token = strstr(all_lower, "-trio ");
	if (token && token[6])
	{
        int n = atoi(&token[6]);
		if ((n == 0) || (n == 1))
			g_nRIOType = n;
	}
	token = strstr(all_lower, "-tbaud "); // [tbaud] force COM1 baud; must match the RIO board's UART rate
	if (token && token[7])
	{
        int n = atoi(&token[7]);
		if ((9600 <= n) && (n <= 921600))
			g_dwRIOBaud = (DWORD)n;
	}
    g_bCanSuicideAllways = (strstr(all_lower, "-suicide") != NULL);
	g_f3dtarget = (strstr(all_lower, "-3dt") != NULL);
	g_bOldLOG = (strstr(all_lower, "-olog") != NULL);
#ifdef _DEBUG
	if (strstr(all_lower, "-regs") != NULL) {
		bool __stdcall CheckScriptRegions();
		void __stdcall EnableScriptRegions();

		if (!CheckScriptRegions())
			EnableScriptRegions();
	} else if (strstr(all_lower, "-spew") != NULL) {
		bool __stdcall CheckScriptSpews();
		void __stdcall EnableScriptSpews();

		if (!CheckScriptSpews())
			EnableScriptSpews();
	}
#endif // _DEBUG

    if (g_nCTCL == _ECTCL_CameraShip) {
        g_bUseCam = true;
    } else {
        token = strstr(all_lower, "-usecam");
        if (token) {
            g_bUseCam = true;
        }
    }
    token = strstr(all_lower, "-capdev ");
    if (token) {
        int nCapDev = (int)GetNumber(&token[8], false);
        if ((0 <= nCapDev) && (nCapDev < 8)) {
            // 0 - main, 1 - radar, 2 - mr
            // 3 - hudchat(left/top), 4 - nav(top/center), 5 - weapon(right/top)
            // 6 - target(left/top), 7 - armor(right/bottom)
            extern DWORD gCaptureDevice;
            gCaptureDevice = (DWORD)nCapDev;
        }
    }

    // jcem - end

	MWApplication::Win32DedicatedServer = (strstr(all_lower, "-win32dedicated") != NULL);
	if (MWApplication::Win32DedicatedServer) {
		Platform=Platform_MFC;
		RunFromOtherApp( hInst, ::GetDesktopWindow(), lpCmdLine );
		CDedicatedServerUI::Run(hInst, hPrevInst, lpCmdLine, nCmdShow);
	}
	else {
		Platform=Platform_Game;
		RunFromWinMain( hInst, hPrevInst, lpCmdLine, nCmdShow );
	}
    // jcem - begin
    g_bLaunched = FALSE;
    g_pfnVehGetShutdownState = NULL;
    g_pfnCTCL_GetType = NULL;
    // jcem - end

	return 0;
}
// jcem - start
int __stdcall CTCL_GetType(void* instance, int args, void* data[])
{
    return CTCL_GetType();
}

int __stdcall CTCL_IsConsole(void* instance, int args, void* data[])
{
    return CTCL_IsConsole();
}

int __stdcall CTCL_IsConsoleX(void* instance, int args, void* data[])
{
    return CTCL_IsConsoleX();
}

int __stdcall CTCL_Get(void* instance, int args, void* data[])
{
    // mw4 project - mw4shell.cpp
	int nRet = 0, param_number = VALUEPARM(0);

	switch (param_number)
	{
    case _CTCL_GetTeslaCountAll:
        ASSERT(CTCL_IsConsole());
        nRet = CTCL_GetTeslaCountAll();
        break;
    case _CTCL_GetTeslaCount:
        ASSERT(CTCL_IsConsole());
        nRet = CTCL_GetTeslaCount();
        break;
    case _CTCL_GetTeslaInfo:
      {
        ASSERT(CTCL_IsConsole());
        int nIdx = INTPARM(1);
        ASSERT((0 <= nIdx) && (nIdx < CTCL_GetTeslaCountAll()));
        STeslaInfo TI;
        CTCL_GetTeslaInfo(nIdx, TI);
        nRet = TI.m_nLauncherConnection;
        INTPARM(2) = TI.m_nConnection2;
        INTPARM(3) = TI.m_nApplType;
        INTPARM(4) = TI.m_nApplState;
        INTPARM(5) = TI.m_nGameState;
        int nGameTime = TI.m_nGameTime;
        int nGameIsServer = TI.m_nGameIsServer;
        if ((TI.m_nApplType != _EAT_None) && (TI.m_nApplState == _EAS_Launched)) {
            switch(TI.m_nGameState)
            {
            default:
            case _EGS_None:
            case _EGS_Idle:
            case _EGS_Closing:
                nGameTime = -1; // indetermined
                nGameIsServer = 2; // indetermined
                break;
            case _EGS_Preparing:
                nGameTime = -1; // indetermined
                break;
            case _EGS_Running:
                //if (!nGameIsServer)
                //    nGameTime = -1; // indetermined
                break;
            }
        } else {
            nGameTime = -1; // indetermined
            nGameIsServer = 2; // indetermined
        }
        INTPARM(6) = nGameTime;
        INTPARM(7) = nGameIsServer;
        break;
      }
    case _CTCL_GetTeslaName:
      {
        ASSERT(CTCL_IsConsole());
        int nIdx = INTPARM(1);
        ASSERT((0 <= nIdx) && (nIdx < CTCL_GetTeslaCountll()));
        strcpy(STRPARM(2), CTCL_GetTeslaName(nIdx));
        break;
      }
    case _CTCL_GetInviteCOOP:
        gosASSERT(FALSE);
        break;
    default:
        break;
    }

    return nRet;
}

int __stdcall CTCL_Set(void* instance, int args, void* data[])
{
    // mw4 project - mw4shell.cpp
	int nRet = 0, param_number = VALUEPARM(0);

	switch (param_number)
	{
    case _CTCL_GetTeslaCountAll:
    case _CTCL_GetTeslaCount:
        ASSERT(CTCL_IsConsole());
        ASSERT(FALSE);
        break;
    case _CTCL_GetTeslaInfo:
    case _CTCL_GetTeslaName:
        gosASSERT(FALSE);
        break;
    case _CTCL_OrderAppl:
      {
        ASSERT(CTCL_IsConsole());
        int nIdx = INTPARM(1);
        ASSERT((0 <= nIdx) && (nIdx < CTCL_GetTeslaCountAll()));
        CTCL_OrderAppl(nIdx, VALUEPARM(2), _EAT_MW4);
      }
        break;
    case _CTCL_SetInviteCOOP:
        gosASSERT(FALSE);
        break;
    default:
        break;
    }

    return nRet;
}

BOOL __stdcall CTCL_Before()
{
    BOOL bRet;

    gos_PushCurrentHeap(MechWarrior4::Heap);
    if (g_nCTCL != _ECTCL_None) {
        if (g_nCTCL != _ECTCL_Console) {
            // _ECTCL_Game or _ECTCL_CameraShip
            CTCL_SetApplType(_EAT_MW4);
            CTCL_SetApplState(_EAS_PreLaunch);
        }
        if (CTCL_Start(g_nCTCL)) {
            bRet = TRUE;
        } else {
            bRet = FALSE;
        }
    } else {
        bRet = TRUE;
    }
    gos_PopCurrentHeap();

    return bRet;
}

void __stdcall CTCL_After()
{
    gos_PushCurrentHeap(MechWarrior4::Heap);
    if (g_nCTCL != _ECTCL_None) {
        CTCL_SetApplState(_EAS_PostLaunch);
        g_pfnCTCL_Proc = NULL;
        CTCL_Stop();

        if (g_nCTCL != _ECTCL_Console) {
            // _ECTCL_Game or _ECTCL_CameraShip
            CTCL_SetGameState(_EGS_None);
            CTCL_SetApplState(_EAS_None);
            CTCL_SetApplType(_EAT_None);
        }
    }
    gos_PopCurrentHeap();
}

void __stdcall CTCL_Proc()
{
    gos_PushCurrentHeap(MechWarrior4::Heap);
    CTCL_Run();
    gos_PopCurrentHeap();
}

void CTCL_API CTCL_DoTerminateAppl()
{
    gos_TerminateApplication();
}

void CTCL_API CTCL_DoMainShell()
{
    if (MW4Shell::Instance)
        MW4Shell::Instance->StartMainShell();
}

void CTCL_API CTCL_DoCreateGame()
{
	//$$COOP
    g_fLastGameStart = gos_GetElapsedTime();
    gos_NetStartGame(NULL, MWApplication::SecureNetGame);

	CancelDialup(NULL, 0, NULL);
	LoadMPConnectionSettings(NULL, 0, NULL);
	InitConnectionWizard(NULL, 0, NULL);

    ConnectionIndex = 0;
    PreConnect(NULL, 0, NULL);

    char* pcsz = &g_aPlayerInfos[0].m_szName[0];;
    if (*pcsz == '\0')
        pcsz = &g_szTeslaAddr[0];
    if (*pcsz == '\x01')
        pcsz++;

    CTCL_DefaultHostSetup(0);
    int error = Mech4CreateGame(&g_szGameName[0], pcsz/*PlayerName*/, NULL/*GamePassword*/);
    if (error == 0) {
        CTCL_DoGame1st();
    } else {
        if (g_bCOOP) {
            g_InviteCOOP.m_pParent = NULL;
            g_InviteCOOP.Clear();
        }
        g_nMech4Comm = 0;
        gos_NetEndGame(); // gos_NetDoneStartGame(); ?
        MW4Shell::Instance->StartMainShell();
      if (!g_bCOOP) {
        CTCL_DoSendGameReturn(_EGR_ErrCreateSession);
      }
    }
}

void CTCL_API CTCL_DoJoinGame()
{
    gos_NetStartGame(NULL, MWApplication::SecureNetGame);

	CancelDialup(NULL, 0, NULL);
	LoadMPConnectionSettings(NULL, 0, NULL);
	InitConnectionWizard(NULL, 0, NULL);

    ConnectionIndex = 0;
    PreConnect(NULL, 0, NULL);

    CreateBrowsers(NULL, 0, NULL);
#if 0
    if (0 < GetTotalGameCount(NULL, 0, NULL))
        RefreshGameList();
    else
#endif
    UpdateGameList(NULL, 0, NULL);

    g_nMech4Comm = 1;
    g_dwJoinStartTicks = GetTickCount();
}

void CTCL_API CTCL_CheckJoinGame()
{
    extern int __stdcall gos_GameIsExist( const char* pcszGameName);
	if (gos_GameIsExist(&g_szGameName[0])) {
        MWApplication* app = MWApplication::GetInstance();

        app->haveNetworkMap = false;
        char* pcsz = &g_aPlayerInfos[0].m_szName[0];
        if (*pcsz == '\0')
            pcsz = &g_szTeslaAddr[0];
        if (*pcsz == '\x01')
            pcsz++;

        int error = gos_JoinGame(&g_szGameName[0], pcsz/*PlayerName*/, NULL/*GamePassword*/, NULL/*NGPassword*/);
        if (error == 0) {
            CTCL_DoGame1st();
        } else {
            if (g_bCOOP) {
                g_InviteCOOP.m_pParent = NULL;
                g_InviteCOOP.Clear();
            }
            g_nMech4Comm = 0;
            gos_NetEndGame(); // gos_NetDoneStartGame(); ?
            MW4Shell::Instance->StartMainShell();
          if (!g_bCOOP) {
            CTCL_DoSendGameReturn(_EGR_ErrJoinSession);
          }
        }
    } else {
        if ((g_dwJoinStartTicks + 25000) <= GetTickCount()) {
            if (g_bCOOP) {
                g_InviteCOOP.m_pParent = NULL;
                g_InviteCOOP.Clear();
            }
            g_nMech4Comm = 0;
		    gos_NetEndGame(); // gos_NetDoneStartGame(); ?
            MW4Shell::Instance->StartMainShell();
          if (!g_bCOOP) {
            CTCL_DoSendGameReturn(_EGR_ErrJoinSession);
        }
        }
    }
}

void CTCL_API CTCL_DoGame1st()
{
    MWApplication* app = MWApplication::GetInstance();
	/*MWApplication *app = Cast_Object(MWApplication *, Application::GetInstance());
	NetMissionParameters::MWNetMissionParameters *params = app->GetLocalNetParams();
	Str_Copy(params->m_serverName, GameName, STRING_SIZE);
	Str_Copy(params->m_serverIP, LocalIPAddress, STRING_SIZE);*/
	
    gos_NetDoneStartGame();

	DWORD networking;
	
	networking = reinterpret_cast<DWORD>(gos_NetInformation(gos_Networking, 0));
	
	app->networkingFlag = (networking)?true:false;
	
	if (app->networkingFlag)
	{
		//$$COOP
		DWORD server = reinterpret_cast<DWORD>(gos_NetInformation(gos_AmITheServer, 0));
		app->serverFlag = (server)?true:false;
		
		if (Network::GetInstance() == NULL)
		{
			gos_PushCurrentHeap(MechWarrior4::Heap);
			Verify(!Network::GetInstance());
			GlobalPointers::AddGlobalPointer(new Network, NetworkGlobalPointerIndex);
			Register_Object(Network::GetInstance());
			gos_PopCurrentHeap();
		}
		
		if (app->serverFlag)
		{
            ASSERT(g_bIsServer);

			// save the options that were set
			app->SaveServerOptions();
			
#if defined(LAB_ONLY)
			MWGameInfo::g_lastGameType = MWGameInfo::g_currentGameType;
			MWGameInfo::g_currentGameType = MWGameInfo::MultiServer;
#endif

			//app->LoadServerOptions();
			app->SendRequestConnectionMessage();
		}
		else
		{
            ASSERT(!g_bIsServer);

	        app->GetLocalNetParams()->ResetParameters();
	        app->GetServerNetParams()->ResetParameters();
            app->haveNetworkMap = false;
		}
        g_fLastGameStart = gos_GetElapsedTime();
        if (g_bCOOP) {
		    if (app->serverFlag) {
                MW4Shell::Instance->StartNetworkServerExecute();
                g_nMech4Comm = 0;
            } else {
                MW4Shell::Instance->StartNetworkClientExecute();
                g_nMech4Comm = 2;
            }
        } else {
		for (int i = 0; i < Maximum_Lancemates; ++i)
		{
			app->lancemateConnectionData[i].Disconnect();
		}
		
		app->memoryDiffKiller.Init();
        g_nMech4Comm = 2;
        }
    } else {
        // is this possible?
        if (g_bCOOP) {
            g_InviteCOOP.m_pParent = NULL;
            g_InviteCOOP.Clear();
        }
        g_nMech4Comm = 0;
		gos_NetEndGame();
        MW4Shell::Instance->StartMainShell();
      if (!g_bCOOP) {
        if (g_bIsServer)
            CTCL_DoSendGameReturn(_EGR_ErrCreateSession);
        else
            CTCL_DoSendGameReturn(_EGR_ErrJoinSession);
      }
    }
}

void CTCL_API CTCL_StartGame(BOOL bRealLaunch)
{
	//$$COOP
    if (bRealLaunch) {
        g_nMech4Comm = 11;
    } else {
	    MW4Shell::Instance->EndAllScripts();
	    MW4Shell::Instance->currentShellRunning = MW4Shell::MainShellRunning; //MW4Shell::NoShellRunning;
	    MW4Shell::Instance->shellCommand = MW4Shell::StartNetworkGameCommand;
	    MW4Shell::Instance->shellStart = MW4Shell::MainShellStart;
        g_nMech4Comm = 9;
    }
}

int _stdcall __CTCL_GetType()
{
    return g_nCTCL;
}
// jcem - end
