/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** Confidential - Westwood Studios *** *********************************************************************************************** * * * Project Name : Commando * * * * $Archive:: /Commando/Code/Commando/init.cpp $* * * * $Author:: Steve_t $* * * * $Modtime:: 10/16/02 11:10a $* * * * $Revision:: 258 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * Commando_Assert_Handler -- Commando callback function for WWASSERT's * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "init.h" #include "debug.h" #include "wwmath.h" #include "ww3d.h" #include "wwphys.h" #include "WWAudio.H" #include "wwsaveload.h" #include "input.h" #include "inputconfigmgr.h" //#include "gamesettings.h" #include "ffactory.h" #include "assets.h" #include "_globals.h" #include "combatgmode.h" // gamemode #include "langmode.h" // gamemode #include "wolgmode.h" // gamemode #include "movie.h" // gamemode #include "gamemenu.h" // gamemode #include "overlay.h" // gamemode #include "multihud.h" // gamemode #include "console.h" // gamemode #include "textdisplay.h" // gamemode #include "scorescreen.h" // gamemode #include "msgloop.h" #include "Resource.H" #include "miscutil.h" #include "cnetwork.h" #include "mathutil.h" #include "win.h" #include "Part_Ldr.H" #include "savegame.H" #include "systemsettings.h" #include "gamedata.h" #include "sphereobj.h" #include "ringobj.h" #include "diagnostics.h" #include "devoptions.h" #include "translatedb.h" #include "useroptions.h" #include "pathmgr.h" #include "string_ids.h" #include "soundrobj.h" #include "crandom.h" #include "systimer.h" #include "renegadedialogmgr.h" #include "campaign.h" #include "diaglog.h" #include "mpsettingsmgr.h" #include "mixfile.h" #include "ffactorylist.h" #include "gameinitmgr.h" #include "serverfps.h" #include "nicenum.h" #include "encyclopediamgr.h" #include "texturethumbnail.h" #include "playermanager.h" #include "teammanager.h" #include "stackdump.h" #include "registry.h" #include "bandwidthgraph.h" #include "buildnum.h" #include "dx8wrapper.h" #include "autostart.h" #include "except.h" #include "wwmemlog.h" #include "except.h" #include "consolemode.h" #include "serversettings.h" #include "pscene.h" #include "dazzle.h" #include "skinpackagemgr.h" #include "modpackagemgr.h" #include "GameSpy_QnR.h" #include "gamespyadmin.h" #include "shutdown.h" #include "specialbuilds.h" extern const char *VALUE_NAME_TEXTURE_FILTER_MODE; /* ** Define IMMEDIATE_LOAD if you want to have the game start right ** up in a given level (for profiling for example) */ // HACK: ATI demo loads the demo level bypassing the mainmenu #ifdef ATI_DEMO_HACK #define IMMEDIATE_LOAD 1 #define IMMEDIATE_LOAD_LEVELNAME "MDD_0807.mix" #else #define IMMEDIATE_LOAD 0 #define IMMEDIATE_LOAD_LEVELNAME "MDD_0803.mix" #endif /* ** This defines the subdirectory where the game will load all data from */ const char * DATA_SUBDIRECTORY = "DATA\\"; const char * SAVE_SUBDIRECTORY = "DATA\\SAVE\\"; const char * CONFIG_SUBDIRECTORY = "DATA\\CONFIG\\"; const char * MOVIES_SUBDIRECTORY = "DATA\\MOVIES\\"; #define STRINGS_FILENAME "STRINGS.TDB" #define CONV_DB_FILENAME "CONV10.CDB" /* ** DebugDisplayHandler */ TextDebugDisplayHandlerClass TextDisplayHandler; /* ** Used to modify where game entries are kept in the registry. */ extern char DefaultRegistryModifier[1024]; /* ** Static global lod settings for particles */ static const float _ParticleLODScreenSizes[17] = { 0.0025f, 0.0050f, 0.0075f, 0.0100f, 0.0300f, 0.0500f, 0.0700f, 0.0900f, 0.1000f, 0.3000f, 0.5000f, 1.0000f, 1.2500f, 1.5000f, 1.7500f, 2.0000f, NO_MAX_SCREEN_SIZE }; /*********************************************************************************************** * Append_To_Assert_History -- keeps a timestamped history of asserts. * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 9/26/2001 tss : Created. * *=============================================================================================*/ void Append_To_Assert_History(const char * message) { if (message == NULL) { // // bail // return; } FILE * file = ::fopen("_asserts.txt", "at"); if (file == NULL) { return; } char line[2000] = ""; // // Blank lines plus timestamp // ::sprintf(line, "\n\nWhen: %s\n", cMiscUtil::Get_Text_Time()); ::fwrite(line, 1, ::strlen(line), file); // // version # // ::sprintf(line, "Version: %d\n", DebugManager::Get_Version_Number()); ::fwrite(line, 1, ::strlen(line), file); // // Full filename // char full_filename[MAX_PATH]; ::GetModuleFileName(NULL, full_filename, sizeof(full_filename)); ::sprintf(line, "Filename: %s\n", full_filename); ::fwrite(line, 1, ::strlen(line), file); // // File size // HANDLE hfile = ::CreateFile(full_filename, 0, 0, NULL, OPEN_EXISTING, 0L, NULL); if (hfile != INVALID_HANDLE_VALUE) { DWORD file_size = ::GetFileSize(hfile, NULL); ::CloseHandle(hfile); ::sprintf(line, "Filesize: %d\n", file_size); ::fwrite(line, 1, ::strlen(line), file); } // // The assert message itself // ::sprintf(line, "Assert: %s\n", message); ::fwrite(line, 1, ::strlen(line), file); ::fclose(file); } /*********************************************************************************************** * Commando_Assert_Handler -- Commando callback function for WWASSERT's * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 3/28/2000 gth : Created. * *=============================================================================================*/ void Commando_Assert_Handler(const char * message) { if (message == NULL) { // // bail // return; } // // TSS092601 // Append_To_Assert_History(message); // // If the exception handler is try to quit the game then don't show an assert. // if (Is_Trying_To_Exit()) { ExitProcess(0); } // // Hand the message off to the scrolling debug screen // DebugManager::Display( message ); // // // IF YOU WANT TO DISABLE CERTAIN ACTIONS HERE, USE // THE REGISTRY SWITCHES!!!!!!!!!!!!! // // #ifdef WWDEBUG Copy_Logs(DebugManager::Get_Version_Number()); #endif // WWDEBUG RegistryClass registry( APPLICATION_SUB_KEY_NAME_DEBUG ); if ( registry.Is_Valid() ) { registry.Set_Int( VALUE_NAME_APPLICATION_CRASH_VERSION, 0 ); } #ifdef WWDEBUG if (cDevOptions::SoundEffectOnAssert.Is_True() && WWAudioClass::Get_Instance() != NULL) { // // Sound effect // WWAudioClass::Get_Instance()->Create_Instant_Sound("Debug_Assertion", Matrix3D(1)); } if (cDevOptions::DisplayLogfileOnAssert.Is_True()) { // // Open up the logfile so that the user can see the assert // at the bottom. // cNetwork::Shell_Command(DebugManager::Logfile_Name()); } //LOG_CALL_STACK; if (cDevOptions::BreakToDebuggerOnAssert.Is_True()) { if (cDevOptions::ShutdownInputOnAssert.Is_True()) { // // This input shutdown is to help those of us who still have the // DirectInput / debugger problem. For some of us the registry fix // doesn't help. // Input::Shutdown(); } /* m $m mm m "$mmmmm m$" mmmmmmm$" """$m m$ m$"""""" mmmmmmm$$$$$$$$$"mmmm mmm$$$$$$$$$$$$$$$$$$ m$$$$m " m " $$$$$$$$$$$$$$$$$$$$$$ $$$$$$"$$$ mmmmmmmmmmmmmmmmmmmmm $$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$ $$$$$$$""" m "$$$$$$$$$$$$$$$$$$$$$ $$$$$$ " " """""""$$$$$$$$$$$m """" mmmmmmmm" m$ "$mmmmm $$"""""" "$ """"""$$ m$" "m " */ _asm int 0x03; } if (cDevOptions::ExitThreadOnAssert.Is_True()) { ExitThread(1); } #endif // WWDEBUG } /* ** */ void _stdcall AudioTextCallback(AudibleSoundClass *sound_obj, const StringClass &text, uint32 user_param) { Vector3 red = Vector3( 1, 0.5f, 0.5f ); StringClass str; str.Format( "%s\n", (const char *)text ); DebugManager::Display_Text( str, red ); } /* ** */ class LoggingFileFactoryClass : public SimpleFileFactoryClass { public: virtual FileClass * Get_File( const char * filename ) { FileClass * file = BaseFactory->Get_File( filename ); Debug_Say(( "FILE_LOG : %s %s\n", filename, ((file==NULL||!file->Is_Available())?"MISSING":"") )); return file; } void Set_Base_Factory( FileFactoryClass * factory ) { BaseFactory = factory; } private: FileFactoryClass * BaseFactory; }; /* ** */ class StrippingFileFactoryClass : public SimpleFileFactoryClass { public: virtual FileClass * Get_File( const char * filename ) { StringClass stripped(true); Strip_Path_From_Filename( stripped, filename ); return BaseFactory->Get_File( stripped ); } void Set_Base_Factory( FileFactoryClass * factory ) { BaseFactory = factory; } private: FileFactoryClass * BaseFactory; }; /* ** */ SimpleFileFactoryClass RenegadeWritingFileFactory; SimpleFileFactoryClass RenegadeBaseFileFactory; MixFileFactoryClass * AlwaysMixFileFactory; FileFactoryListClass _RenegadeFileFactory; StrippingFileFactoryClass AudioFileFactory; LoggingFileFactoryClass LoggingFileFactory; /* ** */ void Construct_Directory_Structure(void) { // // Lookup the path of the executable // char path[MAX_PATH] = { 0 }; ::GetModuleFileName (NULL, path, sizeof (path)); // // Strip off the filename // char *filename = ::strrchr (path, '\\'); if (filename != NULL) { filename[1] = 0; } StringClass data_dir(path,true); data_dir += "data"; StringClass save_dir(data_dir + "\\save",true); StringClass config_dir(data_dir + "\\config",true); // // Create the data directory if necessary // if (GetFileAttributes (data_dir) == 0xFFFFFFFF) { ::CreateDirectory (data_dir, NULL); } // // Create the save directory if necessary // if (GetFileAttributes (save_dir) == 0xFFFFFFFF) { ::CreateDirectory (save_dir, NULL); } // // Create the config directory if necessary // if (GetFileAttributes (config_dir) == 0xFFFFFFFF) { ::CreateDirectory (config_dir, NULL); } return ; } static bool Verify_Log_Directory(const StringClass& folder) { if (GetFileAttributes(folder)!=0xffffffff) return true; //HANDLE file; //file = CreateFile(folder, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //if (file!=INVALID_HANDLE_VALUE) { // CloseHandle(file); // return true; //} if (CreateDirectory(folder,NULL)) { return true; } if (GetLastError() == ERROR_ALREADY_EXISTS) { return(true); } return false; } static bool Create_Log_File_Name(const StringClass& folder, StringClass& filename,bool use_numbering) { StringClass original(filename); if (!use_numbering) { filename.Format("%s\\%s",folder,original); return true; } for (int i=0;i<999;++i) { HANDLE file; filename.Format("%s\\%3.3d%s",folder,i,original); file = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (file!=INVALID_HANDLE_VALUE) { CloseHandle(file); return true; } } return false; } static void Copy_Log(const StringClass& folder,const char* filename,bool use_numbering) { RawFileClass raw_log_file(filename); if (raw_log_file.Is_Available()) { int size=raw_log_file.Size(); if (size) { StringClass log_file_name(filename); if (Create_Log_File_Name(folder,log_file_name,use_numbering)) { DWORD written; HANDLE file; file = CreateFile(log_file_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE != file) { raw_log_file.Open(); unsigned char* memory=new unsigned char[size]; raw_log_file.Read(memory,size); raw_log_file.Close(); WriteFile(file, memory, size, &written, NULL); delete[] memory; CloseHandle(file); } } } } } static class CopyThreadClass : public ThreadClass { public: unsigned Version; CopyThreadClass() : Version(0), ThreadClass("LogCopyThread", &Exception_Handler) {} void Thread_Function() { // Write log to network folder char computer_name[MAX_COMPUTERNAME_LENGTH + 1]; DWORD size = sizeof(computer_name); ::GetComputerName(computer_name, &size); RegistryClass reg(APPLICATION_SUB_KEY_NAME_DEBUG); char path[MAX_PATH]; reg.Get_String("LogPath", path, sizeof(path), "\\\\tanya\\game\\projects\\renegade\\_error_logs"); strcat(path, "\\"); StringClass folder_name(0,true); folder_name.Format("%s%d.%d",path,Version>>16,Version&0xffff); if (!Verify_Log_Directory(folder_name)) return; folder_name+="\\"; folder_name+=computer_name; if (!Verify_Log_Directory(folder_name)) return; Copy_Log(folder_name,DebugManager::Logfile_Name(),true); //"_logfile.txt",true); Copy_Log(folder_name,"_asserts.txt",true); Copy_Log(folder_name,"_except.txt",true); Copy_Log(folder_name,"sysinfo.txt",false); } } CopyThread; void Copy_Logs(unsigned version) { RegistryClass registry( APPLICATION_SUB_KEY_NAME_DEBUG ); if ( registry.Is_Valid() ) { if (registry.Get_Int( VALUE_NAME_DISABLE_LOG_COPYING,0 )) return; } if (CopyThread.Is_Running()) return; CopyThread.Version=version; CopyThread.Execute(); int time=TIMEGETTIME(); while (TIMEGETTIME()-time<5000) { if (!CopyThread.Is_Running()) { break; } Sleep(100); } } void Application_Exception_Callback(void) { #ifdef WWDEBUG Copy_Logs(DebugManager::Get_Version_Number()); #endif // WWDEBUG RegistryClass registry( APPLICATION_SUB_KEY_NAME_DEBUG ); if ( registry.Is_Valid() ) { registry.Set_Int( VALUE_NAME_APPLICATION_CRASH_VERSION, 0 ); } } bool RestartNeeded = true; /*********************************************************************************************** * Get_Version_Number -- Collate version information. * * * * * * * * INPUT: Ptr to var to fill with major version number * * Ptr to var to fill with minor version number * * * * * * OUTPUT: Nothing * * * * WARNINGS: None * * * * HISTORY: * * 12/3/2001 11:26PM ST : Created * *=============================================================================================*/ void Get_Version_Number(unsigned long *major, unsigned long *minor) { // Version info removed per Legal review requirements. LFeenanEA - 8th February 2025 unsigned long version_major = 0; unsigned long version_minor = 0; } /* ** */ #if 0 #define FIRST_CHAR 'a' #define LAST_CHAR 'z' #include "realcrc.h" int CRC_Next( unsigned char ** p, int length ) { int ret = 0; if ( length == -1 ) { return 1; } if ( **p == LAST_CHAR ) { *p = *p-1; ret |= CRC_Next( p, length-1 ); *p = *p+1; **p = FIRST_CHAR; } else { **p = **p+1; } return ret; } void CRC_Check( void ) { Debug_Say(( "CRC_Check\n" )); int count = 0; #define MAX_STRING 10 #define GOAL_CRC 65729409 int start = timeGetTime(); unsigned char string[MAX_STRING+1]; for ( int length = 1; length <= MAX_STRING; length++ ) { unsigned char * p = &string[length-1]; string[length] = 0; for ( int i = 0; i < length; i++ ) { string[i] = FIRST_CHAR; } while ( 1 ) { /* if ( (count & 0x0FFFF) == 0 ) { Debug_Say(( "Checking %d \"%s\"\n", count, string )); }*/ int crc = CRC_String( (char *)string ); if ( crc == GOAL_CRC ) { Debug_Say(( "CRC MATCH \"%s\" (count %d) at %d\n\n", string, count, timeGetTime()-start )); } count++; if ( CRC_Next( &p, length-1 ) != 0 ) { break; } } Debug_Say(( "End length %d (count %d) at %d\n", length, count, timeGetTime()-start )); } // strcpy( string, "miketheheadlesschickenisgod" ); // Debug_Say(( "CRC %d\n", crc )); return; } #endif /* ** */ bool Game_Init(void) { WWMEMLOG(MEM_GAMEINIT); // Set registry key to 1 for the duration of the init. This way we know if the program crashed while the init. RegistryClass registry( APPLICATION_SUB_KEY_NAME_DEBUG ); if ( registry.Is_Valid() ) { registry.Set_Int( VALUE_NAME_GAME_INITIALIZATION_IN_PROGRESS, 1 ); unsigned crash_version=registry.Get_Int( VALUE_NAME_APPLICATION_CRASH_VERSION, 0 ); #ifdef WWDEBUG if (crash_version) Copy_Logs(crash_version); #endif // WWDEBUG registry.Set_Int( VALUE_NAME_APPLICATION_CRASH_VERSION, 0 ); } // // Ensure our directory structure exists // Construct_Directory_Structure (); // // Initialize our debugging framework // DebugManager::Init(); DebugManager::Load_Registry_Settings( APPLICATION_SUB_KEY_NAME_DEBUG ); WWDebug_Install_Assert_Handler(Commando_Assert_Handler); BuildInfoClass::Log_Build_Info(); //CRC_Check(); Get_Version_Number(NULL, NULL); // setup Writing Factory RenegadeWritingFileFactory.Set_Sub_Directory( DATA_SUBDIRECTORY ); _TheWritingFileFactory = &RenegadeWritingFileFactory; RenegadeBaseFileFactory.Set_Sub_Directory( DATA_SUBDIRECTORY ); RenegadeBaseFileFactory.Append_Sub_Directory( SAVE_SUBDIRECTORY ); RenegadeBaseFileFactory.Append_Sub_Directory( CONFIG_SUBDIRECTORY ); _TheSimpleFileFactory->Set_Sub_Directory( DATA_SUBDIRECTORY ); _TheSimpleFileFactory->Append_Sub_Directory( SAVE_SUBDIRECTORY ); _TheSimpleFileFactory->Append_Sub_Directory( CONFIG_SUBDIRECTORY ); _TheSimpleFileFactory->Set_Strip_Path( true ); _RenegadeFileFactory.Add_FileFactory( &RenegadeBaseFileFactory, "" ); _RenegadeFileFactory.Add_FileFactory( new MixFileFactoryClass( "Always2.dat", &RenegadeBaseFileFactory ), "Always2.dat" ); _RenegadeFileFactory.Add_FileFactory( new MixFileFactoryClass( "Always.dbs", &RenegadeBaseFileFactory ), "Always.dbs" ); _RenegadeFileFactory.Add_FileFactory( new MixFileFactoryClass( "Always.dat", &RenegadeBaseFileFactory ), "Always.dat" ); // // Search for all mix files in the data directory // WIN32_FIND_DATA find_info = { 0 }; BOOL keep_going = TRUE; HANDLE file_find = NULL; for (file_find = ::FindFirstFile ("data\\*.mix", &find_info); (file_find != INVALID_HANDLE_VALUE) && keep_going; keep_going = ::FindNextFile (file_find, &find_info)) { // // Add this mix file to our mix file factory list // _RenegadeFileFactory.Add_FileFactory( new MixFileFactoryClass (find_info.cFileName, &RenegadeBaseFileFactory ), find_info.cFileName ); } // // Close the search handle // if (file_find != INVALID_HANDLE_VALUE) { ::FindClose (file_find); } _TheFileFactory = &_RenegadeFileFactory; // Logging File Factory if ( DebugManager::Is_File_Logging_Enabled() ) { LoggingFileFactory.Set_Base_Factory( &_RenegadeFileFactory ); _TheFileFactory = &LoggingFileFactory; } AudioFileFactory.Set_Base_Factory( _TheFileFactory ); //Setup_Mix_File(); // Lets seed the Random Generator, a little int count = TIMEGETTIME() & 0xFF; while ( count-- > 0 ) { FreeRandom.Get_Int(); } // Thumbnail manager pre init will ensure that thumbnail database // is up-to-date. bool show_thumbnail_pre_init_dialog = true; #ifdef WWDEBUG show_thumbnail_pre_init_dialog = cDevOptions::ShowThumbnailPreInitDialog.Get(); #endif // WWDEBUG // ThumbnailManagerClass::Pre_Init(show_thumbnail_pre_init_dialog); // // Create an instance of the sound library // new WWAudioClass(ConsoleBox.Is_Exclusive()); WWAudioClass::Get_Instance()->Initialize( APPLICATION_SUB_KEY_NAME_SOUND ); WWAudioClass::Get_Instance()->Set_File_Factory( &AudioFileFactory ); // Install text callback WWAudioClass::Get_Instance()->Register_Text_Callback(AudioTextCallback,0); // // Load the multiplayer settings // MPSettingsMgrClass::Load_Settings (); /* ** */ WW3DAssetManager * asset_manager = new WW3DAssetManager; // asset_manager->Open_Texture_File_Cache("cache_"); asset_manager->Set_WW3D_Load_On_Demand( true ); asset_manager->Register_Prototype_Loader(&_ParticleEmitterLoader); asset_manager->Register_Prototype_Loader(&_SphereLoader); asset_manager->Register_Prototype_Loader(&_RingLoader); asset_manager->Register_Prototype_Loader (&_SoundRenderObjLoader); asset_manager->Set_Activate_Fog_On_Load (true); //GameSettings::Init(); // Initialize WWMath WWMath::Init(); // Initialize the pathfind system PathMgrClass::Initialize (); // Initialize WW3D switch ( WW3D::Init(MainWindow, NULL, ConsoleBox.Is_Exclusive() ? true : false)) { case WW3D_ERROR_OK: // Success! break; case WW3D_ERROR_DIRECTX8_INITIALIZATION_FAILED: default: WWDEBUG_SAY(("WW3D::Init Failed!\r\n")); ::MessageBox(NULL, "DirectX 8.0 or later is required to play C&C:Renegade.", "Renegade Graphics Initialization Error.", MB_OK); return false; } if (ConsoleBox.Is_Exclusive()) { WW3D::Enable_Decals(false); PhysicsSceneClass * scene = PhysicsSceneClass::Get_Instance(); scene->Set_Max_Simultaneous_Shadows(0); DazzleRenderObjClass::Enable_Dazzle_Rendering(false); } else { if ( WW3D::Registry_Load_Render_Device( APPLICATION_SUB_KEY_NAME_RENDER, true ) != WW3D_ERROR_OK ) { WWDEBUG_SAY(("WW3D::Registry_Load_Render_Device Failed!\r\n")); return false; } if ( WW3D::Registry_Save_Render_Device( APPLICATION_SUB_KEY_NAME_RENDER ) != WW3D_ERROR_OK ) { WWDEBUG_SAY(("WW3D::Registry_Save_Render_Device Failed!\r\n")); return false; } WW3D::Enable_Static_Sort_Lists (true); } if (AutoRestart.Get_Restart_Flag() || ServerSettingsClass::Is_Command_Line_Mode() || ConsoleBox.Is_Exclusive()) { if (!ConsoleBox.Is_Exclusive()) { ::ShowWindow( MainWindow, SW_MINIMIZE ); // minimize if we are starting automatically. } ConsoleBox.Init(); } else { ::ShowWindow( MainWindow, SW_SHOW ); // show the (initially hidden) window } // Clear screen for (int frame=0;frame<3;++frame) { WW3D::Begin_Render(true,true,Vector3(0.0f,0.0f,0.0f)); WW3D::End_Render(); } ParticleEmitterClass::Set_Default_Remove_On_Complete(false); // (gth) 09/17/2000 - by default emitters shouldn't self-destruct for (int i=0; i<17; i++) { ParticleBufferClass::Set_LOD_Max_Screen_Size(i,_ParticleLODScreenSizes[i]); } if ( cUserOptions::PermitDiagLogging.Is_True() && DebugManager::Is_Diag_Logging_Enabled() ) { DiagLogClass::Init(); } WWPhys::Init(); WWSaveLoad::Init(); // // Load the strings table // TranslateDBClass::Initialize(); FileClass *file = _TheFileFactory->Get_File( STRINGS_FILENAME ); if (file != NULL) { file->Open (FileClass::READ); // Open or the file if ( file->Is_Available() ) { ChunkLoadClass cload (file); // Load the database SaveLoadSystemClass::Load(cload); } file->Close (); // Close the file _TheFileFactory->Return_File (file); } //TranslateDBClass::Set_Current_Language (TranslateDBClass::LANGID_CHINESE); // // Initialize the input control system // bool dinput_avail = (ConsoleBox.Is_Exclusive()) ? false : true; Input::Init(dinput_avail); Input::Load_Registry( APPLICATION_SUB_KEY_NAME_CONTROLS ); InputConfigMgrClass::Initialize(); // // Initialize the skin selection framework // SkinPackageMgrClass::Initialize (); ModPackageMgrClass::Initialize (); ModPackageMgrClass::Build_List (); // // Load the conversation database // file = _TheFileFactory->Get_File( CONV_DB_FILENAME ); if (file != NULL) { file->Open (FileClass::READ); // Open or the file if ( file->Is_Available() ) { ChunkLoadClass cload (file); // Load the database SaveLoadSystemClass::Load(cload); } file->Close (); // Close the file _TheFileFactory->Return_File (file); } // // Check to make sure the code version matches the strings // table version // if (TranslateDBClass::Get_Version_Number () != STRINGS_VER) { MessageBox( 0, "This build of Renegade is out of sync with the strings database (strings.tdb). Strings will be incorrect and may cause the game to crash.", "Version Error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND ); } // // Note: Due to interdependencies (yuck!) between these subsystems, here's the // order they need to be initialized in: // // - Physics Scene Class (via CombatManager::Scene_Init) // - SystemSettings // - RenegadeDialogMgrClass // // CombatManager::Scene_Init(); if (!ConsoleBox.Is_Exclusive()) { SystemSettings::Init(); } RenegadeDialogMgrClass::Initialize(); cNetwork::Onetime_Init(); cServerFps::Create_Instance(); cPlayerManager::Onetime_Init(); cTeamManager::Onetime_Init(); cGameData::Onetime_Init(); cBandwidthGraph::Onetime_Init(); cNetUtil::Wsa_Init(); CombatManager::Init(ConsoleBox.Is_Exclusive() ? false : true); CampaignManager::Init(); // This order is also draw and think order GameModeManager::Add( new CombatGameModeClass ); GameModeManager::Add( new LanGameModeClass ); GameModeManager::Add( new WolGameModeClass ); GameModeManager::Add( new OverlayGameModeClass ); GameModeManager::Add( new MenuGameModeClass2 ); // Putting menu after overlay so we see the text GameModeManager::Add( new MovieGameModeClass ); GameModeManager::Add( new ConsoleGameModeClass ); GameModeManager::Add( new ScoreScreenGameModeClass ); //GameModeManager::Add( new LobbyGameModeClass ); GameModeManager::Add( new TextDisplayGameModeClass ); GameModeManager::Add( new Overlay3DGameModeClass ); GameModeManager::Find( "Overlay3D" )->Activate(); GameModeManager::Find( "Overlay" )->Activate(); GameModeManager::Find( "Console" )->Activate(); GameModeManager::Find( "Menu" )->Activate(); GameModeManager::Find( "TextDisplay" )->Activate(); // After TextDisplay is created, install the Display Handler DebugManager::Set_Display_Handler(&TextDisplayHandler); //DEADMENU MenuManager::Set_Menu( "Menu_Main" ); // Load the accelerator table and hand it off to WWLIB. // Note: Accelerator tables that are loaded from resources (like // we are doing here) do not need to be manually freed. Windows // will cleanup for us when the process terminates. HACCEL haccel = ::LoadAccelerators (::GetModuleHandle (NULL), MAKEINTRESOURCE (IDR_ACCELERATOR)); if (haccel) { ::Add_Accelerator (MainWindow, haccel); } //WW3D::Set_Texture_Reduction( 1 ); // // Initialize the encyclopedia logic // EncyclopediaMgrClass::Initialize (); #if (IMMEDIATE_LOAD) // Immediately load up the specified level GameInitMgrClass::Initialize_SP (); GameInitMgrClass::Start_Game (IMMEDIATE_LOAD_LEVELNAME); #endif cDiagnostics::Init(); //cHelpText::Init(); // // NIC initialization // cNicEnum::Init(); if ( registry.Is_Valid() ) { registry.Set_Int( VALUE_NAME_GAME_INITIALIZATION_IN_PROGRESS, 0 ); registry.Set_Int( VALUE_NAME_APPLICATION_CRASH_VERSION, DebugManager::Get_Version_Number() ); } #if (IMMEDIATE_LOAD==0) #if 0 // Not anymore // // Start the main menu // RenegadeDialogMgrClass::Goto_Location (RenegadeDialogMgrClass::LOC_MAIN_MENU); #else // // Parse the server settings files if they will be used soon to make sure there are no errors. // if (ServerSettingsClass::Is_Command_Line_Mode()) { if (!ServerSettingsClass::Parse(false)) { AutoRestart.Set_Restart_Flag(false); Game_Shutdown(); return (false); } } // // If this is a post crash restart (or a FDS starting up) then just go straight into the game. // if (AutoRestart.Get_Restart_Flag()) { AutoRestart.Restart_Game(); } else if (cGameSpyAdmin::Is_Gamespy_Game()) { if (!ConsoleBox.Is_Exclusive()) { RenegadeDialogMgrClass::Goto_Location (RenegadeDialogMgrClass::LOC_SPLASH_IN); } } else { MovieGameModeClass * mode = (MovieGameModeClass *)GameModeManager::Find ("Movie"); if ( mode ) { mode->Activate(); mode->Startup_Movies( ); } } #endif #endif // // Send our Spy Usage Info off to Gamespy // GameSpyQnR.TrackUsage(); return true; } /*********************************************************************************************** * Build_Registry_Location_String -- Get a complete path to a registry location * * * * * * * * INPUT: Game base path * * Base modifier path * * Sub path * * * * OUTPUT: Ptr to complete path * * * * WARNINGS: None * * * * HISTORY: * * 11/9/2001 3:39PM ST : Created * *=============================================================================================*/ char *Build_Registry_Location_String(char *base, char *modifier, char *sub) { static char _whole_registry_string[1024]; WWASSERT(base != NULL); WWASSERT(sub != NULL); if (modifier == NULL) { modifier = DefaultRegistryModifier; } if (base && *base != 0) { strcpy(_whole_registry_string, base); } if (modifier && *modifier != 0) { strcat(_whole_registry_string, "\\"); strcat(_whole_registry_string, modifier); } if (sub && *sub != 0) { strcat(_whole_registry_string, "\\"); strcat(_whole_registry_string, sub); } return(_whole_registry_string); }