shithub: choc

Download patch

ref: e1188317dbd09738abdcd41e585a6d1a7ac1f79a
parent: 93f58bbef5f4c941f32edbb6285d4650d6456c5d
parent: ca78a3ab8f72957395611729b3a5df0500622633
author: Simon Howard <[email protected]>
date: Fri Jan 1 16:25:55 EST 2016

Merge branch 'master' into sdl2-branch

--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1,5 @@
 Simon Howard <[email protected]>
 James Haley <[email protected]>
 Samuel Villarreal <[email protected]>
+Fabian Greffrath <[email protected]>
+Jonathan Dowland <[email protected]>
--- a/configure.ac
+++ b/configure.ac
@@ -9,6 +9,7 @@
 PACKAGE_ISSUES="https://github.com/chocolate-doom/chocolate-doom/issues"
 
 AC_CONFIG_AUX_DIR(autotools)
+AC_CANONICAL_HOST
 
 orig_CFLAGS="$CFLAGS"
 
@@ -81,8 +82,15 @@
         [Build without libsamplerate @<:@default=check@:>@]),
     [],
     [
-        AC_CHECK_LIB(samplerate, src_new)
+        [with_libsamplerate=check]
     ])
+    AS_IF([test "x$with_libsamplerate" != xno], [
+        AC_CHECK_LIB(samplerate, src_new, [], [
+            AS_IF([test "x$with_libsamplerate" != xcheck], [AC_MSG_FAILURE(
+                [--with-libsamplerate was given, but test for libsamplerate failed])
+            ])
+        ])
+    ])
     # Check for libpng.
     AC_ARG_WITH([libpng],
     AS_HELP_STRING([--without-libpng],
@@ -89,8 +97,15 @@
         [Build without libpng @<:@default=check@:>@]),
     [],
     [
+        [with_libpng=check]
+    ])
+    AS_IF([test "x$with_libpng" != xno], [
         AC_CHECK_LIB(z, zlibVersion)
-        AC_CHECK_LIB(png, png_get_io_ptr)
+        AC_CHECK_LIB(png, png_get_io_ptr, [], [
+            AS_IF([test "x$with_libpng" != xcheck], [AC_MSG_FAILURE(
+                [--with-libpng was given, but test for libpng failed])
+            ])
+        ])
     ])
     AC_CHECK_LIB(m, log)
 
@@ -104,8 +119,15 @@
     AC_CHECK_LIB(amd64, amd64_iopl)
 ])
 
-case $host in
-  *cygwin* | *mingw* )
+AC_ARG_WITH([bashcompletiondir],
+    AS_HELP_STRING([--with-bashcompletiondir=DIR], [Bash completion directory]),
+    [],
+    [AS_IF([$($PKG_CONFIG --exists bash-completion 2> /dev/null)],
+        [bashcompletiondir=$($PKG_CONFIG --variable=completionsdir bash-completion)],
+	[bashcompletiondir=${datadir}/bash-completion/completions])])
+
+case "$host" in
+  *-*-mingw* | *-*-cygwin* | *-*-msvc* )
     AC_CHECK_TOOL(WINDRES, windres, )
     ;;
   *)
@@ -154,6 +176,8 @@
 AC_SUBST(PACKAGE_URL)
 AC_SUBST(PACKAGE_ISSUES)
 
+AC_SUBST(bashcompletiondir)
+
 dnl Shut up the datarootdir warnings.
 AC_DEFUN([AC_DATAROOTDIR_CHECKED])
 
@@ -160,6 +184,7 @@
 AC_OUTPUT([
 Makefile
 man/Makefile
+man/bash-completion/Makefile
 opl/Makefile
 opl/examples/Makefile
 pcsound/Makefile
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -1,3 +1,5 @@
+SUBDIRS = bash-completion
+
 MANPAGE_GEN_FILES = environ.man           \
                     iwad_paths.man        \
                     doom.template         \
@@ -52,7 +54,7 @@
 DOCGEN = $(MANDIR)/docgen
 
 $(SETUP_MAN_PAGES): chocolate-setup.6
-	cp $< $@
+	cp chocolate-setup.6 $@
 
 @[email protected]: ../src $(MANPAGE_GEN_FILES)
 	$(DOCGEN) -g doom -m doom.template $(top_srcdir)/src $(top_srcdir)/src/doom > $@
--- /dev/null
+++ b/man/bash-completion/.gitignore
@@ -1,0 +1,4 @@
+*doom
+*heretic
+*hexen
+*strife
--- /dev/null
+++ b/man/bash-completion/Makefile.am
@@ -1,0 +1,44 @@
+bashcompletiondir=@bashcompletiondir@
+
+BASH_COMPLETION_TEMPLATES = \
+    doom.template \
+    heretic.template \
+    hexen.template \
+    strife.template
+
+if HAVE_PYTHON
+
+BASH_COMPLETION_SCRIPTLETS = \
+    @PROGRAM_PREFIX@doom \
+    @PROGRAM_PREFIX@heretic \
+    @PROGRAM_PREFIX@hexen \
+    @PROGRAM_PREFIX@strife
+
+bashcompletion_DATA = $(BASH_COMPLETION_SCRIPTLETS)
+CLEANFILES = $(BASH_COMPLETION_SCRIPTLETS)
+
+MANDIR = $(top_srcdir)/man
+DOCGEN = $(MANDIR)/docgen
+
+@PROGRAM_PREFIX@doom: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES)
+	$(DOCGEN) -g doom -b doom.template $(top_srcdir)/src $(top_srcdir)/src/doom > $@
+
+@PROGRAM_PREFIX@heretic: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES)
+	$(DOCGEN) -g heretic -b heretic.template $(top_srcdir)/src $(top_srcdir)/src/heretic > $@
+
+@PROGRAM_PREFIX@hexen: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES)
+	$(DOCGEN) -g hexen -b hexen.template $(top_srcdir)/src $(top_srcdir)/src/hexen > $@
+
+@PROGRAM_PREFIX@strife: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES)
+	$(DOCGEN) -g strife -b strife.template $(top_srcdir)/src $(top_srcdir)/src/strife > $@
+
+EXTRA_DIST = \
+    $(BASH_COMPLETION_TEMPLATES) \
+    $(BASH_COMPLETION_SCRIPTLETS)
+
+else
+
+EXTRA_DIST = \
+    $(BASH_COMPLETION_TEMPLATES)
+
+endif
--- /dev/null
+++ b/man/bash-completion/doom.template
@@ -1,0 +1,51 @@
+# bash completion for Chocolate Doom                       -*- shell-script -*-
+
+_chocolate_doom()
+{
+    local cur prev words cword
+    _init_completion || return
+
+    # Save the previous switch on the command line in the prevsw variable
+    local i prevsw=""
+    for (( i=1; $cword > 1 && i <= $cword; i++ )); do
+        if [[ ${words[i]} == -* ]]; then
+            prevsw=${words[i]}
+        fi
+    done
+
+    # Allow adding more than one file with the same extension to the same switch
+    case $prevsw in
+        -config|-extraconfig)
+            _filedir cfg
+            ;;
+        -file|-iwad|-aa|-af|-as|-merge|-nwtmerge)
+            _filedir wad
+            ;;
+        -playdemo|-timedemo)
+            _filedir lmp
+            ;;
+        -deh)
+            _filedir '@(bex|deh)'
+            ;;
+    esac
+
+    case $prev in
+        -pack)
+            COMPREPLY=(doom2 tnt plutonia)
+            ;;
+        -gameversion)
+            COMPREPLY=(1.9 ultimate final final2 hacx chex)
+            ;;
+        -setmem)
+            COMPREPLY=(dos622 dos71 dosbox)
+            ;;
+    esac
+
+    if [[ $cur == -* ]]; then
+        COMPREPLY=( $( compgen -W '@content' -- "$cur" ) )
+    fi
+} &&
+
+complete -F _chocolate_doom chocolate-doom
+
+# ex: ts=4 sw=4 et filetype=sh
--- /dev/null
+++ b/man/bash-completion/heretic.template
@@ -1,0 +1,48 @@
+# bash completion for Chocolate Heretic                    -*- shell-script -*-
+
+_chocolate_heretic()
+{
+    local cur prev words cword
+    _init_completion || return
+
+    # Save the previous switch on the command line in the prevsw variable
+    local i prevsw=""
+    for (( i=1; $cword > 1 && i <= $cword; i++ )); do
+        if [[ ${words[i]} == -* ]]; then
+            prevsw=${words[i]}
+        fi
+    done
+
+    # Allow adding more than one file with the same extension to the same switch
+    case $prevsw in
+        -config|-extraconfig)
+            _filedir cfg
+            ;;
+        -file|-iwad|-aa|-af|-as|-merge|-nwtmerge)
+            _filedir wad
+            ;;
+        -playdemo|-timedemo)
+            _filedir lmp
+            ;;
+        -deh)
+            _filedir hhe
+            ;;
+    esac
+
+    case $prev in
+        -hhever)
+            COMPREPLY=(1.0 1.2 1.3)
+            ;;
+        -setmem)
+            COMPREPLY=(dos622 dos71 dosbox)
+            ;;
+    esac
+
+    if [[ $cur == -* ]]; then
+        COMPREPLY=( $( compgen -W '@content' -- "$cur" ) )
+    fi
+} &&
+
+complete -F _chocolate_heretic chocolate-heretic
+
+# ex: ts=4 sw=4 et filetype=sh
--- /dev/null
+++ b/man/bash-completion/hexen.template
@@ -1,0 +1,42 @@
+# bash completion for Chocolate Hexen                     -*- shell-script -*-
+
+_chocolate_hexen()
+{
+    local cur prev words cword
+    _init_completion || return
+
+    # Save the previous switch on the command line in the prevsw variable
+    local i prevsw=""
+    for (( i=1; $cword > 1 && i <= $cword; i++ )); do
+        if [[ ${words[i]} == -* ]]; then
+            prevsw=${words[i]}
+        fi
+    done
+
+    # Allow adding more than one file with the same extension to the same switch
+    case $prevsw in
+        -config|-extraconfig)
+            _filedir cfg
+            ;;
+        -file|-iwad|-aa|-af|-as|-merge|-nwtmerge)
+            _filedir wad
+            ;;
+        -playdemo|-timedemo)
+            _filedir lmp
+            ;;
+    esac
+
+    case $prev in
+        -setmem)
+            COMPREPLY=(dos622 dos71 dosbox)
+            ;;
+    esac
+
+    if [[ $cur == -* ]]; then
+        COMPREPLY=( $( compgen -W '@content' -- "$cur" ) )
+    fi
+} &&
+
+complete -F _chocolate_hexen chocolate-hexen
+
+# ex: ts=4 sw=4 et filetype=sh
--- /dev/null
+++ b/man/bash-completion/strife.template
@@ -1,0 +1,48 @@
+# bash completion for Chocolate Strife                     -*- shell-script -*-
+
+_chocolate_strife()
+{
+    local cur prev words cword
+    _init_completion || return
+
+    # Save the previous switch on the command line in the prevsw variable
+    local i prevsw=""
+    for (( i=1; $cword > 1 && i <= $cword; i++ )); do
+        if [[ ${words[i]} == -* ]]; then
+            prevsw=${words[i]}
+        fi
+    done
+
+    # Allow adding more than one file with the same extension to the same switch
+    case $prevsw in
+        -config|-extraconfig)
+            _filedir cfg
+            ;;
+        -file|-iwad|-aa|-af|-as|-merge|-nwtmerge)
+            _filedir wad
+            ;;
+        -playdemo|-timedemo)
+            _filedir lmp
+            ;;
+        -deh)
+            _filedir seh
+            ;;
+    esac
+
+    case $prev in
+        -gameversion)
+            COMPREPLY=(1.2 1.31)
+            ;;
+        -setmem)
+            COMPREPLY=(dos622 dos71 dosbox)
+            ;;
+    esac
+
+    if [[ $cur == -* ]]; then
+        COMPREPLY=( $( compgen -W '@content' -- "$cur" ) )
+    fi
+} &&
+
+complete -F _chocolate_strife chocolate-strife
+
+# ex: ts=4 sw=4 et filetype=sh
--- a/man/docgen
+++ b/man/docgen
@@ -106,6 +106,19 @@
 
         return result
 
+    def completion_output(self):
+        result = ""
+
+        self.params.sort()
+
+        for p in self.params:
+            if p.should_show():
+                result += p.completion_output(0)
+
+        result = result.rstrip()
+
+        return result
+
     def manpage_output(self):
         result = ".SH " + self.description.upper() + "\n"
 
@@ -278,6 +291,12 @@
 
         return result
 
+    def completion_output(self, w):
+
+        result = self.name + " "
+
+        return result
+
 # Read list of wiki pages
 
 def read_wikipages():
@@ -444,6 +463,15 @@
 
     print_template(template_file, content)
 
+def completion_output(targets, template_file):
+
+    content = ""
+
+    for t in targets:
+        content += t.completion_output() + "\n"
+
+    print_template(template_file, content)
+
 def usage():
     print("Usage: %s [-V] [-c tag] [-g game] ( -m | -w | -p ) <dir>..." \
             % sys.argv[0])
@@ -452,6 +480,7 @@
     print("   -m :  Manpage output")
     print("   -w :  Wikitext output")
     print("   -p :  Plaintext output")
+    print("   -b :  Bash-Completion output")
     print("   -V :  Don't show Vanilla Doom options")
     print("   -g :  Only document options for specified game.")
     sys.exit(0)
@@ -458,7 +487,7 @@
 
 # Parse command line
 
-opts, args = getopt.getopt(sys.argv[1:], "m:wp:c:g:V")
+opts, args = getopt.getopt(sys.argv[1:], "m:wp:b:c:g:V")
 
 output_function = None
 template = None
@@ -473,6 +502,9 @@
         output_function = wiki_output
     elif opt[0] == "-p":
         output_function = plaintext_output
+        template = opt[1]
+    elif opt[0] == "-b":
+        output_function = completion_output
         template = opt[1]
     elif opt[0] == "-V":
         show_vanilla_options = False
--- a/msvc/doom.vcproj
+++ b/msvc/doom.vcproj
@@ -380,6 +380,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\v_diskicon.h"
+				>
+			</File>
+			<File
 				RelativePath="..\src\v_patch.h"
 				>
 			</File>
@@ -793,6 +797,10 @@
 			</File>
 			<File
 				RelativePath="..\src\tables.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\v_diskicon.c"
 				>
 			</File>
 			<File
--- a/msvc/heretic.vcproj
+++ b/msvc/heretic.vcproj
@@ -374,6 +374,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\v_diskicon.c"
+				>
+			</File>
+			<File
 				RelativePath="..\src\v_video.c"
 				>
 			</File>
@@ -789,6 +793,10 @@
 			</File>
 			<File
 				RelativePath="..\src\tables.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\v_diskicon.h"
 				>
 			</File>
 			<File
--- a/msvc/hexen.vcproj
+++ b/msvc/hexen.vcproj
@@ -355,6 +355,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\v_diskicon.c"
+				>
+			</File>
+			<File
 				RelativePath="..\src\v_video.c"
 				>
 			</File>
@@ -750,6 +754,10 @@
 			</File>
 			<File
 				RelativePath="..\src\tables.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\v_diskicon.h"
 				>
 			</File>
 			<File
--- a/msvc/strife.vcproj
+++ b/msvc/strife.vcproj
@@ -380,6 +380,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\v_diskicon.h"
+				>
+			</File>
+			<File
 				RelativePath="..\src\v_patch.h"
 				>
 			</File>
@@ -817,6 +821,10 @@
 			</File>
 			<File
 				RelativePath="..\src\tables.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\v_diskicon.c"
 				>
 			</File>
 			<File
--- a/opl/opl.c
+++ b/opl/opl.c
@@ -27,7 +27,7 @@
 
 //#define OPL_DEBUG_TRACE
 
-#ifdef HAVE_IOPERM
+#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM)
 extern opl_driver_t opl_linux_driver;
 #endif
 #if defined(HAVE_LIBI386) || defined(HAVE_LIBAMD64)
@@ -40,7 +40,7 @@
 
 static opl_driver_t *drivers[] =
 {
-#ifdef HAVE_IOPERM
+#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM)
     &opl_linux_driver,
 #endif
 #if defined(HAVE_LIBI386) || defined(HAVE_LIBAMD64)
--- a/opl/opl_linux.c
+++ b/opl/opl_linux.c
@@ -17,7 +17,7 @@
 
 #include "config.h"
 
-#ifdef HAVE_IOPERM
+#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM)
 
 #include <stdio.h>
 #include <string.h>
@@ -99,5 +99,5 @@
     OPL_Timer_AdjustCallbacks,
 };
 
-#endif /* #ifdef HAVE_IOPERM */
+#endif /* #if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM) */
 
--- a/pkg/osx/Execute.m
+++ b/pkg/osx/Execute.m
@@ -26,6 +26,7 @@
 
 #define RESPONSE_FILE "/tmp/launcher.rsp"
 #define TEMP_SCRIPT "/tmp/tempscript.sh"
+#define WINDOW_TITLE PACKAGE_STRING " command prompt"
 
 static char *executable_path;
 
@@ -182,6 +183,9 @@
     fprintf(stream, "DOOMWADPATH=\"%s\"\n", doomwadpath);
     fprintf(stream, "export DOOMWADPATH\n");
     fprintf(stream, "rm -f \"%s\"\n", TEMP_SCRIPT);
+
+    // Window title to something more interesting than "tempscript":
+    fprintf(stream, "echo -en \"\\033]0;%s\\a\"\n", WINDOW_TITLE);
 
     // Display a useful message:
 
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -79,6 +79,7 @@
 sha1.c               sha1.h                \
 memio.c              memio.h               \
 tables.c             tables.h              \
+v_diskicon.c         v_diskicon.h          \
 v_video.c            v_video.h             \
                      v_patch.h             \
 w_checksum.c         w_checksum.h          \
@@ -185,7 +186,7 @@
 @PROGRAM_PREFIX@strife_LDADD = strife/libstrife.a $(EXTRA_LIBS)
 
 $(SETUP_BINARIES): @PROGRAM_PREFIX@setup$(EXEEXT)
-	cp $< $@
+	cp @PROGRAM_PREFIX@setup$(EXEEXT) $@
 
 # Source files needed for chocolate-setup:
 
@@ -271,13 +272,14 @@
 if HAVE_PYTHON
 
 icon.c : $(top_builddir)/data/doom.png
-	$(top_builddir)/data/convert-icon $< $@
+	$(top_builddir)/data/convert-icon $(top_builddir)/data/doom.png $@
 
 endif
 
 midiread : midifile.c
-	$(CC) -DTEST $(CFLAGS) @LDFLAGS@ $< -o $@
+	$(CC) -DTEST $(CFLAGS) @LDFLAGS@ midifile.c -o $@
 
-mus2mid : mus2mid.c memio.c z_native.c i_system.c m_argv.c m_misc.c
-	$(CC) -DSTANDALONE -I$(top_builddir) $(CFLAGS) @LDFLAGS@ $^ -o $@
+MUS2MID_SOURCES = mus2mid.c memio.c z_native.c i_system.c m_argv.c m_misc.c
+mus2mid : $(MUS2MID_SOURCES)
+	$(CC) -DSTANDALONE -I$(top_builddir) $(CFLAGS) @LDFLAGS@ $(MUS2MID_SOURCES) -o $@
 
--- a/src/d_mode.c
+++ b/src/d_mode.c
@@ -30,7 +30,7 @@
     int episode;
     int map;
 } valid_modes[] = {
-    { pack_chex, shareware,  1, 5 },
+    { pack_chex, retail,     1, 5 },
     { doom,      shareware,  1, 9 },
     { doom,      registered, 3, 9 },
     { doom,      retail,     4, 9 },
--- a/src/doom/am_map.c
+++ b/src/doom/am_map.c
@@ -99,8 +99,8 @@
 #define M_ZOOMOUT       ((int) (FRACUNIT/1.02))
 
 // translates between frame-buffer and map distances
-#define FTOM(x) FixedMul(((x)<<16),scale_ftom)
-#define MTOF(x) (FixedMul((x),scale_mtof)>>16)
+#define FTOM(x) FixedMul(((x)<<FRACBITS),scale_ftom)
+#define MTOF(x) (FixedMul((x),scale_mtof)>>FRACBITS)
 // translates between frame-buffer and map coordinates
 #define CXMTOF(x)  (f_x + MTOF((x)-m_x))
 #define CYMTOF(y)  (f_y + (f_h - MTOF((y)-m_y)))
@@ -199,7 +199,7 @@
 
 boolean    	automapactive = false;
 static int 	finit_width = SCREENWIDTH;
-static int 	finit_height = SCREENHEIGHT - 32;
+static int 	finit_height = SCREENHEIGHT - ST_HEIGHT;
 
 // location of window on screen
 static int 	f_x;
@@ -833,7 +833,7 @@
 //
 void AM_clearFB(int color)
 {
-    memset(fb, color, f_w*f_h);
+    memset(fb, color, f_w*f_h*sizeof(*fb));
 }
 
 
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -40,6 +40,7 @@
 #include "w_main.h"
 #include "w_wad.h"
 #include "s_sound.h"
+#include "v_diskicon.h"
 #include "v_video.h"
 
 #include "f_finale.h"
@@ -216,12 +217,12 @@
 	    break;
 	if (automapactive)
 	    AM_Drawer ();
-	if (wipe || (viewheight != 200 && fullscreen) )
+	if (wipe || (viewheight != SCREENHEIGHT && fullscreen) || disk_indicator == disk_dirty)
 	    redrawsbar = true;
 	if (inhelpscreensstate && !inhelpscreens)
 	    redrawsbar = true;              // just put away the help screen
-	ST_Drawer (viewheight == 200, redrawsbar );
-	fullscreen = viewheight == 200;
+	ST_Drawer (viewheight == SCREENHEIGHT, redrawsbar );
+	fullscreen = viewheight == SCREENHEIGHT;
 	break;
 
       case GS_INTERMISSION:
@@ -259,7 +260,7 @@
     }
 
     // see if the border needs to be updated to the screen
-    if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != 320)
+    if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != SCREENWIDTH)
     {
 	if (menuactive || menuactivestate || !viewactivestate)
 	    borderdrawcount = 3;
@@ -369,6 +370,7 @@
     M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit);
     M_BindIntVariable("vanilla_demo_limit",     &vanilla_demo_limit);
     M_BindIntVariable("show_endoom",            &show_endoom);
+    M_BindIntVariable("show_diskicon",          &show_diskicon);
 
     // Multiplayer chat macros
 
@@ -429,7 +431,7 @@
     I_GraphicsCheckCommandLine();
     I_SetGrabMouseCallback(D_GrabMouseCallback);
     I_InitGraphics();
-    I_EnableLoadingDisk();
+    V_EnableLoadingDisk(SCREENWIDTH - LOADING_DISK_W, SCREENHEIGHT - LOADING_DISK_H);
 
     V_RestoreBuffer();
     R_ExecuteSetViewSize();
@@ -964,8 +966,9 @@
     // @arg <version>
     // @category compat
     //
-    // Emulate a specific version of Doom.  Valid values are "1.9",
-    // "ultimate", "final", "final2", "hacx" and "chex".
+    // Emulate a specific version of Doom.  Valid values are "1.666",
+    // "1.7", "1.8", "1.9", "ultimate", "final", "final2", "hacx" and
+    // "chex".
     //
 
     p = M_CheckParmWithArgs("-gameversion", 1);
--- a/src/doom/f_finale.c
+++ b/src/doom/f_finale.c
@@ -512,7 +512,7 @@
     }
     
     // draw it
-    cx = 160-width/2;
+    cx = SCREENWIDTH/2-width/2;
     ch = text;
     while (ch)
     {
@@ -559,9 +559,9 @@
 			
     patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE);
     if (flip)
-	V_DrawPatchFlipped(160, 170, patch);
+	V_DrawPatchFlipped(SCREENWIDTH/2, 170, patch);
     else
-	V_DrawPatch(160, 170, patch);
+	V_DrawPatch(SCREENWIDTH/2, 170, patch);
 }
 
 
@@ -618,18 +618,18 @@
 
     V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
 	
-    scrolled = (320 - ((signed int) finalecount-230)/2);
-    if (scrolled > 320)
-	scrolled = 320;
+    scrolled = (SCREENWIDTH - ((signed int) finalecount-230)/2);
+    if (scrolled > SCREENWIDTH)
+	scrolled = SCREENWIDTH;
     if (scrolled < 0)
 	scrolled = 0;
 		
     for ( x=0 ; x<SCREENWIDTH ; x++)
     {
-	if (x+scrolled < 320)
+	if (x+scrolled < SCREENWIDTH)
 	    F_DrawPatchCol (x, p1, x+scrolled);
 	else
-	    F_DrawPatchCol (x, p2, x+scrolled - 320);		
+	    F_DrawPatchCol (x, p2, x+scrolled - SCREENWIDTH);		
     }
 	
     if (finalecount < 1130)
--- a/src/doom/f_wipe.c
+++ b/src/doom/f_wipe.c
@@ -49,13 +49,13 @@
     int		y;
     short*	dest;
 
-    dest = (short*) Z_Malloc(width*height*2, PU_STATIC, 0);
+    dest = (short*) Z_Malloc(width*height*sizeof(*dest), PU_STATIC, 0);
 
     for(y=0;y<height;y++)
 	for(x=0;x<width;x++)
 	    dest[x*height+y] = array[y*width+x];
 
-    memcpy(array, dest, width*height*2);
+    memcpy(array, dest, width*height*sizeof(*dest));
 
     Z_Free(dest);
 
@@ -67,7 +67,7 @@
   int	height,
   int	ticks )
 {
-    memcpy(wipe_scr, wipe_scr_start, width*height);
+    memcpy(wipe_scr, wipe_scr_start, width*height*sizeof(*wipe_scr));
     return 0;
 }
 
@@ -138,7 +138,7 @@
     int i, r;
     
     // copy start screen to main screen
-    memcpy(wipe_scr, wipe_scr_start, width*height);
+    memcpy(wipe_scr, wipe_scr_start, width*height*sizeof(*wipe_scr));
     
     // makes this wipe faster (in theory)
     // to have stuff in column-major format
@@ -234,7 +234,7 @@
   int	width,
   int	height )
 {
-    wipe_scr_start = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL);
+    wipe_scr_start = Z_Malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*wipe_scr_start), PU_STATIC, NULL);
     I_ReadScreen(wipe_scr_start);
     return 0;
 }
@@ -246,7 +246,7 @@
   int	width,
   int	height )
 {
-    wipe_scr_end = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL);
+    wipe_scr_end = Z_Malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*wipe_scr_end), PU_STATIC, NULL);
     I_ReadScreen(wipe_scr_end);
     V_DrawBlock(x, y, width, height, wipe_scr_start); // restore start scr.
     return 0;
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -1726,9 +1726,6 @@
     // the -warp command line parameter to behave differently.
     // This is left here for posterity.
 
-    if (skill > sk_nightmare)
-	skill = sk_nightmare;
-
     // This was quite messy with SPECIAL and commented parts.
     // Supposedly hacks to make the latest edition work.
     // It might not work properly.
@@ -1751,6 +1748,33 @@
 	episode = 3;
     }
     */
+
+    if (skill > sk_nightmare)
+	skill = sk_nightmare;
+
+    if (gameversion >= exe_ultimate)
+    {
+        if (episode == 0)
+        {
+            episode = 4;
+        }
+    }
+    else
+    {
+        if (episode < 1)
+        {
+            episode = 1;
+        }
+        if (episode > 3)
+        {
+            episode = 3;
+        }
+    }
+
+    if (episode > 1 && gamemode == shareware)
+    {
+        episode = 1;
+    }
 
     if (map < 1)
 	map = 1;
--- a/src/doom/m_menu.c
+++ b/src/doom/m_menu.c
@@ -1962,7 +1962,7 @@
     if (messageToPrint)
     {
 	start = 0;
-	y = 100 - M_StringHeight(messageString) / 2;
+	y = SCREENHEIGHT/2 - M_StringHeight(messageString) / 2;
 	while (messageString[start] != '\0')
 	{
 	    int foundnewline = 0;
@@ -1990,7 +1990,7 @@
                 start += strlen(string);
             }
 
-	    x = 160 - M_StringWidth(string) / 2;
+	    x = SCREENWIDTH/2 - M_StringWidth(string) / 2;
 	    M_WriteText(x, y, string);
 	    y += SHORT(hu_font[0]->height);
 	}
--- a/src/doom/p_doors.c
+++ b/src/doom/p_doors.c
@@ -21,6 +21,7 @@
 #include "doomdef.h"
 #include "deh_main.h"
 #include "p_local.h"
+#include "i_system.h"
 
 #include "s_sound.h"
 
--- a/src/doom/p_enemy.c
+++ b/src/doom/p_enemy.c
@@ -212,7 +212,7 @@
     if (!actor->info->meleestate)
 	dist -= 128*FRACUNIT;	// no melee attack, so fire more
 
-    dist >>= 16;
+    dist >>= FRACBITS;
 
     if (actor->type == MT_VILE)
     {
--- a/src/doom/p_map.c
+++ b/src/doom/p_map.c
@@ -1083,8 +1083,8 @@
     shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
 
     // can't shoot outside view angles
-    topslope = 100*FRACUNIT/160;	
-    bottomslope = -100*FRACUNIT/160;
+    topslope = (SCREENHEIGHT/2)*FRACUNIT/(SCREENWIDTH/2);	
+    bottomslope = -(SCREENHEIGHT/2)*FRACUNIT/(SCREENWIDTH/2);
     
     attackrange = distance;
     linetarget = NULL;
--- a/src/doom/p_pspr.c
+++ b/src/doom/p_pspr.c
@@ -726,7 +726,7 @@
     {
 	damage = 5*(P_Random ()%3+1);
 	angle = player->mo->angle;
-	angle += (P_Random()-P_Random())<<19;
+	angle += (P_Random()-P_Random())<<ANGLETOFINESHIFT;
 	P_LineAttack (player->mo,
 		      angle,
 		      MISSILERANGE,
--- a/src/doom/p_setup.c
+++ b/src/doom/p_setup.c
@@ -192,12 +192,20 @@
 	li->v1 = &vertexes[SHORT(ml->v1)];
 	li->v2 = &vertexes[SHORT(ml->v2)];
 
-	li->angle = (SHORT(ml->angle))<<16;
-	li->offset = (SHORT(ml->offset))<<16;
+	li->angle = (SHORT(ml->angle))<<FRACBITS;
+	li->offset = (SHORT(ml->offset))<<FRACBITS;
 	linedef = SHORT(ml->linedef);
 	ldef = &lines[linedef];
 	li->linedef = ldef;
 	side = SHORT(ml->side);
+
+        // e6y: check for wrong indexes
+        if ((unsigned)ldef->sidenum[side] >= (unsigned)numsides)
+        {
+            I_Error("P_LoadSegs: linedef %d for seg %d references a non-existent sidedef %d",
+                    linedef, i, (unsigned)ldef->sidenum[side]);
+        }
+
 	li->sidedef = &sides[ldef->sidenum[side]];
 	li->frontsector = sides[ldef->sidenum[side]].sector;
 
--- a/src/doom/p_user.c
+++ b/src/doom/p_user.c
@@ -144,7 +144,7 @@
 	
     cmd = &player->cmd;
 	
-    player->mo->angle += (cmd->angleturn<<16);
+    player->mo->angle += (cmd->angleturn<<FRACBITS);
 
     // Do not let the player control movement
     //  if not onground.
--- a/src/doom/r_draw.c
+++ b/src/doom/r_draw.c
@@ -843,7 +843,7 @@
 	
     if (background_buffer == NULL)
     {
-        background_buffer = Z_Malloc(SCREENWIDTH * (SCREENHEIGHT - SBARHEIGHT),
+        background_buffer = Z_Malloc(SCREENWIDTH * (SCREENHEIGHT - SBARHEIGHT) * sizeof(*background_buffer),
                                      PU_STATIC, NULL);
     }
 
@@ -928,7 +928,7 @@
 
     if (background_buffer != NULL)
     {
-        memcpy(I_VideoBuffer + ofs, background_buffer + ofs, count); 
+        memcpy(I_VideoBuffer + ofs, background_buffer + ofs, count * sizeof(*I_VideoBuffer));
     }
 } 
 
--- a/src/doom/r_main.c
+++ b/src/doom/r_main.c
@@ -482,7 +482,7 @@
     num = FixedMul(projection,sineb)<<detailshift;
     den = FixedMul(rw_distance,sinea);
 
-    if (den > num>>16)
+    if (den > num>>FRACBITS)
     {
 	scale = FixedDiv (num, den);
 
@@ -841,7 +841,7 @@
     {
 	fixedcolormap =
 	    colormaps
-	    + player->fixedcolormap*256*sizeof(lighttable_t);
+	    + player->fixedcolormap*256;
 	
 	walllights = scalelightfixed;
 
--- a/src/doom/r_segs.c
+++ b/src/doom/r_segs.c
@@ -715,7 +715,7 @@
     if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture)
 	 && !ds_p->sprtopclip)
     {
-	memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
+	memcpy (lastopening, ceilingclip+start, sizeof(*lastopening)*(rw_stopx-start));
 	ds_p->sprtopclip = lastopening - start;
 	lastopening += rw_stopx - start;
     }
@@ -723,7 +723,7 @@
     if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture)
 	 && !ds_p->sprbottomclip)
     {
-	memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
+	memcpy (lastopening, floorclip+start, sizeof(*lastopening)*(rw_stopx-start));
 	ds_p->sprbottomclip = lastopening - start;
 	lastopening += rw_stopx - start;	
     }
--- a/src/doom/r_sky.c
+++ b/src/doom/r_sky.c
@@ -47,6 +47,6 @@
 void R_InitSkyMap (void)
 {
   // skyflatnum = R_FlatNumForName ( SKYFLATNAME );
-    skytexturemid = 100*FRACUNIT;
+    skytexturemid = SCREENHEIGHT/2*FRACUNIT;
 }
 
--- a/src/doom/r_things.c
+++ b/src/doom/r_things.c
@@ -38,7 +38,7 @@
 
 
 #define MINZ				(FRACUNIT*4)
-#define BASEYCENTER			100
+#define BASEYCENTER			(SCREENHEIGHT/2)
 
 //void R_DrawColumn (void);
 //void R_DrawFuzzColumn (void);
@@ -665,7 +665,7 @@
     flip = (boolean)sprframe->flip[0];
     
     // calculate edges of the shape
-    tx = psp->sx-160*FRACUNIT;
+    tx = psp->sx-(SCREENWIDTH/2)*FRACUNIT;
 	
     tx -= spriteoffset[lump];	
     x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS;
--- a/src/doom/st_stuff.c
+++ b/src/doom/st_stuff.c
@@ -611,7 +611,7 @@
       
       if (gamemode == commercial)
       {
-	epsd = 1;
+	epsd = 0;
 	map = (buf[0] - '0')*10 + buf[1] - '0';
       }
       else
@@ -635,31 +635,41 @@
       }
 
       // Catch invalid maps.
-      if (epsd < 1)
-	return false;
+      if (gamemode != commercial)
+      {
+          if (epsd < 1)
+          {
+              return false;
+          }
+          if (epsd > 4)
+          {
+              return false;
+          }
+          if (epsd == 4 && gameversion < exe_ultimate)
+          {
+              return false;
+          }
+          if (map < 1)
+          {
+              return false;
+          }
+          if (map > 9)
+          {
+              return false;
+          }
+      }
+      else
+      {
+          if (map < 1)
+          {
+              return false;
+          }
+          if (map > 40)
+          {
+              return false;
+          }
+      }
 
-      if (map < 1)
-	return false;
-
-      // Ohmygod - this is not going to work.
-      if ((gamemode == retail)
-	  && ((epsd > 4) || (map > 9)))
-	return false;
-
-      if ((gamemode == registered)
-	  && ((epsd > 3) || (map > 9)))
-	return false;
-
-      if ((gamemode == shareware)
-	  && ((epsd > 1) || (map > 9)))
-	return false;
-
-      // The source release has this check as map > 34. However, Vanilla
-      // Doom allows IDCLEV up to MAP40 even though it normally crashes.
-      if ((gamemode == commercial)
-	&& (( epsd > 1) || (map > 40)))
-	return false;
-
       // So be it.
       plyr->message = DEH_String(STSTR_CLEV);
       G_DeferedInitNew(gameskill, epsd, map);
@@ -1420,6 +1430,6 @@
 void ST_Init (void)
 {
     ST_loadData();
-    st_backing_screen = (byte *) Z_Malloc(ST_WIDTH * ST_HEIGHT, PU_STATIC, 0);
+    st_backing_screen = (byte *) Z_Malloc(ST_WIDTH * ST_HEIGHT * sizeof(*st_backing_screen), PU_STATIC, 0);
 }
 
--- a/src/doom/wi_stuff.c
+++ b/src/doom/wi_stuff.c
@@ -1810,7 +1810,7 @@
     if (!wbs->maxsecret)
 	wbs->maxsecret = 1;
 
-    if ( gamemode != retail )
+    if ( gameversion < exe_ultimate )
       if (wbs->epsd > 2)
 	wbs->epsd -= 3;
 }
--- a/src/doomtype.h
+++ b/src/doomtype.h
@@ -52,10 +52,10 @@
 
 #ifdef __GNUC__
 
-#ifdef __clang__
-#define PACKEDATTR __attribute__((packed))
-#else
+#if defined(_WIN32) && !defined(__clang__)
 #define PACKEDATTR __attribute__((packed,gcc_struct))
+#else
+#define PACKEDATTR __attribute__((packed))
 #endif
 
 #else
--- a/src/hexen/h2def.h
+++ b/src/hexen/h2def.h
@@ -58,19 +58,22 @@
 #endif
 
 // Past distributions
-#ifndef VER_ID
-#define VER_ID "DVL"
-#endif
+//#ifndef VER_ID
+//#define VER_ID "DVL"
+//#endif
 //#define HEXEN_VERSIONTEXT "ID V1.2"
 //#define HEXEN_VERSIONTEXT "RETAIL STORE BETA"               // 9/26/95
 //#define HEXEN_VERSIONTEXT "DVL BETA 10 05 95" // Used for GT for testing
 //#define HEXEN_VERSIONTEXT "DVL BETA 10 07 95" // Just an update for Romero
 //#define HEXEN_VERSIONTEXT "FINAL 1.0 (10 13 95)" // Just an update for Romero
-#ifdef RANGECHECK
-#define HEXEN_VERSIONTEXT "Version 1.1 +R "__DATE__" ("VER_ID")"
-#else
-#define HEXEN_VERSIONTEXT "Version 1.1 "__DATE__" ("VER_ID")"
-#endif
+//#ifdef RANGECHECK
+//#define HEXEN_VERSIONTEXT "Version 1.1 +R "__DATE__" ("VER_ID")"
+//#else
+//#define HEXEN_VERSIONTEXT "Version 1.1 "__DATE__" ("VER_ID")"
+//#endif
+#define HEXEN_VERSIONTEXT ((gamemode == shareware) ? \
+                           "DEMO 10 16 95" : \
+                           "VERSION 1.1 MAR 22 1996 (BCP)")
 
 // all exterior data is defined here
 #include "xddefs.h"
--- a/src/i_oplmusic.c
+++ b/src/i_oplmusic.c
@@ -85,6 +85,7 @@
     // Volume level
 
     int volume;
+    int volume_base;
 
     // Pan
 
@@ -311,6 +312,7 @@
 static boolean music_initialized = false;
 
 //static boolean musicpaused = false;
+static int start_music_volume;
 static int current_music_volume;
 
 // GENMIDI lump instrument data:
@@ -572,8 +574,7 @@
 
     // Multiply note volume and channel volume to get the actual volume.
 
-    midi_volume = 2 * (volume_mapping_table[(voice->channel->volume
-                  * current_music_volume) / 127] + 1);
+    midi_volume = 2 * (volume_mapping_table[voice->channel->volume] + 1);
 
     full_volume = (volume_mapping_table[voice->note_volume] * midi_volume)
                 >> 9;
@@ -645,12 +646,20 @@
     }
 }
 
+static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume,
+                             boolean clip_start);
+
 // Set music volume (0 - 127)
 
 static void I_OPL_SetMusicVolume(int volume)
 {
-    unsigned int i;
+    unsigned int i, j;
 
+    if (current_music_volume == volume)
+    {
+        return;
+    }
+
     // Internal state variable.
 
     current_music_volume = volume;
@@ -657,11 +666,19 @@
 
     // Update the volume of all voices.
 
-    for (i = 0; i < num_opl_voices; ++i)
+    for (i = 0; i < num_tracks; ++i)
     {
-        if (voices[i].channel != NULL)
+        for (j = 0; j < MIDI_CHANNELS_PER_TRACK; ++j)
         {
-            SetVoiceVolume(&voices[i], voices[i].note_volume);
+            if (j == 15)
+            {
+                SetChannelVolume(&tracks[i].channels[j], volume, false);
+            }
+            else
+            {
+                SetChannelVolume(&tracks[i].channels[j],
+                                 tracks[i].channels[j].volume_base, false);
+            }
         }
     }
 }
@@ -1117,10 +1134,23 @@
     // channel, and change the instrument.
 }
 
-static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume)
+static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume,
+                             boolean clip_start)
 {
     unsigned int i;
 
+    channel->volume_base = volume;
+
+    if (volume > current_music_volume)
+    {
+        volume = current_music_volume;
+    }
+
+    if (clip_start && volume > start_music_volume)
+    {
+        volume = start_music_volume;
+    }
+
     channel->volume = volume;
 
     // Update all voices that this channel is using.
@@ -1232,7 +1262,7 @@
     switch (controller)
     {
         case MIDI_CONTROLLER_MAIN_VOLUME:
-            SetChannelVolume(channel, param);
+            SetChannelVolume(channel, param, true);
             break;
 
         case MIDI_CONTROLLER_PAN:
@@ -1370,19 +1400,26 @@
 }
 
 static void ScheduleTrack(opl_track_data_t *track);
+static void InitChannel(opl_track_data_t *track, opl_channel_data_t *channel);
 
 // Restart a song from the beginning.
 
 static void RestartSong(void *unused)
 {
-    unsigned int i;
+    unsigned int i, j;
 
     running_tracks = num_tracks;
 
+    start_music_volume = current_music_volume;
+
     for (i = 0; i < num_tracks; ++i)
     {
         MIDI_RestartIterator(tracks[i].iter);
         ScheduleTrack(&tracks[i]);
+        for (j = 0; j < MIDI_CHANNELS_PER_TRACK; ++j)
+        {
+            InitChannel(&tracks[i], &tracks[i].channels[j]);
+        }
     }
 }
 
@@ -1453,7 +1490,12 @@
     // TODO: Work out sensible defaults?
 
     channel->instrument = &main_instrs[0];
-    channel->volume = 127;
+    channel->volume = current_music_volume;
+    channel->volume_base = 100;
+    if (channel->volume > channel->volume_base)
+    {
+        channel->volume = channel->volume_base;
+    }
     channel->pan = 0x30;
     channel->bend = 0;
 }
@@ -1506,6 +1548,8 @@
     // TODO: this is wrong
 
     us_per_beat = 500 * 1000;
+
+    start_music_volume = current_music_volume;
 
     for (i = 0; i < num_tracks; ++i)
     {
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -44,6 +44,7 @@
 #include "m_config.h"
 #include "m_misc.h"
 #include "tables.h"
+#include "v_diskicon.h"
 #include "v_video.h"
 #include "w_wad.h"
 #include "z_zone.h"
@@ -92,11 +93,8 @@
     '{', '|', '}', '~', 127
 };
 
-
-#define LOADING_DISK_W 16
-#define LOADING_DISK_H 16
-
 #if 0 // obsolete software scaling routines
+
 // Non aspect ratio-corrected modes (direct multiples of 320x200)
 
 static screen_mode_t *screen_modes[] = {
@@ -193,6 +191,20 @@
 
 int png_screenshots = 0;
 
+// Display disk activity indicator.
+
+int show_diskicon = 1;
+
+// Only display the disk icon if more then this much bytes have been read
+// during the previous tic.
+
+static const int diskicon_threshold = 20*1024;
+int diskicon_readbytes = 0;
+
+// if true, I_VideoBuffer is screen->pixels
+
+static boolean native_surface;
+
 // Screen width and height, from configuration file.
 
 int screen_width = SCREENWIDTH;
@@ -383,57 +395,6 @@
     }
 }
 
-void I_EnableLoadingDisk(void)
-{
-    patch_t *disk;
-    byte *tmpbuf;
-    char *disk_name;
-    int y;
-
-    if (!strcmp(SDL_GetCurrentVideoDriver(), "Quartz"))
-    {
-        // MacOS Quartz gives us pageflipped graphics that screw up the 
-        // display when we use the loading disk.  Disable it.
-        // This is a gross hack.
-        // SDL2-TODO: Check this is still needed.
-
-        return;
-    }
-
-    if (M_CheckParm("-cdrom") > 0)
-        disk_name = DEH_String("STCDROM");
-    else
-        disk_name = DEH_String("STDISK");
-
-    disk = W_CacheLumpName(disk_name, PU_STATIC);
-
-    // Draw the patch into a temporary buffer
-
-    tmpbuf = Z_Malloc(SCREENWIDTH * (disk->height + 1), PU_STATIC, NULL);
-    V_UseBuffer(tmpbuf);
-
-    // Draw the disk to the screen:
-
-    V_DrawPatch(0, 0, disk);
-
-    disk_image = Z_Malloc(LOADING_DISK_W * LOADING_DISK_H, PU_STATIC, NULL);
-    saved_background = Z_Malloc(LOADING_DISK_W * LOADING_DISK_H, PU_STATIC, NULL);
-
-    for (y=0; y<LOADING_DISK_H; ++y) 
-    {
-        memcpy(disk_image + LOADING_DISK_W * y,
-               tmpbuf + SCREENWIDTH * y,
-               LOADING_DISK_W);
-    }
-
-    // All done - free the screen buffer and restore the normal 
-    // video buffer.
-
-    W_ReleaseLumpName(disk_name);
-    V_RestoreBuffer();
-    Z_Free(tmpbuf);
-}
-
 //
 // Translates the SDL key
 //
@@ -935,94 +896,6 @@
 }
 #endif
 
-// TODO: needed for I_BeginRead() and I_EndRead(),
-// but let's forget about this for a while
-/*
-static void UpdateRect(int x1, int y1, int x2, int y2)
-{
-    SDL_Rect update_rect;
-    int x1_scaled, x2_scaled, y1_scaled, y2_scaled;
-
-    // Do stretching and blitting
-
-    if (BlitArea(x1, y1, x2, y2))
-    {
-        // Update the area
-
-        x1_scaled = (x1 * screen_mode->width) / SCREENWIDTH;
-        y1_scaled = (y1 * screen_mode->height) / SCREENHEIGHT;
-        x2_scaled = (x2 * screen_mode->width) / SCREENWIDTH;
-        y2_scaled = (y2 * screen_mode->height) / SCREENHEIGHT;
-
-        update_rect.x = x1_scaled;
-        update_rect.y = y1_scaled;
-        update_rect.x = x2_scaled - x1_scaled;
-        update_rect.y = y2_scaled - y1_scaled;
-
-        SDL_UpdateWindowSurfaceRects(screen, &update_rect, 1);
-    }
-}
-*/
-
-// TODO: let's forget about this for a while
-void I_BeginRead(void)
-{
-/*
-    byte *screenloc = I_VideoBuffer
-                    + (SCREENHEIGHT - LOADING_DISK_H) * SCREENWIDTH
-                    + (SCREENWIDTH - LOADING_DISK_W);
-    int y;
-
-    if (!initialized || disk_image == NULL)
-        return;
-
-    // save background and copy the disk image in
-
-    for (y=0; y<LOADING_DISK_H; ++y)
-    {
-        memcpy(saved_background + y * LOADING_DISK_W,
-               screenloc,
-               LOADING_DISK_W);
-        memcpy(screenloc,
-               disk_image + y * LOADING_DISK_W,
-               LOADING_DISK_W);
-
-        screenloc += SCREENWIDTH;
-    }
-
-    UpdateRect(SCREENWIDTH - LOADING_DISK_W, SCREENHEIGHT - LOADING_DISK_H,
-               SCREENWIDTH, SCREENHEIGHT);
-*/
-}
-
-// TODO: let's forget about this for a while
-void I_EndRead(void)
-{
-/*
-    byte *screenloc = I_VideoBuffer
-                    + (SCREENHEIGHT - LOADING_DISK_H) * SCREENWIDTH
-                    + (SCREENWIDTH - LOADING_DISK_W);
-    int y;
-
-    if (!initialized || disk_image == NULL)
-        return;
-
-    // save background and copy the disk image in
-
-    for (y=0; y<LOADING_DISK_H; ++y)
-    {
-        memcpy(screenloc,
-               saved_background + y * LOADING_DISK_W,
-               LOADING_DISK_W);
-
-        screenloc += SCREENWIDTH;
-    }
-
-    UpdateRect(SCREENWIDTH - LOADING_DISK_W, SCREENHEIGHT - LOADING_DISK_H,
-               SCREENWIDTH, SCREENHEIGHT);
-*/
-}
-
 static void CreateUpscaledTexture(int w, int h)
 {
     const int actualheight = aspect_ratio_correct ?
@@ -1224,7 +1097,7 @@
 //
 void I_ReadScreen (byte* scr)
 {
-    memcpy(scr, I_VideoBuffer, SCREENWIDTH*SCREENHEIGHT);
+    memcpy(scr, I_VideoBuffer, SCREENWIDTH*SCREENHEIGHT*sizeof(*scr));
 }
 
 
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -110,7 +110,6 @@
 void I_ReadScreen (byte* scr);
 
 void I_BeginRead (void);
-void I_EndRead (void);
 
 void I_SetWindowTitle(char *title);
 
@@ -135,7 +134,7 @@
 
 // Enable the loading disk image displayed when reading from disk.
 
-void I_EnableLoadingDisk(void);
+void I_EnableLoadingDisk(int xoffs, int yoffs);
 
 extern char *video_driver;
 extern boolean screenvisible;
@@ -151,5 +150,8 @@
 extern int screen_height;
 extern int fullscreen;
 extern int aspect_ratio_correct;
+
+extern int show_diskicon;
+extern int diskicon_readbytes;
 
 #endif
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -840,6 +840,15 @@
     CONFIG_VARIABLE_INT(show_endoom),
 
     //!
+    // @game doom strife
+    //
+    // If non-zero, a disk activity indicator is displayed when data is read
+    // from disk. If zero, the disk activity indicator is not displayed.
+    //
+
+    CONFIG_VARIABLE_INT(show_diskicon),
+
+    //!
     // If non-zero, save screenshots in PNG format.
     //
 
--- a/src/m_fixed.c
+++ b/src/m_fixed.c
@@ -54,7 +54,7 @@
     {
 	int64_t result;
 
-	result = ((int64_t) a << 16) / b;
+	result = ((int64_t) a << FRACBITS) / b;
 
 	return (fixed_t) result;
     }
--- a/src/setup/Makefile.am
+++ b/src/setup/Makefile.am
@@ -39,7 +39,7 @@
 if HAVE_PYTHON
 
 setup_icon.c : $(top_builddir)/data/setup.png
-	$(top_builddir)/data/convert-icon $^ $@
+	$(top_builddir)/data/convert-icon $(top_builddir)/data/setup.png $@
 
 endif
 
--- a/src/setup/display.c
+++ b/src/setup/display.c
@@ -84,6 +84,7 @@
 
 int graphical_startup = 1;
 int show_endoom = 1;
+int show_diskicon = 1;
 int png_screenshots = 0;
 
 // These are the last screen width/height values that were chosen by the
@@ -355,6 +356,13 @@
                                       &show_endoom));
     }
 
+    if (gamemission == doom || gamemission == strife)
+    {
+        TXT_AddWidget(window,
+                      TXT_NewCheckBox("Show disk activity indicator",
+                                      &show_diskicon));
+    }
+
 #ifdef HAVE_LIBPNG
     TXT_AddWidget(window,
                   TXT_NewCheckBox("Save screenshots in PNG format",
@@ -485,6 +493,11 @@
      || gamemission == strife)
     {
         M_BindIntVariable("show_endoom",               &show_endoom);
+    }
+
+    if (gamemission == doom || gamemission == strife)
+    {
+        M_BindIntVariable("show_diskicon",             &show_diskicon);
     }
 
     if (gamemission == heretic || gamemission == hexen || gamemission == strife)
--- a/src/strife/d_main.c
+++ b/src/strife/d_main.c
@@ -40,6 +40,7 @@
 #include "w_main.h"
 #include "w_wad.h"
 #include "s_sound.h"
+#include "v_diskicon.h"
 #include "v_video.h"
 
 #include "f_finale.h"
@@ -300,7 +301,7 @@
     // see if the border needs to be updated to the screen
     if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != 320)
     {
-        if (menuactive || menuactivestate || !viewactivestate)
+        if (menuactive || menuactivestate || !viewactivestate || disk_indicator == disk_dirty)
         {
             borderdrawcount = 3;
             popupactivestate = false;
@@ -441,6 +442,7 @@
     M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit);
     M_BindIntVariable("vanilla_demo_limit",     &vanilla_demo_limit);
     M_BindIntVariable("show_endoom",            &show_endoom);
+    M_BindIntVariable("show_diskicon",          &show_diskicon);
     M_BindIntVariable("graphical_startup",      &graphical_startup);
 
     M_BindStringVariable("back_flat",           &back_flat);
@@ -509,7 +511,7 @@
         I_InitGraphics();
     }
 
-    I_EnableLoadingDisk();
+    V_EnableLoadingDisk(SCREENWIDTH - LOADING_DISK_W, 0);
     I_SetGrabMouseCallback(D_GrabMouseCallback);
 
     V_RestoreBuffer();
--- a/src/tables.c
+++ b/src/tables.c
@@ -61,7 +61,7 @@
     }
 }
 
-const int finetangent[4096] =
+const fixed_t finetangent[4096] =
 {
     -170910304,-56965752,-34178904,-24413316,-18988036,-15535599,-13145455,-11392683,
     -10052327,-8994149,-8137527,-7429880,-6835455,-6329090,-5892567,-5512368,
@@ -578,7 +578,7 @@
 };
 
 
-const int finesine[10240] =
+const fixed_t finesine[10240] =
 {
     25,75,125,175,226,276,326,376,
     427,477,527,578,628,678,728,779,
--- /dev/null
+++ b/src/v_diskicon.c
@@ -1,0 +1,61 @@
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005-2014 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.
+//
+// DESCRIPTION:
+//	Disk load indicator.
+//
+
+#include "doomtype.h"
+#include "deh_str.h"
+#include "m_argv.h"
+#include "v_video.h"
+#include "w_wad.h"
+#include "z_zone.h"
+
+#include "v_diskicon.h"
+
+// disk image patch (either STDISK or STCDROM)
+
+static patch_t *disk;
+
+static int loading_disk_xoffs = 0;
+static int loading_disk_yoffs = 0;
+
+disk_indicator_e disk_indicator = disk_off;
+
+void V_EnableLoadingDisk(int xoffs, int yoffs)
+{
+    char *disk_name;
+
+    loading_disk_xoffs = xoffs;
+    loading_disk_yoffs = yoffs;
+
+    if (M_CheckParm("-cdrom") > 0)
+        disk_name = DEH_String("STCDROM");
+    else
+        disk_name = DEH_String("STDISK");
+
+    disk = W_CacheLumpName(disk_name, PU_STATIC);
+}
+
+void V_BeginRead(void)
+{
+    if (disk == NULL)
+        return;
+
+    // Draw the disk to the screen
+    V_DrawPatch(loading_disk_xoffs, loading_disk_yoffs, disk);
+
+    disk_indicator = disk_dirty;
+}
--- /dev/null
+++ b/src/v_diskicon.h
@@ -1,0 +1,39 @@
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005-2014 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.
+//
+// DESCRIPTION:
+//	Disk load indicator.
+//
+
+#ifndef __V_DISKICON__
+#define __V_DISKICON__
+
+// Dimensions of the flashing "loading" disk icon
+
+#define LOADING_DISK_W 16
+#define LOADING_DISK_H 16
+
+typedef enum
+{
+    disk_off,
+    disk_on,
+    disk_dirty
+} disk_indicator_e;
+
+extern disk_indicator_e disk_indicator;
+
+extern void V_EnableLoadingDisk (int xoffs, int yoffs);
+extern void V_BeginRead (void);
+
+#endif
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -110,7 +110,7 @@
 
     for ( ; height>0 ; height--) 
     { 
-        memcpy(dest, src, width); 
+        memcpy(dest, src, width * sizeof(*dest));
         src += SCREENWIDTH; 
         dest += SCREENWIDTH; 
     } 
@@ -520,7 +520,7 @@
 
     while (height--) 
     { 
-	memcpy (dest, src, width); 
+	memcpy (dest, src, width * sizeof(*dest));
 	src += width; 
 	dest += SCREENWIDTH; 
     } 
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -30,6 +30,7 @@
 #include "i_system.h"
 #include "i_video.h"
 #include "m_misc.h"
+#include "v_diskicon.h"
 #include "z_zone.h"
 
 #include "w_wad.h"
@@ -347,8 +348,10 @@
 
     l = lumpinfo[lump];
 
-    I_BeginRead();
+    diskicon_readbytes += l->size;
 
+    disk_indicator = disk_on;
+
     c = W_Read(l->wad_file, l->position, dest, l->size);
 
     if (c < l->size)
@@ -356,8 +359,6 @@
         I_Error("W_ReadLump: only read %i of %i on lump %i",
                 c, l->size, lump);
     }
-
-    I_EndRead();
 }
 
 
--- a/textscreen/txt_table.c
+++ b/textscreen/txt_table.c
@@ -149,11 +149,8 @@
                                       unsigned int *row_heights,
                                       unsigned int *w, unsigned int *h)
 {
-    txt_widget_t *widget;
     int cell_w, cell_h;
     int x1, y1;
-
-    widget = table->widgets[y * table->columns + x];
 
     // Find which cells this widget occupies.
     CellOverflowedSize(table, x, y, &cell_w, &cell_h);