void D_DoomMain()

in doom_py/src/vizdoom/src/d_main.cpp [2277:2731]


void D_DoomMain (void)
{
	int p;
	const char *v;
	const char *wad;
	DArgs *execFiles;
	TArray<FString> pwads;
	FString *args;
	int argcount;	
	FIWadManager *iwad_man;

	// +logfile gets checked too late to catch the full startup log in the logfile so do some extra check for it here.
	FString logfile = Args->TakeValue("+logfile");
	if (logfile.IsNotEmpty())
	{
		execLogfile(logfile);
	}

	if (Args->CheckParm("-hashfiles"))
	{
		const char *filename = "fileinfo.txt";
		Printf("Hashing loaded content to: %s\n", filename);
		hashfile = fopen(filename, "w");
		if (hashfile)
		{
			fprintf(hashfile, "%s version %s (%s)\n", GAMENAME, GetVersionString(), GetGitHash());
#ifdef __VERSION__
			fprintf(hashfile, "Compiler version: %s\n", __VERSION__);
#endif
			fprintf(hashfile, "Command line:");
			for (int i = 0; i < Args->NumArgs(); ++i)
			{
				fprintf(hashfile, " %s", Args->GetArg(i));
			}
			fprintf(hashfile, "\n");
		}
	}

	D_DoomInit();

	// [RH] Make sure zdoom.pk3 is always loaded,
	// as it contains magic stuff we need.

	wad = BaseFileSearch (BASEWAD, NULL, true);
	if (wad == NULL)
	{
		I_FatalError ("Cannot find " BASEWAD);
	}
	FString basewad = wad;

	iwad_man = new FIWadManager;
	iwad_man->ParseIWadInfos(basewad);

	// Now that we have the IWADINFO, initialize the autoload ini sections.
	GameConfig->DoAutoloadSetup(iwad_man);

	PClass::StaticInit ();
	atterm(FinalGC);

	// reinit from here

	do
	{
		if (restart)
		{
			C_InitConsole(SCREENWIDTH, SCREENHEIGHT, false);
		}
		nospriterename = false;

		// Load zdoom.pk3 alone so that we can get access to the internal gameinfos before 
		// the IWAD is known.

		GetCmdLineFiles(pwads);
		FString iwad = CheckGameInfo(pwads);

		// The IWAD selection dialogue does not show in fullscreen so if the
		// restart is initiated without a defined IWAD assume for now that it's not going to change.
		if (iwad.IsEmpty()) iwad = lastIWAD;

		if (iwad_man == NULL)
		{
			iwad_man = new FIWadManager;
			iwad_man->ParseIWadInfos(basewad);
		}
		const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad, basewad);
		gameinfo.gametype = iwad_info->gametype;
		gameinfo.flags = iwad_info->flags;
		gameinfo.ConfigName = iwad_info->Configname;
		lastIWAD = iwad;

		//if ((gameinfo.flags & GI_SHAREWARE) && pwads.Size() > 0)
		//{
		//	I_FatalError ("You cannot -file with the shareware version. Register!");
		//}

		FBaseCVar::DisableCallbacks();
		GameConfig->DoGameSetup (gameinfo.ConfigName);

		AddAutoloadFiles(iwad_info->Autoname);

		// Process automatically executed files
		FExecList *exec;
		execFiles = new DArgs;
		GameConfig->AddAutoexec(execFiles, gameinfo.ConfigName);
		exec = D_MultiExec(execFiles, NULL);

		// Process .cfg files at the start of the command line.
		execFiles = Args->GatherFiles ("-exec");
		exec = D_MultiExec(execFiles, exec);

		// [RH] process all + commands on the command line
		exec = C_ParseCmdLineParams(exec);

		CopyFiles(allwads, pwads);
		if (exec != NULL)
		{
			exec->AddPullins(allwads);
		}

		// Since this function will never leave we must delete this array here manually.
		pwads.Clear();
		pwads.ShrinkToFit();

		if (hashfile)
		{
			Printf("Notice: File hashing is incredibly verbose. Expect loading files to take much longer than usual.\n");
		}

		Printf ("W_Init: Init WADfiles.\n");
		Wads.InitMultipleFiles (allwads);
		allwads.Clear();
		allwads.ShrinkToFit();
		SetMapxxFlag();

		GameConfig->DoKeySetup(gameinfo.ConfigName);

		// Now that wads are loaded, define mod-specific cvars.
		ParseCVarInfo();

		// Actually exec command line commands and exec files.
		if (exec != NULL)
		{
			exec->ExecCommands();
			delete exec;
			exec = NULL;
		}

		// [RH] Initialize localizable strings.
		GStrings.LoadStrings (false);

		V_InitFontColors ();

		// [RH] Moved these up here so that we can do most of our
		//		startup output in a fullscreen console.

		CT_Init ();

		if (!restart)
		{
			Printf ("I_Init: Setting up machine state.\n");
			I_Init ();
			I_CreateRenderer();
		}

		Printf ("V_Init: allocate screen.\n");
		V_Init (!!restart);

		// Base systems have been inited; enable cvar callbacks
		FBaseCVar::EnableCallbacks ();

		Printf ("S_Init: Setting up sound.\n");
		S_Init ();

		Printf ("ST_Init: Init startup screen.\n");
		if (!restart)
		{
			StartScreen = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5);
		}
		else
		{
			StartScreen = new FStartupScreen(0);
		}

		ParseCompatibility();

		CheckCmdLine();

		// [RH] Load sound environments
		S_ParseReverbDef ();

		// [RH] Parse any SNDINFO lumps
		Printf ("S_InitData: Load sound definitions.\n");
		S_InitData ();

		// [RH] Parse through all loaded mapinfo lumps
		Printf ("G_ParseMapInfo: Load map definitions.\n");
		G_ParseMapInfo (iwad_info->MapInfo);
		ReadStatistics();

		// MUSINFO must be parsed after MAPINFO
		S_ParseMusInfo();

		Printf ("Texman.Init: Init texture manager.\n");
		TexMan.Init();
		C_InitConback();

		// [CW] Parse any TEAMINFO lumps.
		Printf ("ParseTeamInfo: Load team definitions.\n");
		TeamLibrary.ParseTeamInfo ();

		FActorInfo::StaticInit ();

		// [GRB] Initialize player class list
		SetupPlayerClasses ();


		// [RH] Load custom key and weapon settings from WADs
		D_LoadWadSettings ();

		// [GRB] Check if someone used clearplayerclasses but not addplayerclass
		if (PlayerClasses.Size () == 0)
		{
			I_FatalError ("No player classes defined");
		}

		StartScreen->Progress ();

		Printf ("R_Init: Init %s refresh subsystem.\n", gameinfo.ConfigName.GetChars());
		StartScreen->LoadingStatus ("Loading graphics", 0x3f);
		R_Init ();

		Printf ("DecalLibrary: Load decals.\n");
		DecalLibrary.ReadAllDecals ();

		// [RH] Add any .deh and .bex files on the command line.
		// If there are none, try adding any in the config file.
		// Note that the command line overrides defaults from the config.

		if ((ConsiderPatches("-deh") | ConsiderPatches("-bex")) == 0 &&
			gameinfo.gametype == GAME_Doom && GameConfig->SetSection ("Doom.DefaultDehacked"))
		{
			const char *key;
			const char *value;

			while (GameConfig->NextInSection (key, value))
			{
				if (stricmp (key, "Path") == 0 && FileExists (value))
				{
					Printf ("Applying patch %s\n", value);
					D_LoadDehFile(value);
				}
			}
		}

		// Load embedded Dehacked patches
		D_LoadDehLumps();

		// Create replacements for dehacked pickups
		FinishDehPatch();

		InitActorNumsFromMapinfo();
		InitSpawnablesFromMapinfo();
		FActorInfo::StaticSetActorNums ();

		//Added by MC:
		bglobal.getspawned.Clear();
		argcount = Args->CheckParmList("-bots", &args);
		for (p = 0; p < argcount; ++p)
		{
			bglobal.getspawned.Push(args[p]);
		}
		bglobal.spawn_tries = 0;
		bglobal.wanted_botnum = bglobal.getspawned.Size();

		Printf ("M_Init: Init menus.\n");
		M_Init ();

		Printf ("P_Init: Init Playloop state.\n");
		StartScreen->LoadingStatus ("Init game engine", 0x3f);
		AM_StaticInit();
		P_Init ();

		P_SetupWeapons_ntohton();

		//SBarInfo support.
		SBarInfo::Load();
		HUD_InitHud();

		// [RH] User-configurable startup strings. Because BOOM does.
		static const char *startupString[5] = {
			"STARTUP1", "STARTUP2", "STARTUP3", "STARTUP4", "STARTUP5"
		};
		for (p = 0; p < 5; ++p)
		{
			const char *str = GStrings[startupString[p]];
			if (str != NULL && str[0] != '\0')
			{
				Printf ("%s\n", str);
			}
		}

		if (!restart)
		{
			Printf ("D_CheckNetGame: Checking network game status.\n");
			StartScreen->LoadingStatus ("Checking network game status.", 0x3f);
			D_CheckNetGame ();
		}

		// [RH] Lock any cvars that should be locked now that we're
		// about to begin the game.
		FBaseCVar::EnableNoSet ();

		delete iwad_man;	// now we won't need this anymore
		iwad_man = NULL;

		// [RH] Run any saved commands from the command line or autoexec.cfg now.
		gamestate = GS_FULLCONSOLE;
		Net_NewMakeTic ();
		DThinker::RunThinkers ();
		gamestate = GS_STARTUP;

		//ViZDoom_Init();

		if (!restart)
		{
			// start the apropriate game based on parms
			v = Args->CheckValue ("-record");

			if (v)
			{
				G_RecordDemo (v);
				autostart = true;
			}

			delete StartScreen;
			StartScreen = NULL;
			S_Sound (CHAN_BODY, "misc/startupdone", 1, ATTN_NONE);

			if (Args->CheckParm("-norun"))
			{
				throw CNoRunExit();
			}

			V_Init2();
			UpdateJoystickMenu(NULL);

#ifdef VIZDOOM_DEPTH_TEST
			depthMap = new depthBuffer(screen->GetWidth(), screen->GetHeight());
			depthMap->setDepthBoundries(120000000,358000);//probabli gud, but SHOULDN'T BE HERE
#endif
			v = Args->CheckValue ("-loadgame");
			if (v)
			{
				FString file(v);
				FixPathSeperator (file);
				DefaultExtension (file, ".zds");
				G_LoadGame (file);
			}

			v = Args->CheckValue("-playdemo");
			if (v != NULL)
			{
				singledemo = true;				// quit after one demo
				G_DeferedPlayDemo (v);
				D_DoomLoop ();	// never returns
			}

			v = Args->CheckValue ("-timedemo");
			if (v)
			{
				G_TimeDemo (v);
				D_DoomLoop ();	// never returns
			}

			if (gameaction != ga_loadgame && gameaction != ga_loadgamehidecon)
			{
				if (autostart || netgame)
				{
					// Do not do any screenwipes when autostarting a game.
					if (!Args->CheckParm("-warpwipe"))
					{
						NoWipe = TICRATE;
					}
					CheckWarpTransMap (startmap, true);
					if (demorecording)
						G_BeginRecording (startmap);
					G_InitNew (startmap, false);
					if (StoredWarp.IsNotEmpty())
					{
						AddCommandString(StoredWarp.LockBuffer());
						StoredWarp = NULL;
					}
				}
				else
				{
					D_StartTitle ();				// start up intro loop
				}
			}
			else if (demorecording)
			{
				G_BeginRecording (NULL);
			}
						
			atterm (D_QuitNetGame);		// killough
		}
		else
		{
			// let the renderer reinitialize some stuff if needed
			screen->GameRestart();
			// These calls from inside V_Init2 are still necessary
			C_NewModeAdjust();
			M_InitVideoModesMenu();
			D_StartTitle ();				// start up intro loop
			setmodeneeded = false;			// This may be set to true here, but isn't needed for a restart
		}

		try
		{
			D_DoomLoop ();		// never returns
		}
		catch (CRestartException &)
		{
			// Music and sound should be stopped first
			//S_StopMusic(true);
			//S_StopAllChannels ();
			delete depthMap;
			ViZDoom_Close();

			M_ClearMenus();					// close menu if open
			F_EndFinale();					// If an intermission is active, end it now

			// clean up game state
			ST_Clear();
			D_ErrorCleanup ();
			P_FreeLevelData();
			P_FreeExtraLevelData();

			M_SaveDefaults(NULL);			// save config before the restart

			// delete all data that cannot be left until reinitialization
			V_ClearFonts();					// must clear global font pointers
			R_DeinitTranslationTables();	// some tables are initialized from outside the translation code.
			gameinfo.~gameinfo_t();
			new (&gameinfo) gameinfo_t;		// Reset gameinfo
			S_Shutdown();					// free all channels and delete playlist
			C_ClearAliases();				// CCMDs won't be reinitialized so these need to be deleted here
			DestroyCVarsFlagged(CVAR_MOD);	// Delete any cvar left by mods

			GC::FullGC();					// perform one final garbage collection before deleting the class data
			PClass::ClearRuntimeData();		// clear all runtime generated class data
			restart++;
		}
	}
	while (1);
}