Files
firestorm/Gameleap/code/mw4/Code/MW4Application/MW4Application.cpp
T
9ba2d594b1 Add -tmon switch to hard-assign display devices
Display roles are auto-detected in FindVideoCards(): the main view takes the
first hardware-rasterizing device that is not a 1280x480-capable span, the radar
takes the next, and mode 4's two MFD panels take the two after that. That works
until DirectDraw enumerates the adapters in an unexpected order, at which point
the wrong content appears on the wrong monitor with no way to correct it.

Adds an override that keeps auto-detection as the default:

    -tmon <main>,<radar>,<mfd1>,<mfd2>

Values are 1-based, so the normal case is "-tmon 1,2,3,4". A value of 0 leaves
that slot auto-detected, so "-tmon 2,1,0,0" swaps only main and radar. Separators
may be ',' '/' or ':'. mfd1/mfd2 are only meaningful with -tmfds 4. Omitting the
switch entirely preserves existing behaviour exactly.

Implementation:

- Parsed in MW4Application's WinMain alongside -tmfds. That runs before GameOS
  calls FindVideoCards(), so the values are in place for device selection.
- Stored in g_naMonitorOverride[4] (VideoCard.cpp), extern'd in MW4Application.cpp.
- ApplyMonitorOverride() validates the index against NumDevices, so a stale -tmon
  on a machine with fewer monitors falls back to auto-detection rather than
  breaking startup.
- Ordering matters and is deliberate: main and radar are applied BEFORE the mode 4
  MFD search so that search still skips whichever devices the operator picked;
  mfd1/mfd2 are applied after it. Partial overrides therefore compose correctly.

Role map: main = Environment.FullScreenDevice, radar = g_nNonDualHead,
mfd1 = g_nMFD1, mfd2 = g_nMFD2. The mode 1 span (g_nDualHead) is intentionally
not overridable -- it is detected by 1280x480 mode support, which only the span
card advertises, so that detection is reliable.

Also adds a SPEW line logging the final role -> device map and device count.
Note this is only visible in Profile/LAB builds; SPEW compiles out in Release
(gos2X/Gos.h), so in Release the order is determined by observation.

Verified: compiles clean, console launches. Multi-monitor testing pending.

Co-authored-by: Claude Opus 5 (Anthropic) <noreply@anthropic.com>
Co-authored-by: GitHub Copilot <copilot@github.com>
2026-07-24 23:39:59 -05:00

1946 lines
54 KiB
C++

//===========================================================================//
// 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), 4 - split dual 640x480
// [tmon] Display-device override in Main/Radar/MFD1/MFD2 order; -1 = auto-detect.
// Defined in CoreTech GameOS VideoCard.cpp and consumed by FindVideoCards().
extern int g_naMonitorOverride[4];
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;
}
// [tmon] Hard-assign the display devices when DirectDraw enumerates them in an
// unexpected order. Syntax: -tmon <main>,<radar>,<mfd1>,<mfd2>
// Values are 1-based (the normal case is "-tmon 1,2,3,4"); a value of 0 leaves that
// slot to auto-detection, so "-tmon 2,1,0,0" only swaps main and radar. Separators
// may be ',' '/' or ':'. mfd1/mfd2 are only used by -tmfds 4.
token = strstr(all_lower, "-tmon ");
if (token)
{
const char* p = &token[6];
int slot = 0;
while (slot < 4)
{
while (*p == ' ')
p++;
if ((*p < '0') || ('9' < *p))
break;
int v = atoi(p);
while (('0' <= *p) && (*p <= '9'))
p++;
// 0 = leave auto-detected, otherwise convert 1-based to a 0-based device index
g_naMonitorOverride[slot] = (0 < v) ? (v - 1) : -1;
slot++;
if ((*p == ',') || (*p == '/') || (*p == ':'))
p++;
else
break;
}
}
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