foxygit / doom Log in
commit 391e7466b1efb7cbede4a1c356a210d9e7ee616b
Merge: fa328faf 822664b4
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Mon Jun 13 22:21:37 2011 +0000
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Mon Jun 13 22:21:37 2011 +0000

    Merge from trunk.

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

 BUGS                                            |  13 --
 ChangeLog                                       | 255 ++++++++++++++++++++
 HACKING                                         |   2 +
 INSTALL                                         | 173 --------------
 Makefile.am                                     |  31 ++-
 NEWS                                            |  70 +++++-
 NOT-BUGS                                        |  40 ++--
 README                                          |  11 +-
 README.OPL                                      |   2 +
 TODO                                            |   2 +
 autogen.sh                                      |  16 +-
 codeblocks/config.h                             |   9 +-
 codeblocks/game-res.rc                          |  10 +-
 codeblocks/setup-res.rc                         |   8 +-
 configure.in                                    |   7 +-
 data/.gitignore                                 |   4 +
 data/Makefile.am                                |  21 ++
 man/INSTALL.template                            | 253 ++++++++++++++++++++
 man/Makefile.am                                 |  11 +-
 man/simplecpp                                   | 211 +++++++++++++++++
 msvc/config.h                                   |   9 +-
 msvc/win32.rc                                   |  10 +-
 opl/opl_win32.c                                 |  31 ++-
 pkg/Makefile.am                                 |   3 +
 pkg/config.make.in                              |   2 -
 pkg/osx/AppController.m                         |   8 +
 pkg/osx/Execute.h                               |   1 +
 pkg/osx/Execute.m                               |  23 ++
 pkg/osx/GNUmakefile                             |  34 ++-
 pkg/osx/IWADController.h                        |   1 +
 pkg/osx/IWADController.m                        |  39 ++++
 pkg/osx/LauncherManager.h                       |   7 +
 pkg/osx/LauncherManager.m                       |  30 +++
 pkg/osx/Resources/launcher.nib/designable.nib   | 296 ++++++++++++++++++++++--
 pkg/osx/Resources/launcher.nib/keyedobjects.nib | Bin 24936 -> 27157 bytes
 pkg/osx/disk/background.png                     | Bin 0 -> 42578 bytes
 pkg/osx/disk/dir.DS_Store                       | Bin 0 -> 8196 bytes
 pkg/osx/dmgfix                                  |  64 +++++
 pkg/win32/GNUmakefile                           |   4 +
 rpm.spec.in                                     |  12 +-
 src/Makefile.am                                 |  12 +
 src/d_mode.h                                    |   1 +
 src/deh_io.c                                    |   2 +-
 src/doom-screensaver.desktop.in                 |   8 +-
 src/doom.desktop.in                             |   7 +
 src/doom/d_main.c                               |  40 +++-
 src/doom/d_net.c                                |   3 +-
 src/doom/doom.desktop.in                        |   7 +
 src/doom/doomstat.c                             |   2 +-
 src/doom/g_game.c                               |   7 +
 src/doom/m_menu.c                               |   1 +
 src/doom/p_map.c                                |  59 ++---
 src/doom/p_setup.c                              |  27 ++-
 src/doom/st_stuff.c                             |   9 +-
 src/i_endoom.c                                  |   2 +-
 src/i_oplmusic.c                                |   9 +-
 src/i_scale.c                                   |  16 ++
 src/i_system.c                                  | 148 +++++++++++-
 src/i_system.h                                  |   2 +
 src/i_video.c                                   |   2 +-
 src/m_misc.c                                    |  25 +-
 src/net_server.c                                |   1 +
 src/setup/Makefile.am                           |   6 +
 src/setup/display.c                             | 221 ++++++++++++------
 src/setup/joystick.c                            |   3 +
 src/setup/setup-manifest.xml.in                 |  25 +-
 src/setup/setup.desktop.in                      |   7 +
 src/setup/sound.c                               |   2 +-
 src/setup/txt_joybinput.c                       |  21 +-
 src/setup/txt_joybinput.h                       |   1 +
 src/setup/txt_keyinput.c                        |  21 +-
 src/setup/txt_keyinput.h                        |   1 +
 src/setup/txt_mouseinput.c                      |  20 +-
 src/setup/txt_mouseinput.h                      |   1 +
 textscreen/txt_button.c                         |   8 +-
 textscreen/txt_checkbox.c                       |   8 +-
 textscreen/txt_desktop.c                        |  10 +
 textscreen/txt_desktop.h                        |   9 +
 textscreen/txt_dropdown.c                       |  27 ++-
 textscreen/txt_gui.c                            |   4 +-
 textscreen/txt_gui.h                            |   4 +
 textscreen/txt_inputbox.c                       |   8 +-
 textscreen/txt_label.c                          |   2 +-
 textscreen/txt_main.h                           |  24 +-
 textscreen/txt_radiobutton.c                    |   8 +-
 textscreen/txt_scrollpane.c                     |  40 +++-
 textscreen/txt_sdl.c                            |  86 ++++++-
 textscreen/txt_separator.c                      |  26 ++-
 textscreen/txt_separator.h                      |  10 +-
 textscreen/txt_spinctrl.c                       |  10 +-
 textscreen/txt_table.c                          |   7 +
 textscreen/txt_widget.c                         |  62 +++++
 textscreen/txt_widget.h                         |  34 ++-
 textscreen/txt_window.c                         |  15 +-
 textscreen/txt_window_action.c                  |  19 +-
 95 files changed, 2336 insertions(+), 527 deletions(-)

diff --cc Makefile.am
index 09fc5868,d766ab61..46c9dec8
--- a/Makefile.am
+++ b/Makefile.am
@@@ -3,65 -3,50 +3,61 @@@ AUX_DIST_GEN
          $(ac_aux_dir)/missing

  MSVC_FILES=                             \
 -        msvc/README                     \
 +        msvc/chocolate.sln              \
          msvc/config.h                   \
 +        msvc/doom.vcproj                \
 +        msvc/heretic.vcproj             \
 +        msvc/hexen.vcproj               \
          msvc/inttypes.h                 \
 +        msvc/libpcsound.vcproj          \
 +        msvc/libtextscreen.vcproj       \
 +        msvc/README                     \
 +        msvc/server.vcproj              \
 +        msvc/setup.vcproj               \
          msvc/stdint.h                   \
 -        msvc/win32.rc                   \
 -        msvc/ChocolateDoom.sln          \
 -        msvc/ChocolateDoom.vcproj
 +        msvc/win32.rc

  CODEBLOCKS_FILES=                              \
 -	codeblocks/config.h                    \
 -	codeblocks/game.cbp                    \
 -	codeblocks/game-res.rc                 \
 -	codeblocks/libpcsound.cbp              \
 -	codeblocks/main.workspace              \
 -	codeblocks/README                      \
 -	codeblocks/server.cbp                  \
 -	codeblocks/setup.cbp                   \
 -	codeblocks/setup-res.rc                \
 -	codeblocks/textscreen.cbp
 +        codeblocks/chocolate.workspace         \
 +        codeblocks/config.h                    \
 +        codeblocks/doom.cbp                    \
 +        codeblocks/game-res.rc                 \
 +        codeblocks/heretic.cbp                 \
 +        codeblocks/hexen.cbp                   \
 +        codeblocks/libpcsound.cbp              \
 +        codeblocks/libtextscreen.cbp           \
 +        codeblocks/README                      \
 +        codeblocks/server.cbp                  \
 +        codeblocks/setup.cbp                   \
 +        codeblocks/setup-res.rc

- DATA_FILES=                   \
-         data/README           \
-         data/doom.ico         \
-         data/doom8.ico        \
-         data/doom.png         \
-         data/setup.ico        \
-         data/setup8.ico       \
-         data/setup.png        \
-         data/convert-icon
+ DOC_FILES=                              \
+         CMDLINE                         \
+         README                          \
+         README.OPL                      \
+         NEWS                            \
+         ChangeLog                       \
+         NOT-BUGS

  EXTRA_DIST=                             \
          $(AUX_DIST_GEN)                 \
          $(MSVC_FILES)                   \
          $(CODEBLOCKS_FILES)             \
-         $(DATA_FILES)                   \
+         $(DOC_FILES)                    \
          .lvimrc                         \
-         config.h                        \
-         CMDLINE                         \
          HACKING                         \
-         README.OPL                      \
          TODO                            \
-         BUGS                            \
-         NOT-BUGS                        \
          rpm.spec

+ docdir=$(prefix)/share/doc/@PACKAGE@
+ doc_DATA=$(DOC_FILES)
+
  MAINTAINERCLEANFILES =  $(AUX_DIST_GEN)

 -SUBDIRS=wince textscreen opl pcsound data src man setup
 +docdir=$(prefix)/share/doc/@PACKAGE@
 +
- SUBDIRS=wince textscreen opl pcsound src man
++SUBDIRS=wince textscreen opl pcsound data src man
 +
  DIST_SUBDIRS=pkg $(SUBDIRS)

  if HAVE_PYTHON
diff --cc configure.in
index c100d7cf,dbb48777..1b0650e3
--- a/configure.in
+++ b/configure.in
@@@ -150,18 -151,17 +150,21 @@@ opl/examples/Makefil
  pcsound/Makefile
  pkg/Makefile
  pkg/config.make
 -pkg/osx/Info.plist
  pkg/osx/Info-gnustep.plist
 -setup/Makefile
 -setup/setup.desktop
 -setup/setup-res.rc
 -setup/setup-manifest.xml
 +pkg/osx/Info.plist
 +rpm.spec
+ data/Makefile
  src/Makefile
+ src/doom.desktop
  src/doom-screensaver.desktop
 +src/doom/Makefile
 +src/heretic/Makefile
 +src/hexen/Makefile
  src/resource.rc
 +src/setup-res.rc
 +src/setup/Makefile
++src/setup/setup.desktop
 +src/setup/setup-manifest.xml
  textscreen/Makefile
  textscreen/examples/Makefile
  wince/Makefile
diff --cc pkg/osx/GNUmakefile
index aa31daf4,d53a9981..cf8c42fc
--- a/pkg/osx/GNUmakefile
+++ b/pkg/osx/GNUmakefile
@@@ -64,15 -80,21 +80,25 @@@ $(STAGING_DIR): launcher $(TOPLEVEL_DOC

  	./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)doom "$(APP_BIN_DIR)"
  	$(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)doom"
 -	./cp-with-libs $(TOPLEVEL)/setup/$(PROGRAM_PREFIX)setup "$(APP_BIN_DIR)"
 +	./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)heretic "$(APP_BIN_DIR)"
 +	$(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)heretic"
 +	./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)hexen "$(APP_BIN_DIR)"
 +	$(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)hexen"
 +	./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)setup "$(APP_BIN_DIR)"
  	$(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)setup"

+ 	$(TOPLEVEL)/man/simplecpp -DPRECOMPILED -D__MACOSX__  \
+ 	             < $(TOPLEVEL)/man/INSTALL.template       \
+ 	             > "$(APP_DOC_DIR)/INSTALL"
+
  	find $(STAGING_DIR) -name .svn -delete -exec rm -rf {} \; || true

+ 	mkdir -p "$(APP_BIN_DIR)/man/man5" "$(APP_BIN_DIR)/man/man6"
+ 	cp $(TOPLEVEL)/man/*.5 "$(APP_BIN_DIR)/man/man5"
+ 	cp $(TOPLEVEL)/man/*.6 "$(APP_BIN_DIR)/man/man6"
+ 	cp disk/dir.DS_Store $(STAGING_DIR)/.DS_Store
+ 	cp disk/background.png $(STAGING_DIR)/background.png
+
  clean : launcher_clean
  	rm -f $(DMG)
  	rm -rf $(STAGING_DIR)
diff --cc pkg/osx/IWADController.h
index fef28918,7464af9f..2f691f69
--- a/pkg/osx/IWADController.h
+++ b/pkg/osx/IWADController.h
@@@ -50,7 -47,7 +50,8 @@@
  - (void) saveConfig;
  - (char *) doomWadPath;
  - (void) setEnvironment;
 +- (const char *) getGameName;
+ - (BOOL) addIWADPath: (NSString *) path;

  @end

diff --cc src/Makefile.am
index 5dc9fe11,24c6e2b2..746a015b
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@@ -128,69 -166,35 +128,81 @@@ SOURCE_FILES = $(COMMON_SOURCE_FILES
                 $(FEATURE_WAD_MERGE_SOURCE_FILES)   \
                 $(FEATURE_SOUND_SOURCE_FILES)

 +SOURCE_FILES_WITH_DEH = $(SOURCE_FILES)                    \
 +                        $(FEATURE_DEHACKED_SOURCE_FILES)
 +
 +EXTRA_LIBS =                                               \
 +               $(top_builddir)/wince/libc_wince.a          \
 +               $(top_builddir)/textscreen/libtextscreen.a  \
 +               $(top_builddir)/pcsound/libpcsound.a        \
 +               $(top_builddir)/opl/libopl.a                \
 +               @LDFLAGS@                                   \
 +               @SDL_LIBS@                                  \
 +               @SDLMIXER_LIBS@                             \
 +               @SDLNET_LIBS@
 +
  if HAVE_WINDRES
 -@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES) resource.rc
 +@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) resource.rc \
 +               $(FEATURE_MULTIPLAYER_SOURCE_FILES)
  else
 -@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES)
 +@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) \
 +               $(FEATURE_MULTIPLAYER_SOURCE_FILES)
  endif

 -@PROGRAM_PREFIX@doom_LDADD =                         \
 -                       ../wince/libc_wince.a         \
 -                       ../textscreen/libtextscreen.a \
 -                       ../pcsound/libpcsound.a       \
 -                       ../opl/libopl.a               \
 -                       @LDFLAGS@                     \
 -                       @SDLMIXER_LIBS@               \
 -                       @SDLNET_LIBS@
 +@PROGRAM_PREFIX@doom_LDADD = doom/libdoom.a $(EXTRA_LIBS)
 +
 +if HAVE_WINDRES
 +@PROGRAM_PREFIX@heretic_SOURCES=$(SOURCE_FILES_WITH_DEH) resource.rc
 +else
 +@PROGRAM_PREFIX@heretic_SOURCES=$(SOURCE_FILES_WITH_DEH)
 +endif
 +
 +@PROGRAM_PREFIX@heretic_LDADD = heretic/libheretic.a $(EXTRA_LIBS)
 +
 +if HAVE_WINDRES
 +@PROGRAM_PREFIX@hexen_SOURCES=$(SOURCE_FILES) resource.rc
 +else
 +@PROGRAM_PREFIX@hexen_SOURCES=$(SOURCE_FILES)
 +endif
 +
 +@PROGRAM_PREFIX@hexen_LDADD = hexen/libhexen.a $(EXTRA_LIBS)
 +
 +# Source files needed for chocolate-setup:
 +
 +SETUP_FILES=                               \
 +deh_str.c            deh_str.h             \
 +d_mode.c             d_mode.h              \
 +d_iwad.c             d_iwad.h              \
 +m_config.c           m_config.h            \
 +m_controls.c         m_controls.h          \
 +z_native.c           z_zone.h
 +
 +if HAVE_WINDRES
 +@PROGRAM_PREFIX@setup_SOURCES=$(SETUP_FILES) $(COMMON_SOURCE_FILES) setup-res.rc
 +else
 +@PROGRAM_PREFIX@setup_SOURCES=$(SETUP_FILES) $(COMMON_SOURCE_FILES)
 +endif
 +@PROGRAM_PREFIX@setup_LDADD = setup/libsetup.a                             \
 +                        $(top_builddir)/wince/libc_wince.a           \
 +                        $(top_builddir)/textscreen/libtextscreen.a   \
 +                        @LDFLAGS@ @SDL_LIBS@ @SDLMIXER_LIBS@ @SDLNET_LIBS@

 -EXTRA_DIST = icon.c
 +EXTRA_DIST =                        \
 +        icon.c                      \
 +        doom-screensaver.desktop.in

+ appdir = $(prefix)/share/applications
+ app_DATA = @PROGRAM_PREFIX@doom.desktop
+
+ @PROGRAM_PREFIX@doom.desktop : doom.desktop
+ 	cp $^ $@
+
+ screensaverdir = $(prefix)/share/applications/screensavers
+ screensaver_DATA = @PROGRAM_PREFIX@doom-screensaver.desktop
+
+ @PROGRAM_PREFIX@doom-screensaver.desktop: doom-screensaver.desktop
+ 	cp $^ $@
+
  .rc.o:
  	$(WINDRES) $^ -o $@
  %.o : %.rc
diff --cc src/d_mode.h
index 29f61c10,00000000..1c4fff64
mode 100644,000000..100644
--- a/src/d_mode.h
+++ b/src/d_mode.h
@@@ -1,95 -1,0 +1,96 @@@
 +// 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:
 +//   Functions and definitions relating to the game type and operational
 +//   mode.
 +//
 +//-----------------------------------------------------------------------------
 +
 +#ifndef __D_MODE__
 +#define __D_MODE__
 +
 +#include "doomtype.h"
 +
 +// The "mission" controls what game we are playing.
 +
 +typedef enum
 +{
 +    doom,            // Doom 1
 +    doom2,           // Doom 2
 +    pack_tnt,        // Final Doom: TNT: Evilution
 +    pack_plut,       // Final Doom: The Plutonia Experiment
 +    heretic,         // Heretic
 +    hexen,           // Hexen
 +
 +    none
 +} GameMission_t;
 +
 +// The "mode" allows more accurate specification of the game mode we are
 +// in: eg. shareware vs. registered.  So doom1.wad and doom.wad are the
 +// same mission, but a different mode.
 +
 +typedef enum
 +{
 +    shareware,       // Doom/Heretic shareware
 +    registered,      // Doom/Heretic registered
 +    commercial,      // Doom II/Hexen
 +    retail,          // Ultimate Doom
 +    indetermined     // Unknown.
 +} GameMode_t;
 +
 +// What version are we emulating?
 +
 +typedef enum
 +{
 +    exe_doom_1_9,    // Doom 1.9: used for shareware, registered and commercial
 +    exe_hacx,        // Hacx
 +    exe_ultimate,    // Ultimate Doom (retail)
 +    exe_final,       // Final Doom
++    exe_final2,      // Final Doom (alternate exe)
 +    exe_chex,        // Chex Quest executable (based on Final Doom)
 +
 +    exe_heretic_1_3, // Heretic 1.3
 +
 +    exe_hexen_1_1    // Hexen 1.1
 +} GameVersion_t;
 +
 +// Skill level.
 +
 +typedef enum
 +{
 +    sk_noitems = -1,        // the "-skill 0" hack
 +    sk_baby = 0,
 +    sk_easy,
 +    sk_medium,
 +    sk_hard,
 +    sk_nightmare
 +} skill_t;
 +
 +boolean D_ValidGameMode(GameMission_t mission, GameMode_t mode);
 +boolean D_ValidGameVersion(GameMission_t mission, GameVersion_t version);
 +boolean D_ValidEpisodeMap(GameMission_t mission, GameMode_t mode,
 +                          int episode, int map);
 +int D_GetNumEpisodes(GameMission_t mission, GameMode_t mode);
 +boolean D_IsEpisodeMap(GameMission_t mission);
 +
 +#endif /* #ifndef __D_MODE__ */
 +
diff --cc src/doom/d_net.c
index dd1ec563,00000000..f3155a9b
mode 100644,000000..100644
--- a/src/doom/d_net.c
+++ b/src/doom/d_net.c
@@@ -1,933 -1,0 +1,934 @@@
 +// 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_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_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)
++    if (M_CheckParm("-server") > 0
++     || M_CheckParm("-privateserver") > 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_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/doom/doom.desktop.in
index 00000000,00000000..44b76e62
new file mode 100644
--- /dev/null
+++ b/src/doom/doom.desktop.in
@@@ -1,0 -1,0 +1,7 @@@
++[Desktop Entry]
++Name=@PACKAGE_NAME@
++Exec=@PROGRAM_PREFIX@doom
++Icon=@PROGRAM_PREFIX@doom
++Type=Application
++Comment=@PACKAGE_SHORTDESC@
++Categories=Game;ActionGame;
diff --cc src/i_endoom.c
index 021a3604,00000000..09c2d2d2
mode 100644,000000..100644
--- a/src/i_endoom.c
+++ b/src/i_endoom.c
@@@ -1,82 -1,0 +1,82 @@@
 +// Emacs style mode select   -*- C++ -*-
 +//-----------------------------------------------------------------------------
 +//
 +// Copyright(C) 2005-8 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:
 +//    Exit text-mode ENDOOM screen.
 +//
 +//-----------------------------------------------------------------------------
 +
 +#include <stdio.h>
 +#include <string.h>
 +
 +#include "doomtype.h"
 +#include "i_video.h"
 +
 +#include "txt_main.h"
 +
 +#define ENDOOM_W 80
 +#define ENDOOM_H 25
 +
 +//
 +// Displays the text mode ending screen after the game quits
 +//
 +
 +void I_Endoom(byte *endoom_data)
 +{
 +    unsigned char *screendata;
 +    int y;
 +    int indent;
 +
 +    // Set up text mode screen
 +
 +    TXT_Init();
 +
 +    // Write the data to the screen memory
 +
 +    screendata = TXT_GetScreenData();
 +
 +    indent = (ENDOOM_W - TXT_SCREEN_W) / 2;
 +
 +    for (y=0; y<TXT_SCREEN_H; ++y)
 +    {
 +        memcpy(screendata + (y * TXT_SCREEN_W * 2),
 +               endoom_data + (y * ENDOOM_W + indent) * 2,
 +               TXT_SCREEN_W * 2);
 +    }
 +
 +    // Wait for a keypress
 +
 +    while (true)
 +    {
 +        TXT_UpdateScreen();
 +
-         if (TXT_GetChar() >= 0)
++        if (TXT_GetChar() > 0)
 +        {
 +            break;
 +        }
 +
 +        TXT_Sleep(0);
 +    }
 +
 +    // Shut down text mode screen
 +
 +    TXT_Shutdown();
 +}
 +
diff --cc src/i_system.c
index 0a856ca9,15e91653..1d961956
--- a/src/i_system.c
+++ b/src/i_system.c
@@@ -274,15 -223,64 +278,14 @@@ void I_Init (void
      I_InitTimer();
      I_InitJoystick();
  }
 -
 -#define ENDOOM_W 80
 -#define ENDOOM_H 25
 -
 -//
 -// Displays the text mode ending screen after the game quits
 -//
 -
 -void I_Endoom(void)
 +void I_BindVariables(void)
  {
 -    unsigned char *endoom_data;
 -    unsigned char *screendata;
 -    int y;
 -    int indent;
 -
 -    endoom_data = W_CacheLumpName(DEH_String("ENDOOM"), PU_STATIC);
 -
 -    // Set up text mode screen
 -
 -    TXT_Init();
 -
 -    // Make sure the new window has the right title and icon
 -
 -    I_SetWindowCaption();
 -    I_SetWindowIcon();
 -
 -    // Write the data to the screen memory
 -
 -    screendata = TXT_GetScreenData();
 -
 -    indent = (ENDOOM_W - TXT_SCREEN_W) / 2;
 -
 -    for (y=0; y<TXT_SCREEN_H; ++y)
 -    {
 -        memcpy(screendata + (y * TXT_SCREEN_W * 2),
 -               endoom_data + (y * ENDOOM_W + indent) * 2,
 -               TXT_SCREEN_W * 2);
 -    }
 -
 -    // Wait for a keypress
 -
 -    while (true)
 -    {
 -        TXT_UpdateScreen();
 -
 -        if (TXT_GetChar() > 0)
 -        {
 -            break;
 -        }
 -
 -        TXT_Sleep(0);
 -    }
 -
 -    // Shut down text mode screen
 -
 -    TXT_Shutdown();
 +    I_BindVideoVariables();
 +    I_BindJoystickVariables();
 +    I_BindSoundVariables();
  }
 +*/

-
  //
  // I_Quit
  //
diff --cc src/i_system.h
index 0697f7db,06e7f662..5a99b213
--- a/src/i_system.h
+++ b/src/i_system.h
@@@ -71,27 -86,7 +71,29 @@@ void I_Tactile (int on, int off, int to

  void I_Error (char *error, ...);

+ boolean I_GetMemoryValue(unsigned int offset, void *value, int size);
+
 +// Schedule a function to be called when the program exits.
 +// If run_if_error is true, the function is called if the exit
 +// is due to an error (I_Error)
 +
 +void I_AtExit(atexit_func_t func, boolean run_if_error);
 +
 +// Add all system-specific config file variable bindings.
 +
 +void I_BindVariables(void);
 +
 +// Print startup banner copyright message.
 +
 +void I_PrintStartupBanner(char *gamedescription);
 +
 +// Print a centered text banner displaying the given string.
 +
 +void I_PrintBanner(char *text);
 +
 +// Print a dividing line for startup banners.
 +
 +void I_PrintDivider(void);
 +
  #endif

diff --cc src/i_video.c
index 9d70e88e,15e4a6b7..6a3175bb
--- a/src/i_video.c
+++ b/src/i_video.c
@@@ -616,74 -511,6 +616,74 @@@ static int AccelerateMouse(int val
      }
  }

 +// Get the equivalent ASCII (Unicode?) character for a keypress.
 +
 +static int GetTypedChar(SDL_Event *event)
 +{
 +    int key;
 +
 +    // If Vanilla keyboard mapping enabled, the keyboard
 +    // scan code is used to give the character typed.
 +    // This does not change depending on keyboard layout.
 +    // If you have a German keyboard, pressing 'z' will
 +    // give 'y', for example.  It is desirable to be able
 +    // to fix this so that people with non-standard
 +    // keyboard mappings can type properly.  If vanilla
 +    // mode is disabled, use the properly translated
 +    // version.
 +
 +    if (vanilla_keyboard_mapping)
 +    {
 +        key = TranslateKey(&event->key.keysym);
 +
 +        // Is shift held down?  If so, perform a translation.
 +
 +        if (shiftdown > 0)
 +        {
 +            if (key >= 0 && key < arrlen(shiftxform))
 +            {
 +                key = shiftxform[key];
 +            }
 +            else
 +            {
 +                key = 0;
 +            }
 +        }
 +
 +        return key;
 +    }
 +    else
 +    {
 +        // Unicode value, from key layout.
 +
-         return event->key.keysym.unicode;
++        return tolower(event->key.keysym.unicode);
 +    }
 +}
 +
 +static void UpdateShiftStatus(SDL_Event *event)
 +{
 +    int change;
 +
 +    if (event->type == SDL_KEYDOWN)
 +    {
 +        change = 1;
 +    }
 +    else if (event->type == SDL_KEYUP)
 +    {
 +        change = -1;
 +    }
 +    else
 +    {
 +        return;
 +    }
 +
 +    if (event->key.keysym.sym == SDLK_LSHIFT
 +     || event->key.keysym.sym == SDLK_RSHIFT)
 +    {
 +        shiftdown += change;
 +    }
 +}
 +
  void I_GetEvent(void)
  {
      SDL_Event sdlevent;
diff --cc src/m_misc.c
index ed41b5f1,9a5fb84a..e14436a3
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@@ -207,85 -206,3 +207,92 @@@ boolean M_StrToInt(const char *str, in
          || sscanf(str, " %d", result) == 1;
  }

 +void M_ExtractFileBase(char *path, char *dest)
 +{
-     char*	src;
-     int		length;
++    char *src;
++    char *filename;
++    int length;
 +
 +    src = path + strlen(path) - 1;
 +
 +    // back up until a \ or the start
 +    while (src != path && *(src - 1) != DIR_SEPARATOR)
 +    {
 +	src--;
 +    }
 +
-     // copy up to eight characters
-     memset(dest, 0, 8);
++    filename = src;
++
++    // Copy up to eight characters
++    // Note: Vanilla Doom exits with an error if a filename is specified
++    // with a base of more than eight characters.  To remove the 8.3
++    // filename limit, instead we simply truncate the name.
++
 +    length = 0;
++    memset(dest, 0, 8);
 +
 +    while (*src != '\0' && *src != '.')
 +    {
-         ++length;
-
- 	if (length > 8)
++        if (length >= 8)
 +        {
- 	    I_Error ("Filename base of %s >8 chars", path);
++            printf("Warning: Truncated '%s' lump name to '%.8s'.\n",
++                   filename, dest);
++            break;
 +        }
 +
- 	*dest++ = toupper((int)*src++);
++	dest[length++] = toupper((int)*src++);
 +    }
 +}
 +
 +//---------------------------------------------------------------------------
 +//
 +// PROC M_ForceUppercase
 +//
 +// Change string to uppercase.
 +//
 +//---------------------------------------------------------------------------
 +
 +void M_ForceUppercase(char *text)
 +{
 +    char *p;
 +
 +    for (p = text; *p != '\0'; ++p)
 +    {
 +        *p = toupper(*p);
 +    }
 +}
 +
 +//
 +// M_StrCaseStr
 +//
 +// Case-insensitive version of strstr()
 +//
 +
 +char *M_StrCaseStr(char *haystack, char *needle)
 +{
 +    unsigned int haystack_len;
 +    unsigned int needle_len;
 +    unsigned int len;
 +    unsigned int i;
 +
 +    haystack_len = strlen(haystack);
 +    needle_len = strlen(needle);
 +
 +    if (haystack_len < needle_len)
 +    {
 +        return NULL;
 +    }
 +
 +    len = haystack_len - needle_len;
 +
 +    for (i = 0; i <= len; ++i)
 +    {
 +        if (!strncasecmp(haystack + i, needle, needle_len))
 +        {
 +            return haystack + i;
 +        }
 +    }
 +
 +    return NULL;
 +}
 +
diff --cc src/setup/Makefile.am
index 25ab38e3,37bea567..7fe051ee
--- a/src/setup/Makefile.am
+++ b/src/setup/Makefile.am
@@@ -27,10 -24,33 +27,16 @@@ libsetup_a_SOURCES = $(SOURCE_FILES
  EXTRA_DIST=                                     \
      setup_icon.c

 -if HAVE_WINDRES
 -@PROGRAM_PREFIX@setup_SOURCES=$(SOURCE_FILES) setup-res.rc
 -else
 -@PROGRAM_PREFIX@setup_SOURCES=$(SOURCE_FILES)
 -endif
 -
 -@PROGRAM_PREFIX@setup_LDADD =                        \
 -                       ../wince/libc_wince.a         \
 -                       ../textscreen/libtextscreen.a \
 -                       @SDLMIXER_LIBS@               \
 -                       @LDFLAGS@
 -
+ appdir = $(prefix)/share/applications
+ app_DATA = @PROGRAM_PREFIX@setup.desktop
+
+ @PROGRAM_PREFIX@setup.desktop : setup.desktop
+ 	cp $^ $@
+
 -.rc.o:
 -	$(WINDRES) $^ -o $@
 -%.o : %.rc
 -	$(WINDRES) $^ -o $@
 -
  if HAVE_PYTHON

 -setup_icon.c : ../data/setup8.ico
 -	../data/convert-icon $^ $@
 +setup_icon.c : $(top_builddir)/data/setup8.ico
 +	$(top_builddir)/data/convert-icon $^ $@

  endif

diff --cc src/setup/display.c
index 9ed0ae5f,f15b2b06..72f3c057
--- a/src/setup/display.c
+++ b/src/setup/display.c
@@@ -579,6 -580,48 +590,60 @@@ static void UpdateVideoDriver(TXT_UNCAS

  #endif

+ static void AdvancedDisplayConfig(TXT_UNCAST_ARG(widget),
+                                   TXT_UNCAST_ARG(modes_table))
+ {
+     TXT_CAST_ARG(txt_table_t, modes_table);
+     txt_window_t *window;
+     txt_checkbox_t *ar_checkbox;
+
+     window = TXT_NewWindow("Advanced display options");
+
+     TXT_SetColumnWidths(window, 35);
+
+     TXT_AddWidgets(window,
+                    ar_checkbox = TXT_NewCheckBox("Fix aspect ratio",
+                                                  &aspect_ratio_correct),
 -                   TXT_NewCheckBox("Show ENDOOM screen on exit", &show_endoom),
+                    NULL);
+
++    if (gamemission == heretic || gamemission == hexen)
++    {
++        TXT_AddWidget(window,
++                      TXT_NewCheckBox("Graphical startup", &graphical_startup));
++    }
++
++    if (gamemission == doom || gamemission == heretic)
++    {
++        TXT_AddWidget(window,
++                      TXT_NewCheckBox("Show ENDOOM screen on exit",
++                                      &show_endoom));
++    }
++
+     TXT_SignalConnect(ar_checkbox, "changed", GenerateModesTable, modes_table);
+
+     // On Windows, there is an extra control to change between
+     // the Windows GDI and DirectX video drivers.
+
+ #if defined(_WIN32) && !defined(_WIN32_WCE)
+     {
+         txt_radiobutton_t *dx_button, *gdi_button;
+
+         TXT_AddWidgets(window,
+                        TXT_NewSeparator("Windows video driver"),
+                        dx_button = TXT_NewRadioButton("DirectX",
+                                                       &use_directx, 1),
+                        gdi_button = TXT_NewRadioButton("Windows GDI",
+                                                        &use_directx, 0),
+                        NULL);
+
+         TXT_SignalConnect(dx_button, "selected",
+                           UpdateVideoDriver, modes_table);
+         TXT_SignalConnect(gdi_button, "selected",
+                           UpdateVideoDriver, modes_table);
+         SetWin32VideoDriver();
+     }
+ #endif
+ }

  void ConfigDisplay(void)
  {
@@@ -639,119 -675,85 +697,130 @@@

      modes_table = TXT_NewTable(num_columns);

-     // The window is set at a fixed vertical position.  This keeps
-     // the top of the window stationary when switching between
-     // fullscreen and windowed mode (which causes the window's
-     // height to change).
+     // Build window:

-     TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP,
-                                   TXT_SCREEN_W / 2, window_y);
+     TXT_AddWidget(window,
+                   fs_checkbox = TXT_NewCheckBox("Full screen", &fullscreen));

-     // On Windows, there is an extra control to change between
-     // the Windows GDI and DirectX video drivers.
-
- #if defined(_WIN32) && !defined(_WIN32_WCE)
+     if (num_supported_bpps > 1)
      {
-         txt_table_t *driver_table;
-         txt_dropdown_list_t *driver_list;
-
-         driver_table = TXT_NewTable(2);
-
-         TXT_SetColumnWidths(driver_table, 20, 0);
-
-         TXT_AddWidgets(driver_table,
-                        TXT_NewLabel("Video driver"),
-                        driver_list = TXT_NewDropdownList(&win32_video_driver,
-                                                          win32_video_drivers,
-                                                          2),
+         TXT_AddWidgets(window,
+                        TXT_NewSeparator("Color depth"),
+                        bpp_table = TXT_NewTable(4),
                         NULL);

-         TXT_SignalConnect(driver_list, "changed",
-                           UpdateVideoDriver, modes_table);
-         SetWin32VideoDriver();
+         for (i = 0; i < num_supported_bpps; ++i)
+         {
+             txt_radiobutton_t *button;

-         TXT_AddWidget(window, driver_table);
-     }
- #endif
+             button = TXT_NewRadioButton(supported_bpps[i],
+                                         &selected_bpp, i);

-     // Screen modes list
+             TXT_AddWidget(bpp_table, button);
+             TXT_SignalConnect(button, "selected", UpdateBPP, modes_table);
+         }
+     }

      TXT_AddWidgets(window,
-                    TXT_NewSeparator("Screen mode"),
-                    bpp_table = TXT_NewTable(2),
+                    modes_separator = TXT_NewSeparator(""),
                     modes_table,
-                    TXT_NewSeparator("Misc."),
                     NULL);

-     if (gamemission == heretic || gamemission == hexen)
+     TXT_SignalConnect(fs_checkbox, "changed",
+                       GenerateModesTable, modes_table);
+     TXT_SignalConnect(fs_checkbox, "changed",
+                       UpdateModeSeparator, modes_separator);
+
+     // How many rows high will the configuration window be?
+     // Need to take into account number of fullscreen modes, and also
+     // number of supported pixel depths.
+     // The windowed modes list is four rows, so take the maximum of
+     // windowed and fullscreen.
+
+     num_rows = (num_screen_modes_fullscreen + num_columns - 1) / num_columns;
+
+     if (num_rows < 4)
      {
-         TXT_AddWidget(window,
-                       TXT_NewCheckBox("Graphical startup", &graphical_startup));
+         num_rows = 4;
      }

-     if (gamemission == doom || gamemission == heretic)
+     if (num_supported_bpps > 1)
      {
-         TXT_AddWidget(window,
-                       TXT_NewCheckBox("Show ENDOOM screen", &show_endoom));
+         num_rows += 2;
      }

-     TXT_AddWidgets(bpp_table,
-                    TXT_NewLabel("Color depth: "),
-                    bpp_selector = TXT_NewDropdownList(&selected_bpp,
-                                                       supported_bpps,
-                                                       num_supported_bpps),
-                    NULL);
+     if (num_rows < 14)
+     {
+         window_y = 8 - ((num_rows + 1) / 2);
+     }
+     else
+     {
+         window_y = 1;
+     }

+     // The window is set at a fixed vertical position.  This keeps
+     // the top of the window stationary when switching between
+     // fullscreen and windowed mode (which causes the window's
+     // height to change).

-     TXT_SignalConnect(bpp_selector, "changed", UpdateBPP, modes_table);
-     TXT_SignalConnect(fs_checkbox, "changed", GenerateModesTable, modes_table);
-     TXT_SignalConnect(ar_checkbox, "changed", GenerateModesTable, modes_table);
+     TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP,
+                                   TXT_SCREEN_W / 2, window_y);

      GenerateModesTable(NULL, modes_table);
+     UpdateModeSeparator(NULL, modes_separator);
+
+     // Button to open "advanced" window.
+     // Need to pass a pointer to the modes table, as some of the options
+     // in there trigger a rebuild of it.
+
+     advanced_button = TXT_NewWindowAction('a', "Advanced");
+     TXT_SetWindowAction(window, TXT_HORIZ_CENTER, advanced_button);
+     TXT_SignalConnect(advanced_button, "pressed",
+                       AdvancedDisplayConfig, modes_table);
  }

 +void BindDisplayVariables(void)
 +{
 +    M_BindVariable("autoadjust_video_settings", &autoadjust_video_settings);
 +    M_BindVariable("aspect_ratio_correct",      &aspect_ratio_correct);
 +    M_BindVariable("fullscreen",                &fullscreen);
 +    M_BindVariable("screen_width",              &screen_width);
 +    M_BindVariable("screen_height",             &screen_height);
 +    M_BindVariable("screen_bpp",                &screen_bpp);
 +    M_BindVariable("startup_delay",             &startup_delay);
 +    M_BindVariable("video_driver",              &video_driver);
 +    M_BindVariable("usegamma",                  &usegamma);
 +
 +
 +    if (gamemission == doom || gamemission == heretic)
 +    {
 +        M_BindVariable("show_endoom",               &show_endoom);
 +    }
 +
 +    if (gamemission == heretic || gamemission == hexen)
 +    {
 +        M_BindVariable("graphical_startup",        &graphical_startup);
 +    }
 +
 +    // Windows Vista or later?  Set screen color depth to
 +    // 32 bits per pixel, as 8-bit palettized screen modes
 +    // don't work properly in recent versions.
 +
 +#if defined(_WIN32) && !defined(_WIN32_WCE)
 +    {
 +        OSVERSIONINFOEX version_info;
 +
 +        ZeroMemory(&version_info, sizeof(OSVERSIONINFOEX));
 +        version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
 +
 +        GetVersionEx((OSVERSIONINFO *) &version_info);
 +
 +        if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT
 +         && version_info.dwMajorVersion >= 6)
 +        {
 +            screen_bpp = 32;
 +        }
 +    }
 +#endif
 +}
 +
diff --cc src/setup/joystick.c
index 0fc00ea1,5d2dfd68..2a7b1f79
--- a/src/setup/joystick.c
+++ b/src/setup/joystick.c
@@@ -23,13 -22,11 +23,14 @@@
  #include <stdlib.h>

  #include "doomtype.h"
 +#include "m_config.h"
 +#include "m_controls.h"
  #include "textscreen.h"
 -#include "txt_joybinput.h"

+ #include "execute.h"
  #include "joystick.h"
 +#include "mode.h"
 +#include "txt_joybinput.h"

  typedef enum
  {
diff --cc src/setup/setup.desktop.in
index 00000000,79fb38be..79fb38be
mode 000000,100644..100644
--- a/src/setup/setup.desktop.in
+++ b/src/setup/setup.desktop.in
diff --cc src/setup/sound.c
index 627549b5,7386e789..9e13edd9
--- a/src/setup/sound.c
+++ b/src/setup/sound.c
@@@ -60,35 -54,23 +60,35 @@@ static char *musicmode_strings[]
  {
      "Disabled",
      "OPL (Adlib/SB)",
 -    "Native MIDI"
 +    "Native MIDI",
 +    "CD audio"
  };

 -int snd_sfxdevice = SNDDEVICE_SB;
 -int numChannels = 8;
 -int sfxVolume = 8;
 +// Config file variables:

 +int snd_sfxdevice = SNDDEVICE_SB;
  int snd_musicdevice = SNDDEVICE_GENMIDI;
- int snd_samplerate = 22050;
 -int musicVolume = 8;
 -
+ int snd_samplerate = 44100;
  int opl_io_port = 0x388;

 -int use_libsamplerate = 0;
 +static int numChannels = 8;
 +static int sfxVolume = 15;
 +static int musicVolume = 15;
 +static int use_libsamplerate = 0;
 +
 +// DOS specific variables: these are unused but should be maintained
 +// so that the config file can be shared between chocolate
 +// doom and doom.exe
 +
 +static int snd_sbport = 0;
 +static int snd_sbirq = 0;
 +static int snd_sbdma = 0;
 +static int snd_mport = 0;
 +
 +// GUI variables:

  static int snd_sfxmode;
 -static int snd_musmode;
 +static int snd_musicmode;

  static void UpdateSndDevices(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data))
  {