Investigating a field report that the cameraship secondary armor/score/map screen showed its background BMP but no overlay graphics "on certain video cards". The video card was a red herring: the machine was launched with -ctcltype 2 (game pod) instead of 3 (cameraship), and the overlay block in hudchat.cpp is gated on CTCL_GetType()==_ECTCL_CameraShip, so it never ran. This is hard to spot because the two gates are independent. HSH_EnterFullScreen2 and CMR_Device open the screen and paint its background based purely on whether a spare secondary monitor exists, and never consult the CTCL role. A wrong -ctcltype therefore yields a screen that lights up, shows the correct artwork and renders nothing, which is visually identical to a DirectDraw failure. The same background-only screen also appears on a game pod when an MFD mode finds no dual-head span and falls through to the single-secondary mr_device path. Diagnostics added: - render.cpp: log the CTCL type in gos-displays.txt from HSH_EnterFullScreen2, via the existing g_pfnCTCL_GetType hook so GameOS gains no game-code dependency. Always logged, and states in words whether overlays will be drawn. - render.cpp/.hpp: CHSH_Device::m_nDrawCalls, incremented in DrawQuad, DrawThickFrame and DrawTexture, reset in CMR_Device::BeginScene and reported for the first 5 frames from CMR_Device::EndScene when -tmr is active. Zero draws proves the overlay code never ran; non-zero with a blank screen would mean it ran and drew invisibly. This distinction is what settled the case. - render.cpp: log CMR_Device surface creation plus the overlay texture's dimensions, depth and channel masks. - New -tmr <0-3> switch (MW4Application.cpp, documented in -help): 0 normal, 1 background blit with DDBLTFAST_WAIT|DDBLTFAST_NOCOLORKEY, 2 Clear instead of the background blit, 3 as 2 plus alpha blending off and an untextured magenta DrawQuad. Mode 3 drew magenta and mode 2 was pure black, which cleared the 3D device, the flip and the background blit in two runs; the draw counter then reported 0 and pointed straight at the gate. Documented as STEP 11 in CLAUDE.md, including the field triage rule: read "CTCL type =" in gos-displays.txt before suspecting drivers. Co-authored-by: Claude Opus 5 (Anthropic) <noreply@anthropic.com> Co-authored-by: GitHub Copilot <copilot@github.com>
2188 lines
66 KiB
C++
2188 lines
66 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];
|
|
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.",
|
|
" Example: -tmon 1,2,4,3 swaps the two MFD panels.",
|
|
" -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.",
|
|
" -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,",
|
|
" 1% low, worst frame in ms, and a count of frames",
|
|
" taking over twice the average (hitches). 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;
|
|
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
|