shithub: choc

Download patch

ref: 122dcc372f579c54ba2e6f793493cfa4d0a7d609
parent: 46ad00deca23f3c57fcaed47af67f9003d6a4048
parent: b6491fa4aefc073a760d4bad51f55c2d6c0f5f35
author: Simon Howard <[email protected]>
date: Tue Jun 9 14:28:51 EDT 2009

Merge from trunk.

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

--- a/.lvimrc
+++ b/.lvimrc
@@ -4,3 +4,28 @@
 set softtabstop=4
 set shiftwidth=4
 
+" Add all tag files to tags path.
+
+let topdir = findfile("configure.in", ".;")
+let topdir = substitute(topdir, "configure.in", "", "")
+
+" Check tags file in current dir:
+set tags+=tags
+
+" Add tag files in parent directories:
+let tagfiles = findfile("tags", ".;", -1)
+
+" Add tag files for libraries:
+call add(tagfiles, topdir . "textscreen/tags")
+call add(tagfiles, topdir . "pcsound/tags")
+
+for tagfile in tagfiles
+    " Don't go beyond the project top level when adding parent dirs:
+    if stridx(tagfile, topdir) >= 0
+        exec "set tags+=" . tagfile
+    endif
+endfor
+
+unlet topdir
+unlet tagfiles
+
--- a/Makefile.am
+++ b/Makefile.am
@@ -52,7 +52,7 @@
 MAINTAINERCLEANFILES =  $(AUX_DIST_GEN)
 
 docdir=$(prefix)/share/doc/@PACKAGE@
-SUBDIRS=textscreen pcsound src man 
+SUBDIRS=wince textscreen pcsound src man 
 
 if HAVE_PYTHON
 
--- a/configure.in
+++ b/configure.in
@@ -53,6 +53,19 @@
     exit -1
 ])
 
+# Windows CE build?
+
+WINDOWS_CE=false
+
+case "$host" in
+    *mingw32ce*|*cegcc*|*wince*)
+        CFLAGS="-I../wince $CFLAGS"
+        WINDOWS_CE=true
+        ;;
+    *)
+        ;;
+esac
+
 AC_CHECK_HEADERS([linux/kd.h dev/isa/spkrio.h dev/speaker/speaker.h])
 AC_CHECK_FUNCS(mmap sched_setaffinity)
 
@@ -61,6 +74,7 @@
 
 AC_CHECK_TOOL(WINDRES, windres, )
 
+AM_CONDITIONAL(WINDOWS_CE, $WINDOWS_CE)
 AM_CONDITIONAL(HAVE_WINDRES, test "$WINDRES" != "")
 AM_CONDITIONAL(HAVE_PYTHON, $HAVE_PYTHON)
 
@@ -89,6 +103,7 @@
 
 AC_OUTPUT([
 Makefile
+wince/Makefile
 textscreen/Makefile
 textscreen/examples/Makefile
 man/Makefile
--- a/pcsound/pcsound.c
+++ b/pcsound/pcsound.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "SDL_getenv.h"
 #include "config.h"
 #include "pcsound.h"
 #include "pcsound_internal.h"
--- a/pcsound/pcsound_win32.c
+++ b/pcsound/pcsound_win32.c
@@ -26,6 +26,7 @@
 #ifdef _WIN32
 
 #include "SDL.h"
+#include "SDL_thread.h"
 #include <windows.h>
 
 #include "pcsound.h"
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -115,6 +115,7 @@
                $(FEATURE_SOUND_SOURCE_FILES)
 
 EXTRA_LIBS =                                       \
+               ../wince/libc_wince.a               \
 	       ../textscreen/libtextscreen.a       \
 	       ../pcsound/libpcsound.a             \
 	       @LDFLAGS@                           \
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -76,7 +76,7 @@
 // keys installed by the Windows installers for various CD versions
 // of Doom.  From these keys we can deduce where to find an IWAD.
 
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(_WIN32_WCE)
 
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
@@ -490,7 +490,14 @@
 
     AddDoomWadPath();
 
-#ifdef _WIN32
+#if defined(_WIN32_WCE)
+
+    // Windows CE locations:
+
+    AddIWADDir("\\Storage Card");
+    AddIWADDir(getenv("HOME"));
+
+#elif defined(_WIN32) 
 
     // Search the registry and find where IWADs have been installed.
 
--- a/src/doom/am_map.c
+++ b/src/doom/am_map.c
@@ -90,19 +90,18 @@
 
 // drawing stuff
 
-#define AM_PANDOWNKEY	KEY_DOWNARROW
-#define AM_PANUPKEY	KEY_UPARROW
-#define AM_PANRIGHTKEY	KEY_RIGHTARROW
-#define AM_PANLEFTKEY	KEY_LEFTARROW
-#define AM_ZOOMINKEY	'='
-#define AM_ZOOMOUTKEY	'-'
-#define AM_STARTKEY	KEY_TAB
-#define AM_ENDKEY	KEY_TAB
-#define AM_GOBIGKEY	'0'
-#define AM_FOLLOWKEY	'f'
-#define AM_GRIDKEY	'g'
-#define AM_MARKKEY	'm'
-#define AM_CLEARMARKKEY	'c'
+int key_map_north     = KEY_UPARROW;
+int key_map_south     = KEY_DOWNARROW;
+int key_map_east      = KEY_RIGHTARROW;
+int key_map_west      = KEY_LEFTARROW;
+int key_map_zoomin    = '=';
+int key_map_zoomout   = '-';
+int key_map_toggle    = KEY_TAB;
+int key_map_maxzoom   = '0';
+int key_map_follow    = 'f';
+int key_map_grid      = 'g';
+int key_map_mark      = 'm';
+int key_map_clearmark = 'c';
 
 #define AM_NUMMARKPOINTS 10
 
@@ -629,12 +628,13 @@
     static int cheatstate=0;
     static int bigstate=0;
     static char buffer[20];
+    int key;
 
     rc = false;
 
     if (!automapactive)
     {
-	if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY)
+	if (ev->type == ev_keydown && ev->data1 == key_map_toggle)
 	{
 	    AM_Start ();
 	    viewactive = false;
@@ -641,79 +641,91 @@
 	    rc = true;
 	}
     }
-
     else if (ev->type == ev_keydown)
     {
-
 	rc = true;
-	switch(ev->data1)
-	{
-	  case AM_PANRIGHTKEY: // pan right
-	    if (!followplayer) m_paninc.x = FTOM(F_PANINC);
-	    else rc = false;
-	    break;
-	  case AM_PANLEFTKEY: // pan left
-	    if (!followplayer) m_paninc.x = -FTOM(F_PANINC);
-	    else rc = false;
-	    break;
-	  case AM_PANUPKEY: // pan up
-	    if (!followplayer) m_paninc.y = FTOM(F_PANINC);
-	    else rc = false;
-	    break;
-	  case AM_PANDOWNKEY: // pan down
-	    if (!followplayer) m_paninc.y = -FTOM(F_PANINC);
-	    else rc = false;
-	    break;
-	  case AM_ZOOMOUTKEY: // zoom out
-	    mtof_zoommul = M_ZOOMOUT;
-	    ftom_zoommul = M_ZOOMIN;
-	    break;
-	  case AM_ZOOMINKEY: // zoom in
-	    mtof_zoommul = M_ZOOMIN;
-	    ftom_zoommul = M_ZOOMOUT;
-	    break;
-	  case AM_ENDKEY:
-	    bigstate = 0;
-	    viewactive = true;
-	    AM_Stop ();
-	    break;
-	  case AM_GOBIGKEY:
-	    bigstate = !bigstate;
-	    if (bigstate)
-	    {
-		AM_saveScaleAndLoc();
-		AM_minOutWindowScale();
-	    }
-	    else AM_restoreScaleAndLoc();
-	    break;
-	  case AM_FOLLOWKEY:
-	    followplayer = !followplayer;
-	    f_oldloc.x = INT_MAX;
+        key = ev->data1;
+
+        if (key == key_map_east)          // pan right
+        {
+            if (!followplayer) m_paninc.x = FTOM(F_PANINC);
+            else rc = false;
+        }
+        else if (key == key_map_west)     // pan left
+        {
+            if (!followplayer) m_paninc.x = -FTOM(F_PANINC);
+            else rc = false;
+        }
+        else if (key == key_map_north)    // pan up
+        {
+            if (!followplayer) m_paninc.y = FTOM(F_PANINC);
+            else rc = false;
+        }
+        else if (key == key_map_south)    // pan down
+        {
+            if (!followplayer) m_paninc.y = -FTOM(F_PANINC);
+            else rc = false;
+        }
+        else if (key == key_map_zoomout)  // zoom out
+        {
+            mtof_zoommul = M_ZOOMOUT;
+            ftom_zoommul = M_ZOOMIN;
+        }
+        else if (key == key_map_zoomin)   // zoom in
+        {
+            mtof_zoommul = M_ZOOMIN;
+            ftom_zoommul = M_ZOOMOUT;
+        }
+        else if (key == key_map_toggle)
+        {
+            bigstate = 0;
+            viewactive = true;
+            AM_Stop ();
+        }
+        else if (key == key_map_maxzoom)
+        {
+            bigstate = !bigstate;
+            if (bigstate)
+            {
+                AM_saveScaleAndLoc();
+                AM_minOutWindowScale();
+            }
+            else AM_restoreScaleAndLoc();
+        }
+        else if (key == key_map_follow)
+        {
+            followplayer = !followplayer;
+            f_oldloc.x = INT_MAX;
             if (followplayer)
                 plr->message = DEH_String(AMSTR_FOLLOWON);
             else
                 plr->message = DEH_String(AMSTR_FOLLOWOFF);
-	    break;
-	  case AM_GRIDKEY:
-	    grid = !grid;
+        }
+        else if (key == key_map_grid)
+        {
+            grid = !grid;
             if (grid)
                 plr->message = DEH_String(AMSTR_GRIDON);
             else
                 plr->message = DEH_String(AMSTR_GRIDOFF);
-	    break;
-	  case AM_MARKKEY:
-	    sprintf(buffer, "%s %d", DEH_String(AMSTR_MARKEDSPOT), markpointnum);
-	    plr->message = buffer;
-	    AM_addMark();
-	    break;
-	  case AM_CLEARMARKKEY:
-	    AM_clearMarks();
-	    plr->message = DEH_String(AMSTR_MARKSCLEARED);
-	    break;
-	  default:
-	    cheatstate=0;
-	    rc = false;
-	}
+        }
+        else if (key == key_map_mark)
+        {
+            sprintf(buffer, "%s %d", DEH_String(AMSTR_MARKEDSPOT), markpointnum);
+            plr->message = buffer;
+            AM_addMark();
+        }
+        else if (key == key_map_clearmark)
+        {
+            AM_clearMarks();
+            plr->message = DEH_String(AMSTR_MARKSCLEARED);
+        }
+        else
+        {
+            cheatstate=0;
+            rc = false;
+        }
+
 	if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data2))
 	{
 	    rc = false;
@@ -720,30 +732,32 @@
 	    cheating = (cheating+1) % 3;
 	}
     }
-
     else if (ev->type == ev_keyup)
     {
-	rc = false;
-	switch (ev->data1)
-	{
-	  case AM_PANRIGHTKEY:
-	    if (!followplayer) m_paninc.x = 0;
-	    break;
-	  case AM_PANLEFTKEY:
-	    if (!followplayer) m_paninc.x = 0;
-	    break;
-	  case AM_PANUPKEY:
-	    if (!followplayer) m_paninc.y = 0;
-	    break;
-	  case AM_PANDOWNKEY:
-	    if (!followplayer) m_paninc.y = 0;
-	    break;
-	  case AM_ZOOMOUTKEY:
-	  case AM_ZOOMINKEY:
-	    mtof_zoommul = FRACUNIT;
-	    ftom_zoommul = FRACUNIT;
-	    break;
-	}
+        rc = false;
+        key = ev->data1;
+
+        if (key == key_map_east)
+        {
+            if (!followplayer) m_paninc.x = 0;
+        }
+        else if (key == key_map_west)
+        {
+            if (!followplayer) m_paninc.x = 0;
+        }
+        else if (key == key_map_north)
+        {
+            if (!followplayer) m_paninc.y = 0;
+        }
+        else if (key == key_map_south)
+        {
+            if (!followplayer) m_paninc.y = 0;
+        }
+        else if (key == key_map_zoomout || key == key_map_zoomin)
+        {
+            mtof_zoommul = FRACUNIT;
+            ftom_zoommul = FRACUNIT;
+        }
     }
 
     return rc;
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -1122,8 +1122,7 @@
         I_Error("Game mode indeterminate.  No IWAD file was found.  Try\n"
                 "specifying one with the '-iwad' command line parameter.\n");
     }
-	
-    setbuf (stdout, NULL);
+
     modifiedgame = false;
 
     //!
--- a/src/doom/deh_ammo.c
+++ b/src/doom/deh_ammo.c
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "doomdef.h"
 #include "doomtype.h"
 #include "deh_defs.h"
 #include "deh_io.h"
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -157,6 +157,15 @@
  
 byte		consistancy[MAXPLAYERS][BACKUPTICS]; 
  
+int             key_weapon1 = '1';
+int             key_weapon2 = '2';
+int             key_weapon3 = '3';
+int             key_weapon4 = '4';
+int             key_weapon5 = '5';
+int             key_weapon6 = '6';
+int             key_weapon7 = '7';
+int             key_weapon8 = '8';
+ 
 #define MAXPLMOVE		(forwardmove[1]) 
  
 #define TURBOTHRESHOLD	0x32
@@ -165,6 +174,17 @@
 fixed_t         sidemove[2] = {0x18, 0x28}; 
 fixed_t         angleturn[3] = {640, 1280, 320};    // + slow turn 
 
+static int *weapon_keys[] = {
+    &key_weapon1,
+    &key_weapon2,
+    &key_weapon3,
+    &key_weapon4,
+    &key_weapon5,
+    &key_weapon6,
+    &key_weapon7,
+    &key_weapon8
+};
+
 #define SLOWTURNTICS	6 
  
 #define NUMKEYS		256 
@@ -455,13 +475,18 @@
     } 
 
     // chainsaw overrides 
-    for (i=0 ; i<NUMWEAPONS-1 ; i++)        
-	if (gamekeydown['1'+i]) 
-	{ 
+
+    for (i=0; i<arrlen(weapon_keys); ++i)
+    {
+        int key = *weapon_keys[i];
+
+        if (gamekeydown[key])
+        {
 	    cmd->buttons |= BT_CHANGE; 
 	    cmd->buttons |= i<<BT_WEAPONSHIFT; 
 	    break; 
-	}
+        }
+    }
     
     // mouse
     if (mousebuttons[mousebforward]) 
--- a/src/doom/m_menu.c
+++ b/src/doom/m_menu.c
@@ -73,6 +73,35 @@
 extern boolean		chat_on;		// in heads-up code
 
 //
+// menu keys:
+//
+
+int key_menu_activate  = KEY_ESCAPE;
+int key_menu_up        = KEY_UPARROW;
+int key_menu_down      = KEY_DOWNARROW;
+int key_menu_left      = KEY_LEFTARROW;
+int key_menu_right     = KEY_RIGHTARROW;
+int key_menu_back      = KEY_BACKSPACE;
+int key_menu_forward   = KEY_ENTER;
+int key_menu_confirm   = 'y';
+int key_menu_abort     = 'n';
+
+int key_menu_help      = KEY_F1;
+int key_menu_save      = KEY_F2;
+int key_menu_load      = KEY_F3;
+int key_menu_volume    = KEY_F4;
+int key_menu_detail    = KEY_F5;
+int key_menu_qsave     = KEY_F6;
+int key_menu_endgame   = KEY_F7;
+int key_menu_messages  = KEY_F8;
+int key_menu_qload     = KEY_F9;
+int key_menu_quit      = KEY_F10;
+int key_menu_gamma     = KEY_F11;
+
+int key_menu_incscreen = KEY_EQUALS;
+int key_menu_decscreen = KEY_MINUS;
+
+//
 // defaulted values
 //
 int			mouseSensitivity = 5;
@@ -678,9 +707,9 @@
 //
 char    tempstring[80];
 
-void M_QuickSaveResponse(int ch)
+void M_QuickSaveResponse(int key)
 {
-    if (ch == 'y')
+    if (key == key_menu_confirm)
     {
 	M_DoSave(quickSaveSlot);
 	S_StartSound(NULL,sfx_swtchx);
@@ -715,9 +744,9 @@
 //
 // M_QuickLoad
 //
-void M_QuickLoadResponse(int ch)
+void M_QuickLoadResponse(int key)
 {
-    if (ch == 'y')
+    if (key == key_menu_confirm)
     {
 	M_LoadSelect(quickSaveSlot);
 	S_StartSound(NULL,sfx_swtchx);
@@ -935,9 +964,9 @@
     V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_EPISOD"), PU_CACHE));
 }
 
-void M_VerifyNightmare(int ch)
+void M_VerifyNightmare(int key)
 {
-    if (ch != 'y')
+    if (key != key_menu_confirm)
 	return;
 		
     G_DeferedInitNew(nightmare,epi+1,1);
@@ -1036,9 +1065,9 @@
 //
 // M_EndGame
 //
-void M_EndGameResponse(int ch)
+void M_EndGameResponse(int key)
 {
-    if (ch != 'y')
+    if (key != key_menu_confirm)
 	return;
 		
     currentMenu->lastOn = itemOn;
@@ -1132,9 +1161,9 @@
 
 
 
-void M_QuitResponse(int ch)
+void M_QuitResponse(int key)
 {
-    if (ch != 'y')
+    if (key != key_menu_confirm)
 	return;
     if (!netgame)
     {
@@ -1441,34 +1470,34 @@
     {
 	if (ev->data3 == -1)
 	{
-	    key = KEY_UPARROW;
+	    key = key_menu_up;
 	    joywait = I_GetTime() + 5;
 	}
 	else if (ev->data3 == 1)
 	{
-	    key = KEY_DOWNARROW;
+	    key = key_menu_down;
 	    joywait = I_GetTime() + 5;
 	}
 		
 	if (ev->data2 == -1)
 	{
-	    key = KEY_LEFTARROW;
+	    key = key_menu_left;
 	    joywait = I_GetTime() + 2;
 	}
 	else if (ev->data2 == 1)
 	{
-	    key = KEY_RIGHTARROW;
+	    key = key_menu_right;
 	    joywait = I_GetTime() + 2;
 	}
 		
 	if (ev->data1&1)
 	{
-	    key = KEY_ENTER;
+	    key = key_menu_forward;
 	    joywait = I_GetTime() + 5;
 	}
 	if (ev->data1&2)
 	{
-	    key = KEY_BACKSPACE;
+	    key = key_menu_back;
 	    joywait = I_GetTime() + 5;
 	}
     }
@@ -1479,13 +1508,13 @@
 	    mousey += ev->data3;
 	    if (mousey < lasty-30)
 	    {
-		key = KEY_DOWNARROW;
+		key = key_menu_down;
 		mousewait = I_GetTime() + 5;
 		mousey = lasty -= 30;
 	    }
 	    else if (mousey > lasty+30)
 	    {
-		key = KEY_UPARROW;
+		key = key_menu_up;
 		mousewait = I_GetTime() + 5;
 		mousey = lasty += 30;
 	    }
@@ -1493,13 +1522,13 @@
 	    mousex += ev->data2;
 	    if (mousex < lastx-30)
 	    {
-		key = KEY_LEFTARROW;
+		key = key_menu_left;
 		mousewait = I_GetTime() + 5;
 		mousex = lastx -= 30;
 	    }
 	    else if (mousex > lastx+30)
 	    {
-		key = KEY_RIGHTARROW;
+		key = key_menu_right;
 		mousewait = I_GetTime() + 5;
 		mousex = lastx += 30;
 	    }
@@ -1506,13 +1535,13 @@
 		
 	    if (ev->data1&1)
 	    {
-		key = KEY_ENTER;
+		key = key_menu_forward;
 		mousewait = I_GetTime() + 15;
 	    }
 			
 	    if (ev->data1&2)
 	    {
-		key = KEY_BACKSPACE;
+		key = key_menu_back;
 		mousewait = I_GetTime() + 15;
 	    }
 	}
@@ -1534,7 +1563,7 @@
 
     if (testcontrols)
     {
-        if (key == KEY_ESCAPE || key == KEY_F10)
+        if (key == key_menu_activate || key == key_menu_quit)
         {
             I_Quit();
             return true;
@@ -1594,46 +1623,52 @@
     // Take care of any messages that need input
     if (messageToPrint)
     {
-	if (messageNeedsInput == true &&
-	    !(ch == ' ' || ch == 'n' || ch == 'y' || key == KEY_ESCAPE))
-	    return false;
-		
+	if (messageNeedsInput)
+        {
+            if (key != ' ' && key != KEY_ESCAPE
+             && key != key_menu_confirm && key != key_menu_abort)
+            {
+                return false;
+            }
+	}
+
 	menuactive = messageLastMenuActive;
 	messageToPrint = 0;
 	if (messageRoutine)
-	    messageRoutine(ch);
-			
+	    messageRoutine(key);
+
 	menuactive = false;
 	S_StartSound(NULL,sfx_swtchx);
 	return true;
     }
-	
-    if (devparm && key == KEY_F1)
+
+    if (devparm && key == key_menu_help)
     {
 	G_ScreenShot ();
 	return true;
     }
-		
-    
+
     // F-Keys
     if (!menuactive)
-	switch(key)
-	{
-	  case KEY_MINUS:         // Screen size down
+    {
+	if (key == key_menu_decscreen)      // Screen size down
+        {
 	    if (automapactive || chat_on)
 		return false;
 	    M_SizeDisplay(0);
 	    S_StartSound(NULL,sfx_stnmov);
 	    return true;
-				
-	  case KEY_EQUALS:        // Screen size up
+	}
+        else if (key == key_menu_incscreen) // Screen size up
+        {
 	    if (automapactive || chat_on)
 		return false;
 	    M_SizeDisplay(1);
 	    S_StartSound(NULL,sfx_stnmov);
 	    return true;
-				
-	  case KEY_F1:            // Help key
+	}
+        else if (key == key_menu_help)     // Help key
+        {
 	    M_StartControlPanel ();
 
 	    if ( gamemode == retail )
@@ -1640,61 +1675,71 @@
 	      currentMenu = &ReadDef2;
 	    else
 	      currentMenu = &ReadDef1;
-	    
+
 	    itemOn = 0;
 	    S_StartSound(NULL,sfx_swtchn);
 	    return true;
-				
-	  case KEY_F2:            // Save
+	}
+        else if (key == key_menu_save)     // Save
+        {
 	    M_StartControlPanel();
 	    S_StartSound(NULL,sfx_swtchn);
 	    M_SaveGame(0);
 	    return true;
-				
-	  case KEY_F3:            // Load
+        }
+        else if (key == key_menu_load)     // Load
+        {
 	    M_StartControlPanel();
 	    S_StartSound(NULL,sfx_swtchn);
 	    M_LoadGame(0);
 	    return true;
-				
-	  case KEY_F4:            // Sound Volume
+        }
+        else if (key == key_menu_volume)   // Sound Volume
+        {
 	    M_StartControlPanel ();
 	    currentMenu = &SoundDef;
 	    itemOn = sfx_vol;
 	    S_StartSound(NULL,sfx_swtchn);
 	    return true;
-				
-	  case KEY_F5:            // Detail toggle
+	}
+        else if (key == key_menu_detail)   // Detail toggle
+        {
 	    M_ChangeDetail(0);
 	    S_StartSound(NULL,sfx_swtchn);
 	    return true;
-				
-	  case KEY_F6:            // Quicksave
+        }
+        else if (key == key_menu_qsave)    // Quicksave
+        {
 	    S_StartSound(NULL,sfx_swtchn);
 	    M_QuickSave();
 	    return true;
-				
-	  case KEY_F7:            // End game
+        }
+        else if (key == key_menu_endgame)  // End game
+        {
 	    S_StartSound(NULL,sfx_swtchn);
 	    M_EndGame(0);
 	    return true;
-				
-	  case KEY_F8:            // Toggle messages
+        }
+        else if (key == key_menu_messages) // Toggle messages
+        {
 	    M_ChangeMessages(0);
 	    S_StartSound(NULL,sfx_swtchn);
 	    return true;
-				
-	  case KEY_F9:            // Quickload
+        }
+        else if (key == key_menu_qload)    // Quickload
+        {
 	    S_StartSound(NULL,sfx_swtchn);
 	    M_QuickLoad();
 	    return true;
-				
-	  case KEY_F10:           // Quit DOOM
+        }
+        else if (key == key_menu_quit)     // Quit DOOM
+        {
 	    S_StartSound(NULL,sfx_swtchn);
 	    M_QuitDOOM(0);
 	    return true;
-				
-	  case KEY_F11:           // gamma toggle
+        }
+        else if (key == key_menu_gamma)    // gamma toggle
+        {
 	    usegamma++;
 	    if (usegamma > 4)
 		usegamma = 0;
@@ -1701,14 +1746,13 @@
 	    players[consoleplayer].message = DEH_String(gammamsg[usegamma]);
             I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE));
 	    return true;
-				
 	}
+    }
 
-    
     // Pop-up menu?
     if (!menuactive)
     {
-	if (key == KEY_ESCAPE)
+	if (key == key_menu_activate)
 	{
 	    M_StartControlPanel ();
 	    S_StartSound(NULL,sfx_swtchn);
@@ -1719,10 +1763,12 @@
 
     
     // Keys usable within menu
-    switch (key)
+
+    if (key == key_menu_down)
     {
-      case KEY_DOWNARROW:
-	do
+        // Move down to next item
+
+        do
 	{
 	    if (itemOn+1 > currentMenu->numitems-1)
 		itemOn = 0;
@@ -1729,9 +1775,13 @@
 	    else itemOn++;
 	    S_StartSound(NULL,sfx_pstop);
 	} while(currentMenu->menuitems[itemOn].status==-1);
+
 	return true;
-		
-      case KEY_UPARROW:
+    }
+    else if (key == key_menu_up)
+    {
+        // Move back up to previous item
+
 	do
 	{
 	    if (!itemOn)
@@ -1739,9 +1789,13 @@
 	    else itemOn--;
 	    S_StartSound(NULL,sfx_pstop);
 	} while(currentMenu->menuitems[itemOn].status==-1);
+
 	return true;
+    }
+    else if (key == key_menu_left)
+    {
+        // Slide slider left
 
-      case KEY_LEFTARROW:
 	if (currentMenu->menuitems[itemOn].routine &&
 	    currentMenu->menuitems[itemOn].status == 2)
 	{
@@ -1749,8 +1803,11 @@
 	    currentMenu->menuitems[itemOn].routine(0);
 	}
 	return true;
-		
-      case KEY_RIGHTARROW:
+    }
+    else if (key == key_menu_right)
+    {
+        // Slide slider right
+
 	if (currentMenu->menuitems[itemOn].routine &&
 	    currentMenu->menuitems[itemOn].status == 2)
 	{
@@ -1758,8 +1815,11 @@
 	    currentMenu->menuitems[itemOn].routine(1);
 	}
 	return true;
+    }
+    else if (key == key_menu_forward)
+    {
+        // Activate menu item
 
-      case KEY_ENTER:
 	if (currentMenu->menuitems[itemOn].routine &&
 	    currentMenu->menuitems[itemOn].status)
 	{
@@ -1776,14 +1836,20 @@
 	    }
 	}
 	return true;
-		
-      case KEY_ESCAPE:
+    }
+    else if (key == key_menu_activate)
+    {
+        // Deactivate menu
+
 	currentMenu->lastOn = itemOn;
 	M_ClearMenus ();
 	S_StartSound(NULL,sfx_swtchx);
 	return true;
-		
-      case KEY_BACKSPACE:
+    }
+    else if (key == key_menu_back)
+    {
+        // Go back to previous menu
+
 	currentMenu->lastOn = itemOn;
 	if (currentMenu->prevMenu)
 	{
@@ -1792,9 +1858,13 @@
 	    S_StartSound(NULL,sfx_swtchn);
 	}
 	return true;
-	
-      default:
+    }
+    else if (ch != 0)
+    {
+        // Keyboard shortcut?
+
 	for (i = itemOn+1;i < currentMenu->numitems;i++)
+        {
 	    if (currentMenu->menuitems[i].alphaKey == ch)
 	    {
 		itemOn = i;
@@ -1801,7 +1871,10 @@
 		S_StartSound(NULL,sfx_pstop);
 		return true;
 	    }
+        }
+
 	for (i = 0;i <= itemOn;i++)
+        {
 	    if (currentMenu->menuitems[i].alphaKey == ch)
 	    {
 		itemOn = i;
@@ -1808,8 +1881,7 @@
 		S_StartSound(NULL,sfx_pstop);
 		return true;
 	    }
-	break;
-	
+        }
     }
 
     return false;
--- a/src/doomtype.h
+++ b/src/doomtype.h
@@ -62,6 +62,13 @@
 #define PACKEDATTR
 #endif
 
+// Windows CE is missing some vital ANSI C functions.  We have to
+// use our own replacements.
+
+#ifdef _WIN32_WCE
+#include "libc_wince.h"
+#endif
+
 // C99 integer types; with gcc we just use this.  Other compilers 
 // should add conditional statements that define the C99 types.
 
--- a/src/i_main.c
+++ b/src/i_main.c
@@ -40,8 +40,16 @@
 
 void D_DoomMain (void);
 
-#if defined(_WIN32)
+#if defined(_WIN32_WCE)
 
+// Windows CE?  I doubt it even supports SMP..
+
+static void LockCPUAffinity(void)
+{
+}
+
+#elif defined(_WIN32)
+
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
@@ -129,6 +137,15 @@
 
     myargc = argc;
     myargv = argv;
+
+#ifdef _WIN32_WCE
+
+    // Windows CE has no environment, but SDL provides an implementation.
+    // Populate the environment with the values we normally find.
+
+    PopulateEnvironment();
+
+#endif
 
     // Only schedule on a single core, if we have multiple
     // cores.  This is to work around a bug in SDL_mixer.
--- a/src/i_system.c
+++ b/src/i_system.c
@@ -113,6 +113,11 @@
     *size = I_GetHeapSize();
 
     zonemem = malloc(*size);
+
+    if (zonemem == NULL)
+    {
+        I_Error("Failed to allocate %i bytes for zone memory", *size);
+    }
     
     printf("zone memory: %p, %x allocated for zone\n", 
            zonemem, *size);
@@ -261,6 +266,7 @@
     // On Windows, pop up a dialog box with the error message.
     {
         char msgbuf[512];
+        wchar_t wmsgbuf[512];
 
         va_start(argptr, error);
         memset(msgbuf, 0, sizeof(msgbuf));
@@ -267,7 +273,11 @@
         vsnprintf(msgbuf, sizeof(msgbuf) - 1, error, argptr);
         va_end(argptr);
 
-        MessageBox(NULL, msgbuf, "Error", MB_OK);
+        MultiByteToWideChar(CP_ACP, 0,
+                            msgbuf, strlen(msgbuf) + 1,
+                            wmsgbuf, sizeof(wmsgbuf));
+
+        MessageBoxW(NULL, wmsgbuf, L"Error", MB_OK);
     }
 #endif
 
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -1140,111 +1140,110 @@
     return best_mode;
 }
 
-// If the video mode set in the configuration file is not available,
-// try to choose a different mode.
+// Adjust to an appropriate fullscreen mode.
+// Returns true if successful.
 
-static void I_AutoAdjustSettings(void)
+static boolean AutoAdjustFullscreen(void)
 {
-    if (fullscreen)
-    {
-        SDL_Rect **modes;
-        SDL_Rect *best_mode;
-        screen_mode_t *screen_mode;
-        int target_pixels, diff, best_diff;
-        int i;
+    SDL_Rect **modes;
+    SDL_Rect *best_mode;
+    screen_mode_t *screen_mode;
+    int target_pixels, diff, best_diff;
+    int i;
 
-        modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
+    modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
 
-        // Find the best mode that matches the mode specified in the
-        // configuration file
+    // No fullscreen modes available at all?
 
-        best_mode = NULL;
-        best_diff = INT_MAX;
-        target_pixels = screen_width * screen_height;
+    if (modes == NULL || modes == (SDL_Rect **) -1 || *modes == NULL)
+    {
+        return false;
+    }
 
-        for (i=0; modes[i] != NULL; ++i) 
-        {
-            //printf("%ix%i?\n", modes[i]->w, modes[i]->h);
+    // Find the best mode that matches the mode specified in the
+    // configuration file
 
-            // What screen_mode_t would be used for this video mode?
+    best_mode = NULL;
+    best_diff = INT_MAX;
+    target_pixels = screen_width * screen_height;
 
-            screen_mode = I_FindScreenMode(modes[i]->w, modes[i]->h);
+    for (i=0; modes[i] != NULL; ++i) 
+    {
+        //printf("%ix%i?\n", modes[i]->w, modes[i]->h);
 
-            // Never choose a screen mode that we cannot run in, or
-            // is poor quality for fullscreen
+        // What screen_mode_t would be used for this video mode?
 
-            if (screen_mode == NULL || screen_mode->poor_quality)
-            {
-            //    printf("\tUnsupported / poor quality\n");
-                continue;
-            }
+        screen_mode = I_FindScreenMode(modes[i]->w, modes[i]->h);
 
-            // Do we have the exact mode?
-            // If so, no autoadjust needed
+        // Never choose a screen mode that we cannot run in, or
+        // is poor quality for fullscreen
 
-            if (screen_width == modes[i]->w && screen_height == modes[i]->h)
-            {
-            //    printf("\tExact mode!\n");
-                return;
-            }
-
-            // Is this mode better than the current mode?
-
-            diff = (screen_width - modes[i]->w) 
-                     * (screen_width - modes[i]->w)
-                 + (screen_height - modes[i]->h)
-                     * (screen_height - modes[i]->h);
-
-            if (diff < best_diff)
-            {
-            //    printf("\tA valid mode\n");
-                best_mode = modes[i];
-                best_diff = diff;
-            }
+        if (screen_mode == NULL || screen_mode->poor_quality)
+        {
+        //    printf("\tUnsupported / poor quality\n");
+            continue;
         }
 
-        if (best_mode == NULL)
-        {
-            // Unable to find a valid mode!
+        // Do we have the exact mode?
+        // If so, no autoadjust needed
 
-            I_Error("Unable to find any valid video mode at all!");
+        if (screen_width == modes[i]->w && screen_height == modes[i]->h)
+        {
+        //    printf("\tExact mode!\n");
+            return true;
         }
 
-        printf("I_InitGraphics: %ix%i mode not supported on this machine.\n",
-               screen_width, screen_height);
+        // Is this mode better than the current mode?
 
-        screen_width = best_mode->w;
-        screen_height = best_mode->h;
+        diff = (screen_width - modes[i]->w) * (screen_width - modes[i]->w)
+             + (screen_height - modes[i]->h) * (screen_height - modes[i]->h);
 
+        if (diff < best_diff)
+        {
+        //    printf("\tA valid mode\n");
+            best_mode = modes[i];
+            best_diff = diff;
+        }
     }
-    else
+
+    if (best_mode == NULL)
     {
-        screen_mode_t *best_mode;
+        // Unable to find a valid mode!
 
-        //
-        // Windowed mode.
-        //
-        // Find a screen_mode_t to fit within the current settings
-        //
+        return false;
+    }
 
-        best_mode = I_FindScreenMode(screen_width, screen_height);
+    printf("I_InitGraphics: %ix%i mode not supported on this machine.\n",
+           screen_width, screen_height);
 
-        if (best_mode == NULL) 
-        {
-            // Nothing fits within the current settings.
-            // Pick the closest to 320x200 possible.
+    screen_width = best_mode->w;
+    screen_height = best_mode->h;
 
-            best_mode = I_FindScreenMode(SCREENWIDTH, SCREENHEIGHT_4_3);
-        }
+    return true;
+}
 
-        // Do we have the exact mode already?
+// Auto-adjust to a valid windowed mode.
 
-        if (best_mode->width == screen_width 
-         && best_mode->height == screen_height)
-        {
-            return;
-        }
+static void AutoAdjustWindowed(void)
+{
+    screen_mode_t *best_mode;
 
+    // Find a screen_mode_t to fit within the current settings
+
+    best_mode = I_FindScreenMode(screen_width, screen_height);
+
+    if (best_mode == NULL)
+    {
+        // Nothing fits within the current settings.
+        // Pick the closest to 320x200 possible.
+
+        best_mode = I_FindScreenMode(SCREENWIDTH, SCREENHEIGHT_4_3);
+    }
+
+    // Switch to the best mode if necessary.
+
+    if (best_mode->width != screen_width || best_mode->height != screen_height)
+    {
         printf("I_InitGraphics: Cannot run at specified mode: %ix%i\n",
                screen_width, screen_height);
 
@@ -1251,14 +1250,45 @@
         screen_width = best_mode->width;
         screen_height = best_mode->height;
     }
+}
 
-    printf("I_InitGraphics: Auto-adjusted to %ix%i.\n",
-           screen_width, screen_height);
+// If the video mode set in the configuration file is not available,
+// try to choose a different mode.
 
-    printf("NOTE: Your video settings have been adjusted.  "
-           "To disable this behavior,\n"
-           "set autoadjust_video_settings to 0 in your "
-           "configuration file.\n");
+static void I_AutoAdjustSettings(void)
+{
+    int old_screen_w, old_screen_h;
+
+    old_screen_w = screen_width;
+    old_screen_h = screen_height;
+
+    // If we are running fullscreen, try to autoadjust to a valid fullscreen
+    // mode.  If this is impossible, switch to windowed.
+
+    if (fullscreen && !AutoAdjustFullscreen())
+    {
+        fullscreen = 0;
+    }
+
+    // If we are running windowed, pick a valid window size.
+
+    if (!fullscreen)
+    {
+        AutoAdjustWindowed();
+    }
+
+    // Have the settings changed?  Show a message.
+
+    if (screen_width != old_screen_w || screen_height != old_screen_h)
+    {
+        printf("I_InitGraphics: Auto-adjusted to %ix%i.\n",
+               screen_width, screen_height);
+
+        printf("NOTE: Your video settings have been adjusted.  "
+               "To disable this behavior,\n"
+               "set autoadjust_video_settings to 0 in your "
+               "configuration file.\n");
+    }
 }
 
 // Set video size to a particular scale factor (1x, 2x, 3x, etc.)
@@ -1559,7 +1589,7 @@
         free(env_string);
     }
 
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(_WIN32_WCE)
 
     // Allow -gdi as a shortcut for using the windib driver.
 
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -712,6 +712,8 @@
 
     CONFIG_VARIABLE_INT(dclick_use),
 
+#ifdef FEATURE_SOUND
+
     //!
     // Controls whether libsamplerate support is used for performing
     // sample rate conversions of sound effects.  Support for this
@@ -726,6 +728,260 @@
     //
 
     CONFIG_VARIABLE_INT(use_libsamplerate),
+
+#endif
+
+    //!
+    // Key that activates the menu when pressed.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_activate),
+
+    //!
+    // Key that moves the cursor up on the menu.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_up),
+
+    //!
+    // Key that moves the cursor down on the menu.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_down),
+
+    //!
+    // Key that moves the currently selected slider on the menu left.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_left),
+
+    //!
+    // Key that moves the currently selected slider on the menu right.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_right),
+
+    //!
+    // Key to go back to the previous menu.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_back),
+
+    //!
+    // Key to activate the currently selected menu item.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_forward),
+
+    //!
+    // Key to answer 'yes' to a question in the menu.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_confirm),
+
+    //!
+    // Key to answer 'no' to a question in the menu.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_abort),
+
+    //!
+    // Keyboard shortcut to bring up the help screen.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_help),
+
+    //!
+    // Keyboard shortcut to bring up the save game menu.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_save),
+
+    //!
+    // Keyboard shortcut to bring up the load game menu.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_load),
+
+    //!
+    // Keyboard shortcut to bring up the sound volume menu.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_volume),
+
+    //!
+    // Keyboard shortcut to toggle the detail level.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_detail),
+
+    //!
+    // Keyboard shortcut to quicksave the current game.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_qsave),
+
+    //!
+    // Keyboard shortcut to end the game.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_endgame),
+
+    //!
+    // Keyboard shortcut to toggle heads-up messages.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_messages),
+
+    //!
+    // Keyboard shortcut to load the last quicksave.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_qload),
+
+    //!
+    // Keyboard shortcut to quit the game.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_quit),
+
+    //!
+    // Keyboard shortcut to toggle the gamma correction level.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_gamma),
+
+    //!
+    // Keyboard shortcut to increase the screen size.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_incscreen),
+
+    //!
+    // Keyboard shortcut to decrease the screen size.
+    //
+
+    CONFIG_VARIABLE_KEY(key_menu_decscreen),
+
+    //!
+    // Key to toggle the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_toggle),
+
+    //!
+    // Key to pan north when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_north),
+
+    //!
+    // Key to pan south when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_south),
+
+    //!
+    // Key to pan east when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_east),
+
+    //!
+    // Key to pan west when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_west),
+
+    //!
+    // Key to zoom in when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_zoomin),
+
+    //!
+    // Key to zoom out when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_zoomout),
+
+    //!
+    // Key to zoom out the maximum amount when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_maxzoom),
+
+    //!
+    // Key to toggle follow mode when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_follow),
+
+    //!
+    // Key to toggle the grid display when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_grid),
+
+    //!
+    // Key to set a mark when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_mark),
+
+    //!
+    // Key to clear all marks when in the map view.
+    //
+
+    CONFIG_VARIABLE_KEY(key_map_clearmark),
+
+    //!
+    // Key to select weapon 1.
+    //
+
+    CONFIG_VARIABLE_KEY(key_weapon1),
+
+    //!
+    // Key to select weapon 2.
+    //
+
+    CONFIG_VARIABLE_KEY(key_weapon2),
+
+    //!
+    // Key to select weapon 3.
+    //
+
+    CONFIG_VARIABLE_KEY(key_weapon3),
+
+    //!
+    // Key to select weapon 4.
+    //
+
+    CONFIG_VARIABLE_KEY(key_weapon4),
+
+    //!
+    // Key to select weapon 5.
+    //
+
+    CONFIG_VARIABLE_KEY(key_weapon5),
+
+    //!
+    // Key to select weapon 6.
+    //
+
+    CONFIG_VARIABLE_KEY(key_weapon6),
+
+    //!
+    // Key to select weapon 7.
+    //
+
+    CONFIG_VARIABLE_KEY(key_weapon7),
+
+    //!
+    // Key to select weapon 8.
+    //
+
+    CONFIG_VARIABLE_KEY(key_weapon8),
 };
 
 static default_collection_t extra_defaults =
@@ -1109,10 +1365,12 @@
 
 static char *GetDefaultConfigDir(void)
 {
-#ifndef _WIN32
-    // On Unix systems we put configuration into ~/.chocolate-doom, but
-    // on Windows we just use the current directory, like Vanilla.
+#if !defined(_WIN32) || defined(_WIN32_WCE)
 
+    // Configuration settings are stored in ~/.chocolate-doom/,
+    // except on Windows, where we behave like Vanilla Doom and
+    // save in the current directory.
+
     char *homedir;
     char *result;
 
@@ -1133,8 +1391,6 @@
     else
 #endif /* #ifndef _WIN32 */
     {
-        // On Windows, we just use the current directory.
-
         return strdup("");
     }
 }
--- a/src/setup/display.c
+++ b/src/setup/display.c
@@ -121,7 +121,7 @@
     }
     else
     {
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(_WIN32_WCE)
         // On Windows, use DirectX over windib by default.
 
         putenv("SDL_VIDEODRIVER=directx");
@@ -192,7 +192,14 @@
 
     modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
 
-    for (num_modes=0; modes[num_modes] != NULL; ++num_modes);
+    if (modes == NULL || modes == (SDL_Rect **) -1)
+    {
+        num_modes = 0;
+    }
+    else
+    {
+        for (num_modes=0; modes[num_modes] != NULL; ++num_modes);
+    }
 
     // Build the screen_modes_fullscreen array
 
@@ -310,7 +317,7 @@
     screen_height = modes[vidmode].h;
 }
 
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(_WIN32_WCE)
 
 static int win32_video_driver = 0;
 
@@ -403,7 +410,7 @@
     // On Windows, there is an extra control to change between 
     // the Windows GDI and DirectX video drivers.
 
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(_WIN32_WCE)
     {
         txt_table_t *driver_table;
         txt_dropdown_list_t *driver_list;
--- a/src/setup/execute.c
+++ b/src/setup/execute.c
@@ -28,11 +28,19 @@
 
 #include <sys/types.h>
 
-#ifndef _WIN32
-    #include <sys/wait.h>
-    #include <unistd.h>
+#if defined(_WIN32_WCE)
+
+#include "libc_wince.h"
+
+#elif defined(_WIN32)
+
+#include <process.h>
+
 #else
-    #include <process.h>
+
+#include <sys/wait.h>
+#include <unistd.h>
+
 #endif
 
 #include "textscreen.h"
@@ -126,7 +134,16 @@
     fprintf(context->stream, "\n");
 }
 
-#ifdef _WIN32
+#if defined(_WIN32_WCE)
+
+static int ExecuteCommand(const char **argv)
+{
+    // Windows CE version.
+    // TODO
+    return 0;
+}
+
+#elif defined(_WIN32)
 
 static int ExecuteCommand(const char **argv)
 {
--- a/src/setup/keyboard.c
+++ b/src/setup/keyboard.c
@@ -18,6 +18,7 @@
 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 // 02111-1307, USA.
 //
+
 #include "textscreen.h"
 #include "doomtype.h"
 #include "m_config.h"
@@ -32,17 +33,86 @@
 
 static int vanilla_keyboard_mapping = 1;
 
+// Menu keys:
+
+int key_menu_activate  = KEY_ESCAPE;
+int key_menu_up        = KEY_UPARROW;
+int key_menu_down      = KEY_DOWNARROW;
+int key_menu_left      = KEY_LEFTARROW;
+int key_menu_right     = KEY_RIGHTARROW;
+int key_menu_back      = KEY_BACKSPACE;
+int key_menu_forward   = KEY_ENTER;
+int key_menu_confirm   = 'y';
+int key_menu_abort     = 'n';
+
+int key_menu_help      = KEY_F1;
+int key_menu_save      = KEY_F2;
+int key_menu_load      = KEY_F3;
+int key_menu_volume    = KEY_F4;
+int key_menu_detail    = KEY_F5;
+int key_menu_qsave     = KEY_F6;
+int key_menu_endgame   = KEY_F7;
+int key_menu_messages  = KEY_F8;
+int key_menu_qload     = KEY_F9;
+int key_menu_quit      = KEY_F10;
+int key_menu_gamma     = KEY_F11;
+
+int key_menu_incscreen = KEY_EQUALS;
+int key_menu_decscreen = KEY_MINUS;
+
+int key_map_north      = KEY_UPARROW;
+int key_map_south      = KEY_DOWNARROW;
+int key_map_east       = KEY_RIGHTARROW;
+int key_map_west       = KEY_LEFTARROW;
+int key_map_zoomin     = '=';
+int key_map_zoomout    = '-';
+int key_map_toggle     = KEY_TAB;
+int key_map_maxzoom    = '0';
+int key_map_follow     = 'f';
+int key_map_grid       = 'g';
+int key_map_mark       = 'm';
+int key_map_clearmark  = 'c';
+
+int key_weapon1        = '1';
+int key_weapon2        = '2';
+int key_weapon3        = '3';
+int key_weapon4        = '4';
+int key_weapon5        = '5';
+int key_weapon6        = '6';
+int key_weapon7        = '7';
+int key_weapon8        = '8';
+
 static int always_run = 0;
 
-static int *allkeys[] = {
-    &key_left, &key_right, &key_up, &key_down,
-    &key_strafeleft, &key_straferight, &key_strafe,
-    &key_jump, &key_fire, &key_use, &key_speed,
-    &key_flyup, &key_flydown, &key_flycenter,
-    &key_lookup, &key_lookdown, &key_lookcenter,
-    &key_invleft, &key_invright, &key_useartifact
-};
+// Keys within these groups cannot have the same value.
 
+static int *controls[] = { &key_left, &key_right, &key_up, &key_down,
+                           &key_strafeleft, &key_straferight, &key_fire,
+                           &key_use, &key_strafe, &key_speed, &key_jump, 
+                           &key_flyup, &key_flydown, &key_flycenter,
+                           &key_lookup, &key_lookdown, &key_lookcenter,
+                           &key_invleft, &key_invright, &key_useartifact,
+                           &key_weapon1, &key_weapon2, &key_weapon3,
+                           &key_weapon4, &key_weapon5, &key_weapon6,
+                           &key_weapon7, &key_weapon8,
+                           NULL };
+
+static int *menu_nav[] = { &key_menu_activate, &key_menu_up, &key_menu_down,
+                           &key_menu_left, &key_menu_right, &key_menu_back,
+                           &key_menu_forward, NULL };
+
+static int *shortcuts[] = { &key_menu_help, &key_menu_save, &key_menu_load,
+                            &key_menu_volume, &key_menu_detail, &key_menu_qsave,
+                            &key_menu_endgame, &key_menu_messages,
+                            &key_menu_qload, &key_menu_quit, &key_menu_gamma,
+                            &key_menu_incscreen, &key_menu_decscreen, NULL };
+
+static int *map_keys[] = { &key_map_north, &key_map_south, &key_map_east,
+                           &key_map_west, &key_map_zoomin, &key_map_zoomout,
+                           &key_map_toggle, &key_map_maxzoom, &key_map_follow,
+                           &key_map_grid, &key_map_mark, &key_map_clearmark,
+                           NULL };
+
 static void UpdateJoybSpeed(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(var))
 {
     if (always_run)
@@ -63,26 +133,61 @@
     }
 }
 
-// Callback invoked when a key control is set
+static int VarInGroup(int *variable, int **group)
+{
+    unsigned int i;
 
-static void KeySetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable))
+    for (i=0; group[i] != NULL; ++i)
+    {
+        if (group[i] == variable)
+        {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static void CheckKeyGroup(int *variable, int **group)
 {
-    TXT_CAST_ARG(int, variable);
     unsigned int i;
 
-    for (i=0; i<arrlen(allkeys); ++i)
+    // Don't check unless the variable is in this group.
+
+    if (!VarInGroup(variable, group))
     {
-        if (*variable == *allkeys[i] && allkeys[i] != variable)
+        return;
+    }
+
+    // If another variable has the same value as the new value, reset it.
+
+    for (i=0; group[i] != NULL; ++i)
+    {
+        if (*variable == *group[i] && group[i] != variable)
         {
             // A different key has the same value.  Clear the existing
             // value. This ensures that no two keys can have the same
             // value.
 
-            *allkeys[i] = 0;
+            *group[i] = 0;
         }
     }
 }
 
+// Callback invoked when a key control is set
+
+static void KeySetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable))
+{
+    TXT_CAST_ARG(int, variable);
+
+    CheckKeyGroup(variable, controls);
+    CheckKeyGroup(variable, menu_nav);
+    CheckKeyGroup(variable, shortcuts);
+    CheckKeyGroup(variable, map_keys);
+}
+
+// Add a label and keyboard input to the specified table.
+
 static void AddKeyControl(txt_table_t *table, char *name, int *var)
 {
     txt_key_input_t *key_input;
@@ -90,6 +195,7 @@
     TXT_AddWidget(table, TXT_NewLabel(name));
     key_input = TXT_NewKeyInput(var);
     TXT_AddWidget(table, key_input);
+
     TXT_SignalConnect(key_input, "set", KeySetCallback, var);
 }
 
@@ -130,6 +236,92 @@
     AddKeyControl(inv_table, "Use artifact", &key_useartifact);
 }
 
+static void OtherKeysDialog(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused))
+{
+    txt_window_t *window;
+    txt_table_t *table;
+    txt_scrollpane_t *scrollpane;
+
+    window = TXT_NewWindow("Other keys");
+
+    table = TXT_NewTable(2);
+
+    TXT_SetColumnWidths(table, 25, 10);
+
+    TXT_AddWidgets(table, TXT_NewLabel(" - Weapons - "),
+                          TXT_NewStrut(0, 0),
+                          NULL);
+
+    AddKeyControl(table, "Weapon 1",              &key_weapon1);
+    AddKeyControl(table, "Weapon 2",              &key_weapon2);
+    AddKeyControl(table, "Weapon 3",              &key_weapon3);
+    AddKeyControl(table, "Weapon 4",              &key_weapon4);
+    AddKeyControl(table, "Weapon 5",              &key_weapon5);
+    AddKeyControl(table, "Weapon 6",              &key_weapon6);
+    AddKeyControl(table, "Weapon 7",              &key_weapon7);
+    AddKeyControl(table, "Weapon 8",              &key_weapon8);
+
+    TXT_AddWidgets(table, TXT_NewStrut(0, 1),
+                          TXT_NewStrut(0, 1),
+                          TXT_NewLabel(" - Menu navigation - "),
+                          TXT_NewStrut(0, 0),
+                          NULL);
+
+    AddKeyControl(table, "Activate menu",         &key_menu_activate);
+    AddKeyControl(table, "Move cursor up",        &key_menu_up);
+    AddKeyControl(table, "Move cursor down",      &key_menu_down);
+    AddKeyControl(table, "Move slider left",      &key_menu_left);
+    AddKeyControl(table, "Move slider right",     &key_menu_right);
+    AddKeyControl(table, "Go to previous menu",   &key_menu_back);
+    AddKeyControl(table, "Activate menu item",    &key_menu_forward);
+    AddKeyControl(table, "Confirm action",        &key_menu_confirm);
+    AddKeyControl(table, "Cancel action",         &key_menu_abort);
+
+    TXT_AddWidgets(table, TXT_NewStrut(0, 1),
+                          TXT_NewStrut(0, 1),
+                          TXT_NewLabel(" - Shortcut keys - "),
+                          TXT_NewStrut(0, 0),
+                          NULL);
+
+    AddKeyControl(table, "Help screen",           &key_menu_help);
+    AddKeyControl(table, "Save game",             &key_menu_save);
+    AddKeyControl(table, "Load game",             &key_menu_load);
+    AddKeyControl(table, "Sound volume",          &key_menu_volume);
+    AddKeyControl(table, "Toggle detail",         &key_menu_detail);
+    AddKeyControl(table, "Quick save",            &key_menu_qsave);
+    AddKeyControl(table, "End game",              &key_menu_endgame);
+    AddKeyControl(table, "Toggle messages",       &key_menu_messages);
+    AddKeyControl(table, "Quick load",            &key_menu_qload);
+    AddKeyControl(table, "Quit game",             &key_menu_quit);
+    AddKeyControl(table, "Toggle gamma",          &key_menu_gamma);
+
+    AddKeyControl(table, "Increase screen size",  &key_menu_incscreen);
+    AddKeyControl(table, "Decrease screen size",  &key_menu_decscreen);
+
+    TXT_AddWidgets(table, TXT_NewStrut(0, 1),
+                          TXT_NewStrut(0, 1),
+                          TXT_NewLabel(" - Map - "),
+                          TXT_NewStrut(0, 0),
+                          NULL);
+
+    AddKeyControl(table, "Toggle map",            &key_map_toggle);
+    AddKeyControl(table, "Zoom in",               &key_map_zoomin);
+    AddKeyControl(table, "Zoom out",              &key_map_zoomout);
+    AddKeyControl(table, "Maximum zoom out",      &key_map_maxzoom);
+    AddKeyControl(table, "Follow mode",           &key_map_follow);
+    AddKeyControl(table, "Pan north",             &key_map_north);
+    AddKeyControl(table, "Pan south",             &key_map_south);
+    AddKeyControl(table, "Pan east",              &key_map_east);
+    AddKeyControl(table, "Pan west",              &key_map_west);
+    AddKeyControl(table, "Toggle grid",           &key_map_grid);
+    AddKeyControl(table, "Mark location",         &key_map_mark);
+    AddKeyControl(table, "Clear all marks",       &key_map_clearmark);
+
+    scrollpane = TXT_NewScrollPane(0, 12, table);
+
+    TXT_AddWidget(window, scrollpane);
+}
+
 void ConfigKeyboard(void)
 {
     txt_window_t *window;
@@ -141,12 +333,13 @@
 
     window = TXT_NewWindow("Keyboard configuration");
 
-    TXT_AddWidgets(window, 
+    TXT_AddWidgets(window,
                    TXT_NewSeparator("Movement"),
                    movement_table = TXT_NewTable(4),
 
                    TXT_NewSeparator("Action"),
                    action_table = TXT_NewTable(4),
+                   TXT_NewButton2("Other keys...", OtherKeysDialog, NULL),
                    NULL);
 
     // Look up/down, inventory and flying controls are only in Heretic/Hexen
--- a/src/setup/keyboard.h
+++ b/src/setup/keyboard.h
@@ -22,6 +22,59 @@
 #ifndef SETUP_KEYBOARD_H 
 #define SETUP_KEYBOARD_H 
 
+// Menu keys:
+
+extern int key_menu_activate;
+extern int key_menu_up;
+extern int key_menu_down;
+extern int key_menu_left;
+extern int key_menu_right;
+extern int key_menu_back;
+extern int key_menu_forward;
+extern int key_menu_confirm;
+extern int key_menu_abort;
+
+extern int key_menu_help;
+extern int key_menu_save;
+extern int key_menu_load;
+extern int key_menu_volume;
+extern int key_menu_detail;
+extern int key_menu_qsave;
+extern int key_menu_endgame;
+extern int key_menu_messages;
+extern int key_menu_qload;
+extern int key_menu_quit;
+extern int key_menu_gamma;
+
+extern int key_menu_incscreen;
+extern int key_menu_decscreen;
+
+// Automap keys:
+
+extern int key_map_north;
+extern int key_map_south;
+extern int key_map_east;
+extern int key_map_west;
+extern int key_map_zoomin;
+extern int key_map_zoomout;
+extern int key_map_toggle;
+extern int key_map_maxzoom;
+extern int key_map_follow;
+extern int key_map_grid;
+extern int key_map_mark;
+extern int key_map_clearmark;
+
+// Weapon keys:
+
+extern int key_weapon1;
+extern int key_weapon2;
+extern int key_weapon3;
+extern int key_weapon4;
+extern int key_weapon5;
+extern int key_weapon6;
+extern int key_weapon7;
+extern int key_weapon8;
+
 void ConfigKeyboard(void);
 void BindKeyboardVariables(void);
 
--- a/src/setup/mainmenu.c
+++ b/src/setup/mainmenu.c
@@ -22,6 +22,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#ifdef _WIN32_WCE
+#include "libc_wince.h"
+#endif
+
 #include "config.h"
 #include "textscreen.h"
 
@@ -252,6 +256,7 @@
 void D_DoomMain(void)
 {
     SetupMission(MissionSet);
+
     RunGUI();
 }
 
--- a/src/w_file_win32.c
+++ b/src/w_file_win32.c
@@ -94,12 +94,24 @@
 static wad_file_t *W_Win32_OpenFile(char *path)
 {
     win32_wad_file_t *result;
+    wchar_t wpath[MAX_PATH + 1];
     HANDLE handle;
-    OFSTRUCT fileinfo;
 
-    handle = (HANDLE) OpenFile(path, &fileinfo, OF_READ);
+    // Open the file:
 
-    if (handle == (HANDLE) HFILE_ERROR)
+    MultiByteToWideChar(CP_OEMCP, 0,
+                        path, strlen(path) + 1,
+                        wpath, sizeof(wpath));
+
+    handle = CreateFileW(wpath,
+                         GENERIC_READ,
+                         FILE_SHARE_READ,
+                         NULL,
+                         OPEN_EXISTING,
+                         FILE_ATTRIBUTE_NORMAL,
+                         NULL);
+
+    if (handle == INVALID_HANDLE_VALUE)
     {
         return NULL;
     }
--- a/textscreen/Makefile.am
+++ b/textscreen/Makefile.am
@@ -1,6 +1,8 @@
 
 AM_CFLAGS = -I../src
 
+CTAGS_ARGS=-I TXT_UNCAST_ARG+
+
 # build this directory before the examples directory.
 
 SUBDIRS= . examples
--- a/textscreen/txt_sdl.c
+++ b/textscreen/txt_sdl.c
@@ -142,6 +142,9 @@
 
     if (modes == NULL || modes == (SDL_Rect **) -1 || *modes == NULL)
     {
+#ifdef _WIN32_WCE
+        font = &small_font;
+#endif
         return;
     }
 
@@ -168,7 +171,10 @@
 {
     int flags;
 
-    SDL_InitSubSystem(SDL_INIT_VIDEO);
+    if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
+    {
+        return 0;
+    }
 
     flags = SDL_SWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
 
--- /dev/null
+++ b/wince/Makefile.am
@@ -1,0 +1,16 @@
+
+noinst_LIBRARIES=libc_wince.a
+
+if WINDOWS_CE
+
+libc_wince_a_SOURCES =                            \
+        env.c            env.h                    \
+	errno.c          errno.h                  \
+        fileops.c        fileops.h
+
+else
+
+libc_wince_a_SOURCES =
+
+endif
+
--- /dev/null
+++ b/wince/README
@@ -1,0 +1,8 @@
+Windows CE is a horribly crippled operating system.  The poor thing doesn't
+even include a complete implementation of the ANSI standard C library.  This
+is a mini-library called libc_wince that implements some of the missing
+library functions.  I've only implemented those necessary to get Chocolate
+Doom to compile.
+
+On non-Windows CE platforms it is just built as an empty library.
+
--- /dev/null
+++ b/wince/env.c
@@ -1,0 +1,65 @@
+//
+// "Extension" implementation of getenv for Windows CE.
+//
+// I (Simon Howard) release this file to the public domain.
+//
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <windows.h>
+#include <lmcons.h>
+#include <secext.h>
+#include <shlobj.h>
+
+#include "env.h"
+
+static void WCharToChar(wchar_t *src, char *dest, int buf_len)
+{
+    unsigned int len;
+
+    len = wcslen(src) + 1;
+
+    WideCharToMultiByte(CP_OEMCP, 0, src, len, dest, buf_len, NULL, NULL);
+}
+
+static void SetEnvironment(char *env_string, wchar_t *wvalue)
+{
+    char value[MAX_PATH + 10];
+    int env_len;
+
+    // Construct the string for putenv: NAME=value
+
+    env_len = strlen(env_string);
+    strcpy(value, env_string);
+
+    WCharToChar(wvalue, value + env_len, sizeof(value) - env_len);
+
+    // Set the environment variable:
+
+    putenv(value);
+}
+
+void PopulateEnvironment(void)
+{
+    wchar_t temp[MAX_PATH];
+    DWORD buf_len;
+
+    // Username:
+
+    buf_len = UNLEN;
+    GetUserNameExW(NameDisplay, temp, &buf_len);
+    SetEnvironment("USER=", temp);
+    SetEnvironment("USERNAME=", temp);
+
+    // Temp dir:
+
+    GetTempPathW(MAX_PATH, temp);
+    SetEnvironment("TEMP=", temp);
+
+    // Use My Documents dir as home:
+
+    SHGetSpecialFolderPath(NULL, temp, CSIDL_PERSONAL, 0);
+    SetEnvironment("HOME=", temp);
+}
+
--- /dev/null
+++ b/wince/env.h
@@ -1,0 +1,17 @@
+//
+// "Extension" implementation of getenv for Windows CE.
+//
+// I (Simon Howard) release this file to the public domain.
+//
+
+#ifndef WINCE_ENV_H
+#define WINCE_ENV_H
+
+// SDL provides an implementation of getenv/putenv:
+
+#include "SDL_getenv.h"
+
+extern void PopulateEnvironment(void);
+
+#endif /* #ifndef WINCE_ENV_H */
+
--- /dev/null
+++ b/wince/errno.c
@@ -1,0 +1,20 @@
+//
+// "Extension" implementation of errno.h for Windows CE.
+//
+// I (Simon Howard) release this file to the public domain.
+//
+
+#include <windows.h>
+
+#include "errno.h"
+
+// This should really be a thread-local variable.  Oh well.
+
+static int my_errno;
+
+int *_GetErrno()
+{
+    my_errno = GetLastError();
+    return &my_errno;
+}
+
--- /dev/null
+++ b/wince/errno.h
@@ -1,0 +1,17 @@
+//
+// "Extension" implementation of errno.h for Windows CE.
+//
+// I (Simon Howard) release this file to the public domain.
+//
+
+#ifndef WINCE_ERRNO_H
+#define WINCE_ERRNO_H
+
+#define EISDIR          21      /* Is a directory */
+
+extern int *_GetErrno();
+
+#define errno (*_GetErrno())
+
+#endif /* #ifndef WINCE_ERROR_H */
+
--- /dev/null
+++ b/wince/fileops.c
@@ -1,0 +1,49 @@
+//
+// "Extension" implementation of ANSI C file functions for Windows CE.
+//
+// I (Simon Howard) release this file to the public domain.
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <windows.h>
+
+#include "fileops.h"
+
+int remove(const char *pathname)
+{
+    wchar_t temp[MAX_PATH + 1];
+
+    MultiByteToWideChar(CP_OEMCP,
+                        0,
+                        pathname,
+                        strlen(pathname) + 1,
+                        temp,
+                        MAX_PATH);
+
+    return DeleteFileW(temp) != 0;
+}
+
+int rename(const char *oldpath, const char *newpath)
+{
+    wchar_t oldpath1[MAX_PATH + 1];
+    wchar_t newpath1[MAX_PATH + 1];
+
+    MultiByteToWideChar(CP_OEMCP,
+                        0,
+                        oldpath,
+                        strlen(oldpath) + 1,
+                        oldpath1,
+                        MAX_PATH);
+    MultiByteToWideChar(CP_OEMCP,
+                        0,
+                        newpath,
+                        strlen(newpath) + 1,
+                        newpath1,
+                        MAX_PATH);
+
+    return MoveFileW(oldpath1, newpath1);
+}
+
--- /dev/null
+++ b/wince/fileops.h
@@ -1,0 +1,14 @@
+//
+// "Extension" implementation of ANSI C file functions for Windows CE.
+//
+// I (Simon Howard) release this file to the public domain.
+//
+
+#ifndef WINCE_FILEOPS_H
+#define WINCE_FILEOPS_H
+
+int remove(const char *pathname);
+int rename(const char *oldpath, const char *newpath);
+
+#endif /* #ifndef WINCE_FILEOPS_H */
+
--- /dev/null
+++ b/wince/libc_wince.h
@@ -1,0 +1,4 @@
+
+#include "env.h"
+#include "fileops.h"
+