foxygit / doom Log in
commit a9996b41e954d85fde5ec5188bbf6a7f4df88011
Merge: 7d7b5087 a366f68b
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Sat Feb 12 15:38:08 2011 +0000
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Sat Feb 12 15:38:08 2011 +0000

    Merge from trunk.

    Subversion-branch: /branches/raven-branch
    Subversion-revision: 2258

 ChangeLog                                       |  377 ++++
 NEWS                                            |   30 +-
 NOT-BUGS                                        |   23 +
 codeblocks/config.h                             |    6 +-
 codeblocks/game-res.rc                          |   10 +-
 codeblocks/setup-res.rc                         |    8 +-
 configure.in                                    |    2 +-
 man/chocolate-server.6                          |    6 +
 man/docgen                                      |    4 +-
 msvc/config.h                                   |    6 +-
 msvc/win32.rc                                   |   10 +-
 pkg/Makefile.am                                 |    3 +-
 pkg/osx/LauncherManager.h                       |    1 -
 pkg/osx/LauncherManager.m                       |    1 -
 pkg/osx/Resources/launcher.nib/classes.nib      |   47 -
 pkg/osx/Resources/launcher.nib/designable.nib   | 2679 +++++++++++++++++++++++
 pkg/osx/Resources/launcher.nib/info.nib         |   23 -
 pkg/osx/Resources/launcher.nib/keyedobjects.nib |  Bin 19616 -> 24936 bytes
 rpm.spec.in                                     |    1 +
 src/d_iwad.c                                    |    2 +-
 src/doom/d_main.c                               |  104 +-
 src/doom/d_net.c                                |    6 +-
 src/doom/dstrings.h                             |    9 -
 src/doom/g_game.c                               |   12 +-
 src/doom/m_menu.c                               |    8 +-
 src/doom/p_map.c                                |    2 +-
 src/doom/p_spec.c                               |    4 +-
 src/i_system.c                                  |    2 +-
 src/i_video.c                                   |   24 +-
 src/m_argv.c                                    |   13 +-
 src/m_argv.h                                    |    4 +
 src/m_config.c                                  |   22 +-
 src/net_sdl.c                                   |    4 +-
 src/net_server.c                                |    4 +-
 src/setup/display.c                             |   56 +-
 src/setup/execute.c                             |   55 +-
 src/setup/execute.h                             |    2 +-
 src/setup/mainmenu.c                            |   26 +-
 src/setup/multiplayer.c                         |   30 +-
 src/w_main.c                                    |   12 +-
 textscreen/txt_checkbox.c                       |    8 +-
 textscreen/txt_radiobutton.c                    |    8 +-
 textscreen/txt_sdl.c                            |    4 -
 43 files changed, 3392 insertions(+), 266 deletions(-)

diff --cc src/doom/d_main.c
index 69dd6e9f,73978c2f..2f116f1e
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@@ -1310,42 -1011,159 +1316,34 @@@ void D_DoomMain (void

      DEH_printf("W_Init: Init WADfiles.\n");
      D_AddFile(iwadfile);
 -
 -#ifdef FEATURE_WAD_MERGE
 -
 -    // Merged PWADs are loaded first, because they are supposed to be
 -    // modified IWADs.
 -
 -    //!
 -    // @arg <files>
 -    // @category mod
 -    //
 -    // Simulates the behavior of deutex's -merge option, merging a PWAD
 -    // into the main IWAD.  Multiple files may be specified.
 -    //
 -
 -    p = M_CheckParmWithArgs("-merge", 1);
 -
 -    if (p > 0)
 -    {
 -        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
 -        {
 -            char *filename;
 -
 -            filename = D_TryFindWADByName(myargv[p]);
 -
 -            printf(" merging %s\n", filename);
 -            W_MergeFile(filename);
 -        }
 -    }
 -
 -    // NWT-style merging:
 -
 -    // NWT's -merge option:
 -
 -    //!
 -    // @arg <files>
 -    // @category mod
 -    //
 -    // Simulates the behavior of NWT's -merge option.  Multiple files
 -    // may be specified.
 -
 -    p = M_CheckParmWithArgs("-nwtmerge", 1);
 -
 -    if (p > 0)
 -    {
 -        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
 -        {
 -            char *filename;
 -
 -            filename = D_TryFindWADByName(myargv[p]);
 -
 -            printf(" performing NWT-style merge of %s\n", filename);
 -            W_NWTDashMerge(filename);
 -        }
 -    }
 -
 -    // Add flats
 -
 -    //!
 -    // @arg <files>
 -    // @category mod
 -    //
 -    // Simulates the behavior of NWT's -af option, merging flats into
 -    // the main IWAD directory.  Multiple files may be specified.
 -    //
 -
 -    p = M_CheckParmWithArgs("-af", 1);
 -
 -    if (p > 0)
 -    {
 -        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
 -        {
 -            char *filename;
 -
 -            filename = D_TryFindWADByName(myargv[p]);
 -
 -            printf(" merging flats from %s\n", filename);
 -            W_NWTMergeFile(filename, W_NWT_MERGE_FLATS);
 -        }
 -    }
 -
 -    //!
 -    // @arg <files>
 -    // @category mod
 -    //
 -    // Simulates the behavior of NWT's -as option, merging sprites
 -    // into the main IWAD directory.  Multiple files may be specified.
 -    //
 -
 -    p = M_CheckParmWithArgs("-as", 1);
 -
 -    if (p > 0)
 -    {
 -        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
 -        {
 -            char *filename;
 -
 -            filename = D_TryFindWADByName(myargv[p]);
 -
 -            printf(" merging sprites from %s\n", filename);
 -            W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES);
 -        }
 -    }
 -
 -    //!
 -    // @arg <files>
 -    // @category mod
 -    //
 -    // Equivalent to "-af <files> -as <files>".
 -    //
 -
 -    p = M_CheckParmWithArgs("-aa", 1);
 -
 -    if (p > 0)
 -    {
 -        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
 -        {
 -            char *filename;
 -
 -            filename = D_TryFindWADByName(myargv[p]);
 -
 -            printf(" merging sprites and flats from %s\n", filename);
 -            W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES | W_NWT_MERGE_FLATS);
 -        }
 -    }
 -
 -#endif
 +    modifiedgame = W_ParseCommandLine();

-     // add any files specified on the command line with -file wadfile
-     // to the wad list
+     //!
+     // @arg <files>
+     // @vanilla
      //
-     // convenience hack to allow -wart e m to add a wad file
-     // prepend a tilde to the filename so wadfile will be reloadable
-     p = M_CheckParm ("-wart");
+     // Load the specified PWAD files.
+     //
+
+     p = M_CheckParmWithArgs("-file", 1);
      if (p)
      {
- 	myargv[p][4] = 'p';     // big hack, change to -warp
+ 	// the parms after p are wadfile/lump names,
+ 	// until end of parms or another - preceded parm
+ 	modifiedgame = true;            // homebrew levels
+ 	while (++p != myargc && myargv[p][0] != '-')
+         {
+             char *filename;

- 	// Map name handling.
- 	switch (gamemode )
- 	{
- 	  case shareware:
- 	  case retail:
- 	  case registered:
- 	    sprintf (file,"~"DEVMAPS"E%cM%c.wad",
- 		     myargv[p+1][0], myargv[p+2][0]);
- 	    printf("Warping to Episode %s, Map %s.\n",
- 		   myargv[p+1],myargv[p+2]);
- 	    break;
-
- 	  case commercial:
- 	  default:
- 	    p = atoi (myargv[p+1]);
- 	    if (p<10)
- 	      sprintf (file,"~"DEVMAPS"cdata/map0%i.wad", p);
- 	    else
- 	      sprintf (file,"~"DEVMAPS"cdata/map%i.wad", p);
- 	    break;
- 	}
- 	D_AddFile (file);
+             filename = D_TryFindWADByName(myargv[p]);
+
+ 	    D_AddFile(filename);
+         }
      }

+     // Debug:
+ //    W_PrintDirectory();
+
      //!
      // @arg <demo>
      // @category demo
diff --cc src/doom/d_net.c
index 73e7368f,00000000..dd1ec563
mode 100644,000000..100644
--- a/src/doom/d_net.c
+++ b/src/doom/d_net.c
@@@ -1,933 -1,0 +1,933 @@@
 +// Emacs style mode select   -*- C++ -*-
 +//-----------------------------------------------------------------------------
 +//
 +// Copyright(C) 1993-1996 Id Software, Inc.
 +// Copyright(C) 2005 Simon Howard
 +//
 +// 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 2
 +// 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, write to the Free Software
 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 +// 02111-1307, USA.
 +//
 +// DESCRIPTION:
 +//	DOOM Network game communication and protocol,
 +//	all OS independend parts.
 +//
 +//-----------------------------------------------------------------------------
 +
 +#include <stdlib.h>
 +
 +#include "doomfeatures.h"
 +
 +#include "d_main.h"
 +#include "m_argv.h"
 +#include "m_menu.h"
 +#include "i_system.h"
 +#include "i_timer.h"
 +#include "i_video.h"
 +#include "g_game.h"
 +#include "doomdef.h"
 +#include "doomstat.h"
 +
 +#include "deh_main.h"
 +
 +#include "net_client.h"
 +#include "net_gui.h"
 +#include "net_io.h"
 +#include "net_query.h"
 +#include "net_server.h"
 +#include "net_sdl.h"
 +#include "net_loop.h"
 +
 +// The complete set of data for a particular tic.
 +
 +typedef struct
 +{
 +    ticcmd_t cmds[MAXPLAYERS];
 +    boolean ingame[MAXPLAYERS];
 +} ticcmd_set_t;
 +
 +//
 +// NETWORKING
 +//
 +// gametic is the tic about to (or currently being) run
 +// maketic is the tic that hasn't had control made for it yet
 +// recvtic is the latest tic received from the server.
 +//
 +// a gametic cannot be run until ticcmds are received for it
 +// from all players.
 +//
 +
 +ticcmd_set_t ticdata[BACKUPTICS];
 +ticcmd_t *netcmds;
 +
 +int             maketic;
 +int             recvtic;
 +
 +// Used for original sync code.
 +
 +static int      skiptics = 0;
 +
 +// Reduce the bandwidth needed by sampling game input less and transmitting
 +// less.  If ticdup is 2, sample half normal, 3 = one third normal, etc.
 +
 +int		ticdup;
 +
 +// Send this many extra (backup) tics in each packet.
 +
 +int             extratics;
 +
 +// Amount to offset the timer for game sync.
 +
 +fixed_t         offsetms;
 +
 +// Use new client syncronisation code
 +
 +boolean         new_sync = true;
 +
 +// 35 fps clock adjusted by offsetms milliseconds
 +
 +static int GetAdjustedTime(void)
 +{
 +    int time_ms;
 +
 +    time_ms = I_GetTimeMS();
 +
 +    if (new_sync)
 +    {
 +	// Use the adjustments from net_client.c only if we are
 +	// using the new sync mode.
 +
 +        time_ms += (offsetms / FRACUNIT);
 +    }
 +
 +    return (time_ms * TICRATE) / 1000;
 +}
 +
 +//
 +// NetUpdate
 +// Builds ticcmds for console player,
 +// sends out a packet
 +//
 +int      lasttime;
 +
 +void NetUpdate (void)
 +{
 +    int nowtime;
 +    int newtics;
 +    int	i;
 +    int	gameticdiv;
 +
 +    // If we are running with singletics (timing a demo), this
 +    // is all done separately.
 +
 +    if (singletics)
 +        return;
 +
 +#ifdef FEATURE_MULTIPLAYER
 +
 +    // Run network subsystems
 +
 +    NET_CL_Run();
 +    NET_SV_Run();
 +
 +#endif
 +
 +    // check time
 +    nowtime = GetAdjustedTime() / ticdup;
 +    newtics = nowtime - lasttime;
 +
 +    lasttime = nowtime;
 +
 +    if (skiptics <= newtics)
 +    {
 +        newtics -= skiptics;
 +        skiptics = 0;
 +    }
 +    else
 +    {
 +        skiptics -= newtics;
 +        newtics = 0;
 +    }
 +
 +    // build new ticcmds for console player
 +    gameticdiv = gametic/ticdup;
 +
 +    for (i=0 ; i<newtics ; i++)
 +    {
 +        ticcmd_t cmd;
 +
 +	I_StartTic ();
 +	D_ProcessEvents ();
 +
 +        // Always run the menu
 +
 +        M_Ticker ();
 +
 +        if (drone)
 +        {
 +            // In drone mode, do not generate any ticcmds.
 +
 +            continue;
 +        }
 +
 +        if (new_sync)
 +        {
 +           // If playing single player, do not allow tics to buffer
 +           // up very far
 +
 +           if ((!netgame || demoplayback) && maketic - gameticdiv > 2)
 +               break;
 +
 +           // Never go more than ~200ms ahead
 +
 +           if (maketic - gameticdiv > 8)
 +               break;
 +        }
 +	else
 +	{
 +           if (maketic - gameticdiv >= 5)
 +               break;
 +	}
 +
 +	//printf ("mk:%i ",maketic);
 +	G_BuildTiccmd(&cmd);
 +
 +#ifdef FEATURE_MULTIPLAYER
 +
 +        if (net_client_connected)
 +        {
 +            NET_CL_SendTiccmd(&cmd, maketic);
 +        }
 +
 +#endif
 +        ticdata[maketic % BACKUPTICS].cmds[consoleplayer] = cmd;
 +        ticdata[maketic % BACKUPTICS].ingame[consoleplayer] = true;
 +
 +	++maketic;
 +    }
 +}
 +
 +// Called when a player leaves the game
 +
 +static void D_PlayerQuitGame(player_t *player)
 +{
 +    static char exitmsg[80];
 +    unsigned int player_num;
 +
 +    player_num = player - players;
 +
 +    // Do this the same way as Vanilla Doom does, to allow dehacked
 +    // replacements of this message
 +
 +    strncpy(exitmsg, DEH_String("Player 1 left the game"), sizeof(exitmsg));
 +    exitmsg[sizeof(exitmsg) - 1] = '\0';
 +
 +    exitmsg[7] += player_num;
 +
 +    playeringame[player_num] = false;
 +    players[consoleplayer].message = exitmsg;
 +
 +    // TODO: check if it is sensible to do this:
 +
 +    if (demorecording)
 +    {
 +        G_CheckDemoStatus ();
 +    }
 +}
 +
 +static void D_Disconnected(void)
 +{
 +    // In drone mode, the game cannot continue once disconnected.
 +
 +    if (drone)
 +    {
 +        I_Error("Disconnected from server in drone mode.");
 +    }
 +
 +    // disconnected from server
 +
 +    printf("Disconnected from server.\n");
 +}
 +
 +//
 +// Invoked by the network engine when a complete set of ticcmds is
 +// available.
 +//
 +
 +void D_ReceiveTic(ticcmd_t *ticcmds, boolean *players_mask)
 +{
 +    int i;
 +
 +    // Disconnected from server?
 +
 +    if (ticcmds == NULL && players_mask == NULL)
 +    {
 +        D_Disconnected();
 +        return;
 +    }
 +
 +    for (i = 0; i < MAXPLAYERS; ++i)
 +    {
 +        if (!drone && i == consoleplayer)
 +        {
 +            // This is us.  Don't overwrite it.
 +        }
 +        else
 +        {
 +            ticdata[recvtic % BACKUPTICS].cmds[i] = ticcmds[i];
 +            ticdata[recvtic % BACKUPTICS].ingame[i] = players_mask[i];
 +        }
 +    }
 +
 +    ++recvtic;
 +}
 +
 +//
 +// Start game loop
 +//
 +// Called after the screen is set but before the game starts running.
 +//
 +
 +void D_StartGameLoop(void)
 +{
 +    lasttime = GetAdjustedTime() / ticdup;
 +}
 +
 +// Load game settings from the specified structure and
 +// set global variables.
 +
 +static void LoadGameSettings(net_gamesettings_t *settings)
 +{
 +    unsigned int i;
 +
 +    deathmatch = settings->deathmatch;
 +    ticdup = settings->ticdup;
 +    extratics = settings->extratics;
 +    startepisode = settings->episode;
 +    startmap = settings->map;
 +    startskill = settings->skill;
 +    startloadgame = settings->loadgame;
 +    lowres_turn = settings->lowres_turn;
 +    nomonsters = settings->nomonsters;
 +    fastparm = settings->fast_monsters;
 +    respawnparm = settings->respawn_monsters;
 +    timelimit = settings->timelimit;
 +
 +    if (lowres_turn)
 +    {
 +        printf("NOTE: Turning resolution is reduced; this is probably "
 +               "because there is a client recording a Vanilla demo.\n");
 +    }
 +
 +    new_sync = settings->new_sync;
 +
 +    if (new_sync == false)
 +    {
 +	printf("Syncing netgames like Vanilla Doom.\n");
 +    }
 +
 +    if (!drone)
 +    {
 +        consoleplayer = settings->consoleplayer;
 +    }
 +    else
 +    {
 +        consoleplayer = 0;
 +    }
 +
 +    for (i=0; i<MAXPLAYERS; ++i)
 +    {
 +        playeringame[i] = i < settings->num_players;
 +    }
 +}
 +
 +// Save the game settings from global variables to the specified
 +// game settings structure.
 +
 +static void SaveGameSettings(net_gamesettings_t *settings,
 +                             net_connect_data_t *connect_data)
 +{
 +    int i;
 +
 +    // Fill in game settings structure with appropriate parameters
 +    // for the new game
 +
 +    settings->deathmatch = deathmatch;
 +    settings->episode = startepisode;
 +    settings->map = startmap;
 +    settings->skill = startskill;
 +    settings->loadgame = startloadgame;
 +    settings->gameversion = gameversion;
 +    settings->nomonsters = nomonsters;
 +    settings->fast_monsters = fastparm;
 +    settings->respawn_monsters = respawnparm;
 +    settings->timelimit = timelimit;
 +
 +    settings->lowres_turn = M_CheckParm("-record") > 0
 +                         && M_CheckParm("-longtics") == 0;
 +
 +    //!
 +    // @category net
 +    //
 +    // Use original game sync code.
 +    //
 +
 +    if (M_CheckParm("-oldsync") > 0)
 +	settings->new_sync = 0;
 +    else
 +	settings->new_sync = 1;
 +
 +    //!
 +    // @category net
 +    // @arg <n>
 +    //
 +    // Send n extra tics in every packet as insurance against dropped
 +    // packets.
 +    //
 +
-     i = M_CheckParm("-extratics");
++    i = M_CheckParmWithArgs("-extratics", 1);
 +
 +    if (i > 0)
 +        settings->extratics = atoi(myargv[i+1]);
 +    else
 +        settings->extratics = 1;
 +
 +    //!
 +    // @category net
 +    // @arg <n>
 +    //
 +    // Reduce the resolution of the game by a factor of n, reducing
 +    // the amount of network bandwidth needed.
 +    //
 +
-     i = M_CheckParm("-dup");
++    i = M_CheckParmWithArgs("-dup", 1);
 +
 +    if (i > 0)
 +        settings->ticdup = atoi(myargv[i+1]);
 +    else
 +        settings->ticdup = 1;
 +
 +    //
 +    // Connect data
 +    //
 +
 +    // Game type fields:
 +
 +    connect_data->gamemode = gamemode;
 +    connect_data->gamemission = gamemission;
 +
 +    // Drone mode?
 +
 +    connect_data->drone = M_CheckParm("-drone") > 0;
 +
 +    // Are we recording a demo? Possibly set lowres turn mode
 +
 +    connect_data->lowres_turn = settings->lowres_turn;
 +}
 +
 +void D_InitSinglePlayerGame(net_gamesettings_t *settings)
 +{
 +    // default values for single player
 +
 +    settings->consoleplayer = 0;
 +    settings->num_players = 1;
 +
 +    netgame = false;
 +
 +    //!
 +    // @category net
 +    //
 +    // Start the game playing as though in a netgame with a single
 +    // player.  This can also be used to play back single player netgame
 +    // demos.
 +    //
 +
 +    if (M_CheckParm("-solo-net") > 0)
 +    {
 +        netgame = true;
 +    }
 +}
 +
 +boolean D_InitNetGame(net_connect_data_t *connect_data,
 +                      net_gamesettings_t *settings)
 +{
 +    net_addr_t *addr = NULL;
 +    int i;
 +
 +
 +#ifdef FEATURE_MULTIPLAYER
 +
 +    //!
 +    // @category net
 +    //
 +    // Start a multiplayer server, listening for connections.
 +    //
 +
 +    if (M_CheckParm("-server") > 0)
 +    {
 +        NET_SV_Init();
 +        NET_SV_AddModule(&net_loop_server_module);
 +        NET_SV_AddModule(&net_sdl_module);
 +        NET_SV_RegisterWithMaster();
 +
 +        net_loop_client_module.InitClient();
 +        addr = net_loop_client_module.ResolveAddress(NULL);
 +    }
 +    else
 +    {
 +        //!
 +        // @category net
 +        //
 +        // Automatically search the local LAN for a multiplayer
 +        // server and join it.
 +        //
 +
 +        i = M_CheckParm("-autojoin");
 +
 +        if (i > 0)
 +        {
 +            addr = NET_FindLANServer();
 +
 +            if (addr == NULL)
 +            {
 +                I_Error("No server found on local LAN");
 +            }
 +        }
 +
 +        //!
 +        // @arg <address>
 +        // @category net
 +        //
 +        // Connect to a multiplayer server running on the given
 +        // address.
 +        //
 +
-         i = M_CheckParm("-connect");
++        i = M_CheckParmWithArgs("-connect", 1);
 +
 +        if (i > 0)
 +        {
 +            net_sdl_module.InitClient();
 +            addr = net_sdl_module.ResolveAddress(myargv[i+1]);
 +
 +            if (addr == NULL)
 +            {
 +                I_Error("Unable to resolve '%s'\n", myargv[i+1]);
 +            }
 +        }
 +    }
 +
 +    if (addr != NULL)
 +    {
 +        if (M_CheckParm("-drone") > 0)
 +        {
 +            connect_data->drone = true;
 +        }
 +
 +        //!
 +        // @category net
 +        //
 +        // Run as the left screen in three screen mode.
 +        //
 +
 +        if (M_CheckParm("-left") > 0)
 +        {
 +            viewangleoffset = ANG90;
 +            connect_data->drone = true;
 +        }
 +
 +        //!
 +        // @category net
 +        //
 +        // Run as the right screen in three screen mode.
 +        //
 +
 +        if (M_CheckParm("-right") > 0)
 +        {
 +            viewangleoffset = ANG270;
 +            connect_data->drone = true;
 +        }
 +
 +        if (!NET_CL_Connect(addr, connect_data))
 +        {
 +            I_Error("D_CheckNetGame: Failed to connect to %s\n",
 +                    NET_AddrToString(addr));
 +        }
 +
 +        printf("D_CheckNetGame: Connected to %s\n", NET_AddrToString(addr));
 +
 +        // Wait for game start message received from server.
 +
 +        NET_WaitForStart(settings);
 +
 +        // Read the game settings that were received.
 +
 +        NET_CL_GetSettings(settings);
 +
 +        return true;
 +    }
 +
 +#endif
 +
 +    return false;
 +}
 +
 +//
 +// D_CheckNetGame
 +// Works out player numbers among the net participants
 +//
 +extern	int			viewangleoffset;
 +
 +void D_CheckNetGame (void)
 +{
 +    net_connect_data_t connect_data;
 +    net_gamesettings_t settings;
 +
 +    offsetms = 0;
 +    recvtic = 0;
 +
 +    // Call D_QuitNetGame on exit
 +
 +    I_AtExit(D_QuitNetGame, true);
 +
 +    SaveGameSettings(&settings, &connect_data);
 +
 +    if (D_InitNetGame(&connect_data, &settings))
 +    {
 +        netgame = true;
 +        autostart = true;
 +    }
 +    else
 +    {
 +        D_InitSinglePlayerGame(&settings);
 +    }
 +
 +    LoadGameSettings(&settings);
 +
 +    DEH_printf("startskill %i  deathmatch: %i  startmap: %i  startepisode: %i\n",
 +               startskill, deathmatch, startmap, startepisode);
 +
 +    DEH_printf("player %i of %i (%i nodes)\n",
 +               consoleplayer+1, settings.num_players, settings.num_players);
 +
 +    // Show players here; the server might have specified a time limit
 +
 +    if (timelimit > 0 && deathmatch)
 +    {
 +        // Gross hack to work like Vanilla:
 +
 +        if (timelimit == 20 && M_CheckParm("-avg"))
 +        {
 +            DEH_printf("Austin Virtual Gaming: Levels will end "
 +                           "after 20 minutes\n");
 +        }
 +        else
 +        {
 +            DEH_printf("Levels will end after %d minute", timelimit);
 +            if (timelimit > 1)
 +                printf("s");
 +            printf(".\n");
 +        }
 +    }
 +}
 +
 +
 +//
 +// D_QuitNetGame
 +// Called before quitting to leave a net game
 +// without hanging the other players
 +//
 +void D_QuitNetGame (void)
 +{
 +#ifdef FEATURE_MULTIPLAYER
 +
 +    NET_SV_Shutdown();
 +    NET_CL_Disconnect();
 +
 +#endif
 +
 +}
 +
 +static int GetLowTic(void)
 +{
 +    int lowtic;
 +
 +    lowtic = maketic;
 +
 +#ifdef FEATURE_MULTIPLAYER
 +    if (net_client_connected)
 +    {
 +        if (drone || recvtic < lowtic)
 +        {
 +            lowtic = recvtic;
 +        }
 +    }
 +#endif
 +
 +    return lowtic;
 +}
 +
 +int	frametics[4];
 +int	frameon;
 +int	frameskip[4];
 +int	oldnettics;
 +
 +static void OldNetSync(void)
 +{
 +    unsigned int i;
 +    unsigned int keyplayer = -1;
 +
 +    frameon++;
 +
 +    // ideally maketic should be 1 - 3 tics above lowtic
 +    // if we are consistantly slower, speed up time
 +
 +    for (i=0 ; i<MAXPLAYERS ; i++)
 +    {
 +        // TODO: playeringame should not be used here.
 +
 +        if (playeringame[i])
 +        {
 +            keyplayer = i;
 +            break;
 +        }
 +    }
 +
 +    if (keyplayer < 0)
 +    {
 +        // If there are no players, we can never advance anyway
 +
 +        return;
 +    }
 +
 +    if (consoleplayer == keyplayer)
 +    {
 +        // the key player does not adapt
 +    }
 +    else
 +    {
 +        if (maketic <= recvtic)
 +        {
 +            lasttime--;
 +            // printf ("-");
 +        }
 +
 +        frameskip[frameon & 3] = oldnettics > recvtic;
 +        oldnettics = maketic;
 +
 +        if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
 +        {
 +            skiptics = 1;
 +            // printf ("+");
 +        }
 +    }
 +}
 +
 +// Returns true if there are players in the game:
 +
 +static boolean PlayersInGame(void)
 +{
 +    boolean result = false;
 +    unsigned int i;
 +
 +    // If we are connected to a server, check if there are any players
 +    // in the game.
 +
 +    if (net_client_connected)
 +    {
 +        for (i = 0; i < MAXPLAYERS; ++i)
 +        {
 +            result = result || playeringame[i];
 +        }
 +    }
 +
 +    // Whether single or multi-player, unless we are running as a drone,
 +    // we are in the game.
 +
 +    if (!drone)
 +    {
 +        result = true;
 +    }
 +
 +    return result;
 +}
 +
 +// When using ticdup, certain values must be cleared out when running
 +// the duplicate ticcmds.
 +
 +static void TicdupSquash(ticcmd_set_t *set)
 +{
 +    ticcmd_t *cmd;
 +    unsigned int i;
 +
 +    for (i = 0; i < MAXPLAYERS ; ++i)
 +    {
 +        cmd = &set->cmds[i];
 +        cmd->chatchar = 0;
 +        if (cmd->buttons & BT_SPECIAL)
 +            cmd->buttons = 0;
 +    }
 +}
 +
 +static void D_RunTic(ticcmd_set_t *set)
 +{
 +    extern boolean advancedemo;
 +    unsigned int i;
 +
 +    // Check for player quits.
 +
 +    for (i = 0; i < MAXPLAYERS; ++i)
 +    {
 +        if (playeringame[i] && !set->ingame[i])
 +        {
 +            D_PlayerQuitGame(&players[i]);
 +        }
 +    }
 +
 +    netcmds = set->cmds;
 +
 +    // check that there are players in the game.  if not, we cannot
 +    // run a tic.
 +
 +    if (advancedemo)
 +        D_DoAdvanceDemo ();
 +
 +    G_Ticker ();
 +}
 +
 +// When running in single player mode, clear all the ingame[] array
 +// except the consoleplayer.
 +
 +static void SinglePlayerClear(ticcmd_set_t *set)
 +{
 +    unsigned int i;
 +
 +    for (i = 0; i < MAXPLAYERS; ++i)
 +    {
 +        if (i != consoleplayer)
 +        {
 +            set->ingame[i] = false;
 +        }
 +    }
 +}
 +
 +//
 +// TryRunTics
 +//
 +
 +void TryRunTics (void)
 +{
 +    int	i;
 +    int	lowtic;
 +    int	entertic;
 +    static int oldentertics;
 +    int realtics;
 +    int	availabletics;
 +    int	counts;
 +
 +    // get real tics
 +    entertic = I_GetTime() / ticdup;
 +    realtics = entertic - oldentertics;
 +    oldentertics = entertic;
 +
 +    // get available tics
 +    NetUpdate ();
 +
 +    lowtic = GetLowTic();
 +
 +    availabletics = lowtic - gametic/ticdup;
 +
 +    // decide how many tics to run
 +
 +    if (new_sync)
 +    {
 +	counts = availabletics;
 +    }
 +    else
 +    {
 +        // decide how many tics to run
 +        if (realtics < availabletics-1)
 +            counts = realtics+1;
 +        else if (realtics < availabletics)
 +            counts = realtics;
 +        else
 +            counts = availabletics;
 +
 +        if (counts < 1)
 +            counts = 1;
 +
 +        if (net_client_connected)
 +        {
 +            OldNetSync();
 +        }
 +    }
 +
 +    if (counts < 1)
 +	counts = 1;
 +
 +    // wait for new tics if needed
 +
 +    while (!PlayersInGame() || lowtic < gametic/ticdup + counts)
 +    {
 +	NetUpdate ();
 +
 +        lowtic = GetLowTic();
 +
 +	if (lowtic < gametic/ticdup)
 +	    I_Error ("TryRunTics: lowtic < gametic");
 +
 +        // Don't stay in this loop forever.  The menu is still running,
 +        // so return to update the screen
 +
 +	if (I_GetTime() / ticdup - entertic > 0)
 +	{
 +	    return;
 +	}
 +
 +        I_Sleep(1);
 +    }
 +
 +    // run the count * ticdup dics
 +    while (counts--)
 +    {
 +        ticcmd_set_t *set;
 +
 +        if (!PlayersInGame())
 +        {
 +            return;
 +        }
 +
 +        set = &ticdata[(gametic / ticdup) % BACKUPTICS];
 +
 +        if (!net_client_connected)
 +        {
 +            SinglePlayerClear(set);
 +        }
 +
 +	for (i=0 ; i<ticdup ; i++)
 +	{
 +            if (gametic/ticdup > lowtic)
 +                I_Error ("gametic>lowtic");
 +
 +            D_RunTic(set);
 +	    gametic++;
 +
 +	    // modify command for duplicated tics
 +
 +            TicdupSquash(set);
 +	}
 +
 +	NetUpdate ();	// check for new console commands
 +    }
 +}
 +
diff --cc src/m_argv.c
index 875829bd,4d321bbc..59381b65
--- a/src/m_argv.c
+++ b/src/m_argv.c
@@@ -60,20 -60,13 +60,25 @@@ int M_CheckParmWithArgs(char *check, in
      return 0;
  }

 +//
 +// M_ParmExists
 +//
 +// Returns true if the given parameter exists in the program's command
 +// line arguments, false if not.
 +//
 +
 +boolean M_ParmExists(char *check)
 +{
 +    return M_CheckParm(check) != 0;
 +}
 +
+ int M_CheckParm(char *check)
+ {
+     return M_CheckParmWithArgs(check, 0);
+ }
+
  #define MAXARGVS        100
 -
 +
  static void LoadResponseFile(int argv_index)
  {
      FILE *handle;
diff --cc src/m_argv.h
index 859f93e4,f5b26f94..2fb76a2a
--- a/src/m_argv.h
+++ b/src/m_argv.h
@@@ -40,14 -38,10 +40,18 @@@ extern  char**	myargv
  // in the arg list (0 if not found).
  int M_CheckParm (char* check);

+ // Same as M_CheckParm, but checks that num_args arguments are available
+ // following the specified argument.
+ int M_CheckParmWithArgs(char *check, int num_args);
+
  void M_FindResponseFile(void);

 +// Parameter has been specified?
 +
 +boolean M_ParmExists(char *check);
 +
 +// Get name of executable used to run this program:
 +
 +char *M_GetExecutableName(void);
 +
  #endif
diff --cc src/m_config.c
index cb7d449c,04d0a963..a0f97dc2
--- a/src/m_config.c
+++ b/src/m_config.c
@@@ -1419,13 -1415,13 +1429,13 @@@ void M_LoadDefaults (void
      // @arg <file>
      // @vanilla
      //
 -    // Load configuration from the specified file, instead of
 -    // default.cfg.
 +    // Load configuration from the specified file.  The default
 +    // configuration file (for Doom) is named default.cfg.
      //

-     i = M_CheckParm ("-config");
+     i = M_CheckParmWithArgs("-config", 1);

-     if (i && i<myargc-1)
+     if (i)
      {
  	doom_defaults.filename = myargv[i+1];
  	printf ("	default file: %s\n",doom_defaults.filename);
@@@ -1442,13 -1437,13 +1452,13 @@@
      //!
      // @arg <file>
      //
 -    // Load extra configuration from the specified file, instead
 -    // of chocolate-doom.cfg.
 +    // Load extra configuration from the specified file.  The default
 +    // configuration file for Doom is named chocolate-doom.cfg.
      //

-     i = M_CheckParm("-extraconfig");
+     i = M_CheckParmWithArgs("-extraconfig", 1);

-     if (i && i<myargc-1)
+     if (i)
      {
          extra_defaults.filename = myargv[i+1];
          printf("        extra configuration file: %s\n",
diff --cc src/setup/mainmenu.c
index ffa174de,a3dfafed..55496010
--- a/src/setup/mainmenu.c
+++ b/src/setup/mainmenu.c
@@@ -313,6 -270,25 +311,24 @@@ static void InitTextscreen(void

      TXT_SetDesktopTitle(PACKAGE_NAME " Setup ver " PACKAGE_VERSION);
      SetIcon();
+ }
+
+ // Restart the textscreen library.  Used when the video_driver variable
+ // is changed.
+
+ void RestartTextscreen(void)
+ {
+     TXT_Shutdown();
+     InitTextscreen();
+ }
+
+ //
+ // Initialize and run the textscreen GUI.
+ //
+
+ static void RunGUI(void)
+ {
+     InitTextscreen();
 -    MainMenu();

      TXT_GUIMainLoop();
  }
diff --cc src/setup/multiplayer.c
index 0d88221f,eece16d4..aed89212
--- a/src/setup/multiplayer.c
+++ b/src/setup/multiplayer.c
@@@ -68,12 -76,12 +68,12 @@@ static int found_iwad_selected

  static char *iwadfile;

 -static char *skills[] =
 +static char *doom_skills[] =
  {
-     "I'm too young to die!",
+     "I'm too young to die.",
      "Hey, not too rough.",
      "Hurt me plenty.",
-     "Ultra-violence",
+     "Ultra-Violence.",
      "NIGHTMARE!",
  };

@@@ -654,17 -622,8 +658,17 @@@ static void StartGameMenu(char *window_
      TXT_SetWindowAction(window, TXT_HORIZ_CENTER, WadWindowAction());
      TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, StartGameAction(multiplayer));

-     TXT_SetColumnWidths(gameopt_table, 12, 12);
+     TXT_SetColumnWidths(gameopt_table, 12, 6);

 +    if (gamemission == doom)
 +    {
 +        num_mult_types = 3;
 +    }
 +    else
 +    {
 +        num_mult_types = 2;
 +    }
 +
      TXT_AddWidgets(gameopt_table,
             TXT_NewLabel("Game"),
             iwad_selector = IWADSelector(),
diff --cc src/w_main.c
index 92a394dd,00000000..ed285498
mode 100644,000000..100644
--- a/src/w_main.c
+++ b/src/w_main.c
@@@ -1,206 -1,0 +1,206 @@@
 +// Emacs style mode select   -*- C++ -*-
 +//-----------------------------------------------------------------------------
 +//
 +// Copyright(C) 1993-1996 Id Software, Inc.
 +// Copyright(C) 2005-2010 Simon Howard
 +//
 +// 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 2
 +// 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, write to the Free Software
 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 +// 02111-1307, USA.
 +//
 +// DESCRIPTION:
 +//     Common code to parse command line, identifying WAD files to load.
 +//
 +//-----------------------------------------------------------------------------
 +
 +#include "doomfeatures.h"
 +#include "d_iwad.h"
 +#include "m_argv.h"
 +#include "w_main.h"
 +#include "w_merge.h"
 +#include "w_wad.h"
 +#include "z_zone.h"
 +
 +// Parse the command line, merging WAD files that are sppecified.
 +// Returns true if at least one file was added.
 +
 +boolean W_ParseCommandLine(void)
 +{
 +    boolean modifiedgame = false;
 +    int p;
 +
 +#ifdef FEATURE_WAD_MERGE
 +
 +    // Merged PWADs are loaded first, because they are supposed to be
 +    // modified IWADs.
 +
 +    //!
 +    // @arg <files>
 +    // @category mod
 +    //
 +    // Simulates the behavior of deutex's -merge option, merging a PWAD
 +    // into the main IWAD.  Multiple files may be specified.
 +    //
 +
-     p = M_CheckParm("-merge");
++    p = M_CheckParmWithArgs("-merge", 1);
 +
 +    if (p > 0)
 +    {
 +        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
 +        {
 +            char *filename;
 +
 +            modifiedgame = true;
 +
 +            filename = D_TryFindWADByName(myargv[p]);
 +
 +            printf(" merging %s\n", filename);
 +            W_MergeFile(filename);
 +        }
 +    }
 +
 +    // NWT-style merging:
 +
 +    // NWT's -merge option:
 +
 +    //!
 +    // @arg <files>
 +    // @category mod
 +    //
 +    // Simulates the behavior of NWT's -merge option.  Multiple files
 +    // may be specified.
 +
-     p = M_CheckParm("-nwtmerge");
++    p = M_CheckParmWithArgs("-nwtmerge", 1);
 +
 +    if (p > 0)
 +    {
 +        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
 +        {
 +            char *filename;
 +
 +            modifiedgame = true;
 +
 +            filename = D_TryFindWADByName(myargv[p]);
 +
 +            printf(" performing NWT-style merge of %s\n", filename);
 +            W_NWTDashMerge(filename);
 +        }
 +    }
 +
 +    // Add flats
 +
 +    //!
 +    // @arg <files>
 +    // @category mod
 +    //
 +    // Simulates the behavior of NWT's -af option, merging flats into
 +    // the main IWAD directory.  Multiple files may be specified.
 +    //
 +
-     p = M_CheckParm("-af");
++    p = M_CheckParmWithArgs("-af", 1);
 +
 +    if (p > 0)
 +    {
 +        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
 +        {
 +            char *filename;
 +
 +            modifiedgame = true;
 +
 +            filename = D_TryFindWADByName(myargv[p]);
 +
 +            printf(" merging flats from %s\n", filename);
 +            W_NWTMergeFile(filename, W_NWT_MERGE_FLATS);
 +        }
 +    }
 +
 +    //!
 +    // @arg <files>
 +    // @category mod
 +    //
 +    // Simulates the behavior of NWT's -as option, merging sprites
 +    // into the main IWAD directory.  Multiple files may be specified.
 +    //
 +
-     p = M_CheckParm("-as");
++    p = M_CheckParmWithArgs("-as", 1);
 +
 +    if (p > 0)
 +    {
 +        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
 +        {
 +            char *filename;
 +
 +            modifiedgame = true;
 +            filename = D_TryFindWADByName(myargv[p]);
 +
 +            printf(" merging sprites from %s\n", filename);
 +            W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES);
 +        }
 +    }
 +
 +    //!
 +    // @arg <files>
 +    // @category mod
 +    //
 +    // Equivalent to "-af <files> -as <files>".
 +    //
 +
-     p = M_CheckParm("-aa");
++    p = M_CheckParmWithArgs("-aa", 1);
 +
 +    if (p > 0)
 +    {
 +        for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
 +        {
 +            char *filename;
 +
 +            modifiedgame = true;
 +
 +            filename = D_TryFindWADByName(myargv[p]);
 +
 +            printf(" merging sprites and flats from %s\n", filename);
 +            W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES | W_NWT_MERGE_FLATS);
 +        }
 +    }
 +
 +#endif
 +
 +    //!
 +    // @arg <files>
 +    // @vanilla
 +    //
 +    // Load the specified PWAD files.
 +    //
 +
-     p = M_CheckParm ("-file");
++    p = M_CheckParmWithArgs ("-file", 1);
 +    if (p)
 +    {
 +	// the parms after p are wadfile/lump names,
 +	// until end of parms or another - preceded parm
 +	modifiedgame = true;            // homebrew levels
 +	while (++p != myargc && myargv[p][0] != '-')
 +        {
 +            char *filename;
 +
 +            filename = D_TryFindWADByName(myargv[p]);
 +
 +            printf(" adding %s\n", filename);
 +	    W_AddFile(filename);
 +        }
 +    }
 +
 +//    W_PrintDirectory();
 +
 +    return modifiedgame;
 +}
 +