/* ================== WinMain ================== */ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { const HCURSOR hcurSave = ::SetCursor(LoadCursor(0, IDC_WAIT)); Sys_SetPhysicalWorkMemory(192 << 20, 1024 << 20); Sys_GetCurrentMemoryStatus(exeLaunchMemoryStats); #if 0 DWORD handler = (DWORD)_except_handler; __asm { // Build EXCEPTION_REGISTRATION record: push handler // Address of handler function push FS:[0] // Address of previous handler mov FS:[0],ESP // Install new EXECEPTION_REGISTRATION } #endif win32.hInstance = hInstance; idStr::Copynz(sys_cmdline, lpCmdLine, sizeof(sys_cmdline)); // done before Com/Sys_Init since we need this for error output Sys_CreateConsole(); // no abort/retry/fail errors SetErrorMode(SEM_FAILCRITICALERRORS); for (int i = 0; i < MAX_CRITICAL_SECTIONS; i++) { InitializeCriticalSection(&win32.criticalSections[i]); } // get the initial time base Sys_Milliseconds(); #ifdef DEBUG // disable the painfully slow MS heap check every 1024 allocs _CrtSetDbgFlag(0); #endif // Sys_FPU_EnableExceptions( TEST_FPU_EXCEPTIONS ); Sys_FPU_SetPrecision(FPU_PRECISION_DOUBLE_EXTENDED); common->Init(0, NULL, lpCmdLine); #if TEST_FPU_EXCEPTIONS != 0 common->Printf(Sys_FPU_GetState()); #endif #ifndef ID_DEDICATED if (win32.win_notaskkeys.GetInteger()) { DisableTaskKeys(TRUE, FALSE, /*( win32.win_notaskkeys.GetInteger() == 2 )*/ FALSE); } #endif Sys_StartAsyncThread(); // hide or show the early console as necessary if (win32.win_viewlog.GetInteger() || com_skipRenderer.GetBool() || idAsyncNetwork::serverDedicated.GetInteger()) { Sys_ShowConsole(1, true); } else { Sys_ShowConsole(0, false); } #ifdef SET_THREAD_AFFINITY // give the main thread an affinity for the first cpu SetThreadAffinityMask(GetCurrentThread(), 1); #endif ::SetCursor(hcurSave); // Launch the script debugger if (strstr(lpCmdLine, "+debugger")) { // DebuggerClientInit( lpCmdLine ); return 0; } ::SetFocus(win32.hWnd); // main game loop while (1) { Win_Frame(); #ifdef DEBUG Sys_MemFrame(); #endif // set exceptions, even if some crappy syscall changes them! Sys_FPU_EnableExceptions(TEST_FPU_EXCEPTIONS); #ifdef ID_ALLOW_TOOLS if (com_editors) { if (com_editors & EDITOR_GUI) { // GUI editor GUIEditorRun(); } else if (com_editors & EDITOR_RADIANT) { // Level Editor RadiantRun(); } else if (com_editors & EDITOR_MATERIAL) { //BSM Nerve: Add support for the material editor MaterialEditorRun(); } else { if (com_editors & EDITOR_LIGHT) { // in-game Light Editor LightEditorRun(); } if (com_editors & EDITOR_SOUND) { // in-game Sound Editor SoundEditorRun(); } if (com_editors & EDITOR_DECL) { // in-game Declaration Browser DeclBrowserRun(); } if (com_editors & EDITOR_AF) { // in-game Articulated Figure Editor AFEditorRun(); } if (com_editors & EDITOR_PARTICLE) { // in-game Particle Editor ParticleEditorRun(); } if (com_editors & EDITOR_SCRIPT) { // in-game Script Editor ScriptEditorRun(); } if (com_editors & EDITOR_PDA) { // in-game PDA Editor PDAEditorRun(); } } } #endif // run the game common->Frame(); } // never gets here return 0; }
/* ================== WinMain ================== */ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { const HCURSOR hcurSave = ::SetCursor( LoadCursor( 0, IDC_WAIT ) ); Sys_SetPhysicalWorkMemory( 192 << 20, 1024 << 20 ); Sys_GetCurrentMemoryStatus( exeLaunchMemoryStats ); #if 0 DWORD handler = (DWORD)_except_handler; __asm { // Build EXCEPTION_REGISTRATION record: push handler // Address of handler function push FS:[0] // Address of previous handler mov FS:[0],ESP // Install new EXECEPTION_REGISTRATION } #endif win32.hInstance = hInstance; idStr::Copynz( sys_cmdline, lpCmdLine, sizeof( sys_cmdline ) ); // done before Com/Sys_Init since we need this for error output Sys_CreateConsole(); // no abort/retry/fail errors SetErrorMode( SEM_FAILCRITICALERRORS ); for ( int i = 0; i < MAX_CRITICAL_SECTIONS; i++ ) { InitializeCriticalSection( &win32.criticalSections[i] ); } // make sure the timer is high precision, otherwise // NT gets 18ms resolution timeBeginPeriod( 1 ); // get the initial time base Sys_Milliseconds(); #ifdef DEBUG // disable the painfully slow MS heap check every 1024 allocs _CrtSetDbgFlag( 0 ); #endif // Sys_FPU_EnableExceptions( TEST_FPU_EXCEPTIONS ); Sys_FPU_SetPrecision( FPU_PRECISION_DOUBLE_EXTENDED ); common->Init( 0, NULL, lpCmdLine ); #if TEST_FPU_EXCEPTIONS != 0 common->Printf( Sys_FPU_GetState() ); #endif if ( win32.win_notaskkeys.GetInteger() ) { DisableTaskKeys( TRUE, FALSE, /*( win32.win_notaskkeys.GetInteger() == 2 )*/ FALSE ); } // hide or show the early console as necessary if ( win32.win_viewlog.GetInteger() ) { Sys_ShowConsole( 1, true ); } else { Sys_ShowConsole( 0, false ); } #ifdef SET_THREAD_AFFINITY // give the main thread an affinity for the first cpu SetThreadAffinityMask( GetCurrentThread(), 1 ); #endif ::SetCursor( hcurSave ); ::SetFocus( win32.hWnd ); // main game loop while( 1 ) { Win_Frame(); #ifdef DEBUG Sys_MemFrame(); #endif // set exceptions, even if some crappy syscall changes them! Sys_FPU_EnableExceptions( TEST_FPU_EXCEPTIONS ); // run the game common->Frame(); } // never gets here return 0; }
/* ================== WinMain ================== */ int main(int argc, char *argv[]) { const HCURSOR hcurSave = ::SetCursor( LoadCursor( 0, IDC_WAIT ) ); Sys_SetPhysicalWorkMemory( 192 << 20, 1024 << 20 ); win32.hInstance = GetModuleHandle(NULL); // done before Com/Sys_Init since we need this for error output Sys_CreateConsole(); // no abort/retry/fail errors SetErrorMode( SEM_FAILCRITICALERRORS ); #ifdef DEBUG // disable the painfully slow MS heap check every 1024 allocs _CrtSetDbgFlag( 0 ); #endif if ( argc > 1 ) { common->Init( argc-1, &argv[1] ); } else { common->Init( 0, NULL ); } // hide or show the early console as necessary if ( win32.win_viewlog.GetInteger() || com_skipRenderer.GetBool() || idAsyncNetwork::serverDedicated.GetInteger() ) { Sys_ShowConsole( 1, true ); } else { Sys_ShowConsole( 0, false ); } #ifdef SET_THREAD_AFFINITY // give the main thread an affinity for the first cpu SetThreadAffinityMask( GetCurrentThread(), 1 ); #endif ::SetCursor( hcurSave ); // Launch the script debugger if ( strstr( GetCommandLine(), "+debugger" ) ) { // DebuggerClientInit( lpCmdLine ); return 0; } ::SetFocus( win32.hWnd ); // main game loop while( 1 ) { Win_Frame(); #ifdef ID_ALLOW_TOOLS if ( com_editors ) { if ( com_editors & EDITOR_GUI ) { // GUI editor GUIEditorRun(); } else if ( com_editors & EDITOR_RADIANT ) { // Level Editor RadiantRun(); } else if (com_editors & EDITOR_MATERIAL ) { //BSM Nerve: Add support for the material editor MaterialEditorRun(); } else { if ( com_editors & EDITOR_LIGHT ) { // in-game Light Editor LightEditorRun(); } if ( com_editors & EDITOR_SOUND ) { // in-game Sound Editor SoundEditorRun(); } if ( com_editors & EDITOR_DECL ) { // in-game Declaration Browser DeclBrowserRun(); } if ( com_editors & EDITOR_AF ) { // in-game Articulated Figure Editor AFEditorRun(); } if ( com_editors & EDITOR_PARTICLE ) { // in-game Particle Editor ParticleEditorRun(); } if ( com_editors & EDITOR_SCRIPT ) { // in-game Script Editor ScriptEditorRun(); } if ( com_editors & EDITOR_PDA ) { // in-game PDA Editor PDAEditorRun(); } } } #endif // run the game common->Frame(); } // never gets here return 0; }
/* =============== idCommonLocal::ExecuteMapChange Performs the initialization of a game based on session match parameters, used for both single player and multiplayer, but not for renderDemos, which don't create a game at all. Exits with mapSpawned = true =============== */ void idCommonLocal::ExecuteMapChange() { if ( session->GetState() != idSession::LOADING ) { idLib::Warning( "Session state is not LOADING in ExecuteMapChange" ); return; } // Clear all dialogs before beginning the load common->Dialog().ClearDialogs( true ); // Remember the current load ID. // This is so we can tell if we had a new loadmap request from within an existing loadmap call const int cachedLoadingID = session->GetLoadingID(); const idMatchParameters & matchParameters = session->GetActingGameStateLobbyBase().GetMatchParms(); if ( matchParameters.numSlots <= 0 ) { idLib::Warning( "numSlots <= 0 in ExecuteMapChange" ); return; } insideExecuteMapChange = true; common->Printf( "--------- Execute Map Change ---------\n" ); common->Printf( "Map: %s\n", matchParameters.mapName.c_str() ); // ensure that r_znear is reset to the default value // this fixes issues with the projection matrix getting messed up when switching maps or loading a saved game // while an in-game cinematic is playing. cvarSystem->SetCVarFloat( "r_znear", 1.0f ); // reset all cheat cvars for a multiplayer game if ( IsMultiplayer() ) { cvarSystem->ResetFlaggedVariables( CVAR_CHEAT ); } int start = Sys_Milliseconds(); for ( int i = 0; i < MAX_INPUT_DEVICES; i++ ) { Sys_SetRumble( i, 0, 0 ); } // close console and remove any prints from the notify lines console->Close(); // clear all menu sounds soundWorld->Pause(); menuSoundWorld->ClearAllSoundEmitters(); soundSystem->SetPlayingSoundWorld( menuSoundWorld ); soundSystem->Render(); // extract the map name from serverinfo currentMapName = matchParameters.mapName; currentMapName.StripFileExtension(); idStrStatic< MAX_OSPATH > fullMapName = "maps/"; fullMapName += currentMapName; fullMapName.SetFileExtension( "map" ); if ( mapSpawnData.savegameFile ) { fileSystem->BeginLevelLoad( currentMapName, NULL, 0 ); } else { fileSystem->BeginLevelLoad( currentMapName, saveFile.GetDataPtr(), saveFile.GetAllocated() ); } // capture the current screen and start a wipe // immediately complete the wipe to fade out the level transition // run the wipe to completion StartWipe( "wipeMaterial", true ); CompleteWipe(); int sm = Sys_Milliseconds(); // shut down the existing game if it is running UnloadMap(); int ms = Sys_Milliseconds() - sm; common->Printf( "%6d msec to unload map\n", ms ); // Free media from previous level and // note which media we are going to need to load sm = Sys_Milliseconds(); renderSystem->BeginLevelLoad(); soundSystem->BeginLevelLoad(); declManager->BeginLevelLoad(); uiManager->BeginLevelLoad(); ms = Sys_Milliseconds() - sm; common->Printf( "%6d msec to free assets\n", ms ); //Sys_DumpMemory( true ); // load / program a gui to stay up on the screen while loading // set the loading gui that we will wipe to bool hellMap = false; LoadLoadingGui( currentMapName, hellMap ); // Stop rendering the wipe ClearWipe(); if ( fileSystem->UsingResourceFiles() ) { idStrStatic< MAX_OSPATH > manifestName = currentMapName; manifestName.Replace( "game/", "maps/" ); manifestName.Replace( "/mp/", "/" ); manifestName += ".preload"; idPreloadManifest manifest; manifest.LoadManifest( manifestName ); renderSystem->Preload( manifest, currentMapName ); soundSystem->Preload( manifest ); game->Preload( manifest ); } if ( common->IsMultiplayer() ) { // In multiplayer, make sure the player is either 60Hz or 120Hz // to avoid potential issues. const float mpEngineHz = ( com_engineHz.GetFloat() < 90.0f ) ? 60.0f : 120.0f; com_engineHz_denominator = 100LL * mpEngineHz; com_engineHz_latched = mpEngineHz; } else { // allow com_engineHz to be changed between map loads com_engineHz_denominator = 100LL * com_engineHz.GetFloat(); com_engineHz_latched = com_engineHz.GetFloat(); } // note any warning prints that happen during the load process common->ClearWarnings( currentMapName ); // release the mouse cursor // before we do this potentially long operation Sys_GrabMouseCursor( false ); // let the renderSystem load all the geometry if ( !renderWorld->InitFromMap( fullMapName ) ) { common->Error( "couldn't load %s", fullMapName.c_str() ); } // for the synchronous networking we needed to roll the angles over from // level to level, but now we can just clear everything usercmdGen->InitForNewMap(); // load and spawn all other entities ( from a savegame possibly ) if ( mapSpawnData.savegameFile ) { if ( !game->InitFromSaveGame( fullMapName, renderWorld, soundWorld, mapSpawnData.savegameFile, mapSpawnData.stringTableFile, mapSpawnData.savegameVersion ) ) { // If the loadgame failed, end the session, which will force us to go back to the main menu session->QuitMatchToTitle(); } } else { if ( !IsMultiplayer() ) { assert( game->GetLocalClientNum() == 0 ); assert( matchParameters.gameMode == GAME_MODE_SINGLEPLAYER ); assert( matchParameters.gameMap == GAME_MAP_SINGLEPLAYER ); game->SetPersistentPlayerInfo( 0, mapSpawnData.persistentPlayerInfo ); } game->SetServerInfo( matchParameters.serverInfo ); game->InitFromNewMap( fullMapName, renderWorld, soundWorld, matchParameters.gameMode, Sys_Milliseconds() ); } game->Shell_CreateMenu( true ); // Reset some values important to multiplayer ResetNetworkingState(); // If the session state is not loading here, something went wrong. if ( session->GetState() == idSession::LOADING && session->GetLoadingID() == cachedLoadingID ) { // Notify session we are done loading session->LoadingFinished(); while ( session->GetState() == idSession::LOADING ) { Sys_GenerateEvents(); session->UpdateSignInManager(); session->Pump(); Sys_Sleep( 10 ); } } if ( !mapSpawnData.savegameFile ) { // run a single frame to catch any resources that are referenced by events posted in spawn idUserCmdMgr emptyCommandManager; gameReturn_t emptyGameReturn; for ( int playerIndex = 0; playerIndex < MAX_PLAYERS; ++playerIndex ) { emptyCommandManager.PutUserCmdForPlayer( playerIndex, usercmd_t() ); } if ( IsClient() ) { game->ClientRunFrame( emptyCommandManager, false, emptyGameReturn ); } else { game->RunFrame( emptyCommandManager, emptyGameReturn ); } } renderSystem->EndLevelLoad(); soundSystem->EndLevelLoad(); declManager->EndLevelLoad(); uiManager->EndLevelLoad( currentMapName ); fileSystem->EndLevelLoad(); if ( !mapSpawnData.savegameFile && !IsMultiplayer() ) { common->Printf( "----- Running initial game frames -----\n" ); // In single player, run a bunch of frames to make sure ragdolls are settled idUserCmdMgr emptyCommandManager; gameReturn_t emptyGameReturn; for ( int i = 0; i < 100; i++ ) { for ( int playerIndex = 0; playerIndex < MAX_PLAYERS; ++playerIndex ) { emptyCommandManager.PutUserCmdForPlayer( playerIndex, usercmd_t() ); } game->RunFrame( emptyCommandManager, emptyGameReturn ); } // kick off an auto-save of the game (so we can always continue in this map if we die before hitting an autosave) common->Printf( "----- Saving Game -----\n" ); SaveGame( "autosave" ); } common->Printf( "----- Generating Interactions -----\n" ); // let the renderSystem generate interactions now that everything is spawned renderWorld->GenerateAllInteractions(); { int vertexMemUsedKB = vertexCache.staticData.vertexMemUsed.GetValue() / 1024; int indexMemUsedKB = vertexCache.staticData.indexMemUsed.GetValue() / 1024; idLib::Printf( "Used %dkb of static vertex memory (%d%%)\n", vertexMemUsedKB, vertexMemUsedKB * 100 / ( STATIC_VERTEX_MEMORY / 1024 ) ); idLib::Printf( "Used %dkb of static index memory (%d%%)\n", indexMemUsedKB, indexMemUsedKB * 100 / ( STATIC_INDEX_MEMORY / 1024 ) ); } if ( common->JapaneseCensorship() ) { if ( currentMapName.Icmp( "game/mp/d3xpdm3" ) == 0 ) { const idMaterial * gizpool2 = declManager->FindMaterial( "textures/hell/gizpool2" ); idMaterial * chiglass1bluex = const_cast<idMaterial *>( declManager->FindMaterial( "textures/sfx/chiglass1bluex" ) ); idTempArray<char> text( gizpool2->GetTextLength() ); gizpool2->GetText( text.Ptr() ); chiglass1bluex->Parse( text.Ptr(), text.Num(), false ); } } common->PrintWarnings(); session->Pump(); if ( session->GetState() != idSession::INGAME ) { // Something went wrong, don't process stale reliables that have been queued up. reliableQueue.Clear(); } usercmdGen->Clear(); // remove any prints from the notify lines console->ClearNotifyLines(); Sys_SetPhysicalWorkMemory( -1, -1 ); // at this point we should be done with the loading gui so we kill it delete loadGUI; loadGUI = NULL; // capture the current screen and start a wipe StartWipe( "wipe2Material" ); // we are valid for game draws now insideExecuteMapChange = false; mapSpawned = true; Sys_ClearEvents(); int msec = Sys_Milliseconds() - start; common->Printf( "%6d msec to load %s\n", msec, currentMapName.c_str() ); //Sys_DumpMemory( false ); // Issue a render at the very end of the load process to update soundTime before the first frame soundSystem->Render(); }