shithub: choc

Download patch

ref: afa0c4c7979c1508605d0e79487f299cd03adda6
parent: 095bc1110b3c11fbf2e17bfd51bf78909fe34662
parent: 2c6e7b2f10c32ca0406ca6753e7701d83e6dea8f
author: Simon Howard <[email protected]>
date: Sat Nov 21 11:36:46 EST 2009

Merge from trunk.

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

--- a/Makefile.am
+++ b/Makefile.am
@@ -53,6 +53,7 @@
 
 docdir=$(prefix)/share/doc/@PACKAGE@
 SUBDIRS=wince textscreen pcsound src man 
+DIST_SUBDIRS=pkg $(SUBDIRS)
 
 if HAVE_PYTHON
 
--- /dev/null
+++ b/acinclude.m4
@@ -1,0 +1,36 @@
+
+dnl
+dnl SDL workaround autoconf macros, by Simon Howard.
+dnl I release the contents of this file to the public domain.
+dnl
+
+dnl Macro to check if autoconf's compile tests have been broken by
+dnl SDL.  Tries to build the simplest possible program, and if it
+dnl fails, calls the given block.
+
+AC_DEFUN([AC_CHECK_SDL_BREAKAGE], [
+    AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [], [
+        $1
+    ])
+])
+
+dnl Macro to work around SDL redefining main.  The provided block
+dnl is run with main #defined to SDL_main via a compiler switch
+dnl if autoconf tests are found to be broken.
+
+AC_DEFUN([AC_SDL_MAIN_WORKAROUND], [
+    sdl_workaround_saved_CFLAGS="$CFLAGS"
+
+    AC_CHECK_SDL_BREAKAGE([
+        CFLAGS="$CFLAGS -Dmain=SDL_main"
+    ])
+
+    AC_CHECK_SDL_BREAKAGE([
+        AC_MSG_ERROR([Autoconf checks broken by SDL, and can't figure out how to fix them.])
+    ])
+
+    $1
+
+    CFLAGS="$sdl_workaround_saved_CFLAGS"
+])
+
--- a/configure.in
+++ b/configure.in
@@ -39,20 +39,43 @@
 CFLAGS="$CFLAGS $SDL_CFLAGS"
 LDFLAGS="$LDFLAGS $SDL_LIBS"
 
-AC_CHECK_LIB(SDL_mixer,Mix_LoadMUS,[
-    SDLMIXER_LIBS="$SDLMIXER_LIBS -lSDL_mixer"
-],[
-    echo "*** Could not find SDL_mixer.  Please install it."
-    exit -1
-])
+# On some platforms, SDL renames main() to SDL_main() using a #define,
+# so that its own main, stored in the SDLmain library, can be run first.
+# Unfortunately, this causes problems for autoconf, which builds
+# test programs to probe the system.  All library/header/symbol checks
+# must be run in this block, that performs a workaround for the problem.
 
-AC_CHECK_LIB(SDL_net,SDLNet_UDP_Send,[
-    SDLNET_LIBS="$SDLNET_LIBS -lSDL_net"
-],[
-    echo "*** Could not find SDL_net.  Please install it."
-    exit -1
+AC_SDL_MAIN_WORKAROUND([
+
+    # Check for SDL_mixer.
+
+    AC_CHECK_LIB(SDL_mixer,Mix_LoadMUS,[
+        SDLMIXER_LIBS="$SDLMIXER_LIBS -lSDL_mixer"
+    ],[
+        echo "*** Could not find SDL_mixer.  Please install it."
+        exit -1
+    ])
+
+    # Check for SDL_net.
+
+    AC_CHECK_LIB(SDL_net,SDLNet_UDP_Send,[
+        SDLNET_LIBS="$SDLNET_LIBS -lSDL_net"
+    ],[
+        echo "*** Could not find SDL_net.  Please install it."
+        exit -1
+    ])
+
+    # Check for libsamplerate.
+
+    AC_CHECK_LIB(samplerate, src_new)
+
+    AC_CHECK_HEADERS([linux/kd.h dev/isa/spkrio.h dev/speaker/speaker.h])
+    AC_CHECK_FUNCS(mmap sched_setaffinity)
 ])
 
+AC_CHECK_TOOL(WINDRES, windres, )
+AC_CHECK_TOOL(STRIP, strip, )
+
 # Windows CE build?
 
 WINDOWS_CE=false
@@ -66,14 +89,6 @@
         ;;
 esac
 
-AC_CHECK_HEADERS([linux/kd.h dev/isa/spkrio.h dev/speaker/speaker.h])
-AC_CHECK_FUNCS(mmap sched_setaffinity)
-
-# DWF 2008-02-10:  FIXME
-AC_CHECK_LIB(samplerate, src_new)
-
-AC_CHECK_TOOL(WINDRES, windres, )
-
 AM_CONDITIONAL(WINDOWS_CE, $WINDOWS_CE)
 AM_CONDITIONAL(HAVE_WINDRES, test "$WINDRES" != "")
 AM_CONDITIONAL(HAVE_PYTHON, $HAVE_PYTHON)
@@ -120,7 +135,9 @@
 src/hexen/Makefile
 src/setup/Makefile
 pcsound/Makefile
-pkg/wince/Makefile
+pkg/Makefile
+pkg/wince/GNUmakefile
+pkg/win32/GNUmakefile
 src/resource.rc
 src/setup-res.rc
 src/setup/setup-manifest.xml
--- a/pcsound/pcsound.c
+++ b/pcsound/pcsound.c
@@ -109,7 +109,7 @@
                 }
                 else
                 {
-                    printf("Failed to initialise PC sound driver: %s\n",
+                    printf("Failed to initialize PC sound driver: %s\n",
                            drivers[i]->name);
                     break;
                 }
--- a/pcsound/pcsound_sdl.c
+++ b/pcsound/pcsound_sdl.c
@@ -35,10 +35,10 @@
 #define MAX_SOUND_SLICE_TIME 70 /* ms */
 #define SQUARE_WAVE_AMP 0x2000
 
-// If true, we initialised SDL and have the responsibility to shut it 
+// If true, we initialized SDL and have the responsibility to shut it 
 // down
 
-static int sdl_was_initialised = 0;
+static int sdl_was_initialized = 0;
 
 // Callback function to invoke when we want new sound data
 
@@ -146,7 +146,7 @@
     }
 }
 
-static int SDLIsInitialised(void)
+static int SDLIsInitialized(void)
 {
     int freq, channels;
     Uint16 format;
@@ -156,11 +156,11 @@
 
 static void PCSound_SDL_Shutdown(void)
 {
-    if (sdl_was_initialised)
+    if (sdl_was_initialized)
     {
         Mix_CloseAudio();
         SDL_QuitSubSystem(SDL_INIT_AUDIO);
-        sdl_was_initialised = 0;
+        sdl_was_initialized = 0;
     }
 }
 
@@ -196,9 +196,9 @@
     int slicesize;
 
     // Check if SDL_mixer has been opened already
-    // If not, we must initialise it now
+    // If not, we must initialize it now
 
-    if (!SDLIsInitialised())
+    if (!SDLIsInitialized())
     {
         if (SDL_Init(SDL_INIT_AUDIO) < 0)
         {
@@ -210,7 +210,7 @@
 
         if (Mix_OpenAudio(pcsound_sample_rate, AUDIO_S16SYS, 2, slicesize) < 0)
         {
-            fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError());
+            fprintf(stderr, "Error initializing SDL_mixer: %s\n", Mix_GetError());
 
             SDL_QuitSubSystem(SDL_INIT_AUDIO);
             return 0;
@@ -221,7 +221,7 @@
         // When this module shuts down, it has the responsibility to 
         // shut down SDL.
 
-        sdl_was_initialised = 1;
+        sdl_was_initialized = 1;
     }
 
     // Get the mixer frequency, format and number of channels.
--- /dev/null
+++ b/pkg/Makefile.am
@@ -1,0 +1,3 @@
+
+DIST_SUBDIRS=wince win32
+
--- /dev/null
+++ b/pkg/win32/GNUmakefile.am
@@ -1,0 +1,36 @@
+
+TOPLEVEL=../..
+
+EXE_FILES=$(TOPLEVEL)/src/@[email protected]        \
+          $(TOPLEVEL)/src/@[email protected]    \
+          $(TOPLEVEL)/src/@[email protected]      \
+          $(TOPLEVEL)/src/@[email protected]     \
+          $(TOPLEVEL)/src/@[email protected]
+
+DLL_FILES=$(TOPLEVEL)/src/SDL.dll                      \
+          $(TOPLEVEL)/src/SDL_mixer.dll                \
+          $(TOPLEVEL)/src/SDL_net.dll
+
+DOC_FILES=README       \
+          COPYING      \
+          ChangeLog    \
+          NEWS         \
+          BUGS         \
+          CMDLINE      \
+          TODO
+
+noinst_DATA=@PACKAGE_TARNAME@-@[email protected]
+
+@PACKAGE_TARNAME@-@[email protected] : staging
+	zip -j -r $@ staging/
+
+staging: $(EXE_FILES) $(DLL_FILES) $(patsubst %,../../%,$(DOC_FILES))
+	rm -rf staging
+	mkdir staging
+	cp $(EXE_FILES) $(DLL_FILES) staging/
+	$(STRIP) staging/*.exe
+	for f in $(DOC_FILES); do                    \
+		cp $(TOPLEVEL)/$$f staging/$$f.txt;  \
+		unix2dos staging/$$f.txt;            \
+	done
+
--- /dev/null
+++ b/pkg/win32/README
@@ -1,0 +1,4 @@
+
+Makefile to build Windows packages.  Requires zip and unix2dos cygwin
+packages to be installed.
+
--- /dev/null
+++ b/pkg/wince/GNUmakefile.am
@@ -1,0 +1,30 @@
+
+# Doom:
+
+DOOM_CAB=chocolate-doom-@[email protected]
+DOOM_CFG=doom-cab.cfg
+DOOM_DEPS=$(shell ./wince-cabgen -d $(DOOM_CFG))
+
+$(DOOM_CAB) : $(DOOM_CFG) $(DOOM_DEPS)
+	./wince-cabgen $< $@
+
+# Heretic:
+
+HERETIC_CAB=chocolate-heretic-@[email protected]
+HERETIC_CFG=heretic-cab.cfg
+HERETIC_DEPS=$(shell ./wince-cabgen -d $(HERETIC_CFG))
+
+$(HERETIC_CAB) : $(HERETIC_CFG) $(HERETIC_DEPS)
+	./wince-cabgen $< $@
+
+# Hexen:
+
+HEXEN_CAB=chocolate-hexen-@[email protected]
+HEXEN_CFG=hexen-cab.cfg
+HEXEN_DEPS=$(shell ./wince-cabgen -d $(HEXEN_CFG))
+
+$(HEXEN_CAB) : $(HEXEN_CFG) $(HEXEN_DEPS)
+	./wince-cabgen $< $@
+
+noinst_DATA = $(DOOM_CAB) $(HERETIC_CAB) $(HEXEN_CAB)
+
--- a/pkg/wince/Makefile.am
+++ /dev/null
@@ -1,30 +1,0 @@
-
-# Doom:
-
-DOOM_CAB=chocolate-doom-@[email protected]
-DOOM_CFG=doom-cab.cfg
-DOOM_DEPS=$(shell ./wince-cabgen -d $(DOOM_CFG))
-
-$(DOOM_CAB) : $(DOOM_CFG) $(DOOM_DEPS)
-	./wince-cabgen $< $@
-
-# Heretic:
-
-HERETIC_CAB=chocolate-heretic-@[email protected]
-HERETIC_CFG=heretic-cab.cfg
-HERETIC_DEPS=$(shell ./wince-cabgen -d $(HERETIC_CFG))
-
-$(HERETIC_CAB) : $(HERETIC_CFG) $(HERETIC_DEPS)
-	./wince-cabgen $< $@
-
-# Hexen:
-
-HEXEN_CAB=chocolate-hexen-@[email protected]
-HEXEN_CFG=hexen-cab.cfg
-HEXEN_DEPS=$(shell ./wince-cabgen -d $(HEXEN_CFG))
-
-$(HEXEN_CAB) : $(HEXEN_CFG) $(HEXEN_DEPS)
-	./wince-cabgen $< $@
-
-noinst_DATA = $(DOOM_CAB) $(HERETIC_CAB) $(HEXEN_CAB)
-
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -19,7 +19,7 @@
 // 02111-1307, USA.
 //
 // DESCRIPTION:
-//     Search for and locate an IWAD file, and initialise according
+//     Search for and locate an IWAD file, and initialize according
 //     to the IWAD type.
 //
 //-----------------------------------------------------------------------------
--- a/src/d_iwad.h
+++ b/src/d_iwad.h
@@ -19,7 +19,7 @@
 // 02111-1307, USA.
 //
 // DESCRIPTION:
-//     Find IWAD and initialise according to IWAD type.
+//     Find IWAD and initialize according to IWAD type.
 //
 //-----------------------------------------------------------------------------
 
--- a/src/deh_str.c
+++ b/src/deh_str.c
@@ -66,7 +66,7 @@
 {
     int entry;
 
-    // Fallback if we have not initialised the hash table yet
+    // Fallback if we have not initialized the hash table yet
 
     if (hash_table_length < 0)
 	return s;
@@ -164,7 +164,7 @@
 {
     deh_substitution_t *sub;
 
-    // Initialise the hash table if this is the first time
+    // Initialize the hash table if this is the first time
 
     if (hash_table_length < 0)
     {
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -901,7 +901,7 @@
     { NULL,                  NULL,         0},
 };
 
-// Initialise the game version
+// Initialize the game version
 
 static void InitGameVersion(void)
 {
@@ -1701,7 +1701,7 @@
     I_InitJoystick();
 
 #ifdef FEATURE_MULTIPLAYER
-    printf ("NET_Init: Initialise network subsystem.\n");
+    printf ("NET_Init: Init network subsystem.\n");
     NET_Init ();
 #endif
 
--- a/src/doom/d_net.h
+++ b/src/doom/d_net.h
@@ -42,7 +42,7 @@
 //? how many ticks to run?
 void TryRunTics (void);
 
-// Called at start of game loop to initialise timers
+// Called at start of game loop to initialize timers
 void D_StartGameLoop(void);
 
 extern boolean drone;
--- a/src/doom/deh_defs.h
+++ b/src/doom/deh_defs.h
@@ -41,7 +41,7 @@
 {
     char *name;
 
-    // Called on startup to initialise code
+    // Called on startup to initialize code
 
     deh_section_init_t init;
     
--- a/src/doom/deh_main.c
+++ b/src/doom/deh_main.c
@@ -110,7 +110,7 @@
 
 // Called on startup to call the Init functions
 
-static void InitialiseSections(void)
+static void InitializeSections(void)
 {
     unsigned int i;
 
@@ -385,7 +385,7 @@
     char *filename;
     int p;
 
-    InitialiseSections();
+    InitializeSections();
 
     //!
     // @category mod
--- a/src/doom/deh_ptr.c
+++ b/src/doom/deh_ptr.c
@@ -56,7 +56,7 @@
 {
     int i;
     
-    // Initialise list of dehacked pointers
+    // Initialize list of dehacked pointers
 
     for (i=0; i<NUMSTATES; ++i)
         codeptrs[i] = states[i].action;
--- a/src/doom/p_doors.c
+++ b/src/doom/p_doors.c
@@ -420,8 +420,41 @@
 	    {
 		if (!thing->player)
 		    return;		// JDC: bad guys never close doors
-		
-		door->direction = -1;	// start going down immediately
+
+                // When is a door not a door?
+                // In Vanilla, door->direction is set, even though
+                // "specialdata" might not actually point at a door.
+
+                if (door->thinker.function.acp1 == (actionf_p1) T_VerticalDoor)
+                {
+                    door->direction = -1;	// start going down immediately
+                }
+                else if (door->thinker.function.acp1 == (actionf_p1) T_PlatRaise)
+                {
+                    // Erm, this is a plat, not a door.
+                    // This notably causes a problem in ep1-0500.lmp where
+                    // a plat and a door are cross-referenced; the door
+                    // doesn't open on 64-bit.
+                    // The direction field in vldoor_t corresponds to the wait
+                    // field in plat_t.  Let's set that to -1 instead.
+
+                    plat_t *plat;
+
+                    plat = (plat_t *) door;
+                    plat->wait = -1;
+                }
+                else
+                {
+                    // This isn't a door OR a plat.  Now we're in trouble.
+
+                    fprintf(stderr, "EV_VerticalDoor: Tried to close "
+                                    "something that wasn't a door.\n");
+
+                    // Try closing it anyway. At least it will work on 32-bit
+                    // machines.
+
+                    door->direction = -1;
+                }
 	    }
 	    return;
 	}
--- a/src/doom/p_map.c
+++ b/src/doom/p_map.c
@@ -36,6 +36,7 @@
 
 #include "doomdef.h"
 #include "m_argv.h"
+#include "m_misc.h"
 #include "p_local.h"
 
 #include "s_sound.h"
@@ -1412,7 +1413,7 @@
         
         if (p > 0)
         {
-            baseaddr = atoi(myargv[p+1]);
+            M_StrToInt(myargv[p+1], (int *) &baseaddr);
         }
         else
         {
--- a/src/doom/p_spec.c
+++ b/src/doom/p_spec.c
@@ -38,6 +38,7 @@
 #include "i_system.h"
 #include "z_zone.h"
 #include "m_argv.h"
+#include "m_misc.h"
 #include "m_random.h"
 #include "w_wad.h"
 
@@ -1169,11 +1170,95 @@
 		memset(&buttonlist[i],0,sizeof(button_t));
 	    }
 	}
-	
 }
 
 
+//
+// Donut overrun emulation
+//
+// Derived from the code from PrBoom+.  Thanks go to Andrey Budko (entryway)
+// as usual :-)
+//
 
+#define DONUT_FLOORHEIGHT_DEFAULT 0x00000000
+#define DONUT_FLOORPIC_DEFAULT 0x16
+
+static void DonutOverrun(fixed_t *s3_floorheight, short *s3_floorpic,
+                         line_t *line, sector_t *pillar_sector)
+{
+    static int first = 1;
+    static int tmp_s3_floorheight;
+    static int tmp_s3_floorpic;
+
+    extern int numflats;
+
+    if (first)
+    {
+        int p;
+
+        // This is the first time we have had an overrun.
+        first = 0;
+
+        // Default values
+        tmp_s3_floorheight = DONUT_FLOORHEIGHT_DEFAULT;
+        tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT;
+
+        //!
+        // @category compat
+        // @arg <x> <y>
+        //
+        // Use the specified magic values when emulating behavior caused
+        // by memory overruns from improperly constructed donuts.
+        // In Vanilla Doom this can differ depending on the operating
+        // system.  The default (if this option is not specified) is to
+        // emulate the behavior when running under Windows 98.
+
+        p = M_CheckParm("-donut");
+
+        if (p > 0 && p < myargc - 2)
+        {
+            // Dump of needed memory: (fixed_t)0000:0000 and (short)0000:0008
+            //
+            // C:\>debug
+            // -d 0:0
+            //
+            // DOS 6.22:
+            // 0000:0000    (57 92 19 00) F4 06 70 00-(16 00)
+            // DOS 7.1:
+            // 0000:0000    (9E 0F C9 00) 65 04 70 00-(16 00)
+            // Win98:
+            // 0000:0000    (00 00 00 00) 65 04 70 00-(16 00)
+            // DOSBox under XP:
+            // 0000:0000    (00 00 00 F1) ?? ?? ?? 00-(07 00)
+
+            M_StrToInt(myargv[p + 1], &tmp_s3_floorheight);
+            M_StrToInt(myargv[p + 2], &tmp_s3_floorpic);
+
+            if (tmp_s3_floorpic >= numflats)
+            {
+                fprintf(stderr,
+                        "DonutOverrun: The second parameter for \"-donut\" "
+                        "switch should be greater than 0 and less than number "
+                        "of flats (%d). Using default value (%d) instead. \n",
+                        numflats, DONUT_FLOORPIC_DEFAULT);
+                tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT;
+            }
+        }
+    }
+
+    /*
+    fprintf(stderr,
+            "Linedef: %d; Sector: %d; "
+            "New floor height: %d; New floor pic: %d\n",
+            line->iLineID, pillar_sector->iSectorID,
+            tmp_s3_floorheight >> 16, tmp_s3_floorpic);
+     */
+
+    *s3_floorheight = (fixed_t) tmp_s3_floorheight;
+    *s3_floorpic = (short) tmp_s3_floorpic;
+}
+
+
 //
 // Special Stuff that can not be categorized
 //
@@ -1186,26 +1271,67 @@
     int			rtn;
     int			i;
     floormove_t*	floor;
-	
+    fixed_t s3_floorheight;
+    short s3_floorpic;
+
     secnum = -1;
     rtn = 0;
     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
     {
 	s1 = &sectors[secnum];
-		
+
 	// ALREADY MOVING?  IF SO, KEEP GOING...
 	if (s1->specialdata)
 	    continue;
-			
+
 	rtn = 1;
 	s2 = getNextSector(s1->lines[0],s1);
-	for (i = 0;i < s2->linecount;i++)
+
+        // Vanilla Doom does not check if the linedef is one sided.  The
+        // game does not crash, but reads invalid memory and causes the
+        // sector floor to move "down" to some unknown height.
+        // DOSbox prints a warning about an invalid memory access.
+        //
+        // I'm not sure exactly what invalid memory is being read.  This
+        // isn't something that should be done, anyway.
+        // Just print a warning and return.
+
+        if (s2 == NULL)
+        {
+            fprintf(stderr,
+                    "EV_DoDonut: linedef had no second sidedef! "
+                    "Unexpected behavior may occur in Vanilla Doom. \n");
+	    break;
+        }
+
+	for (i = 0; i < s2->linecount; i++)
 	{
-	    if ((!s2->lines[i]->flags & ML_TWOSIDED) ||
-		(s2->lines[i]->backsector == s1))
-		continue;
 	    s3 = s2->lines[i]->backsector;
-	    
+
+	    if (s3 == s1)
+		continue;
+
+            if (s3 == NULL)
+            {
+                // e6y
+                // s3 is NULL, so
+                // s3->floorheight is an int at 0000:0000
+                // s3->floorpic is a short at 0000:0008
+                // Trying to emulate
+
+                fprintf(stderr,
+                        "EV_DoDonut: WARNING: emulating buffer overrun due to "
+                        "NULL back sector. "
+                        "Unexpected behavior may occur in Vanilla Doom.\n");
+
+                DonutOverrun(&s3_floorheight, &s3_floorpic, line, s1);
+            }
+            else
+            {
+                s3_floorheight = s3->floorheight;
+                s3_floorpic = s3->floorpic;
+            }
+
 	    //	Spawn rising slime
 	    floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
 	    P_AddThinker (&floor->thinker);
@@ -1216,9 +1342,9 @@
 	    floor->direction = 1;
 	    floor->sector = s2;
 	    floor->speed = FLOORSPEED / 2;
-	    floor->texture = s3->floorpic;
+	    floor->texture = s3_floorpic;
 	    floor->newspecial = 0;
-	    floor->floordestheight = s3->floorheight;
+	    floor->floordestheight = s3_floorheight;
 	    
 	    //	Spawn lowering donut-hole
 	    floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
@@ -1230,7 +1356,7 @@
 	    floor->direction = -1;
 	    floor->sector = s1;
 	    floor->speed = FLOORSPEED / 2;
-	    floor->floordestheight = s3->floorheight;
+	    floor->floordestheight = s3_floorheight;
 	    break;
 	}
     }
--- a/src/doomtype.h
+++ b/src/doomtype.h
@@ -52,7 +52,7 @@
 //
 // The packed attribute forces structures to be packed into the minimum 
 // space necessary.  If this is not done, the compiler may align structure
-// fields differently to optimise memory access, inflating the overall
+// fields differently to optimize memory access, inflating the overall
 // structure size.  It is important to use the packed attribute on certain
 // structures where alignment is important, particularly data read/written
 // to disk.
--- a/src/i_joystick.c
+++ b/src/i_joystick.c
@@ -115,7 +115,7 @@
 
     SDL_JoystickEventState(SDL_ENABLE);
 
-    // Initialised okay!
+    // Initialized okay!
 
     printf("I_InitJoystick: %s\n", SDL_JoystickName(joystick_index));
 }
--- a/src/i_pcsound.c
+++ b/src/i_pcsound.c
@@ -36,7 +36,7 @@
 
 #include "pcsound.h"
 
-static boolean pcs_initialised = false;
+static boolean pcs_initialized = false;
 
 static SDL_mutex *sound_lock;
 static boolean use_sfx_prefix;
@@ -178,7 +178,7 @@
 {
     int result;
 
-    if (!pcs_initialised)
+    if (!pcs_initialized)
     {
         return -1;
     }
@@ -214,7 +214,7 @@
 
 static void I_PCS_StopSound(int handle)
 {
-    if (!pcs_initialised)
+    if (!pcs_initialized)
     {
         return;
     }
@@ -258,7 +258,7 @@
 
 static boolean I_PCS_SoundIsPlaying(int handle)
 {
-    if (!pcs_initialised)
+    if (!pcs_initialized)
     {
         return false;
     }
@@ -279,21 +279,21 @@
 
     PCSound_SetSampleRate(snd_samplerate);
 
-    // Initialise the PC speaker subsystem.
+    // Initialize the PC speaker subsystem.
 
-    pcs_initialised = PCSound_Init(PCSCallbackFunc);
+    pcs_initialized = PCSound_Init(PCSCallbackFunc);
 
-    if (pcs_initialised)
+    if (pcs_initialized)
     {
         sound_lock = SDL_CreateMutex();
     }
 
-    return pcs_initialised;
+    return pcs_initialized;
 }
 
 static void I_PCS_ShutdownSound(void)
 {
-    if (pcs_initialised)
+    if (pcs_initialized)
     {
         PCSound_Shutdown();
     }
--- a/src/i_sdlmusic.c
+++ b/src/i_sdlmusic.c
@@ -43,12 +43,12 @@
 
 #define MAXMIDLENGTH (96 * 1024)
 
-static boolean music_initialised = false;
+static boolean music_initialized = false;
 
-// If this is true, this module initialised SDL sound and has the 
+// If this is true, this module initialized SDL sound and has the 
 // responsibility to shut it down
 
-static boolean sdl_was_initialised = false;
+static boolean sdl_was_initialized = false;
 
 static boolean musicpaused = false;
 static int current_music_volume;
@@ -57,21 +57,21 @@
 
 static void I_SDL_ShutdownMusic(void)
 {    
-    if (music_initialised)
+    if (music_initialized)
     {
         Mix_HaltMusic();
-        music_initialised = false;
+        music_initialized = false;
 
-        if (sdl_was_initialised)
+        if (sdl_was_initialized)
         {
             Mix_CloseAudio();
             SDL_QuitSubSystem(SDL_INIT_AUDIO);
-            sdl_was_initialised = false;
+            sdl_was_initialized = false;
         }
     }
 }
 
-static boolean SDLIsInitialised(void)
+static boolean SDLIsInitialized(void)
 {
     int freq, channels;
     Uint16 format;
@@ -79,25 +79,35 @@
     return Mix_QuerySpec(&freq, &format, &channels) != 0;
 }
 
-// Initialise music subsystem
+// Initialize music subsystem
 
 static boolean I_SDL_InitMusic(void)
-{ 
-    // When trying to run with music enabled on OSX, display
-    // a warning message.
+{
+    // SDL_mixer prior to v1.2.11 has a bug that causes crashes
+    // with MIDI playback.  Print a warning message if we are
+    // using an old version.
 
-#ifdef __APPLE__
-    printf("\n"
-           "                   *** WARNING ***\n"
-           "      Music playback on OSX may cause crashes and\n"
-           "      is disabled by default.\n"
-           "\n");
+#ifdef __MACOSX__
+    {
+        const SDL_version *v = Mix_Linked_Version();
+
+        if (SDL_VERSIONNUM(v->major, v->minor, v->patch)
+          < SDL_VERSIONNUM(1, 2, 11))
+        {
+            printf("\n"
+               "                   *** WARNING ***\n"
+               "      You are using an old version of SDL_mixer.\n"
+               "      Music playback on this version may cause crashes\n"
+               "      under OS X and is disabled by default.\n"
+               "\n");
+        }
+    }
 #endif
-    
-    // If SDL_mixer is not initialised, we have to initialise it 
+
+    // If SDL_mixer is not initialized, we have to initialize it
     // and have the responsibility to shut it down later on.
 
-    if (!SDLIsInitialised())
+    if (!SDLIsInitialized())
     {
         if (SDL_Init(SDL_INIT_AUDIO) < 0)
         {
@@ -107,7 +117,7 @@
 
         if (Mix_OpenAudio(snd_samplerate, AUDIO_S16SYS, 2, 1024) < 0)
         {
-            fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError());
+            fprintf(stderr, "Error initializing SDL_mixer: %s\n", Mix_GetError());
             SDL_QuitSubSystem(SDL_INIT_AUDIO);
             return false;
         }
@@ -114,10 +124,10 @@
 
         SDL_PauseAudio(0);
 
-        sdl_was_initialised = true;
+        sdl_was_initialized = true;
     }
 
-    music_initialised = true;
+    music_initialized = true;
 
     return true;
 }
@@ -160,7 +170,7 @@
     Mix_Music *music = (Mix_Music *) handle;
     int loops;
 
-    if (!music_initialised)
+    if (!music_initialized)
     {
         return;
     }
@@ -184,7 +194,7 @@
 
 static void I_SDL_PauseSong(void)
 {
-    if (!music_initialised)
+    if (!music_initialized)
     {
         return;
     }
@@ -196,7 +206,7 @@
 
 static void I_SDL_ResumeSong(void)
 {
-    if (!music_initialised)
+    if (!music_initialized)
     {
         return;
     }
@@ -208,7 +218,7 @@
 
 static void I_SDL_StopSong(void)
 {
-    if (!music_initialised)
+    if (!music_initialized)
     {
         return;
     }
@@ -220,7 +230,7 @@
 {
     Mix_Music *music = (Mix_Music *) handle;
 
-    if (!music_initialised)
+    if (!music_initialized)
     {
         return;
     }
@@ -271,7 +281,7 @@
     char *filename;
     Mix_Music *music;
 
-    if (!music_initialised)
+    if (!music_initialized)
     {
         return NULL;
     }
@@ -315,7 +325,7 @@
 // Is the song playing?
 static boolean I_SDL_MusicIsPlaying(void)
 {
-    if (!music_initialised)
+    if (!music_initialized)
     {
         return false;
     }
--- a/src/i_sdlsound.c
+++ b/src/i_sdlsound.c
@@ -51,7 +51,7 @@
 #define LOW_PASS_FILTER
 #define NUM_CHANNELS 16
 
-static boolean sound_initialised = false;
+static boolean sound_initialized = false;
 
 static sfxinfo_t *channels_playing[NUM_CHANNELS];
 
@@ -311,7 +311,7 @@
 
     chunk = AllocateChunk(sfxinfo, expanded_length);
 
-    // If we can, use the standard / optimised SDL conversion routines.
+    // If we can, use the standard / optimized SDL conversion routines.
     
     if (samplerate <= mixer_freq
      && ConvertibleRatio(samplerate, mixer_freq)
@@ -554,7 +554,7 @@
 {
     int left, right;
 
-    if (!sound_initialised)
+    if (!sound_initialized)
     {
         return;
     }
@@ -588,7 +588,7 @@
 {
     Mix_Chunk *chunk;
 
-    if (!sound_initialised)
+    if (!sound_initialized)
     {
         return -1;
     }
@@ -622,7 +622,7 @@
 
 static void I_SDL_StopSound (int handle)
 {
-    if (!sound_initialised)
+    if (!sound_initialized)
     {
         return;
     }
@@ -670,7 +670,7 @@
 
 static void I_SDL_ShutdownSound(void)
 {    
-    if (!sound_initialised)
+    if (!sound_initialized)
     {
         return;
     }
@@ -678,7 +678,7 @@
     Mix_CloseAudio();
     SDL_QuitSubSystem(SDL_INIT_AUDIO);
 
-    sound_initialised = false;
+    sound_initialized = false;
 }
 
 
@@ -735,7 +735,7 @@
     
     SDL_PauseAudio(0);
 
-    sound_initialised = true;
+    sound_initialized = true;
 
     return true;
 }
--- a/src/i_sound.c
+++ b/src/i_sound.c
@@ -26,6 +26,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "SDL_mixer.h"
+
 #include "config.h"
 #include "doomfeatures.h"
 #include "doomtype.h"
@@ -35,14 +37,6 @@
 #include "m_argv.h"
 #include "m_config.h"
 
-// Disable music on OSX by default; there are problems with SDL_mixer.
-
-#ifndef __APPLE__
-#define DEFAULT_MUSIC_DEVICE SNDDEVICE_SB
-#else
-#define DEFAULT_MUSIC_DEVICE SNDDEVICE_NONE
-#endif
-
 // Sound sample rate to use for digital output (Hz)
 
 int snd_samplerate = 44100;
@@ -52,7 +46,7 @@
 static sound_module_t *sound_module;
 static music_module_t *music_module;
 
-int snd_musicdevice = DEFAULT_MUSIC_DEVICE;
+int snd_musicdevice = SNDDEVICE_SB;
 int snd_sfxdevice = SNDDEVICE_SB;
 
 // Sound modules
@@ -109,7 +103,7 @@
     return false;
 }
 
-// Find and initialise a sound_module_t appropriate for the setting
+// Find and initialize a sound_module_t appropriate for the setting
 // in snd_sfxdevice.
 
 static void InitSfxModule(boolean use_sfx_prefix)
@@ -127,7 +121,7 @@
                             sound_modules[i]->sound_devices,
                             sound_modules[i]->num_sound_devices))
         {
-            // Initialise the module
+            // Initialize the module
 
             if (sound_modules[i]->Init(use_sfx_prefix))
             {
@@ -138,7 +132,7 @@
     }
 }
 
-// Initialise music according to snd_musicdevice.
+// Initialize music according to snd_musicdevice.
 
 static void InitMusicModule(void)
 {
@@ -155,7 +149,7 @@
                             music_modules[i]->sound_devices,
                             music_modules[i]->num_sound_devices))
         {
-            // Initialise the module
+            // Initialize the module
 
             if (music_modules[i]->Init())
             {
@@ -200,7 +194,7 @@
 
     nomusic = M_CheckParm("-nomusic") > 0;
 
-    // Initialise the sound and music subsystems.
+    // Initialize the sound and music subsystems.
 
     if (!nosound && !screensaver_mode)
     {
@@ -415,6 +409,22 @@
     M_BindVariable("snd_samplerate",    &snd_samplerate);
 #ifdef FEATURE_SOUND
     M_BindVariable("use_libsamplerate", &use_libsamplerate);
+#endif
+
+    // Before SDL_mixer version 1.2.11, MIDI music caused the game
+    // to crash when it looped.  If this is an old SDL_mixer version,
+    // disable MIDI.
+
+#ifdef __MACOSX__
+    {
+        const SDL_version *v = Mix_Linked_Version();
+
+        if (SDL_VERSIONNUM(v->major, v->minor, v->patch)
+          < SDL_VERSIONNUM(1, 2, 11))
+        {
+            snd_musicdevice = SNDDEVICE_NONE;
+        }
+    }
 #endif
 }
 
--- a/src/i_timer.c
+++ b/src/i_timer.c
@@ -81,7 +81,7 @@
 
 void I_InitTimer(void)
 {
-    // initialise timer
+    // initialize timer
 
     SDL_Init(SDL_INIT_TIMER);
 }
--- a/src/i_timer.h
+++ b/src/i_timer.h
@@ -40,7 +40,7 @@
 // Pause for a specified number of ms
 void I_Sleep(int ms);
 
-// Initialise timer
+// Initialize timer
 void I_InitTimer(void);
 
 // Wait for vertical retrace or pause a bit.
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -93,6 +93,9 @@
 };
 
 
+#define LOADING_DISK_W 16
+#define LOADING_DISK_H 16
+
 // Non aspect ratio-corrected modes (direct multiples of 320x200)
 
 static screen_mode_t *screen_modes[] = {
@@ -145,7 +148,7 @@
 
 // display has been set up?
 
-static boolean initialised = false;
+static boolean initialized = false;
 
 // disable mouse?
 
@@ -221,7 +224,6 @@
 // restored by EndRead
 
 static byte *disk_image = NULL;
-static int disk_image_w, disk_image_h;
 static byte *saved_background;
 static boolean window_focused;
 
@@ -338,7 +340,7 @@
     state = SDL_GetAppState();
 
     // We should have input (keyboard) focus and be visible 
-    // (not minimised)
+    // (not minimized)
 
     window_focused = (state & SDL_APPINPUTFOCUS) && (state & SDL_APPACTIVE);
 
@@ -378,20 +380,18 @@
     tmpbuf = Z_Malloc(SCREENWIDTH * (disk->height + 1), PU_STATIC, NULL);
     V_UseBuffer(tmpbuf);
 
-    disk_image_w = SHORT(disk->width);
-    disk_image_h = SHORT(disk->height);
+    // Draw the disk to the screen:
+
     V_DrawPatch(0, 0, disk);
 
-    // Copy the disk into the disk_image buffer.
+    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);
 
-    disk_image = Z_Malloc(disk_image_w * disk_image_h, PU_STATIC, NULL);
-    saved_background = Z_Malloc(disk_image_w * disk_image_h, PU_STATIC, NULL);
-
-    for (y=0; y<disk_image_h; ++y) 
+    for (y=0; y<LOADING_DISK_H; ++y) 
     {
-        memcpy(disk_image + disk_image_w * y,
+        memcpy(disk_image + LOADING_DISK_W * y,
                tmpbuf + SCREENWIDTH * y,
-               disk_image_w);
+               LOADING_DISK_W);
     }
 
     // All done - free the screen buffer and restore the normal 
@@ -435,7 +435,9 @@
 
       case SDLK_PAUSE:	return KEY_PAUSE;
 
+#if !SDL_VERSION_ATLEAST(1, 3, 0)
       case SDLK_EQUALS: return KEY_EQUALS;
+#endif
 
       case SDLK_MINUS:          return KEY_MINUS;
 
@@ -448,9 +450,11 @@
 	return KEY_RCTRL;
 	
       case SDLK_LALT:
-      case SDLK_LMETA:
       case SDLK_RALT:
+#if !SDL_VERSION_ATLEAST(1, 3, 0)
+      case SDLK_LMETA:
       case SDLK_RMETA:
+#endif
         return KEY_RALT;
 
       case SDLK_CAPSLOCK: return KEY_CAPSLOCK;
@@ -497,7 +501,7 @@
 
 void I_ShutdownGraphics(void)
 {
-    if (initialised)
+    if (initialized)
     {
         SDL_ShowCursor(1);
         SDL_WM_GrabInput(SDL_GRAB_OFF);
@@ -504,7 +508,7 @@
 
         SDL_QuitSubSystem(SDL_INIT_VIDEO);
     
-        initialised = false;
+        initialized = false;
     }
 }
 
@@ -521,9 +525,15 @@
 
 static int MouseButtonState(void)
 {
-    Uint8 state = SDL_GetMouseState(NULL, NULL);
+    Uint8 state;
     int result = 0;
 
+#if SDL_VERSION_ATLEAST(1, 3, 0)
+    state = SDL_GetMouseState(0, NULL, NULL);
+#else
+    state = SDL_GetMouseState(NULL, NULL);
+#endif
+
     // Note: button "0" is left, button "1" is right,
     // button "2" is middle for Doom.  This is different
     // to how SDL sees things.
@@ -739,7 +749,11 @@
     // Clear any relative movement caused by warping
 
     SDL_PumpEvents();
+#if SDL_VERSION_ATLEAST(1, 3, 0)
+    SDL_GetRelativeMouseState(0, NULL, NULL);
+#else
     SDL_GetRelativeMouseState(NULL, NULL);
+#endif
 }
 
 //
@@ -753,7 +767,11 @@
     int x, y;
     event_t ev;
 
+#if SDL_VERSION_ATLEAST(1, 3, 0)
+    SDL_GetRelativeMouseState(0, &x, &y);
+#else
     SDL_GetRelativeMouseState(&x, &y);
+#endif
 
     if (x != 0 || y != 0) 
     {
@@ -784,7 +802,7 @@
 //
 void I_StartTic (void)
 {
-    if (!initialised)
+    if (!initialized)
     {
         return;
     }
@@ -898,50 +916,54 @@
 
 void I_BeginRead(void)
 {
+    byte *screenloc = I_VideoBuffer
+                    + (SCREENHEIGHT - LOADING_DISK_H) * SCREENWIDTH
+                    + (SCREENWIDTH - LOADING_DISK_W);
     int y;
 
-    if (!initialised || disk_image == NULL)
+    if (!initialized || disk_image == NULL)
         return;
 
     // save background and copy the disk image in
 
-    for (y=0; y<disk_image_h; ++y)
+    for (y=0; y<LOADING_DISK_H; ++y)
     {
-        byte *screenloc = 
-               I_VideoBuffer
-                 + (SCREENHEIGHT - 1 - disk_image_h + y) * SCREENWIDTH
-                 + (SCREENWIDTH - 1 - disk_image_w);
-
-        memcpy(saved_background + y * disk_image_w,
+        memcpy(saved_background + y * LOADING_DISK_W,
                screenloc,
-               disk_image_w);
-        memcpy(screenloc, disk_image + y * disk_image_w, disk_image_w);
+               LOADING_DISK_W);
+        memcpy(screenloc,
+               disk_image + y * LOADING_DISK_W,
+               LOADING_DISK_W);
+
+        screenloc += SCREENWIDTH;
     }
 
-    UpdateRect(SCREENWIDTH - disk_image_w, SCREENHEIGHT - disk_image_h,
+    UpdateRect(SCREENWIDTH - LOADING_DISK_W, SCREENHEIGHT - LOADING_DISK_H,
                SCREENWIDTH, SCREENHEIGHT);
 }
 
 void I_EndRead(void)
 {
+    byte *screenloc = I_VideoBuffer
+                    + (SCREENHEIGHT - LOADING_DISK_H) * SCREENWIDTH
+                    + (SCREENWIDTH - LOADING_DISK_W);
     int y;
 
-    if (!initialised || disk_image == NULL)
+    if (!initialized || disk_image == NULL)
         return;
 
     // save background and copy the disk image in
 
-    for (y=0; y<disk_image_h; ++y)
+    for (y=0; y<LOADING_DISK_H; ++y)
     {
-        byte *screenloc = 
-               I_VideoBuffer
-                 + (SCREENHEIGHT - 1 - disk_image_h + y) * SCREENWIDTH
-                 + (SCREENWIDTH - 1 - disk_image_w);
+        memcpy(screenloc,
+               saved_background + y * LOADING_DISK_W,
+               LOADING_DISK_W);
 
-        memcpy(screenloc, saved_background + y * disk_image_w, disk_image_w);
+        screenloc += SCREENWIDTH;
     }
 
-    UpdateRect(SCREENWIDTH - disk_image_w, SCREENHEIGHT - disk_image_h,
+    UpdateRect(SCREENWIDTH - LOADING_DISK_W, SCREENHEIGHT - LOADING_DISK_H,
                SCREENWIDTH, SCREENHEIGHT);
 }
 
@@ -955,7 +977,7 @@
     int		i;
     // UNUSED static unsigned char *bigscreen=0;
 
-    if (!initialised)
+    if (!initialized)
         return;
 
     if (noblit)
@@ -1697,7 +1719,7 @@
 
     if (SDL_Init(SDL_INIT_VIDEO) < 0) 
     {
-        I_Error("Failed to initialise video: %s", SDL_GetError());
+        I_Error("Failed to initialize video: %s", SDL_GetError());
     }
 
     // Check for command-line video-related parameters.
@@ -1750,7 +1772,9 @@
     // has to be done before the call to SDL_SetVideoMode.
 
     I_InitWindowTitle();
+#if !SDL_VERSION_ATLEAST(1, 3, 0)
     I_InitWindowIcon();
+#endif
 
     // Set the video mode.
 
@@ -1874,7 +1898,7 @@
         CenterMouse();
     }
 
-    initialised = true;
+    initialized = true;
 
     // Call I_ShutdownGraphics on quit
 
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -1214,7 +1214,14 @@
 
                 intparm = ParseIntParameter(strparm);
                 def->untranslated = intparm;
-                intparm = scantokey[intparm];
+                if (intparm >= 0 && intparm < 128)
+                {
+                    intparm = scantokey[intparm];
+                }
+                else
+                {
+                    intparm = 0;
+                }
 
                 def->original_translated = intparm;
                 * (int *) def->location = intparm;
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -199,6 +199,14 @@
     return result;
 }
 
+boolean M_StrToInt(const char *str, int *result)
+{
+    return sscanf(str, " 0x%x", result) == 1
+        || sscanf(str, " 0X%x", result) == 1
+        || sscanf(str, " 0%o", result) == 1
+        || sscanf(str, " %d", result) == 1;
+}
+
 void M_ExtractFileBase(char *path, char *dest)
 {
     char*	src;
--- a/src/m_misc.h
+++ b/src/m_misc.h
@@ -39,6 +39,7 @@
 char *M_TempFile(char *s);
 boolean M_FileExists(char *file);
 long M_FileLength(FILE *handle);
+boolean M_StrToInt(const char *str, int *result);
 void M_ExtractFileBase(char *path, char *dest);
 void M_ForceUppercase(char *text);
 
--- a/src/net_client.c
+++ b/src/net_client.c
@@ -1155,7 +1155,7 @@
 
     client_context = NET_NewContext();
     
-    // initialise module for client mode
+    // initialize module for client mode
 
     if (!addr->module->InitClient())
     {
@@ -1167,7 +1167,7 @@
     net_client_connected = true;
     net_client_received_wait_data = false;
 
-    // Initialise connection
+    // Initialize connection
 
     NET_Conn_InitClient(&client_connection, addr);
 
--- a/src/net_common.c
+++ b/src/net_common.c
@@ -61,7 +61,7 @@
     conn->reliable_recv_seq = 0;
 }
 
-// Initialise as a client connection
+// Initialize as a client connection
 
 void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr)
 {
@@ -69,7 +69,7 @@
     conn->state = NET_CONN_STATE_CONNECTING;
 }
 
-// Initialise as a server connection
+// Initialize as a server connection
 
 void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr)
 {
--- a/src/net_defs.h
+++ b/src/net_defs.h
@@ -60,11 +60,11 @@
 
 struct _net_module_s
 {
-    // Initialise this module for use as a client
+    // Initialize this module for use as a client
 
     boolean (*InitClient)(void);
 
-    // Initialise this module for use as a server
+    // Initialize this module for use as a server
 
     boolean (*InitServer)(void);
 
--- a/src/net_gui.c
+++ b/src/net_gui.c
@@ -263,7 +263,7 @@
 {
     if (!TXT_Init())
     {
-        fprintf(stderr, "Failed to initialise GUI\n");
+        fprintf(stderr, "Failed to initialize GUI\n");
         exit(-1);
     }
 
--- a/src/net_loop.c
+++ b/src/net_loop.c
@@ -99,7 +99,7 @@
 
 static boolean NET_CL_InitServer(void)
 {
-    I_Error("NET_CL_InitServer: attempted to initialise client pipe end as a server!");
+    I_Error("NET_CL_InitServer: attempted to initialize client pipe end as a server!");
     return false;
 }
 
@@ -161,7 +161,7 @@
 
 static boolean NET_SV_InitClient(void)
 {
-    I_Error("NET_SV_InitClient: attempted to initialise server pipe end as a client!");
+    I_Error("NET_SV_InitClient: attempted to initialize server pipe end as a client!");
     return false;
 }
 
--- a/src/net_sdl.c
+++ b/src/net_sdl.c
@@ -57,7 +57,7 @@
 static addrpair_t **addr_table;
 static int addr_table_size = -1;
 
-// Initialises the address table
+// Initializes the address table
 
 static void NET_SDL_InitAddrTable(void)
 {
--- a/src/net_server.c
+++ b/src/net_server.c
@@ -120,7 +120,7 @@
 } net_client_recv_t;
 
 static net_server_state_t server_state;
-static boolean server_initialised = false;
+static boolean server_initialized = false;
 static net_client_t clients[MAXNETNODES];
 static net_client_t *sv_players[MAXPLAYERS];
 static net_context_t *server_context;
@@ -613,7 +613,7 @@
             return;
         }
         
-        // Activate, initialise connection
+        // Activate, initialize connection
 
         NET_SV_InitNewClient(client, addr, player_name);
 
@@ -1490,13 +1490,13 @@
     NET_AddModule(server_context, module);
 }
 
-// Initialise server and wait for connections
+// Initialize server and wait for connections
 
 void NET_SV_Init(void)
 {
     int i;
 
-    // initialise send/receive context
+    // initialize send/receive context
 
     server_context = NET_NewContext();
 
@@ -1511,7 +1511,7 @@
 
     server_state = SERVER_WAITING_START;
     sv_gamemode = indetermined;
-    server_initialised = true;
+    server_initialized = true;
 }
 
 // Run server code to check for new packets/send packets as the server
@@ -1523,7 +1523,7 @@
     net_packet_t *packet;
     int i;
 
-    if (!server_initialised)
+    if (!server_initialized)
     {
         return;
     }
@@ -1565,7 +1565,7 @@
     boolean running;
     int start_time;
 
-    if (!server_initialised)
+    if (!server_initialized)
     {
         return;
     }
--- a/src/net_server.h
+++ b/src/net_server.h
@@ -24,7 +24,7 @@
 #ifndef NET_SERVER_H
 #define NET_SERVER_H
 
-// initialise server and wait for connections
+// initialize server and wait for connections
 
 void NET_SV_Init(void);
 
--- a/src/setup/Makefile.am
+++ b/src/setup/Makefile.am
@@ -2,6 +2,7 @@
 gamesdir = $(prefix)/games
 
 AM_CFLAGS = @SDL_CFLAGS@                                           \
+            @SDLMIXER_CFLAGS@                                      \
             -I$(top_builddir)/textscreen -I..                      \
             -DINSTALL_DIR="\"$(gamesdir)\""
 
--- a/src/setup/execute.c
+++ b/src/setup/execute.c
@@ -159,81 +159,69 @@
     }
 }
 
-static wchar_t *GetFullExePath(const char *program)
+static void ConcatWCString(wchar_t *buf, const char *value)
 {
+    MultiByteToWideChar(CP_OEMCP, 0,
+                        value, strlen(value) + 1,
+                        buf + wcslen(buf), strlen(value) + 1);
+}
+
+// Build the command line string, a wide character string of the form:
+//
+// "program" "arg"
+
+static wchar_t *BuildCommandLine(const char *program, const char *arg)
+{
     wchar_t *result;
-    unsigned int path_len;
     char *sep;
 
-    // Find the full path to the EXE to execute, by taking the path
-    // to this program and concatenating the EXE name:
+    result = calloc(strlen(myargv[0]) + strlen(program) + strlen(arg) + 6,
+                    sizeof(wchar_t));
 
+    wcscpy(result, L"\"");
+
     sep = strrchr(myargv[0], DIR_SEPARATOR);
 
-    if (sep == NULL)
+    if (sep != NULL)
     {
-        path_len = 0;
-        result = calloc(strlen(program) + 1, sizeof(wchar_t));
-    }
-    else
-    {
-        path_len = sep - myargv[0] + 1;
+        ConcatWCString(result, myargv[0]);
 
-        result = calloc(path_len + strlen(program) + 1,
-                        sizeof(wchar_t));
-        MultiByteToWideChar(CP_OEMCP, 0,
-                            myargv[0], path_len,
-                            result, path_len);
+        // Cut off the string after the last directory separator,
+        // before appending the actual program.
+
+        result[sep - myargv[0] + 2] = '\0';
+        
     }
 
-    MultiByteToWideChar(CP_OEMCP, 0,
-                        program, strlen(program) + 1,
-                        result + path_len, strlen(program) + 1);
+    ConcatWCString(result, program);
 
-    return result;
-}
+    wcscat(result, L"\" \"");
 
-// Convert command line argument to wchar_t string and add surrounding
-// "" quotes:
+    ConcatWCString(result, arg);
 
-static wchar_t *GetPaddedWideArg(const char *arg)
-{
-    wchar_t *result;
-    unsigned int len = strlen(arg);
+    wcscat(result, L"\"");
 
-    // Convert the command line arg to a wide char string:
-
-    result = calloc(len + 3, sizeof(wchar_t));
-    MultiByteToWideChar(CP_OEMCP, 0,
-                        arg, len + 1,
-                        result + 1, len + 1);
-
-    // Surrounding quotes:
-
-    result[0] = '"';
-    result[len + 1] = '"';
-    result[len + 2] = 0;
-
     return result;
 }
 
 static int ExecuteCommand(const char *program, const char *arg)
 {
+    STARTUPINFOW startup_info;
     PROCESS_INFORMATION proc_info;
-    wchar_t *exe_path;
-    wchar_t *warg;
+    wchar_t *command;
     int result = 0;
 
-    exe_path = GetFullExePath(program);
-    warg = GetPaddedWideArg(arg);
+    command = BuildCommandLine(program, arg);
 
     // Invoke the program:
 
     memset(&proc_info, 0, sizeof(proc_info));
+    memset(&startup_info, 0, sizeof(startup_info));
+    startup_info.cb = sizeof(startup_info);
 
-    if (!CreateProcessW(exe_path, warg,
-                        NULL, NULL, FALSE, 0, NULL, NULL, NULL,
-                        &proc_info))
+    if (!CreateProcessW(NULL, command,
+                        NULL, NULL, FALSE, 0, NULL, NULL,
+                        &startup_info, &proc_info))
     {
         result = -1;
     }
@@ -247,8 +235,7 @@
         CloseHandle(proc_info.hThread);
     }
 
-    free(exe_path);
-    free(warg);
+    free(command);
 
     return result;
 }
@@ -255,11 +242,41 @@
 
 #else
 
+// Given the specified program name, get the full path to the program,
+// assuming that it is in the same directory as this program is.
+
+static char *GetFullExePath(const char *program)
+{
+    char *result;
+    char *sep;
+    unsigned int path_len;
+
+    sep = strrchr(myargv[0], DIR_SEPARATOR);
+
+    if (sep == NULL)
+    {
+        result = strdup(program);
+    }
+    else
+    {
+        path_len = sep - myargv[0] + 1;
+
+        result = malloc(strlen(program) + path_len + 1);
+
+        strncpy(result, myargv[0], path_len);
+        result[path_len] = '\0';
+
+        strcat(result, program);
+    }
+
+    return result;
+}
+
 static int ExecuteCommand(const char *program, const char *arg)
 {
     pid_t childpid;
     int result;
-    const char *argv[] = { program, arg, NULL };
+    const char *argv[3];
 
     childpid = fork();
 
@@ -267,7 +284,11 @@
     {
         // This is the child.  Execute the command.
 
-        execv(argv[0], (char **) argv);
+        argv[0] = GetFullExePath(program);
+        argv[1] = arg;
+        argv[2] = NULL;
+
+        execvp(argv[0], (char **) argv);
 
         exit(-1);
     }
--- a/src/setup/joystick.c
+++ b/src/setup/joystick.c
@@ -38,7 +38,7 @@
     CALIBRATE_UP,
 } calibration_stage_t;
 
-// SDL joystick successfully initialised?
+// SDL joystick successfully initialized?
 
 static int joystick_initted = 0;
 
--- a/src/setup/mainmenu.c
+++ b/src/setup/mainmenu.c
@@ -19,6 +19,7 @@
 // 02111-1307, USA.
 //
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -175,6 +176,10 @@
     TXT_SetWindowAction(window, TXT_HORIZ_LEFT, quit_action);
 }
 
+//
+// Initialize all configuration variables, load config file, etc
+//
+
 static void InitConfig(void)
 {
     InitBindings();
@@ -228,7 +233,7 @@
 }
 
 // 
-// Initialise and run the textscreen GUI.
+// Initialize and run the textscreen GUI.
 //
 
 static void RunGUI(void)
@@ -237,7 +242,7 @@
 
     if (!TXT_Init())
     {
-        fprintf(stderr, "Failed to initialise GUI\n");
+        fprintf(stderr, "Failed to initialize GUI\n");
         exit(-1);
     }
 
--- a/src/setup/multiplayer.c
+++ b/src/setup/multiplayer.c
@@ -783,7 +783,7 @@
         HUSTR_CHATMACRO0,
     };
     
-    // If the chat macros have not been set, initialise with defaults.
+    // If the chat macros have not been set, initialize with defaults.
 
     for (i=0; i<10; ++i)
     {
--- a/src/setup/sound.c
+++ b/src/setup/sound.c
@@ -23,6 +23,8 @@
 
 #include <stdlib.h>
 
+#include "SDL_mixer.h"
+
 #include "textscreen.h"
 #include "m_config.h"
 
@@ -60,19 +62,10 @@
     "CD audio"
 };
 
-// Disable MIDI music on OSX: there are problems with the native
-// MIDI code in SDL_mixer.
-
-#ifdef __MACOSX__
-#define DEFAULT_MUSIC_DEVICE SNDDEVICE_NONE
-#else
-#define DEFAULT_MUSIC_DEVICE SNDDEVICE_SB
-#endif
-
 // Config file variables:
 
 int snd_sfxdevice = SNDDEVICE_SB;
-int snd_musicdevice = DEFAULT_MUSIC_DEVICE;
+int snd_musicdevice = SNDDEVICE_SB;
 int snd_samplerate = 22050;
 
 static int numChannels = 8;
@@ -237,5 +230,21 @@
     M_BindVariable("snd_sbirq",          &snd_sbirq);
     M_BindVariable("snd_sbdma",          &snd_sbdma);
     M_BindVariable("snd_mport",          &snd_mport);
+
+    // Before SDL_mixer version 1.2.11, MIDI music caused the game
+    // to crash when it looped.  If this is an old SDL_mixer version,
+    // disable MIDI.
+
+#ifdef __MACOSX__
+    {
+        const SDL_version *v = Mix_Linked_Version();
+
+        if (SDL_VERSIONNUM(v->major, v->minor, v->patch)
+          < SDL_VERSIONNUM(1, 2, 11))
+        {
+            snd_musicdevice = SNDDEVICE_NONE;
+        }
+    }
+#endif
 }
 
--- a/src/w_merge.c
+++ b/src/w_merge.c
@@ -144,7 +144,7 @@
     SetupList(&pwad_sprites, &pwad, "S_START", "S_END", "SS_START", "SS_END");
 }
 
-// Initialise the replace list
+// Initialize the replace list
 
 static void InitSpriteList(void)
 {
--- a/textscreen/txt_desktop.c
+++ b/textscreen/txt_desktop.c
@@ -61,7 +61,7 @@
     num_windows = to;
 }
 
-static void DrawDesktopBackground(char *title)
+static void DrawDesktopBackground(const char *title)
 {
     int i;
     unsigned char *screendata;
@@ -117,7 +117,7 @@
 void TXT_DrawDesktop(void)
 {
     int i;
-    char *title;
+    const char *title;
 
     TXT_InitClipArea();
 
--- a/textscreen/txt_dropdown.c
+++ b/textscreen/txt_dropdown.c
@@ -193,7 +193,7 @@
 {
     TXT_CAST_ARG(txt_dropdown_list_t, list);
     unsigned int i;
-    char *str;
+    const char *str;
 
     // Set bg/fg text colors.
 
--- a/textscreen/txt_gui.c
+++ b/textscreen/txt_gui.c
@@ -55,7 +55,7 @@
 #define VALID_X(x) ((x) >= cliparea->x1 && (x) < cliparea->x2)
 #define VALID_Y(y) ((y) >= cliparea->y1 && (y) < cliparea->y2)
 
-void TXT_DrawDesktopBackground(char *title)
+void TXT_DrawDesktopBackground(const char *title)
 {
     int i;
     unsigned char *screendata;
@@ -125,7 +125,7 @@
     }
 }
 
-void TXT_DrawWindowFrame(char *title, int x, int y, int w, int h)
+void TXT_DrawWindowFrame(const char *title, int x, int y, int w, int h)
 {
     int x1, y1;
     int bx, by;
@@ -224,17 +224,16 @@
     }
 }
 
-void TXT_DrawString(char *s)
+void TXT_DrawString(const char *s)
 {
     int x, y;
     int x1;
-    char *p;
+    const char *p;
 
     TXT_GetXY(&x, &y);
 
     if (VALID_Y(y))
     {
-        p = s;
         x1 = x;
 
         for (p = s; *p != '\0'; ++p)
--- a/textscreen/txt_gui.h
+++ b/textscreen/txt_gui.h
@@ -27,10 +27,10 @@
 #ifndef TXT_GUI_H
 #define TXT_GUI_H
 
-void TXT_DrawDesktopBackground(char *title);
-void TXT_DrawWindowFrame(char *title, int x, int y, int w, int h);
+void TXT_DrawDesktopBackground(const char *title);
+void TXT_DrawWindowFrame(const char *title, int x, int y, int w, int h);
 void TXT_DrawSeparator(int x, int y, int w);
-void TXT_DrawString(char *s);
+void TXT_DrawString(const char *s);
 
 void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range);
 void TXT_DrawVertScrollbar(int x, int y, int h, int cursor, int range);
--- a/textscreen/txt_inputbox.c
+++ b/textscreen/txt_inputbox.c
@@ -53,7 +53,7 @@
 
     w = inputbox->widget.w;
 
-    // Select the background colour based on whether we are currently
+    // Select the background color based on whether we are currently
     // editing, and if not, whether the widget is selected.
 
     if (inputbox->editing && selected)
--- a/textscreen/txt_io.c
+++ b/textscreen/txt_io.c
@@ -33,7 +33,7 @@
 static struct 
 {
     txt_color_t color;
-    char *name;
+    const char *name;
 } colors[] = {
     {TXT_COLOR_BLACK,           "black"},
     {TXT_COLOR_BLUE,            "blue"},
@@ -147,11 +147,11 @@
     PutChar(screen, c);
 }
 
-void TXT_Puts(char *s)
+void TXT_Puts(const char *s)
 {
     int previous_color = TXT_COLOR_BLACK;
     unsigned char *screen;
-    char *p;
+    const char *p;
     char colorname_buf[20];
     char *ending;
     int col;
--- a/textscreen/txt_io.h
+++ b/textscreen/txt_io.h
@@ -30,7 +30,7 @@
 #include "txt_main.h"
 
 void TXT_PutChar(int c);
-void TXT_Puts(char *s);
+void TXT_Puts(const char *s);
 void TXT_GotoXY(int x, int y);
 void TXT_GetXY(int *x, int *y);
 void TXT_FGColor(txt_color_t color);
--- a/textscreen/txt_main.h
+++ b/textscreen/txt_main.h
@@ -67,7 +67,7 @@
     TXT_COLOR_BRIGHT_WHITE,
 } txt_color_t;
 
-// Initialise the screen
+// Initialize the screen
 // Returns 1 if successful, 0 if failed.
 
 int TXT_Init(void);
--- a/textscreen/txt_scrollpane.c
+++ b/textscreen/txt_scrollpane.c
@@ -254,10 +254,53 @@
     }
 }
 
+// Another hack for tables - when scrolling in 'pages', the normal key press
+// event does not provide children with enough information to know how far
+// to move their selection to reach a new page. This function does so.
+// Note that it *only* affects scrolling in pages, not with arrows!
+// A side-effect of this, rather than 'pulling' the selection to fit within
+// the new page, is that we will jump straight over ranges of unselectable
+// items longer than a page, but that is also true of arrow-key scrolling.
+// The other unfortunate effect of doing things this way is that page keys
+// have no effect on tables _not_ in scrollpanes: not even home/end.
+
+static int PageSelectedWidget(txt_scrollpane_t *scrollpane, int key)
+{
+    int pagex = 0; // No page left/right yet, but some keyboards have them
+    int pagey = 0;
+
+    // Subtract one from the absolute page distance as this is slightly more
+    // intuitive: a page down first jumps to the bottom of the current page,
+    // then proceeds to scroll onwards.
+
+    switch (key)
+    {
+        case KEY_PGUP:
+            pagey = 1 - scrollpane->h;
+            break;
+
+        case KEY_PGDN:
+            pagey = scrollpane->h - 1;
+            break;
+
+        default: // We shouldn't even be in this function
+            return 0;
+    }
+
+    if (scrollpane->child->widget_class == &txt_table_class)
+    {
+        return TXT_PageTable(scrollpane->child, pagex, pagey);
+    }
+
+    return 0;
+}
+
 // Interpret arrow key presses as scroll commands
 
 static int InterpretScrollKey(txt_scrollpane_t *scrollpane, int key)
 {
+    int maxy;
+
     switch (key)
     {
         case KEY_UPARROW:
@@ -292,6 +335,31 @@
             }
             break;
 
+        case KEY_PGUP:
+            if (scrollpane->y > 0)
+            {
+                scrollpane->y -= scrollpane->h;
+                if (scrollpane->y < 0)
+                {
+                    scrollpane->y = 0;
+                }
+                return 1;
+            }
+            break;
+
+        case KEY_PGDN:
+            maxy = FullHeight(scrollpane) - scrollpane->h;
+            if (scrollpane->y < maxy)
+            {
+                scrollpane->y += scrollpane->h;
+                if (scrollpane->y > maxy)
+                {
+                    scrollpane->y = maxy;
+                }
+                return 1;
+            }
+            break;
+
         default:
             break;
     }
@@ -316,8 +384,14 @@
 
         if (scrollpane->child->widget_class == &txt_table_class
          && (key == KEY_UPARROW || key == KEY_DOWNARROW
-          || key == KEY_LEFTARROW || key == KEY_RIGHTARROW))
+          || key == KEY_LEFTARROW || key == KEY_RIGHTARROW
+          || key == KEY_PGUP || key == KEY_PGDN))
         {
+            if (PageSelectedWidget(scrollpane, key))
+            {
+                result = 1;
+            }
+
             ShowSelectedWidget(scrollpane);
         }
 
--- a/textscreen/txt_sdl.c
+++ b/textscreen/txt_sdl.c
@@ -162,7 +162,7 @@
 }
 
 //
-// Initialise text mode screen
+// Initialize text mode screen
 //
 // Returns 1 if successful, 0 if an error occurred
 //
@@ -221,7 +221,7 @@
     unsigned char *p;
     unsigned char *s, *s1;
     int bg, fg;
-    int x1, y1;
+    unsigned int x1, y1;
 
     p = &screendata[(y * TXT_SCREEN_W + x) * 2];
     character = p[0];
@@ -267,19 +267,44 @@
     }
 }
 
+static int LimitToRange(int val, int min, int max)
+{
+    if (val < min)
+    {
+        return min;
+    }
+    else if (val > max)
+    {
+        return max;
+    }
+    else
+    {
+        return val;
+    }
+}
+
 void TXT_UpdateScreenArea(int x, int y, int w, int h)
 {
     int x1, y1;
+    int x_end;
+    int y_end;
 
-    for (y1=y; y1<y+h; ++y1)
+    x_end = LimitToRange(x + w, 0, TXT_SCREEN_W - 1);
+    y_end = LimitToRange(y + h, 0, TXT_SCREEN_H - 1);
+    x = LimitToRange(x, 0, TXT_SCREEN_W - 1);
+    y = LimitToRange(y, 0, TXT_SCREEN_H - 1);
+
+    for (y1=y; y1<y_end; ++y1)
     {
-        for (x1=x; x1<x+w; ++x1)
+        for (x1=x; x1<x_end; ++x1)
         {
             UpdateCharacter(x1, y1);
         }
     }
 
-    SDL_UpdateRect(screen, x * font->w, y * font->h, w * font->w, h * font->h);
+    SDL_UpdateRect(screen,
+                   x * font->w, y * font->h,
+                   (x_end - x) * font->w, (y_end - y) * font->h);
 }
 
 void TXT_UpdateScreen(void)
@@ -289,7 +314,11 @@
 
 void TXT_GetMousePosition(int *x, int *y)
 {
+#if SDL_VERSION_ATLEAST(1, 3, 0)
+    SDL_GetMouseState(0, x, y);
+#else
     SDL_GetMouseState(x, y);
+#endif
 
     *x /= font->w;
     *y /= font->h;
@@ -328,7 +357,9 @@
 
         case SDLK_PAUSE:       return KEY_PAUSE;
 
+#if !SDL_VERSION_ATLEAST(1, 3, 0)
         case SDLK_EQUALS:      return KEY_EQUALS;
+#endif
 
         case SDLK_LSHIFT:
         case SDLK_RSHIFT:
@@ -339,9 +370,11 @@
                                return KEY_RCTRL;
 
         case SDLK_LALT:
-        case SDLK_LMETA:
         case SDLK_RALT:
+#if !SDL_VERSION_ATLEAST(1, 3, 0)
+        case SDLK_LMETA:
         case SDLK_RMETA:
+#endif
                                return KEY_RALT;
 
         case SDLK_CAPSLOCK:    return KEY_CAPSLOCK;
@@ -462,7 +495,7 @@
     return -1;
 }
 
-static char *SpecialKeyName(int key)
+static const char *SpecialKeyName(int key)
 {
     switch (key)
     {
@@ -528,7 +561,7 @@
 
 void TXT_GetKeyDescription(int key, char *buf)
 {
-    char *keyname;
+    const char *keyname;
 
     keyname = SpecialKeyName(key);
 
--- a/textscreen/txt_table.c
+++ b/textscreen/txt_table.c
@@ -770,3 +770,85 @@
     va_end(args);
 }
 
+// Moves the select by at least the given number of characters.
+// Currently quietly ignores pagex, as we don't use it.
+
+int TXT_PageTable(TXT_UNCAST_ARG(table), int pagex, int pagey)
+{
+    TXT_CAST_ARG(txt_table_t, table);
+    unsigned int *column_widths;
+    unsigned int *row_heights;
+    int rows;
+    int changed = 0;
+
+    rows = TableRows(table);
+
+    row_heights = malloc(sizeof(int) * rows);
+    column_widths = malloc(sizeof(int) * table->columns);
+
+    CalcRowColSizes(table, row_heights, column_widths);
+
+    if (pagex)
+    {
+        // @todo Jump selection to the left or right as needed
+    }
+
+    if (pagey)
+    {
+        int new_x, new_y;
+        int distance = 0;
+        int dir;
+
+        // What direction are we moving?
+
+        if (pagey > 0)
+        {
+            dir = 1;
+        }
+        else
+        {
+            dir = -1;
+        }
+
+        // Move the cursor until the desired distance is reached.
+
+        new_y = table->selected_y;
+
+        while (new_y >= 0 && new_y < rows)
+        {
+            // We are about to travel a distance equal to the height of the row
+            // we are about to leave.
+
+            distance += row_heights[new_y];
+
+            // *Now* increment the loop.
+
+            new_y += dir;
+
+            new_x = FindSelectableColumn(table, new_y, table->selected_x);
+
+            if (new_x >= 0)
+            {
+                // Found a selectable widget in this column!
+                // Select it anyway in case we don't find something better.
+
+                table->selected_x = new_x;
+                table->selected_y = new_y;
+                changed = 1;
+
+                // ...but is it far enough away?
+
+                if (distance >= abs(pagey))
+                {
+                    break;
+                }
+            }
+        }
+    }
+
+    free(row_heights);
+    free(column_widths);
+
+    return changed;
+}
+
--- a/textscreen/txt_table.h
+++ b/textscreen/txt_table.h
@@ -178,6 +178,19 @@
 
 void TXT_ClearTable(TXT_UNCAST_ARG(table));
 
+/**
+ * Hack to move the selection in a table by a 'page', triggered by the
+ * scrollpane. This acts as per the keyboard events for the arrows, but moves
+ * the selection by at least the specified number of characters.
+ *
+ * @param table    The table.
+ * @param pagex    Minimum distance to move the selection horizontally.
+ * @param pagey    Minimum distance to move the selection vertically.
+ * @return         Non-zero if the selection has been changed.
+ */
+
+int TXT_PageTable(TXT_UNCAST_ARG(table), int pagex, int pagey);
+
 #endif /* #ifndef TXT_TABLE_T */
 
 
--- a/textscreen/txt_widget.c
+++ b/textscreen/txt_widget.c
@@ -94,7 +94,7 @@
 }
 
 void TXT_SignalConnect(TXT_UNCAST_ARG(widget),
-                       char *signal_name,
+                       const char *signal_name,
                        TxtWidgetSignalFunc func, 
                        void *user_data)
 {
@@ -117,7 +117,7 @@
     callback->user_data = user_data;
 }
 
-void TXT_EmitSignal(TXT_UNCAST_ARG(widget), char *signal_name)
+void TXT_EmitSignal(TXT_UNCAST_ARG(widget), const char *signal_name)
 {
     TXT_CAST_ARG(txt_widget_t, widget);
     txt_callback_table_t *table;
--- a/textscreen/txt_widget.h
+++ b/textscreen/txt_widget.h
@@ -106,7 +106,7 @@
 void TXT_InitWidget(TXT_UNCAST_ARG(widget), txt_widget_class_t *widget_class);
 void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget));
 void TXT_DrawWidget(TXT_UNCAST_ARG(widget), int selected);
-void TXT_EmitSignal(TXT_UNCAST_ARG(widget), char *signal_name);
+void TXT_EmitSignal(TXT_UNCAST_ARG(widget), const char *signal_name);
 int TXT_WidgetKeyPress(TXT_UNCAST_ARG(widget), int key);
 void TXT_WidgetMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b);
 void TXT_DestroyWidget(TXT_UNCAST_ARG(widget));
@@ -121,7 +121,7 @@
  * @param user_data    User-specified pointer to pass to the callback function.
  */
 
-void TXT_SignalConnect(TXT_UNCAST_ARG(widget), char *signal_name,
+void TXT_SignalConnect(TXT_UNCAST_ARG(widget), const char *signal_name,
                        TxtWidgetSignalFunc func, void *user_data);
 
 /**
--- a/textscreen/txt_window_action.c
+++ b/textscreen/txt_window_action.c
@@ -101,7 +101,7 @@
     NULL,
 };
 
-txt_window_action_t *TXT_NewWindowAction(int key, char *label)
+txt_window_action_t *TXT_NewWindowAction(int key, const char *label)
 {
     txt_window_action_t *action;
 
--- a/textscreen/txt_window_action.h
+++ b/textscreen/txt_window_action.h
@@ -59,7 +59,7 @@
  * @return              Pointer to the new window action widget.
  */
 
-txt_window_action_t *TXT_NewWindowAction(int key, char *label);
+txt_window_action_t *TXT_NewWindowAction(int key, const char *label);
 
 /**
  * Create a new window action that closes the window when the
--- a/wince/Makefile.am
+++ b/wince/Makefile.am
@@ -10,7 +10,7 @@
 
 else
 
-libc_wince_a_SOURCES =
+libc_wince_a_SOURCES = dummy.c
 
 endif
 
--- /dev/null
+++ b/wince/dummy.c
@@ -1,0 +1,8 @@
+
+// Dummy source file so that the Windows CE workaround library is
+// not empty.  Some platforms don't like empty libraries.
+
+void DummyWindowsCEFunction(void)
+{
+}
+