Files
firestorm/Gameleap/code/mw4/Code/MW4Application/MW4Application.cpp
T
8bfaf9b9ad Publish V5.1.0b_RC2: rebuilt binaries, repacked props, RC2 documentation
RC2 build, verified to launch on the Windows box and copied back into the
deployment at MW4/. Supersedes RC1 (a0331e78), which predates everything in
sections 12-17 of the test checklist.

Binaries and content
--------------------
* MW4.exe / MW4pro.exe rebuilt from CoreTech GameOS + MW4Application. Carries
  the display work that landed after the RC1 build: -tident, the full
  gos-displays.txt start-up trace with the CLASH and CTCL-type reports, the
  HSH_EnterFullScreen2 panel re-entry fix, the -tmr cameraship ladder, and the
  updated -help text.
* Launcher / autoconfig / mw4print / ctcls / MissionLang / ScriptStrings
  relinked in the same pass.
* props.mw4 + props.dep fully repacked (deleted first, not incremental), so the
  23-entry time list, the restored 7-minute default and the V5.1.0b2 console
  title are actually in the package rather than only in the source tree.
* mw4-help.txt regenerated from the new exe; the diff is the proof the built
  binary carries the documentation changes.

Documentation, renamed to RC2
-----------------------------
* RELEASE-NOTES-5.1.0b_RC1.{md,html} -> ..._RC2.{md,html}, both hand-maintained
  in step, ASCII + CRLF so they open correctly in Notepad on a pod.
  - New "Already testing RC1?" block at the top. RC1's notes already described
    -tident and the CLASH report, but the RC1 BINARY does not contain them, so
    anyone comparing the two needed that stated explicitly.
  - Time limits corrected to 23 entries (1-15, 20, 25, 30, 45, 60, 120, 180,
    240) with the 7-minute default restoration called out.
  - New section on the cameraship Map/Armor screen: background but no overlays
    is -ctcltype 2 on a cameraship, not a video card. Includes the
    "CTCL type =" log line and -tmr 3 as the follow-up check.
  - -fps description corrected: the per-second column is a 5% low and the 1% /
    0.1% lows are in the session summary. The old text described behaviour that
    had already been changed.
  - Switch table gained -tmr; known issues gained stereo-only audio and the
    single-monitor -tident caveat; upgrade checklist now names V5.1.0b2.
* testing-checklist-5.1.0b1.txt -> testing-checklist-5.1.0b_RC2.txt, with a
  build-requirements header and new sections 12-17 covering -tident, the
  display trace (including a deliberate -tmon clash to exercise the CLASH
  report), the panel re-entry fix, cameraship/-tmr, 240-minute missions and a
  -help verification pass.
* OPTIONS-INI.md: TimeList_Index is documented as no longer driving the console
  lobby default (the script uses a literal since the list was expanded) while
  TimeList_Value remains live; added a table of the files the game writes next
  to MW4.exe. Also repaired the CP949/CP1252 damage in that file - it carried
  literal 0xA1 0xE6 arrows, 0x97 em dashes and ~20 '?' characters where dashes
  had been lost. Now pure ASCII.
* README.md points at the RC2 notes.

Source
------
MW4Application.cpp help text: -fps now matches what gos-fps.txt actually
prints, and -ctcltype states that a cameraship must use 3 and what goes wrong
when it does not. Audited all 80 switches parsed in the file against the help
array - none missing, and no game-facing switch is parsed anywhere else.

Deployment housekeeping
-----------------------
* dgVoodoo.conf: ScalingMode = stretched_ar, which is the setting the release
  notes require and which fails SILENTLY when wrong. FPSLimit was left at 20
  from bench testing and would have shipped a 20 fps cap to every Win10/11 pod
  - raised to 60.
* banner.txt reset from a test string to the shipped placeholder.
* Removed two stray screen000*.bmp captures and the duplicate dbstruct.txt
  (db_schema.sql is the current name, per b4089291).
* .gitignore: gos-displays.txt and gos-fps.txt are truncated on every launch
  and are per-machine, so they are no longer mirrored.

Not yet done: multi-monitor pod testing of this binary. -tident, the re-entry
fix and -tmr have not been exercised on real MFD hardware - that is what the
new checklist sections are for.

Co-authored-by: Claude Opus 5 (Anthropic) <noreply@anthropic.com>
Co-authored-by: GitHub Copilot <copilot@github.com>
2026-08-07 13:07:43 -05:00

2229 lines
69 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 <stdio.h> // [help] FILE/fopen/fprintf used by MW4_ShowCommandLineHelp
#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];
// [tident] Non-zero paints each display with its -tmon number, then exits.
extern int g_nIdentDisplays;
extern int g_nIdentSeconds;
extern int g_nRIOType;
extern DWORD g_dwRIOBaud; // [tbaud]
// [fpslog] Non-zero enables the per-second frame pacing report (gos-fps.txt).
// Defined in CoreTech GameOS WinMain.cpp.
extern int g_nFpsLog;
// [panelcoop] SetCooperativeLevel form used by the radar/MFD panels; 0 = legacy.
// Defined in CoreTech GameOS render.cpp.
extern int g_nHshCoopMode;
// [mrdiag] Cameraship secondary-screen (Map/Armor) diagnostic mode; 0 = normal.
// Defined in CoreTech GameOS render.cpp.
extern int g_nMRDiag;
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
);
// [help] ---------------------------------------------------------------------
// Complete command-line reference, shown by "MW4.exe -help".
//
// MW4 is a GUI-subsystem application, so there is no console to print to when it
// is launched normally. -help therefore writes the full reference to
// mw4-help.txt next to the executable, opens it in Notepad, and exits without
// starting the game. If Notepad cannot be launched, a message box reports where
// the file was written.
//
// KEEP THIS IN SYNC when adding or changing a command-line switch.
static const char* const g_apszCommandLineHelp[] =
{
"BattleTech: FireStorm - MW4.exe command line reference",
"======================================================",
"",
"Usage: MW4.exe [options]",
"",
"Options may appear in any order and are case-insensitive. An option that takes",
"a value must be followed by a single space and then the value, for example:",
"",
" MW4.exe -tmfds 4 -tmon 1,2,3,4 -tbaud 115200",
"",
"Values outside the documented range are ignored and the default is kept.",
"",
"",
"DISPLAY AND VIDEO",
"-----------------",
" -window Run in a window instead of fullscreen.",
" -fullscreen Force fullscreen. Overrides -window.",
" -tmfds <0-4> MFD output mode:",
" 0 = no MFDs",
" 1 = original 1280x480 span (5 channels + radar)",
" 2 = black and white (3 channels + 1 dual)",
" 3 = colour (3 channels + 2 dual)",
" 4 = split dual 640x480 - drives two independent",
" MFD monitors, so no span hardware is needed",
" -tmon <m>,<r>,<f1>,<f2> Hard-assign display devices in the order",
" main, radar, MFD1, MFD2. Values are 1-based; a",
" value of 0 leaves that slot auto-detected.",
" Separators may be ',' '/' or ':'.",
" MFD1 and MFD2 only apply with -tmfds 4.",
"",
" These are DirectDraw device numbers. They are NOT",
" the numbers shown in Windows Display Settings, and",
" on many machines the two do not match. Do not read",
" them off the Settings screen.",
"",
" To find the right values: launch the game once,",
" then open gos-displays.txt next to MW4.exe and read",
" the 'Desktop arrangement, left to right' list. It",
" gives each monitor's position, size and device",
" number. Add 1 to the device number for -tmon.",
" Example: -tmon 1,2,4,3 swaps the two MFD panels.",
" -tident [seconds] Identify the displays, then exit. Each monitor is",
" filled with a colour and the number to use for it",
" in -tmon. Write the numbers down, then set -tmon in",
" the order main,radar,MFD1,MFD2.",
" This is the reliable way to map the monitors: the",
" numbers Windows Display Settings shows cannot be",
" read by any program, so they cannot be trusted to",
" match. Default 20 seconds; accepts 3 to 120.",
" No display mode is changed and the game does not",
" start - it exits when the time is up.",
" -tcoop <0-5> How the radar/MFD panels claim their displays.",
" 0 = legacy single call (as shipped; works on XP",
" and under dgVoodoo2, fails on Windows 10).",
" 1 = drop SETFOCUSWINDOW, let DirectDraw create",
" the device window.",
" 2 = SETFOCUSWINDOW first, then CREATEDEVICEWINDOW.",
" 3 = SETFOCUSWINDOW first, then EXCLUSIVE only,",
" matching what the main display already does.",
" 4 = EXCLUSIVE|FULLSCREEN only. The main display",
" has already set the focus window, so the",
" panels never contend for it.",
" 5 = as 4, plus ALLOWREBOOT.",
" Results are reported in gos-displays.txt.",
" -tmr <0-3> Cameraship Map/Armor screen diagnostics.",
" 0 = normal.",
" 1 = wait for the background blit to finish before",
" drawing the overlays.",
" 2 = skip the background image entirely.",
" 3 = as 2, plus a solid magenta test rectangle.",
" Use when that screen shows its background but no",
" overlay graphics or text.",
" -mechview <1|2> Show the rotating mech view. 1 = on the radar",
" -mv <1|2> screen, 2 = on the main screen. Default: off.",
" -3dt Draw the MFD target as a live 3D model instead of",
" the pre-rendered 2D bitmaps.",
" -capdev <0-7> Select which device screen captures come from:",
" 0 main, 1 radar, 2 mission review, 3 hudchat,",
" 4 nav, 5 weapon, 6 target, 7 armor",
"",
"",
"AUDIO AND PLASMA DISPLAY",
"------------------------",
" -nosound Disable all sound output.",
" -noplasma Disable the COM2 plasma score display.",
" -pctime <seconds> Plasma display clear time. Minimum 3.",
"",
"",
"POD HARDWARE AND ARCADE (CTCL)",
"------------------------------",
" -ctcltype <1-3> CTCL role for this machine:",
" -ctcl <1-3> 1 = console, 2 = game pod, 3 = cameraship.",
" Default when absent: console.",
" A cameraship MUST use 3. With 2 its Map/Armor",
" screen still opens and paints its background, but",
" draws no overlays at all, which looks like a video",
" card fault. The role in use is reported in",
" gos-displays.txt as 'CTCL type ='.",
" -dragon Disable CTCL entirely and run standalone.",
" -coop Co-operative arcade mode. Implies 1 coin per game",
" and the game-pod role.",
" -#coop <coins> Co-op with an explicit coin count. A negative",
" value selects the cameraship role instead.",
" -trio <0|1> RIO cockpit board protocol. 0 = original board,",
" 1 = newer protocol (different framing and acks).",
" -tbaud <9600-921600> Force the COM1 baud rate for the RIO board. Use",
" for replica boards with a high-speed UART. The",
" wire protocol is unchanged; only the rate differs.",
" -useorgjoy Use the original joystick axis mapping.",
" -ojoy Same as -useorgjoy.",
" -usetockeys Enable TOC keys. They are disabled by default.",
" -tocadt <seconds> TOC auto-detect timeout. Minimum 5.",
" -auxadt <seconds> AUX auto-detect timeout. Minimum 3.",
" -usecam Force camera mode. Implied by the cameraship role.",
" -suicide Allow self-destruct at any time.",
" -jpd Enable JPD input handling.",
"",
"",
"ZOOM AND FIELD OF VIEW",
"----------------------",
" -zmfova <0.01-0.5> Zoom field-of-view, stage A.",
" -zmfovb <0.01-0.5> Zoom field-of-view, stage B. A and B are swapped",
" automatically so that A is the wider of the two.",
" -zmmrgn <0.01-0.49> Zoom left/right margin, as a fraction of width.",
" -zmtime <0, or 0.05-3.0> Zoom transition time in seconds. 0 = instant.",
"",
"",
"MULTIPLAYER AND NETWORK",
"-----------------------",
" -serve Automatically host a server game on startup.",
" -lobby Indicates the game was started from a lobby.",
" -game <file> Load the named game/mission file.",
" -gamename <name> Name advertised for the hosted game.",
" -playername <name> Player name to use.",
" -password <password> Password for the hosted or joined game.",
" -advertiseport <port> Port used to advertise the server.",
" -ipx Use IPX in the server browser.",
" -nodplay Disable DirectPlay networking.",
" -directplayprotocol Force use of the DirectPlay protocol.",
" -secure Enable secure networking for the game session.",
" -set_internet Configure network settings for internet play.",
" -set_lan Configure network settings for LAN play.",
" -win32dedicated Run as a Win32 dedicated server. Disables sound",
" and rendering and uses the dedicated server UI.",
" -allowmultiple Allow more than one instance of the game to run.",
" -oldmpui Use the older multiplayer user interface.",
"",
"",
"LOGGING AND DIAGNOSTICS",
"-----------------------",
" -zlogstyle <value> ZLog output style.",
" -zlogflush <value> ZLog flush behaviour.",
" -zlogbuffer <size> ZLog buffer size.",
" -zlogname <filename> ZLog output file name.",
" -olog Write the legacy .log match report instead of the",
" newer .rpt format.",
" -fps Write a per-second frame pacing report to",
" gos-fps.txt next to the executable: average fps,",
" 5% low, worst frame in ms, and a count of frames",
" taking over twice the average (hitches). A summary",
" written at exit gives the whole-session 1% and",
" 0.1% lows. Useful for confirming smooth pacing on",
" the MFD modes. Off unless this switch is given.",
" -gamestats Save game statistics.",
" -help Show this reference and exit without starting.",
"",
"",
"DEVELOPMENT AND TEST BUILDS",
"---------------------------",
"The following are only active in LAB (Debug, Armor and Profile) builds. In a",
"Release build they are accepted and ignored.",
"",
" -build Rebuild the resource packages at startup.",
" -norun Do not run the game after building.",
" -demo Demo mode.",
" -rekey Re-key resources.",
" -bloat Enable bloat diagnostics.",
" -reportnotresourced Report assets that are not in a resource package.",
" -armorlevel <0-4> Assertion/armor checking level.",
" -leak <n> Memory trace level.",
" -diskfirst Prefer loose files on disk over packaged data.",
" -testclasses Run internal class self-tests.",
" -aistats Enable AI statistics collection.",
" -bspmap Save BSP map differences.",
" -showscripterrors Display script errors as they occur.",
" -mrtest Mission review test mode.",
" -prtest Print report test mode.",
" -nowrc Disable weapon range checking.",
" -regs Debug builds only: enable script regions.",
" -spew Debug builds only: enable script spews.",
"",
"",
"OTHER",
"-----",
" -nocd Skip the CD check. (The CD check is already",
" disabled unconditionally in this build.)",
" -noeula Skip the end user licence agreement screen.",
" -noautoconfig Skip automatic video and sound configuration.",
"",
"",
"RECOGNISED BUT INACTIVE",
"-----------------------",
" -join Parsed for compatibility but has no effect; the",
" code that consumed it is commented out.",
" -noabzug Parsed only in a disabled code path.",
"",
"",
"RELATED CONFIGURATION",
"---------------------",
"Most persistent settings live in options.ini next to MW4.exe rather than on the",
"command line. See OPTIONS-INI.md in the source repository for a full reference.",
"Arcade pod assignments live in c:\\ctcl.ini.",
NULL
};
static void MW4_ShowCommandLineHelp()
{
char szDir[MAX_PATH];
char szPath[MAX_PATH];
// Write next to the executable rather than the working directory, so the file
// is easy to find no matter how the game was launched.
szDir[0] = '\0';
GetModuleFileNameA(NULL, szDir, sizeof(szDir));
char* pSlash = strrchr(szDir, '\\');
if (pSlash)
*(pSlash + 1) = '\0';
else
szDir[0] = '\0';
sprintf(szPath, "%smw4-help.txt", szDir);
FILE* f = fopen(szPath, "wt");
if (!f)
{
MessageBoxA(NULL,
"Could not write mw4-help.txt next to MW4.exe.\n"
"Check that the folder is writable.",
"MW4 command line help", MB_OK | MB_ICONWARNING);
return;
}
for (int i = 0; g_apszCommandLineHelp[i] != NULL; i++)
fprintf(f, "%s\n", g_apszCommandLineHelp[i]);
fclose(f);
// Open it for the user. WinExec is used rather than ShellExecute to avoid a
// dependency on shellapi.h in this translation unit.
char szCmd[MAX_PATH + 32];
sprintf(szCmd, "notepad.exe \"%s\"", szPath);
if (WinExec(szCmd, SW_SHOWNORMAL) < 32)
{
char szMsg[MAX_PATH + 128];
sprintf(szMsg,
"The MW4.exe command line reference was written to:\n\n%s",
szPath);
MessageBoxA(NULL, szMsg, "MW4 command line help", MB_OK | MB_ICONINFORMATION);
}
}
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
}
// [help] -help is handled at the top of WinMain (see MW4_ShowCommandLineHelp),
// which runs before this and exits the process. The old partial list that used
// to live here was incomplete and only reached the debug log, so it was removed
// in favour of a single maintained reference.
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);
// [help] Handle -help before anything is initialised: write the full command
// line reference next to the exe, open it, and exit without starting the game.
if (strstr(all_lower, "-help"))
{
MW4_ShowCommandLineHelp();
return 0;
}
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;
}
// [panelcoop] Cooperative-level form for the radar/MFD panels. 0 = legacy combined
// call (what shipped); 1-3 are forms compatible with strict modern DirectDraw.
token = strstr(all_lower, "-tcoop ");
if (token && token[7])
{
int n = atoi(&token[7]);
if ((0 <= n) && (n <= 5))
g_nHshCoopMode = n;
}
// [mrdiag] Cameraship Map/Armor screen diagnostics. 0 = normal behaviour.
token = strstr(all_lower, "-tmr ");
if (token && token[5])
{
int n = atoi(&token[5]);
if ((0 <= n) && (n <= 3))
g_nMRDiag = n;
}
// [fpslog] Enable the per-second frame pacing report written to gos-fps.txt.
g_nFpsLog = (strstr(all_lower, "-fps") != NULL) ? 1 : 0;
// [tident] Paint each display with the number to use in -tmon, then exit. Windows
// Display Settings monitor numbers cannot be read programmatically, so this is the
// only way to hand the operator an authoritative mapping.
g_nIdentDisplays = (strstr(all_lower, "-tident") != NULL) ? 1 : 0;
token = strstr(all_lower, "-tident ");
if (token && token[8])
{
int n = atoi(&token[8]);
if ((3 <= n) && (n <= 120))
g_nIdentSeconds = 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