void FGameConfigFile::DoGameSetup (const char *gamename)
{
	const char *key;
	const char *value;
	enum { Doom, Heretic, Hexen, Strife, Chex } game;

	if (strcmp (gamename, "Heretic") == 0)
		game = Heretic;
	else if (strcmp (gamename, "Hexen") == 0)
		game = Hexen;
	else if (strcmp (gamename, "Strife") == 0)
		game = Strife;
	else if (strcmp (gamename, "Chex") == 0)
		game = Chex;
	else
		game = Doom;

	if (bMigrating)
	{
		MigrateOldConfig ();
	}
	sublen = countof(section) - 1 - mysnprintf (section, countof(section), "%s.", gamename);
	subsection = section + countof(section) - sublen - 1;
	section[countof(section) - 1] = '\0';
	
	strncpy (subsection, "UnknownConsoleVariables", sublen);
	if (SetSection (section))
	{
		ReadCVars (0);
	}

	strncpy (subsection, "ConsoleVariables", sublen);
	if (SetSection (section))
	{
		ReadCVars (0);
	}

	if (game != Doom && game != Strife && game != Chex)
	{
		SetRavenDefaults (game == Hexen);
	}

	// The NetServerInfo section will be read when it's determined that
	// a netgame is being played.
	strncpy (subsection, "LocalServerInfo", sublen);
	if (SetSection (section))
	{
		ReadCVars (0);
	}

	strncpy (subsection, "Player", sublen);
	if (SetSection (section))
	{
		ReadCVars (0);
	}

	strncpy (subsection, "Bindings", sublen);
	if (!SetSection (section))
	{ // Config has no bindings for the given game
		if (!bMigrating)
		{
			C_SetDefaultBindings ();
		}
	}
	else
	{
		C_UnbindAll ();
		while (NextInSection (key, value))
		{
			C_DoBind (key, value, false);
		}
	}

	strncpy (subsection, "DoubleBindings", sublen);
	if (SetSection (section))
	{
		while (NextInSection (key, value))
		{
			C_DoBind (key, value, true);
		}
	}

	strncpy (subsection, "ConsoleAliases", sublen);
	if (SetSection (section))
	{
		const char *name = NULL;
		while (NextInSection (key, value))
		{
			if (stricmp (key, "Name") == 0)
			{
				name = value;
			}
			else if (stricmp (key, "Command") == 0 && name != NULL)
			{
				C_SetAlias (name, value);
				name = NULL;
			}
		}
	}
}
FGameConfigFile::FGameConfigFile ()
{
#ifdef __APPLE__
	FString user_docs, user_app_support, local_app_support;
#endif
	FString pathname;
	
	bMigrating = false;
	pathname = GetConfigPath (true);
	ChangePathName (pathname);
	LoadConfigFile (MigrateStub, NULL);

	if (!HaveSections ())
	{ // Config file not found; try the old one
		MigrateOldConfig ();
	}

	// If zdoom.ini was read from the program directory, switch
	// to the user directory now. If it was read from the user
	// directory, this effectively does nothing.
	pathname = GetConfigPath (false);
	ChangePathName (pathname);

	// Set default IWAD search paths if none present
	if (!SetSection ("IWADSearch.Directories"))
	{
		SetSection ("IWADSearch.Directories", true);
		SetValueForKey ("Path", ".", true);
		SetValueForKey ("Path", "$DOOMWADDIR", true);
#ifdef __APPLE__
		char cpath[PATH_MAX];
		FSRef folder;
		
		if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) &&
			noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
		{
			user_docs << cpath << "/" GAME_DIR;
			SetValueForKey("Path", user_docs, true);
		}
		else
		{
			SetValueForKey("Path", "~/" GAME_DIR, true);
		}
		if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &folder) &&
			noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
		{
			user_app_support << cpath << "/" GAME_DIR;
			SetValueForKey("Path", user_app_support, true);
		}
		SetValueForKey ("Path", "$PROGDIR", true);
		if (noErr == FSFindFolder(kLocalDomain, kApplicationSupportFolderType, kCreateFolder, &folder) &&
			noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX))
		{
			local_app_support << cpath << "/" GAME_DIR;
			SetValueForKey("Path", local_app_support, true);
		}
#elif !defined(unix)
		SetValueForKey ("Path", "$HOME", true);
		SetValueForKey ("Path", "$PROGDIR", true);
#else
		SetValueForKey ("Path", "~/" GAME_DIR, true);
		SetValueForKey ("Path", SHARE_DIR, true);
#endif
	}

	// Set default search paths if none present
	if (!SetSection ("FileSearch.Directories"))
	{
		SetSection ("FileSearch.Directories", true);
#ifdef __APPLE__
		SetValueForKey ("Path", user_docs, true);
		SetValueForKey ("Path", user_app_support, true);
		SetValueForKey ("Path", "$PROGDIR", true);
		SetValueForKey ("Path", local_app_support, true);
#elif !defined(unix)
		SetValueForKey ("Path", "$PROGDIR", true);
#else
		SetValueForKey ("Path", SHARE_DIR, true);
#endif
		SetValueForKey ("Path", "$DOOMWADDIR", true);
	}

	// Create auto-load sections, so users know what's available.
	// Note that this totem pole is the reverse of the order that
	// they will appear in the file.
	CreateSectionAtStart("Chex3.Autoload");
	CreateSectionAtStart("Chex.Autoload");
	CreateSectionAtStart("Strife.Autoload");
	CreateSectionAtStart("HexenDemo.Autoload");
	CreateSectionAtStart("HexenDK.Autoload");
	CreateSectionAtStart("Hexen.Autoload");
	CreateSectionAtStart("Heretic.Autoload");
	CreateSectionAtStart("FreeDM.Autoload");
	CreateSectionAtStart("Freedoom1.Autoload");
	CreateSectionAtStart("Freedoom.Autoload");
	CreateSectionAtStart("Plutonia.Autoload");
	CreateSectionAtStart("TNT.Autoload");
	CreateSectionAtStart("Doom2.Autoload");
	CreateSectionAtStart("Doom1.Autoload");
	CreateSectionAtStart("Doom.Autoload");
	CreateSectionAtStart("Global.Autoload");

	// The same goes for auto-exec files.
	CreateStandardAutoExec("Chex.AutoExec", true);
	CreateStandardAutoExec("Strife.AutoExec", true);
	CreateStandardAutoExec("Hexen.AutoExec", true);
	CreateStandardAutoExec("Heretic.AutoExec", true);
	CreateStandardAutoExec("Doom.AutoExec", true);

	// Move search paths back to the top.
	MoveSectionToStart("FileSearch.Directories");
	MoveSectionToStart("IWADSearch.Directories");

	// Add some self-documentation.
	SetSectionNote("IWADSearch.Directories",
		"# These are the directories to automatically search for IWADs.\n"
		"# Each directory should be on a separate line, preceded by Path=\n");
	SetSectionNote("FileSearch.Directories",
		"# These are the directories to search for wads added with the -file\n"
		"# command line parameter, if they cannot be found with the path\n"
		"# as-is. Layout is the same as for IWADSearch.Directories\n");
	SetSectionNote("Doom.AutoExec",
		"# Files to automatically execute when running the corresponding game.\n"
		"# Each file should be on its own line, preceded by Path=\n\n");
	SetSectionNote("Global.Autoload",
		"# WAD files to always load. These are loaded after the IWAD but before\n"
		"# any files added with -file. Place each file on its own line, preceded\n"
		"# by Path=\n");
	SetSectionNote("Doom.Autoload",
		"# Wad files to automatically load depending on the game and IWAD you are\n"
		"# playing.  You may have have files that are loaded for all similar IWADs\n"
		"# (the game) and files that are only loaded for particular IWADs. For example,\n"
		"# any files listed under Doom.Autoload will be loaded for any version of Doom,\n"
		"# but files listed under Doom2.Autoload will only load when you are\n"
		"# playing Doom 2.\n\n");
}
void FGameConfigFile::DoGameSetup (const char *gamename)
{
	const char *key;
	const char *value;

	if (bMigrating)
	{
		MigrateOldConfig ();
	}
	sublen = countof(section) - 1 - mysnprintf (section, countof(section), "%s.", gamename);
	subsection = section + countof(section) - sublen - 1;
	section[countof(section) - 1] = '\0';
	
	strncpy (subsection, "UnknownConsoleVariables", sublen);
	if (SetSection (section))
	{
		ReadCVars (0);
	}

	strncpy (subsection, "ConsoleVariables", sublen);
	if (SetSection (section))
	{
		ReadCVars (0);
	}

	if (gameinfo.gametype & GAME_Raven)
	{
		SetRavenDefaults (gameinfo.gametype == GAME_Hexen);
	}

	// The NetServerInfo section will be read when it's determined that
	// a netgame is being played.
	strncpy (subsection, "LocalServerInfo", sublen);
	if (SetSection (section))
	{
		ReadCVars (0);
	}

	strncpy (subsection, "Player", sublen);
	if (SetSection (section))
	{
		ReadCVars (0);
	}

	if (!bMigrating)
	{
		C_SetDefaultBindings ();
	}

	strncpy (subsection, "Bindings", sublen);
	if (SetSection (section))
	{
		Bindings.UnbindAll();
		while (NextInSection (key, value))
		{
			Bindings.DoBind (key, value);
		}
	}

	strncpy (subsection, "DoubleBindings", sublen);
	if (SetSection (section))
	{
		DoubleBindings.UnbindAll();
		while (NextInSection (key, value))
		{
			DoubleBindings.DoBind (key, value);
		}
	}

	strncpy (subsection, "AutomapBindings", sublen);
	if (SetSection (section))
	{
		AutomapBindings.UnbindAll();
		while (NextInSection (key, value))
		{
			AutomapBindings.DoBind (key, value);
		}
	}

	strncpy (subsection, "ConsoleAliases", sublen);
	if (SetSection (section))
	{
		const char *name = NULL;
		while (NextInSection (key, value))
		{
			if (stricmp (key, "Name") == 0)
			{
				name = value;
			}
			else if (stricmp (key, "Command") == 0 && name != NULL)
			{
				C_SetAlias (name, value);
				name = NULL;
			}
		}
	}
	OkayToWrite = true;
}